1 /*
2  *  FIPS-180-2 compliant SHA-384/512 implementation
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0
6  *
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
8  *  not use this file except in compliance with the License.
9  *  You may obtain a copy of the License at
10  *
11  *  http://www.apache.org/licenses/LICENSE-2.0
12  *
13  *  Unless required by applicable law or agreed to in writing, software
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  *  See the License for the specific language governing permissions and
17  *  limitations under the License.
18  */
19 /*
20  *  The SHA-512 Secure Hash Standard was published by NIST in 2002.
21  *
22  *  http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
23  */
24 
25 #include "common.h"
26 
27 #if defined(MBEDTLS_SHA512_C)
28 
29 #include "mbedtls/sha512.h"
30 #include "mbedtls/platform_util.h"
31 #include "mbedtls/error.h"
32 
33 #if defined(_MSC_VER) || defined(__WATCOMC__)
34   #define UL64(x) x##ui64
35 #else
36   #define UL64(x) x##ULL
37 #endif
38 
39 #include <string.h>
40 
41 #if defined(MBEDTLS_SELF_TEST)
42 #if defined(MBEDTLS_PLATFORM_C)
43 #include "mbedtls/platform.h"
44 #else
45 #include <stdio.h>
46 #include <stdlib.h>
47 #define mbedtls_printf printf
48 #define mbedtls_calloc    calloc
49 #define mbedtls_free       free
50 #endif /* MBEDTLS_PLATFORM_C */
51 #endif /* MBEDTLS_SELF_TEST */
52 
53 #define SHA512_VALIDATE_RET(cond)                           \
54     MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
55 #define SHA512_VALIDATE(cond)  MBEDTLS_INTERNAL_VALIDATE( cond )
56 
57 #if !defined(MBEDTLS_SHA512_ALT)
58 
59 #if defined(MBEDTLS_SHA512_SMALLER)
sha512_put_uint64_be(uint64_t n,unsigned char * b,uint8_t i)60 static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
61 {
62     MBEDTLS_PUT_UINT64_BE(n, b, i);
63 }
64 #else
65 #define sha512_put_uint64_be    MBEDTLS_PUT_UINT64_BE
66 #endif /* MBEDTLS_SHA512_SMALLER */
67 
mbedtls_sha512_init(mbedtls_sha512_context * ctx)68 void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
69 {
70     SHA512_VALIDATE( ctx != NULL );
71 
72     memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
73 }
74 
mbedtls_sha512_free(mbedtls_sha512_context * ctx)75 void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
76 {
77     if( ctx == NULL )
78         return;
79 
80     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
81 }
82 
mbedtls_sha512_clone(mbedtls_sha512_context * dst,const mbedtls_sha512_context * src)83 void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
84                            const mbedtls_sha512_context *src )
85 {
86     SHA512_VALIDATE( dst != NULL );
87     SHA512_VALIDATE( src != NULL );
88 
89     *dst = *src;
90 }
91 
92 /*
93  * SHA-512 context setup
94  */
mbedtls_sha512_starts(mbedtls_sha512_context * ctx,int is384)95 int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
96 {
97     SHA512_VALIDATE_RET( ctx != NULL );
98 #if defined(MBEDTLS_SHA384_C)
99     SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
100 #else
101     SHA512_VALIDATE_RET( is384 == 0 );
102 #endif
103 
104     ctx->total[0] = 0;
105     ctx->total[1] = 0;
106 
107     if( is384 == 0 )
108     {
109         /* SHA-512 */
110         ctx->state[0] = UL64(0x6A09E667F3BCC908);
111         ctx->state[1] = UL64(0xBB67AE8584CAA73B);
112         ctx->state[2] = UL64(0x3C6EF372FE94F82B);
113         ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
114         ctx->state[4] = UL64(0x510E527FADE682D1);
115         ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
116         ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
117         ctx->state[7] = UL64(0x5BE0CD19137E2179);
118     }
119     else
120     {
121 #if !defined(MBEDTLS_SHA384_C)
122         return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
123 #else
124         /* SHA-384 */
125         ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
126         ctx->state[1] = UL64(0x629A292A367CD507);
127         ctx->state[2] = UL64(0x9159015A3070DD17);
128         ctx->state[3] = UL64(0x152FECD8F70E5939);
129         ctx->state[4] = UL64(0x67332667FFC00B31);
130         ctx->state[5] = UL64(0x8EB44A8768581511);
131         ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
132         ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
133 #endif /* MBEDTLS_SHA384_C */
134     }
135 
136 #if defined(MBEDTLS_SHA384_C)
137     ctx->is384 = is384;
138 #endif
139 
140     return( 0 );
141 }
142 
143 #if !defined(MBEDTLS_SHA512_PROCESS_ALT)
144 
145 /*
146  * Round constants
147  */
148 static const uint64_t K[80] =
149 {
150     UL64(0x428A2F98D728AE22),  UL64(0x7137449123EF65CD),
151     UL64(0xB5C0FBCFEC4D3B2F),  UL64(0xE9B5DBA58189DBBC),
152     UL64(0x3956C25BF348B538),  UL64(0x59F111F1B605D019),
153     UL64(0x923F82A4AF194F9B),  UL64(0xAB1C5ED5DA6D8118),
154     UL64(0xD807AA98A3030242),  UL64(0x12835B0145706FBE),
155     UL64(0x243185BE4EE4B28C),  UL64(0x550C7DC3D5FFB4E2),
156     UL64(0x72BE5D74F27B896F),  UL64(0x80DEB1FE3B1696B1),
157     UL64(0x9BDC06A725C71235),  UL64(0xC19BF174CF692694),
158     UL64(0xE49B69C19EF14AD2),  UL64(0xEFBE4786384F25E3),
159     UL64(0x0FC19DC68B8CD5B5),  UL64(0x240CA1CC77AC9C65),
160     UL64(0x2DE92C6F592B0275),  UL64(0x4A7484AA6EA6E483),
161     UL64(0x5CB0A9DCBD41FBD4),  UL64(0x76F988DA831153B5),
162     UL64(0x983E5152EE66DFAB),  UL64(0xA831C66D2DB43210),
163     UL64(0xB00327C898FB213F),  UL64(0xBF597FC7BEEF0EE4),
164     UL64(0xC6E00BF33DA88FC2),  UL64(0xD5A79147930AA725),
165     UL64(0x06CA6351E003826F),  UL64(0x142929670A0E6E70),
166     UL64(0x27B70A8546D22FFC),  UL64(0x2E1B21385C26C926),
167     UL64(0x4D2C6DFC5AC42AED),  UL64(0x53380D139D95B3DF),
168     UL64(0x650A73548BAF63DE),  UL64(0x766A0ABB3C77B2A8),
169     UL64(0x81C2C92E47EDAEE6),  UL64(0x92722C851482353B),
170     UL64(0xA2BFE8A14CF10364),  UL64(0xA81A664BBC423001),
171     UL64(0xC24B8B70D0F89791),  UL64(0xC76C51A30654BE30),
172     UL64(0xD192E819D6EF5218),  UL64(0xD69906245565A910),
173     UL64(0xF40E35855771202A),  UL64(0x106AA07032BBD1B8),
174     UL64(0x19A4C116B8D2D0C8),  UL64(0x1E376C085141AB53),
175     UL64(0x2748774CDF8EEB99),  UL64(0x34B0BCB5E19B48A8),
176     UL64(0x391C0CB3C5C95A63),  UL64(0x4ED8AA4AE3418ACB),
177     UL64(0x5B9CCA4F7763E373),  UL64(0x682E6FF3D6B2B8A3),
178     UL64(0x748F82EE5DEFB2FC),  UL64(0x78A5636F43172F60),
179     UL64(0x84C87814A1F0AB72),  UL64(0x8CC702081A6439EC),
180     UL64(0x90BEFFFA23631E28),  UL64(0xA4506CEBDE82BDE9),
181     UL64(0xBEF9A3F7B2C67915),  UL64(0xC67178F2E372532B),
182     UL64(0xCA273ECEEA26619C),  UL64(0xD186B8C721C0C207),
183     UL64(0xEADA7DD6CDE0EB1E),  UL64(0xF57D4F7FEE6ED178),
184     UL64(0x06F067AA72176FBA),  UL64(0x0A637DC5A2C898A6),
185     UL64(0x113F9804BEF90DAE),  UL64(0x1B710B35131C471B),
186     UL64(0x28DB77F523047D84),  UL64(0x32CAAB7B40C72493),
187     UL64(0x3C9EBE0A15C9BEBC),  UL64(0x431D67C49C100D4C),
188     UL64(0x4CC5D4BECB3E42B6),  UL64(0x597F299CFC657E2A),
189     UL64(0x5FCB6FAB3AD6FAEC),  UL64(0x6C44198C4A475817)
190 };
191 
mbedtls_internal_sha512_process(mbedtls_sha512_context * ctx,const unsigned char data[128])192 int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
193                                      const unsigned char data[128] )
194 {
195     int i;
196     struct
197     {
198         uint64_t temp1, temp2, W[80];
199         uint64_t A[8];
200     } local;
201 
202     SHA512_VALIDATE_RET( ctx != NULL );
203     SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
204 
205 #define  SHR(x,n) ((x) >> (n))
206 #define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
207 
208 #define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^  SHR(x, 7))
209 #define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^  SHR(x, 6))
210 
211 #define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
212 #define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
213 
214 #define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
215 #define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
216 
217 #define P(a,b,c,d,e,f,g,h,x,K)                                      \
218     do                                                              \
219     {                                                               \
220         local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x);    \
221         local.temp2 = S2(a) + F0((a),(b),(c));                      \
222         (d) += local.temp1; (h) = local.temp1 + local.temp2;        \
223     } while( 0 )
224 
225     for( i = 0; i < 8; i++ )
226         local.A[i] = ctx->state[i];
227 
228 #if defined(MBEDTLS_SHA512_SMALLER)
229     for( i = 0; i < 80; i++ )
230     {
231         if( i < 16 )
232         {
233             local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
234         }
235         else
236         {
237             local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +
238                    S0(local.W[i - 15]) + local.W[i - 16];
239         }
240 
241         P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
242            local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
243 
244         local.temp1 = local.A[7]; local.A[7] = local.A[6];
245         local.A[6] = local.A[5]; local.A[5] = local.A[4];
246         local.A[4] = local.A[3]; local.A[3] = local.A[2];
247         local.A[2] = local.A[1]; local.A[1] = local.A[0];
248         local.A[0] = local.temp1;
249     }
250 #else /* MBEDTLS_SHA512_SMALLER */
251     for( i = 0; i < 16; i++ )
252     {
253         local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
254     }
255 
256     for( ; i < 80; i++ )
257     {
258         local.W[i] = S1(local.W[i -  2]) + local.W[i -  7] +
259                S0(local.W[i - 15]) + local.W[i - 16];
260     }
261 
262     i = 0;
263     do
264     {
265         P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
266            local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
267         P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
268            local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
269         P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
270            local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
271         P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
272            local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
273         P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
274            local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
275         P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
276            local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
277         P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
278            local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
279         P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
280            local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
281     }
282     while( i < 80 );
283 #endif /* MBEDTLS_SHA512_SMALLER */
284 
285     for( i = 0; i < 8; i++ )
286         ctx->state[i] += local.A[i];
287 
288     /* Zeroise buffers and variables to clear sensitive data from memory. */
289     mbedtls_platform_zeroize( &local, sizeof( local ) );
290 
291     return( 0 );
292 }
293 
294 #endif /* !MBEDTLS_SHA512_PROCESS_ALT */
295 
296 /*
297  * SHA-512 process buffer
298  */
mbedtls_sha512_update(mbedtls_sha512_context * ctx,const unsigned char * input,size_t ilen)299 int mbedtls_sha512_update( mbedtls_sha512_context *ctx,
300                                const unsigned char *input,
301                                size_t ilen )
302 {
303     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
304     size_t fill;
305     unsigned int left;
306 
307     SHA512_VALIDATE_RET( ctx != NULL );
308     SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
309 
310     if( ilen == 0 )
311         return( 0 );
312 
313     left = (unsigned int) (ctx->total[0] & 0x7F);
314     fill = 128 - left;
315 
316     ctx->total[0] += (uint64_t) ilen;
317 
318     if( ctx->total[0] < (uint64_t) ilen )
319         ctx->total[1]++;
320 
321     if( left && ilen >= fill )
322     {
323         memcpy( (void *) (ctx->buffer + left), input, fill );
324 
325         if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
326             return( ret );
327 
328         input += fill;
329         ilen  -= fill;
330         left = 0;
331     }
332 
333     while( ilen >= 128 )
334     {
335         if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 )
336             return( ret );
337 
338         input += 128;
339         ilen  -= 128;
340     }
341 
342     if( ilen > 0 )
343         memcpy( (void *) (ctx->buffer + left), input, ilen );
344 
345     return( 0 );
346 }
347 
348 /*
349  * SHA-512 final digest
350  */
mbedtls_sha512_finish(mbedtls_sha512_context * ctx,unsigned char * output)351 int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
352                                unsigned char *output )
353 {
354     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
355     unsigned used;
356     uint64_t high, low;
357 
358     SHA512_VALIDATE_RET( ctx != NULL );
359     SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
360 
361     /*
362      * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
363      */
364     used = ctx->total[0] & 0x7F;
365 
366     ctx->buffer[used++] = 0x80;
367 
368     if( used <= 112 )
369     {
370         /* Enough room for padding + length in current block */
371         memset( ctx->buffer + used, 0, 112 - used );
372     }
373     else
374     {
375         /* We'll need an extra block */
376         memset( ctx->buffer + used, 0, 128 - used );
377 
378         if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
379             return( ret );
380 
381         memset( ctx->buffer, 0, 112 );
382     }
383 
384     /*
385      * Add message length
386      */
387     high = ( ctx->total[0] >> 61 )
388          | ( ctx->total[1] <<  3 );
389     low  = ( ctx->total[0] <<  3 );
390 
391     sha512_put_uint64_be( high, ctx->buffer, 112 );
392     sha512_put_uint64_be( low,  ctx->buffer, 120 );
393 
394     if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
395         return( ret );
396 
397     /*
398      * Output final state
399      */
400     sha512_put_uint64_be( ctx->state[0], output,  0 );
401     sha512_put_uint64_be( ctx->state[1], output,  8 );
402     sha512_put_uint64_be( ctx->state[2], output, 16 );
403     sha512_put_uint64_be( ctx->state[3], output, 24 );
404     sha512_put_uint64_be( ctx->state[4], output, 32 );
405     sha512_put_uint64_be( ctx->state[5], output, 40 );
406 
407 #if defined(MBEDTLS_SHA384_C)
408     if( ctx->is384 == 0 )
409 #endif
410     {
411         sha512_put_uint64_be( ctx->state[6], output, 48 );
412         sha512_put_uint64_be( ctx->state[7], output, 56 );
413     }
414 
415     return( 0 );
416 }
417 
418 #endif /* !MBEDTLS_SHA512_ALT */
419 
420 /*
421  * output = SHA-512( input buffer )
422  */
mbedtls_sha512(const unsigned char * input,size_t ilen,unsigned char * output,int is384)423 int mbedtls_sha512( const unsigned char *input,
424                     size_t ilen,
425                     unsigned char *output,
426                     int is384 )
427 {
428     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
429     mbedtls_sha512_context ctx;
430 
431 #if defined(MBEDTLS_SHA384_C)
432     SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
433 #else
434     SHA512_VALIDATE_RET( is384 == 0 );
435 #endif
436     SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
437     SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
438 
439     mbedtls_sha512_init( &ctx );
440 
441     if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
442         goto exit;
443 
444     if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 )
445         goto exit;
446 
447     if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 )
448         goto exit;
449 
450 exit:
451     mbedtls_sha512_free( &ctx );
452 
453     return( ret );
454 }
455 
456 #if defined(MBEDTLS_SELF_TEST)
457 
458 /*
459  * FIPS-180-2 test vectors
460  */
461 static const unsigned char sha512_test_buf[3][113] =
462 {
463     { "abc" },
464     { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
465     { "" }
466 };
467 
468 static const size_t sha512_test_buflen[3] =
469 {
470     3, 112, 1000
471 };
472 
473 static const unsigned char sha512_test_sum[][64] =
474 {
475 #if defined(MBEDTLS_SHA384_C)
476     /*
477      * SHA-384 test vectors
478      */
479     { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
480       0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
481       0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
482       0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
483       0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
484       0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
485     { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
486       0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
487       0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
488       0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
489       0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
490       0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
491     { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
492       0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
493       0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
494       0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
495       0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
496       0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
497 #endif /* MBEDTLS_SHA384_C */
498 
499     /*
500      * SHA-512 test vectors
501      */
502     { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
503       0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
504       0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
505       0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
506       0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
507       0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
508       0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
509       0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
510     { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
511       0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
512       0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
513       0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
514       0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
515       0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
516       0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
517       0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
518     { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
519       0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
520       0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
521       0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
522       0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
523       0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
524       0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
525       0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
526 };
527 
528 #define ARRAY_LENGTH( a )   ( sizeof( a ) / sizeof( ( a )[0] ) )
529 
530 /*
531  * Checkup routine
532  */
mbedtls_sha512_self_test(int verbose)533 int mbedtls_sha512_self_test( int verbose )
534 {
535     int i, j, k, buflen, ret = 0;
536     unsigned char *buf;
537     unsigned char sha512sum[64];
538     mbedtls_sha512_context ctx;
539 
540     buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
541     if( NULL == buf )
542     {
543         if( verbose != 0 )
544             mbedtls_printf( "Buffer allocation failed\n" );
545 
546         return( 1 );
547     }
548 
549     mbedtls_sha512_init( &ctx );
550 
551     for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
552     {
553         j = i % 3;
554 #if defined(MBEDTLS_SHA384_C)
555         k = i < 3;
556 #else
557         k = 0;
558 #endif
559 
560         if( verbose != 0 )
561             mbedtls_printf( "  SHA-%d test #%d: ", 512 - k * 128, j + 1 );
562 
563         if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
564             goto fail;
565 
566         if( j == 2 )
567         {
568             memset( buf, 'a', buflen = 1000 );
569 
570             for( j = 0; j < 1000; j++ )
571             {
572                 ret = mbedtls_sha512_update( &ctx, buf, buflen );
573                 if( ret != 0 )
574                     goto fail;
575             }
576         }
577         else
578         {
579             ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
580                                              sha512_test_buflen[j] );
581             if( ret != 0 )
582                 goto fail;
583         }
584 
585         if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
586             goto fail;
587 
588         if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
589         {
590             ret = 1;
591             goto fail;
592         }
593 
594         if( verbose != 0 )
595             mbedtls_printf( "passed\n" );
596     }
597 
598     if( verbose != 0 )
599         mbedtls_printf( "\n" );
600 
601     goto exit;
602 
603 fail:
604     if( verbose != 0 )
605         mbedtls_printf( "failed\n" );
606 
607 exit:
608     mbedtls_sha512_free( &ctx );
609     mbedtls_free( buf );
610 
611     return( ret );
612 }
613 
614 #undef ARRAY_LENGTH
615 
616 #endif /* MBEDTLS_SELF_TEST */
617 
618 #endif /* MBEDTLS_SHA512_C */
619