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