1 /*
2 * SHA-512 implementation with hardware ESP support added.
3 *
4 * SPDX-FileCopyrightText: The Mbed TLS Contributors
5 *
6 * SPDX-License-Identifier: Apache-2.0
7 *
8 * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
9 */
10 /*
11 * The SHA-512 Secure Hash Standard was published by NIST in 2002.
12 *
13 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
14 */
15
16 #include <mbedtls/build_info.h>
17
18 #if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT)
19
20 #include "mbedtls/sha512.h"
21
22 #if defined(_MSC_VER) || defined(__WATCOMC__)
23 #define UL64(x) x##ui64
24 #else
25 #define UL64(x) x##ULL
26 #endif
27
28 #include <string.h>
29
30 #if defined(MBEDTLS_SELF_TEST)
31 #if defined(MBEDTLS_PLATFORM_C)
32 #include "mbedtls/platform.h"
33 #else
34 #include <stdio.h>
35 #define mbedtls_printf printf
36 #endif /* MBEDTLS_PLATFORM_C */
37 #endif /* MBEDTLS_SELF_TEST */
38
39 #include "sha/sha_dma.h"
40
41 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)42 static void mbedtls_zeroize( void *v, size_t n )
43 {
44 volatile unsigned char *p = v;
45 while ( n-- ) {
46 *p++ = 0;
47 }
48 }
49
50 /*
51 * 64-bit integer manipulation macros (big endian)
52 */
53 #ifndef PUT_UINT64_BE
54 #define PUT_UINT64_BE(n,b,i) \
55 { \
56 (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
57 (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
58 (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
59 (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
60 (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
61 (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
62 (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
63 (b)[(i) + 7] = (unsigned char) ( (n) ); \
64 }
65 #endif /* PUT_UINT64_BE */
66
esp_sha512_set_mode(mbedtls_sha512_context * ctx,esp_sha_type type)67 void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type)
68 {
69 switch (type) {
70 case SHA2_384:
71 case SHA2_512224:
72 case SHA2_512256:
73 case SHA2_512T:
74 ctx->mode = type;
75 break;
76 default:
77 ctx->mode = SHA2_512;
78 break;
79 }
80 }
81
82
83 /* For SHA512/t mode the intial hash value will depend on t */
esp_sha512_set_t(mbedtls_sha512_context * ctx,uint16_t t_val)84 void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val)
85 {
86 ctx->t_val = t_val;
87 }
88
mbedtls_sha512_init(mbedtls_sha512_context * ctx)89 void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
90 {
91 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
92 }
93
mbedtls_sha512_free(mbedtls_sha512_context * ctx)94 void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
95 {
96 if ( ctx == NULL ) {
97 return;
98 }
99
100 mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
101 }
102
mbedtls_sha512_clone(mbedtls_sha512_context * dst,const mbedtls_sha512_context * src)103 void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
104 const mbedtls_sha512_context *src )
105 {
106 memcpy(dst, src, sizeof(mbedtls_sha512_context));
107 }
108
109 /*
110 * SHA-512 context setup
111 */
mbedtls_sha512_starts(mbedtls_sha512_context * ctx,int is384)112 int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
113 {
114 mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
115
116 if ( is384 ) {
117 ctx->mode = SHA2_384;
118 } else {
119 ctx->mode = SHA2_512;
120 }
121
122 return 0;
123 }
124
esp_internal_sha_update_state(mbedtls_sha512_context * ctx)125 static int esp_internal_sha_update_state(mbedtls_sha512_context *ctx)
126 {
127 if (ctx->sha_state == ESP_SHA512_STATE_INIT) {
128 if (ctx->mode == SHA2_512T) {
129 int ret = -1;
130 if ((ret = esp_sha_512_t_init_hash(ctx->t_val)) != 0) {
131 return ret;
132 }
133 ctx->first_block = false;
134 } else {
135 ctx->first_block = true;
136 }
137 ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS;
138 } else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) {
139 ctx->first_block = false;
140 esp_sha_write_digest_state(ctx->mode, ctx->state);
141 }
142 return 0;
143 }
144
esp_internal_sha512_dma_process(mbedtls_sha512_context * ctx,const uint8_t * data,size_t len,uint8_t * buf,size_t buf_len)145 static int esp_internal_sha512_dma_process(mbedtls_sha512_context *ctx,
146 const uint8_t *data, size_t len,
147 uint8_t *buf, size_t buf_len)
148 {
149
150
151 return esp_sha_dma(ctx->mode, data, len, buf, buf_len, ctx->first_block);
152
153
154 }
155
mbedtls_internal_sha512_process(mbedtls_sha512_context * ctx,const unsigned char data[128])156 int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
157 {
158 int ret = -1;
159 esp_sha_acquire_hardware();
160
161 ret = esp_internal_sha_update_state(ctx);
162 if (ret != 0) {
163 esp_sha_release_hardware();
164 return ret;
165 }
166
167 ret = esp_internal_sha512_dma_process(ctx, data, 128, 0, 0);
168 if (ret != 0) {
169 esp_sha_release_hardware();
170 return ret;
171 }
172
173 esp_sha_read_digest_state(ctx->mode, ctx->state);
174 esp_sha_release_hardware();
175
176 return ret;
177
178 }
179
180 /*
181 * SHA-512 process buffer
182 */
mbedtls_sha512_update(mbedtls_sha512_context * ctx,const unsigned char * input,size_t ilen)183 int mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
184 size_t ilen )
185 {
186 size_t fill;
187 unsigned int left, len, local_len = 0;
188
189 if ( ilen == 0 ) {
190 return 0;
191 }
192
193 left = (unsigned int) (ctx->total[0] & 0x7F);
194 fill = 128 - left;
195
196 ctx->total[0] += (uint64_t) ilen;
197
198 if ( ctx->total[0] < (uint64_t) ilen ) {
199 ctx->total[1]++;
200 }
201
202 if ( left && ilen >= fill ) {
203 memcpy( (void *) (ctx->buffer + left), input, fill );
204
205 input += fill;
206 ilen -= fill;
207 left = 0;
208 local_len = 128;
209 }
210
211 len = (ilen / 128) * 128;
212
213 if ( len || local_len) {
214
215 esp_sha_acquire_hardware();
216
217 int ret = esp_internal_sha_update_state(ctx);
218
219 if (ret != 0) {
220 esp_sha_release_hardware();
221 return ret;
222 }
223
224 ret = esp_internal_sha512_dma_process(ctx, input, len, ctx->buffer, local_len);
225
226 if (ret != 0) {
227 esp_sha_release_hardware();
228 return ret;
229 }
230
231 esp_sha_read_digest_state(ctx->mode, ctx->state);
232
233 esp_sha_release_hardware();
234
235 }
236
237
238 if ( ilen > 0 ) {
239 memcpy( (void *) (ctx->buffer + left), input + len, ilen - len );
240 }
241
242 return 0;
243 }
244
245 static const unsigned char sha512_padding[128] = {
246 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
247 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
248 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
249 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
250 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
251 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
252 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
253 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
254 };
255
256 /*
257 * SHA-512 final digest
258 */
mbedtls_sha512_finish(mbedtls_sha512_context * ctx,unsigned char * output)259 int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char *output )
260 {
261 int ret = -1;
262 size_t last, padn;
263 uint64_t high, low;
264 unsigned char msglen[16];
265
266 high = ( ctx->total[0] >> 61 )
267 | ( ctx->total[1] << 3 );
268 low = ( ctx->total[0] << 3 );
269
270 PUT_UINT64_BE( high, msglen, 0 );
271 PUT_UINT64_BE( low, msglen, 8 );
272
273 last = (size_t)( ctx->total[0] & 0x7F );
274 padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
275
276 if ( ( ret = mbedtls_sha512_update( ctx, sha512_padding, padn ) ) != 0 ) {
277 return ret;
278 }
279
280 if ( ( ret = mbedtls_sha512_update( ctx, msglen, 16 ) ) != 0 ) {
281 return ret;
282 }
283
284 if (ctx->mode == SHA2_384) {
285 memcpy(output, ctx->state, 48);
286 } else {
287 memcpy(output, ctx->state, 64);
288 }
289
290 return ret;
291 }
292
293 #endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */
294