blob: 92ada8c35ffdcd1a34519cdc9c285ab6960de4eb [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * FIPS-180-2 compliant SHA-384/512 implementation
3 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02004 * Copyright The Mbed TLS Contributors
Manuel Pégourié-Gonnard37ff1402015-09-04 14:21:07 +02005 * 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.
Paul Bakker5121ce52009-01-03 21:22:43 +000018 */
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
Gilles Peskinedb09ef62020-06-03 01:43:33 +020025#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000026
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020027#if defined(MBEDTLS_SHA512_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000028
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000029#include "mbedtls/sha512.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050030#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000031#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000032
Manuel Pégourié-Gonnard1dd16742015-03-05 16:13:04 +000033#if defined(_MSC_VER) || defined(__WATCOMC__)
34 #define UL64(x) x##ui64
35#else
36 #define UL64(x) x##ULL
37#endif
38
Rich Evans00ab4702015-02-06 13:43:58 +000039#include <string.h>
40
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000041#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010042
Tom Cosgrove87fbfb52022-03-15 10:51:52 +000043#if defined(__aarch64__)
44# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
45 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
46# include <arm_neon.h>
47# endif
48# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
49# if defined(__unix__)
50# if defined(__linux__)
51 /* Our preferred method of detection is getauxval() */
52# include <sys/auxv.h>
53# endif
54 /* Use SIGILL on Unix, and fall back to it on Linux */
55# include <signal.h>
56# endif
57# endif
58#elif defined(_M_ARM64)
59# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
60 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
61# include <arm64_neon.h>
62# endif
63#else
64# undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
65# undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
66#endif
67
68#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
69/*
70 * Capability detection code comes early, so we can disable
71 * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
72 */
73#if defined(HWCAP_SHA512)
74static int mbedtls_a64_crypto_sha512_determine_support( void )
75{
76 return( ( getauxval( AT_HWCAP ) & HWCAP_SHA512 ) ? 1 : 0 );
77}
78#elif defined(__APPLE__)
79#include <sys/types.h>
80#include <sys/sysctl.h>
81
82static int mbedtls_a64_crypto_sha512_determine_support( void )
83{
84 int value = 0;
85 size_t value_len = sizeof(value);
86
87 int ret = sysctlbyname( "hw.optional.armv8_2_sha512", &value, &value_len,
88 NULL, 0 );
89 return( ret == 0 && value != 0 );
90}
91#elif defined(_M_ARM64)
92/*
93 * As of March 2022, there don't appear to be any PF_ARM_V8_* flags
94 * available to pass to IsProcessorFeaturePresent() to check for
95 * SHA-512 support. So we fall back to the C code only.
96 */
97#if defined(_MSC_VER)
98#pragma message "No mechanism to detect A64_CRYPTO found, using C code only"
99#else
100#warning "No mechanism to detect A64_CRYPTO found, using C code only"
101#endif
102#elif defined(__unix__) && defined(SIG_SETMASK)
103/* Detection with SIGILL, setjmp() and longjmp() */
104#include <signal.h>
105#include <setjmp.h>
106
107#ifndef asm
108#define asm __asm__
109#endif
110
111static jmp_buf return_from_sigill;
112
113/*
114 * A64 SHA512 support detection via SIGILL
115 */
116static void sigill_handler( int signal )
117{
118 (void) signal;
119 longjmp( return_from_sigill, 1 );
120}
121
122static int mbedtls_a64_crypto_sha512_determine_support( void )
123{
124 struct sigaction old_action, new_action;
125
126 sigset_t old_mask;
127 if( sigprocmask( 0, NULL, &old_mask ) )
128 return( 0 );
129
130 sigemptyset( &new_action.sa_mask );
131 new_action.sa_flags = 0;
132 new_action.sa_handler = sigill_handler;
133
134 sigaction( SIGILL, &new_action, &old_action );
135
136 static int ret = 0;
137
138 if( setjmp( return_from_sigill ) == 0 ) /* First return only */
139 {
140 /* If this traps, we will return a second time from setjmp() with 1 */
141 asm( "sha512h q0, q0, v0.2d" : : : "v0" );
142 ret = 1;
143 }
144
145 sigaction( SIGILL, &old_action, NULL );
146 sigprocmask( SIG_SETMASK, &old_mask, NULL );
147
148 return( ret );
149}
150#else
151#warning "No mechanism to detect A64_CRYPTO found, using C code only"
152#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
153#endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */
154
155#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
156
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +0200157#if !defined(MBEDTLS_SHA512_ALT)
158
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000159#define SHA512_BLOCK_SIZE 128
160
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200161#if defined(MBEDTLS_SHA512_SMALLER)
162static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
163{
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100164 MBEDTLS_PUT_UINT64_BE(n, b, i);
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200165}
166#else
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100167#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200168#endif /* MBEDTLS_SHA512_SMALLER */
169
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200170void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200171{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200172 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200173}
174
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200175void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200176{
177 if( ctx == NULL )
178 return;
179
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500180 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200181}
182
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200183void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
184 const mbedtls_sha512_context *src )
185{
186 *dst = *src;
187}
188
Paul Bakker5121ce52009-01-03 21:22:43 +0000189/*
190 * SHA-512 context setup
191 */
TRodziewicz26371e42021-06-08 16:45:41 +0200192int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000193{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200194#if defined(MBEDTLS_SHA384_C)
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100195 if( is384 != 0 && is384 != 1 )
196 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100197#else
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100198 if( is384 != 0 )
199 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100200#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000201
Paul Bakker5121ce52009-01-03 21:22:43 +0000202 ctx->total[0] = 0;
203 ctx->total[1] = 0;
204
205 if( is384 == 0 )
206 {
207 /* SHA-512 */
208 ctx->state[0] = UL64(0x6A09E667F3BCC908);
209 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
210 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
211 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
212 ctx->state[4] = UL64(0x510E527FADE682D1);
213 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
214 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
215 ctx->state[7] = UL64(0x5BE0CD19137E2179);
216 }
217 else
218 {
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200219#if !defined(MBEDTLS_SHA384_C)
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200220 return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
221#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000222 /* SHA-384 */
223 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
224 ctx->state[1] = UL64(0x629A292A367CD507);
225 ctx->state[2] = UL64(0x9159015A3070DD17);
226 ctx->state[3] = UL64(0x152FECD8F70E5939);
227 ctx->state[4] = UL64(0x67332667FFC00B31);
228 ctx->state[5] = UL64(0x8EB44A8768581511);
229 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
230 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200231#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 }
233
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200234#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000235 ctx->is384 = is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200236#endif
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100237
238 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000239}
240
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200241#if !defined(MBEDTLS_SHA512_PROCESS_ALT)
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200242
243/*
244 * Round constants
245 */
246static const uint64_t K[80] =
247{
248 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
249 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
250 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
251 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
252 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
253 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
254 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
255 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
256 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
257 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
258 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
259 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
260 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
261 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
262 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
263 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
264 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
265 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
266 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
267 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
268 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
269 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
270 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
271 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
272 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
273 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
274 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
275 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
276 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
277 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
278 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
279 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
280 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
281 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
282 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
283 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
284 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
285 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
286 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
287 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
288};
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000289#endif
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200290
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000291#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
292 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
293
294#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
295# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many
296# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process
297#endif
298
299#ifndef asm
300#define asm __asm__
301#endif
302
303/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
304 * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
305 */
306
307#if defined(__clang__) && \
308 (__clang_major__ < 13 || \
309 (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))
310static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)
311{
312 asm( "sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y) );
313 return( x );
314}
315static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
316{
317 asm( "sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
318 return( x );
319}
320static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
321{
322 asm( "sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
323 return( x );
324}
325static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
326{
327 asm( "sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
328 return( x );
329}
330#endif /* __clang__ etc */
331
332static size_t mbedtls_internal_sha512_process_many_a64_crypto(
333 mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len )
334{
335 uint64x2_t ab = vld1q_u64( &ctx->state[0] );
336 uint64x2_t cd = vld1q_u64( &ctx->state[2] );
337 uint64x2_t ef = vld1q_u64( &ctx->state[4] );
338 uint64x2_t gh = vld1q_u64( &ctx->state[6] );
339
340 size_t processed = 0;
341
342 for ( ;
343 len >= SHA512_BLOCK_SIZE;
344 processed += SHA512_BLOCK_SIZE,
345 msg += SHA512_BLOCK_SIZE,
346 len -= SHA512_BLOCK_SIZE )
347 {
348 uint64x2_t initial_sum, sum, intermed;
349
350 uint64x2_t ab_orig = ab;
351 uint64x2_t cd_orig = cd;
352 uint64x2_t ef_orig = ef;
353 uint64x2_t gh_orig = gh;
354
355 uint64x2_t s0 = (uint64x2_t) vld1q_u8( msg + 16 * 0 );
356 uint64x2_t s1 = (uint64x2_t) vld1q_u8( msg + 16 * 1 );
357 uint64x2_t s2 = (uint64x2_t) vld1q_u8( msg + 16 * 2 );
358 uint64x2_t s3 = (uint64x2_t) vld1q_u8( msg + 16 * 3 );
359 uint64x2_t s4 = (uint64x2_t) vld1q_u8( msg + 16 * 4 );
360 uint64x2_t s5 = (uint64x2_t) vld1q_u8( msg + 16 * 5 );
361 uint64x2_t s6 = (uint64x2_t) vld1q_u8( msg + 16 * 6 );
362 uint64x2_t s7 = (uint64x2_t) vld1q_u8( msg + 16 * 7 );
363
364#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */
365 s0 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s0 ) ) );
366 s1 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s1 ) ) );
367 s2 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s2 ) ) );
368 s3 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s3 ) ) );
369 s4 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s4 ) ) );
370 s5 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s5 ) ) );
371 s6 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s6 ) ) );
372 s7 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s7 ) ) );
373#endif
374
375 /* Rounds 0 and 1 */
376 initial_sum = vaddq_u64( s0, vld1q_u64( &K[0] ) );
377 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
378 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
379 gh = vsha512h2q_u64( intermed, cd, ab );
380 cd = vaddq_u64( cd, intermed );
381
382 /* Rounds 2 and 3 */
383 initial_sum = vaddq_u64( s1, vld1q_u64( &K[2] ) );
384 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
385 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
386 ef = vsha512h2q_u64( intermed, ab, gh );
387 ab = vaddq_u64( ab, intermed );
388
389 /* Rounds 4 and 5 */
390 initial_sum = vaddq_u64( s2, vld1q_u64( &K[4] ) );
391 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
392 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
393 cd = vsha512h2q_u64( intermed, gh, ef );
394 gh = vaddq_u64( gh, intermed );
395
396 /* Rounds 6 and 7 */
397 initial_sum = vaddq_u64( s3, vld1q_u64( &K[6] ) );
398 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
399 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
400 ab = vsha512h2q_u64( intermed, ef, cd );
401 ef = vaddq_u64( ef, intermed );
402
403 /* Rounds 8 and 9 */
404 initial_sum = vaddq_u64( s4, vld1q_u64( &K[8] ) );
405 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
406 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
407 gh = vsha512h2q_u64( intermed, cd, ab );
408 cd = vaddq_u64( cd, intermed );
409
410 /* Rounds 10 and 11 */
411 initial_sum = vaddq_u64( s5, vld1q_u64( &K[10] ) );
412 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
413 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
414 ef = vsha512h2q_u64( intermed, ab, gh );
415 ab = vaddq_u64( ab, intermed );
416
417 /* Rounds 12 and 13 */
418 initial_sum = vaddq_u64( s6, vld1q_u64( &K[12] ) );
419 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
420 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
421 cd = vsha512h2q_u64( intermed, gh, ef );
422 gh = vaddq_u64( gh, intermed );
423
424 /* Rounds 14 and 15 */
425 initial_sum = vaddq_u64( s7, vld1q_u64( &K[14] ) );
426 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
427 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
428 ab = vsha512h2q_u64( intermed, ef, cd );
429 ef = vaddq_u64( ef, intermed );
430
431 for ( unsigned int t = 16; t < 80; t += 16 )
432 {
433 /* Rounds t and t + 1 */
434 s0 = vsha512su1q_u64( vsha512su0q_u64( s0, s1 ), s7, vextq_u64( s4, s5, 1 ) );
435 initial_sum = vaddq_u64( s0, vld1q_u64( &K[t] ) );
436 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
437 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
438 gh = vsha512h2q_u64( intermed, cd, ab );
439 cd = vaddq_u64( cd, intermed );
440
441 /* Rounds t + 2 and t + 3 */
442 s1 = vsha512su1q_u64( vsha512su0q_u64( s1, s2 ), s0, vextq_u64( s5, s6, 1 ) );
443 initial_sum = vaddq_u64( s1, vld1q_u64( &K[t + 2] ) );
444 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
445 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
446 ef = vsha512h2q_u64( intermed, ab, gh );
447 ab = vaddq_u64( ab, intermed );
448
449 /* Rounds t + 4 and t + 5 */
450 s2 = vsha512su1q_u64( vsha512su0q_u64( s2, s3 ), s1, vextq_u64( s6, s7, 1 ) );
451 initial_sum = vaddq_u64( s2, vld1q_u64( &K[t + 4] ) );
452 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
453 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
454 cd = vsha512h2q_u64( intermed, gh, ef );
455 gh = vaddq_u64( gh, intermed );
456
457 /* Rounds t + 6 and t + 7 */
458 s3 = vsha512su1q_u64( vsha512su0q_u64( s3, s4 ), s2, vextq_u64( s7, s0, 1 ) );
459 initial_sum = vaddq_u64( s3, vld1q_u64( &K[t + 6] ) );
460 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
461 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
462 ab = vsha512h2q_u64( intermed, ef, cd );
463 ef = vaddq_u64( ef, intermed );
464
465 /* Rounds t + 8 and t + 9 */
466 s4 = vsha512su1q_u64( vsha512su0q_u64( s4, s5 ), s3, vextq_u64( s0, s1, 1 ) );
467 initial_sum = vaddq_u64( s4, vld1q_u64( &K[t + 8] ) );
468 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
469 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
470 gh = vsha512h2q_u64( intermed, cd, ab );
471 cd = vaddq_u64( cd, intermed );
472
473 /* Rounds t + 10 and t + 11 */
474 s5 = vsha512su1q_u64( vsha512su0q_u64( s5, s6 ), s4, vextq_u64( s1, s2, 1 ) );
475 initial_sum = vaddq_u64( s5, vld1q_u64( &K[t + 10] ) );
476 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
477 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
478 ef = vsha512h2q_u64( intermed, ab, gh );
479 ab = vaddq_u64( ab, intermed );
480
481 /* Rounds t + 12 and t + 13 */
482 s6 = vsha512su1q_u64( vsha512su0q_u64( s6, s7 ), s5, vextq_u64( s2, s3, 1 ) );
483 initial_sum = vaddq_u64( s6, vld1q_u64( &K[t + 12] ) );
484 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
485 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
486 cd = vsha512h2q_u64( intermed, gh, ef );
487 gh = vaddq_u64( gh, intermed );
488
489 /* Rounds t + 14 and t + 15 */
490 s7 = vsha512su1q_u64( vsha512su0q_u64( s7, s0 ), s6, vextq_u64( s3, s4, 1 ) );
491 initial_sum = vaddq_u64( s7, vld1q_u64( &K[t + 14] ) );
492 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
493 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
494 ab = vsha512h2q_u64( intermed, ef, cd );
495 ef = vaddq_u64( ef, intermed );
496 }
497
498 ab = vaddq_u64( ab, ab_orig );
499 cd = vaddq_u64( cd, cd_orig );
500 ef = vaddq_u64( ef, ef_orig );
501 gh = vaddq_u64( gh, gh_orig );
502 }
503
504 vst1q_u64( &ctx->state[0], ab );
505 vst1q_u64( &ctx->state[2], cd );
506 vst1q_u64( &ctx->state[4], ef );
507 vst1q_u64( &ctx->state[6], gh );
508
509 return( processed );
510}
511
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100512#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
513/*
514 * This function is for internal use only if we are building both C and A64
515 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
516 */
517static
518#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000519int mbedtls_internal_sha512_process_a64_crypto( mbedtls_sha512_context *ctx,
520 const unsigned char data[SHA512_BLOCK_SIZE] )
521{
522 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, data,
523 SHA512_BLOCK_SIZE ) == SHA512_BLOCK_SIZE ) ? 0 : -1;
524}
525
526#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
527
528
529#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
530#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
531#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process
532#endif
533
534
535#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
536
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100537#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
538/*
539 * This function is for internal use only if we are building both C and A64
540 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
541 */
542static
543#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000544int mbedtls_internal_sha512_process_c( mbedtls_sha512_context *ctx,
545 const unsigned char data[SHA512_BLOCK_SIZE] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000546{
547 int i;
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200548 struct
549 {
550 uint64_t temp1, temp2, W[80];
551 uint64_t A[8];
552 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000553
Hanno Becker1eeca412018-10-15 12:01:35 +0100554#define SHR(x,n) ((x) >> (n))
Hanno Becker26d02e12018-10-30 09:29:25 +0000555#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000556
557#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
558#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
559
560#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
561#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
562
Hanno Becker1eeca412018-10-15 12:01:35 +0100563#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
564#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200566#define P(a,b,c,d,e,f,g,h,x,K) \
567 do \
568 { \
569 local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \
570 local.temp2 = S2(a) + F0((a),(b),(c)); \
571 (d) += local.temp1; (h) = local.temp1 + local.temp2; \
Hanno Becker1eeca412018-10-15 12:01:35 +0100572 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000573
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200574 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200575 local.A[i] = ctx->state[i];
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200576
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200577#if defined(MBEDTLS_SHA512_SMALLER)
578 for( i = 0; i < 80; i++ )
579 {
580 if( i < 16 )
581 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100582 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200583 }
584 else
585 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200586 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
587 S0(local.W[i - 15]) + local.W[i - 16];
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200588 }
589
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200590 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
591 local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200592
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200593 local.temp1 = local.A[7]; local.A[7] = local.A[6];
594 local.A[6] = local.A[5]; local.A[5] = local.A[4];
595 local.A[4] = local.A[3]; local.A[3] = local.A[2];
596 local.A[2] = local.A[1]; local.A[1] = local.A[0];
597 local.A[0] = local.temp1;
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200598 }
599#else /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000600 for( i = 0; i < 16; i++ )
601 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100602 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000603 }
604
605 for( ; i < 80; i++ )
606 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200607 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
608 S0(local.W[i - 15]) + local.W[i - 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000609 }
610
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 i = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 do
613 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200614 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
615 local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
616 P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
617 local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
618 P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
619 local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
620 P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
621 local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
622 P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
623 local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
624 P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
625 local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
626 P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
627 local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
628 P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
629 local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000630 }
631 while( i < 80 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200632#endif /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000633
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200634 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200635 ctx->state[i] += local.A[i];
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100636
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200637 /* Zeroise buffers and variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200638 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100639
640 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000641}
Jaeden Amero041039f2018-02-19 15:28:08 +0000642
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000643#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
644
645
646#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
647
648static size_t mbedtls_internal_sha512_process_many_c(
649 mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)
650{
651 size_t processed = 0;
652
653 while( len >= SHA512_BLOCK_SIZE )
654 {
655 if( mbedtls_internal_sha512_process_c( ctx, data ) != 0)
656 return( 0 );
657
658 data += SHA512_BLOCK_SIZE;
659 len -= SHA512_BLOCK_SIZE;
660
661 processed += SHA512_BLOCK_SIZE;
662 }
663
664 return( processed );
665}
666
667#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
668
669
670#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
671
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100672static int mbedtls_a64_crypto_sha512_has_support( void )
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000673{
674 static int done = 0;
675 static int supported = 0;
676
677 if( !done )
678 {
679 supported = mbedtls_a64_crypto_sha512_determine_support();
680 done = 1;
681 }
682
683 return( supported );
684}
685
686static size_t mbedtls_internal_sha512_process_many( mbedtls_sha512_context *ctx,
687 const uint8_t *msg, size_t len )
688{
689 if( mbedtls_a64_crypto_sha512_has_support() )
690 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, msg, len ) );
691 else
692 return( mbedtls_internal_sha512_process_many_c( ctx, msg, len ) );
693}
694
695int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
696 const unsigned char data[SHA512_BLOCK_SIZE] )
697{
698 if( mbedtls_a64_crypto_sha512_has_support() )
699 return( mbedtls_internal_sha512_process_a64_crypto( ctx, data ) );
700 else
701 return( mbedtls_internal_sha512_process_c( ctx, data ) );
702}
703
704#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000705
706/*
707 * SHA-512 process buffer
708 */
TRodziewicz26371e42021-06-08 16:45:41 +0200709int mbedtls_sha512_update( mbedtls_sha512_context *ctx,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100710 const unsigned char *input,
711 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000712{
Janos Follath24eed8d2019-11-22 13:21:35 +0000713 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000714 size_t fill;
Paul Bakkerb8213a12011-07-11 08:16:18 +0000715 unsigned int left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
Brian White12895d12014-04-11 11:29:42 -0400717 if( ilen == 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100718 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000719
Paul Bakkerb8213a12011-07-11 08:16:18 +0000720 left = (unsigned int) (ctx->total[0] & 0x7F);
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000721 fill = SHA512_BLOCK_SIZE - left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000722
Paul Bakker5c2364c2012-10-01 14:41:15 +0000723 ctx->total[0] += (uint64_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000724
Paul Bakker5c2364c2012-10-01 14:41:15 +0000725 if( ctx->total[0] < (uint64_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000726 ctx->total[1]++;
727
728 if( left && ilen >= fill )
729 {
Paul Bakker3c2122f2013-06-24 19:03:14 +0200730 memcpy( (void *) (ctx->buffer + left), input, fill );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100731
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100732 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100733 return( ret );
734
Paul Bakker5121ce52009-01-03 21:22:43 +0000735 input += fill;
736 ilen -= fill;
737 left = 0;
738 }
739
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000740 while( ilen >= SHA512_BLOCK_SIZE )
Paul Bakker5121ce52009-01-03 21:22:43 +0000741 {
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000742 size_t processed =
743 mbedtls_internal_sha512_process_many( ctx, input, ilen );
744 if( processed < SHA512_BLOCK_SIZE )
745 return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100746
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000747 input += processed;
748 ilen -= processed;
Paul Bakker5121ce52009-01-03 21:22:43 +0000749 }
750
751 if( ilen > 0 )
Paul Bakker3c2122f2013-06-24 19:03:14 +0200752 memcpy( (void *) (ctx->buffer + left), input, ilen );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100753
754 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000755}
756
Paul Bakker5121ce52009-01-03 21:22:43 +0000757/*
758 * SHA-512 final digest
759 */
TRodziewicz26371e42021-06-08 16:45:41 +0200760int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200761 unsigned char *output )
Paul Bakker5121ce52009-01-03 21:22:43 +0000762{
Janos Follath24eed8d2019-11-22 13:21:35 +0000763 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200764 unsigned used;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000765 uint64_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000766
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200767 /*
768 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
769 */
770 used = ctx->total[0] & 0x7F;
771
772 ctx->buffer[used++] = 0x80;
773
774 if( used <= 112 )
775 {
776 /* Enough room for padding + length in current block */
777 memset( ctx->buffer + used, 0, 112 - used );
778 }
779 else
780 {
781 /* We'll need an extra block */
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000782 memset( ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used );
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200783
784 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
785 return( ret );
786
787 memset( ctx->buffer, 0, 112 );
788 }
789
790 /*
791 * Add message length
792 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000793 high = ( ctx->total[0] >> 61 )
794 | ( ctx->total[1] << 3 );
795 low = ( ctx->total[0] << 3 );
796
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200797 sha512_put_uint64_be( high, ctx->buffer, 112 );
798 sha512_put_uint64_be( low, ctx->buffer, 120 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000799
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200800 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
801 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000802
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200803 /*
804 * Output final state
805 */
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200806 sha512_put_uint64_be( ctx->state[0], output, 0 );
807 sha512_put_uint64_be( ctx->state[1], output, 8 );
808 sha512_put_uint64_be( ctx->state[2], output, 16 );
809 sha512_put_uint64_be( ctx->state[3], output, 24 );
810 sha512_put_uint64_be( ctx->state[4], output, 32 );
811 sha512_put_uint64_be( ctx->state[5], output, 40 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
David Horstmann2788f6b2022-10-06 18:45:09 +0100813 int truncated = 0;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200814#if defined(MBEDTLS_SHA384_C)
David Horstmann2788f6b2022-10-06 18:45:09 +0100815 truncated = ctx->is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200816#endif
David Horstmann2788f6b2022-10-06 18:45:09 +0100817 if( !truncated )
Paul Bakker5121ce52009-01-03 21:22:43 +0000818 {
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200819 sha512_put_uint64_be( ctx->state[6], output, 48 );
820 sha512_put_uint64_be( ctx->state[7], output, 56 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 }
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100822
823 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824}
825
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200826#endif /* !MBEDTLS_SHA512_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200827
Paul Bakker5121ce52009-01-03 21:22:43 +0000828/*
829 * output = SHA-512( input buffer )
830 */
TRodziewicz26371e42021-06-08 16:45:41 +0200831int mbedtls_sha512( const unsigned char *input,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100832 size_t ilen,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200833 unsigned char *output,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100834 int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000835{
Janos Follath24eed8d2019-11-22 13:21:35 +0000836 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200837 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000838
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200839#if defined(MBEDTLS_SHA384_C)
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100840 if( is384 != 0 && is384 != 1 )
841 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100842#else
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100843 if( is384 != 0 )
844 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100845#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000846
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 mbedtls_sha512_init( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100848
TRodziewicz26371e42021-06-08 16:45:41 +0200849 if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100850 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100851
TRodziewicz26371e42021-06-08 16:45:41 +0200852 if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100853 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100854
TRodziewicz26371e42021-06-08 16:45:41 +0200855 if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100856 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100857
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100858exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200859 mbedtls_sha512_free( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100860
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100861 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000862}
863
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200864#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000865
866/*
867 * FIPS-180-2 test vectors
868 */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000869static const unsigned char sha512_test_buf[3][113] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000870{
871 { "abc" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200872 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000873 { "" }
874};
875
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100876static const size_t sha512_test_buflen[3] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000877{
878 3, 112, 1000
879};
880
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200881static const unsigned char sha512_test_sum[][64] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000882{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200883#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000884 /*
885 * SHA-384 test vectors
886 */
887 { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
888 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
889 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
890 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
891 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
892 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
893 { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
894 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
895 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
896 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
897 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
898 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
899 { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
900 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
901 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
902 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
903 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
904 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200905#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000906
907 /*
908 * SHA-512 test vectors
909 */
910 { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
911 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
912 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
913 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
914 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
915 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
916 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
917 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
918 { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
919 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
920 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
921 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
922 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
923 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
924 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
925 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
926 { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
927 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
928 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
929 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
930 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
931 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
932 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
933 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
934};
935
Manuel Pégourié-Gonnard74ca84a2020-01-29 09:46:49 +0100936#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200937
Paul Bakker5121ce52009-01-03 21:22:43 +0000938/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000939 * Checkup routine
940 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200941int mbedtls_sha512_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000942{
Paul Bakker5b4af392014-06-26 12:09:34 +0200943 int i, j, k, buflen, ret = 0;
Russ Butlerbb83b422016-10-12 17:36:50 -0500944 unsigned char *buf;
Paul Bakker9e36f042013-06-30 14:34:05 +0200945 unsigned char sha512sum[64];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200946 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000947
Russ Butlerbb83b422016-10-12 17:36:50 -0500948 buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
949 if( NULL == buf )
950 {
951 if( verbose != 0 )
952 mbedtls_printf( "Buffer allocation failed\n" );
953
954 return( 1 );
955 }
956
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200957 mbedtls_sha512_init( &ctx );
Paul Bakker5b4af392014-06-26 12:09:34 +0200958
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +0100959 for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000960 {
961 j = i % 3;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200962#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000963 k = i < 3;
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200964#else
965 k = 0;
966#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000967
968 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200969 mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000970
TRodziewicz26371e42021-06-08 16:45:41 +0200971 if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100972 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000973
974 if( j == 2 )
975 {
976 memset( buf, 'a', buflen = 1000 );
977
978 for( j = 0; j < 1000; j++ )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100979 {
TRodziewicz26371e42021-06-08 16:45:41 +0200980 ret = mbedtls_sha512_update( &ctx, buf, buflen );
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100981 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100982 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100983 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000984 }
985 else
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100986 {
TRodziewicz26371e42021-06-08 16:45:41 +0200987 ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100988 sha512_test_buflen[j] );
989 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100990 goto fail;
991 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000992
TRodziewicz26371e42021-06-08 16:45:41 +0200993 if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100994 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000995
Paul Bakker9e36f042013-06-30 14:34:05 +0200996 if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100997 {
998 ret = 1;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100999 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001000 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001001
1002 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001003 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001004 }
1005
1006 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001007 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001008
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001009 goto exit;
1010
1011fail:
1012 if( verbose != 0 )
1013 mbedtls_printf( "failed\n" );
1014
Paul Bakker5b4af392014-06-26 12:09:34 +02001015exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001016 mbedtls_sha512_free( &ctx );
Russ Butlerbb83b422016-10-12 17:36:50 -05001017 mbedtls_free( buf );
Paul Bakker5b4af392014-06-26 12:09:34 +02001018
1019 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001020}
1021
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +01001022#undef ARRAY_LENGTH
Manuel Pégourié-Gonnard2d885492020-01-07 10:17:35 +01001023
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00001025
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026#endif /* MBEDTLS_SHA512_C */