• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)&reg_addr_buf[i]);
146             digest_state_words[i]   = DPORT_SEQUENCE_REG_READ((uint32_t)&reg_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)&reg_addr_buf[0], digest_word_len);
151     }
152 }
153 
154 #ifdef __cplusplus
155 }
156 #endif
157