diff --git a/ChangeLog.d/sha3.txt b/ChangeLog.d/sha3.txt
new file mode 100644
index 000000000000..dafff74f169d
--- /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 23a83f2c84d7..11600bb60e71 100644
--- a/include/mbedtls/error.h
+++ b/include/mbedtls/error.h
@@ -73,6 +73,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 75e41476237b..985a50a7df3a 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -3164,6 +3164,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/md.h b/include/mbedtls/md.h
index 7bad24dc9b1c..a1429036875f 100644
--- a/include/mbedtls/md.h
+++ b/include/mbedtls/md.h
@@ -149,9 +149,13 @@ typedef enum {
MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */
MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */
MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */
+ MBEDTLS_MD_SHA3_224, /**< The SHA3-224 message digest. */
+ MBEDTLS_MD_SHA3_256, /**< The SHA3-256 message digest. */
+ MBEDTLS_MD_SHA3_384, /**< The SHA3-384 message digest. */
+ MBEDTLS_MD_SHA3_512, /**< The SHA3-512 message digest. */
} mbedtls_md_type_t;
-#if defined(MBEDTLS_MD_CAN_SHA512)
+#if defined(MBEDTLS_MD_CAN_SHA512) || defined(MBEDTLS_SHA3_C)
#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */
#elif defined(MBEDTLS_MD_CAN_SHA384)
#define MBEDTLS_MD_MAX_SIZE 48 /* longest known is SHA384 */
@@ -164,7 +168,9 @@ typedef enum {
or smaller (MD5 and earlier) */
#endif
-#if defined(MBEDTLS_MD_CAN_SHA512)
+#if defined(MBEDTLS_SHA3_C)
+#define MBEDTLS_MD_MAX_BLOCK_SIZE 144 /* the longest known is SHA3-224 */
+#elif defined(MBEDTLS_MD_CAN_SHA512)
#define MBEDTLS_MD_MAX_BLOCK_SIZE 128
#else
#define MBEDTLS_MD_MAX_BLOCK_SIZE 64
diff --git a/include/mbedtls/sha3.h b/include/mbedtls/sha3.h
new file mode 100644
index 000000000000..2ddb22a3bef1
--- /dev/null
+++ b/include/mbedtls/sha3.h
@@ -0,0 +1,199 @@
+/**
+ * \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;
+
+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;
+
+/**
+ * \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 the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,
+ * SHA-3 384 and SHA-3 512 \c olen 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 Defines the length of output buffer (in bytes). For SHA-3 224, SHA-3 256,
+ * SHA-3 384 and SHA-3 512 \c olen must equal to 28, 32, 48 and 64,
+ * respectively.
+ *
+ * \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);
+
+#if defined(MBEDTLS_SELF_TEST)
+/**
+ * \brief Checkup routine for the algorithms implemented
+ * by this module: SHA3-224, SHA3-256, SHA3-384, SHA3-512,
+ * SHAKE128, SHAKE256, cSHAKE128 and cSHAKE256.
+ *
+ * \return 0 if successful, or 1 if the test failed.
+ */
+int mbedtls_sha3_self_test(int verbose);
+#endif /* MBEDTLS_SELF_TEST */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* mbedtls_sha3.h */
diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt
index a992d8a71a0a..b60728c43993 100644
--- a/library/CMakeLists.txt
+++ b/library/CMakeLists.txt
@@ -84,6 +84,7 @@ set(src_crypto
sha1.c
sha256.c
sha512.c
+ sha3.c
threading.c
timing.c
version.c
diff --git a/library/Makefile b/library/Makefile
index 160aa6be5397..4e02bcd24810 100644
--- a/library/Makefile
+++ b/library/Makefile
@@ -149,6 +149,7 @@ OBJS_CRYPTO= \
sha1.o \
sha256.o \
sha512.o \
+ sha3.o \
threading.o \
timing.o \
version.o \
diff --git a/library/md.c b/library/md.c
index bebe3580bdda..993b006d2135 100644
--- a/library/md.c
+++ b/library/md.c
@@ -51,6 +51,9 @@
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
+#if defined(MBEDTLS_SHA3_C)
+#include "mbedtls/sha3.h"
+#endif
#if defined(MBEDTLS_MD_SOME_PSA)
#include
@@ -128,6 +131,33 @@ const mbedtls_md_info_t mbedtls_sha512_info = {
};
#endif
+#if defined(MBEDTLS_SHA3_C)
+const mbedtls_md_info_t mbedtls_sha3_224_info = {
+ "SHA3-224",
+ MBEDTLS_MD_SHA3_224,
+ 28,
+ 144,
+};
+const mbedtls_md_info_t mbedtls_sha3_256_info = {
+ "SHA3-256",
+ MBEDTLS_MD_SHA3_256,
+ 32,
+ 136,
+};
+const mbedtls_md_info_t mbedtls_sha3_384_info = {
+ "SHA3-384",
+ MBEDTLS_MD_SHA3_384,
+ 48,
+ 104,
+};
+const mbedtls_md_info_t mbedtls_sha3_512_info = {
+ "SHA3-512",
+ MBEDTLS_MD_SHA3_512,
+ 64,
+ 72,
+};
+#endif
+
const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
{
switch (md_type) {
@@ -158,6 +188,16 @@ const mbedtls_md_info_t *mbedtls_md_info_from_type(mbedtls_md_type_t md_type)
#if defined(MBEDTLS_MD_CAN_SHA512)
case MBEDTLS_MD_SHA512:
return &mbedtls_sha512_info;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ return &mbedtls_sha3_224_info;
+ case MBEDTLS_MD_SHA3_256:
+ return &mbedtls_sha3_256_info;
+ case MBEDTLS_MD_SHA3_384:
+ return &mbedtls_sha3_384_info;
+ case MBEDTLS_MD_SHA3_512:
+ return &mbedtls_sha3_512_info;
#endif
default:
return NULL;
@@ -279,6 +319,14 @@ void mbedtls_md_free(mbedtls_md_context_t *ctx)
case MBEDTLS_MD_SHA512:
mbedtls_sha512_free(ctx->md_ctx);
break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ case MBEDTLS_MD_SHA3_256:
+ case MBEDTLS_MD_SHA3_384:
+ case MBEDTLS_MD_SHA3_512:
+ mbedtls_sha3_free(ctx->md_ctx);
+ break;
#endif
default:
/* Shouldn't happen */
@@ -357,6 +405,14 @@ int mbedtls_md_clone(mbedtls_md_context_t *dst,
case MBEDTLS_MD_SHA512:
mbedtls_sha512_clone(dst->md_ctx, src->md_ctx);
break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ case MBEDTLS_MD_SHA3_256:
+ case MBEDTLS_MD_SHA3_384:
+ case MBEDTLS_MD_SHA3_512:
+ mbedtls_sha3_clone(dst->md_ctx, src->md_ctx);
+ break;
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -434,6 +490,14 @@ int mbedtls_md_setup(mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info
case MBEDTLS_MD_SHA512:
ALLOC(sha512);
break;
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ case MBEDTLS_MD_SHA3_256:
+ case MBEDTLS_MD_SHA3_384:
+ case MBEDTLS_MD_SHA3_512:
+ ALLOC(sha3);
+ break;
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -496,6 +560,16 @@ int mbedtls_md_starts(mbedtls_md_context_t *ctx)
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA512:
return mbedtls_sha512_starts(ctx->md_ctx, 0);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_224);
+ case MBEDTLS_MD_SHA3_256:
+ return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_256);
+ case MBEDTLS_MD_SHA3_384:
+ return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_384);
+ case MBEDTLS_MD_SHA3_512:
+ return mbedtls_sha3_starts(ctx->md_ctx, MBEDTLS_SHA3_512);
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -543,6 +617,13 @@ int mbedtls_md_update(mbedtls_md_context_t *ctx, const unsigned char *input, siz
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA512:
return mbedtls_sha512_update(ctx->md_ctx, input, ilen);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ case MBEDTLS_MD_SHA3_256:
+ case MBEDTLS_MD_SHA3_384:
+ case MBEDTLS_MD_SHA3_512:
+ return mbedtls_sha3_update(ctx->md_ctx, input, ilen);
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -592,6 +673,13 @@ int mbedtls_md_finish(mbedtls_md_context_t *ctx, unsigned char *output)
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA512:
return mbedtls_sha512_finish(ctx->md_ctx, output);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ case MBEDTLS_MD_SHA3_256:
+ case MBEDTLS_MD_SHA3_384:
+ case MBEDTLS_MD_SHA3_512:
+ return mbedtls_sha3_finish(ctx->md_ctx, output, ctx->md_info->size);
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -643,6 +731,16 @@ int mbedtls_md(const mbedtls_md_info_t *md_info, const unsigned char *input, siz
#if defined(MBEDTLS_SHA512_C)
case MBEDTLS_MD_SHA512:
return mbedtls_sha512(input, ilen, output, 0);
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ case MBEDTLS_MD_SHA3_224:
+ return mbedtls_sha3(MBEDTLS_SHA3_224, input, ilen, output, md_info->size);
+ case MBEDTLS_MD_SHA3_256:
+ return mbedtls_sha3(MBEDTLS_SHA3_256, input, ilen, output, md_info->size);
+ case MBEDTLS_MD_SHA3_384:
+ return mbedtls_sha3(MBEDTLS_SHA3_384, input, ilen, output, md_info->size);
+ case MBEDTLS_MD_SHA3_512:
+ return mbedtls_sha3(MBEDTLS_SHA3_512, input, ilen, output, md_info->size);
#endif
default:
return MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -704,6 +802,12 @@ static const int supported_digests[] = {
#if defined(MBEDTLS_MD_CAN_MD5)
MBEDTLS_MD_MD5,
#endif
+#if defined(MBEDTLS_SHA3_C)
+ MBEDTLS_MD_SHA3_224,
+ MBEDTLS_MD_SHA3_256,
+ MBEDTLS_MD_SHA3_384,
+ MBEDTLS_MD_SHA3_512,
+#endif
MBEDTLS_MD_NONE
};
@@ -754,6 +858,17 @@ const mbedtls_md_info_t *mbedtls_md_info_from_string(const char *md_name)
if (!strcmp("SHA512", md_name)) {
return mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
}
+#endif
+#if defined(MBEDTLS_SHA3_C)
+ if (!strcmp("SHA3-224", md_name)) {
+ return mbedtls_md_info_from_type(MBEDTLS_MD_SHA3_224);
+ } else if (!strcmp("SHA3-256", md_name)) {
+ return mbedtls_md_info_from_type(MBEDTLS_MD_SHA3_256);
+ } else if (!strcmp("SHA3-384", md_name)) {
+ return mbedtls_md_info_from_type(MBEDTLS_MD_SHA3_384);
+ } else if (!strcmp("SHA3-512", md_name)) {
+ return mbedtls_md_info_from_type(MBEDTLS_MD_SHA3_512);
+ }
#endif
return NULL;
}
diff --git a/library/md_wrap.h b/library/md_wrap.h
index cd539b54be32..5e1e327e7d9d 100644
--- a/library/md_wrap.h
+++ b/library/md_wrap.h
@@ -73,6 +73,12 @@ extern const mbedtls_md_info_t mbedtls_sha384_info;
#if defined(MBEDTLS_SHA512_C)
extern const mbedtls_md_info_t mbedtls_sha512_info;
#endif
+#if defined(MBEDTLS_SHA3_C)
+extern const mbedtls_md_info_t mbedtls_sha3_224_info;
+extern const mbedtls_md_info_t mbedtls_sha3_256_info;
+extern const mbedtls_md_info_t mbedtls_sha3_384_info;
+extern const mbedtls_md_info_t mbedtls_sha3_512_info;
+#endif
#ifdef __cplusplus
}
diff --git a/library/sha3.c b/library/sha3.c
new file mode 100644
index 000000000000..959928e9da9e
--- /dev/null
+++ b/library/sha3.c
@@ -0,0 +1,622 @@
+/*
+ * 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)
+#include "mbedtls/platform.h"
+#endif /* MBEDTLS_SELF_TEST */
+
+/*
+ * 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 || p->id == MBEDTLS_SHA3_NONE) {
+ 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;
+
+ memset(ctx->state, 0, sizeof(ctx->state));
+ ctx->index = 0;
+
+ 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 || output == NULL) {
+ return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
+ }
+
+ /* Catch SHA-3 families, with fixed output length */
+ if (ctx->olen > 0) {
+ if (ctx->olen > olen) {
+ return MBEDTLS_ERR_SHA3_BAD_INPUT_DATA;
+ }
+ olen = ctx->olen;
+ }
+
+ 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;
+}
+
+/*
+ * 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;
+
+ mbedtls_sha3_init(&ctx);
+
+ /* Sanity checks are performed in every mbedtls_sha3_xxx() */
+ 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;
+}
+
+/**************** Self-tests ****************/
+
+#if defined(MBEDTLS_SELF_TEST)
+
+static const unsigned char test_data[2][4] =
+{
+ "",
+ "abc",
+};
+
+static const size_t test_data_len[2] =
+{
+ 0, /* "" */
+ 3 /* "abc" */
+};
+
+static const unsigned char test_hash_sha3_224[2][28] =
+{
+ { /* "" */
+ 0x6B, 0x4E, 0x03, 0x42, 0x36, 0x67, 0xDB, 0xB7,
+ 0x3B, 0x6E, 0x15, 0x45, 0x4F, 0x0E, 0xB1, 0xAB,
+ 0xD4, 0x59, 0x7F, 0x9A, 0x1B, 0x07, 0x8E, 0x3F,
+ 0x5B, 0x5A, 0x6B, 0xC7
+ },
+ { /* "abc" */
+ 0xE6, 0x42, 0x82, 0x4C, 0x3F, 0x8C, 0xF2, 0x4A,
+ 0xD0, 0x92, 0x34, 0xEE, 0x7D, 0x3C, 0x76, 0x6F,
+ 0xC9, 0xA3, 0xA5, 0x16, 0x8D, 0x0C, 0x94, 0xAD,
+ 0x73, 0xB4, 0x6F, 0xDF
+ }
+};
+
+static const unsigned char test_hash_sha3_256[2][32] =
+{
+ { /* "" */
+ 0xA7, 0xFF, 0xC6, 0xF8, 0xBF, 0x1E, 0xD7, 0x66,
+ 0x51, 0xC1, 0x47, 0x56, 0xA0, 0x61, 0xD6, 0x62,
+ 0xF5, 0x80, 0xFF, 0x4D, 0xE4, 0x3B, 0x49, 0xFA,
+ 0x82, 0xD8, 0x0A, 0x4B, 0x80, 0xF8, 0x43, 0x4A
+ },
+ { /* "abc" */
+ 0x3A, 0x98, 0x5D, 0xA7, 0x4F, 0xE2, 0x25, 0xB2,
+ 0x04, 0x5C, 0x17, 0x2D, 0x6B, 0xD3, 0x90, 0xBD,
+ 0x85, 0x5F, 0x08, 0x6E, 0x3E, 0x9D, 0x52, 0x5B,
+ 0x46, 0xBF, 0xE2, 0x45, 0x11, 0x43, 0x15, 0x32
+ }
+};
+
+static const unsigned char test_hash_sha3_384[2][48] =
+{
+ { /* "" */
+ 0x0C, 0x63, 0xA7, 0x5B, 0x84, 0x5E, 0x4F, 0x7D,
+ 0x01, 0x10, 0x7D, 0x85, 0x2E, 0x4C, 0x24, 0x85,
+ 0xC5, 0x1A, 0x50, 0xAA, 0xAA, 0x94, 0xFC, 0x61,
+ 0x99, 0x5E, 0x71, 0xBB, 0xEE, 0x98, 0x3A, 0x2A,
+ 0xC3, 0x71, 0x38, 0x31, 0x26, 0x4A, 0xDB, 0x47,
+ 0xFB, 0x6B, 0xD1, 0xE0, 0x58, 0xD5, 0xF0, 0x04
+ },
+ { /* "abc" */
+ 0xEC, 0x01, 0x49, 0x82, 0x88, 0x51, 0x6F, 0xC9,
+ 0x26, 0x45, 0x9F, 0x58, 0xE2, 0xC6, 0xAD, 0x8D,
+ 0xF9, 0xB4, 0x73, 0xCB, 0x0F, 0xC0, 0x8C, 0x25,
+ 0x96, 0xDA, 0x7C, 0xF0, 0xE4, 0x9B, 0xE4, 0xB2,
+ 0x98, 0xD8, 0x8C, 0xEA, 0x92, 0x7A, 0xC7, 0xF5,
+ 0x39, 0xF1, 0xED, 0xF2, 0x28, 0x37, 0x6D, 0x25
+ }
+};
+
+static const unsigned char test_hash_sha3_512[2][64] =
+{
+ { /* "" */
+ 0xA6, 0x9F, 0x73, 0xCC, 0xA2, 0x3A, 0x9A, 0xC5,
+ 0xC8, 0xB5, 0x67, 0xDC, 0x18, 0x5A, 0x75, 0x6E,
+ 0x97, 0xC9, 0x82, 0x16, 0x4F, 0xE2, 0x58, 0x59,
+ 0xE0, 0xD1, 0xDC, 0xC1, 0x47, 0x5C, 0x80, 0xA6,
+ 0x15, 0xB2, 0x12, 0x3A, 0xF1, 0xF5, 0xF9, 0x4C,
+ 0x11, 0xE3, 0xE9, 0x40, 0x2C, 0x3A, 0xC5, 0x58,
+ 0xF5, 0x00, 0x19, 0x9D, 0x95, 0xB6, 0xD3, 0xE3,
+ 0x01, 0x75, 0x85, 0x86, 0x28, 0x1D, 0xCD, 0x26
+ },
+ { /* "abc" */
+ 0xB7, 0x51, 0x85, 0x0B, 0x1A, 0x57, 0x16, 0x8A,
+ 0x56, 0x93, 0xCD, 0x92, 0x4B, 0x6B, 0x09, 0x6E,
+ 0x08, 0xF6, 0x21, 0x82, 0x74, 0x44, 0xF7, 0x0D,
+ 0x88, 0x4F, 0x5D, 0x02, 0x40, 0xD2, 0x71, 0x2E,
+ 0x10, 0xE1, 0x16, 0xE9, 0x19, 0x2A, 0xF3, 0xC9,
+ 0x1A, 0x7E, 0xC5, 0x76, 0x47, 0xE3, 0x93, 0x40,
+ 0x57, 0x34, 0x0B, 0x4C, 0xF4, 0x08, 0xD5, 0xA5,
+ 0x65, 0x92, 0xF8, 0x27, 0x4E, 0xEC, 0x53, 0xF0
+ }
+};
+
+static const unsigned char long_kat_hash_sha3_224[28] =
+{
+ 0xD6, 0x93, 0x35, 0xB9, 0x33, 0x25, 0x19, 0x2E,
+ 0x51, 0x6A, 0x91, 0x2E, 0x6D, 0x19, 0xA1, 0x5C,
+ 0xB5, 0x1C, 0x6E, 0xD5, 0xC1, 0x52, 0x43, 0xE7,
+ 0xA7, 0xFD, 0x65, 0x3C
+};
+
+static const unsigned char long_kat_hash_sha3_256[32] =
+{
+ 0x5C, 0x88, 0x75, 0xAE, 0x47, 0x4A, 0x36, 0x34,
+ 0xBA, 0x4F, 0xD5, 0x5E, 0xC8, 0x5B, 0xFF, 0xD6,
+ 0x61, 0xF3, 0x2A, 0xCA, 0x75, 0xC6, 0xD6, 0x99,
+ 0xD0, 0xCD, 0xCB, 0x6C, 0x11, 0x58, 0x91, 0xC1
+};
+
+static const unsigned char long_kat_hash_sha3_384[48] =
+{
+ 0xEE, 0xE9, 0xE2, 0x4D, 0x78, 0xC1, 0x85, 0x53,
+ 0x37, 0x98, 0x34, 0x51, 0xDF, 0x97, 0xC8, 0xAD,
+ 0x9E, 0xED, 0xF2, 0x56, 0xC6, 0x33, 0x4F, 0x8E,
+ 0x94, 0x8D, 0x25, 0x2D, 0x5E, 0x0E, 0x76, 0x84,
+ 0x7A, 0xA0, 0x77, 0x4D, 0xDB, 0x90, 0xA8, 0x42,
+ 0x19, 0x0D, 0x2C, 0x55, 0x8B, 0x4B, 0x83, 0x40
+};
+
+static const unsigned char long_kat_hash_sha3_512[64] =
+{
+ 0x3C, 0x3A, 0x87, 0x6D, 0xA1, 0x40, 0x34, 0xAB,
+ 0x60, 0x62, 0x7C, 0x07, 0x7B, 0xB9, 0x8F, 0x7E,
+ 0x12, 0x0A, 0x2A, 0x53, 0x70, 0x21, 0x2D, 0xFF,
+ 0xB3, 0x38, 0x5A, 0x18, 0xD4, 0xF3, 0x88, 0x59,
+ 0xED, 0x31, 0x1D, 0x0A, 0x9D, 0x51, 0x41, 0xCE,
+ 0x9C, 0xC5, 0xC6, 0x6E, 0xE6, 0x89, 0xB2, 0x66,
+ 0xA8, 0xAA, 0x18, 0xAC, 0xE8, 0x28, 0x2A, 0x0E,
+ 0x0D, 0xB5, 0x96, 0xC9, 0x0B, 0x0A, 0x7B, 0x87
+};
+
+static int mbedtls_sha3_kat_test(int verbose,
+ const char *type_name,
+ mbedtls_sha3_id id,
+ int test_num)
+{
+ uint8_t hash[64];
+ int result;
+
+ result = mbedtls_sha3(id,
+ test_data[test_num], test_data_len[test_num],
+ hash, sizeof(hash));
+ if (result != 0) {
+ if (verbose != 0) {
+ mbedtls_printf(" %s test %d error code: %d\n",
+ type_name, test_num, result);
+ }
+
+ return result;
+ }
+
+ switch (id) {
+ case MBEDTLS_SHA3_224:
+ result = memcmp(hash, test_hash_sha3_224[test_num], 28);
+ break;
+ case MBEDTLS_SHA3_256:
+ result = memcmp(hash, test_hash_sha3_256[test_num], 32);
+ break;
+ case MBEDTLS_SHA3_384:
+ result = memcmp(hash, test_hash_sha3_384[test_num], 48);
+ break;
+ case MBEDTLS_SHA3_512:
+ result = memcmp(hash, test_hash_sha3_512[test_num], 64);
+ break;
+ default:
+ break;
+ }
+
+ if (0 != result) {
+ if (verbose != 0) {
+ mbedtls_printf(" %s test %d failed\n", type_name, test_num);
+ }
+
+ return -1;
+ }
+
+ if (verbose != 0) {
+ mbedtls_printf(" %s test %d passed\n", type_name, test_num);
+ }
+
+ return 0;
+}
+
+static int mbedtls_sha3_long_kat_test(int verbose,
+ const char *type_name,
+ mbedtls_sha3_id id)
+{
+ mbedtls_sha3_context ctx;
+ unsigned char buffer[1000];
+ unsigned char hash[64];
+ int i;
+ int result = 0;
+
+ memset(buffer, 'a', 1000);
+
+ if (verbose != 0) {
+ mbedtls_printf(" %s long KAT test ", type_name);
+ }
+
+ mbedtls_sha3_init(&ctx);
+
+ result = mbedtls_sha3_starts(&ctx, id);
+ if (result != 0) {
+ if (verbose != 0) {
+ mbedtls_printf("setup failed\n ");
+ }
+ }
+
+ /* Process 1,000,000 (one million) 'a' characters */
+ for (i = 0; i < 1000; i++) {
+ result = mbedtls_sha3_update(&ctx, buffer, 1000);
+ if (result != 0) {
+ if (verbose != 0) {
+ mbedtls_printf("update error code: %i\n", result);
+ }
+
+ goto cleanup;
+ }
+ }
+
+ result = mbedtls_sha3_finish(&ctx, hash, sizeof(hash));
+ if (result != 0) {
+ if (verbose != 0) {
+ mbedtls_printf("finish error code: %d\n", result);
+ }
+
+ goto cleanup;
+ }
+
+ switch (id) {
+ case MBEDTLS_SHA3_224:
+ result = memcmp(hash, long_kat_hash_sha3_224, 28);
+ break;
+ case MBEDTLS_SHA3_256:
+ result = memcmp(hash, long_kat_hash_sha3_256, 32);
+ break;
+ case MBEDTLS_SHA3_384:
+ result = memcmp(hash, long_kat_hash_sha3_384, 48);
+ break;
+ case MBEDTLS_SHA3_512:
+ result = memcmp(hash, long_kat_hash_sha3_512, 64);
+ break;
+ default:
+ break;
+ }
+
+ if (result != 0) {
+ if (verbose != 0) {
+ mbedtls_printf("failed\n");
+ }
+ }
+
+ if (verbose != 0) {
+ mbedtls_printf("passed\n");
+ }
+
+cleanup:
+ mbedtls_sha3_free(&ctx);
+ return result;
+}
+
+int mbedtls_sha3_self_test(int verbose)
+{
+ int i;
+
+ /* SHA3 Known Answer Tests (KAT) */
+ for (i = 0; i < 2; i++) {
+ if (0 != mbedtls_sha3_kat_test(verbose,
+ "SHA3-224", MBEDTLS_SHA3_224, i)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_kat_test(verbose,
+ "SHA3-256", MBEDTLS_SHA3_256, i)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_kat_test(verbose,
+ "SHA3-384", MBEDTLS_SHA3_384, i)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_kat_test(verbose,
+ "SHA3-512", MBEDTLS_SHA3_512, i)) {
+ return 1;
+ }
+ }
+
+ /* SHA3 long KAT tests */
+ if (0 != mbedtls_sha3_long_kat_test(verbose,
+ "SHA3-224", MBEDTLS_SHA3_224)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_long_kat_test(verbose,
+ "SHA3-256", MBEDTLS_SHA3_256)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_long_kat_test(verbose,
+ "SHA3-384", MBEDTLS_SHA3_384)) {
+ return 1;
+ }
+
+ if (0 != mbedtls_sha3_long_kat_test(verbose,
+ "SHA3-512", MBEDTLS_SHA3_512)) {
+ return 1;
+ }
+
+ if (verbose != 0) {
+ mbedtls_printf("\n");
+ }
+
+ return 0;
+}
+#endif /* MBEDTLS_SELF_TEST */
+
+#endif /* MBEDTLS_SHA3_C */
diff --git a/programs/test/benchmark.c b/programs/test/benchmark.c
index 226faf35c3de..ecc4e94a6342 100644
--- a/programs/test/benchmark.c
+++ b/programs/test/benchmark.c
@@ -39,6 +39,7 @@ int main(void)
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
+#include "mbedtls/sha3.h"
#include "mbedtls/des.h"
#include "mbedtls/aes.h"
@@ -113,11 +114,12 @@ static void mbedtls_set_alarm(int seconds);
#define TITLE_LEN 25
#define OPTIONS \
- "md5, ripemd160, sha1, sha256, sha512,\n" \
- "des3, des, camellia, chacha20,\n" \
+ "md5, ripemd160, sha1, sha256, sha512,\n" \
+ "sha3_224, sha3_256, sha3_384, sha3_512,\n" \
+ "des3, des, camellia, chacha20,\n" \
"aes_cbc, aes_gcm, aes_ccm, aes_xts, chachapoly,\n" \
"aes_cmac, des3_cmac, poly1305\n" \
- "ctr_drbg, hmac_drbg\n" \
+ "ctr_drbg, hmac_drbg\n" \
"rsa, dhm, ecdsa, ecdh.\n"
#if defined(MBEDTLS_ERROR_C)
@@ -506,6 +508,7 @@ unsigned char buf[BUFSIZE];
typedef struct {
char md5, ripemd160, sha1, sha256, sha512,
+ sha3_224, sha3_256, sha3_384, sha3_512,
des3, des,
aes_cbc, aes_gcm, aes_ccm, aes_xts, chachapoly,
aes_cmac, des3_cmac,
@@ -553,6 +556,14 @@ int main(int argc, char *argv[])
todo.sha256 = 1;
} else if (strcmp(argv[i], "sha512") == 0) {
todo.sha512 = 1;
+ } else if (strcmp(argv[i], "sha3_224") == 0) {
+ todo.sha3_224 = 1;
+ } else if (strcmp(argv[i], "sha3_256") == 0) {
+ todo.sha3_256 = 1;
+ } else if (strcmp(argv[i], "sha3_384") == 0) {
+ todo.sha3_384 = 1;
+ } else if (strcmp(argv[i], "sha3_512") == 0) {
+ todo.sha3_512 = 1;
} else if (strcmp(argv[i], "des3") == 0) {
todo.des3 = 1;
} else if (strcmp(argv[i], "des") == 0) {
@@ -645,6 +656,20 @@ int main(int argc, char *argv[])
TIME_AND_TSC("SHA-512", mbedtls_sha512(buf, BUFSIZE, tmp, 0));
}
#endif
+#if defined(MBEDTLS_SHA3_C)
+ if (todo.sha3_224) {
+ TIME_AND_TSC("SHA3-224", mbedtls_sha3(MBEDTLS_SHA3_224, buf, BUFSIZE, tmp, 28));
+ }
+ if (todo.sha3_256) {
+ TIME_AND_TSC("SHA3-256", mbedtls_sha3(MBEDTLS_SHA3_256, buf, BUFSIZE, tmp, 32));
+ }
+ if (todo.sha3_384) {
+ TIME_AND_TSC("SHA3-384", mbedtls_sha3(MBEDTLS_SHA3_384, buf, BUFSIZE, tmp, 48));
+ }
+ if (todo.sha3_512) {
+ TIME_AND_TSC("SHA3-512", mbedtls_sha3(MBEDTLS_SHA3_512, buf, BUFSIZE, tmp, 64));
+ }
+#endif
#if defined(MBEDTLS_DES_C)
#if defined(MBEDTLS_CIPHER_MODE_CBC)
diff --git a/programs/test/selftest.c b/programs/test/selftest.c
index 13423a1a6af3..f896d4f9da09 100644
--- a/programs/test/selftest.c
+++ b/programs/test/selftest.c
@@ -33,6 +33,7 @@
#include "mbedtls/sha1.h"
#include "mbedtls/sha256.h"
#include "mbedtls/sha512.h"
+#include "mbedtls/sha3.h"
#include "mbedtls/des.h"
#include "mbedtls/aes.h"
#include "mbedtls/camellia.h"
@@ -251,6 +252,9 @@ const selftest_t selftests[] =
#if defined(MBEDTLS_SHA512_C)
{ "sha512", mbedtls_sha512_self_test },
#endif
+#if defined(MBEDTLS_SHA3_C)
+ { "sha3", mbedtls_sha3_self_test },
+#endif
#if defined(MBEDTLS_DES_C)
{ "des", mbedtls_des_self_test },
#endif
diff --git a/scripts/generate_errors.pl b/scripts/generate_errors.pl
index 878cfba33cf8..664a349e9823 100755
--- a/scripts/generate_errors.pl
+++ b/scripts/generate_errors.pl
@@ -49,7 +49,7 @@
CAMELLIA CCM CHACHA20 CHACHAPOLY CMAC CTR_DRBG DES
ENTROPY ERROR GCM HKDF HMAC_DRBG LMS 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 PKCS7 );
diff --git a/tests/scripts/depends.py b/tests/scripts/depends.py
index b29ea0aa61ac..61908eb817a9 100755
--- a/tests/scripts/depends.py
+++ b/tests/scripts/depends.py
@@ -426,7 +426,8 @@ def __init__(self, options, conf):
'hashes': DualDomain(hash_symbols, build_and_test,
exclude=r'MBEDTLS_(MD|RIPEMD|SHA1_)' \
'|MBEDTLS_SHA224_' \
- '|MBEDTLS_SHA384_'),
+ '|MBEDTLS_SHA384_' \
+ '|MBEDTLS_SHA3_'),
# Key exchange types.
'kex': ExclusiveDomain(key_exchange_symbols, build_and_test),
'pkalgs': ComplementaryDomain(['MBEDTLS_ECDSA_C',
diff --git a/tests/suites/test_suite_md.data b/tests/suites/test_suite_md.data
index ccc7b10ae4a1..0b0afee723b7 100644
--- a/tests/suites/test_suite_md.data
+++ b/tests/suites/test_suite_md.data
@@ -33,6 +33,22 @@ Information on SHA512
depends_on:MBEDTLS_MD_CAN_SHA512
md_info:MBEDTLS_MD_SHA512:"SHA512":64
+Information on SHA3-224
+depends_on:MBEDTLS_SHA3_C
+md_info:MBEDTLS_MD_SHA3_224:"SHA3-224":28
+
+Information on SHA3-256
+depends_on:MBEDTLS_SHA3_C
+md_info:MBEDTLS_MD_SHA3_256:"SHA3-256":32
+
+Information on SHA3-384
+depends_on:MBEDTLS_SHA3_C
+md_info:MBEDTLS_MD_SHA3_384:"SHA3-384":48
+
+Information on SHA3-512
+depends_on:MBEDTLS_SHA3_C
+md_info:MBEDTLS_MD_SHA3_512:"SHA3-512":64
+
generic mbedtls_md5 Test vector RFC1321 #1
depends_on:MBEDTLS_MD_CAN_MD5
md_text:MBEDTLS_MD_MD5:"":"d41d8cd98f00b204e9800998ecf8427e"
@@ -93,6 +109,22 @@ generic mbedtls_ripemd160 Test vector from paper #8
depends_on:MBEDTLS_MD_CAN_RIPEMD160
md_text:MBEDTLS_MD_RIPEMD160:"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+generic mbedtls_sha3 SHA3-224 Test vector from CAVS 19.0 with Len = 8
+depends_on:MBEDTLS_SHA3_C
+md_hex:MBEDTLS_MD_SHA3_224:"01":"488286d9d32716e5881ea1ee51f36d3660d70f0db03b3f612ce9eda4"
+
+generic mbedtls_sha3 SHA3-256 Test vector from CAVS 19.0 with Len = 8
+depends_on:MBEDTLS_SHA3_C
+md_hex:MBEDTLS_MD_SHA3_256:"e9":"f0d04dd1e6cfc29a4460d521796852f25d9ef8d28b44ee91ff5b759d72c1e6d6"
+
+generic mbedtls_sha3 SHA3-384 Test vector from CAVS 19.0 with Len = 8
+depends_on:MBEDTLS_SHA3_C
+md_hex:MBEDTLS_MD_SHA3_384:"80":"7541384852e10ff10d5fb6a7213a4a6c15ccc86d8bc1068ac04f69277142944f4ee50d91fdc56553db06b2f5039c8ab7"
+
+generic mbedtls_sha3 SHA3-512 Test vector from CAVS 19.0 with Len = 8
+depends_on:MBEDTLS_SHA3_C
+md_hex:MBEDTLS_MD_SHA3_512:"e5":"150240baf95fb36f8ccb87a19a41767e7aed95125075a2b2dbba6e565e1ce8575f2b042b62e29a04e9440314a821c6224182964d8b557b16a492b3806f4c39c1"
+
generic HMAC-MD5 Hash File OpenSSL test #1
depends_on:MBEDTLS_MD_CAN_MD5
mbedtls_md_hmac:MBEDTLS_MD_MD5:16:"61616161616161616161616161616161":"b91ce5ac77d33c234e61002ed6":"42552882f00bd4633ea81135a184b284"
@@ -225,6 +257,22 @@ generic multi step mbedtls_ripemd160 Test vector from paper #8
depends_on:MBEDTLS_MD_CAN_RIPEMD160
md_text_multi:MBEDTLS_MD_RIPEMD160:"12345678901234567890123456789012345678901234567890123456789012345678901234567890":"9b752e45573d4b39f4dbd3323cab82bf63326bfb"
+generic multi step mbedtls_sha3 SHA3-224 Test vector from CAVS 19.0 with Len = 48
+depends_on:MBEDTLS_SHA3_C
+md_hex_multi:MBEDTLS_MD_SHA3_224:"e7183e4d89c9":"650618f3b945c07de85b8478d69609647d5e2a432c6b15fbb3db91e4"
+
+generic multi step mbedtls_sha3 SHA3-256 Test vector from CAVS 19.0 with Len = 48
+depends_on:MBEDTLS_SHA3_C
+md_hex_multi:MBEDTLS_MD_SHA3_256:"e6fd42037f80":"2294f8d3834f24aa9037c431f8c233a66a57b23fa3de10530bbb6911f6e1850f"
+
+generic multi step mbedtls_sha3 SHA3-384 Test vector from CAVS 19.0 with Len = 48
+depends_on:MBEDTLS_SHA3_C
+md_hex_multi:MBEDTLS_MD_SHA3_384:"5a6659e9f0e7":"21b1f3f63b907f968821185a7fe30b16d47e1d6ee5b9c80be68947854de7a8ef4a03a6b2e4ec96abdd4fa29ab9796f28"
+
+generic multi step mbedtls_sha3 SHA3-512 Test vector from CAVS 19.0 with Len = 48
+depends_on:MBEDTLS_SHA3_C
+md_hex_multi:MBEDTLS_MD_SHA3_512:"71a986d2f662":"def6aac2b08c98d56a0501a8cb93f5b47d6322daf99e03255457c303326395f765576930f8571d89c01e727cc79c2d4497f85c45691b554e20da810c2bc865ef"
+
generic multi step HMAC-MD5 Hash File OpenSSL test #1
depends_on:MBEDTLS_MD_CAN_MD5
md_hmac_multi:MBEDTLS_MD_MD5:16:"61616161616161616161616161616161":"b91ce5ac77d33c234e61002ed6":"42552882f00bd4633ea81135a184b284"
@@ -473,6 +521,70 @@ generic HMAC-SHA-512 Test Vector NIST CAVS #6
depends_on:MBEDTLS_MD_CAN_SHA512
mbedtls_md_hmac:MBEDTLS_MD_SHA512:48:"8ab783d5acf32efa0d9c0a21abce955e96630d89":"17371e013dce839963d54418e97be4bd9fa3cb2a368a5220f5aa1b8aaddfa3bdefc91afe7c717244fd2fb640f5cb9d9bf3e25f7f0c8bc758883b89dcdce6d749d9672fed222277ece3e84b3ec01b96f70c125fcb3cbee6d19b8ef0873f915f173bdb05d81629ba187cc8ac1934b2f75952fb7616ae6bd812946df694bd2763af":"9ac7ca8d1aefc166b046e4cf7602ebe181a0e5055474bff5b342106731da0d7e48e4d87bc0a6f05871574289a1b099f8"
+HMAC-SHA3-224: NIST example #1: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+mbedtls_md_hmac:MBEDTLS_MD_SHA3_224:28:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59"
+
+HMAC-SHA3-224: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+mbedtls_md_hmac:MBEDTLS_MD_SHA3_256:32:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"
+
+HMAC-SHA3-256: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+mbedtls_md_hmac:MBEDTLS_MD_SHA3_384:48:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394959697":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac"
+
+HMAC-SHA3-384: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+mbedtls_md_hmac:MBEDTLS_MD_SHA3_512:64:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915"
+
+HMAC-SHA3-512: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+md_hmac_multi:MBEDTLS_MD_SHA3_224:28:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7a8a9aaab":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"078695eecc227c636ad31d063a15dd05a7e819a66ec6d8de1e193e59"
+
+HMAC-SHA3-224 multi-step: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+md_hmac_multi:MBEDTLS_MD_SHA3_256:32:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9fa0a1a2a3a4a5a6a7":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"9bcf2c238e235c3ce88404e813bd2f3a97185ac6f238c63d6229a00b07974258"
+
+HMAC-SHA3-256 multi-step: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+md_hmac_multi:MBEDTLS_MD_SHA3_384:48:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f808182838485868788898a8b8c8d8e8f9091929394959697":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"e5ae4c739f455279368ebf36d4f5354c95aa184c899d3870e460ebc288ef1f9470053f73f7c6da2a71bcaec38ce7d6ac"
+
+HMAC-SHA3-384 multi-step: NIST example #4: keylenblocklen
+depends_on:MBEDTLS_SHA3_C
+md_hmac_multi:MBEDTLS_MD_SHA3_512:64:"000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f8081828384858687":"53616d706c65206d65737361676520666f72206b65796c656e3e626c6f636b6c656e":"5f464f5e5b7848e3885e49b2c385f0694985d0e38966242dc4a5fe3fea4b37d46b65ceced5dcf59438dd840bab22269f0ba7febdb9fcf74602a35666b2a32915"
+
+HMAC-SHA3-512 multi-step: NIST example #4: keylenlen);
+
+ TEST_ASSERT(mbedtls_sha3(family, in->x, in->len, output, hash->len) == 0);
+
+ ASSERT_COMPARE(output, hash->len, hash->x, hash->len);
+
+exit:
+ mbedtls_free(output);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA3_C */
+void mbedtls_sha3_multi(int family, data_t *in, data_t *hash)
+{
+ unsigned char *output = NULL;
+ mbedtls_sha3_context ctx;
+ const unsigned int block_size = 256;
+
+ ASSERT_ALLOC(output, hash->len);
+
+ mbedtls_sha3_init(&ctx);
+ mbedtls_sha3_starts(&ctx, family);
+
+ for (size_t l = 0; l < in->len; l += block_size) {
+ TEST_ASSERT(mbedtls_sha3_update(&ctx, in->x + l, MIN(in->len - l, block_size)) == 0);
+ }
+
+ TEST_ASSERT(mbedtls_sha3_finish(&ctx, output, hash->len) == 0);
+
+ ASSERT_COMPARE(output, hash->len, hash->x, hash->len);
+
+exit:
+ mbedtls_free(output);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA3_C */
+void sha3_streaming(int type, data_t *input)
+{
+ mbedtls_sha3_context ctx;
+ unsigned char reference_hash[64];
+ unsigned char hash[64];
+ size_t chunk_size;
+ size_t hash_length = (type == MBEDTLS_SHA3_224 ? 28 :
+ type == MBEDTLS_SHA3_256 ? 32 :
+ type == MBEDTLS_SHA3_384 ? 48 :
+ type == MBEDTLS_SHA3_512 ? 64 :
+ 0);
+
+ mbedtls_sha3_init(&ctx);
+ memset(reference_hash, 0, sizeof(reference_hash));
+ memset(hash, 0, sizeof(hash));
+ TEST_ASSERT(hash_length != 0);
+
+ /* Generate a reference hash */
+ mbedtls_sha3(type, input->x, input->len, reference_hash, hash_length);
+
+ /* Repeat each test with increasingly-sized data chunks
+ * E.g. start by processing bytes individual bytes, then 2-byte chunks,
+ * then 3-byte chunks, and so on...
+ * At each test ensure that the same hash is generated.
+ */
+ for (chunk_size = 1; chunk_size < input->len; chunk_size++) {
+ size_t i;
+ size_t remaining = input->len;
+
+ mbedtls_sha3_init(&ctx);
+ TEST_ASSERT(mbedtls_sha3_starts(&ctx, type) == 0);
+
+ for (i = 0; i < input->len; i += chunk_size) {
+ size_t len = remaining >= chunk_size ? chunk_size : remaining;
+ TEST_ASSERT(mbedtls_sha3_update(&ctx, input->x + i, len) == 0);
+ remaining -= len;
+ }
+
+ mbedtls_sha3_finish(&ctx, hash, hash_length);
+ mbedtls_sha3_free(&ctx);
+
+ ASSERT_COMPARE(hash, hash_length, reference_hash, hash_length);
+ }
+
+exit:
+ mbedtls_sha3_free(&ctx);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA3_C */
+void sha3_reuse(data_t *input1, data_t *hash1,
+ data_t *input2, data_t *hash2)
+{
+ unsigned char output[64];
+ mbedtls_sha3_context ctx;
+ mbedtls_sha3_id type1, type2;
+
+ mbedtls_sha3_init(&ctx);
+ switch (hash1->len) {
+ case 28: type1 = MBEDTLS_SHA3_224; break;
+ case 32: type1 = MBEDTLS_SHA3_256; break;
+ case 48: type1 = MBEDTLS_SHA3_384; break;
+ case 64: type1 = MBEDTLS_SHA3_512; break;
+ default: TEST_ASSERT(!"hash1->len validity"); break;
+ }
+ switch (hash2->len) {
+ case 28: type2 = MBEDTLS_SHA3_224; break;
+ case 32: type2 = MBEDTLS_SHA3_256; break;
+ case 48: type2 = MBEDTLS_SHA3_384; break;
+ case 64: type2 = MBEDTLS_SHA3_512; break;
+ default: TEST_ASSERT(!"hash2->len validity"); break;
+ }
+
+ /* Round 1 */
+ TEST_ASSERT(mbedtls_sha3_starts(&ctx, type1) == 0);
+ TEST_ASSERT(mbedtls_sha3_update(&ctx, input1->x, input1->len) == 0);
+ TEST_ASSERT(mbedtls_sha3_finish(&ctx, output, sizeof(output)) == 0);
+ ASSERT_COMPARE(output, hash1->len, hash1->x, hash1->len);
+
+ /* Round 2 */
+ TEST_ASSERT(mbedtls_sha3_starts(&ctx, type2) == 0);
+ TEST_ASSERT(mbedtls_sha3_update(&ctx, input2->x, input2->len) == 0);
+ TEST_ASSERT(mbedtls_sha3_finish(&ctx, output, sizeof(output)) == 0);
+ ASSERT_COMPARE(output, hash2->len, hash2->x, hash2->len);
+
+exit:
+ mbedtls_sha3_free(&ctx);
+}
+/* END_CASE */
+
+/* BEGIN_CASE depends_on:MBEDTLS_SHA3_C:MBEDTLS_SELF_TEST */
+void sha3_selftest()
+{
+ TEST_ASSERT(mbedtls_sha3_self_test(0) == 0);
+}
+/* END_CASE */