blob: ae2c2262c71d2f8355a2491129aaaa9227e8c510 [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
Hanno Beckerc7560492018-12-20 10:23:39 +0000157#define SHA512_VALIDATE_RET(cond) \
158 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
159#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
160
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +0200161#if !defined(MBEDTLS_SHA512_ALT)
162
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000163#define SHA512_BLOCK_SIZE 128
164
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200165#if defined(MBEDTLS_SHA512_SMALLER)
166static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
167{
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100168 MBEDTLS_PUT_UINT64_BE(n, b, i);
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200169}
170#else
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100171#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200172#endif /* MBEDTLS_SHA512_SMALLER */
173
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200174void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200175{
Hanno Becker38e15d42018-12-18 17:54:00 +0000176 SHA512_VALIDATE( ctx != NULL );
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000177
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200178 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200179}
180
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200181void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200182{
183 if( ctx == NULL )
184 return;
185
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500186 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200187}
188
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200189void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
190 const mbedtls_sha512_context *src )
191{
Hanno Becker38e15d42018-12-18 17:54:00 +0000192 SHA512_VALIDATE( dst != NULL );
193 SHA512_VALIDATE( src != NULL );
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000194
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200195 *dst = *src;
196}
197
Paul Bakker5121ce52009-01-03 21:22:43 +0000198/*
199 * SHA-512 context setup
200 */
TRodziewicz26371e42021-06-08 16:45:41 +0200201int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000202{
Hanno Becker38e15d42018-12-18 17:54:00 +0000203 SHA512_VALIDATE_RET( ctx != NULL );
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200204#if defined(MBEDTLS_SHA384_C)
Hanno Becker38e15d42018-12-18 17:54:00 +0000205 SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100206#else
207 SHA512_VALIDATE_RET( is384 == 0 );
208#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000209
Paul Bakker5121ce52009-01-03 21:22:43 +0000210 ctx->total[0] = 0;
211 ctx->total[1] = 0;
212
213 if( is384 == 0 )
214 {
215 /* SHA-512 */
216 ctx->state[0] = UL64(0x6A09E667F3BCC908);
217 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
218 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
219 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
220 ctx->state[4] = UL64(0x510E527FADE682D1);
221 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
222 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
223 ctx->state[7] = UL64(0x5BE0CD19137E2179);
224 }
225 else
226 {
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200227#if !defined(MBEDTLS_SHA384_C)
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200228 return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
229#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000230 /* SHA-384 */
231 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
232 ctx->state[1] = UL64(0x629A292A367CD507);
233 ctx->state[2] = UL64(0x9159015A3070DD17);
234 ctx->state[3] = UL64(0x152FECD8F70E5939);
235 ctx->state[4] = UL64(0x67332667FFC00B31);
236 ctx->state[5] = UL64(0x8EB44A8768581511);
237 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
238 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200239#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000240 }
241
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200242#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000243 ctx->is384 = is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200244#endif
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100245
246 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000247}
248
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200249#if !defined(MBEDTLS_SHA512_PROCESS_ALT)
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200250
251/*
252 * Round constants
253 */
254static const uint64_t K[80] =
255{
256 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
257 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
258 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
259 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
260 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
261 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
262 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
263 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
264 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
265 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
266 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
267 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
268 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
269 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
270 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
271 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
272 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
273 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
274 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
275 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
276 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
277 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
278 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
279 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
280 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
281 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
282 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
283 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
284 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
285 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
286 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
287 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
288 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
289 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
290 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
291 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
292 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
293 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
294 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
295 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
296};
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000297#endif
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200298
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000299#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
300 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
301
302#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
303# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many
304# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process
305#endif
306
307#ifndef asm
308#define asm __asm__
309#endif
310
311/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
312 * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
313 */
314
315#if defined(__clang__) && \
316 (__clang_major__ < 13 || \
317 (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))
318static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)
319{
320 asm( "sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y) );
321 return( x );
322}
323static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
324{
325 asm( "sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
326 return( x );
327}
328static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
329{
330 asm( "sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
331 return( x );
332}
333static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
334{
335 asm( "sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
336 return( x );
337}
338#endif /* __clang__ etc */
339
340static size_t mbedtls_internal_sha512_process_many_a64_crypto(
341 mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len )
342{
343 uint64x2_t ab = vld1q_u64( &ctx->state[0] );
344 uint64x2_t cd = vld1q_u64( &ctx->state[2] );
345 uint64x2_t ef = vld1q_u64( &ctx->state[4] );
346 uint64x2_t gh = vld1q_u64( &ctx->state[6] );
347
348 size_t processed = 0;
349
350 for ( ;
351 len >= SHA512_BLOCK_SIZE;
352 processed += SHA512_BLOCK_SIZE,
353 msg += SHA512_BLOCK_SIZE,
354 len -= SHA512_BLOCK_SIZE )
355 {
356 uint64x2_t initial_sum, sum, intermed;
357
358 uint64x2_t ab_orig = ab;
359 uint64x2_t cd_orig = cd;
360 uint64x2_t ef_orig = ef;
361 uint64x2_t gh_orig = gh;
362
363 uint64x2_t s0 = (uint64x2_t) vld1q_u8( msg + 16 * 0 );
364 uint64x2_t s1 = (uint64x2_t) vld1q_u8( msg + 16 * 1 );
365 uint64x2_t s2 = (uint64x2_t) vld1q_u8( msg + 16 * 2 );
366 uint64x2_t s3 = (uint64x2_t) vld1q_u8( msg + 16 * 3 );
367 uint64x2_t s4 = (uint64x2_t) vld1q_u8( msg + 16 * 4 );
368 uint64x2_t s5 = (uint64x2_t) vld1q_u8( msg + 16 * 5 );
369 uint64x2_t s6 = (uint64x2_t) vld1q_u8( msg + 16 * 6 );
370 uint64x2_t s7 = (uint64x2_t) vld1q_u8( msg + 16 * 7 );
371
372#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */
373 s0 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s0 ) ) );
374 s1 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s1 ) ) );
375 s2 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s2 ) ) );
376 s3 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s3 ) ) );
377 s4 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s4 ) ) );
378 s5 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s5 ) ) );
379 s6 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s6 ) ) );
380 s7 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s7 ) ) );
381#endif
382
383 /* Rounds 0 and 1 */
384 initial_sum = vaddq_u64( s0, vld1q_u64( &K[0] ) );
385 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
386 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
387 gh = vsha512h2q_u64( intermed, cd, ab );
388 cd = vaddq_u64( cd, intermed );
389
390 /* Rounds 2 and 3 */
391 initial_sum = vaddq_u64( s1, vld1q_u64( &K[2] ) );
392 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
393 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
394 ef = vsha512h2q_u64( intermed, ab, gh );
395 ab = vaddq_u64( ab, intermed );
396
397 /* Rounds 4 and 5 */
398 initial_sum = vaddq_u64( s2, vld1q_u64( &K[4] ) );
399 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
400 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
401 cd = vsha512h2q_u64( intermed, gh, ef );
402 gh = vaddq_u64( gh, intermed );
403
404 /* Rounds 6 and 7 */
405 initial_sum = vaddq_u64( s3, vld1q_u64( &K[6] ) );
406 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
407 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
408 ab = vsha512h2q_u64( intermed, ef, cd );
409 ef = vaddq_u64( ef, intermed );
410
411 /* Rounds 8 and 9 */
412 initial_sum = vaddq_u64( s4, vld1q_u64( &K[8] ) );
413 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
414 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
415 gh = vsha512h2q_u64( intermed, cd, ab );
416 cd = vaddq_u64( cd, intermed );
417
418 /* Rounds 10 and 11 */
419 initial_sum = vaddq_u64( s5, vld1q_u64( &K[10] ) );
420 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
421 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
422 ef = vsha512h2q_u64( intermed, ab, gh );
423 ab = vaddq_u64( ab, intermed );
424
425 /* Rounds 12 and 13 */
426 initial_sum = vaddq_u64( s6, vld1q_u64( &K[12] ) );
427 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
428 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
429 cd = vsha512h2q_u64( intermed, gh, ef );
430 gh = vaddq_u64( gh, intermed );
431
432 /* Rounds 14 and 15 */
433 initial_sum = vaddq_u64( s7, vld1q_u64( &K[14] ) );
434 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
435 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
436 ab = vsha512h2q_u64( intermed, ef, cd );
437 ef = vaddq_u64( ef, intermed );
438
439 for ( unsigned int t = 16; t < 80; t += 16 )
440 {
441 /* Rounds t and t + 1 */
442 s0 = vsha512su1q_u64( vsha512su0q_u64( s0, s1 ), s7, vextq_u64( s4, s5, 1 ) );
443 initial_sum = vaddq_u64( s0, vld1q_u64( &K[t] ) );
444 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
445 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
446 gh = vsha512h2q_u64( intermed, cd, ab );
447 cd = vaddq_u64( cd, intermed );
448
449 /* Rounds t + 2 and t + 3 */
450 s1 = vsha512su1q_u64( vsha512su0q_u64( s1, s2 ), s0, vextq_u64( s5, s6, 1 ) );
451 initial_sum = vaddq_u64( s1, vld1q_u64( &K[t + 2] ) );
452 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
453 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
454 ef = vsha512h2q_u64( intermed, ab, gh );
455 ab = vaddq_u64( ab, intermed );
456
457 /* Rounds t + 4 and t + 5 */
458 s2 = vsha512su1q_u64( vsha512su0q_u64( s2, s3 ), s1, vextq_u64( s6, s7, 1 ) );
459 initial_sum = vaddq_u64( s2, vld1q_u64( &K[t + 4] ) );
460 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
461 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
462 cd = vsha512h2q_u64( intermed, gh, ef );
463 gh = vaddq_u64( gh, intermed );
464
465 /* Rounds t + 6 and t + 7 */
466 s3 = vsha512su1q_u64( vsha512su0q_u64( s3, s4 ), s2, vextq_u64( s7, s0, 1 ) );
467 initial_sum = vaddq_u64( s3, vld1q_u64( &K[t + 6] ) );
468 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
469 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
470 ab = vsha512h2q_u64( intermed, ef, cd );
471 ef = vaddq_u64( ef, intermed );
472
473 /* Rounds t + 8 and t + 9 */
474 s4 = vsha512su1q_u64( vsha512su0q_u64( s4, s5 ), s3, vextq_u64( s0, s1, 1 ) );
475 initial_sum = vaddq_u64( s4, vld1q_u64( &K[t + 8] ) );
476 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
477 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
478 gh = vsha512h2q_u64( intermed, cd, ab );
479 cd = vaddq_u64( cd, intermed );
480
481 /* Rounds t + 10 and t + 11 */
482 s5 = vsha512su1q_u64( vsha512su0q_u64( s5, s6 ), s4, vextq_u64( s1, s2, 1 ) );
483 initial_sum = vaddq_u64( s5, vld1q_u64( &K[t + 10] ) );
484 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
485 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
486 ef = vsha512h2q_u64( intermed, ab, gh );
487 ab = vaddq_u64( ab, intermed );
488
489 /* Rounds t + 12 and t + 13 */
490 s6 = vsha512su1q_u64( vsha512su0q_u64( s6, s7 ), s5, vextq_u64( s2, s3, 1 ) );
491 initial_sum = vaddq_u64( s6, vld1q_u64( &K[t + 12] ) );
492 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
493 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
494 cd = vsha512h2q_u64( intermed, gh, ef );
495 gh = vaddq_u64( gh, intermed );
496
497 /* Rounds t + 14 and t + 15 */
498 s7 = vsha512su1q_u64( vsha512su0q_u64( s7, s0 ), s6, vextq_u64( s3, s4, 1 ) );
499 initial_sum = vaddq_u64( s7, vld1q_u64( &K[t + 14] ) );
500 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
501 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
502 ab = vsha512h2q_u64( intermed, ef, cd );
503 ef = vaddq_u64( ef, intermed );
504 }
505
506 ab = vaddq_u64( ab, ab_orig );
507 cd = vaddq_u64( cd, cd_orig );
508 ef = vaddq_u64( ef, ef_orig );
509 gh = vaddq_u64( gh, gh_orig );
510 }
511
512 vst1q_u64( &ctx->state[0], ab );
513 vst1q_u64( &ctx->state[2], cd );
514 vst1q_u64( &ctx->state[4], ef );
515 vst1q_u64( &ctx->state[6], gh );
516
517 return( processed );
518}
519
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100520#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
521/*
522 * This function is for internal use only if we are building both C and A64
523 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
524 */
525static
526#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000527int mbedtls_internal_sha512_process_a64_crypto( mbedtls_sha512_context *ctx,
528 const unsigned char data[SHA512_BLOCK_SIZE] )
529{
530 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, data,
531 SHA512_BLOCK_SIZE ) == SHA512_BLOCK_SIZE ) ? 0 : -1;
532}
533
534#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
535
536
537#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
538#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
539#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process
540#endif
541
542
543#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
544
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100545#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
546/*
547 * This function is for internal use only if we are building both C and A64
548 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
549 */
550static
551#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000552int mbedtls_internal_sha512_process_c( mbedtls_sha512_context *ctx,
553 const unsigned char data[SHA512_BLOCK_SIZE] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000554{
555 int i;
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200556 struct
557 {
558 uint64_t temp1, temp2, W[80];
559 uint64_t A[8];
560 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000561
Hanno Becker38e15d42018-12-18 17:54:00 +0000562 SHA512_VALIDATE_RET( ctx != NULL );
563 SHA512_VALIDATE_RET( (const unsigned char *)data != NULL );
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000564
Hanno Becker1eeca412018-10-15 12:01:35 +0100565#define SHR(x,n) ((x) >> (n))
Hanno Becker26d02e12018-10-30 09:29:25 +0000566#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000567
568#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
569#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
570
571#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
572#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
573
Hanno Becker1eeca412018-10-15 12:01:35 +0100574#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
575#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000576
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200577#define P(a,b,c,d,e,f,g,h,x,K) \
578 do \
579 { \
580 local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \
581 local.temp2 = S2(a) + F0((a),(b),(c)); \
582 (d) += local.temp1; (h) = local.temp1 + local.temp2; \
Hanno Becker1eeca412018-10-15 12:01:35 +0100583 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000584
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200585 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200586 local.A[i] = ctx->state[i];
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200587
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200588#if defined(MBEDTLS_SHA512_SMALLER)
589 for( i = 0; i < 80; i++ )
590 {
591 if( i < 16 )
592 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100593 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200594 }
595 else
596 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200597 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
598 S0(local.W[i - 15]) + local.W[i - 16];
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200599 }
600
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200601 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
602 local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200603
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200604 local.temp1 = local.A[7]; local.A[7] = local.A[6];
605 local.A[6] = local.A[5]; local.A[5] = local.A[4];
606 local.A[4] = local.A[3]; local.A[3] = local.A[2];
607 local.A[2] = local.A[1]; local.A[1] = local.A[0];
608 local.A[0] = local.temp1;
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200609 }
610#else /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000611 for( i = 0; i < 16; i++ )
612 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100613 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000614 }
615
616 for( ; i < 80; i++ )
617 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200618 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
619 S0(local.W[i - 15]) + local.W[i - 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000620 }
621
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 i = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 do
624 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200625 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
626 local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
627 P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
628 local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
629 P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
630 local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
631 P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
632 local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
633 P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
634 local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
635 P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
636 local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
637 P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
638 local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
639 P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
640 local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000641 }
642 while( i < 80 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200643#endif /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000644
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200645 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200646 ctx->state[i] += local.A[i];
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100647
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200648 /* Zeroise buffers and variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200649 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100650
651 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000652}
Jaeden Amero041039f2018-02-19 15:28:08 +0000653
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000654#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
655
656
657#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
658
659static size_t mbedtls_internal_sha512_process_many_c(
660 mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)
661{
662 size_t processed = 0;
663
664 while( len >= SHA512_BLOCK_SIZE )
665 {
666 if( mbedtls_internal_sha512_process_c( ctx, data ) != 0)
667 return( 0 );
668
669 data += SHA512_BLOCK_SIZE;
670 len -= SHA512_BLOCK_SIZE;
671
672 processed += SHA512_BLOCK_SIZE;
673 }
674
675 return( processed );
676}
677
678#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
679
680
681#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
682
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100683static int mbedtls_a64_crypto_sha512_has_support( void )
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000684{
685 static int done = 0;
686 static int supported = 0;
687
688 if( !done )
689 {
690 supported = mbedtls_a64_crypto_sha512_determine_support();
691 done = 1;
692 }
693
694 return( supported );
695}
696
697static size_t mbedtls_internal_sha512_process_many( mbedtls_sha512_context *ctx,
698 const uint8_t *msg, size_t len )
699{
700 if( mbedtls_a64_crypto_sha512_has_support() )
701 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, msg, len ) );
702 else
703 return( mbedtls_internal_sha512_process_many_c( ctx, msg, len ) );
704}
705
706int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
707 const unsigned char data[SHA512_BLOCK_SIZE] )
708{
709 if( mbedtls_a64_crypto_sha512_has_support() )
710 return( mbedtls_internal_sha512_process_a64_crypto( ctx, data ) );
711 else
712 return( mbedtls_internal_sha512_process_c( ctx, data ) );
713}
714
715#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000716
717/*
718 * SHA-512 process buffer
719 */
TRodziewicz26371e42021-06-08 16:45:41 +0200720int mbedtls_sha512_update( mbedtls_sha512_context *ctx,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100721 const unsigned char *input,
722 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000723{
Janos Follath24eed8d2019-11-22 13:21:35 +0000724 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000725 size_t fill;
Paul Bakkerb8213a12011-07-11 08:16:18 +0000726 unsigned int left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000727
Hanno Becker38e15d42018-12-18 17:54:00 +0000728 SHA512_VALIDATE_RET( ctx != NULL );
729 SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
Hanno Beckerca6f4582018-12-18 15:37:22 +0000730
Brian White12895d12014-04-11 11:29:42 -0400731 if( ilen == 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100732 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000733
Paul Bakkerb8213a12011-07-11 08:16:18 +0000734 left = (unsigned int) (ctx->total[0] & 0x7F);
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000735 fill = SHA512_BLOCK_SIZE - left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
Paul Bakker5c2364c2012-10-01 14:41:15 +0000737 ctx->total[0] += (uint64_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000738
Paul Bakker5c2364c2012-10-01 14:41:15 +0000739 if( ctx->total[0] < (uint64_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000740 ctx->total[1]++;
741
742 if( left && ilen >= fill )
743 {
Paul Bakker3c2122f2013-06-24 19:03:14 +0200744 memcpy( (void *) (ctx->buffer + left), input, fill );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100745
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100746 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100747 return( ret );
748
Paul Bakker5121ce52009-01-03 21:22:43 +0000749 input += fill;
750 ilen -= fill;
751 left = 0;
752 }
753
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000754 while( ilen >= SHA512_BLOCK_SIZE )
Paul Bakker5121ce52009-01-03 21:22:43 +0000755 {
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000756 size_t processed =
757 mbedtls_internal_sha512_process_many( ctx, input, ilen );
758 if( processed < SHA512_BLOCK_SIZE )
759 return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100760
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000761 input += processed;
762 ilen -= processed;
Paul Bakker5121ce52009-01-03 21:22:43 +0000763 }
764
765 if( ilen > 0 )
Paul Bakker3c2122f2013-06-24 19:03:14 +0200766 memcpy( (void *) (ctx->buffer + left), input, ilen );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100767
768 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000769}
770
Paul Bakker5121ce52009-01-03 21:22:43 +0000771/*
772 * SHA-512 final digest
773 */
TRodziewicz26371e42021-06-08 16:45:41 +0200774int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200775 unsigned char *output )
Paul Bakker5121ce52009-01-03 21:22:43 +0000776{
Janos Follath24eed8d2019-11-22 13:21:35 +0000777 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200778 unsigned used;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000779 uint64_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000780
Hanno Becker38e15d42018-12-18 17:54:00 +0000781 SHA512_VALIDATE_RET( ctx != NULL );
782 SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000783
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200784 /*
785 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
786 */
787 used = ctx->total[0] & 0x7F;
788
789 ctx->buffer[used++] = 0x80;
790
791 if( used <= 112 )
792 {
793 /* Enough room for padding + length in current block */
794 memset( ctx->buffer + used, 0, 112 - used );
795 }
796 else
797 {
798 /* We'll need an extra block */
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000799 memset( ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used );
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200800
801 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
802 return( ret );
803
804 memset( ctx->buffer, 0, 112 );
805 }
806
807 /*
808 * Add message length
809 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000810 high = ( ctx->total[0] >> 61 )
811 | ( ctx->total[1] << 3 );
812 low = ( ctx->total[0] << 3 );
813
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200814 sha512_put_uint64_be( high, ctx->buffer, 112 );
815 sha512_put_uint64_be( low, ctx->buffer, 120 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000816
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200817 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
818 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000819
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200820 /*
821 * Output final state
822 */
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200823 sha512_put_uint64_be( ctx->state[0], output, 0 );
824 sha512_put_uint64_be( ctx->state[1], output, 8 );
825 sha512_put_uint64_be( ctx->state[2], output, 16 );
826 sha512_put_uint64_be( ctx->state[3], output, 24 );
827 sha512_put_uint64_be( ctx->state[4], output, 32 );
828 sha512_put_uint64_be( ctx->state[5], output, 40 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000829
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200830#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 if( ctx->is384 == 0 )
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200832#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000833 {
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200834 sha512_put_uint64_be( ctx->state[6], output, 48 );
835 sha512_put_uint64_be( ctx->state[7], output, 56 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000836 }
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100837
838 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000839}
840
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200841#endif /* !MBEDTLS_SHA512_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200842
Paul Bakker5121ce52009-01-03 21:22:43 +0000843/*
844 * output = SHA-512( input buffer )
845 */
TRodziewicz26371e42021-06-08 16:45:41 +0200846int mbedtls_sha512( const unsigned char *input,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100847 size_t ilen,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200848 unsigned char *output,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100849 int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000850{
Janos Follath24eed8d2019-11-22 13:21:35 +0000851 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200852 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000853
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200854#if defined(MBEDTLS_SHA384_C)
Hanno Becker38e15d42018-12-18 17:54:00 +0000855 SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100856#else
857 SHA512_VALIDATE_RET( is384 == 0 );
858#endif
Hanno Becker38e15d42018-12-18 17:54:00 +0000859 SHA512_VALIDATE_RET( ilen == 0 || input != NULL );
860 SHA512_VALIDATE_RET( (unsigned char *)output != NULL );
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000861
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200862 mbedtls_sha512_init( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100863
TRodziewicz26371e42021-06-08 16:45:41 +0200864 if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100865 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100866
TRodziewicz26371e42021-06-08 16:45:41 +0200867 if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100868 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100869
TRodziewicz26371e42021-06-08 16:45:41 +0200870 if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100871 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100872
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100873exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874 mbedtls_sha512_free( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100875
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100876 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000877}
878
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200879#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000880
881/*
882 * FIPS-180-2 test vectors
883 */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000884static const unsigned char sha512_test_buf[3][113] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000885{
886 { "abc" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200887 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000888 { "" }
889};
890
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100891static const size_t sha512_test_buflen[3] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
893 3, 112, 1000
894};
895
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200896static const unsigned char sha512_test_sum[][64] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000897{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200898#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000899 /*
900 * SHA-384 test vectors
901 */
902 { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
903 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
904 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
905 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
906 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
907 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
908 { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
909 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
910 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
911 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
912 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
913 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
914 { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
915 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
916 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
917 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
918 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
919 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200920#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000921
922 /*
923 * SHA-512 test vectors
924 */
925 { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
926 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
927 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
928 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
929 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
930 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
931 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
932 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
933 { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
934 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
935 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
936 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
937 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
938 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
939 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
940 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
941 { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
942 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
943 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
944 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
945 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
946 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
947 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
948 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
949};
950
Manuel Pégourié-Gonnard74ca84a2020-01-29 09:46:49 +0100951#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200952
Paul Bakker5121ce52009-01-03 21:22:43 +0000953/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000954 * Checkup routine
955 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956int mbedtls_sha512_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000957{
Paul Bakker5b4af392014-06-26 12:09:34 +0200958 int i, j, k, buflen, ret = 0;
Russ Butlerbb83b422016-10-12 17:36:50 -0500959 unsigned char *buf;
Paul Bakker9e36f042013-06-30 14:34:05 +0200960 unsigned char sha512sum[64];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200961 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000962
Russ Butlerbb83b422016-10-12 17:36:50 -0500963 buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
964 if( NULL == buf )
965 {
966 if( verbose != 0 )
967 mbedtls_printf( "Buffer allocation failed\n" );
968
969 return( 1 );
970 }
971
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200972 mbedtls_sha512_init( &ctx );
Paul Bakker5b4af392014-06-26 12:09:34 +0200973
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +0100974 for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000975 {
976 j = i % 3;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200977#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000978 k = i < 3;
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200979#else
980 k = 0;
981#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000982
983 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200984 mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000985
TRodziewicz26371e42021-06-08 16:45:41 +0200986 if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100987 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000988
989 if( j == 2 )
990 {
991 memset( buf, 'a', buflen = 1000 );
992
993 for( j = 0; j < 1000; j++ )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100994 {
TRodziewicz26371e42021-06-08 16:45:41 +0200995 ret = mbedtls_sha512_update( &ctx, buf, buflen );
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100996 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100997 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100998 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000999 }
1000 else
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001001 {
TRodziewicz26371e42021-06-08 16:45:41 +02001002 ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001003 sha512_test_buflen[j] );
1004 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001005 goto fail;
1006 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001007
TRodziewicz26371e42021-06-08 16:45:41 +02001008 if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001009 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +00001010
Paul Bakker9e36f042013-06-30 14:34:05 +02001011 if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001012 {
1013 ret = 1;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001014 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001015 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
1017 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001018 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001019 }
1020
1021 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001022 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001023
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001024 goto exit;
1025
1026fail:
1027 if( verbose != 0 )
1028 mbedtls_printf( "failed\n" );
1029
Paul Bakker5b4af392014-06-26 12:09:34 +02001030exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001031 mbedtls_sha512_free( &ctx );
Russ Butlerbb83b422016-10-12 17:36:50 -05001032 mbedtls_free( buf );
Paul Bakker5b4af392014-06-26 12:09:34 +02001033
1034 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001035}
1036
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +01001037#undef ARRAY_LENGTH
Manuel Pégourié-Gonnard2d885492020-01-07 10:17:35 +01001038
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001039#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00001040
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001041#endif /* MBEDTLS_SHA512_C */