esp_hmac.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /*
  2. * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. */
  6. #include <string.h>
  7. #include "rom/efuse.h"
  8. #include "rom/hmac.h"
  9. #include "rom/ets_sys.h"
  10. #include "esp_efuse.h"
  11. #include "esp_efuse_table.h"
  12. #include "esp_hmac.h"
  13. #include "esp_log.h"
  14. #include "esp_crypto_lock.h"
  15. #include "esp_private/esp_crypto_lock_internal.h"
  16. #include "soc/hwcrypto_reg.h"
  17. #include "soc/system_reg.h"
  18. #if !CONFIG_IDF_TARGET_ESP32S2
  19. #include "hal/ds_ll.h"
  20. #include "hal/hmac_hal.h"
  21. #include "hal/hmac_ll.h"
  22. #include "esp_private/periph_ctrl.h"
  23. #endif
  24. #define SHA256_BLOCK_SZ 64
  25. #define SHA256_PAD_SZ 8
  26. #if defined(CONFIG_IDF_TARGET_ESP32S3) || defined(CONFIG_IDF_TARGET_ESP32S2)
  27. #define JTAG_STATUS_BIT ESP_EFUSE_HARD_DIS_JTAG
  28. #else
  29. /* For ESP32C3, ESP32C6, ESP32H2, ESP32P4 */
  30. #define JTAG_STATUS_BIT ESP_EFUSE_DIS_PAD_JTAG
  31. #endif
  32. static const char *TAG = "esp_hmac";
  33. #if !CONFIG_IDF_TARGET_ESP32S2
  34. /**
  35. * @brief Apply the HMAC padding without the embedded length.
  36. *
  37. * @note This function does not check the data length, it is the responsibility of the other functions in this
  38. * module to make sure that \c data_len is at most SHA256_BLOCK_SZ - 1 so the padding fits in.
  39. * Otherwise, this function has undefined behavior.
  40. * Note however, that for the actual HMAC implementation, the length also needs to be applied at the end
  41. * of the block. This function alone deosn't do that.
  42. */
  43. static void write_and_padd(uint8_t *block, const uint8_t *data, uint16_t data_len)
  44. {
  45. memcpy(block, data, data_len);
  46. // Apply a one bit, followed by zero bits (refer to the TRM of respective target).
  47. block[data_len] = 0x80;
  48. bzero(block + data_len + 1, SHA256_BLOCK_SZ - data_len - 1);
  49. }
  50. esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
  51. const void *message,
  52. size_t message_len,
  53. uint8_t *hmac)
  54. {
  55. const uint8_t *message_bytes = (const uint8_t *)message;
  56. if (!message || !hmac) {
  57. return ESP_ERR_INVALID_ARG;
  58. }
  59. if (key_id >= HMAC_KEY_MAX) {
  60. return ESP_ERR_INVALID_ARG;
  61. }
  62. esp_crypto_hmac_lock_acquire();
  63. // We also enable SHA and DS here. SHA is used by HMAC, DS will otherwise hold SHA in reset state.
  64. HMAC_RCC_ATOMIC() {
  65. hmac_ll_enable_bus_clock(true);
  66. hmac_ll_reset_register();
  67. }
  68. periph_module_enable(PERIPH_SHA_MODULE);
  69. DS_RCC_ATOMIC() {
  70. ds_ll_enable_bus_clock(true);
  71. ds_ll_reset_register();
  72. }
  73. hmac_hal_start();
  74. uint32_t conf_error = hmac_hal_configure(HMAC_OUTPUT_USER, key_id);
  75. if (conf_error) {
  76. esp_crypto_hmac_lock_release();
  77. return ESP_FAIL;
  78. }
  79. if (message_len + 1 + SHA256_PAD_SZ <= SHA256_BLOCK_SZ) {
  80. // If message including padding is only one block...
  81. // Last message block, so apply SHA-256 padding rules in software
  82. uint8_t block[SHA256_BLOCK_SZ];
  83. uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
  84. write_and_padd(block, message_bytes, message_len);
  85. // Final block: append the bit length in this block and signal padding to peripheral
  86. memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
  87. &bit_len, sizeof(bit_len));
  88. hmac_hal_write_one_block_512(block);
  89. } else {
  90. // If message including padding is needs more than one block
  91. // write all blocks without padding except the last one
  92. size_t remaining_blocks = message_len / SHA256_BLOCK_SZ;
  93. for (int i = 1; i < remaining_blocks; i++) {
  94. hmac_hal_write_block_512(message_bytes);
  95. message_bytes += SHA256_BLOCK_SZ;
  96. hmac_hal_next_block_normal();
  97. }
  98. // If message fits into one block but without padding, we must not write another block.
  99. if (remaining_blocks) {
  100. hmac_hal_write_block_512(message_bytes);
  101. message_bytes += SHA256_BLOCK_SZ;
  102. }
  103. size_t remaining = message_len % SHA256_BLOCK_SZ;
  104. // Last message block, so apply SHA-256 padding rules in software
  105. uint8_t block[SHA256_BLOCK_SZ];
  106. uint64_t bit_len = __builtin_bswap64(message_len * 8 + 512);
  107. // If the remaining message and appended padding doesn't fit into a single block, we have to write an
  108. // extra block with the rest of the message and potential padding first.
  109. if (remaining >= SHA256_BLOCK_SZ - SHA256_PAD_SZ) {
  110. write_and_padd(block, message_bytes, remaining);
  111. hmac_hal_next_block_normal();
  112. hmac_hal_write_block_512(block);
  113. bzero(block, SHA256_BLOCK_SZ);
  114. } else {
  115. write_and_padd(block, message_bytes, remaining);
  116. }
  117. memcpy(block + SHA256_BLOCK_SZ - sizeof(bit_len),
  118. &bit_len, sizeof(bit_len));
  119. hmac_hal_next_block_padding();
  120. hmac_hal_write_block_512(block);
  121. }
  122. // Read back result (bit swapped)
  123. hmac_hal_read_result_256(hmac);
  124. DS_RCC_ATOMIC() {
  125. ds_ll_enable_bus_clock(false);
  126. }
  127. periph_module_disable(PERIPH_SHA_MODULE);
  128. HMAC_RCC_ATOMIC() {
  129. hmac_ll_enable_bus_clock(false);
  130. }
  131. esp_crypto_hmac_lock_release();
  132. return ESP_OK;
  133. }
  134. static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) {
  135. return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id;
  136. }
  137. esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
  138. {
  139. int ets_status;
  140. esp_err_t err = ESP_OK;
  141. if ((!token) || (key_id >= HMAC_KEY_MAX))
  142. return ESP_ERR_INVALID_ARG;
  143. /* Check if JTAG is permanently disabled by HW Disable eFuse */
  144. if (esp_efuse_read_field_bit(JTAG_STATUS_BIT)) {
  145. ESP_LOGE(TAG, "JTAG disabled permanently.");
  146. return ESP_FAIL;
  147. }
  148. esp_crypto_hmac_lock_acquire();
  149. ets_status = ets_jtag_enable_temporarily(token, convert_key_type(key_id));
  150. if (ets_status != ETS_OK) {
  151. // ets_jtag_enable_temporarily returns either ETS_OK or ETS_FAIL
  152. err = ESP_FAIL;
  153. ESP_LOGE(TAG, "JTAG re-enabling failed (%d)", err);
  154. }
  155. ESP_LOGD(TAG, "HMAC computation in downstream mode is completed.");
  156. ets_hmac_disable();
  157. esp_crypto_hmac_lock_release();
  158. return err;
  159. }
  160. esp_err_t esp_hmac_jtag_disable()
  161. {
  162. esp_crypto_hmac_lock_acquire();
  163. REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
  164. esp_crypto_hmac_lock_release();
  165. ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
  166. return ESP_OK;
  167. }
  168. #else /* !CONFIG_IDF_TARGET_ESP32S2 */
  169. static ets_efuse_block_t convert_key_type(hmac_key_id_t key_id) {
  170. return ETS_EFUSE_BLOCK_KEY0 + (ets_efuse_block_t) key_id;
  171. }
  172. esp_err_t esp_hmac_calculate(hmac_key_id_t key_id,
  173. const void *message,
  174. size_t message_len,
  175. uint8_t *hmac)
  176. {
  177. int hmac_ret;
  178. if (!message || !hmac) return ESP_ERR_INVALID_ARG;
  179. if (key_id >= HMAC_KEY_MAX) return ESP_ERR_INVALID_ARG;
  180. esp_crypto_dma_lock_acquire();
  181. ets_hmac_enable();
  182. hmac_ret = ets_hmac_calculate_message(convert_key_type(key_id), message, message_len, hmac);
  183. ets_hmac_disable();
  184. esp_crypto_dma_lock_release();
  185. if (hmac_ret != 0) {
  186. return ESP_FAIL;
  187. } else {
  188. return ESP_OK;
  189. }
  190. }
  191. esp_err_t esp_hmac_jtag_enable(hmac_key_id_t key_id, const uint8_t *token)
  192. {
  193. int ets_status;
  194. esp_err_t err = ESP_OK;
  195. if ((!token) || (key_id >= HMAC_KEY_MAX))
  196. return ESP_ERR_INVALID_ARG;
  197. /* Check if JTAG is permanently disabled by HW Disable eFuse */
  198. if (esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG)) {
  199. ESP_LOGE(TAG, "JTAG disabled permanently.");
  200. return ESP_FAIL;
  201. }
  202. esp_crypto_dma_lock_acquire();
  203. ets_hmac_enable();
  204. /* Token updating into HMAC module. */
  205. for (int i = 0; i < 32; i += 4) {
  206. uint32_t key_word;
  207. memcpy(&key_word, &token[i], 4);
  208. REG_WRITE(DPORT_JTAG_CTRL_0_REG + i, __builtin_bswap32(key_word));
  209. }
  210. ets_status = ets_hmac_calculate_downstream(convert_key_type(key_id), ETS_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG);
  211. if (ets_status != ETS_OK) {
  212. err = ESP_FAIL;
  213. ESP_LOGE(TAG, "HMAC downstream JTAG enable mode setting failed. (%d)", err);
  214. }
  215. ESP_LOGD(TAG, "HMAC computation in downstream mode is completed.");
  216. ets_hmac_disable();
  217. esp_crypto_dma_lock_release();
  218. return err;
  219. }
  220. esp_err_t esp_hmac_jtag_disable()
  221. {
  222. esp_crypto_dma_lock_acquire();
  223. REG_WRITE(HMAC_SET_INVALIDATE_JTAG_REG, 1);
  224. esp_crypto_dma_lock_release();
  225. ESP_LOGD(TAG, "Invalidate JTAG result register. JTAG disabled.");
  226. return ESP_OK;
  227. }
  228. #endif /* CONFIG_IDF_TARGET_ESP32S2*/