1 /*
2 * SHA-512 implementation with hardware ESP32 support added.
3 * Uses mbedTLS software implementation for failover when concurrent
4 * SHA operations are in use.
5 *
6 * SPDX-FileCopyrightText: The Mbed TLS Contributors
7 *
8 * SPDX-License-Identifier: Apache-2.0
9 *
10 * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
11 */
12 /*
13 * The SHA-512 Secure Hash Standard was published by NIST in 2002.
14 *
15 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
16 */
17
18 #include <mbedtls/build_info.h>
19
20 #if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT)
21
22 #include "mbedtls/sha512.h"
23
24 #if defined(_MSC_VER) || defined(__WATCOMC__)
25 #define UL64(x) x##ui64
26 #else
27 #define UL64(x) x##ULL
28 #endif
29
30 #include <string.h>
31
32 #if defined(MBEDTLS_SELF_TEST)
33 #if defined(MBEDTLS_PLATFORM_C)
34 #include "mbedtls/platform.h"
35 #else
36 #include <stdio.h>
37 #define mbedtls_printf printf
38 #endif /* MBEDTLS_PLATFORM_C */
39 #endif /* MBEDTLS_SELF_TEST */
40
41 #include "sha/sha_parallel_engine.h"
42
sha_type(const mbedtls_sha512_context * ctx)43 inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx)
44 {
45 return ctx->is384 ? SHA2_384 : SHA2_512;
46 }
47
48 /* Implementation that should never be optimized out by the compiler */
mbedtls_zeroize(void * v,size_t n)49 static void mbedtls_zeroize( void *v, size_t n )
50 {
51 volatile unsigned char *p = v;
52 while ( n-- ) {
53 *p++ = 0;
54 }
55 }
56
57 /*
58 * 64-bit integer manipulation macros (big endian)
59 */
60 #ifndef GET_UINT64_BE
61 #define GET_UINT64_BE(n,b,i) \
62 { \
63 (n) = ( (uint64_t) (b)[(i) ] << 56 ) \
64 | ( (uint64_t) (b)[(i) + 1] << 48 ) \
65 | ( (uint64_t) (b)[(i) + 2] << 40 ) \
66 | ( (uint64_t) (b)[(i) + 3] << 32 ) \
67 | ( (uint64_t) (b)[(i) + 4] << 24 ) \
68 | ( (uint64_t) (b)[(i) + 5] << 16 ) \
69 | ( (uint64_t) (b)[(i) + 6] << 8 ) \
70 | ( (uint64_t) (b)[(i) + 7] ); \
71 }
72 #endif /* GET_UINT64_BE */
73
74 #ifndef PUT_UINT64_BE
75 #define PUT_UINT64_BE(n,b,i) \
76 { \
77 (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
78 (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
79 (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
80 (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
81 (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
82 (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
83 (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
84 (b)[(i) + 7] = (unsigned char) ( (n) ); \
85 }
86 #endif /* PUT_UINT64_BE */
87
mbedtls_sha512_init(mbedtls_sha512_context * ctx)88 void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
89 {
90 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
91 }
92
mbedtls_sha512_free(mbedtls_sha512_context * ctx)93 void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
94 {
95 if ( ctx == NULL ) {
96 return;
97 }
98
99 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
100 esp_sha_unlock_engine(sha_type(ctx));
101 }
102 mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
103 }
104
mbedtls_sha512_clone(mbedtls_sha512_context * dst,const mbedtls_sha512_context * src)105 void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
106 const mbedtls_sha512_context *src )
107 {
108 *dst = *src;
109
110 if (src->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
111 /* Copy hardware digest state out to cloned state,
112 which will be a software digest.
113
114 Always read 512 bits of state, even for SHA-384
115 (SHA-384 state is identical to SHA-512, only
116 digest is truncated.)
117 */
118 esp_sha_read_digest_state(SHA2_512, dst->state);
119 dst->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
120 }
121 }
122
123
124 /*
125 * SHA-512 context setup
126 */
mbedtls_sha512_starts(mbedtls_sha512_context * ctx,int is384)127 int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
128 {
129 ctx->total[0] = 0;
130 ctx->total[1] = 0;
131
132 if ( is384 == 0 ) {
133 /* SHA-512 */
134 ctx->state[0] = UL64(0x6A09E667F3BCC908);
135 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
136 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
137 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
138 ctx->state[4] = UL64(0x510E527FADE682D1);
139 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
140 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
141 ctx->state[7] = UL64(0x5BE0CD19137E2179);
142 } else {
143 /* SHA-384 */
144 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
145 ctx->state[1] = UL64(0x629A292A367CD507);
146 ctx->state[2] = UL64(0x9159015A3070DD17);
147 ctx->state[3] = UL64(0x152FECD8F70E5939);
148 ctx->state[4] = UL64(0x67332667FFC00B31);
149 ctx->state[5] = UL64(0x8EB44A8768581511);
150 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
151 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
152 }
153
154 ctx->is384 = is384;
155 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
156 esp_sha_unlock_engine(sha_type(ctx));
157 }
158 ctx->mode = ESP_MBEDTLS_SHA512_UNUSED;
159
160 return 0;
161 }
162
163 /*
164 * Round constants
165 */
166 static const uint64_t K[80] = {
167 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
168 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
169 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
170 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
171 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
172 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
173 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
174 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
175 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
176 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
177 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
178 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
179 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
180 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
181 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
182 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
183 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
184 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
185 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
186 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
187 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
188 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
189 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
190 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
191 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
192 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
193 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
194 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
195 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
196 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
197 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
198 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
199 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
200 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
201 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
202 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
203 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
204 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
205 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
206 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
207 };
208
209
mbedtls_sha512_software_process(mbedtls_sha512_context * ctx,const unsigned char data[128])210 static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
211 {
212 int i;
213 uint64_t temp1, temp2, W[80];
214 uint64_t A, B, C, D, E, F, G, H;
215
216 #define SHR(x,n) (x >> n)
217 #define ROTR(x,n) (SHR(x,n) | (x << (64 - n)))
218
219 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
220 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
221
222 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
223 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
224
225 #define F0(x,y,z) ((x & y) | (z & (x | y)))
226 #define F1(x,y,z) (z ^ (x & (y ^ z)))
227
228 #define P(a,b,c,d,e,f,g,h,x,K) \
229 { \
230 temp1 = h + S3(e) + F1(e,f,g) + K + x; \
231 temp2 = S2(a) + F0(a,b,c); \
232 d += temp1; h = temp1 + temp2; \
233 }
234
235 for ( i = 0; i < 16; i++ ) {
236 GET_UINT64_BE( W[i], data, i << 3 );
237 }
238
239 for ( ; i < 80; i++ ) {
240 W[i] = S1(W[i - 2]) + W[i - 7] +
241 S0(W[i - 15]) + W[i - 16];
242 }
243
244 A = ctx->state[0];
245 B = ctx->state[1];
246 C = ctx->state[2];
247 D = ctx->state[3];
248 E = ctx->state[4];
249 F = ctx->state[5];
250 G = ctx->state[6];
251 H = ctx->state[7];
252 i = 0;
253
254 do {
255 P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++;
256 P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++;
257 P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++;
258 P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++;
259 P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++;
260 P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++;
261 P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++;
262 P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++;
263 } while ( i < 80 );
264
265 ctx->state[0] += A;
266 ctx->state[1] += B;
267 ctx->state[2] += C;
268 ctx->state[3] += D;
269 ctx->state[4] += E;
270 ctx->state[5] += F;
271 ctx->state[6] += G;
272 ctx->state[7] += H;
273 }
274
275
esp_internal_sha512_parallel_engine_process(mbedtls_sha512_context * ctx,const unsigned char data[128],bool read_digest)276 static int esp_internal_sha512_parallel_engine_process( mbedtls_sha512_context *ctx, const unsigned char data[128], bool read_digest )
277 {
278 bool first_block = false;
279
280 if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) {
281 /* try to use hardware for this digest */
282 if (esp_sha_try_lock_engine(sha_type(ctx))) {
283 ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE;
284 first_block = true;
285 } else {
286 ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
287 }
288 }
289
290 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
291 esp_sha_block(sha_type(ctx), data, first_block);
292 if (read_digest) {
293 esp_sha_read_digest_state(sha_type(ctx), ctx->state);
294 }
295 } else {
296 mbedtls_sha512_software_process(ctx, data);
297 }
298
299 return 0;
300 }
301
302
mbedtls_internal_sha512_process(mbedtls_sha512_context * ctx,const unsigned char data[128])303 int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
304 {
305 return esp_internal_sha512_parallel_engine_process(ctx, data, true);
306 }
307
308
309 /*
310 * SHA-512 process buffer
311 */
mbedtls_sha512_update(mbedtls_sha512_context * ctx,const unsigned char * input,size_t ilen)312 int mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input,
313 size_t ilen )
314 {
315 int ret = -1;
316 size_t fill;
317 unsigned int left;
318
319 if ( ilen == 0 ) {
320 return 0;
321 }
322
323 left = (unsigned int) (ctx->total[0] & 0x7F);
324 fill = 128 - left;
325
326 ctx->total[0] += (uint64_t) ilen;
327
328 if ( ctx->total[0] < (uint64_t) ilen ) {
329 ctx->total[1]++;
330 }
331
332 if ( left && ilen >= fill ) {
333 memcpy( (void *) (ctx->buffer + left), input, fill );
334 if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, ctx->buffer, false ) ) != 0 ) {
335 return ret;
336 }
337
338 input += fill;
339 ilen -= fill;
340 left = 0;
341 }
342
343 while ( ilen >= 128 ) {
344 if ( ( ret = esp_internal_sha512_parallel_engine_process( ctx, input, false ) ) != 0 ) {
345 return ret;
346 }
347
348 input += 128;
349 ilen -= 128;
350 }
351
352 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
353 esp_sha_read_digest_state(sha_type(ctx), ctx->state);
354 }
355
356 if ( ilen > 0 ) {
357 memcpy( (void *) (ctx->buffer + left), input, ilen );
358 }
359
360 return 0;
361 }
362
363 static const unsigned char sha512_padding[128] = {
364 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
365 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
366 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
367 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
368 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
369 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
370 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
371 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
372 };
373
374 /*
375 * SHA-512 final digest
376 */
mbedtls_sha512_finish(mbedtls_sha512_context * ctx,unsigned char * output)377 int mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char *output )
378 {
379 int ret = -1;
380 size_t last, padn;
381 uint64_t high, low;
382 unsigned char msglen[16];
383
384 high = ( ctx->total[0] >> 61 )
385 | ( ctx->total[1] << 3 );
386 low = ( ctx->total[0] << 3 );
387
388 PUT_UINT64_BE( high, msglen, 0 );
389 PUT_UINT64_BE( low, msglen, 8 );
390
391 last = (size_t)( ctx->total[0] & 0x7F );
392 padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
393
394 if ( ( ret = mbedtls_sha512_update( ctx, sha512_padding, padn ) ) != 0 ) {
395 goto out;
396 }
397
398 if ( ( ret = mbedtls_sha512_update( ctx, msglen, 16 ) ) != 0 ) {
399 goto out;
400 }
401
402 /* if state is in hardware, read it out */
403 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
404 esp_sha_read_digest_state(sha_type(ctx), ctx->state);
405 }
406
407 PUT_UINT64_BE( ctx->state[0], output, 0 );
408 PUT_UINT64_BE( ctx->state[1], output, 8 );
409 PUT_UINT64_BE( ctx->state[2], output, 16 );
410 PUT_UINT64_BE( ctx->state[3], output, 24 );
411 PUT_UINT64_BE( ctx->state[4], output, 32 );
412 PUT_UINT64_BE( ctx->state[5], output, 40 );
413
414 if ( ctx->is384 == 0 ) {
415 PUT_UINT64_BE( ctx->state[6], output, 48 );
416 PUT_UINT64_BE( ctx->state[7], output, 56 );
417 }
418
419 out:
420 if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) {
421 esp_sha_unlock_engine(sha_type(ctx));
422 ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE;
423 }
424
425 return ret;
426 }
427
428 #endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */
429