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