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