1 // Copyright 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 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #pragma once
15
16 #include <stdbool.h>
17 #include "hal/sha_types.h"
18 #include "soc/hwcrypto_reg.h"
19 #include "soc/dport_access.h"
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #define SHA_LL_TYPE_OFFSET 0x10
26
27 /**
28 * @brief Returns the LOAD_REG register address for the given sha type
29 *
30 * @param sha_type The SHA algorithm type
31 * @return uint32_t the LOAD_REG register address
32 */
SHA_LOAD_REG(esp_sha_type sha_type)33 inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type)
34 {
35 return SHA_1_LOAD_REG + sha_type * SHA_LL_TYPE_OFFSET;
36 }
37
38 /**
39 * @brief Returns the BUSY register address for the given sha type
40 *
41 * @param sha_type The SHA algorithm type
42 * @return uint32_t the BUSY register address
43 */
SHA_BUSY_REG(esp_sha_type sha_type)44 inline static uint32_t SHA_BUSY_REG(esp_sha_type sha_type)
45 {
46 return SHA_1_BUSY_REG + sha_type * SHA_LL_TYPE_OFFSET;
47 }
48
49 /**
50 * @brief Returns the START register address for the given sha type
51 *
52 * @param sha_type The SHA algorithm type
53 * @return uint32_t the START register address
54 */
SHA_START_REG(esp_sha_type sha_type)55 inline static uint32_t SHA_START_REG(esp_sha_type sha_type)
56 {
57 return SHA_1_START_REG + sha_type * SHA_LL_TYPE_OFFSET;
58 }
59
60 /**
61 * @brief Returns the CONTINUE register address for the given sha type
62 *
63 * @param sha_type The SHA algorithm type
64 * @return uint32_t the CONTINUE register address
65 */
SHA_CONTINUE_REG(esp_sha_type sha_type)66 inline static uint32_t SHA_CONTINUE_REG(esp_sha_type sha_type)
67 {
68 return SHA_1_CONTINUE_REG + sha_type * SHA_LL_TYPE_OFFSET;
69 }
70
71 /**
72 * @brief Start a new SHA block conversion (no initial hash in HW)
73 *
74 * @param sha_type The SHA algorithm type
75 */
sha_ll_start_block(esp_sha_type sha_type)76 static inline void sha_ll_start_block(esp_sha_type sha_type)
77 {
78 DPORT_REG_WRITE(SHA_START_REG(sha_type), 1);
79 }
80
81 /**
82 * @brief Continue a SHA block conversion (initial hash in HW)
83 *
84 * @param sha_type The SHA algorithm type
85 */
sha_ll_continue_block(esp_sha_type sha_type)86 static inline void sha_ll_continue_block(esp_sha_type sha_type)
87 {
88 DPORT_REG_WRITE(SHA_CONTINUE_REG(sha_type), 1);
89 }
90
91 /**
92 * @brief Load the current hash digest to digest register
93 *
94 * @param sha_type The SHA algorithm type
95 */
sha_ll_load(esp_sha_type sha_type)96 static inline void sha_ll_load(esp_sha_type sha_type)
97 {
98 DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1);
99 }
100
101 /**
102 * @brief Checks if the SHA engine is currently busy hashing a block
103 *
104 * @return true SHA engine busy
105 * @return false SHA engine idle
106 */
sha_ll_busy(void)107 static inline bool sha_ll_busy(void)
108 {
109 return (DPORT_REG_READ(SHA_1_BUSY_REG) || DPORT_REG_READ(SHA_256_BUSY_REG)
110 || DPORT_REG_READ(SHA_384_BUSY_REG) || DPORT_REG_READ(SHA_512_BUSY_REG));
111 }
112
113 /**
114 * @brief Write a text (message) block to the SHA engine
115 *
116 * @param input_text Input buffer to be written to the SHA engine
117 * @param block_word_len Number of words in block
118 */
sha_ll_fill_text_block(const void * input_text,size_t block_word_len)119 static inline void sha_ll_fill_text_block(const void *input_text, size_t block_word_len)
120 {
121 uint32_t *reg_addr_buf = NULL;
122 uint32_t *data_words = NULL;
123 reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
124 data_words = (uint32_t *)input_text;
125 for (size_t i = 0; i < block_word_len; i++) {
126 reg_addr_buf[i] = __builtin_bswap32(data_words[i]);
127 }
128 }
129
130 /**
131 * @brief Read the message digest from the SHA engine
132 *
133 * @param sha_type The SHA algorithm type
134 * @param digest_state Buffer that message digest will be written to
135 * @param digest_word_len Length of the message digest
136 */
sha_ll_read_digest(esp_sha_type sha_type,void * digest_state,size_t digest_word_len)137 static inline void sha_ll_read_digest(esp_sha_type sha_type, void *digest_state, size_t digest_word_len)
138 {
139 uint32_t *digest_state_words = (uint32_t *)digest_state;
140 uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
141 if (sha_type == SHA2_384 || sha_type == SHA2_512) {
142 /* for these ciphers using 64-bit states, swap each pair of words */
143 DPORT_INTERRUPT_DISABLE(); // Disable interrupt only on current CPU.
144 for (size_t i = 0; i < digest_word_len; i += 2) {
145 digest_state_words[i + 1] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i]);
146 digest_state_words[i] = DPORT_SEQUENCE_REG_READ((uint32_t)®_addr_buf[i + 1]);
147 }
148 DPORT_INTERRUPT_RESTORE(); // restore the previous interrupt level
149 } else {
150 esp_dport_access_read_buffer(digest_state_words, (uint32_t)®_addr_buf[0], digest_word_len);
151 }
152 }
153
154 #ifdef __cplusplus
155 }
156 #endif
157