esp_hmac.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. // Copyright 2015-2020 Espressif Systems (Shanghai) PTE LTD
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. // http://www.apache.org/licenses/LICENSE-2.0
  7. //
  8. // Unless required by applicable law or agreed to in writing, software
  9. // distributed under the License is distributed on an "AS IS" BASIS,
  10. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  11. // See the License for the specific language governing permissions and
  12. // limitations under the License.
  13. #include <string.h>
  14. #include "driver/periph_ctrl.h"
  15. #include "esp32c3/rom/hmac.h"
  16. #include "esp32c3/rom/ets_sys.h"
  17. #include "esp_efuse.h"
  18. #include "esp_efuse_table.h"
  19. #include "esp_hmac.h"
  20. #include "esp_log.h"
  21. #include "esp_crypto_lock.h"
  22. #include "soc/hwcrypto_reg.h"
  23. #include "hal/hmac_hal.h"
  24. #define SHA256_BLOCK_SZ 64
  25. #define SHA256_PAD_SZ 8
  26. static const char *TAG = "esp_hmac";
  27. /**
  28. * @brief Apply the HMAC padding without the embedded length.
  29. *
  30. * @note This function does not check the data length, it is the responsibility of the other functions in this
  31. * module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
  32. * Otherwise, this function has undefined behavior.
  33. * Note however, that for the actual HMAC implementation on ESP32C3, the length also needs to be applied at the end
  34. * of the block. This function alone deosn't do that.
  35. */
  36. static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
  37. {
  38. memcpy(block, data, data_len);
  39. // Apply a one bit, followed by zero bits (refer to the ESP32C3 TRM).
  40. block[data_len] = 0x80;
  41. bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
  42. }
  43. esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
  44. const void *message,
  45. size_t message_len,
  46. uint8_t *hmac)
  47. {
  48. const uint8_t *message_bytes = (const uint8_t *)message;
  49. if (!message || !hmac) {
  50. return ESP_ERR_INVALID_ARG;
  51. }
  52. if (key_id >= HMAC_KEY_MAX) {
  53. return ESP_ERR_INVALID_ARG;
  54. }
  55. esp_crypto_hmac_lock_acquire();
  56. // We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
  57. periph_module_enable(PERIPH_HMAC_MODULE);
  58. periph_module_enable(PERIPH_SHA_MODULE);
  59. periph_module_enable(PERIPH_DS_MODULE);
  60. hmac_hal_start();
  61. uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
  62. if (conf_error) {
  63. esp_crypto_hmac_lock_release();
  64. return ESP_FAIL;
  65. }
  66. if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
  67. // If message including padding is only one block...
  68. // Last message block, so apply SHA-256 padding rules in software
  69. uint8_t block[SHA256_BLOCK_SZ];
  70. uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
  71. write_and_padd(block, message_bytes, message_len);
  72. // Final block: append the bit length in this block and signal padding to peripheral
  73. memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
  74. &bit_len, sizeof(bit_len));
  75. hmac_hal_write_one_block_512(block);
  76. } else {
  77. // If message including padding is needs more than one block
  78. // write all blocks without padding except the last one
  79. size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
  80. for (int i = 1; i < remaining_blocks; i++) {
  81. hmac_hal_write_block_512(message_bytes);
  82. message_bytes += SHA256_BLOCK_SZ;
  83. hmac_hal_next_block_normal();
  84. }
  85. // If message fits into one block but without padding, we must not write another block.
  86. if (remaining_blocks) {
  87. hmac_hal_write_block_512(message_bytes);
  88. message_bytes += SHA256_BLOCK_SZ;
  89. }
  90. size_t remaining = message_len % SHA256_BLOCK_SZ;
  91. // Last message block, so apply SHA-256 padding rules in software
  92. uint8_t block[SHA256_BLOCK_SZ];
  93. uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
  94. // If the remaining message and appended padding doesn't fit into a single block, we have to write an
  95. // extra block with the rest of the message and potential padding first.
  96. if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
  97. write_and_padd(block, message_bytes, remaining);
  98. hmac_hal_next_block_normal();
  99. hmac_hal_write_block_512(block);
  100. bzero(block, SHA256_BLOCK_SZ);
  101. } else {
  102. write_and_padd(block, message_bytes, remaining);
  103. }
  104. memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
  105. &bit_len, sizeof(bit_len));
  106. hmac_hal_next_block_padding();
  107. hmac_hal_write_block_512(block);
  108. }
  109. // Read back result (bit swapped)
  110. hmac_hal_read_result_256(hmac);
  111. periph_module_disable(PERIPH_DS_MODULE);
  112. periph_module_disable(PERIPH_SHA_MODULE);
  113. periph_module_disable(PERIPH_HMAC_MODULE);
  114. esp_crypto_hmac_lock_release();
  115. return ESP_OK;
  116. }
  117. static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) {
  118. return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id;
  119. }
  120. esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
  121. {
  122. int ets_status;
  123. esp_err_t err = ESP_OK;
  124. if ((!token) || (key_id >= HMAC_KEY_MAX))
  125. return ESP_ERR_INVALID_ARG;
  126. /* Check if JTAG is permanently disabled by HW Disable eFuse */
  127. if (esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG)) {
  128. ESP_LOGE(TAG, "JTAG disabled permanently.");
  129. return ESP_FAIL;
  130. }
  131. esp_crypto_hmac_lock_acquire();
  132. ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id));
  133. if (ets_status != ETS_OK) {
  134. // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL
  135. err = ESP_FAIL;
  136. ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err);
  137. }
  138. ESP_LOGD(TAG, "HMAC computation in downstream mode is completed.");
  139. ets_hmac_disable();
  140. esp_crypto_hmac_lock_release();
  141. return err;
  142. }
  143. esp_err_t esp_hmac_jtag_disable()
  144. {
  145. esp_crypto_hmac_lock_acquire();
  146. REG_SET_BIT(HMAC_SET_INVALIDATE_JTAG_REG, HMAC_INVALIDATE_JTAG);
  147. esp_crypto_hmac_lock_release();
  148. ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
  149. return ESP_OK;
  150. }