blob: 9be05cb7ee897e491c12446eea68a574182927d1 [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é-Gonnard2cf5a7c2015-04-08 12:49:31 +020041#if defined(MBEDTLS_SELF_TEST)
42#if defined(MBEDTLS_PLATFORM_C)
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000043#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010044#else
Rich Evans00ab4702015-02-06 13:43:58 +000045#include <stdio.h>
Russ Butlerbb83b422016-10-12 17:36:50 -050046#include <stdlib.h>
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020047#define mbedtls_printf printf
Russ Butlerbb83b422016-10-12 17:36:50 -050048#define mbedtls_calloc calloc
49#define mbedtls_free free
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020050#endif /* MBEDTLS_PLATFORM_C */
51#endif /* MBEDTLS_SELF_TEST */
Paul Bakker7dc4c442014-02-01 22:50:26 +010052
Tom Cosgrove87fbfb52022-03-15 10:51:52 +000053#if defined(__aarch64__)
54# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
55 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
56# include <arm_neon.h>
57# endif
58# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
59# if defined(__unix__)
60# if defined(__linux__)
61 /* Our preferred method of detection is getauxval() */
62# include <sys/auxv.h>
63# endif
64 /* Use SIGILL on Unix, and fall back to it on Linux */
65# include <signal.h>
66# endif
67# endif
68#elif defined(_M_ARM64)
69# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
70 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
71# include <arm64_neon.h>
72# endif
73#else
74# undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY
75# undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
76#endif
77
78#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
79/*
80 * Capability detection code comes early, so we can disable
81 * MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
82 */
83#if defined(HWCAP_SHA512)
84static int mbedtls_a64_crypto_sha512_determine_support( void )
85{
86 return( ( getauxval( AT_HWCAP ) & HWCAP_SHA512 ) ? 1 : 0 );
87}
88#elif defined(__APPLE__)
89#include <sys/types.h>
90#include <sys/sysctl.h>
91
92static int mbedtls_a64_crypto_sha512_determine_support( void )
93{
94 int value = 0;
95 size_t value_len = sizeof(value);
96
97 int ret = sysctlbyname( "hw.optional.armv8_2_sha512", &value, &value_len,
98 NULL, 0 );
99 return( ret == 0 && value != 0 );
100}
101#elif defined(_M_ARM64)
102/*
103 * As of March 2022, there don't appear to be any PF_ARM_V8_* flags
104 * available to pass to IsProcessorFeaturePresent() to check for
105 * SHA-512 support. So we fall back to the C code only.
106 */
107#if defined(_MSC_VER)
108#pragma message "No mechanism to detect A64_CRYPTO found, using C code only"
109#else
110#warning "No mechanism to detect A64_CRYPTO found, using C code only"
111#endif
112#elif defined(__unix__) && defined(SIG_SETMASK)
113/* Detection with SIGILL, setjmp() and longjmp() */
114#include <signal.h>
115#include <setjmp.h>
116
117#ifndef asm
118#define asm __asm__
119#endif
120
121static jmp_buf return_from_sigill;
122
123/*
124 * A64 SHA512 support detection via SIGILL
125 */
126static void sigill_handler( int signal )
127{
128 (void) signal;
129 longjmp( return_from_sigill, 1 );
130}
131
132static int mbedtls_a64_crypto_sha512_determine_support( void )
133{
134 struct sigaction old_action, new_action;
135
136 sigset_t old_mask;
137 if( sigprocmask( 0, NULL, &old_mask ) )
138 return( 0 );
139
140 sigemptyset( &new_action.sa_mask );
141 new_action.sa_flags = 0;
142 new_action.sa_handler = sigill_handler;
143
144 sigaction( SIGILL, &new_action, &old_action );
145
146 static int ret = 0;
147
148 if( setjmp( return_from_sigill ) == 0 ) /* First return only */
149 {
150 /* If this traps, we will return a second time from setjmp() with 1 */
151 asm( "sha512h q0, q0, v0.2d" : : : "v0" );
152 ret = 1;
153 }
154
155 sigaction( SIGILL, &old_action, NULL );
156 sigprocmask( SIG_SETMASK, &old_mask, NULL );
157
158 return( ret );
159}
160#else
161#warning "No mechanism to detect A64_CRYPTO found, using C code only"
162#undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
163#endif /* HWCAP_SHA512, __APPLE__, __unix__ && SIG_SETMASK */
164
165#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
166
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +0200167#if !defined(MBEDTLS_SHA512_ALT)
168
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000169#define SHA512_BLOCK_SIZE 128
170
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200171#if defined(MBEDTLS_SHA512_SMALLER)
172static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
173{
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100174 MBEDTLS_PUT_UINT64_BE(n, b, i);
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200175}
176#else
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100177#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200178#endif /* MBEDTLS_SHA512_SMALLER */
179
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200180void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200181{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200182 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200183}
184
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200185void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200186{
187 if( ctx == NULL )
188 return;
189
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500190 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200191}
192
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200193void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
194 const mbedtls_sha512_context *src )
195{
196 *dst = *src;
197}
198
Paul Bakker5121ce52009-01-03 21:22:43 +0000199/*
200 * SHA-512 context setup
201 */
TRodziewicz26371e42021-06-08 16:45:41 +0200202int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000203{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200204#if defined(MBEDTLS_SHA384_C)
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100205 if( is384 != 0 && is384 != 1 )
206 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100207#else
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100208 if( is384 != 0 )
209 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100210#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000211
Paul Bakker5121ce52009-01-03 21:22:43 +0000212 ctx->total[0] = 0;
213 ctx->total[1] = 0;
214
215 if( is384 == 0 )
216 {
217 /* SHA-512 */
218 ctx->state[0] = UL64(0x6A09E667F3BCC908);
219 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
220 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
221 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
222 ctx->state[4] = UL64(0x510E527FADE682D1);
223 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
224 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
225 ctx->state[7] = UL64(0x5BE0CD19137E2179);
226 }
227 else
228 {
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200229#if !defined(MBEDTLS_SHA384_C)
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200230 return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
231#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000232 /* SHA-384 */
233 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
234 ctx->state[1] = UL64(0x629A292A367CD507);
235 ctx->state[2] = UL64(0x9159015A3070DD17);
236 ctx->state[3] = UL64(0x152FECD8F70E5939);
237 ctx->state[4] = UL64(0x67332667FFC00B31);
238 ctx->state[5] = UL64(0x8EB44A8768581511);
239 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
240 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200241#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000242 }
243
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200244#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000245 ctx->is384 = is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200246#endif
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100247
248 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000249}
250
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200251#if !defined(MBEDTLS_SHA512_PROCESS_ALT)
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200252
253/*
254 * Round constants
255 */
256static const uint64_t K[80] =
257{
258 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
259 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
260 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
261 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
262 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
263 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
264 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
265 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
266 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
267 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
268 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
269 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
270 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
271 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
272 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
273 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
274 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
275 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
276 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
277 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
278 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
279 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
280 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
281 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
282 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
283 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
284 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
285 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
286 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
287 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
288 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
289 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
290 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
291 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
292 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
293 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
294 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
295 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
296 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
297 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
298};
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000299#endif
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200300
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000301#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
302 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
303
304#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
305# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many
306# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process
307#endif
308
309#ifndef asm
310#define asm __asm__
311#endif
312
313/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
314 * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
315 */
316
317#if defined(__clang__) && \
318 (__clang_major__ < 13 || \
319 (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))
320static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)
321{
322 asm( "sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y) );
323 return( x );
324}
325static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
326{
327 asm( "sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
328 return( x );
329}
330static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
331{
332 asm( "sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
333 return( x );
334}
335static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
336{
337 asm( "sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
338 return( x );
339}
340#endif /* __clang__ etc */
341
342static size_t mbedtls_internal_sha512_process_many_a64_crypto(
343 mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len )
344{
345 uint64x2_t ab = vld1q_u64( &ctx->state[0] );
346 uint64x2_t cd = vld1q_u64( &ctx->state[2] );
347 uint64x2_t ef = vld1q_u64( &ctx->state[4] );
348 uint64x2_t gh = vld1q_u64( &ctx->state[6] );
349
350 size_t processed = 0;
351
352 for ( ;
353 len >= SHA512_BLOCK_SIZE;
354 processed += SHA512_BLOCK_SIZE,
355 msg += SHA512_BLOCK_SIZE,
356 len -= SHA512_BLOCK_SIZE )
357 {
358 uint64x2_t initial_sum, sum, intermed;
359
360 uint64x2_t ab_orig = ab;
361 uint64x2_t cd_orig = cd;
362 uint64x2_t ef_orig = ef;
363 uint64x2_t gh_orig = gh;
364
365 uint64x2_t s0 = (uint64x2_t) vld1q_u8( msg + 16 * 0 );
366 uint64x2_t s1 = (uint64x2_t) vld1q_u8( msg + 16 * 1 );
367 uint64x2_t s2 = (uint64x2_t) vld1q_u8( msg + 16 * 2 );
368 uint64x2_t s3 = (uint64x2_t) vld1q_u8( msg + 16 * 3 );
369 uint64x2_t s4 = (uint64x2_t) vld1q_u8( msg + 16 * 4 );
370 uint64x2_t s5 = (uint64x2_t) vld1q_u8( msg + 16 * 5 );
371 uint64x2_t s6 = (uint64x2_t) vld1q_u8( msg + 16 * 6 );
372 uint64x2_t s7 = (uint64x2_t) vld1q_u8( msg + 16 * 7 );
373
374#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */
375 s0 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s0 ) ) );
376 s1 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s1 ) ) );
377 s2 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s2 ) ) );
378 s3 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s3 ) ) );
379 s4 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s4 ) ) );
380 s5 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s5 ) ) );
381 s6 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s6 ) ) );
382 s7 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s7 ) ) );
383#endif
384
385 /* Rounds 0 and 1 */
386 initial_sum = vaddq_u64( s0, vld1q_u64( &K[0] ) );
387 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
388 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
389 gh = vsha512h2q_u64( intermed, cd, ab );
390 cd = vaddq_u64( cd, intermed );
391
392 /* Rounds 2 and 3 */
393 initial_sum = vaddq_u64( s1, vld1q_u64( &K[2] ) );
394 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
395 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
396 ef = vsha512h2q_u64( intermed, ab, gh );
397 ab = vaddq_u64( ab, intermed );
398
399 /* Rounds 4 and 5 */
400 initial_sum = vaddq_u64( s2, vld1q_u64( &K[4] ) );
401 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
402 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
403 cd = vsha512h2q_u64( intermed, gh, ef );
404 gh = vaddq_u64( gh, intermed );
405
406 /* Rounds 6 and 7 */
407 initial_sum = vaddq_u64( s3, vld1q_u64( &K[6] ) );
408 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
409 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
410 ab = vsha512h2q_u64( intermed, ef, cd );
411 ef = vaddq_u64( ef, intermed );
412
413 /* Rounds 8 and 9 */
414 initial_sum = vaddq_u64( s4, vld1q_u64( &K[8] ) );
415 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
416 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
417 gh = vsha512h2q_u64( intermed, cd, ab );
418 cd = vaddq_u64( cd, intermed );
419
420 /* Rounds 10 and 11 */
421 initial_sum = vaddq_u64( s5, vld1q_u64( &K[10] ) );
422 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
423 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
424 ef = vsha512h2q_u64( intermed, ab, gh );
425 ab = vaddq_u64( ab, intermed );
426
427 /* Rounds 12 and 13 */
428 initial_sum = vaddq_u64( s6, vld1q_u64( &K[12] ) );
429 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
430 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
431 cd = vsha512h2q_u64( intermed, gh, ef );
432 gh = vaddq_u64( gh, intermed );
433
434 /* Rounds 14 and 15 */
435 initial_sum = vaddq_u64( s7, vld1q_u64( &K[14] ) );
436 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
437 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
438 ab = vsha512h2q_u64( intermed, ef, cd );
439 ef = vaddq_u64( ef, intermed );
440
441 for ( unsigned int t = 16; t < 80; t += 16 )
442 {
443 /* Rounds t and t + 1 */
444 s0 = vsha512su1q_u64( vsha512su0q_u64( s0, s1 ), s7, vextq_u64( s4, s5, 1 ) );
445 initial_sum = vaddq_u64( s0, vld1q_u64( &K[t] ) );
446 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
447 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
448 gh = vsha512h2q_u64( intermed, cd, ab );
449 cd = vaddq_u64( cd, intermed );
450
451 /* Rounds t + 2 and t + 3 */
452 s1 = vsha512su1q_u64( vsha512su0q_u64( s1, s2 ), s0, vextq_u64( s5, s6, 1 ) );
453 initial_sum = vaddq_u64( s1, vld1q_u64( &K[t + 2] ) );
454 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
455 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
456 ef = vsha512h2q_u64( intermed, ab, gh );
457 ab = vaddq_u64( ab, intermed );
458
459 /* Rounds t + 4 and t + 5 */
460 s2 = vsha512su1q_u64( vsha512su0q_u64( s2, s3 ), s1, vextq_u64( s6, s7, 1 ) );
461 initial_sum = vaddq_u64( s2, vld1q_u64( &K[t + 4] ) );
462 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
463 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
464 cd = vsha512h2q_u64( intermed, gh, ef );
465 gh = vaddq_u64( gh, intermed );
466
467 /* Rounds t + 6 and t + 7 */
468 s3 = vsha512su1q_u64( vsha512su0q_u64( s3, s4 ), s2, vextq_u64( s7, s0, 1 ) );
469 initial_sum = vaddq_u64( s3, vld1q_u64( &K[t + 6] ) );
470 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
471 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
472 ab = vsha512h2q_u64( intermed, ef, cd );
473 ef = vaddq_u64( ef, intermed );
474
475 /* Rounds t + 8 and t + 9 */
476 s4 = vsha512su1q_u64( vsha512su0q_u64( s4, s5 ), s3, vextq_u64( s0, s1, 1 ) );
477 initial_sum = vaddq_u64( s4, vld1q_u64( &K[t + 8] ) );
478 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
479 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
480 gh = vsha512h2q_u64( intermed, cd, ab );
481 cd = vaddq_u64( cd, intermed );
482
483 /* Rounds t + 10 and t + 11 */
484 s5 = vsha512su1q_u64( vsha512su0q_u64( s5, s6 ), s4, vextq_u64( s1, s2, 1 ) );
485 initial_sum = vaddq_u64( s5, vld1q_u64( &K[t + 10] ) );
486 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
487 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
488 ef = vsha512h2q_u64( intermed, ab, gh );
489 ab = vaddq_u64( ab, intermed );
490
491 /* Rounds t + 12 and t + 13 */
492 s6 = vsha512su1q_u64( vsha512su0q_u64( s6, s7 ), s5, vextq_u64( s2, s3, 1 ) );
493 initial_sum = vaddq_u64( s6, vld1q_u64( &K[t + 12] ) );
494 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
495 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
496 cd = vsha512h2q_u64( intermed, gh, ef );
497 gh = vaddq_u64( gh, intermed );
498
499 /* Rounds t + 14 and t + 15 */
500 s7 = vsha512su1q_u64( vsha512su0q_u64( s7, s0 ), s6, vextq_u64( s3, s4, 1 ) );
501 initial_sum = vaddq_u64( s7, vld1q_u64( &K[t + 14] ) );
502 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
503 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
504 ab = vsha512h2q_u64( intermed, ef, cd );
505 ef = vaddq_u64( ef, intermed );
506 }
507
508 ab = vaddq_u64( ab, ab_orig );
509 cd = vaddq_u64( cd, cd_orig );
510 ef = vaddq_u64( ef, ef_orig );
511 gh = vaddq_u64( gh, gh_orig );
512 }
513
514 vst1q_u64( &ctx->state[0], ab );
515 vst1q_u64( &ctx->state[2], cd );
516 vst1q_u64( &ctx->state[4], ef );
517 vst1q_u64( &ctx->state[6], gh );
518
519 return( processed );
520}
521
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100522#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
523/*
524 * This function is for internal use only if we are building both C and A64
525 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
526 */
527static
528#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000529int mbedtls_internal_sha512_process_a64_crypto( mbedtls_sha512_context *ctx,
530 const unsigned char data[SHA512_BLOCK_SIZE] )
531{
532 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, data,
533 SHA512_BLOCK_SIZE ) == SHA512_BLOCK_SIZE ) ? 0 : -1;
534}
535
536#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
537
538
539#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
540#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
541#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process
542#endif
543
544
545#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
546
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100547#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
548/*
549 * This function is for internal use only if we are building both C and A64
550 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
551 */
552static
553#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000554int mbedtls_internal_sha512_process_c( mbedtls_sha512_context *ctx,
555 const unsigned char data[SHA512_BLOCK_SIZE] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000556{
557 int i;
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200558 struct
559 {
560 uint64_t temp1, temp2, W[80];
561 uint64_t A[8];
562 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000563
Hanno Becker1eeca412018-10-15 12:01:35 +0100564#define SHR(x,n) ((x) >> (n))
Hanno Becker26d02e12018-10-30 09:29:25 +0000565#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000566
567#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
568#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
569
570#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
571#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
572
Hanno Becker1eeca412018-10-15 12:01:35 +0100573#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
574#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000575
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200576#define P(a,b,c,d,e,f,g,h,x,K) \
577 do \
578 { \
579 local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \
580 local.temp2 = S2(a) + F0((a),(b),(c)); \
581 (d) += local.temp1; (h) = local.temp1 + local.temp2; \
Hanno Becker1eeca412018-10-15 12:01:35 +0100582 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000583
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200584 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200585 local.A[i] = ctx->state[i];
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200586
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200587#if defined(MBEDTLS_SHA512_SMALLER)
588 for( i = 0; i < 80; i++ )
589 {
590 if( i < 16 )
591 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100592 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200593 }
594 else
595 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200596 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
597 S0(local.W[i - 15]) + local.W[i - 16];
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200598 }
599
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200600 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
601 local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200602
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200603 local.temp1 = local.A[7]; local.A[7] = local.A[6];
604 local.A[6] = local.A[5]; local.A[5] = local.A[4];
605 local.A[4] = local.A[3]; local.A[3] = local.A[2];
606 local.A[2] = local.A[1]; local.A[1] = local.A[0];
607 local.A[0] = local.temp1;
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200608 }
609#else /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000610 for( i = 0; i < 16; i++ )
611 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100612 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000613 }
614
615 for( ; i < 80; i++ )
616 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200617 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
618 S0(local.W[i - 15]) + local.W[i - 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000619 }
620
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 i = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000622 do
623 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200624 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
625 local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
626 P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
627 local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
628 P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
629 local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
630 P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
631 local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
632 P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
633 local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
634 P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
635 local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
636 P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
637 local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
638 P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
639 local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000640 }
641 while( i < 80 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200642#endif /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000643
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200644 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200645 ctx->state[i] += local.A[i];
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100646
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200647 /* Zeroise buffers and variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200648 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100649
650 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000651}
Jaeden Amero041039f2018-02-19 15:28:08 +0000652
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000653#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
654
655
656#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
657
658static size_t mbedtls_internal_sha512_process_many_c(
659 mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)
660{
661 size_t processed = 0;
662
663 while( len >= SHA512_BLOCK_SIZE )
664 {
665 if( mbedtls_internal_sha512_process_c( ctx, data ) != 0)
666 return( 0 );
667
668 data += SHA512_BLOCK_SIZE;
669 len -= SHA512_BLOCK_SIZE;
670
671 processed += SHA512_BLOCK_SIZE;
672 }
673
674 return( processed );
675}
676
677#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
678
679
680#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
681
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100682static int mbedtls_a64_crypto_sha512_has_support( void )
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000683{
684 static int done = 0;
685 static int supported = 0;
686
687 if( !done )
688 {
689 supported = mbedtls_a64_crypto_sha512_determine_support();
690 done = 1;
691 }
692
693 return( supported );
694}
695
696static size_t mbedtls_internal_sha512_process_many( mbedtls_sha512_context *ctx,
697 const uint8_t *msg, size_t len )
698{
699 if( mbedtls_a64_crypto_sha512_has_support() )
700 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, msg, len ) );
701 else
702 return( mbedtls_internal_sha512_process_many_c( ctx, msg, len ) );
703}
704
705int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
706 const unsigned char data[SHA512_BLOCK_SIZE] )
707{
708 if( mbedtls_a64_crypto_sha512_has_support() )
709 return( mbedtls_internal_sha512_process_a64_crypto( ctx, data ) );
710 else
711 return( mbedtls_internal_sha512_process_c( ctx, data ) );
712}
713
714#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000715
716/*
717 * SHA-512 process buffer
718 */
TRodziewicz26371e42021-06-08 16:45:41 +0200719int mbedtls_sha512_update( mbedtls_sha512_context *ctx,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100720 const unsigned char *input,
721 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000722{
Janos Follath24eed8d2019-11-22 13:21:35 +0000723 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000724 size_t fill;
Paul Bakkerb8213a12011-07-11 08:16:18 +0000725 unsigned int left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000726
Brian White12895d12014-04-11 11:29:42 -0400727 if( ilen == 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100728 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000729
Paul Bakkerb8213a12011-07-11 08:16:18 +0000730 left = (unsigned int) (ctx->total[0] & 0x7F);
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000731 fill = SHA512_BLOCK_SIZE - left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000732
Paul Bakker5c2364c2012-10-01 14:41:15 +0000733 ctx->total[0] += (uint64_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734
Paul Bakker5c2364c2012-10-01 14:41:15 +0000735 if( ctx->total[0] < (uint64_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000736 ctx->total[1]++;
737
738 if( left && ilen >= fill )
739 {
Paul Bakker3c2122f2013-06-24 19:03:14 +0200740 memcpy( (void *) (ctx->buffer + left), input, fill );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100741
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100742 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100743 return( ret );
744
Paul Bakker5121ce52009-01-03 21:22:43 +0000745 input += fill;
746 ilen -= fill;
747 left = 0;
748 }
749
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000750 while( ilen >= SHA512_BLOCK_SIZE )
Paul Bakker5121ce52009-01-03 21:22:43 +0000751 {
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000752 size_t processed =
753 mbedtls_internal_sha512_process_many( ctx, input, ilen );
754 if( processed < SHA512_BLOCK_SIZE )
755 return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100756
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000757 input += processed;
758 ilen -= processed;
Paul Bakker5121ce52009-01-03 21:22:43 +0000759 }
760
761 if( ilen > 0 )
Paul Bakker3c2122f2013-06-24 19:03:14 +0200762 memcpy( (void *) (ctx->buffer + left), input, ilen );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100763
764 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000765}
766
Paul Bakker5121ce52009-01-03 21:22:43 +0000767/*
768 * SHA-512 final digest
769 */
TRodziewicz26371e42021-06-08 16:45:41 +0200770int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200771 unsigned char *output )
Paul Bakker5121ce52009-01-03 21:22:43 +0000772{
Janos Follath24eed8d2019-11-22 13:21:35 +0000773 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200774 unsigned used;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000775 uint64_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000776
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200777 /*
778 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
779 */
780 used = ctx->total[0] & 0x7F;
781
782 ctx->buffer[used++] = 0x80;
783
784 if( used <= 112 )
785 {
786 /* Enough room for padding + length in current block */
787 memset( ctx->buffer + used, 0, 112 - used );
788 }
789 else
790 {
791 /* We'll need an extra block */
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000792 memset( ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used );
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200793
794 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
795 return( ret );
796
797 memset( ctx->buffer, 0, 112 );
798 }
799
800 /*
801 * Add message length
802 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000803 high = ( ctx->total[0] >> 61 )
804 | ( ctx->total[1] << 3 );
805 low = ( ctx->total[0] << 3 );
806
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200807 sha512_put_uint64_be( high, ctx->buffer, 112 );
808 sha512_put_uint64_be( low, ctx->buffer, 120 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000809
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200810 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
811 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000812
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200813 /*
814 * Output final state
815 */
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200816 sha512_put_uint64_be( ctx->state[0], output, 0 );
817 sha512_put_uint64_be( ctx->state[1], output, 8 );
818 sha512_put_uint64_be( ctx->state[2], output, 16 );
819 sha512_put_uint64_be( ctx->state[3], output, 24 );
820 sha512_put_uint64_be( ctx->state[4], output, 32 );
821 sha512_put_uint64_be( ctx->state[5], output, 40 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000822
David Horstmann2788f6b2022-10-06 18:45:09 +0100823 int truncated = 0;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200824#if defined(MBEDTLS_SHA384_C)
David Horstmann2788f6b2022-10-06 18:45:09 +0100825 truncated = ctx->is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200826#endif
David Horstmann2788f6b2022-10-06 18:45:09 +0100827 if( !truncated )
Paul Bakker5121ce52009-01-03 21:22:43 +0000828 {
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200829 sha512_put_uint64_be( ctx->state[6], output, 48 );
830 sha512_put_uint64_be( ctx->state[7], output, 56 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000831 }
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100832
833 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000834}
835
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200836#endif /* !MBEDTLS_SHA512_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200837
Paul Bakker5121ce52009-01-03 21:22:43 +0000838/*
839 * output = SHA-512( input buffer )
840 */
TRodziewicz26371e42021-06-08 16:45:41 +0200841int mbedtls_sha512( const unsigned char *input,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100842 size_t ilen,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200843 unsigned char *output,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100844 int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000845{
Janos Follath24eed8d2019-11-22 13:21:35 +0000846 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200847 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000848
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200849#if defined(MBEDTLS_SHA384_C)
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100850 if( is384 != 0 && is384 != 1 )
851 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100852#else
Tuvshinzaya Erdenekhuu5893ab02022-08-05 15:59:19 +0100853 if( is384 != 0 )
854 return MBEDTLS_ERR_SHA512_BAD_INPUT_DATA;
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100855#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000856
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200857 mbedtls_sha512_init( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100858
TRodziewicz26371e42021-06-08 16:45:41 +0200859 if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100860 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100861
TRodziewicz26371e42021-06-08 16:45:41 +0200862 if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100863 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100864
TRodziewicz26371e42021-06-08 16:45:41 +0200865 if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100866 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100867
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100868exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200869 mbedtls_sha512_free( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100870
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100871 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000872}
873
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200874#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000875
876/*
877 * FIPS-180-2 test vectors
878 */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000879static const unsigned char sha512_test_buf[3][113] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000880{
881 { "abc" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200882 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000883 { "" }
884};
885
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100886static const size_t sha512_test_buflen[3] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000887{
888 3, 112, 1000
889};
890
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200891static const unsigned char sha512_test_sum[][64] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000892{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200893#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000894 /*
895 * SHA-384 test vectors
896 */
897 { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
898 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
899 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
900 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
901 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
902 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
903 { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
904 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
905 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
906 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
907 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
908 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
909 { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
910 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
911 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
912 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
913 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
914 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200915#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000916
917 /*
918 * SHA-512 test vectors
919 */
920 { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
921 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
922 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
923 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
924 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
925 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
926 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
927 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
928 { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
929 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
930 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
931 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
932 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
933 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
934 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
935 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
936 { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
937 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
938 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
939 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
940 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
941 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
942 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
943 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
944};
945
Manuel Pégourié-Gonnard74ca84a2020-01-29 09:46:49 +0100946#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200947
Paul Bakker5121ce52009-01-03 21:22:43 +0000948/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000949 * Checkup routine
950 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200951int mbedtls_sha512_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000952{
Paul Bakker5b4af392014-06-26 12:09:34 +0200953 int i, j, k, buflen, ret = 0;
Russ Butlerbb83b422016-10-12 17:36:50 -0500954 unsigned char *buf;
Paul Bakker9e36f042013-06-30 14:34:05 +0200955 unsigned char sha512sum[64];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200956 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000957
Russ Butlerbb83b422016-10-12 17:36:50 -0500958 buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
959 if( NULL == buf )
960 {
961 if( verbose != 0 )
962 mbedtls_printf( "Buffer allocation failed\n" );
963
964 return( 1 );
965 }
966
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200967 mbedtls_sha512_init( &ctx );
Paul Bakker5b4af392014-06-26 12:09:34 +0200968
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +0100969 for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000970 {
971 j = i % 3;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200972#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000973 k = i < 3;
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200974#else
975 k = 0;
976#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000977
978 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200979 mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000980
TRodziewicz26371e42021-06-08 16:45:41 +0200981 if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100982 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000983
984 if( j == 2 )
985 {
986 memset( buf, 'a', buflen = 1000 );
987
988 for( j = 0; j < 1000; j++ )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100989 {
TRodziewicz26371e42021-06-08 16:45:41 +0200990 ret = mbedtls_sha512_update( &ctx, buf, buflen );
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100991 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100992 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100993 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000994 }
995 else
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100996 {
TRodziewicz26371e42021-06-08 16:45:41 +0200997 ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100998 sha512_test_buflen[j] );
999 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001000 goto fail;
1001 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001002
TRodziewicz26371e42021-06-08 16:45:41 +02001003 if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001004 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +00001005
Paul Bakker9e36f042013-06-30 14:34:05 +02001006 if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001007 {
1008 ret = 1;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001009 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001010 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001011
1012 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001013 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001014 }
1015
1016 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001017 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001018
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001019 goto exit;
1020
1021fail:
1022 if( verbose != 0 )
1023 mbedtls_printf( "failed\n" );
1024
Paul Bakker5b4af392014-06-26 12:09:34 +02001025exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001026 mbedtls_sha512_free( &ctx );
Russ Butlerbb83b422016-10-12 17:36:50 -05001027 mbedtls_free( buf );
Paul Bakker5b4af392014-06-26 12:09:34 +02001028
1029 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001030}
1031
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +01001032#undef ARRAY_LENGTH
Manuel Pégourié-Gonnard2d885492020-01-07 10:17:35 +01001033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00001035
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001036#endif /* MBEDTLS_SHA512_C */