blob: c575bbd10e3c6d4c281e68dca0a489644409afaf [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
Hanno Beckerc7560492018-12-20 10:23:39 +0000167#define SHA512_VALIDATE_RET(cond) \
168 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA512_BAD_INPUT_DATA )
169#define SHA512_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
170
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +0200171#if !defined(MBEDTLS_SHA512_ALT)
172
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000173#define SHA512_BLOCK_SIZE 128
174
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200175#if defined(MBEDTLS_SHA512_SMALLER)
176static void sha512_put_uint64_be( uint64_t n, unsigned char *b, uint8_t i )
177{
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100178 MBEDTLS_PUT_UINT64_BE(n, b, i);
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200179}
180#else
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100181#define sha512_put_uint64_be MBEDTLS_PUT_UINT64_BE
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200182#endif /* MBEDTLS_SHA512_SMALLER */
183
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200184void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200185{
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200186 memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200187}
188
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200189void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
Paul Bakker5b4af392014-06-26 12:09:34 +0200190{
191 if( ctx == NULL )
192 return;
193
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -0500194 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
Paul Bakker5b4af392014-06-26 12:09:34 +0200195}
196
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200197void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
198 const mbedtls_sha512_context *src )
199{
200 *dst = *src;
201}
202
Paul Bakker5121ce52009-01-03 21:22:43 +0000203/*
204 * SHA-512 context setup
205 */
TRodziewicz26371e42021-06-08 16:45:41 +0200206int mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000207{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200208#if defined(MBEDTLS_SHA384_C)
Hanno Becker38e15d42018-12-18 17:54:00 +0000209 SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100210#else
211 SHA512_VALIDATE_RET( is384 == 0 );
212#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000213
Paul Bakker5121ce52009-01-03 21:22:43 +0000214 ctx->total[0] = 0;
215 ctx->total[1] = 0;
216
217 if( is384 == 0 )
218 {
219 /* SHA-512 */
220 ctx->state[0] = UL64(0x6A09E667F3BCC908);
221 ctx->state[1] = UL64(0xBB67AE8584CAA73B);
222 ctx->state[2] = UL64(0x3C6EF372FE94F82B);
223 ctx->state[3] = UL64(0xA54FF53A5F1D36F1);
224 ctx->state[4] = UL64(0x510E527FADE682D1);
225 ctx->state[5] = UL64(0x9B05688C2B3E6C1F);
226 ctx->state[6] = UL64(0x1F83D9ABFB41BD6B);
227 ctx->state[7] = UL64(0x5BE0CD19137E2179);
228 }
229 else
230 {
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200231#if !defined(MBEDTLS_SHA384_C)
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200232 return( MBEDTLS_ERR_SHA512_BAD_INPUT_DATA );
233#else
Paul Bakker5121ce52009-01-03 21:22:43 +0000234 /* SHA-384 */
235 ctx->state[0] = UL64(0xCBBB9D5DC1059ED8);
236 ctx->state[1] = UL64(0x629A292A367CD507);
237 ctx->state[2] = UL64(0x9159015A3070DD17);
238 ctx->state[3] = UL64(0x152FECD8F70E5939);
239 ctx->state[4] = UL64(0x67332667FFC00B31);
240 ctx->state[5] = UL64(0x8EB44A8768581511);
241 ctx->state[6] = UL64(0xDB0C2E0D64F98FA7);
242 ctx->state[7] = UL64(0x47B5481DBEFA4FA4);
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200243#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000244 }
245
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200246#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000247 ctx->is384 = is384;
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200248#endif
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100249
250 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000251}
252
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200253#if !defined(MBEDTLS_SHA512_PROCESS_ALT)
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200254
255/*
256 * Round constants
257 */
258static const uint64_t K[80] =
259{
260 UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD),
261 UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC),
262 UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019),
263 UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118),
264 UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE),
265 UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2),
266 UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1),
267 UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694),
268 UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3),
269 UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65),
270 UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483),
271 UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5),
272 UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210),
273 UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4),
274 UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725),
275 UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70),
276 UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926),
277 UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF),
278 UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8),
279 UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B),
280 UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001),
281 UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30),
282 UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910),
283 UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8),
284 UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53),
285 UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8),
286 UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB),
287 UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3),
288 UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60),
289 UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC),
290 UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9),
291 UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B),
292 UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207),
293 UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178),
294 UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6),
295 UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B),
296 UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493),
297 UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C),
298 UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A),
299 UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817)
300};
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000301#endif
Alexey Skalozub00b78a92016-01-13 17:39:58 +0200302
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000303#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \
304 defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
305
306#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
307# define mbedtls_internal_sha512_process_many_a64_crypto mbedtls_internal_sha512_process_many
308# define mbedtls_internal_sha512_process_a64_crypto mbedtls_internal_sha512_process
309#endif
310
311#ifndef asm
312#define asm __asm__
313#endif
314
315/* Accelerated SHA-512 implementation originally written by Simon Tatham for PuTTY,
316 * under the MIT licence; dual-licensed as Apache 2 with his kind permission.
317 */
318
319#if defined(__clang__) && \
320 (__clang_major__ < 13 || \
321 (__clang_major__ == 13 && __clang_minor__ == 0 && __clang_patchlevel__ == 0))
322static inline uint64x2_t vsha512su0q_u64(uint64x2_t x, uint64x2_t y)
323{
324 asm( "sha512su0 %0.2D,%1.2D" : "+w" (x) : "w" (y) );
325 return( x );
326}
327static inline uint64x2_t vsha512su1q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
328{
329 asm( "sha512su1 %0.2D,%1.2D,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
330 return( x );
331}
332static inline uint64x2_t vsha512hq_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
333{
334 asm( "sha512h %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
335 return( x );
336}
337static inline uint64x2_t vsha512h2q_u64(uint64x2_t x, uint64x2_t y, uint64x2_t z)
338{
339 asm( "sha512h2 %0,%1,%2.2D" : "+w" (x) : "w" (y), "w" (z) );
340 return( x );
341}
342#endif /* __clang__ etc */
343
344static size_t mbedtls_internal_sha512_process_many_a64_crypto(
345 mbedtls_sha512_context *ctx, const uint8_t *msg, size_t len )
346{
347 uint64x2_t ab = vld1q_u64( &ctx->state[0] );
348 uint64x2_t cd = vld1q_u64( &ctx->state[2] );
349 uint64x2_t ef = vld1q_u64( &ctx->state[4] );
350 uint64x2_t gh = vld1q_u64( &ctx->state[6] );
351
352 size_t processed = 0;
353
354 for ( ;
355 len >= SHA512_BLOCK_SIZE;
356 processed += SHA512_BLOCK_SIZE,
357 msg += SHA512_BLOCK_SIZE,
358 len -= SHA512_BLOCK_SIZE )
359 {
360 uint64x2_t initial_sum, sum, intermed;
361
362 uint64x2_t ab_orig = ab;
363 uint64x2_t cd_orig = cd;
364 uint64x2_t ef_orig = ef;
365 uint64x2_t gh_orig = gh;
366
367 uint64x2_t s0 = (uint64x2_t) vld1q_u8( msg + 16 * 0 );
368 uint64x2_t s1 = (uint64x2_t) vld1q_u8( msg + 16 * 1 );
369 uint64x2_t s2 = (uint64x2_t) vld1q_u8( msg + 16 * 2 );
370 uint64x2_t s3 = (uint64x2_t) vld1q_u8( msg + 16 * 3 );
371 uint64x2_t s4 = (uint64x2_t) vld1q_u8( msg + 16 * 4 );
372 uint64x2_t s5 = (uint64x2_t) vld1q_u8( msg + 16 * 5 );
373 uint64x2_t s6 = (uint64x2_t) vld1q_u8( msg + 16 * 6 );
374 uint64x2_t s7 = (uint64x2_t) vld1q_u8( msg + 16 * 7 );
375
376#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* assume LE if these not defined; untested on BE */
377 s0 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s0 ) ) );
378 s1 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s1 ) ) );
379 s2 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s2 ) ) );
380 s3 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s3 ) ) );
381 s4 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s4 ) ) );
382 s5 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s5 ) ) );
383 s6 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s6 ) ) );
384 s7 = vreinterpretq_u64_u8( vrev64q_u8( vreinterpretq_u8_u64( s7 ) ) );
385#endif
386
387 /* Rounds 0 and 1 */
388 initial_sum = vaddq_u64( s0, vld1q_u64( &K[0] ) );
389 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
390 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
391 gh = vsha512h2q_u64( intermed, cd, ab );
392 cd = vaddq_u64( cd, intermed );
393
394 /* Rounds 2 and 3 */
395 initial_sum = vaddq_u64( s1, vld1q_u64( &K[2] ) );
396 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
397 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
398 ef = vsha512h2q_u64( intermed, ab, gh );
399 ab = vaddq_u64( ab, intermed );
400
401 /* Rounds 4 and 5 */
402 initial_sum = vaddq_u64( s2, vld1q_u64( &K[4] ) );
403 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
404 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
405 cd = vsha512h2q_u64( intermed, gh, ef );
406 gh = vaddq_u64( gh, intermed );
407
408 /* Rounds 6 and 7 */
409 initial_sum = vaddq_u64( s3, vld1q_u64( &K[6] ) );
410 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
411 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
412 ab = vsha512h2q_u64( intermed, ef, cd );
413 ef = vaddq_u64( ef, intermed );
414
415 /* Rounds 8 and 9 */
416 initial_sum = vaddq_u64( s4, vld1q_u64( &K[8] ) );
417 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
418 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
419 gh = vsha512h2q_u64( intermed, cd, ab );
420 cd = vaddq_u64( cd, intermed );
421
422 /* Rounds 10 and 11 */
423 initial_sum = vaddq_u64( s5, vld1q_u64( &K[10] ) );
424 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
425 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
426 ef = vsha512h2q_u64( intermed, ab, gh );
427 ab = vaddq_u64( ab, intermed );
428
429 /* Rounds 12 and 13 */
430 initial_sum = vaddq_u64( s6, vld1q_u64( &K[12] ) );
431 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
432 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
433 cd = vsha512h2q_u64( intermed, gh, ef );
434 gh = vaddq_u64( gh, intermed );
435
436 /* Rounds 14 and 15 */
437 initial_sum = vaddq_u64( s7, vld1q_u64( &K[14] ) );
438 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
439 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
440 ab = vsha512h2q_u64( intermed, ef, cd );
441 ef = vaddq_u64( ef, intermed );
442
443 for ( unsigned int t = 16; t < 80; t += 16 )
444 {
445 /* Rounds t and t + 1 */
446 s0 = vsha512su1q_u64( vsha512su0q_u64( s0, s1 ), s7, vextq_u64( s4, s5, 1 ) );
447 initial_sum = vaddq_u64( s0, vld1q_u64( &K[t] ) );
448 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
449 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
450 gh = vsha512h2q_u64( intermed, cd, ab );
451 cd = vaddq_u64( cd, intermed );
452
453 /* Rounds t + 2 and t + 3 */
454 s1 = vsha512su1q_u64( vsha512su0q_u64( s1, s2 ), s0, vextq_u64( s5, s6, 1 ) );
455 initial_sum = vaddq_u64( s1, vld1q_u64( &K[t + 2] ) );
456 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
457 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
458 ef = vsha512h2q_u64( intermed, ab, gh );
459 ab = vaddq_u64( ab, intermed );
460
461 /* Rounds t + 4 and t + 5 */
462 s2 = vsha512su1q_u64( vsha512su0q_u64( s2, s3 ), s1, vextq_u64( s6, s7, 1 ) );
463 initial_sum = vaddq_u64( s2, vld1q_u64( &K[t + 4] ) );
464 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
465 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
466 cd = vsha512h2q_u64( intermed, gh, ef );
467 gh = vaddq_u64( gh, intermed );
468
469 /* Rounds t + 6 and t + 7 */
470 s3 = vsha512su1q_u64( vsha512su0q_u64( s3, s4 ), s2, vextq_u64( s7, s0, 1 ) );
471 initial_sum = vaddq_u64( s3, vld1q_u64( &K[t + 6] ) );
472 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
473 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
474 ab = vsha512h2q_u64( intermed, ef, cd );
475 ef = vaddq_u64( ef, intermed );
476
477 /* Rounds t + 8 and t + 9 */
478 s4 = vsha512su1q_u64( vsha512su0q_u64( s4, s5 ), s3, vextq_u64( s0, s1, 1 ) );
479 initial_sum = vaddq_u64( s4, vld1q_u64( &K[t + 8] ) );
480 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), gh );
481 intermed = vsha512hq_u64( sum, vextq_u64( ef, gh, 1 ), vextq_u64( cd, ef, 1 ) );
482 gh = vsha512h2q_u64( intermed, cd, ab );
483 cd = vaddq_u64( cd, intermed );
484
485 /* Rounds t + 10 and t + 11 */
486 s5 = vsha512su1q_u64( vsha512su0q_u64( s5, s6 ), s4, vextq_u64( s1, s2, 1 ) );
487 initial_sum = vaddq_u64( s5, vld1q_u64( &K[t + 10] ) );
488 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ef );
489 intermed = vsha512hq_u64( sum, vextq_u64( cd, ef, 1 ), vextq_u64( ab, cd, 1 ) );
490 ef = vsha512h2q_u64( intermed, ab, gh );
491 ab = vaddq_u64( ab, intermed );
492
493 /* Rounds t + 12 and t + 13 */
494 s6 = vsha512su1q_u64( vsha512su0q_u64( s6, s7 ), s5, vextq_u64( s2, s3, 1 ) );
495 initial_sum = vaddq_u64( s6, vld1q_u64( &K[t + 12] ) );
496 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), cd );
497 intermed = vsha512hq_u64( sum, vextq_u64( ab, cd, 1 ), vextq_u64( gh, ab, 1 ) );
498 cd = vsha512h2q_u64( intermed, gh, ef );
499 gh = vaddq_u64( gh, intermed );
500
501 /* Rounds t + 14 and t + 15 */
502 s7 = vsha512su1q_u64( vsha512su0q_u64( s7, s0 ), s6, vextq_u64( s3, s4, 1 ) );
503 initial_sum = vaddq_u64( s7, vld1q_u64( &K[t + 14] ) );
504 sum = vaddq_u64( vextq_u64( initial_sum, initial_sum, 1 ), ab );
505 intermed = vsha512hq_u64( sum, vextq_u64( gh, ab, 1 ), vextq_u64( ef, gh, 1 ) );
506 ab = vsha512h2q_u64( intermed, ef, cd );
507 ef = vaddq_u64( ef, intermed );
508 }
509
510 ab = vaddq_u64( ab, ab_orig );
511 cd = vaddq_u64( cd, cd_orig );
512 ef = vaddq_u64( ef, ef_orig );
513 gh = vaddq_u64( gh, gh_orig );
514 }
515
516 vst1q_u64( &ctx->state[0], ab );
517 vst1q_u64( &ctx->state[2], cd );
518 vst1q_u64( &ctx->state[4], ef );
519 vst1q_u64( &ctx->state[6], gh );
520
521 return( processed );
522}
523
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100524#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
525/*
526 * This function is for internal use only if we are building both C and A64
527 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
528 */
529static
530#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000531int mbedtls_internal_sha512_process_a64_crypto( mbedtls_sha512_context *ctx,
532 const unsigned char data[SHA512_BLOCK_SIZE] )
533{
534 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, data,
535 SHA512_BLOCK_SIZE ) == SHA512_BLOCK_SIZE ) ? 0 : -1;
536}
537
538#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
539
540
541#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
542#define mbedtls_internal_sha512_process_many_c mbedtls_internal_sha512_process_many
543#define mbedtls_internal_sha512_process_c mbedtls_internal_sha512_process
544#endif
545
546
547#if !defined(MBEDTLS_SHA512_PROCESS_ALT) && !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
548
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100549#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
550/*
551 * This function is for internal use only if we are building both C and A64
552 * versions, otherwise it is renamed to be the public mbedtls_internal_sha512_process()
553 */
554static
555#endif
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000556int mbedtls_internal_sha512_process_c( mbedtls_sha512_context *ctx,
557 const unsigned char data[SHA512_BLOCK_SIZE] )
Paul Bakker5121ce52009-01-03 21:22:43 +0000558{
559 int i;
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200560 struct
561 {
562 uint64_t temp1, temp2, W[80];
563 uint64_t A[8];
564 } local;
Paul Bakker5121ce52009-01-03 21:22:43 +0000565
Hanno Becker1eeca412018-10-15 12:01:35 +0100566#define SHR(x,n) ((x) >> (n))
Hanno Becker26d02e12018-10-30 09:29:25 +0000567#define ROTR(x,n) (SHR((x),(n)) | ((x) << (64 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000568
569#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7))
570#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6))
571
572#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39))
573#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41))
574
Hanno Becker1eeca412018-10-15 12:01:35 +0100575#define F0(x,y,z) (((x) & (y)) | ((z) & ((x) | (y))))
576#define F1(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000577
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200578#define P(a,b,c,d,e,f,g,h,x,K) \
579 do \
580 { \
581 local.temp1 = (h) + S3(e) + F1((e),(f),(g)) + (K) + (x); \
582 local.temp2 = S2(a) + F0((a),(b),(c)); \
583 (d) += local.temp1; (h) = local.temp1 + local.temp2; \
Hanno Becker1eeca412018-10-15 12:01:35 +0100584 } while( 0 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000585
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200586 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200587 local.A[i] = ctx->state[i];
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200588
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200589#if defined(MBEDTLS_SHA512_SMALLER)
590 for( i = 0; i < 80; i++ )
591 {
592 if( i < 16 )
593 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100594 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200595 }
596 else
597 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200598 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
599 S0(local.W[i - 15]) + local.W[i - 16];
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200600 }
601
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200602 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
603 local.A[5], local.A[6], local.A[7], local.W[i], K[i] );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200604
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200605 local.temp1 = local.A[7]; local.A[7] = local.A[6];
606 local.A[6] = local.A[5]; local.A[5] = local.A[4];
607 local.A[4] = local.A[3]; local.A[3] = local.A[2];
608 local.A[2] = local.A[1]; local.A[1] = local.A[0];
609 local.A[0] = local.temp1;
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200610 }
611#else /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000612 for( i = 0; i < 16; i++ )
613 {
Joe Subbiani99edd6c2021-07-16 12:29:49 +0100614 local.W[i] = MBEDTLS_GET_UINT64_BE( data, i << 3 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000615 }
616
617 for( ; i < 80; i++ )
618 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200619 local.W[i] = S1(local.W[i - 2]) + local.W[i - 7] +
620 S0(local.W[i - 15]) + local.W[i - 16];
Paul Bakker5121ce52009-01-03 21:22:43 +0000621 }
622
Paul Bakker5121ce52009-01-03 21:22:43 +0000623 i = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000624 do
625 {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200626 P( local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
627 local.A[5], local.A[6], local.A[7], local.W[i], K[i] ); i++;
628 P( local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
629 local.A[4], local.A[5], local.A[6], local.W[i], K[i] ); i++;
630 P( local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
631 local.A[3], local.A[4], local.A[5], local.W[i], K[i] ); i++;
632 P( local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
633 local.A[2], local.A[3], local.A[4], local.W[i], K[i] ); i++;
634 P( local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
635 local.A[1], local.A[2], local.A[3], local.W[i], K[i] ); i++;
636 P( local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
637 local.A[0], local.A[1], local.A[2], local.W[i], K[i] ); i++;
638 P( local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
639 local.A[7], local.A[0], local.A[1], local.W[i], K[i] ); i++;
640 P( local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
641 local.A[6], local.A[7], local.A[0], local.W[i], K[i] ); i++;
Paul Bakker5121ce52009-01-03 21:22:43 +0000642 }
643 while( i < 80 );
Manuel Pégourié-Gonnard49d65ba2019-07-17 13:16:54 +0200644#endif /* MBEDTLS_SHA512_SMALLER */
Paul Bakker5121ce52009-01-03 21:22:43 +0000645
Manuel Pégourié-Gonnard0270ed92019-07-17 13:01:56 +0200646 for( i = 0; i < 8; i++ )
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200647 ctx->state[i] += local.A[i];
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100648
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200649 /* Zeroise buffers and variables to clear sensitive data from memory. */
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200650 mbedtls_platform_zeroize( &local, sizeof( local ) );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100651
652 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000653}
Jaeden Amero041039f2018-02-19 15:28:08 +0000654
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000655#endif /* !MBEDTLS_SHA512_PROCESS_ALT && !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
656
657
658#if !defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY)
659
660static size_t mbedtls_internal_sha512_process_many_c(
661 mbedtls_sha512_context *ctx, const uint8_t *data, size_t len)
662{
663 size_t processed = 0;
664
665 while( len >= SHA512_BLOCK_SIZE )
666 {
667 if( mbedtls_internal_sha512_process_c( ctx, data ) != 0)
668 return( 0 );
669
670 data += SHA512_BLOCK_SIZE;
671 len -= SHA512_BLOCK_SIZE;
672
673 processed += SHA512_BLOCK_SIZE;
674 }
675
676 return( processed );
677}
678
679#endif /* !MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY */
680
681
682#if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT)
683
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100684static int mbedtls_a64_crypto_sha512_has_support( void )
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000685{
686 static int done = 0;
687 static int supported = 0;
688
689 if( !done )
690 {
691 supported = mbedtls_a64_crypto_sha512_determine_support();
692 done = 1;
693 }
694
695 return( supported );
696}
697
698static size_t mbedtls_internal_sha512_process_many( mbedtls_sha512_context *ctx,
699 const uint8_t *msg, size_t len )
700{
701 if( mbedtls_a64_crypto_sha512_has_support() )
702 return( mbedtls_internal_sha512_process_many_a64_crypto( ctx, msg, len ) );
703 else
704 return( mbedtls_internal_sha512_process_many_c( ctx, msg, len ) );
705}
706
707int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx,
708 const unsigned char data[SHA512_BLOCK_SIZE] )
709{
710 if( mbedtls_a64_crypto_sha512_has_support() )
711 return( mbedtls_internal_sha512_process_a64_crypto( ctx, data ) );
712 else
713 return( mbedtls_internal_sha512_process_c( ctx, data ) );
714}
715
716#endif /* MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT */
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
718/*
719 * SHA-512 process buffer
720 */
TRodziewicz26371e42021-06-08 16:45:41 +0200721int mbedtls_sha512_update( mbedtls_sha512_context *ctx,
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100722 const unsigned char *input,
723 size_t ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000724{
Janos Follath24eed8d2019-11-22 13:21:35 +0000725 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000726 size_t fill;
Paul Bakkerb8213a12011-07-11 08:16:18 +0000727 unsigned int left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000728
Brian White12895d12014-04-11 11:29:42 -0400729 if( ilen == 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100730 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000731
Paul Bakkerb8213a12011-07-11 08:16:18 +0000732 left = (unsigned int) (ctx->total[0] & 0x7F);
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000733 fill = SHA512_BLOCK_SIZE - left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000734
Paul Bakker5c2364c2012-10-01 14:41:15 +0000735 ctx->total[0] += (uint64_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000736
Paul Bakker5c2364c2012-10-01 14:41:15 +0000737 if( ctx->total[0] < (uint64_t) ilen )
Paul Bakker5121ce52009-01-03 21:22:43 +0000738 ctx->total[1]++;
739
740 if( left && ilen >= fill )
741 {
Paul Bakker3c2122f2013-06-24 19:03:14 +0200742 memcpy( (void *) (ctx->buffer + left), input, fill );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100743
Andres Amaya Garciacccfe082017-06-28 10:36:39 +0100744 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100745 return( ret );
746
Paul Bakker5121ce52009-01-03 21:22:43 +0000747 input += fill;
748 ilen -= fill;
749 left = 0;
750 }
751
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000752 while( ilen >= SHA512_BLOCK_SIZE )
Paul Bakker5121ce52009-01-03 21:22:43 +0000753 {
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000754 size_t processed =
755 mbedtls_internal_sha512_process_many( ctx, input, ilen );
756 if( processed < SHA512_BLOCK_SIZE )
757 return( MBEDTLS_ERR_ERROR_GENERIC_ERROR );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100758
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000759 input += processed;
760 ilen -= processed;
Paul Bakker5121ce52009-01-03 21:22:43 +0000761 }
762
763 if( ilen > 0 )
Paul Bakker3c2122f2013-06-24 19:03:14 +0200764 memcpy( (void *) (ctx->buffer + left), input, ilen );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100765
766 return( 0 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000767}
768
Paul Bakker5121ce52009-01-03 21:22:43 +0000769/*
770 * SHA-512 final digest
771 */
TRodziewicz26371e42021-06-08 16:45:41 +0200772int mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
Gilles Peskinee02e02f2021-05-13 00:22:35 +0200773 unsigned char *output )
Paul Bakker5121ce52009-01-03 21:22:43 +0000774{
Janos Follath24eed8d2019-11-22 13:21:35 +0000775 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200776 unsigned used;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000777 uint64_t high, low;
Paul Bakker5121ce52009-01-03 21:22:43 +0000778
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200779 /*
780 * Add padding: 0x80 then 0x00 until 16 bytes remain for the length
781 */
782 used = ctx->total[0] & 0x7F;
783
784 ctx->buffer[used++] = 0x80;
785
786 if( used <= 112 )
787 {
788 /* Enough room for padding + length in current block */
789 memset( ctx->buffer + used, 0, 112 - used );
790 }
791 else
792 {
793 /* We'll need an extra block */
Tom Cosgrove87fbfb52022-03-15 10:51:52 +0000794 memset( ctx->buffer + used, 0, SHA512_BLOCK_SIZE - used );
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200795
796 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
797 return( ret );
798
799 memset( ctx->buffer, 0, 112 );
800 }
801
802 /*
803 * Add message length
804 */
Paul Bakker5121ce52009-01-03 21:22:43 +0000805 high = ( ctx->total[0] >> 61 )
806 | ( ctx->total[1] << 3 );
807 low = ( ctx->total[0] << 3 );
808
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200809 sha512_put_uint64_be( high, ctx->buffer, 112 );
810 sha512_put_uint64_be( low, ctx->buffer, 120 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000811
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200812 if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 )
813 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000814
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200815 /*
816 * Output final state
817 */
Manuel Pégourié-Gonnard7f071952019-07-17 12:46:56 +0200818 sha512_put_uint64_be( ctx->state[0], output, 0 );
819 sha512_put_uint64_be( ctx->state[1], output, 8 );
820 sha512_put_uint64_be( ctx->state[2], output, 16 );
821 sha512_put_uint64_be( ctx->state[3], output, 24 );
822 sha512_put_uint64_be( ctx->state[4], output, 32 );
823 sha512_put_uint64_be( ctx->state[5], output, 40 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000824
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200825#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000826 if( ctx->is384 == 0 )
Manuel Pégourié-Gonnard3df4e602019-07-17 15:16:14 +0200827#endif
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)
Hanno Becker38e15d42018-12-18 17:54:00 +0000850 SHA512_VALIDATE_RET( is384 == 0 || is384 == 1 );
Manuel Pégourié-Gonnard0b9db442020-01-07 10:14:54 +0100851#else
852 SHA512_VALIDATE_RET( is384 == 0 );
853#endif
Andres Amaya Garciaba519b92018-12-09 20:58:36 +0000854
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200855 mbedtls_sha512_init( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100856
TRodziewicz26371e42021-06-08 16:45:41 +0200857 if( ( ret = mbedtls_sha512_starts( &ctx, is384 ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100858 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100859
TRodziewicz26371e42021-06-08 16:45:41 +0200860 if( ( ret = mbedtls_sha512_update( &ctx, input, ilen ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100861 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100862
TRodziewicz26371e42021-06-08 16:45:41 +0200863 if( ( ret = mbedtls_sha512_finish( &ctx, output ) ) != 0 )
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100864 goto exit;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100865
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100866exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200867 mbedtls_sha512_free( &ctx );
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100868
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100869 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +0000870}
871
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200872#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000873
874/*
875 * FIPS-180-2 test vectors
876 */
Manuel Pégourié-Gonnard28122e42015-03-11 09:13:42 +0000877static const unsigned char sha512_test_buf[3][113] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000878{
879 { "abc" },
Guido Vranken962e4ee2020-08-21 21:08:56 +0200880 { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" },
Paul Bakker5121ce52009-01-03 21:22:43 +0000881 { "" }
882};
883
Andres Amaya Garcia2d0aa8b2017-07-21 14:57:26 +0100884static const size_t sha512_test_buflen[3] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000885{
886 3, 112, 1000
887};
888
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200889static const unsigned char sha512_test_sum[][64] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000890{
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200891#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000892 /*
893 * SHA-384 test vectors
894 */
895 { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B,
896 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07,
897 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63,
898 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED,
899 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23,
900 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 },
901 { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8,
902 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47,
903 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2,
904 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12,
905 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9,
906 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 },
907 { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB,
908 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C,
909 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52,
910 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B,
911 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB,
912 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 },
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200913#endif /* MBEDTLS_SHA384_C */
Paul Bakker5121ce52009-01-03 21:22:43 +0000914
915 /*
916 * SHA-512 test vectors
917 */
918 { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA,
919 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31,
920 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2,
921 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A,
922 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8,
923 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD,
924 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E,
925 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F },
926 { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA,
927 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F,
928 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1,
929 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18,
930 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4,
931 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A,
932 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54,
933 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 },
934 { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64,
935 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63,
936 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28,
937 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB,
938 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A,
939 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B,
940 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E,
941 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B }
942};
943
Manuel Pégourié-Gonnard74ca84a2020-01-29 09:46:49 +0100944#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( ( a )[0] ) )
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200945
Paul Bakker5121ce52009-01-03 21:22:43 +0000946/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000947 * Checkup routine
948 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200949int mbedtls_sha512_self_test( int verbose )
Paul Bakker5121ce52009-01-03 21:22:43 +0000950{
Paul Bakker5b4af392014-06-26 12:09:34 +0200951 int i, j, k, buflen, ret = 0;
Russ Butlerbb83b422016-10-12 17:36:50 -0500952 unsigned char *buf;
Paul Bakker9e36f042013-06-30 14:34:05 +0200953 unsigned char sha512sum[64];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200954 mbedtls_sha512_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000955
Russ Butlerbb83b422016-10-12 17:36:50 -0500956 buf = mbedtls_calloc( 1024, sizeof(unsigned char) );
957 if( NULL == buf )
958 {
959 if( verbose != 0 )
960 mbedtls_printf( "Buffer allocation failed\n" );
961
962 return( 1 );
963 }
964
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200965 mbedtls_sha512_init( &ctx );
Paul Bakker5b4af392014-06-26 12:09:34 +0200966
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +0100967 for( i = 0; i < (int) ARRAY_LENGTH(sha512_test_sum); i++ )
Paul Bakker5121ce52009-01-03 21:22:43 +0000968 {
969 j = i % 3;
Mateusz Starzyk3352a532021-04-06 14:28:22 +0200970#if defined(MBEDTLS_SHA384_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000971 k = i < 3;
Manuel Pégourié-Gonnard39ea19a2019-07-17 15:36:23 +0200972#else
973 k = 0;
974#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000975
976 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200977 mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 );
Paul Bakker5121ce52009-01-03 21:22:43 +0000978
TRodziewicz26371e42021-06-08 16:45:41 +0200979 if( ( ret = mbedtls_sha512_starts( &ctx, k ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100980 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +0000981
982 if( j == 2 )
983 {
984 memset( buf, 'a', buflen = 1000 );
985
986 for( j = 0; j < 1000; j++ )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100987 {
TRodziewicz26371e42021-06-08 16:45:41 +0200988 ret = mbedtls_sha512_update( &ctx, buf, buflen );
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100989 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100990 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100991 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000992 }
993 else
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100994 {
TRodziewicz26371e42021-06-08 16:45:41 +0200995 ret = mbedtls_sha512_update( &ctx, sha512_test_buf[j],
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100996 sha512_test_buflen[j] );
997 if( ret != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +0100998 goto fail;
999 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001000
TRodziewicz26371e42021-06-08 16:45:41 +02001001 if( ( ret = mbedtls_sha512_finish( &ctx, sha512sum ) ) != 0 )
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001002 goto fail;
Paul Bakker5121ce52009-01-03 21:22:43 +00001003
Paul Bakker9e36f042013-06-30 14:34:05 +02001004 if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 )
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001005 {
1006 ret = 1;
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001007 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +01001008 }
Paul Bakker5121ce52009-01-03 21:22:43 +00001009
1010 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001011 mbedtls_printf( "passed\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001012 }
1013
1014 if( verbose != 0 )
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001015 mbedtls_printf( "\n" );
Paul Bakker5121ce52009-01-03 21:22:43 +00001016
Andres Amaya Garcia614c6892017-05-02 12:07:26 +01001017 goto exit;
1018
1019fail:
1020 if( verbose != 0 )
1021 mbedtls_printf( "failed\n" );
1022
Paul Bakker5b4af392014-06-26 12:09:34 +02001023exit:
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001024 mbedtls_sha512_free( &ctx );
Russ Butlerbb83b422016-10-12 17:36:50 -05001025 mbedtls_free( buf );
Paul Bakker5b4af392014-06-26 12:09:34 +02001026
1027 return( ret );
Paul Bakker5121ce52009-01-03 21:22:43 +00001028}
1029
Manuel Pégourié-Gonnard2b9b7802020-01-24 11:01:02 +01001030#undef ARRAY_LENGTH
Manuel Pégourié-Gonnard2d885492020-01-07 10:17:35 +01001031
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001032#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +00001033
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +02001034#endif /* MBEDTLS_SHA512_C */