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
15 // The HAL layer for SHA
16
17 #include "hal/sha_hal.h"
18 #include "hal/sha_types.h"
19 #include "hal/sha_ll.h"
20 #include "soc/soc_caps.h"
21 #include <stdlib.h>
22 #include <stdio.h>
23
24
25 #define SHA1_STATE_LEN_WORDS (160 / 32)
26 #define SHA256_STATE_LEN_WORDS (256 / 32)
27 #define SHA512_STATE_LEN_WORDS (512 / 32)
28
29 #if CONFIG_IDF_TARGET_ESP32
30
31 /* Return state size (in words) for a given SHA type */
state_length(esp_sha_type type)32 inline static size_t state_length(esp_sha_type type)
33 {
34 switch (type) {
35 case SHA1:
36 return SHA1_STATE_LEN_WORDS;
37 case SHA2_256:
38 return SHA256_STATE_LEN_WORDS;
39 case SHA2_384:
40 case SHA2_512:
41 return SHA512_STATE_LEN_WORDS;
42 default:
43 return 0;
44 }
45 }
46
47 #else
48 /* Return state size (in words) for a given SHA type */
state_length(esp_sha_type type)49 inline static size_t state_length(esp_sha_type type)
50 {
51 switch (type) {
52 case SHA1:
53 return SHA1_STATE_LEN_WORDS;
54 case SHA2_224:
55 case SHA2_256:
56 return SHA256_STATE_LEN_WORDS;
57 #if SOC_SHA_SUPPORT_SHA384
58 case SHA2_384:
59 return SHA512_STATE_LEN_WORDS;
60 #endif
61 #if SOC_SHA_SUPPORT_SHA512
62 case SHA2_512:
63 return SHA512_STATE_LEN_WORDS;
64 #endif
65 #if SOC_SHA_SUPPORT_SHA512_T
66 case SHA2_512224:
67 case SHA2_512256:
68 case SHA2_512T:
69 return SHA512_STATE_LEN_WORDS;
70 #endif
71 default:
72 return 0;
73 }
74 }
75 #endif
76
77
78 /* Hash a single block */
sha_hal_hash_block(esp_sha_type sha_type,const void * data_block,size_t block_word_len,bool first_block)79 void sha_hal_hash_block(esp_sha_type sha_type, const void *data_block, size_t block_word_len, bool first_block)
80 {
81 sha_hal_wait_idle();
82
83 sha_ll_fill_text_block(data_block, block_word_len);
84
85 /* Start hashing */
86 if (first_block) {
87 sha_ll_start_block(sha_type);
88 } else {
89 sha_ll_continue_block(sha_type);
90 }
91 }
92
93 #if SOC_SHA_SUPPORT_DMA
94
95 /* Hashes a number of message blocks using DMA */
sha_hal_hash_dma(esp_sha_type sha_type,size_t num_blocks,bool first_block)96 void sha_hal_hash_dma(esp_sha_type sha_type, size_t num_blocks, bool first_block)
97 {
98 sha_hal_wait_idle();
99
100 sha_ll_set_block_num(num_blocks);
101
102 /* Start hashing */
103 if (first_block) {
104 sha_ll_start_dma(sha_type);
105 } else {
106 sha_ll_continue_dma(sha_type);
107 }
108 }
109
110 #endif //SOC_SHA_SUPPORT_DMA
111
sha_hal_wait_idle()112 void sha_hal_wait_idle()
113 {
114 while (sha_ll_busy()) {
115 }
116 }
117
118 /* Reads the current message digest from the SHA engine */
sha_hal_read_digest(esp_sha_type sha_type,void * digest_state)119 void sha_hal_read_digest(esp_sha_type sha_type, void *digest_state)
120 {
121 uint32_t *digest_state_words = (uint32_t *)digest_state;
122
123 sha_ll_load(sha_type);
124 uint32_t word_len = state_length(sha_type);
125
126 sha_hal_wait_idle();
127 sha_ll_read_digest(sha_type, digest_state, word_len);
128
129 /* Fault injection check: verify SHA engine actually ran,
130 state is not all zeroes.
131 */
132 for (size_t i = 0; i < word_len; i++) {
133 if (digest_state_words[i] != 0) {
134 return;
135 }
136 }
137 abort(); // SHA peripheral returned all zero state, probably due to fault injection
138 }
139
140 #if SOC_SHA_SUPPORT_RESUME
141 /* Writes the message digest to the SHA engine */
sha_hal_write_digest(esp_sha_type sha_type,void * digest_state)142 void sha_hal_write_digest(esp_sha_type sha_type, void *digest_state)
143 {
144 sha_ll_write_digest(sha_type, digest_state, state_length(sha_type));
145 }
146 #endif //SOC_SHA_SUPPORT_RESUME
147
148 #if SOC_SHA_SUPPORT_SHA512_T
149
150 /* Calculates and sets the initial digiest for SHA512_t */
sha_hal_sha512_init_hash(uint32_t t_string,uint8_t t_len)151 void sha_hal_sha512_init_hash(uint32_t t_string, uint8_t t_len)
152 {
153 sha_ll_t_string_set(t_string);
154 sha_ll_t_len_set(t_len);
155
156 sha_ll_start_block(SHA2_512T);
157
158 sha_hal_wait_idle();
159 }
160 #endif //SOC_SHA_SUPPORT_SHA512_T
161