blob: f0eb6ad58cb7a6a23d274153b196f57347658de0 [file] [log] [blame]
Paul Bakker5121ce52009-01-03 21:22:43 +00001/*
2 * FIPS-180-2 compliant SHA-256 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-256 Secure Hash Standard was published by NIST in 2002.
21 *
22 * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
23 */
24
Jerry Yua135dee2023-02-16 16:56:22 +080025#if defined(__aarch64__) && !defined(__ARM_FEATURE_CRYPTO) && \
Jerry Yu6f86c192023-03-13 11:03:40 +080026 defined(__clang__) && __clang_major__ >= 4
Jerry Yua135dee2023-02-16 16:56:22 +080027/* TODO: Re-consider above after https://reviews.llvm.org/D131064 merged.
28 *
Jerry Yufc2e1282023-02-27 11:16:56 +080029 * The intrinsic declaration are guarded by predefined ACLE macros in clang:
30 * these are normally only enabled by the -march option on the command line.
31 * By defining the macros ourselves we gain access to those declarations without
32 * requiring -march on the command line.
Jerry Yu4d786a72023-02-22 11:01:07 +080033 *
Jerry Yufc2e1282023-02-27 11:16:56 +080034 * `arm_neon.h` could be included by any header file, so we put these defines
35 * at the top of this file, before any includes.
Jerry Yua135dee2023-02-16 16:56:22 +080036 */
37#define __ARM_FEATURE_CRYPTO 1
Jerry Yuae129c32023-03-03 15:55:56 +080038/* See: https://arm-software.github.io/acle/main/acle.html#cryptographic-extensions
39 *
Jerry Yu490bf082023-03-06 15:21:44 +080040 * `__ARM_FEATURE_CRYPTO` is deprecated, but we need to continue to specify it
41 * for older compilers.
Jerry Yuae129c32023-03-03 15:55:56 +080042 */
43#define __ARM_FEATURE_SHA2 1
Dave Rodgmandb6ab242023-03-14 16:03:57 +000044#define MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG
Jerry Yu490bf082023-03-06 15:21:44 +080045#endif
Jerry Yua135dee2023-02-16 16:56:22 +080046
Gilles Peskinedb09ef62020-06-03 01:43:33 +020047#include "common.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000048
Valerio Settia3f99592022-12-14 10:56:54 +010049#if defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA224_C)
Paul Bakker5121ce52009-01-03 21:22:43 +000050
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000051#include "mbedtls/sha256.h"
Andres Amaya Garcia1f6301b2018-04-17 09:51:09 -050052#include "mbedtls/platform_util.h"
Janos Follath24eed8d2019-11-22 13:21:35 +000053#include "mbedtls/error.h"
Paul Bakker5121ce52009-01-03 21:22:43 +000054
Rich Evans00ab4702015-02-06 13:43:58 +000055#include <string.h>
56
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000057#include "mbedtls/platform.h"
Paul Bakker7dc4c442014-02-01 22:50:26 +010058
Dave Rodgmancc5bf492023-10-03 18:02:56 +010059#if defined(MBEDTLS_ARCH_IS_ARMV8)
Jerry Yu08933d32023-04-27 18:28:00 +080060
Tom Cosgrovef3ebd902022-02-20 22:25:31 +000061# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
Gilles Peskine449bd832023-01-11 14:50:10 +010062 defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
Jerry Yu08933d32023-04-27 18:28:00 +080063
Jerry Yu35f2b262023-02-15 11:35:55 +080064/* *INDENT-OFF* */
Jerry Yu6b00f5a2023-05-04 16:30:21 +080065
66# ifdef __ARM_NEON
67# include <arm_neon.h>
68# else
69# error "Target does not support NEON instructions"
70# endif
71
Dave Rodgman793e2642023-10-04 17:36:20 +010072# if !defined(__ARM_FEATURE_CRYPTO) || defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG)
Jerry Yub1d06bb2023-05-05 14:05:07 +080073# if defined(__ARMCOMPILER_VERSION)
74# if __ARMCOMPILER_VERSION <= 6090000
75# error "Must use minimum -march=armv8-a+crypto for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
76# endif
77# pragma clang attribute push (__attribute__((target("sha2"))), apply_to=function)
78# define MBEDTLS_POP_TARGET_PRAGMA
79# elif defined(__clang__)
Jerry Yu383cbf42023-02-16 15:16:43 +080080# if __clang_major__ < 4
81# error "A more recent Clang is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
Jerry Yu64e5d4a2023-02-15 11:46:57 +080082# endif
Jerry Yub1d06bb2023-05-05 14:05:07 +080083# pragma clang attribute push (__attribute__((target("crypto"))), apply_to=function)
Jerry Yu64e5d4a2023-02-15 11:46:57 +080084# define MBEDTLS_POP_TARGET_PRAGMA
85# elif defined(__GNUC__)
Tom Cosgrovec15a2b92023-03-08 12:55:48 +000086 /* FIXME: GCC 5 claims to support Armv8 Crypto Extensions, but some
87 * intrinsics are missing. Missing intrinsics could be worked around.
Jerry Yu8ae6a012023-02-16 15:16:20 +080088 */
89# if __GNUC__ < 6
Jerry Yu64e5d4a2023-02-15 11:46:57 +080090# error "A more recent GCC is required for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
91# else
Jerry Yu2f2c0492023-02-16 14:24:46 +080092# pragma GCC push_options
Jerry Yu64e5d4a2023-02-15 11:46:57 +080093# pragma GCC target ("arch=armv8-a+crypto")
Jerry Yu2f2c0492023-02-16 14:24:46 +080094# define MBEDTLS_POP_TARGET_PRAGMA
Jerry Yu64e5d4a2023-02-15 11:46:57 +080095# endif
96# else
97# error "Only GCC and Clang supported for MBEDTLS_SHA256_USE_A64_CRYPTO_*"
98# endif
Jerry Yu35f2b262023-02-15 11:35:55 +080099# endif
100/* *INDENT-ON* */
Jerry Yu08933d32023-04-27 18:28:00 +0800101
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000102# endif
Tom Cosgroveb7f5b972022-03-15 11:26:55 +0000103# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
Dave Rodgmanebe42922023-10-04 17:36:44 +0100104# if defined(MBEDTLS_COMPILER_IS_GCC) && !defined(MBEDTLS_ARCH_IS_ARM64)
105# warning "GCC only supports aarch64 for MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT, using C code only"
106# undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
107# endif
Tom Cosgroveb7f5b972022-03-15 11:26:55 +0000108# if defined(__unix__)
109# if defined(__linux__)
Gilles Peskine449bd832023-01-11 14:50:10 +0100110/* Our preferred method of detection is getauxval() */
Tom Cosgroveb7f5b972022-03-15 11:26:55 +0000111# include <sys/auxv.h>
112# endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100113/* Use SIGILL on Unix, and fall back to it on Linux */
Tom Cosgroveb7f5b972022-03-15 11:26:55 +0000114# include <signal.h>
115# endif
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000116# endif
Tom Cosgroveb9987fc2022-02-21 12:26:11 +0000117#elif defined(_M_ARM64)
118# if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
Gilles Peskine449bd832023-01-11 14:50:10 +0100119 defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
Tom Cosgroveb9987fc2022-02-21 12:26:11 +0000120# include <arm64_neon.h>
121# endif
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000122#else
123# undef MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY
124# undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
125#endif
126
127#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
128/*
129 * Capability detection code comes early, so we can disable
130 * MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT if no detection mechanism found
131 */
132#if defined(HWCAP_SHA2)
Gilles Peskine449bd832023-01-11 14:50:10 +0100133static int mbedtls_a64_crypto_sha256_determine_support(void)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000134{
Gilles Peskine449bd832023-01-11 14:50:10 +0100135 return (getauxval(AT_HWCAP) & HWCAP_SHA2) ? 1 : 0;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000136}
137#elif defined(__APPLE__)
Gilles Peskine449bd832023-01-11 14:50:10 +0100138static int mbedtls_a64_crypto_sha256_determine_support(void)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000139{
Gilles Peskine449bd832023-01-11 14:50:10 +0100140 return 1;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000141}
Tom Cosgroveb9987fc2022-02-21 12:26:11 +0000142#elif defined(_M_ARM64)
143#define WIN32_LEAN_AND_MEAN
144#include <Windows.h>
145#include <processthreadsapi.h>
146
Gilles Peskine449bd832023-01-11 14:50:10 +0100147static int mbedtls_a64_crypto_sha256_determine_support(void)
Tom Cosgroveb9987fc2022-02-21 12:26:11 +0000148{
Gilles Peskine449bd832023-01-11 14:50:10 +0100149 return IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) ?
150 1 : 0;
Tom Cosgroveb9987fc2022-02-21 12:26:11 +0000151}
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000152#elif defined(__unix__) && defined(SIG_SETMASK)
153/* Detection with SIGILL, setjmp() and longjmp() */
154#include <signal.h>
155#include <setjmp.h>
156
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000157static jmp_buf return_from_sigill;
158
159/*
160 * A64 SHA256 support detection via SIGILL
161 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100162static void sigill_handler(int signal)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000163{
164 (void) signal;
Gilles Peskine449bd832023-01-11 14:50:10 +0100165 longjmp(return_from_sigill, 1);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000166}
167
Gilles Peskine449bd832023-01-11 14:50:10 +0100168static int mbedtls_a64_crypto_sha256_determine_support(void)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000169{
170 struct sigaction old_action, new_action;
171
172 sigset_t old_mask;
Gilles Peskine449bd832023-01-11 14:50:10 +0100173 if (sigprocmask(0, NULL, &old_mask)) {
174 return 0;
175 }
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000176
Gilles Peskine449bd832023-01-11 14:50:10 +0100177 sigemptyset(&new_action.sa_mask);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000178 new_action.sa_flags = 0;
179 new_action.sa_handler = sigill_handler;
180
Gilles Peskine449bd832023-01-11 14:50:10 +0100181 sigaction(SIGILL, &new_action, &old_action);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000182
183 static int ret = 0;
184
Gilles Peskine449bd832023-01-11 14:50:10 +0100185 if (setjmp(return_from_sigill) == 0) { /* First return only */
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000186 /* If this traps, we will return a second time from setjmp() with 1 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100187 asm ("sha256h q0, q0, v0.4s" : : : "v0");
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000188 ret = 1;
189 }
190
Gilles Peskine449bd832023-01-11 14:50:10 +0100191 sigaction(SIGILL, &old_action, NULL);
192 sigprocmask(SIG_SETMASK, &old_mask, NULL);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000193
Gilles Peskine449bd832023-01-11 14:50:10 +0100194 return ret;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000195}
196#else
197#warning "No mechanism to detect A64_CRYPTO found, using C code only"
198#undef MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
199#endif /* HWCAP_SHA2, __APPLE__, __unix__ && SIG_SETMASK */
200
201#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
202
Manuel Pégourié-Gonnard8b2641d2015-08-27 20:03:46 +0200203#if !defined(MBEDTLS_SHA256_ALT)
204
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000205#define SHA256_BLOCK_SIZE 64
206
Gilles Peskine449bd832023-01-11 14:50:10 +0100207void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +0200208{
Gilles Peskine449bd832023-01-11 14:50:10 +0100209 memset(ctx, 0, sizeof(mbedtls_sha256_context));
Paul Bakker5b4af392014-06-26 12:09:34 +0200210}
211
Gilles Peskine449bd832023-01-11 14:50:10 +0100212void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
Paul Bakker5b4af392014-06-26 12:09:34 +0200213{
Gilles Peskine449bd832023-01-11 14:50:10 +0100214 if (ctx == NULL) {
Paul Bakker5b4af392014-06-26 12:09:34 +0200215 return;
Gilles Peskine449bd832023-01-11 14:50:10 +0100216 }
Paul Bakker5b4af392014-06-26 12:09:34 +0200217
Gilles Peskine449bd832023-01-11 14:50:10 +0100218 mbedtls_platform_zeroize(ctx, sizeof(mbedtls_sha256_context));
Paul Bakker5b4af392014-06-26 12:09:34 +0200219}
220
Gilles Peskine449bd832023-01-11 14:50:10 +0100221void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
222 const mbedtls_sha256_context *src)
Manuel Pégourié-Gonnard16d412f2015-07-06 15:26:26 +0200223{
224 *dst = *src;
225}
226
Paul Bakker5121ce52009-01-03 21:22:43 +0000227/*
228 * SHA-256 context setup
229 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100230int mbedtls_sha256_starts(mbedtls_sha256_context *ctx, int is224)
Paul Bakker5121ce52009-01-03 21:22:43 +0000231{
Valerio Settia3f99592022-12-14 10:56:54 +0100232#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100233 if (is224 != 0 && is224 != 1) {
Tuvshinzaya Erdenekhuu696dfb62022-08-05 15:59:19 +0100234 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100235 }
Valerio Settia3f99592022-12-14 10:56:54 +0100236#elif defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100237 if (is224 != 0) {
Tuvshinzaya Erdenekhuu696dfb62022-08-05 15:59:19 +0100238 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100239 }
Valerio Settia3f99592022-12-14 10:56:54 +0100240#else /* defined MBEDTLS_SHA224_C only */
Gilles Peskine449bd832023-01-11 14:50:10 +0100241 if (is224 == 0) {
Valerio Settia3f99592022-12-14 10:56:54 +0100242 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100243 }
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200244#endif
245
Paul Bakker5121ce52009-01-03 21:22:43 +0000246 ctx->total[0] = 0;
247 ctx->total[1] = 0;
248
Gilles Peskine449bd832023-01-11 14:50:10 +0100249 if (is224 == 0) {
Valerio Settia3f99592022-12-14 10:56:54 +0100250#if defined(MBEDTLS_SHA256_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000251 ctx->state[0] = 0x6A09E667;
252 ctx->state[1] = 0xBB67AE85;
253 ctx->state[2] = 0x3C6EF372;
254 ctx->state[3] = 0xA54FF53A;
255 ctx->state[4] = 0x510E527F;
256 ctx->state[5] = 0x9B05688C;
257 ctx->state[6] = 0x1F83D9AB;
258 ctx->state[7] = 0x5BE0CD19;
Valerio Settia3f99592022-12-14 10:56:54 +0100259#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100260 } else {
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200261#if defined(MBEDTLS_SHA224_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000262 ctx->state[0] = 0xC1059ED8;
263 ctx->state[1] = 0x367CD507;
264 ctx->state[2] = 0x3070DD17;
265 ctx->state[3] = 0xF70E5939;
266 ctx->state[4] = 0xFFC00B31;
267 ctx->state[5] = 0x68581511;
268 ctx->state[6] = 0x64F98FA7;
269 ctx->state[7] = 0xBEFA4FA4;
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200270#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000271 }
272
Valerio Settia3f99592022-12-14 10:56:54 +0100273#if defined(MBEDTLS_SHA224_C)
Paul Bakker5121ce52009-01-03 21:22:43 +0000274 ctx->is224 = is224;
Valerio Settia3f99592022-12-14 10:56:54 +0100275#endif
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100276
Gilles Peskine449bd832023-01-11 14:50:10 +0100277 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000278}
279
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200280#if !defined(MBEDTLS_SHA256_PROCESS_ALT)
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200281static const uint32_t K[] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000282{
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200283 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5,
284 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5,
285 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3,
286 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174,
287 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC,
288 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA,
289 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7,
290 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967,
291 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13,
292 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85,
293 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3,
294 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070,
295 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5,
296 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3,
297 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208,
298 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2,
299};
Paul Bakker5121ce52009-01-03 21:22:43 +0000300
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000301#endif
302
303#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT) || \
304 defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
305
306#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
307# define mbedtls_internal_sha256_process_many_a64_crypto mbedtls_internal_sha256_process_many
308# define mbedtls_internal_sha256_process_a64_crypto mbedtls_internal_sha256_process
309#endif
310
311static size_t mbedtls_internal_sha256_process_many_a64_crypto(
Gilles Peskine449bd832023-01-11 14:50:10 +0100312 mbedtls_sha256_context *ctx, const uint8_t *msg, size_t len)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000313{
Gilles Peskine449bd832023-01-11 14:50:10 +0100314 uint32x4_t abcd = vld1q_u32(&ctx->state[0]);
315 uint32x4_t efgh = vld1q_u32(&ctx->state[4]);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000316
317 size_t processed = 0;
318
Gilles Peskine449bd832023-01-11 14:50:10 +0100319 for (;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000320 len >= SHA256_BLOCK_SIZE;
321 processed += SHA256_BLOCK_SIZE,
Gilles Peskine449bd832023-01-11 14:50:10 +0100322 msg += SHA256_BLOCK_SIZE,
323 len -= SHA256_BLOCK_SIZE) {
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000324 uint32x4_t tmp, abcd_prev;
325
326 uint32x4_t abcd_orig = abcd;
327 uint32x4_t efgh_orig = efgh;
328
Gilles Peskine449bd832023-01-11 14:50:10 +0100329 uint32x4_t sched0 = (uint32x4_t) vld1q_u8(msg + 16 * 0);
330 uint32x4_t sched1 = (uint32x4_t) vld1q_u8(msg + 16 * 1);
331 uint32x4_t sched2 = (uint32x4_t) vld1q_u8(msg + 16 * 2);
332 uint32x4_t sched3 = (uint32x4_t) vld1q_u8(msg + 16 * 3);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000333
334#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ /* Will be true if not defined */
335 /* Untested on BE */
Gilles Peskine449bd832023-01-11 14:50:10 +0100336 sched0 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched0)));
337 sched1 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched1)));
338 sched2 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched2)));
339 sched3 = vreinterpretq_u32_u8(vrev32q_u8(vreinterpretq_u8_u32(sched3)));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000340#endif
341
342 /* Rounds 0 to 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100343 tmp = vaddq_u32(sched0, vld1q_u32(&K[0]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000344 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100345 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
346 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000347
348 /* Rounds 4 to 7 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100349 tmp = vaddq_u32(sched1, vld1q_u32(&K[4]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000350 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100351 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
352 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000353
354 /* Rounds 8 to 11 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100355 tmp = vaddq_u32(sched2, vld1q_u32(&K[8]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000356 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100357 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
358 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000359
360 /* Rounds 12 to 15 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100361 tmp = vaddq_u32(sched3, vld1q_u32(&K[12]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000362 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100363 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
364 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000365
Gilles Peskine449bd832023-01-11 14:50:10 +0100366 for (int t = 16; t < 64; t += 16) {
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000367 /* Rounds t to t + 3 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100368 sched0 = vsha256su1q_u32(vsha256su0q_u32(sched0, sched1), sched2, sched3);
369 tmp = vaddq_u32(sched0, vld1q_u32(&K[t]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000370 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100371 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
372 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000373
374 /* Rounds t + 4 to t + 7 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100375 sched1 = vsha256su1q_u32(vsha256su0q_u32(sched1, sched2), sched3, sched0);
376 tmp = vaddq_u32(sched1, vld1q_u32(&K[t + 4]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000377 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100378 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
379 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000380
381 /* Rounds t + 8 to t + 11 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100382 sched2 = vsha256su1q_u32(vsha256su0q_u32(sched2, sched3), sched0, sched1);
383 tmp = vaddq_u32(sched2, vld1q_u32(&K[t + 8]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000384 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100385 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
386 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000387
388 /* Rounds t + 12 to t + 15 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100389 sched3 = vsha256su1q_u32(vsha256su0q_u32(sched3, sched0), sched1, sched2);
390 tmp = vaddq_u32(sched3, vld1q_u32(&K[t + 12]));
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000391 abcd_prev = abcd;
Gilles Peskine449bd832023-01-11 14:50:10 +0100392 abcd = vsha256hq_u32(abcd_prev, efgh, tmp);
393 efgh = vsha256h2q_u32(efgh, abcd_prev, tmp);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000394 }
395
Gilles Peskine449bd832023-01-11 14:50:10 +0100396 abcd = vaddq_u32(abcd, abcd_orig);
397 efgh = vaddq_u32(efgh, efgh_orig);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000398 }
399
Gilles Peskine449bd832023-01-11 14:50:10 +0100400 vst1q_u32(&ctx->state[0], abcd);
401 vst1q_u32(&ctx->state[4], efgh);
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000402
Gilles Peskine449bd832023-01-11 14:50:10 +0100403 return processed;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000404}
405
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100406#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
407/*
408 * This function is for internal use only if we are building both C and A64
409 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
410 */
411static
412#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100413int mbedtls_internal_sha256_process_a64_crypto(mbedtls_sha256_context *ctx,
414 const unsigned char data[SHA256_BLOCK_SIZE])
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000415{
Gilles Peskine449bd832023-01-11 14:50:10 +0100416 return (mbedtls_internal_sha256_process_many_a64_crypto(ctx, data,
417 SHA256_BLOCK_SIZE) ==
418 SHA256_BLOCK_SIZE) ? 0 : -1;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000419}
420
Tom Cosgroveef2aa0e2023-06-09 11:29:50 +0100421#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT || MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
422
Jerry Yu92fc5382023-02-16 11:17:11 +0800423#if defined(MBEDTLS_POP_TARGET_PRAGMA)
Jerry Yu2f2c0492023-02-16 14:24:46 +0800424#if defined(__clang__)
Jerry Yu92fc5382023-02-16 11:17:11 +0800425#pragma clang attribute pop
Jerry Yu2f2c0492023-02-16 14:24:46 +0800426#elif defined(__GNUC__)
427#pragma GCC pop_options
428#endif
Jerry Yu92fc5382023-02-16 11:17:11 +0800429#undef MBEDTLS_POP_TARGET_PRAGMA
430#endif
431
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000432#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
433#define mbedtls_internal_sha256_process_many_c mbedtls_internal_sha256_process_many
434#define mbedtls_internal_sha256_process_c mbedtls_internal_sha256_process
435#endif
436
437
438#if !defined(MBEDTLS_SHA256_PROCESS_ALT) && \
439 !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
440
Gilles Peskine449bd832023-01-11 14:50:10 +0100441#define SHR(x, n) (((x) & 0xFFFFFFFF) >> (n))
442#define ROTR(x, n) (SHR(x, n) | ((x) << (32 - (n))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000443
Gilles Peskine449bd832023-01-11 14:50:10 +0100444#define S0(x) (ROTR(x, 7) ^ ROTR(x, 18) ^ SHR(x, 3))
445#define S1(x) (ROTR(x, 17) ^ ROTR(x, 19) ^ SHR(x, 10))
Paul Bakker5121ce52009-01-03 21:22:43 +0000446
Gilles Peskine449bd832023-01-11 14:50:10 +0100447#define S2(x) (ROTR(x, 2) ^ ROTR(x, 13) ^ ROTR(x, 22))
448#define S3(x) (ROTR(x, 6) ^ ROTR(x, 11) ^ ROTR(x, 25))
Paul Bakker5121ce52009-01-03 21:22:43 +0000449
Gilles Peskine449bd832023-01-11 14:50:10 +0100450#define F0(x, y, z) (((x) & (y)) | ((z) & ((x) | (y))))
451#define F1(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))
Paul Bakker5121ce52009-01-03 21:22:43 +0000452
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200453#define R(t) \
454 ( \
455 local.W[t] = S1(local.W[(t) - 2]) + local.W[(t) - 7] + \
456 S0(local.W[(t) - 15]) + local.W[(t) - 16] \
Hanno Becker1eeca412018-10-15 12:01:35 +0100457 )
Paul Bakker5121ce52009-01-03 21:22:43 +0000458
Gilles Peskine449bd832023-01-11 14:50:10 +0100459#define P(a, b, c, d, e, f, g, h, x, K) \
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200460 do \
461 { \
Gilles Peskine449bd832023-01-11 14:50:10 +0100462 local.temp1 = (h) + S3(e) + F1((e), (f), (g)) + (K) + (x); \
463 local.temp2 = S2(a) + F0((a), (b), (c)); \
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200464 (d) += local.temp1; (h) = local.temp1 + local.temp2; \
Gilles Peskine449bd832023-01-11 14:50:10 +0100465 } while (0)
Paul Bakker5121ce52009-01-03 21:22:43 +0000466
Tom Cosgrovec144ca62022-04-19 13:52:24 +0100467#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
468/*
469 * This function is for internal use only if we are building both C and A64
470 * versions, otherwise it is renamed to be the public mbedtls_internal_sha256_process()
471 */
472static
473#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100474int mbedtls_internal_sha256_process_c(mbedtls_sha256_context *ctx,
475 const unsigned char data[SHA256_BLOCK_SIZE])
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200476{
Gilles Peskine449bd832023-01-11 14:50:10 +0100477 struct {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200478 uint32_t temp1, temp2, W[64];
479 uint32_t A[8];
480 } local;
481
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200482 unsigned int i;
Paul Bakker5121ce52009-01-03 21:22:43 +0000483
Gilles Peskine449bd832023-01-11 14:50:10 +0100484 for (i = 0; i < 8; i++) {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200485 local.A[i] = ctx->state[i];
Gilles Peskine449bd832023-01-11 14:50:10 +0100486 }
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200487
Manuel Pégourié-Gonnardeb0d8702015-05-28 12:54:04 +0200488#if defined(MBEDTLS_SHA256_SMALLER)
Gilles Peskine449bd832023-01-11 14:50:10 +0100489 for (i = 0; i < 64; i++) {
490 if (i < 16) {
491 local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
492 } else {
493 R(i);
494 }
Manuel Pégourié-Gonnardeb0d8702015-05-28 12:54:04 +0200495
Gilles Peskine449bd832023-01-11 14:50:10 +0100496 P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
497 local.A[5], local.A[6], local.A[7], local.W[i], K[i]);
Manuel Pégourié-Gonnardeb0d8702015-05-28 12:54:04 +0200498
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200499 local.temp1 = local.A[7]; local.A[7] = local.A[6];
500 local.A[6] = local.A[5]; local.A[5] = local.A[4];
501 local.A[4] = local.A[3]; local.A[3] = local.A[2];
502 local.A[2] = local.A[1]; local.A[1] = local.A[0];
503 local.A[0] = local.temp1;
Manuel Pégourié-Gonnardeb0d8702015-05-28 12:54:04 +0200504 }
505#else /* MBEDTLS_SHA256_SMALLER */
Gilles Peskine449bd832023-01-11 14:50:10 +0100506 for (i = 0; i < 16; i++) {
507 local.W[i] = MBEDTLS_GET_UINT32_BE(data, 4 * i);
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200508 }
509
Gilles Peskine449bd832023-01-11 14:50:10 +0100510 for (i = 0; i < 16; i += 8) {
511 P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
512 local.A[5], local.A[6], local.A[7], local.W[i+0], K[i+0]);
513 P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
514 local.A[4], local.A[5], local.A[6], local.W[i+1], K[i+1]);
515 P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
516 local.A[3], local.A[4], local.A[5], local.W[i+2], K[i+2]);
517 P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
518 local.A[2], local.A[3], local.A[4], local.W[i+3], K[i+3]);
519 P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
520 local.A[1], local.A[2], local.A[3], local.W[i+4], K[i+4]);
521 P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
522 local.A[0], local.A[1], local.A[2], local.W[i+5], K[i+5]);
523 P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
524 local.A[7], local.A[0], local.A[1], local.W[i+6], K[i+6]);
525 P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
526 local.A[6], local.A[7], local.A[0], local.W[i+7], K[i+7]);
527 }
528
529 for (i = 16; i < 64; i += 8) {
530 P(local.A[0], local.A[1], local.A[2], local.A[3], local.A[4],
531 local.A[5], local.A[6], local.A[7], R(i+0), K[i+0]);
532 P(local.A[7], local.A[0], local.A[1], local.A[2], local.A[3],
533 local.A[4], local.A[5], local.A[6], R(i+1), K[i+1]);
534 P(local.A[6], local.A[7], local.A[0], local.A[1], local.A[2],
535 local.A[3], local.A[4], local.A[5], R(i+2), K[i+2]);
536 P(local.A[5], local.A[6], local.A[7], local.A[0], local.A[1],
537 local.A[2], local.A[3], local.A[4], R(i+3), K[i+3]);
538 P(local.A[4], local.A[5], local.A[6], local.A[7], local.A[0],
539 local.A[1], local.A[2], local.A[3], R(i+4), K[i+4]);
540 P(local.A[3], local.A[4], local.A[5], local.A[6], local.A[7],
541 local.A[0], local.A[1], local.A[2], R(i+5), K[i+5]);
542 P(local.A[2], local.A[3], local.A[4], local.A[5], local.A[6],
543 local.A[7], local.A[0], local.A[1], R(i+6), K[i+6]);
544 P(local.A[1], local.A[2], local.A[3], local.A[4], local.A[5],
545 local.A[6], local.A[7], local.A[0], R(i+7), K[i+7]);
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200546 }
Manuel Pégourié-Gonnardeb0d8702015-05-28 12:54:04 +0200547#endif /* MBEDTLS_SHA256_SMALLER */
Manuel Pégourié-Gonnarda7a3a5f2015-05-28 12:14:49 +0200548
Gilles Peskine449bd832023-01-11 14:50:10 +0100549 for (i = 0; i < 8; i++) {
gabor-mezei-arm4cb56f82020-08-25 19:12:01 +0200550 ctx->state[i] += local.A[i];
Gilles Peskine449bd832023-01-11 14:50:10 +0100551 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100552
gabor-mezei-arm76749ae2020-07-30 16:41:25 +0200553 /* Zeroise buffers and variables to clear sensitive data from memory. */
Gilles Peskine449bd832023-01-11 14:50:10 +0100554 mbedtls_platform_zeroize(&local, sizeof(local));
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100555
Gilles Peskine449bd832023-01-11 14:50:10 +0100556 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000557}
Jaeden Amero041039f2018-02-19 15:28:08 +0000558
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000559#endif /* !MBEDTLS_SHA256_PROCESS_ALT && !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
560
561
562#if !defined(MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY)
563
564static size_t mbedtls_internal_sha256_process_many_c(
Gilles Peskine449bd832023-01-11 14:50:10 +0100565 mbedtls_sha256_context *ctx, const uint8_t *data, size_t len)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000566{
567 size_t processed = 0;
568
Gilles Peskine449bd832023-01-11 14:50:10 +0100569 while (len >= SHA256_BLOCK_SIZE) {
570 if (mbedtls_internal_sha256_process_c(ctx, data) != 0) {
571 return 0;
572 }
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000573
574 data += SHA256_BLOCK_SIZE;
575 len -= SHA256_BLOCK_SIZE;
576
577 processed += SHA256_BLOCK_SIZE;
578 }
579
Gilles Peskine449bd832023-01-11 14:50:10 +0100580 return processed;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000581}
582
583#endif /* !MBEDTLS_SHA256_USE_A64_CRYPTO_ONLY */
584
585
586#if defined(MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT)
587
Gilles Peskine449bd832023-01-11 14:50:10 +0100588static int mbedtls_a64_crypto_sha256_has_support(void)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000589{
590 static int done = 0;
591 static int supported = 0;
592
Gilles Peskine449bd832023-01-11 14:50:10 +0100593 if (!done) {
Tom Cosgrove7e7aba82022-02-24 08:33:11 +0000594 supported = mbedtls_a64_crypto_sha256_determine_support();
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000595 done = 1;
596 }
597
Gilles Peskine449bd832023-01-11 14:50:10 +0100598 return supported;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000599}
600
Gilles Peskine449bd832023-01-11 14:50:10 +0100601static size_t mbedtls_internal_sha256_process_many(mbedtls_sha256_context *ctx,
602 const uint8_t *msg, size_t len)
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000603{
Gilles Peskine449bd832023-01-11 14:50:10 +0100604 if (mbedtls_a64_crypto_sha256_has_support()) {
605 return mbedtls_internal_sha256_process_many_a64_crypto(ctx, msg, len);
606 } else {
607 return mbedtls_internal_sha256_process_many_c(ctx, msg, len);
608 }
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000609}
610
Gilles Peskine449bd832023-01-11 14:50:10 +0100611int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx,
612 const unsigned char data[SHA256_BLOCK_SIZE])
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000613{
Gilles Peskine449bd832023-01-11 14:50:10 +0100614 if (mbedtls_a64_crypto_sha256_has_support()) {
615 return mbedtls_internal_sha256_process_a64_crypto(ctx, data);
616 } else {
617 return mbedtls_internal_sha256_process_c(ctx, data);
618 }
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000619}
620
621#endif /* MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT */
622
Paul Bakker5121ce52009-01-03 21:22:43 +0000623
624/*
625 * SHA-256 process buffer
626 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100627int mbedtls_sha256_update(mbedtls_sha256_context *ctx,
628 const unsigned char *input,
629 size_t ilen)
Paul Bakker5121ce52009-01-03 21:22:43 +0000630{
Janos Follath24eed8d2019-11-22 13:21:35 +0000631 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Paul Bakker23986e52011-04-24 08:57:21 +0000632 size_t fill;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000633 uint32_t left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000634
Gilles Peskine449bd832023-01-11 14:50:10 +0100635 if (ilen == 0) {
636 return 0;
637 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000638
639 left = ctx->total[0] & 0x3F;
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000640 fill = SHA256_BLOCK_SIZE - left;
Paul Bakker5121ce52009-01-03 21:22:43 +0000641
Paul Bakker5c2364c2012-10-01 14:41:15 +0000642 ctx->total[0] += (uint32_t) ilen;
Paul Bakker5121ce52009-01-03 21:22:43 +0000643 ctx->total[0] &= 0xFFFFFFFF;
644
Gilles Peskine449bd832023-01-11 14:50:10 +0100645 if (ctx->total[0] < (uint32_t) ilen) {
Paul Bakker5121ce52009-01-03 21:22:43 +0000646 ctx->total[1]++;
Gilles Peskine449bd832023-01-11 14:50:10 +0100647 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000648
Gilles Peskine449bd832023-01-11 14:50:10 +0100649 if (left && ilen >= fill) {
650 memcpy((void *) (ctx->buffer + left), input, fill);
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100651
Gilles Peskine449bd832023-01-11 14:50:10 +0100652 if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
653 return ret;
654 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100655
Paul Bakker5121ce52009-01-03 21:22:43 +0000656 input += fill;
657 ilen -= fill;
658 left = 0;
659 }
660
Gilles Peskine449bd832023-01-11 14:50:10 +0100661 while (ilen >= SHA256_BLOCK_SIZE) {
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000662 size_t processed =
Gilles Peskine449bd832023-01-11 14:50:10 +0100663 mbedtls_internal_sha256_process_many(ctx, input, ilen);
664 if (processed < SHA256_BLOCK_SIZE) {
665 return MBEDTLS_ERR_ERROR_GENERIC_ERROR;
666 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100667
Tom Cosgrovef3ebd902022-02-20 22:25:31 +0000668 input += processed;
669 ilen -= processed;
Paul Bakker5121ce52009-01-03 21:22:43 +0000670 }
671
Gilles Peskine449bd832023-01-11 14:50:10 +0100672 if (ilen > 0) {
673 memcpy((void *) (ctx->buffer + left), input, ilen);
674 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100675
Gilles Peskine449bd832023-01-11 14:50:10 +0100676 return 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000677}
678
Paul Bakker5121ce52009-01-03 21:22:43 +0000679/*
680 * SHA-256 final digest
681 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100682int mbedtls_sha256_finish(mbedtls_sha256_context *ctx,
683 unsigned char *output)
Paul Bakker5121ce52009-01-03 21:22:43 +0000684{
Janos Follath24eed8d2019-11-22 13:21:35 +0000685 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200686 uint32_t used;
Paul Bakker5c2364c2012-10-01 14:41:15 +0000687 uint32_t high, low;
Dave Rodgman90330a42023-09-28 17:24:06 +0100688 int truncated = 0;
Paul Bakker5121ce52009-01-03 21:22:43 +0000689
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200690 /*
691 * Add padding: 0x80 then 0x00 until 8 bytes remain for the length
692 */
693 used = ctx->total[0] & 0x3F;
694
695 ctx->buffer[used++] = 0x80;
696
Gilles Peskine449bd832023-01-11 14:50:10 +0100697 if (used <= 56) {
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200698 /* Enough room for padding + length in current block */
Gilles Peskine449bd832023-01-11 14:50:10 +0100699 memset(ctx->buffer + used, 0, 56 - used);
700 } else {
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200701 /* We'll need an extra block */
Gilles Peskine449bd832023-01-11 14:50:10 +0100702 memset(ctx->buffer + used, 0, SHA256_BLOCK_SIZE - used);
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200703
Gilles Peskine449bd832023-01-11 14:50:10 +0100704 if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
Dave Rodgmanaafd1e02023-09-11 12:59:36 +0100705 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100706 }
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200707
Gilles Peskine449bd832023-01-11 14:50:10 +0100708 memset(ctx->buffer, 0, 56);
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200709 }
710
711 /*
712 * Add message length
713 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100714 high = (ctx->total[0] >> 29)
715 | (ctx->total[1] << 3);
716 low = (ctx->total[0] << 3);
Paul Bakker5121ce52009-01-03 21:22:43 +0000717
Gilles Peskine449bd832023-01-11 14:50:10 +0100718 MBEDTLS_PUT_UINT32_BE(high, ctx->buffer, 56);
719 MBEDTLS_PUT_UINT32_BE(low, ctx->buffer, 60);
Paul Bakker5121ce52009-01-03 21:22:43 +0000720
Gilles Peskine449bd832023-01-11 14:50:10 +0100721 if ((ret = mbedtls_internal_sha256_process(ctx, ctx->buffer)) != 0) {
Dave Rodgmanaafd1e02023-09-11 12:59:36 +0100722 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100723 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100724
Manuel Pégourié-Gonnard1cc1fb02018-06-28 12:10:27 +0200725 /*
726 * Output final state
727 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100728 MBEDTLS_PUT_UINT32_BE(ctx->state[0], output, 0);
729 MBEDTLS_PUT_UINT32_BE(ctx->state[1], output, 4);
730 MBEDTLS_PUT_UINT32_BE(ctx->state[2], output, 8);
731 MBEDTLS_PUT_UINT32_BE(ctx->state[3], output, 12);
732 MBEDTLS_PUT_UINT32_BE(ctx->state[4], output, 16);
733 MBEDTLS_PUT_UINT32_BE(ctx->state[5], output, 20);
734 MBEDTLS_PUT_UINT32_BE(ctx->state[6], output, 24);
Paul Bakker5121ce52009-01-03 21:22:43 +0000735
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200736#if defined(MBEDTLS_SHA224_C)
David Horstmann687262c2022-10-06 17:54:57 +0100737 truncated = ctx->is224;
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200738#endif
Gilles Peskine449bd832023-01-11 14:50:10 +0100739 if (!truncated) {
740 MBEDTLS_PUT_UINT32_BE(ctx->state[7], output, 28);
741 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100742
Dave Rodgmanaafd1e02023-09-11 12:59:36 +0100743 ret = 0;
744
745exit:
746 mbedtls_sha256_free(ctx);
747 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000748}
749
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200750#endif /* !MBEDTLS_SHA256_ALT */
Paul Bakker90995b52013-06-24 19:20:35 +0200751
Paul Bakker5121ce52009-01-03 21:22:43 +0000752/*
753 * output = SHA-256( input buffer )
754 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100755int mbedtls_sha256(const unsigned char *input,
756 size_t ilen,
757 unsigned char *output,
758 int is224)
Paul Bakker5121ce52009-01-03 21:22:43 +0000759{
Janos Follath24eed8d2019-11-22 13:21:35 +0000760 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200761 mbedtls_sha256_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000762
Valerio Settia3f99592022-12-14 10:56:54 +0100763#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100764 if (is224 != 0 && is224 != 1) {
Tuvshinzaya Erdenekhuu696dfb62022-08-05 15:59:19 +0100765 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100766 }
Valerio Settia3f99592022-12-14 10:56:54 +0100767#elif defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100768 if (is224 != 0) {
Tuvshinzaya Erdenekhuu696dfb62022-08-05 15:59:19 +0100769 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100770 }
Valerio Settia3f99592022-12-14 10:56:54 +0100771#else /* defined MBEDTLS_SHA224_C only */
Gilles Peskine449bd832023-01-11 14:50:10 +0100772 if (is224 == 0) {
Valerio Settia3f99592022-12-14 10:56:54 +0100773 return MBEDTLS_ERR_SHA256_BAD_INPUT_DATA;
Gilles Peskine449bd832023-01-11 14:50:10 +0100774 }
Mateusz Starzyke3c48b42021-04-19 16:46:28 +0200775#endif
776
Gilles Peskine449bd832023-01-11 14:50:10 +0100777 mbedtls_sha256_init(&ctx);
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100778
Gilles Peskine449bd832023-01-11 14:50:10 +0100779 if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100780 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100781 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100782
Gilles Peskine449bd832023-01-11 14:50:10 +0100783 if ((ret = mbedtls_sha256_update(&ctx, input, ilen)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100784 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100785 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100786
Gilles Peskine449bd832023-01-11 14:50:10 +0100787 if ((ret = mbedtls_sha256_finish(&ctx, output)) != 0) {
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100788 goto exit;
Gilles Peskine449bd832023-01-11 14:50:10 +0100789 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100790
Andres Amaya Garcia0963e6c2017-07-20 14:34:08 +0100791exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100792 mbedtls_sha256_free(&ctx);
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100793
Gilles Peskine449bd832023-01-11 14:50:10 +0100794 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000795}
796
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200797#if defined(MBEDTLS_SELF_TEST)
Paul Bakker5121ce52009-01-03 21:22:43 +0000798/*
799 * FIPS-180-2 test vectors
800 */
Valerio Settia3f99592022-12-14 10:56:54 +0100801static const unsigned char sha_test_buf[3][57] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000802{
803 { "abc" },
804 { "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" },
805 { "" }
806};
807
Valerio Settia3f99592022-12-14 10:56:54 +0100808static const size_t sha_test_buflen[3] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000809{
810 3, 56, 1000
811};
812
Valerio Settia3f99592022-12-14 10:56:54 +0100813typedef const unsigned char (sha_test_sum_t)[32];
814
815/*
816 * SHA-224 test vectors
817 */
818#if defined(MBEDTLS_SHA224_C)
819static sha_test_sum_t sha224_test_sum[] =
Paul Bakker5121ce52009-01-03 21:22:43 +0000820{
Paul Bakker5121ce52009-01-03 21:22:43 +0000821 { 0x23, 0x09, 0x7D, 0x22, 0x34, 0x05, 0xD8, 0x22,
822 0x86, 0x42, 0xA4, 0x77, 0xBD, 0xA2, 0x55, 0xB3,
823 0x2A, 0xAD, 0xBC, 0xE4, 0xBD, 0xA0, 0xB3, 0xF7,
824 0xE3, 0x6C, 0x9D, 0xA7 },
825 { 0x75, 0x38, 0x8B, 0x16, 0x51, 0x27, 0x76, 0xCC,
826 0x5D, 0xBA, 0x5D, 0xA1, 0xFD, 0x89, 0x01, 0x50,
827 0xB0, 0xC6, 0x45, 0x5C, 0xB4, 0xF5, 0x8B, 0x19,
828 0x52, 0x52, 0x25, 0x25 },
829 { 0x20, 0x79, 0x46, 0x55, 0x98, 0x0C, 0x91, 0xD8,
830 0xBB, 0xB4, 0xC1, 0xEA, 0x97, 0x61, 0x8A, 0x4B,
831 0xF0, 0x3F, 0x42, 0x58, 0x19, 0x48, 0xB2, 0xEE,
Valerio Settia3f99592022-12-14 10:56:54 +0100832 0x4E, 0xE7, 0xAD, 0x67 }
833};
834#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000835
Valerio Settia3f99592022-12-14 10:56:54 +0100836/*
837 * SHA-256 test vectors
838 */
839#if defined(MBEDTLS_SHA256_C)
840static sha_test_sum_t sha256_test_sum[] =
841{
Paul Bakker5121ce52009-01-03 21:22:43 +0000842 { 0xBA, 0x78, 0x16, 0xBF, 0x8F, 0x01, 0xCF, 0xEA,
843 0x41, 0x41, 0x40, 0xDE, 0x5D, 0xAE, 0x22, 0x23,
844 0xB0, 0x03, 0x61, 0xA3, 0x96, 0x17, 0x7A, 0x9C,
845 0xB4, 0x10, 0xFF, 0x61, 0xF2, 0x00, 0x15, 0xAD },
846 { 0x24, 0x8D, 0x6A, 0x61, 0xD2, 0x06, 0x38, 0xB8,
847 0xE5, 0xC0, 0x26, 0x93, 0x0C, 0x3E, 0x60, 0x39,
848 0xA3, 0x3C, 0xE4, 0x59, 0x64, 0xFF, 0x21, 0x67,
849 0xF6, 0xEC, 0xED, 0xD4, 0x19, 0xDB, 0x06, 0xC1 },
850 { 0xCD, 0xC7, 0x6E, 0x5C, 0x99, 0x14, 0xFB, 0x92,
851 0x81, 0xA1, 0xC7, 0xE2, 0x84, 0xD7, 0x3E, 0x67,
852 0xF1, 0x80, 0x9A, 0x48, 0xA4, 0x97, 0x20, 0x0E,
853 0x04, 0x6D, 0x39, 0xCC, 0xC7, 0x11, 0x2C, 0xD0 }
854};
Valerio Settia3f99592022-12-14 10:56:54 +0100855#endif
Paul Bakker5121ce52009-01-03 21:22:43 +0000856
857/*
Paul Bakker5121ce52009-01-03 21:22:43 +0000858 * Checkup routine
859 */
Gilles Peskine449bd832023-01-11 14:50:10 +0100860static int mbedtls_sha256_common_self_test(int verbose, int is224)
Paul Bakker5121ce52009-01-03 21:22:43 +0000861{
Valerio Settia3f99592022-12-14 10:56:54 +0100862 int i, buflen, ret = 0;
Russ Butlerbb83b422016-10-12 17:36:50 -0500863 unsigned char *buf;
Paul Bakker9e36f042013-06-30 14:34:05 +0200864 unsigned char sha256sum[32];
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200865 mbedtls_sha256_context ctx;
Paul Bakker5121ce52009-01-03 21:22:43 +0000866
Valerio Settia3f99592022-12-14 10:56:54 +0100867#if defined(MBEDTLS_SHA224_C) && defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100868 sha_test_sum_t *sha_test_sum = (is224) ? sha224_test_sum : sha256_test_sum;
Valerio Settia3f99592022-12-14 10:56:54 +0100869#elif defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100870 sha_test_sum_t *sha_test_sum = sha256_test_sum;
Valerio Settia3f99592022-12-14 10:56:54 +0100871#else
Gilles Peskine449bd832023-01-11 14:50:10 +0100872 sha_test_sum_t *sha_test_sum = sha224_test_sum;
Valerio Settia3f99592022-12-14 10:56:54 +0100873#endif
874
Gilles Peskine449bd832023-01-11 14:50:10 +0100875 buf = mbedtls_calloc(1024, sizeof(unsigned char));
876 if (NULL == buf) {
877 if (verbose != 0) {
878 mbedtls_printf("Buffer allocation failed\n");
879 }
Russ Butlerbb83b422016-10-12 17:36:50 -0500880
Gilles Peskine449bd832023-01-11 14:50:10 +0100881 return 1;
Russ Butlerbb83b422016-10-12 17:36:50 -0500882 }
883
Gilles Peskine449bd832023-01-11 14:50:10 +0100884 mbedtls_sha256_init(&ctx);
Paul Bakker5b4af392014-06-26 12:09:34 +0200885
Gilles Peskine449bd832023-01-11 14:50:10 +0100886 for (i = 0; i < 3; i++) {
887 if (verbose != 0) {
888 mbedtls_printf(" SHA-%d test #%d: ", 256 - is224 * 32, i + 1);
889 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000890
Gilles Peskine449bd832023-01-11 14:50:10 +0100891 if ((ret = mbedtls_sha256_starts(&ctx, is224)) != 0) {
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100892 goto fail;
Gilles Peskine449bd832023-01-11 14:50:10 +0100893 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000894
Gilles Peskine449bd832023-01-11 14:50:10 +0100895 if (i == 2) {
896 memset(buf, 'a', buflen = 1000);
Paul Bakker5121ce52009-01-03 21:22:43 +0000897
Gilles Peskine449bd832023-01-11 14:50:10 +0100898 for (int j = 0; j < 1000; j++) {
899 ret = mbedtls_sha256_update(&ctx, buf, buflen);
900 if (ret != 0) {
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100901 goto fail;
Gilles Peskine449bd832023-01-11 14:50:10 +0100902 }
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100903 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100904
Gilles Peskine449bd832023-01-11 14:50:10 +0100905 } else {
906 ret = mbedtls_sha256_update(&ctx, sha_test_buf[i],
907 sha_test_buflen[i]);
908 if (ret != 0) {
909 goto fail;
910 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100911 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000912
Gilles Peskine449bd832023-01-11 14:50:10 +0100913 if ((ret = mbedtls_sha256_finish(&ctx, sha256sum)) != 0) {
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100914 goto fail;
Gilles Peskine449bd832023-01-11 14:50:10 +0100915 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100916
Paul Bakker5121ce52009-01-03 21:22:43 +0000917
Gilles Peskine449bd832023-01-11 14:50:10 +0100918 if (memcmp(sha256sum, sha_test_sum[i], 32 - is224 * 4) != 0) {
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100919 ret = 1;
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100920 goto fail;
Andres Amaya Garcia6a3f3052017-07-20 14:18:54 +0100921 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000922
Gilles Peskine449bd832023-01-11 14:50:10 +0100923 if (verbose != 0) {
924 mbedtls_printf("passed\n");
925 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000926 }
927
Gilles Peskine449bd832023-01-11 14:50:10 +0100928 if (verbose != 0) {
929 mbedtls_printf("\n");
930 }
Paul Bakker5121ce52009-01-03 21:22:43 +0000931
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100932 goto exit;
933
934fail:
Gilles Peskine449bd832023-01-11 14:50:10 +0100935 if (verbose != 0) {
936 mbedtls_printf("failed\n");
937 }
Andres Amaya Garcia72a7f532017-05-02 11:38:47 +0100938
Paul Bakker5b4af392014-06-26 12:09:34 +0200939exit:
Gilles Peskine449bd832023-01-11 14:50:10 +0100940 mbedtls_sha256_free(&ctx);
941 mbedtls_free(buf);
Paul Bakker5b4af392014-06-26 12:09:34 +0200942
Gilles Peskine449bd832023-01-11 14:50:10 +0100943 return ret;
Paul Bakker5121ce52009-01-03 21:22:43 +0000944}
945
Valerio Settia3f99592022-12-14 10:56:54 +0100946#if defined(MBEDTLS_SHA256_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100947int mbedtls_sha256_self_test(int verbose)
Valerio Settia3f99592022-12-14 10:56:54 +0100948{
Gilles Peskine449bd832023-01-11 14:50:10 +0100949 return mbedtls_sha256_common_self_test(verbose, 0);
Valerio Settia3f99592022-12-14 10:56:54 +0100950}
951#endif /* MBEDTLS_SHA256_C */
952
953#if defined(MBEDTLS_SHA224_C)
Gilles Peskine449bd832023-01-11 14:50:10 +0100954int mbedtls_sha224_self_test(int verbose)
Valerio Settia3f99592022-12-14 10:56:54 +0100955{
Gilles Peskine449bd832023-01-11 14:50:10 +0100956 return mbedtls_sha256_common_self_test(verbose, 1);
Valerio Settia3f99592022-12-14 10:56:54 +0100957}
958#endif /* MBEDTLS_SHA224_C */
959
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200960#endif /* MBEDTLS_SELF_TEST */
Paul Bakker5121ce52009-01-03 21:22:43 +0000961
Valerio Settia3f99592022-12-14 10:56:54 +0100962#endif /* MBEDTLS_SHA256_C || MBEDTLS_SHA224_C */