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