diff --git a/ChangeLog.d/sha3.txt b/ChangeLog.d/sha3.txt new file mode 100644 index 0000000000..dafff74f16 --- /dev/null +++ b/ChangeLog.d/sha3.txt @@ -0,0 +1,3 @@ +Features + * Add SHA3 family hash functions. + diff --git a/include/mbedtls/error.h b/include/mbedtls/error.h index 8b2b9ea580..b23b7491f0 100644 --- a/include/mbedtls/error.h +++ b/include/mbedtls/error.h @@ -78,6 +78,7 @@ * SHA1 1 0x0035-0x0035 0x0073-0x0073 * SHA256 1 0x0037-0x0037 0x0074-0x0074 * SHA512 1 0x0039-0x0039 0x0075-0x0075 + * SHA-3 1 0x0076-0x0076 * CHACHA20 3 0x0051-0x0055 * POLY1305 3 0x0057-0x005B * CHACHAPOLY 2 0x0054-0x0056 diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h index 2d32f67cc1..35a4a0cbd6 100644 --- a/include/mbedtls/mbedtls_config.h +++ b/include/mbedtls/mbedtls_config.h @@ -328,6 +328,7 @@ //#define MBEDTLS_SHA1_ALT //#define MBEDTLS_SHA256_ALT //#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_SHA3_ALT /* * When replacing the elliptic curve module, pleace consider, that it is @@ -2863,6 +2864,17 @@ */ #define MBEDTLS_SHA512_C +/** + * \def MBEDTLS_SHA3_C + * + * Enable the SHA3 cryptographic hash algorithm. + * + * Module: library/sha3.c + * + * This module adds support for SHA3. + */ +#define MBEDTLS_SHA3_C + /** * \def MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT * diff --git a/include/mbedtls/sha3.h b/include/mbedtls/sha3.h new file mode 100644 index 0000000000..adecdc722f --- /dev/null +++ b/include/mbedtls/sha3.h @@ -0,0 +1,198 @@ +/** + * \file sha3.h + * + * \brief This file contains SHA3 definitions and functions. + * + * The Secure Hash Algorithms cryptographic + * hash functions are defined in FIPS 202: SHA-3 Standard: + * Permutation-Based Hash and Extendable-Output Functions . + */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef MBEDTLS_SHA3_H +#define MBEDTLS_SHA3_H +#include "mbedtls/private_access.h" + +#include "mbedtls/build_info.h" + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** SHA3 input data was malformed. */ +#define MBEDTLS_ERR_SHA3_BAD_INPUT_DATA -0x0076 + +/** + * SHA-3 family id. + * + * It identifies the family (SHA3-256, SHA3-512, etc.) + */ + +typedef enum +{ + MBEDTLS_SHA3_NONE = 0, /*!< Operation not defined. */ + MBEDTLS_SHA3_224, /*!< SHA3-224 */ + MBEDTLS_SHA3_256, /*!< SHA3-256 */ + MBEDTLS_SHA3_384, /*!< SHA3-384 */ + MBEDTLS_SHA3_512, /*!< SHA3-512 */ +} mbedtls_sha3_id; + +#if !defined(MBEDTLS_SHA3_ALT) +// Regular implementation +// + +struct mbedtls_sha3_context; +typedef struct mbedtls_sha3_family_functions +{ + mbedtls_sha3_id id; + + uint16_t r; + uint16_t olen; + uint8_t xor_byte; +} +mbedtls_sha3_family_functions; + +/** + * \brief The SHA-3 context structure. + * + * The structure is used SHA-3 checksum calculations. + */ +typedef struct mbedtls_sha3_context { + uint64_t state[25]; + uint8_t index; + uint8_t id; + + uint16_t r; + uint16_t olen; + uint8_t xor_byte; + uint16_t max_block_size; +} +mbedtls_sha3_context; + +#else /* MBEDTLS_SHA3_ALT */ +#include "sha3_alt.h" +#endif /* MBEDTLS_SHA3_ALT */ + +/** + * \brief This function initializes a SHA-3 context. + * + * \param ctx The SHA-3 context to initialize. This must not be \c NULL. + */ +void mbedtls_sha3_init( mbedtls_sha3_context *ctx ); + +/** + * \brief This function clears a SHA-3 context. + * + * \param ctx The SHA-3 context to clear. This may be \c NULL, in which + * case this function returns immediately. If it is not \c NULL, + * it must point to an initialized SHA-3 context. + */ +void mbedtls_sha3_free( mbedtls_sha3_context *ctx ); + +/** + * \brief This function clones the state of a SHA-3 context. + * + * \param dst The destination context. This must be initialized. + * \param src The context to clone. This must be initialized. + */ +void mbedtls_sha3_clone( mbedtls_sha3_context *dst, + const mbedtls_sha3_context *src ); + +/** + * \brief This function starts a SHA-3 checksum + * calculation. + * + * \param ctx The context to use. This must be initialized. + * \param id The id of the SHA-3 family. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_starts( mbedtls_sha3_context *ctx, mbedtls_sha3_id id ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-3 checksum calculation. + * + * \param ctx The SHA-3 context. This must be initialized + * and have a hash operation started. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_update( mbedtls_sha3_context *ctx, + const uint8_t *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-3 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-3 context. This must be initialized + * and have a hash operation started. + * \param output The SHA-3 checksum result. + * This must be a writable buffer of length \c olen bytes. + * \param olen Defines a variable output length (in bytes). \c output must be + * \c olen bytes length. For SHA-3 224, SHA-3 256, SHA-3 384 and + * SHA-3 512 must equal to 28, 32, 48 and 64, respectively. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3_finish( mbedtls_sha3_context *ctx, + uint8_t *output, size_t olen ); + +/** + * \brief This function calculates the SHA-3 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-3 result is calculated as + * output = SHA-3(id, input buffer, d). + * + * \param id The id of the SHA-3 family. + * \param input The buffer holding the data. This must be a readable + * buffer of length \p ilen Bytes. + * \param ilen The length of the input data in Bytes. + * \param output The SHA-3 checksum result. + * This must be a writable buffer of length \c olen bytes. + * \param olen Determines the length (in bytes) of the output. \c output + * must be \c olen bytes length. + * + * \return \c 0 on success. + * \return A negative error code on failure. + */ +int mbedtls_sha3( mbedtls_sha3_id id, const uint8_t *input, + size_t ilen, + uint8_t *output, + size_t olen ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha3.h */ + diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index 6bb2ad38ce..f1b0d76695 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -77,6 +77,7 @@ set(src_crypto sha1.c sha256.c sha512.c + sha3.c ssl_debug_helpers_generated.c threading.c timing.c diff --git a/library/Makefile b/library/Makefile index d267e05b4a..79ea185c37 100644 --- a/library/Makefile +++ b/library/Makefile @@ -142,6 +142,7 @@ OBJS_CRYPTO= \ sha1.o \ sha256.o \ sha512.o \ + sha3.o \ ssl_debug_helpers_generated.o \ threading.o \ timing.o \ diff --git a/library/sha3.c b/library/sha3.c new file mode 100644 index 0000000000..d5db165fbc --- /dev/null +++ b/library/sha3.c @@ -0,0 +1,305 @@ +/* + * FIPS-202 compliant SHA3 implementation + * + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +/* + * The SHA-3 Secure Hash Standard was published by NIST in 2015. + * + * https://nvlpubs.nist.gov/nistpubs/fips/nist.fips.202.pdf + */ + +#include "common.h" + +#if defined(MBEDTLS_SHA3_C) + +#include "mbedtls/sha3.h" +#include "mbedtls/platform_util.h" +#include "mbedtls/error.h" + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA3_ALT) + +/* + * List of supported SHA-3 families + */ +static mbedtls_sha3_family_functions sha3_families[] = { + { MBEDTLS_SHA3_224, 1152, 224, 0x06 }, + { MBEDTLS_SHA3_256, 1088, 256, 0x06 }, + { MBEDTLS_SHA3_384, 832, 384, 0x06 }, + { MBEDTLS_SHA3_512, 576, 512, 0x06 }, + { MBEDTLS_SHA3_NONE, 0, 0, 0 } +}; + +static const uint64_t rc[24] = { + 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, + 0x000000000000808b, 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, + 0x000000000000008a, 0x0000000000000088, 0x0000000080008009, 0x000000008000000a, + 0x000000008000808b, 0x800000000000008b, 0x8000000000008089, 0x8000000000008003, + 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a, + 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008, +}; + +static const uint8_t rho[24] = { + 1, 62, 28, 27, 36, 44, 6, 55, 20, + 3, 10, 43, 25, 39, 41, 45, 15, + 21, 8, 18, 2, 61, 56, 14 +}; + +static const uint8_t pi[24] = { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1, +}; + +#define ROT64( x , y ) ( ( ( x ) << ( y ) ) | ( ( x ) >> ( 64U - ( y ) ) ) ) +#define ABSORB( ctx, idx, v ) do { ctx->state[( idx ) >> 3] ^= ( ( uint64_t ) ( v ) ) << ( ( ( idx ) & 0x7 ) << 3 ); } while( 0 ) +#define SQUEEZE( ctx, idx ) ( ( uint8_t )( ctx->state[( idx ) >> 3] >> ( ( ( idx ) & 0x7 ) << 3 ) ) ) +#define SWAP( x, y ) do { uint64_t tmp = ( x ); ( x ) = ( y ); ( y ) = tmp; } while( 0 ) + +/* The permutation function. */ +static void keccak_f1600(mbedtls_sha3_context *ctx) +{ + uint64_t lane[5]; + uint64_t *s = ctx->state; + int i; + + for( int round = 0; round < 24; round++ ) + { + uint64_t t; + + /* Theta */ + lane[0] = s[0] ^ s[5] ^ s[10] ^ s[15] ^ s[20]; + lane[1] = s[1] ^ s[6] ^ s[11] ^ s[16] ^ s[21]; + lane[2] = s[2] ^ s[7] ^ s[12] ^ s[17] ^ s[22]; + lane[3] = s[3] ^ s[8] ^ s[13] ^ s[18] ^ s[23]; + lane[4] = s[4] ^ s[9] ^ s[14] ^ s[19] ^ s[24]; + + t = lane[4] ^ ROT64( lane[1], 1 ); + s[0] ^= t; s[5] ^= t; s[10] ^= t; s[15] ^= t; s[20] ^= t; + + t = lane[0] ^ ROT64( lane[2], 1 ); + s[1] ^= t; s[6] ^= t; s[11] ^= t; s[16] ^= t; s[21] ^= t; + + t = lane[1] ^ ROT64( lane[3], 1 ); + s[2] ^= t; s[7] ^= t; s[12] ^= t; s[17] ^= t; s[22] ^= t; + + t = lane[2] ^ ROT64( lane[4], 1 ); + s[3] ^= t; s[8] ^= t; s[13] ^= t; s[18] ^= t; s[23] ^= t; + + t = lane[3] ^ ROT64( lane[0], 1 ); + s[4] ^= t; s[9] ^= t; s[14] ^= t; s[19] ^= t; s[24] ^= t; + + /* Rho */ + for( i = 1; i < 25; i++ ) + s[i] = ROT64( s[i], rho[i-1] ); + + /* Pi */ + t = s[1]; + for( i = 0; i < 24; i++ ) + SWAP( s[pi[i]], t ); + + /* Chi */ + lane[0] = s[0]; lane[1] = s[1]; lane[2] = s[2]; lane[3] = s[3]; lane[4] = s[4]; + s[0] ^= (~lane[1]) & lane[2]; + s[1] ^= (~lane[2]) & lane[3]; + s[2] ^= (~lane[3]) & lane[4]; + s[3] ^= (~lane[4]) & lane[0]; + s[4] ^= (~lane[0]) & lane[1]; + + lane[0] = s[5]; lane[1] = s[6]; lane[2] = s[7]; lane[3] = s[8]; lane[4] = s[9]; + s[5] ^= (~lane[1]) & lane[2]; + s[6] ^= (~lane[2]) & lane[3]; + s[7] ^= (~lane[3]) & lane[4]; + s[8] ^= (~lane[4]) & lane[0]; + s[9] ^= (~lane[0]) & lane[1]; + + lane[0] = s[10]; lane[1] = s[11]; lane[2] = s[12]; lane[3] = s[13]; lane[4] = s[14]; + s[10] ^= (~lane[1]) & lane[2]; + s[11] ^= (~lane[2]) & lane[3]; + s[12] ^= (~lane[3]) & lane[4]; + s[13] ^= (~lane[4]) & lane[0]; + s[14] ^= (~lane[0]) & lane[1]; + + lane[0] = s[15]; lane[1] = s[16]; lane[2] = s[17]; lane[3] = s[18]; lane[4] = s[19]; + s[15] ^= (~lane[1]) & lane[2]; + s[16] ^= (~lane[2]) & lane[3]; + s[17] ^= (~lane[3]) & lane[4]; + s[18] ^= (~lane[4]) & lane[0]; + s[19] ^= (~lane[0]) & lane[1]; + + lane[0] = s[20]; lane[1] = s[21]; lane[2] = s[22]; lane[3] = s[23]; lane[4] = s[24]; + s[20] ^= (~lane[1]) & lane[2]; + s[21] ^= (~lane[2]) & lane[3]; + s[22] ^= (~lane[3]) & lane[4]; + s[23] ^= (~lane[4]) & lane[0]; + s[24] ^= (~lane[0]) & lane[1]; + + /* Iota */ + s[0] ^= rc[round]; + } +} + +void mbedtls_sha3_init( mbedtls_sha3_context *ctx ) +{ + if( ctx == NULL ) + return; + + memset( ctx, 0, sizeof( mbedtls_sha3_context ) ); +} + +void mbedtls_sha3_free( mbedtls_sha3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha3_context ) ); +} + +void mbedtls_sha3_clone( mbedtls_sha3_context *dst, + const mbedtls_sha3_context *src ) +{ + if ( dst == NULL || src == NULL ) + return; + + *dst = *src; +} + +/* + * SHA-3 context setup + */ +int mbedtls_sha3_starts( mbedtls_sha3_context *ctx, mbedtls_sha3_id id ) +{ + mbedtls_sha3_family_functions *p = NULL; + if( ctx == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + for( p = sha3_families; p->id != MBEDTLS_SHA3_NONE; p++ ) + { + if( p->id == id ) + break; + } + + if( p == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + ctx->id = id; + ctx->r = p->r; + ctx->olen = p->olen / 8; + ctx->xor_byte = p->xor_byte; + ctx->max_block_size = ctx->r / 8; + + return( 0 ); +} + +/* + * SHA-3 process buffer + */ +int mbedtls_sha3_update( mbedtls_sha3_context *ctx, + const uint8_t *input, + size_t ilen ) +{ + if( ctx == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + if( ilen == 0 || input == NULL ) + return( 0 ); + + while( ilen-- > 0 ) + { + ABSORB( ctx, ctx->index, *input++ ); + if( ( ctx->index = ( ctx->index + 1) % ctx->max_block_size ) == 0 ) + keccak_f1600( ctx ); + } + + return( 0 ); +} + +int mbedtls_sha3_finish( mbedtls_sha3_context *ctx, + uint8_t *output, size_t olen ) +{ + if( ctx == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + if( olen == 0 ) + return( 0 ); + + if( ctx->olen > 0 && ctx->olen != olen ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + ABSORB( ctx, ctx->index, ctx->xor_byte ); + ABSORB( ctx, ctx->max_block_size - 1, 0x80 ); + keccak_f1600( ctx ); + ctx->index = 0; + + while( olen-- > 0 ) + { + *output++ = SQUEEZE( ctx, ctx->index ); + + if( ( ctx->index = ( ctx->index + 1) % ctx->max_block_size ) == 0 ) + keccak_f1600( ctx ); + } + + return( 0 ); +} + +#endif /* !MBEDTLS_SHA3_ALT */ + +/* + * output = SHA3( input buffer ) + */ +int mbedtls_sha3( mbedtls_sha3_id id, const uint8_t *input, + size_t ilen, uint8_t *output, size_t olen ) +{ + int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; + mbedtls_sha3_context ctx; + + if( ilen != 0 && input == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + if( output == NULL ) + return( MBEDTLS_ERR_SHA3_BAD_INPUT_DATA ); + + mbedtls_sha3_init( &ctx ); + + if( ( ret = mbedtls_sha3_starts( &ctx, id ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha3_update( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha3_finish( &ctx, output, olen ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha3_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SHA3_C */ diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl index 0a03f02e96..a0808cad66 100755 --- a/scripts/generate_errors.pl +++ b/scripts/generate_errors.pl @@ -49,7 +49,7 @@ my @low_level_modules = qw( AES ARIA ASN1 BASE64 BIGNUM CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES ENTROPY ERROR GCM HKDF HMAC_DRBG MD5 NET OID PADLOCK PBKDF2 PLATFORM POLY1305 RIPEMD160 - SHA1 SHA256 SHA512 THREADING ); + SHA1 SHA256 SHA512 SHA3 THREADING ); my @high_level_modules = qw( CIPHER DHM ECP MD PEM PK PKCS12 PKCS5 RSA SSL X509 ); diff --git a/tests/include/alt-dummy/sha3_alt.h b/tests/include/alt-dummy/sha3_alt.h new file mode 100644 index 0000000000..7f9345e48a --- /dev/null +++ b/tests/include/alt-dummy/sha3_alt.h @@ -0,0 +1,30 @@ +/* sha3_alt.h with dummy types for MBEDTLS_SHA3_ALT */ +/* + * Copyright The Mbed TLS Contributors + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SHA3_ALT_H +#define SHA3_ALT_H + +typedef struct mbedtls_sha3_context +{ + int dummy; +} +mbedtls_sha3_context; + + +#endif /* sha3_alt.h */ +