Mailing List Archive

[PATCH gnupg 1/1] Addition of cSHAKE and KMAC
---
cipher/cshake-common.c | 142 +++++++++++++++
cipher/cshake-common.h | 63 +++++++
cipher/keccak.c | 215 +++++++++++++++++++++++
cipher/keccak.h | 36 ++++
cipher/mac-internal.h | 22 +++
cipher/mac-kmac.c | 380 +++++++++++++++++++++++++++++++++++++++++
cipher/mac.c | 14 ++
cipher/md.c | 50 +++++-
configure.ac | 2 +-
doc/gcrypt.texi | 31 +++-
src/cipher.h | 2 +
src/fips.c | 2 +
src/gcrypt-int.h | 1 +
src/gcrypt.h.in | 14 +-
src/visibility.c | 1 +
src/visibility.h | 1 +
tests/Makefile.am | 2 +-
tests/basic.c | 313 ++++++++++++++++++++++++++++++++-
tests/cshake.c | 335 ++++++++++++++++++++++++++++++++++++
19 files changed, 1615 insertions(+), 11 deletions(-)
create mode 100644 cipher/cshake-common.c
create mode 100644 cipher/cshake-common.h
create mode 100644 cipher/keccak.h
create mode 100644 cipher/mac-kmac.c
create mode 100644 tests/cshake.c

diff --git a/cipher/cshake-common.c b/cipher/cshake-common.c
new file mode 100644
index 00000000..e0ef15ee
--- /dev/null
+++ b/cipher/cshake-common.c
@@ -0,0 +1,142 @@
+/* cshake-common.c - Some helpers for cSHAKE and KMAC
+ * Copyright (C) 2023 MTG AG
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "cshake-common.h"
+
+
+
+/**
+ * @brief Append data to a buffer
+ *
+ * @param buf the buffer to append data to
+ * @param data data to append
+ * @param len length of the data
+ *
+ * @return 0 on success, 1 if the buffer is overfilled
+ */
+int
+_gcry_cshake_append_to_buffer (gcry_buffer_t *buf,
+ const unsigned char *data,
+ size_t len)
+{
+ if (buf->size - buf->len < len)
+ {
+ return 1;
+ }
+ memcpy (((unsigned char*) buf->data) + buf->len, data, len);
+ buf->len += len;
+ return 0;
+}
+
+static int
+append_byte_to_buffer (gcry_buffer_t *buf, const unsigned char b)
+{
+ return _gcry_cshake_append_to_buffer (buf, &b, 1);
+}
+
+/**
+ * Performs left_encode or right_encode as defined in
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf.
+ * Caller must ensure that sufficient capacity is left in the output buffer.
+ * The function appends at most one byte more (one because of additional length
+ * octed) than the byte size
+ * needed to represent the value of the input parameter s.
+ */
+static size_t
+left_or_right_encode (size_t s,
+ gcry_buffer_t *output_buffer,
+ encoded_direction_t dir)
+{
+ int i;
+ size_t bytes_appended = 0;
+ // determine number of octets needed to encode s
+ for (i = sizeof (s); i > 0; i--)
+ {
+ unsigned char t = (s >> ((i - 1) * 8) & (size_t)0xFF);
+ if (t != 0)
+ {
+ break;
+ }
+ }
+ if (i == 0)
+ {
+ i = 1;
+ }
+ if (dir == left)
+ {
+ if (append_byte_to_buffer (output_buffer, i))
+ {
+ /* error */
+ return 0;
+ }
+ bytes_appended++;
+ }
+ // big endian encoding of s
+ for (int j = i; j > 0; j--)
+ {
+ if (append_byte_to_buffer (output_buffer,
+ s >> (j - 1) * 8 & ((size_t)0xFF)))
+ {
+ /* error */
+ return 0;
+ }
+ bytes_appended++;
+ }
+ if (dir == right)
+ {
+ if (append_byte_to_buffer (output_buffer, (unsigned char)i))
+ {
+ /* error */
+ return 0;
+ }
+ bytes_appended++;
+ }
+ return bytes_appended;
+}
+
+size_t
+_gcry_cshake_left_encode (size_t s,
+ gcry_buffer_t *output_buffer)
+{
+ return left_or_right_encode (s, output_buffer, left);
+}
+
+size_t
+_gcry_cshake_right_encode (size_t s,
+ gcry_buffer_t *output_buffer)
+{
+ size_t result = left_or_right_encode (s, output_buffer, right);
+ return result;
+}
+
+/**
+ * Convert byte length to bit length. Returns zero on overflow, i.e.
+ * precondition that bit length fits into size_t has to be checked by the
+ * caller.
+ */
+size_t
+_gcry_cshake_bit_len_from_byte_len (size_t byte_length)
+{
+ size_t bit_length = 8 * byte_length;
+ if (bit_length < byte_length)
+ {
+ return 0;
+ }
+ return bit_length;
+}
diff --git a/cipher/cshake-common.h b/cipher/cshake-common.h
new file mode 100644
index 00000000..c05e4b39
--- /dev/null
+++ b/cipher/cshake-common.h
@@ -0,0 +1,63 @@
+/* cshake-common.h - Some helpers for cSHAKE and KMAC
+ * Copyright (C) 2012-2017 Jussi Kivilinna <jussi.kivilinna@iki.fi>
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+#ifndef GCRYPT_CSHAKE_COMMON_H
+#define GCRYPT_CSHAKE_COMMON_H
+
+
+#include <config.h>
+#include "g10lib.h"
+#include <stddef.h>
+#include "gcrypt.h"
+
+typedef enum
+{
+ left = 1,
+ right = 2
+} encoded_direction_t;
+
+size_t _gcry_cshake_bit_len_from_byte_len (size_t byte_length);
+
+
+int _gcry_cshake_append_byte_to_buffer (gcry_buffer_t *buf,
+ const unsigned char byte);
+
+/**
+ * Performs left_encode as defined in
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf.
+ * Caller must ensure that sufficient capacity is left in the output buffer to
+ * perform the encoding. The function appends at most one byte more (one
+ * because of additional length octed) than the byte size needed to represent
+ * the value of the input parameter s.
+ */
+size_t _gcry_cshake_left_encode (size_t s, gcry_buffer_t *output_buffer);
+
+
+/**
+ * Performs right_encode as defined in
+ * https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-185.pdf.
+ * Caller must ensure that sufficient capacity is left in the output buffer to
+ * perform the encoding. The function appends at most one byte more (one
+ * because of additional length octed) than the byte size needed to represent
+ * the value of the input parameter s.
+ */
+size_t _gcry_cshake_right_encode (size_t s, gcry_buffer_t *output_buffer);
+
+
+
+#endif
diff --git a/cipher/keccak.c b/cipher/keccak.c
index 9883af4d..8d7b9f87 100644
--- a/cipher/keccak.c
+++ b/cipher/keccak.c
@@ -25,6 +25,8 @@
#include "bufhelp.h"
#include "cipher.h"
#include "hash-common.h"
+#include "keccak.h"
+#include "cshake-common.h"



@@ -112,6 +114,7 @@

#define SHA3_DELIMITED_SUFFIX 0x06
#define SHAKE_DELIMITED_SUFFIX 0x1F
+#define CSHAKE_DELIMITED_SUFFIX 0x04


typedef struct
@@ -154,6 +157,14 @@ typedef struct KECCAK_CONTEXT_S
#endif
} KECCAK_CONTEXT;

+typedef struct CSHAKE_CONTEXT_S
+{
+ KECCAK_CONTEXT keccak_ctx;
+ unsigned int rate_in_bytes;
+ size_t written_bytes_n_s;
+ int n_set;
+ int s_set;
+} CSHAKE_CONTEXT;


#ifdef NEED_COMMON64
@@ -1025,11 +1036,13 @@ keccak_init (int algo, void *context, unsigned int flags)
ctx->blocksize = 576 / 8;
ctx->outlen = 512 / 8;
break;
+ case GCRY_MD_CSHAKE128:
case GCRY_MD_SHAKE128:
ctx->suffix = SHAKE_DELIMITED_SUFFIX;
ctx->blocksize = 1344 / 8;
ctx->outlen = 256 / 8;
break;
+ case GCRY_MD_CSHAKE256:
case GCRY_MD_SHAKE256:
ctx->suffix = SHAKE_DELIMITED_SUFFIX;
ctx->blocksize = 1088 / 8;
@@ -1059,9 +1072,11 @@ keccak_init (int algo, void *context, unsigned int flags)
case GCRY_MD_SHA3_512:
kimd_func = KMID_FUNCTION_SHA3_512;
break;
+ case GCRY_MD_CSHAKE128:
case GCRY_MD_SHAKE128:
kimd_func = KMID_FUNCTION_SHAKE128;
break;
+ case GCRY_MD_CSHAKE256:
case GCRY_MD_SHAKE256:
kimd_func = KMID_FUNCTION_SHAKE256;
break;
@@ -1112,6 +1127,27 @@ shake256_init (void *context, unsigned int flags)
keccak_init (GCRY_MD_SHAKE256, context, flags);
}

+
+static void
+cshake128_init (void *context, unsigned int flags)
+{
+ CSHAKE_CONTEXT *cshake_context = (CSHAKE_CONTEXT *)context;
+ cshake_context->rate_in_bytes = 168;
+ cshake_context->n_set = 0;
+ cshake_context->s_set = 0;
+ keccak_init (GCRY_MD_CSHAKE128, context, flags);
+}
+
+static void
+cshake256_init (void *context, unsigned int flags)
+{
+ CSHAKE_CONTEXT *cshake_context = (CSHAKE_CONTEXT *)context;
+ cshake_context->rate_in_bytes = 136;
+ cshake_context->n_set = 0;
+ cshake_context->s_set = 0;
+ keccak_init (GCRY_MD_CSHAKE256, context, flags);
+}
+
/* The routine final terminates the computation and
* returns the digest.
* The handle is prepared for a new cycle, but adding bytes to the
@@ -1423,6 +1459,147 @@ _gcry_shake256_hash_buffers (void *outbuf, size_t nbytes,
&_gcry_digest_spec_shake256);
}

+
+/** cSHAKE related functions **/
+
+
+/* may only be called with values of n_len that, multiplied by 8 still fit into a size_t */
+static gpg_err_code_t
+_gcry_cshake_input_n (CSHAKE_CONTEXT *cshake_ctx, const void *n, size_t n_len)
+{
+
+ // KECCAK[512](bytepad(encode_string(N)
+ size_t bit_len;
+ unsigned char array[20];
+ int err_flag = 0;
+ gpg_err_code_t rc = 0;
+ gcry_buffer_t buf1;
+ buf1.size = sizeof (array);
+ buf1.data = array;
+ buf1.len = 0;
+
+ if (rc)
+ {
+ return rc;
+ }
+ _gcry_cshake_left_encode (cshake_ctx->rate_in_bytes, &buf1);
+ /* perform encode_string as left-encoding the length and then the buffer */
+ bit_len = _gcry_cshake_bit_len_from_byte_len (n_len);
+ _gcry_cshake_left_encode (bit_len, &buf1);
+ if (err_flag)
+ {
+ return GPG_ERR_INTERNAL;
+ }
+ keccak_write (&cshake_ctx->keccak_ctx, buf1.data, buf1.len);
+ keccak_write (&cshake_ctx->keccak_ctx, n, n_len);
+ cshake_ctx->written_bytes_n_s = buf1.len + n_len;
+ cshake_ctx->n_set = 1;
+ return GPG_ERR_NO_ERROR;
+}
+
+
+/* may only be called with values of n_len that, multiplied by 8 still fit into a size_t */
+static void
+_gcry_cshake_input_s (CSHAKE_CONTEXT *cshake_ctx, const void *s, size_t s_len)
+{
+
+ // KECCAK[(256 or 512)](bytepad(encode_string(N)
+ // KECCAK[(256 or 512)](bytepad(...<already fed> || encode_string(S), w = (168 or 136))
+ size_t bit_len;
+ unsigned char array[20];
+ size_t rem;
+ gcry_buffer_t buf1;
+ buf1.size = sizeof (array);
+ buf1.data = array;
+ buf1.len = 0;
+
+ /* perform encode_string as left-encoding the length and then the buffer */
+ bit_len = _gcry_cshake_bit_len_from_byte_len (s_len);
+
+ _gcry_cshake_left_encode (bit_len, &buf1);
+
+ keccak_write (&cshake_ctx->keccak_ctx, buf1.data, buf1.len);
+ keccak_write (&cshake_ctx->keccak_ctx, s, s_len);
+ cshake_ctx->written_bytes_n_s += buf1.len + s_len;
+ cshake_ctx->s_set = 1;
+
+ /* complete byte_bad operation */
+ rem = cshake_ctx->written_bytes_n_s % cshake_ctx->rate_in_bytes;
+ if (rem != 0)
+ {
+ rem = cshake_ctx->rate_in_bytes - rem;
+ memset (array, 0, sizeof (array));
+ }
+
+ while (rem > 0)
+ {
+ unsigned to_use = rem > sizeof (array) ? sizeof (array) : rem;
+ keccak_write (&cshake_ctx->keccak_ctx, array, to_use);
+ rem -= to_use;
+ }
+}
+
+gpg_err_code_t
+_gcry_cshake_add_input (void *context,
+ enum gcry_ctl_cmds addin_type,
+ const void *v,
+ size_t v_len)
+{
+ gpg_err_code_t rc = 0;
+ CSHAKE_CONTEXT *cshake_context = (CSHAKE_CONTEXT *)context;
+ /* if s is already set, then we cannot add further input special input */
+ if (cshake_context->s_set)
+ {
+ return GPG_ERR_INV_STATE;
+ }
+ /* catch overly long input already here that will cause a problem when it's
+ * byte length is converted to bit length */
+ if ( DOES_MULT_OVERFL_SIZE_T(8, v_len) || v_len > 0xFFFFFFFF)
+ {
+ return GPG_ERR_TOO_LARGE;
+ }
+ /* when either N or S is set as non-empty, then actually use a different
+ * delimeter than in SHAKE */
+ if (v_len > 0)
+ {
+ cshake_context->keccak_ctx.suffix = CSHAKE_DELIMITED_SUFFIX;
+ }
+ if (addin_type == GCRYCTL_CSHAKE_N)
+ {
+ if (cshake_context->n_set)
+ {
+ return GPG_ERR_INV_STATE;
+ }
+ return _gcry_cshake_input_n (cshake_context, v, v_len);
+ }
+ else if (addin_type == GCRYCTL_CSHAKE_S)
+ {
+ if (!cshake_context->n_set)
+ {
+ rc = _gcry_cshake_input_n (cshake_context, NULL, 0);
+ if (rc)
+ {
+ return rc;
+ }
+ }
+ _gcry_cshake_input_s (cshake_context, v, v_len);
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+
+static void
+cshake_write (void *context, const void *inbuf_arg, size_t inlen)
+{
+
+ CSHAKE_CONTEXT *cshake_context = (CSHAKE_CONTEXT *)context;
+ if (cshake_context->n_set && !cshake_context->s_set)
+ {
+ _gcry_cshake_input_s (cshake_context, NULL, 0);
+ }
+ return keccak_write (&cshake_context->keccak_ctx, inbuf_arg, inlen);
+}
+

/*
Self-test section.
@@ -1505,6 +1682,7 @@ selftests_keccak (int algo, int extended, selftest_report_func_t report)
hash_len = 64;
break;

+ case GCRY_MD_CSHAKE128:
case GCRY_MD_SHAKE128:
short_hash =
"\x58\x81\x09\x2d\xd8\x18\xbf\x5c\xf8\xa3\xdd\xb7\x93\xfb\xcb\xa7"
@@ -1518,6 +1696,7 @@ selftests_keccak (int algo, int extended, selftest_report_func_t report)
hash_len = 32;
break;

+ case GCRY_MD_CSHAKE256:
case GCRY_MD_SHAKE256:
short_hash =
"\x48\x33\x66\x60\x13\x60\xa8\x77\x1c\x68\x63\x08\x0c\xc4\x11\x4d"
@@ -1577,7 +1756,9 @@ run_selftests (int algo, int extended, selftest_report_func_t report)
case GCRY_MD_SHA3_256:
case GCRY_MD_SHA3_384:
case GCRY_MD_SHA3_512:
+ case GCRY_MD_CSHAKE128:
case GCRY_MD_SHAKE128:
+ case GCRY_MD_CSHAKE256:
case GCRY_MD_SHAKE256:
ec = selftests_keccak (algo, extended, report);
break;
@@ -1697,3 +1878,37 @@ const gcry_md_spec_t _gcry_digest_spec_shake256 =
sizeof (KECCAK_CONTEXT),
run_selftests
};
+
+const gcry_md_spec_t _gcry_digest_spec_cshake128
+ = {GCRY_MD_CSHAKE128,
+ {0, 1},
+ "CSHAKE128",
+ shake128_asn,
+ DIM (shake128_asn),
+ NULL /* no oid_spec */,
+ 32,
+ cshake128_init,
+ cshake_write,
+ keccak_final,
+ keccak_shake_read,
+ keccak_extract,
+ _gcry_shake128_hash_buffers,
+ sizeof (CSHAKE_CONTEXT),
+ run_selftests};
+const gcry_md_spec_t _gcry_digest_spec_cshake256 = {
+ GCRY_MD_CSHAKE256,
+ {0, 1},
+ "CSHAKE256",
+ shake256_asn,
+ DIM (shake256_asn),
+ NULL /* no oid_spec */,
+ 64,
+ cshake256_init,
+ cshake_write,
+ keccak_final,
+ keccak_shake_read,
+ keccak_extract,
+ _gcry_shake256_hash_buffers,
+ sizeof (CSHAKE_CONTEXT),
+ run_selftests,
+};
diff --git a/cipher/keccak.h b/cipher/keccak.h
new file mode 100644
index 00000000..6b5a3fca
--- /dev/null
+++ b/cipher/keccak.h
@@ -0,0 +1,36 @@
+/* keccak.h - internal keccak-related functionality
+ * Copyright (C) 2023 MTG AG
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "cipher.h"
+#include "gcrypt.h"
+
+
+#define DOES_MULT_OVERFL_SIZE_T(a, b) (a != 0 && ((size_t) (a*b))/a != b)
+
+gpg_err_code_t _gcry_cshake_add_input(void* context,
+ enum gcry_ctl_cmds addin_type,
+ const void *v,
+ size_t v_len);
diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h
index 142ef69e..371a8ab5 100644
--- a/cipher/mac-internal.h
+++ b/cipher/mac-internal.h
@@ -129,6 +129,19 @@ struct gcry_mac_handle
unsigned int count;
unsigned char lastiv[8]; /* IMIT blocksize */
} imit;
+ struct {
+ gcry_md_hd_t md_ctx;
+ unsigned char* computed_mac;
+ int have_computed_mac;
+ int md_algo;
+ unsigned cshake_rate_in_bytes;
+ unsigned char* buffered_key;
+ size_t buffered_key_len;
+ unsigned output_byte_len;
+ int s_set;
+ int key_set;
+ int finalized;
+ } kmac;
} u;
};

@@ -288,3 +301,12 @@ extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_sm4;
#if USE_ARIA
extern const gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aria;
#endif
+
+/*
+ * KMAC algorithms (mac-kmac.c)
+ */
+
+#if USE_SHA3
+extern const gcry_mac_spec_t _gcry_mac_type_spec_kmac128_128;
+extern const gcry_mac_spec_t _gcry_mac_type_spec_kmac256_256;
+#endif
diff --git a/cipher/mac-kmac.c b/cipher/mac-kmac.c
new file mode 100644
index 00000000..ad80cb63
--- /dev/null
+++ b/cipher/mac-kmac.c
@@ -0,0 +1,380 @@
+/* mac-kmac.c - KMAC glue for MAC API
+ * Copyright (C) 2023 MTG AG
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser general Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include "g10lib.h"
+#include "./mac-internal.h"
+#include "gcrypt.h"
+
+#include <stddef.h>
+#include "cshake-common.h"
+#include "bufhelp.h"
+#include "keccak.h"
+
+static void
+write_encoded_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
+{
+
+ size_t written_bytes = 0;
+ size_t bit_len;
+ gcry_buffer_t buf1;
+ unsigned char array[20];
+ unsigned rate_in_bytes = h->u.kmac.cshake_rate_in_bytes;
+ size_t rem;
+
+ /* catch overly large size of key early that would cause problem in
+ * subseuqently invoked conversion routines */
+ buf1.size = sizeof (array);
+ buf1.data = array;
+ buf1.len = 0;
+ /* bytepad(encode_string(key), <keccak_rate>) */
+ /* inside bytepad: leading encoding of w */
+ _gcry_cshake_left_encode (h->u.kmac.cshake_rate_in_bytes, &buf1);
+
+ /* encode_string(key) */
+ bit_len = _gcry_cshake_bit_len_from_byte_len (keylen);
+ _gcry_cshake_left_encode (bit_len, &buf1);
+ _gcry_md_write (h->u.kmac.md_ctx, buf1.data, buf1.len);
+ written_bytes += buf1.len;
+ _gcry_md_write (h->u.kmac.md_ctx, key, keylen);
+ written_bytes += keylen;
+
+
+ /* complete bytebad operation by applying padding */
+ rem = written_bytes % rate_in_bytes;
+ if (rem != 0)
+ {
+ rem = rate_in_bytes - rem;
+ memset (array, 0, sizeof (array));
+ }
+
+ while (rem > 0)
+ {
+ unsigned to_use = rem > sizeof (array) ? sizeof (array) : rem;
+ _gcry_md_write (h->u.kmac.md_ctx, array, to_use);
+ rem -= to_use;
+ }
+ return;
+}
+
+static gpg_err_code_t
+kmac_finalize (gcry_mac_hd_t h)
+{
+
+ size_t bit_len;
+ unsigned char array[20];
+
+ gcry_buffer_t buf1;
+ buf1.size = sizeof (array);
+ buf1.data = array;
+ buf1.len = 0;
+ bit_len = _gcry_cshake_bit_len_from_byte_len (h->u.kmac.output_byte_len);
+ _gcry_cshake_right_encode (bit_len, &buf1);
+ _gcry_md_write (h->u.kmac.md_ctx, buf1.data, buf1.len);
+ h->u.kmac.finalized = 1;
+ return GPG_ERR_NO_ERROR;
+}
+
+static gcry_err_code_t
+kmac_open (gcry_mac_hd_t h)
+{
+ gcry_err_code_t err;
+ gcry_md_hd_t hd;
+ int secure = (h->magic == CTX_MAC_MAGIC_SECURE);
+ unsigned int flags;
+ int md_algo;
+ unsigned rate_in_bytes, output_byte_len;
+ switch (h->spec->algo)
+ {
+ case GCRY_MAC_KMAC128_128:
+ md_algo = GCRY_MD_CSHAKE128;
+ rate_in_bytes = 168;
+ output_byte_len = 256 / 8;
+ break;
+ case GCRY_MAC_KMAC256_256:
+ md_algo = GCRY_MD_CSHAKE256;
+ rate_in_bytes = 136;
+ output_byte_len = 512 / 8;
+ break;
+ default:
+ return GPG_ERR_INV_ARG;
+ }
+ h->u.kmac.buffered_key = NULL;
+ h->u.kmac.md_algo = md_algo;
+ h->u.kmac.s_set = 0;
+ h->u.kmac.key_set = 0;
+ h->u.kmac.output_byte_len = output_byte_len;
+ h->u.kmac.finalized = 0;
+ h->u.kmac.cshake_rate_in_bytes = rate_in_bytes;
+ h->u.kmac.computed_mac = NULL;
+ h->u.kmac.have_computed_mac = 0;
+ flags = (secure ? GCRY_MD_FLAG_SECURE : 0);
+
+ err = _gcry_md_open (&hd, md_algo, flags);
+ if (err)
+ {
+ return err;
+ }
+ h->u.kmac.md_ctx = hd;
+
+ err = _gcry_md_ctl (hd, GCRYCTL_CSHAKE_N, (unsigned char *)"KMAC", 4);
+ if (err)
+ {
+ return err;
+ }
+ h->u.kmac.computed_mac = secure ? xtrymalloc_secure (output_byte_len)
+ : xtrymalloc (output_byte_len);
+ if (!h->u.kmac.computed_mac)
+ {
+ return gpg_err_code_from_syserror ();
+ }
+
+ return GPG_ERR_NO_ERROR;
+}
+
+
+static void
+kmac_close (gcry_mac_hd_t h)
+{
+ _gcry_md_close (h->u.kmac.md_ctx);
+ h->u.kmac.md_ctx = NULL;
+ xfree (h->u.kmac.computed_mac);
+ xfree (h->u.kmac.buffered_key);
+}
+
+static gcry_err_code_t
+kmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen)
+{
+ gcry_err_code_t err = GPG_ERR_NO_ERROR;
+
+ /* catch overly large size of key early that would cause problem in
+ * subseuqently invoked conversion routines */
+ if (DOES_MULT_OVERFL_SIZE_T (8, keylen) || keylen > 0xFFFFFFFF)
+ {
+ return GPG_ERR_TOO_LARGE;
+ }
+ /* if IV=S was set already, then encode and write key to cSHAKE, else
+ * store it. */
+ if (!h->u.kmac.s_set)
+ {
+ h->u.kmac.buffered_key = xtrymalloc_secure (keylen);
+ if (!h->u.kmac.buffered_key)
+ {
+ return GPG_ERR_ENOMEM;
+ }
+ memcpy (h->u.kmac.buffered_key, key, keylen);
+ h->u.kmac.buffered_key_len = keylen;
+ }
+ else
+ {
+ write_encoded_key (h, key, keylen);
+ }
+ h->u.kmac.key_set = 1;
+ return err;
+}
+
+gcry_err_code_t
+kmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen)
+{
+ gpg_err_code_t err = GPG_ERR_NO_ERROR;
+
+ /* catch overly large size of IV early that would cause problem in
+ * subseuqently invoked conversion routines */
+ if (DOES_MULT_OVERFL_SIZE_T (8, ivlen) || ivlen > 0xFFFFFFFF)
+ {
+ return GPG_ERR_TOO_LARGE;
+ }
+ if (h->u.kmac.s_set)
+ {
+ return GPG_ERR_INV_STATE;
+ }
+ err = _gcry_md_ctl (
+ h->u.kmac.md_ctx, GCRYCTL_CSHAKE_S, (unsigned char *)iv, ivlen);
+ if (err)
+ {
+ return err;
+ }
+ h->u.kmac.s_set = 1;
+ /* if key is stored in context already, then write it after having set
+ * S in cshake and free the buffer */
+ if (h->u.kmac.buffered_key != NULL)
+ {
+ write_encoded_key (
+ h, h->u.kmac.buffered_key, h->u.kmac.buffered_key_len);
+ xfree (h->u.kmac.buffered_key);
+ h->u.kmac.buffered_key = NULL;
+ h->u.kmac.buffered_key_len = 0;
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+
+static gcry_err_code_t
+kmac_reset (gcry_mac_hd_t h)
+{
+ /* clear all fields and state */
+ kmac_close (h);
+ return kmac_open (h);
+}
+
+
+static gcry_err_code_t
+kmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
+{
+ gpg_err_code_t err = 0;
+
+ /* If IV (=S in KMAC) was not set, it is implicitly empty */
+ if (!h->u.kmac.s_set)
+ {
+ err = kmac_setiv (h, NULL, 0);
+ if (err)
+ {
+ return err;
+ }
+ }
+ if (!h->u.kmac.key_set || h->u.kmac.finalized)
+ {
+ return GPG_ERR_INV_STATE;
+ }
+ _gcry_md_write (h->u.kmac.md_ctx, buf, buflen);
+ return GPG_ERR_NO_ERROR;
+}
+
+
+static gcry_err_code_t
+kmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen_ptr)
+{
+
+ if (outlen_ptr && *outlen_ptr > h->u.kmac.output_byte_len)
+ {
+ *outlen_ptr = h->u.kmac.output_byte_len;
+ }
+ /* Both read and verify may be called in any order. Thus the KMAC context
+ * holds the computed MAC in a buffer. */
+ if (!h->u.kmac.have_computed_mac)
+ {
+ gpg_err_code_t err = GPG_ERR_NO_ERROR;
+ err = kmac_finalize (h);
+ if (err)
+ {
+ return err;
+ }
+
+ err = _gcry_md_extract (h->u.kmac.md_ctx,
+ h->u.kmac.md_algo,
+ h->u.kmac.computed_mac,
+ h->u.kmac.output_byte_len);
+ if (err)
+ {
+ return err;
+ }
+ h->u.kmac.have_computed_mac = 1;
+ }
+ if (outlen_ptr)
+ {
+ memcpy (outbuf, h->u.kmac.computed_mac, *outlen_ptr);
+ }
+ return GPG_ERR_NO_ERROR;
+}
+
+
+static gcry_err_code_t
+kmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen)
+{
+ /* This function verifies full MACs only. If a too short MAC is provided by
+ * the caller, the verification fails. Note that for instance HMAC in
+ * libgcrypt behaves differently: if there a MAC is provided to the verify
+ * function that is shorter than the regular MAC length, the verification
+ * succeeds if that shorter MAC is a matching the start of the regular MAC.
+ * This behaviour incurs the risk that an implementation issues the
+ * verification of a one-byte-length attacker controlled MAC that then
+ * verifies correctly with probability 1/256 (the case of zero-length MACs is
+ * caught by the higher-level generic MAC API).
+ */
+ gpg_err_code_t err = GPG_ERR_NO_ERROR;
+ size_t outlen = h->u.kmac.output_byte_len;
+ if (buflen != outlen)
+ {
+ return GPG_ERR_INV_LENGTH;
+ }
+ err = kmac_read (h, NULL, NULL);
+ if (err)
+ {
+ return err;
+ }
+ return buf_eq_const (buf, h->u.kmac.computed_mac, outlen) ? 0
+ : GPG_ERR_CHECKSUM;
+}
+static unsigned int
+kmac_get_maclen (int algo)
+{
+ switch (algo)
+ {
+ case GCRY_MAC_KMAC128_128:
+ return 256 / 8;
+ case GCRY_MAC_KMAC256_256:
+ return 512 / 8;
+ default:
+ return 0;
+ }
+}
+
+
+static unsigned int
+kmac_get_keylen (int algo)
+{
+ /* The key length for KMAC is arbitrary. Here, we return values
+ * corresponding to the security level. */
+ switch (algo)
+ {
+ case GCRY_MAC_KMAC128_128:
+ return 128 / 8;
+ case GCRY_MAC_KMAC256_256:
+ return 256 / 8;
+ default:
+ /* return the minimum reasonable value */
+ return 128;
+ }
+}
+
+static const gcry_mac_spec_ops_t kmac_ops = {
+ kmac_open,
+ kmac_close,
+ kmac_setkey,
+ kmac_setiv,
+ kmac_reset,
+ kmac_write,
+ kmac_read,
+ kmac_verify,
+ kmac_get_maclen,
+ kmac_get_keylen,
+ NULL,
+ NULL /* no kmac_selftest */
+};
+
+const gcry_mac_spec_t _gcry_mac_type_spec_kmac128_128
+ = {GCRY_MAC_KMAC128_128, {0, 0}, "KMAC128(128)", &kmac_ops};
+
+const gcry_mac_spec_t _gcry_mac_type_spec_kmac256_256
+ = {GCRY_MAC_KMAC256_256, {0, 0}, "KMAC256(256)", &kmac_ops};
diff --git a/cipher/mac.c b/cipher/mac.c
index 6305f51e..82bf1d98 100644
--- a/cipher/mac.c
+++ b/cipher/mac.c
@@ -407,6 +407,18 @@ static const gcry_mac_spec_t * const mac_list_algo501[] =
#endif
};

+/* KMAC algorithms start with index 601 (enum gcry_mac_algos). The postfixed number indicates the output length in bits. */
+static const gcry_mac_spec_t * const mac_list_algo601[] =
+ {
+#if USE_SHA3
+ &_gcry_mac_type_spec_kmac128_128,
+ &_gcry_mac_type_spec_kmac256_256
+#else
+ NULL,
+ NULL
+#endif
+ };
+



@@ -433,6 +445,8 @@ spec_from_algo (int algo)
spec = mac_list_algo401[algo - 401];
else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501))
spec = mac_list_algo501[algo - 501];
+ else if (algo >= 601 && algo < 601 + DIM(mac_list_algo601))
+ spec = mac_list_algo601[algo - 601];
#if USE_GOST28147
else if (algo == GCRY_MAC_GOST28147_IMIT)
spec = &_gcry_mac_type_spec_gost28147_imit;
diff --git a/cipher/md.c b/cipher/md.c
index a128dd82..81a036d7 100644
--- a/cipher/md.c
+++ b/cipher/md.c
@@ -27,6 +27,8 @@

#include "g10lib.h"
#include "cipher.h"
+#include "gcrypt.h"
+#include "keccak.h"


/* This is the list of the digest implementations included in
@@ -58,6 +60,8 @@ static const gcry_md_spec_t * const digest_list[] =
&_gcry_digest_spec_sha3_512,
&_gcry_digest_spec_shake128,
&_gcry_digest_spec_shake256,
+ &_gcry_digest_spec_cshake128,
+ &_gcry_digest_spec_cshake256,
#endif
#if USE_GOST_R_3411_94
&_gcry_digest_spec_gost3411_94,
@@ -240,7 +244,9 @@ static const gcry_md_spec_t * const digest_list_algo301[] =
#endif
#if USE_SHA512
&_gcry_digest_spec_sha512_256,
- &_gcry_digest_spec_sha512_224
+ &_gcry_digest_spec_sha512_224,
+ &_gcry_digest_spec_cshake128,
+ &_gcry_digest_spec_cshake256
#else
NULL,
NULL
@@ -996,6 +1002,44 @@ prepare_macpads (gcry_md_hd_t a, const unsigned char *key, size_t keylen)
}


+
+static gcry_err_code_t
+_gcry_md_set_add_input (gcry_md_hd_t h,
+ enum gcry_ctl_cmds addin_type,
+ const void *v,
+ size_t v_len)
+{
+ gcry_err_code_t rc = 0;
+ int did_set = 0;
+ GcryDigestEntry *r;
+ if (!h->ctx->list)
+ return GPG_ERR_DIGEST_ALGO; /* Might happen if no algo is enabled. */
+ for (r = h->ctx->list; r; r = r->next)
+ {
+ switch (r->spec->algo)
+ {
+ case GCRY_MD_CSHAKE128:
+ case GCRY_MD_CSHAKE256:
+ rc = _gcry_cshake_add_input (r->context, addin_type, v, v_len);
+ if (!rc)
+ {
+ did_set = 1;
+ }
+ else
+ {
+ return rc;
+ }
+ break;
+ }
+ }
+ if (!did_set)
+ {
+ rc = GPG_ERR_DIGEST_ALGO;
+ }
+ return rc;
+}
+
+
gcry_err_code_t
_gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
{
@@ -1014,6 +1058,10 @@ _gcry_md_ctl (gcry_md_hd_t hd, int cmd, void *buffer, size_t buflen)
case GCRYCTL_STOP_DUMP:
md_stop_debug ( hd );
break;
+ case GCRYCTL_CSHAKE_N:
+ case GCRYCTL_CSHAKE_S:
+ rc = _gcry_md_set_add_input(hd, cmd, buffer, buflen);
+ break;
default:
rc = GPG_ERR_INV_OP;
}
diff --git a/configure.ac b/configure.ac
index 4f7c3a52..6ffc209e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3514,7 +3514,7 @@ fi

LIST_MEMBER(sha3, $enabled_digests)
if test "$found" = "1" ; then
- GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo"
+ GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo cshake-common.lo mac-kmac.lo"
AC_DEFINE(USE_SHA3, 1, [Defined if this module should be included])

case "${host}" in
diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi
index e31c9019..04332214 100644
--- a/doc/gcrypt.texi
+++ b/doc/gcrypt.texi
@@ -3606,7 +3606,7 @@ are also supported.
@c begin table of hash algorithms
@cindex SHA-1
@cindex SHA-224, SHA-256, SHA-384, SHA-512, SHA-512/224, SHA-512/256
-@cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256
+@cindex SHA3-224, SHA3-256, SHA3-384, SHA3-512, SHAKE128, SHAKE256, cSHAKE128, cSHAKE256
@cindex RIPE-MD-160
@cindex MD2, MD4, MD5
@cindex TIGER, TIGER1, TIGER2
@@ -3716,6 +3716,21 @@ This is the SHAKE256 extendable-output function (XOF) algorithm with 256 bit
security strength.
See FIPS 202 for the specification.

+@item GCRY_MD_CSHAKE128
+This is the cSHAKE128 extendable-output function (XOF) algorithm with 128 bit
+security strength defined in NIST SP 800-185. cSHAKE takes optional additional
+inputs N and S, which can be set by using _gcry_md_ctl() with the control
+commands GCRYCTL_CSHAKE_N and GCRYCTL_CSHAKE_S. If both N and S are set, then N
+has to be set before S. If chosen to be non-empty, N and/or S have to be set
+before the first call to _gcry_md_write(). The lengths of N or S is limited to
+a bit length which can be represented by a size_t and does not exceed a byte
+size of 2^(32) - 1.
+
+@item GCRY_MD_CSHAKE256
+This is the cSHAKE256 extendable-output function (XOF) algorithm with 256 bit
+security strength defined in NIST SP 800-185. Regarding the usage of the
+optional additional inputs N and S, see the above description of cSHAKE128.
+
@item GCRY_MD_CRC32
This is the ISO 3309 and ITU-T V.42 cyclic redundancy check. It yields
an output of 4 bytes. Note that this is not a hash algorithm in the
@@ -4394,6 +4409,18 @@ key and one-time nonce.
@item GCRY_MAC_GOST28147_IMIT
This is MAC construction defined in GOST 28147-89 (see RFC 5830 Section 8).

+@item GCRY_MAC_KMAC128_128
+This is the KMAC-128 message authentication code defined in NIST SP 800-185
+with an output length of 128 bits (i.e., L=128). The length of the key and of
+the optional customisation string S, which is modelled as the IV, is limited to
+a bit length which can be represented by a size_t and does not exceed a byte
+length of 2^(32) - 1.
+
+@item GCRY_MAC_KMAC256_256
+This is the KMAC-256 message authentication code defined in NIST SP 800-185
+with an output length of 256 bits (i.e., L=256). Regarding the limitations of
+the key and the customization string S, see GCRY_MAC_KMAC128_128.
+
@end table
@c end table of MAC algorithms

@@ -4444,7 +4471,7 @@ which can be performed with function:

@deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen})

-Set the IV to the value of @var{iv} of length @var{ivlen} bytes.
+Set the IV to the value of @var{iv} of length @var{ivlen} bytes. For KMAC, this function is used to se the value of S, the optional customisation string.
@end deftypefun


diff --git a/src/cipher.h b/src/cipher.h
index 3c48c2c5..3f63295e 100644
--- a/src/cipher.h
+++ b/src/cipher.h
@@ -200,6 +200,8 @@ extern const gcry_md_spec_t _gcry_digest_spec_sha3_512;
extern const gcry_md_spec_t _gcry_digest_spec_sha3_384;
extern const gcry_md_spec_t _gcry_digest_spec_shake128;
extern const gcry_md_spec_t _gcry_digest_spec_shake256;
+extern const gcry_md_spec_t _gcry_digest_spec_cshake128;
+extern const gcry_md_spec_t _gcry_digest_spec_cshake256;
extern const gcry_md_spec_t _gcry_digest_spec_tiger;
extern const gcry_md_spec_t _gcry_digest_spec_tiger1;
extern const gcry_md_spec_t _gcry_digest_spec_tiger2;
diff --git a/src/fips.c b/src/fips.c
index 574776ac..cf91baa8 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -422,6 +422,8 @@ _gcry_fips_indicator_md (va_list arg_ptr)
case GCRY_MD_SHA3_512:
case GCRY_MD_SHAKE128:
case GCRY_MD_SHAKE256:
+ case GCRY_MD_CSHAKE128:
+ case GCRY_MD_CSHAKE256:
return GPG_ERR_NO_ERROR;
default:
return GPG_ERR_NOT_SUPPORTED;
diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h
index ba52fa8e..1f3f1bfb 100644
--- a/src/gcrypt-int.h
+++ b/src/gcrypt-int.h
@@ -164,6 +164,7 @@ const char *_gcry_md_algo_name (int algo) _GCRY_GCC_ATTR_PURE;
int _gcry_md_map_name (const char* name) _GCRY_GCC_ATTR_PURE;
gpg_err_code_t _gcry_md_setkey (gcry_md_hd_t hd,
const void *key, size_t keylen);
+
void _gcry_md_debug (gcry_md_hd_t hd, const char *suffix);

#define _gcry_md_test_algo(a) \
diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in
index 7dc1196b..1a9aa9f5 100644
--- a/src/gcrypt.h.in
+++ b/src/gcrypt.h.in
@@ -333,7 +333,9 @@ enum gcry_ctl_cmds
GCRYCTL_FIPS_SERVICE_INDICATOR_FUNCTION = 84,
GCRYCTL_FIPS_SERVICE_INDICATOR_MAC = 85,
GCRYCTL_FIPS_SERVICE_INDICATOR_MD = 86,
- GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS = 87
+ GCRYCTL_FIPS_SERVICE_INDICATOR_PK_FLAGS = 87,
+ GCRYCTL_CSHAKE_N = 88,
+ GCRYCTL_CSHAKE_S = 89
};

/* Perform various operations defined by CMD. */
@@ -1304,7 +1306,9 @@ enum gcry_md_algos
GCRY_MD_BLAKE2S_128 = 325,
GCRY_MD_SM3 = 326,
GCRY_MD_SHA512_256 = 327,
- GCRY_MD_SHA512_224 = 328
+ GCRY_MD_SHA512_224 = 328,
+ GCRY_MD_CSHAKE128 = 329,
+ GCRY_MD_CSHAKE256 = 330
};

/* Flags used with the open function. */
@@ -1315,6 +1319,7 @@ enum gcry_md_flags
GCRY_MD_FLAG_BUGEMU1 = 0x0100
};

+
/* (Forward declaration.) */
struct gcry_md_context;

@@ -1533,7 +1538,10 @@ enum gcry_mac_algos
GCRY_MAC_POLY1305_SERPENT = 505,
GCRY_MAC_POLY1305_SEED = 506,
GCRY_MAC_POLY1305_SM4 = 507,
- GCRY_MAC_POLY1305_ARIA = 508
+ GCRY_MAC_POLY1305_ARIA = 508,
+
+ GCRY_MAC_KMAC128_128 = 601,
+ GCRY_MAC_KMAC256_256 = 602
};

/* Flags used with the open function. */
diff --git a/src/visibility.c b/src/visibility.c
index 9b29c4f1..d3447e3f 100644
--- a/src/visibility.c
+++ b/src/visibility.c
@@ -1371,6 +1371,7 @@ gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen)
return gpg_error (_gcry_md_setkey (hd, key, keylen));
}

+
void
gcry_md_debug (gcry_md_hd_t hd, const char *suffix)
{
diff --git a/src/visibility.h b/src/visibility.h
index 6aef3278..12286021 100644
--- a/src/visibility.h
+++ b/src/visibility.h
@@ -402,6 +402,7 @@ MARK_VISIBLEX (_gcry_mpi_get_const)
#define gcry_md_reset _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_setkey _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_write _gcry_USE_THE_UNDERSCORED_FUNCTION
+#define gcry_md_set_add_input _gcry_USE_THE_UNDERSCORED_FUNCTION
#define gcry_md_debug _gcry_USE_THE_UNDERSCORED_FUNCTION

#define gcry_mac_algo_info _gcry_USE_THE_UNDERSCORED_FUNCTION
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 9920bae8..690bdbd7 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -25,7 +25,7 @@ tests_bin = \
version t-secmem mpitests t-sexp t-convert \
t-mpi-bit t-mpi-point t-lock \
prime basic keygen pubkey hmac hashtest t-kdf keygrip \
- aeswrap random
+ aeswrap random cshake

if USE_RSA
tests_bin += pkcs1v2 t-rsa-pss t-rsa-15 t-rsa-testparm
diff --git a/tests/basic.c b/tests/basic.c
index a405c82c..bfbd67f3 100644
--- a/tests/basic.c
+++ b/tests/basic.c
@@ -14924,6 +14924,249 @@ check_digests (void)
"\x1b\xeb\x65\x53\xf2\x81\xfa\x75\x69\x48\xc4\x38\x49\x4b\x19\xb4"
"\xee\x69\xa5\x43\x6b\x22\x2b\xc9\x88\xed\xa4\xac\x60\x00\x24\xc9",
0, 512, },
+ { GCRY_MD_CSHAKE128,
+ "",
+ "\x7F\x9C\x2B\xA4\xE8\x8F\x82\x7D\x61\x60\x45\x50\x76\x05\x85\x3E"
+ "\xD7\x3B\x80\x93\xF6\xEF\xBC\x88\xEB\x1A\x6E\xAC\xFA\x66\xEF\x26"
+ "\x3C\xB1\xEE\xA9\x88\x00\x4B\x93\x10\x3C\xFB\x0A\xEE\xFD\x2A\x68"
+ "\x6E\x01\xFA\x4A\x58\xE8\xA3\x63\x9C\xA8\xA1\xE3\xF9\xAE\x57\xE2"
+ "\x35\xB8\xCC\x87\x3C\x23\xDC\x62\xB8\xD2\x60\x16\x9A\xFA\x2F\x75"
+ "\xAB\x91\x6A\x58\xD9\x74\x91\x88\x35\xD2\x5E\x6A\x43\x50\x85\xB2"
+ "\xBA\xDF\xD6\xDF\xAA\xC3\x59\xA5\xEF\xBB\x7B\xCC\x4B\x59\xD5\x38"
+ "\xDF\x9A\x04\x30\x2E\x10\xC8\xBC\x1C\xBF\x1A\x0B\x3A\x51\x20\xEA"
+ "\x17\xCD\xA7\xCF\xAD\x76\x5F\x56\x23\x47\x4D\x36\x8C\xCC\xA8\xAF"
+ "\x00\x07\xCD\x9F\x5E\x4C\x84\x9F\x16\x7A\x58\x0B\x14\xAA\xBD\xEF"
+ "\xAE\xE7\xEE\xF4\x7C\xB0\xFC\xA9\x76\x7B\xE1\xFD\xA6\x94\x19\xDF"
+ "\xB9\x27\xE9\xDF\x07\x34\x8B\x19\x66\x91\xAB\xAE\xB5\x80\xB3\x2D"
+ "\xEF\x58\x53\x8B\x8D\x23\xF8\x77\x32\xEA\x63\xB0\x2B\x4F\xA0\xF4"
+ "\x87\x33\x60\xE2\x84\x19\x28\xCD\x60\xDD\x4C\xEE\x8C\xC0\xD4\xC9"
+ "\x22\xA9\x61\x88\xD0\x32\x67\x5C\x8A\xC8\x50\x93\x3C\x7A\xFF\x15"
+ "\x33\xB9\x4C\x83\x4A\xDB\xB6\x9C\x61\x15\xBA\xD4\x69\x2D\x86\x19"
+ "\xF9\x0B\x0C\xDF\x8A\x7B\x9C\x26\x40\x29\xAC\x18\x5B\x70\xB8\x3F"
+ "\x28\x01\xF2\xF4\xB3\xF7\x0C\x59\x3E\xA3\xAE\xEB\x61\x3A\x7F\x1B"
+ "\x1D\xE3\x3F\xD7\x50\x81\xF5\x92\x30\x5F\x2E\x45\x26\xED\xC0\x96"
+ "\x31\xB1\x09\x58\xF4\x64\xD8\x89\xF3\x1B\xA0\x10\x25\x0F\xDA\x7F"
+ "\x13\x68\xEC\x29\x67\xFC\x84\xEF\x2A\xE9\xAF\xF2\x68\xE0\xB1\x70"
+ "\x0A\xFF\xC6\x82\x0B\x52\x3A\x3D\x91\x71\x35\xF2\xDF\xF2\xEE\x06"
+ "\xBF\xE7\x2B\x31\x24\x72\x1D\x4A\x26\xC0\x4E\x53\xA7\x5E\x30\xE7"
+ "\x3A\x7A\x9C\x4A\x95\xD9\x1C\x55\xD4\x95\xE9\xF5\x1D\xD0\xB5\xE9"
+ "\xD8\x3C\x6D\x5E\x8C\xE8\x03\xAA\x62\xB8\xD6\x54\xDB\x53\xD0\x9B"
+ "\x8D\xCF\xF2\x73\xCD\xFE\xB5\x73\xFA\xD8\xBC\xD4\x55\x78\xBE\xC2"
+ "\xE7\x70\xD0\x1E\xFD\xE8\x6E\x72\x1A\x3F\x7C\x6C\xCE\x27\x5D\xAB"
+ "\xE6\xE2\x14\x3F\x1A\xF1\x8D\xA7\xEF\xDD\xC4\xC7\xB7\x0B\x5E\x34"
+ "\x5D\xB9\x3C\xC9\x36\xBE\xA3\x23\x49\x1C\xCB\x38\xA3\x88\xF5\x46"
+ "\xA9\xFF\x00\xDD\x4E\x13\x00\xB9\xB2\x15\x3D\x20\x41\xD2\x05\xB4"
+ "\x43\xE4\x1B\x45\xA6\x53\xF2\xA5\xC4\x49\x2C\x1A\xDD\x54\x45\x12"
+ "\xDD\xA2\x52\x98\x33\x46\x2B\x71\xA4\x1A\x45\xBE\x97\x29\x0B\x6F",
+ 0, 512, },
+ { GCRY_MD_CSHAKE128,
+ "",
+ "\x7F\x9C\x2B\xA4\xE8\x8F\x82\x7D\x61\x60\x45\x50\x76\x05\x85\x3E"
+ "\xD7\x3B\x80\x93\xF6\xEF\xBC\x88\xEB\x1A\x6E\xAC\xFA\x66\xEF\x26",
+ 0, 0, /* test md_read interface */ },
+ { GCRY_MD_CSHAKE128,
+ "\x5A\xAB\x62\x75\x6D\x30\x7A\x66\x9D\x14\x6A\xBA\x98\x8D\x90\x74"
+ "\xC5\xA1\x59\xB3\xDE\x85\x15\x1A\x81\x9B\x11\x7C\xA1\xFF\x65\x97"
+ "\xF6\x15\x6E\x80\xFD\xD2\x8C\x9C\x31\x76\x83\x51\x64\xD3\x7D\xA7"
+ "\xDA\x11\xD9\x4E\x09\xAD\xD7\x70\xB6\x8A\x6E\x08\x1C\xD2\x2C\xA0"
+ "\xC0\x04\xBF\xE7\xCD\x28\x3B\xF4\x3A\x58\x8D\xA9\x1F\x50\x9B\x27"
+ "\xA6\x58\x4C\x47\x4A\x4A\x2F\x3E\xE0\xF1\xF5\x64\x47\x37\x92\x40"
+ "\xA5\xAB\x1F\xB7\x7F\xDC\xA4\x9B\x30\x5F\x07\xBA\x86\xB6\x27\x56"
+ "\xFB\x9E\xFB\x4F\xC2\x25\xC8\x68\x45\xF0\x26\xEA\x54\x20\x76\xB9"
+ "\x1A\x0B\xC2\xCD\xD1\x36\xE1\x22\xC6\x59\xBE\x25\x9D\x98\xE5\x84"
+ "\x1D\xF4\xC2\xF6\x03\x30\xD4\xD8\xCD\xEE\x7B\xF1\xA0\xA2\x44\x52"
+ "\x4E\xEC\xC6\x8F\xF2\xAE\xF5\xBF\x00\x69\xC9\xE8\x7A\x11\xC6\xE5"
+ "\x19\xDE\x1A\x40\x62\xA1\x0C\x83\x83\x73\x88\xF7\xEF\x58\x59\x8A"
+ "\x38\x46\xF4\x9D\x49\x96\x82\xB6\x83\xC4\xA0\x62\xB4\x21\x59\x4F"
+ "\xAF\xBC\x13\x83\xC9\x43\xBA\x83\xBD\xEF\x51\x5E\xFC\xF1\x0D",
+ "\xF0\x71\x5D\xE3\x56\x92\xFD\x70\x12\x3D\xC6\x83\x68\xD0\xFE\xEC"
+ "\x06\xA0\xC7\x4C\xF8\xAD\xB0\x5D\xDC\x25\x54\x87\xB1\xA8\xD4\xD1"
+ "\x21\x3E\x9E\xAB\xAF\x41\xF1\x16\x17\x19\xD0\x65\xD7\x94\xB7\x50"
+ "\xF8\x4B\xE3\x2A\x32\x34\xB4\xD5\x36\x46\x0D\x55\x20\x68\x8A\x5A"
+ "\x79\xA1\x7A\x4B\xA8\x98\x7F\xCB\x61\xBF\x7D\xAA\x8B\x54\x7B\xF5"
+ "\xC1\xCE\x36\xB5\x6A\x73\x25\x7D\xBB\xF1\xBA\xBB\x64\xF2\x49\xBD"
+ "\xCE\xB6\x7B\xA1\xC8\x88\x37\x0A\x96\x3D\xFD\x6B\x6A\x2A\xDE\x2C"
+ "\xEF\xD1\x4C\x32\x52\xCB\x37\x58\x52\x0F\x0C\x65\xF4\x52\x46\x82"
+ "\x77\x24\x99\x46\x3A\xE1\xA3\x41\x80\x01\x83\xAA\x60\xEF\xA0\x51"
+ "\x18\xA2\x82\x01\x74\x4F\x7B\xA0\xB0\xA3\x92\x8D\xD7\xC0\x26\x3F"
+ "\xD2\x64\xB7\xCD\x7B\x2E\x2E\x09\xB3\x22\xBF\xCE\xA8\xEE\xD0\x42"
+ "\x75\x79\x5B\xE7\xC0\xF0\x0E\x11\x38\x27\x37\x0D\x05\x1D\x50\x26"
+ "\x95\x80\x30\x00\x05\xAC\x12\x88\xFE\xA6\xCD\x9A\xE9\xF4\xF3\x7C"
+ "\xE0\xF8\xAC\xE8\xBF\x3E\xBE\x1D\x70\x56\x25\x59\x54\xC7\x61\x93"
+ "\x1D\x3C\x42\xED\x62\xF7\xF1\xCE\x1B\x94\x5C\xDE\xCC\x0A\x74\x32"
+ "\x2D\x7F\x64\xD6\x00\x4F\xF2\x16\x84\x14\x93\x07\x28\x8B\x44\x8E"
+ "\x45\x43\x34\x75\xB1\xEA\x13\x14\xB0\x0F\x1F\xC4\x50\x08\x9A\x9D"
+ "\x1F\x77\x10\xC6\xD7\x65\x2E\xCF\x65\x4F\x3B\x48\x7D\x02\x83\xD4"
+ "\xD8\xA2\x8E\xFB\x50\x66\xC4\x25\x0D\x5A\xD6\x98\xE1\x5D\xBA\x88"
+ "\xE9\x25\xE4\xDE\x99\xB6\x9B\xC3\x83\xAC\x80\x45\xB7\xF1\x02\x2A"
+ "\xDD\x39\xD4\x43\x54\x6A\xE0\x92\x4F\x13\xF4\x89\x60\x96\xDF\xDF"
+ "\x37\xCA\x72\x20\x79\x87\xC4\xA7\x70\x5A\x7A\xBE\x72\x4B\x7F\xA1"
+ "\x0C\x90\x9F\x39\x25\x44\x9F\x01\x0D\x61\xE2\x07\xAD\xD9\x52\x19"
+ "\x07\x1A\xCE\xED\xB9\xB9\xDC\xED\x32\xA9\xE1\x23\x56\x1D\x60\x82"
+ "\xD4\x6A\xEF\xAE\x07\xEE\x1B\xD1\x32\x76\x5E\x3E\x51\x3C\x66\x50"
+ "\x1B\x38\x7A\xB2\xEE\x09\xA0\x4A\xE6\x3E\x25\x80\x85\x17\xAF\xEA"
+ "\x3E\x05\x11\x69\xCF\xD2\xFF\xF8\xC5\x85\x8E\x2D\x96\x23\x89\x7C"
+ "\x9E\x85\x17\x5A\xC5\xA8\x63\x94\xCD\x0A\x32\xA0\xA6\x2A\x8F\x5D"
+ "\x6C\xCC\xBF\x49\x3D\xAA\x43\xF7\x83\x62\xBB\xCA\x40\xAD\xF7\x33"
+ "\xF8\x71\xE0\xC0\x09\x98\xD9\xBF\xD6\x88\x06\x56\x66\x6C\xD7\xBE"
+ "\x4F\xE9\x89\x2C\x61\xDC\xD5\xCD\x23\xA5\xE4\x27\x7E\xEE\x8B\x4A"
+ "\xFD\x29\xB6\x9B\xBA\x55\x66\x0A\x21\x71\x12\xFF\x6E\x34\x56\xB1",
+ 223, 512, },
+ { GCRY_MD_CSHAKE128,
+ "!",
+ "\x9d\x22\x2c\x79\xc4\xff\x9d\x09\x2c\xf6\xca\x86\x14\x3a\xa4\x11"
+ "\xe3\x69\x97\x38\x08\xef\x97\x09\x32\x55\x82\x6c\x55\x72\xef\x58"
+ "\x42\x4c\x4b\x5c\x28\x47\x5f\xfd\xcf\x98\x16\x63\x86\x7f\xec\x63"
+ "\x21\xc1\x26\x2e\x38\x7b\xcc\xf8\xca\x67\x68\x84\xc4\xa9\xd0\xc1"
+ "\x3b\xfa\x68\x69\x76\x3d\x5a\xe4\xbb\xc9\xb3\xcc\xd0\x9d\x1c\xa5"
+ "\xea\x74\x46\x53\x8d\x69\xb3\xfb\x98\xc7\x2b\x59\xa2\xb4\x81\x7d"
+ "\xb5\xea\xdd\x90\x11\xf9\x0f\xa7\x10\x91\x93\x1f\x81\x34\xf4\xf0"
+ "\x0b\x56\x2e\x2f\xe1\x05\x93\x72\x70\x36\x1c\x19\x09\x86\x2a\xd4"
+ "\x50\x46\xe3\x93\x2f\x5d\xd3\x11\xec\x72\xfe\xc5\xf8\xfb\x8f\x60"
+ "\xb4\x5a\x3b\xee\x3f\x85\xbb\xf7\xfc\xed\xc6\xa5\x55\x67\x76\x48"
+ "\xe0\x65\x4b\x38\x19\x41\xa8\x6b\xd3\xe5\x12\x65\x7b\x0d\x57\xa7"
+ "\x99\x1f\xc4\x54\x3f\x89\xd8\x29\x04\x92\x22\x2c\xe4\xa3\x3e\x17"
+ "\x60\x2b\x3b\x99\xc0\x09\xf7\x65\x5f\x87\x53\x5c\xda\xa3\x71\x6f"
+ "\x58\xc4\x7b\x8a\x15\x7a\xd1\x95\xf0\x28\x09\xf2\x75\x00\xb9\x25"
+ "\x49\x79\x31\x1c\x6b\xb4\x15\x96\x8c\xd1\x04\x31\x16\x9a\x27\xd5"
+ "\xa8\xd6\x1e\x13\xa6\xb8\xb7\x7a\xf1\xf8\xb6\xdd\x2e\xef\xde\xa0"
+ "\x40\x78\x96\x80\x49\x0b\x5e\xdc\xb1\xd3\xe5\x38\xa4\x66\xf7\x57"
+ "\xad\x71\x8f\xe1\xfd\x9f\xae\xef\xa4\x72\x46\xad\x5e\x36\x7f\x87"
+ "\xd3\xb4\x85\x0d\x44\x86\xeb\x21\x99\xe9\x4a\x79\x79\xe2\x09\x1a"
+ "\xbc\xdf\x3b\xc1\x33\x79\xc8\x96\xdc\xeb\x79\xa8\xfd\x08\xf1\x10"
+ "\x73\xf3\x3e\x3f\x99\x23\x22\xb3\x12\x02\xde\xe2\x34\x33\x0c\xf3"
+ "\x30\x4a\x58\x8f\x0d\x59\xda\xe4\xe6\x3b\xa2\xac\x3c\xe6\x82\xcc"
+ "\x19\xd4\xe3\x41\x67\x8c\xc3\xa6\x7a\x47\xc1\x13\xb4\xdb\x89\x0f"
+ "\x30\xa9\x2a\xa0\x8a\x1f\x6d\xc8\xfb\x64\x63\xf8\x03\x8c\x2b\x40"
+ "\xb2\x53\x00\x77\xb2\x36\xce\x88\xaf\xcc\xcd\xa0\x8a\xd6\xd7\x5e"
+ "\xee\x18\x99\xb1\x0c\xd8\x00\xc2\xce\x53\x72\xbf\xf2\x2e\xe3\xa3"
+ "\x39\xd4\xb9\xc1\xa2\xf5\xf4\xb8\x20\xf6\x87\xe5\x51\x9b\xd0\x5b"
+ "\x1f\xc5\xda\x0e\xb4\x53\x36\x81\x4f\x48\x13\x2c\x64\x0e\x66\xc3"
+ "\xa0\x2a\x22\xe6\x35\x98\xf9\x4f\x22\xf3\x51\x84\x11\x04\x46\xb6"
+ "\x48\xcf\x84\x74\xf3\x0c\x43\xea\xd5\x83\x09\xfb\x25\x90\x16\x09"
+ "\xe2\x41\x87\xe8\x01\xc8\x09\x56\x1a\x64\x80\x94\x50\xe6\x03\xc4"
+ "\xa8\x03\x95\x25\xc4\x76\xb5\x8e\x32\xce\x2c\x47\xb3\x7d\xa5\x91",
+ 0, 512, },
+ { GCRY_MD_CSHAKE256,
+ "",
+ "\x46\xB9\xDD\x2B\x0B\xA8\x8D\x13\x23\x3B\x3F\xEB\x74\x3E\xEB\x24"
+ "\x3F\xCD\x52\xEA\x62\xB8\x1B\x82\xB5\x0C\x27\x64\x6E\xD5\x76\x2F"
+ "\xD7\x5D\xC4\xDD\xD8\xC0\xF2\x00\xCB\x05\x01\x9D\x67\xB5\x92\xF6"
+ "\xFC\x82\x1C\x49\x47\x9A\xB4\x86\x40\x29\x2E\xAC\xB3\xB7\xC4\xBE"
+ "\x14\x1E\x96\x61\x6F\xB1\x39\x57\x69\x2C\xC7\xED\xD0\xB4\x5A\xE3"
+ "\xDC\x07\x22\x3C\x8E\x92\x93\x7B\xEF\x84\xBC\x0E\xAB\x86\x28\x53"
+ "\x34\x9E\xC7\x55\x46\xF5\x8F\xB7\xC2\x77\x5C\x38\x46\x2C\x50\x10"
+ "\xD8\x46\xC1\x85\xC1\x51\x11\xE5\x95\x52\x2A\x6B\xCD\x16\xCF\x86"
+ "\xF3\xD1\x22\x10\x9E\x3B\x1F\xDD\x94\x3B\x6A\xEC\x46\x8A\x2D\x62"
+ "\x1A\x7C\x06\xC6\xA9\x57\xC6\x2B\x54\xDA\xFC\x3B\xE8\x75\x67\xD6"
+ "\x77\x23\x13\x95\xF6\x14\x72\x93\xB6\x8C\xEA\xB7\xA9\xE0\xC5\x8D"
+ "\x86\x4E\x8E\xFD\xE4\xE1\xB9\xA4\x6C\xBE\x85\x47\x13\x67\x2F\x5C"
+ "\xAA\xAE\x31\x4E\xD9\x08\x3D\xAB\x4B\x09\x9F\x8E\x30\x0F\x01\xB8"
+ "\x65\x0F\x1F\x4B\x1D\x8F\xCF\x3F\x3C\xB5\x3F\xB8\xE9\xEB\x2E\xA2"
+ "\x03\xBD\xC9\x70\xF5\x0A\xE5\x54\x28\xA9\x1F\x7F\x53\xAC\x26\x6B"
+ "\x28\x41\x9C\x37\x78\xA1\x5F\xD2\x48\xD3\x39\xED\xE7\x85\xFB\x7F"
+ "\x5A\x1A\xAA\x96\xD3\x13\xEA\xCC\x89\x09\x36\xC1\x73\xCD\xCD\x0F"
+ "\xAB\x88\x2C\x45\x75\x5F\xEB\x3A\xED\x96\xD4\x77\xFF\x96\x39\x0B"
+ "\xF9\xA6\x6D\x13\x68\xB2\x08\xE2\x1F\x7C\x10\xD0\x4A\x3D\xBD\x4E"
+ "\x36\x06\x33\xE5\xDB\x4B\x60\x26\x01\xC1\x4C\xEA\x73\x7D\xB3\xDC"
+ "\xF7\x22\x63\x2C\xC7\x78\x51\xCB\xDD\xE2\xAA\xF0\xA3\x3A\x07\xB3"
+ "\x73\x44\x5D\xF4\x90\xCC\x8F\xC1\xE4\x16\x0F\xF1\x18\x37\x8F\x11"
+ "\xF0\x47\x7D\xE0\x55\xA8\x1A\x9E\xDA\x57\xA4\xA2\xCF\xB0\xC8\x39"
+ "\x29\xD3\x10\x91\x2F\x72\x9E\xC6\xCF\xA3\x6C\x6A\xC6\xA7\x58\x37"
+ "\x14\x30\x45\xD7\x91\xCC\x85\xEF\xF5\xB2\x19\x32\xF2\x38\x61\xBC"
+ "\xF2\x3A\x52\xB5\xDA\x67\xEA\xF7\xBA\xAE\x0F\x5F\xB1\x36\x9D\xB7"
+ "\x8F\x3A\xC4\x5F\x8C\x4A\xC5\x67\x1D\x85\x73\x5C\xDD\xDB\x09\xD2"
+ "\xB1\xE3\x4A\x1F\xC0\x66\xFF\x4A\x16\x2C\xB2\x63\xD6\x54\x12\x74"
+ "\xAE\x2F\xCC\x86\x5F\x61\x8A\xBE\x27\xC1\x24\xCD\x8B\x07\x4C\xCD"
+ "\x51\x63\x01\xB9\x18\x75\x82\x4D\x09\x95\x8F\x34\x1E\xF2\x74\xBD"
+ "\xAB\x0B\xAE\x31\x63\x39\x89\x43\x04\xE3\x58\x77\xB0\xC2\x8A\x9B"
+ "\x1F\xD1\x66\xC7\x96\xB9\xCC\x25\x8A\x06\x4A\x8F\x57\xE2\x7F\x2A",
+ 0, 512, },
+ { GCRY_MD_CSHAKE256,
+ "",
+ "\x46\xB9\xDD\x2B\x0B\xA8\x8D\x13\x23\x3B\x3F\xEB\x74\x3E\xEB\x24"
+ "\x3F\xCD\x52\xEA\x62\xB8\x1B\x82\xB5\x0C\x27\x64\x6E\xD5\x76\x2F"
+ "\xD7\x5D\xC4\xDD\xD8\xC0\xF2\x00\xCB\x05\x01\x9D\x67\xB5\x92\xF6"
+ "\xFC\x82\x1C\x49\x47\x9A\xB4\x86\x40\x29\x2E\xAC\xB3\xB7\xC4\xBE",
+ 0, 0, /* test md_read interface */ },
+ { GCRY_MD_CSHAKE256,
+ "\xB3\x2D\x95\xB0\xB9\xAA\xD2\xA8\x81\x6D\xE6\xD0\x6D\x1F\x86\x00"
+ "\x85\x05\xBD\x8C\x14\x12\x4F\x6E\x9A\x16\x3B\x5A\x2A\xDE\x55\xF8"
+ "\x35\xD0\xEC\x38\x80\xEF\x50\x70\x0D\x3B\x25\xE4\x2C\xC0\xAF\x05"
+ "\x0C\xCD\x1B\xE5\xE5\x55\xB2\x30\x87\xE0\x4D\x7B\xF9\x81\x36\x22"
+ "\x78\x0C\x73\x13\xA1\x95\x4F\x87\x40\xB6\xEE\x2D\x3F\x71\xF7\x68"
+ "\xDD\x41\x7F\x52\x04\x82\xBD\x3A\x08\xD4\xF2\x22\xB4\xEE\x9D\xBD"
+ "\x01\x54\x47\xB3\x35\x07\xDD\x50\xF3\xAB\x42\x47\xC5\xDE\x9A\x8A"
+ "\xBD\x62\xA8\xDE\xCE\xA0\x1E\x3B\x87\xC8\xB9\x27\xF5\xB0\x8B\xEB"
+ "\x37\x67\x4C\x6F\x8E\x38\x0C\x04",
+ "\xCC\x2E\xAA\x04\xEE\xF8\x47\x9C\xDA\xE8\x56\x6E\xB8\xFF\xA1\x10"
+ "\x0A\x40\x79\x95\xBF\x99\x9A\xE9\x7E\xDE\x52\x66\x81\xDC\x34\x90"
+ "\x61\x6F\x28\x44\x2D\x20\xDA\x92\x12\x4C\xE0\x81\x58\x8B\x81\x49"
+ "\x1A\xED\xF6\x5C\xAA\xF0\xD2\x7E\x82\xA4\xB0\xE1\xD1\xCA\xB2\x38"
+ "\x33\x32\x8F\x1B\x8D\xA4\x30\xC8\xA0\x87\x66\xA8\x63\x70\xFA\x84"
+ "\x8A\x79\xB5\x99\x8D\xB3\xCF\xFD\x05\x7B\x96\xE1\xE2\xEE\x0E\xF2"
+ "\x29\xEC\xA1\x33\xC1\x55\x48\xF9\x83\x99\x02\x04\x37\x30\xE4\x4B"
+ "\xC5\x2C\x39\xFA\xDC\x1D\xDE\xEA\xD9\x5F\x99\x39\xF2\x20\xCA\x30"
+ "\x06\x61\x54\x0D\xF7\xED\xD9\xAF\x37\x8A\x5D\x4A\x19\xB2\xB9\x3E"
+ "\x6C\x78\xF4\x9C\x35\x33\x43\xA0\xB5\xF1\x19\x13\x2B\x53\x12\xD0"
+ "\x04\x83\x1D\x01\x76\x9A\x31\x6D\x2F\x51\xBF\x64\xCC\xB2\x0A\x21"
+ "\xC2\xCF\x7A\xC8\xFB\x6F\x6E\x90\x70\x61\x26\xBD\xAE\x06\x11\xDD"
+ "\x13\x96\x2E\x8B\x53\xD6\xEA\xE2\x6C\x7B\x0D\x25\x51\xDA\xF6\x24"
+ "\x8E\x9D\x65\x81\x73\x82\xB0\x4D\x23\x39\x2D\x10\x8E\x4D\x34\x43"
+ "\xDE\x5A\xDC\x72\x73\xC7\x21\xA8\xF8\x32\x0E\xCF\xE8\x17\x7A\xC0"
+ "\x67\xCA\x8A\x50\x16\x9A\x6E\x73\x00\x0E\xBC\xDC\x1E\x4E\xE6\x33"
+ "\x9F\xC8\x67\xC3\xD7\xAE\xAB\x84\x14\x63\x98\xD7\xBA\xDE\x12\x1D"
+ "\x19\x89\xFA\x45\x73\x35\x56\x4E\x97\x57\x70\xA3\xA0\x02\x59\xCA"
+ "\x08\x70\x61\x08\x26\x1A\xA2\xD3\x4D\xE0\x0F\x8C\xAC\x7D\x45\xD3"
+ "\x5E\x5A\xA6\x3E\xA6\x9E\x1D\x1A\x2F\x7D\xAB\x39\x00\xD5\x1E\x0B"
+ "\xC6\x53\x48\xA2\x55\x54\x00\x70\x39\xA5\x2C\x3C\x30\x99\x80\xD1"
+ "\x7C\xAD\x20\xF1\x15\x63\x10\xA3\x9C\xD3\x93\x76\x0C\xFE\x58\xF6"
+ "\xF8\xAD\xE4\x21\x31\x28\x82\x80\xA3\x5E\x1D\xB8\x70\x81\x83\xB9"
+ "\x1C\xFA\xF5\x82\x7E\x96\xB0\xF7\x74\xC4\x50\x93\xB4\x17\xAF\xF9"
+ "\xDD\x64\x17\xE5\x99\x64\xA0\x1B\xD2\xA6\x12\xFF\xCF\xBA\x18\xA0"
+ "\xF1\x93\xDB\x29\x7B\x9A\x6C\xC1\xD2\x70\xD9\x7A\xAE\x8F\x8A\x3A"
+ "\x6B\x26\x69\x5A\xB6\x64\x31\xC2\x02\xE1\x39\xD6\x3D\xD3\xA2\x47"
+ "\x78\x67\x6C\xEF\xE3\xE2\x1B\x02\xEC\x4E\x8F\x5C\xFD\x66\x58\x7A"
+ "\x12\xB4\x40\x78\xFC\xD3\x9E\xEE\x44\xBB\xEF\x4A\x94\x9A\x63\xC0"
+ "\xDF\xD5\x8C\xF2\xFB\x2C\xD5\xF0\x02\xE2\xB0\x21\x92\x66\xCF\xC0"
+ "\x31\x81\x74\x86\xDE\x70\xB4\x28\x5A\x8A\x70\xF3\xD3\x8A\x61\xD3"
+ "\x15\x5D\x99\xAA\xF4\xC2\x53\x90\xD7\x36\x45\xAB\x3E\x8D\x80\xF0",
+ 136, 512, },
+ { GCRY_MD_CSHAKE256,
+ "!",
+ "\x35\x78\xa7\xa4\xca\x91\x37\x56\x9c\xdf\x76\xed\x61\x7d\x31\xbb"
+ "\x99\x4f\xca\x9c\x1b\xbf\x8b\x18\x40\x13\xde\x82\x34\xdf\xd1\x3a"
+ "\x3f\xd1\x24\xd4\xdf\x76\xc0\xa5\x39\xee\x7d\xd2\xf6\xe1\xec\x34"
+ "\x61\x24\xc8\x15\xd9\x41\x0e\x14\x5e\xb5\x61\xbc\xd9\x7b\x18\xab"
+ "\x6c\xe8\xd5\x55\x3e\x0e\xab\x3d\x1f\x7d\xfb\x8f\x9d\xee\xfe\x16"
+ "\x84\x7e\x21\x92\xf6\xf6\x1f\xb8\x2f\xb9\x0d\xde\x60\xb1\x90\x63"
+ "\xc5\x6a\x4c\x55\xcd\xd7\xb6\x72\xb7\x5b\xf5\x15\xad\xbf\xe2\x04"
+ "\x90\x3c\x8c\x00\x36\xde\x54\xa2\x99\x9a\x92\x0d\xe9\x0f\x66\xd7"
+ "\xff\x6e\xc8\xe4\xc9\x3d\x24\xae\x34\x6f\xdc\xb3\xa5\xa5\xbd\x57"
+ "\x39\xec\x15\xa6\xed\xdb\x5c\xe5\xb0\x2d\xa5\x30\x39\xfa\xc6\x3e"
+ "\x19\x55\x5f\xaa\x2e\xdd\xc6\x93\xb1\xf0\xc2\xa6\xfc\xbe\x7c\x0a"
+ "\x0a\x09\x1d\x0e\xe7\x00\xd7\x32\x2e\x4b\x0f\xf0\x95\x90\xde\x16"
+ "\x64\x22\xf9\xea\xd5\xda\x4c\x99\x3d\x60\x5f\xe4\xd9\xc6\x34\x84"
+ "\x3a\xa1\x78\xb1\x76\x72\xc6\x56\x8c\x8a\x2e\x62\xab\xeb\xea\x2c"
+ "\x21\xc3\x02\xbd\x36\x6a\xd6\x98\x95\x9e\x1f\x6e\x43\x4a\xf1\x55"
+ "\x56\x8b\x27\x34\xd8\x37\x9f\xcd\x3f\xfe\x64\x89\xba\xff\xa6\xd7"
+ "\x11\x09\x44\x2e\x1b\x34\x4f\x13\x8a\x09\xca\xe3\xe2\xd3\x94\x2e"
+ "\xee\x82\x8f\xc4\x7e\x64\xde\xb5\xe0\x0a\x02\x4a\xe1\xf2\xc0\x77"
+ "\xe6\xb7\xb1\x33\xf6\xc1\xde\x91\x30\x92\xd4\xe8\x29\xec\xd2\xb2"
+ "\xef\x28\xca\x80\x20\x82\x1e\x2b\x8b\xe5\x17\xd9\x3e\xd0\x88\x36"
+ "\xf6\xf0\x66\xcc\x3d\x03\xb6\x25\xd8\x49\x7f\x29\xdb\xc1\xc3\x9e"
+ "\x6f\xe4\x63\x22\x6f\x85\xc1\x28\xa2\xc2\x98\x88\x11\x2e\x06\xa9"
+ "\x9c\x5d\x17\xb2\x5e\x90\x0d\x20\x4f\x39\x72\x31\xcd\xf7\x9c\x31"
+ "\x34\x46\x53\x2d\xad\x07\xf4\xc0\xbd\x9f\xba\x1d\xd4\x13\xd8\xa7"
+ "\xe6\xcb\xc0\xa0\x86\x2c\xc7\x69\x23\x9a\x89\xf9\xdb\x08\x5b\x78"
+ "\xa0\x54\x59\x6a\xd7\x08\x0d\xdf\x96\x01\x9b\x73\x99\xb5\x03\x48"
+ "\x0e\x5a\x65\xa2\x20\x8d\x74\x72\x4c\x98\x7d\x32\x5e\x9b\x0e\x82"
+ "\xfe\xcd\x4f\x27\xf3\x13\x5b\x1d\x9e\x27\xb4\x8e\x69\xdd\x6f\x59"
+ "\x62\xb8\xa6\x3b\x48\x92\x1e\xc8\xee\x53\x86\x9f\x1a\xc1\xc8\x18"
+ "\x23\x87\xee\x0d\x6c\xfe\xf6\x53\xff\x8b\xf6\x05\xf1\x47\x04\xb7"
+ "\x1b\xeb\x65\x53\xf2\x81\xfa\x75\x69\x48\xc4\x38\x49\x4b\x19\xb4"
+ "\xee\x69\xa5\x43\x6b\x22\x2b\xc9\x88\xed\xa4\xac\x60\x00\x24\xc9",
+ 0, 512, },
{ GCRY_MD_BLAKE2B_512, "abc",
"\xBA\x80\xA5\x3F\x98\x1C\x4D\x0D\x6A\x27\x97\xB6\x9F\x12\xF6\xE9"
"\x4C\x21\x2F\x14\x68\x5A\xC4\xB7\x4B\x12\xBB\x6F\xDB\xFF\xA2\xD1"
@@ -15556,6 +15799,8 @@ check_one_hmac (int algo, const char *data, int datalen,
gcry_md_close (hd2);
}

+
+
static void
check_hmac (void)
{
@@ -15924,6 +16169,19 @@ check_one_mac (int algo, const char *data, int datalen,
return;
}

+
+ /* test different order of setting IV and key for one KMAC variant */
+ if (algo == GCRY_MAC_KMAC128_128 && ivlen && iv)
+ {
+ clutter_vector_registers();
+ err = gcry_mac_setiv (hd, iv, ivlen);
+ if (err)
+ fail("algo %d, mac gcry_mac_setiv failed: %s\n", algo,
+ gpg_strerror (err));
+ if (err)
+ goto out;
+ }
+
clutter_vector_registers();
err = gcry_mac_setkey (hd, key, keylen);
if (err)
@@ -15940,12 +16198,12 @@ check_one_mac (int algo, const char *data, int datalen,
goto out;
}

- if (ivlen && iv)
+ if (algo != GCRY_MAC_KMAC128_128 && ivlen && iv)
{
clutter_vector_registers();
err = gcry_mac_setiv (hd, iv, ivlen);
if (err)
- fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo,
+ fail("algo %d, mac gcry_mac_setiv failed: %s\n", algo,
gpg_strerror (err));
if (err)
goto out;
@@ -16964,6 +17222,55 @@ check_mac (void)
NULL,
16, 32 },
#endif /* USE_GOST28147 */
+#if USE_SHA3
+ { GCRY_MAC_KMAC128_128,
+ "\x00\x01\x02\x03",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\xE5\x78\x0B\x0D\x3E\xA6\xF7\xD3\xA4\x29\xC5\x70\x6A\xA4\x3A\x00\xFA\xDB\xD7\xD4\x96\x28\x83\x9E\x31\x87\x24\x3F\x45\x6E\xE1\x4E",
+ "",
+ 4, 0
+ },
+ { GCRY_MAC_KMAC128_128,
+ "\x00\x01\x02\x03",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\x3B\x1F\xBA\x96\x3C\xD8\xB0\xB5\x9E\x8C\x1A\x6D\x71\x88\x8B\x71\x43\x65\x1A\xF8\xBA\x0A\x70\x70\xC0\x97\x9E\x28\x11\x32\x4A\xA5",
+ "My Tagged Application",
+ 4, 0
+ },
+ { GCRY_MAC_KMAC128_128,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\x1F\x5B\x4E\x6C\xCA\x02\x20\x9E\x0D\xCB\x5C\xA6\x35\xB8\x9A\x15\xE2\x71\xEC\xC7\x60\x07\x1D\xFD\x80\x5F\xAA\x38\xF9\x72\x92\x30",
+ "My Tagged Application",
+ 200, 0
+ },
+ { GCRY_MAC_KMAC256_256,
+ "\x00\x01\x02\x03",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\x20\xC5\x70\xC3\x13\x46\xF7\x03\xC9\xAC\x36\xC6\x1C\x03\xCB\x64\xC3\x97\x0D\x0C\xFC\x78\x7E\x9B\x79\x59\x9D\x27\x3A\x68\xD2\xF7\xF6\x9D\x4C\xC3\xDE\x9D\x10\x4A\x35\x16\x89\xF2\x7C\xF6\xF5\x95\x1F\x01\x03\xF3\x3F\x4F\x24\x87\x10\x24\xD9\xC2\x77\x73\xA8\xDD",
+ "My Tagged Application",
+ 4, 0
+ },
+ {
+ /* sample 5 from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf#page=21 */
+ GCRY_MAC_KMAC256_256,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\x75\x35\x8C\xF3\x9E\x41\x49\x4E\x94\x97\x07\x92\x7C\xEE\x0A\xF2\x0A\x3F\xF5\x53\x90\x4C\x86\xB0\x8F\x21\xCC\x41\x4B\xCF\xD6\x91\x58\x9D\x27\xCF\x5E\x15\x36\x9C\xBB\xFF\x8B\x9A\x4C\x2E\xB1\x78\x00\x85\x5D\x02\x35\xFF\x63\x5D\xA8\x25\x33\xEC\x6B\x75\x9B\x69",
+ "",
+ 200, 0
+ },
+ {
+ /* sample 6 from https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf#page=27 */
+ GCRY_MAC_KMAC256_256,
+ "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2A\x2B\x2C\x2D\x2E\x2F\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3A\x3B\x3C\x3D\x3E\x3F\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4A\x4B\x4C\x4D\x4E\x4F\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5A\x5B\x5C\x5D\x5E\x5F\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6A\x6B\x6C\x6D\x6E\x6F\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7A\x7B\x7C\x7D\x7E\x7F\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8A\x8B\x8C\x8D\x8E\x8F\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9A\x9B\x9C\x9D\x9E\x9F\xA0\xA1\xA2\xA3\xA4\xA5\xA6\xA7\xA8\xA9\xAA\xAB\xAC\xAD\xAE\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB\xBC\xBD\xBE\xBF\xC0\xC1\xC2\xC3\xC4\xC5\xC6\xC7",
+ "\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f",
+ "\xB5\x86\x18\xF7\x1F\x92\xE1\xD5\x6C\x1B\x8C\x55\xDD\xD7\xCD\x18\x8B\x97\xB4\xCA\x4D\x99\x83\x1E\xB2\x69\x9A\x83\x7D\xA2\xE4\xD9\x70\xFB\xAC\xFD\xE5\x00\x33\xAE\xA5\x85\xF1\xA2\x70\x85\x10\xC3\x2D\x07\x88\x08\x01\xBD\x18\x28\x98\xFE\x47\x68\x76\xFC\x89\x65",
+ "My Tagged Application",
+ 200, 0
+ },
+
+#endif
{ 0 },
};
gcry_error_t err;
@@ -17000,7 +17307,7 @@ check_mac (void)
gcry_mac_algo_name (algos[i].algo),
algos[i].algo, (int)strlen(algos[i].key),
(!strcmp(algos[i].data, "!") || !strcmp(algos[i].data, "?"))
- ? 1000000 : (int)strlen(algos[i].data));
+ ? 1000000 : ( algos[i].dlen ? algos[i].dlen : (int)strlen(algos[i].data)));

klen = algos[i].klen ? algos[i].klen : strlen(algos[i].key);
dlen = algos[i].dlen ? algos[i].dlen : strlen (algos[i].data);
diff --git a/tests/cshake.c b/tests/cshake.c
new file mode 100644
index 00000000..9bac4fba
--- /dev/null
+++ b/tests/cshake.c
@@ -0,0 +1,335 @@
+/* cshake.c - cSHAKE xof hash regression tests
+ * Copyright (C) 2001, 2002, 2003, 2005, 2008,
+ * 2009 Free Software Foundation, Inc.
+ * Copyright (C) 2013 g10 Code GmbH
+ * Copyright (C) 2023 MTG AG
+ *
+ * This file is part of Libgcrypt.
+ *
+ * Libgcrypt is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * Libgcrypt is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <assert.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h> /* uintptr_t */
+#elif defined(HAVE_INTTYPES_H)
+#include <inttypes.h>
+#else
+/* In this case, uintptr_t is provided by config.h. */
+#endif
+
+// #include "../src/gcrypt-int.h"
+// #include "../src/gcrypt-testapi.h"
+
+#define PGM "cSHAKE"
+#include "t-common.h"
+#include "gcrypt.h"
+
+#if __GNUC__ >= 4
+#define ALWAYS_INLINE __attribute__ ((always_inline))
+#else
+#define ALWAYS_INLINE
+#endif
+
+typedef struct
+{
+
+ enum gcry_md_algos algo;
+ const char *data_hex;
+ const char *n;
+ const char *s;
+ unsigned output_size_bytes;
+ const char *expected_output_hex;
+
+} test_vec_t;
+
+test_vec_t test_vecs[] = {
+
+ { /* from
+ https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/cSHAKE_samples.pdf
+ */
+ GCRY_MD_CSHAKE128,
+ "00010203",
+ "",
+ "Email Signature",
+ 32,
+ "C1C36925B6409A04F1B504FCBCA9D82B4017277CB5ED2B2065FC1D3814D5AAF5" },
+ { /* from
+ https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/cSHAKE_samples.pdf
+ */
+ GCRY_MD_CSHAKE128,
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222"
+ "32"
+ "425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424344454647"
+ "48"
+ "494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6"
+ "C6"
+ "D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90"
+ "91"
+ "92939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B"
+ "5B"
+ "6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7",
+ "",
+ "Email Signature",
+ 32,
+ "C5221D50E4F822D96A2E8881A961420F294B7B24FE3D2094BAED2C6524CC166B" },
+
+ { /* from
+ https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/cSHAKE_samples.pdf
+ */
+ GCRY_MD_CSHAKE256,
+ "00010203",
+ "",
+ "Email Signature",
+ 64,
+ "D008828E2B80AC9D2218FFEE1D070C48B8E4C87BFF32C9699D5B6896EEE0EDD164020E2"
+ "BE"
+ "0560858D9C00C037E34A96937C561A74C412BB4C746469527281C8C" },
+
+ { /* from
+ https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/cSHAKE_samples.pdf
+ */
+ GCRY_MD_CSHAKE256,
+ "000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F2021222"
+ "32"
+ "425262728292A2B2C2D2E2F303132333435363738393A3B3C3D3E3F4041424344454647"
+ "48"
+ "494A4B4C4D4E4F505152535455565758595A5B5C5D5E5F606162636465666768696A6B6"
+ "C6"
+ "D6E6F707172737475767778797A7B7C7D7E7F808182838485868788898A8B8C8D8E8F90"
+ "91"
+ "92939495969798999A9B9C9D9E9FA0A1A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3B4B"
+ "5B"
+ "6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5C6C7",
+ "",
+ "Email Signature",
+ 64,
+ "07DC27B11E51FBAC75BC7B3C1D983E8B4B85FB1DEFAF218912AC86430273091727F42B1"
+ "7ED1DF63E8EC118F04B23633C1DFB1574C8FB55CB45DA8E25AFB092BB" },
+ { /* Created with https://asecuritysite.com/golang/cs */
+ GCRY_MD_CSHAKE128,
+ "00010203",
+ "ABC",
+ "Email Signature",
+ 32,
+ "5CF74DC523ADC0B97EC3614E703835277E9F818879AA1EAE5B2B4E4472EB6A68" },
+ { /* Created with https://asecuritysite.com/golang/cs */
+ GCRY_MD_CSHAKE256,
+ "00010203",
+ "ABC",
+ "Email Signature",
+ 32,
+ "0C34C14C4A56E5FC01BE8C04C759DA61437E86B88DF3E21A934436D427A85E9D" },
+ { /* Created with https://asecuritysite.com/golang/cs */
+ GCRY_MD_CSHAKE128,
+ "00010203",
+ "ABC",
+ "",
+ 32,
+ "266035DF0BEC07A61073571CB3DEB195002955D8A7C88B821A0B1D20ECAC6B5B" },
+ { /* Created with https://asecuritysite.com/golang/cs */
+ GCRY_MD_CSHAKE256,
+ "00010203",
+ "ABC",
+ "",
+ 32,
+ "89D888D030A5CF82CAFB3D9D2B7869C91B46D186700306265606CC97D3DAE42A" }
+};
+
+
+static void *
+hex2buffer (const char *string, size_t *r_length)
+{
+ const char *s;
+ unsigned char *buffer;
+ size_t length;
+
+ buffer = xmalloc (strlen (string) / 2 + 1);
+ length = 0;
+ for (s = string; *s; s += 2)
+ {
+ if (!hexdigitp (s) || !hexdigitp (s + 1))
+ die ("invalid hex digits in \"%s\"\n", string);
+ ((unsigned char *)buffer)[length++] = xtoi_2 (s);
+ }
+ *r_length = length;
+ return buffer;
+}
+
+
+int
+main (int argc, char **argv)
+{
+ gpg_error_t err = GPG_ERR_NO_ERROR;
+ int last_argc = -1;
+
+ unsigned test_cnt = 0;
+
+ if (argc)
+ {
+ argc--;
+ argv++;
+ }
+
+ while (argc && last_argc != argc)
+ {
+ last_argc = argc;
+ if (!strcmp (*argv, "--"))
+ {
+ argc--;
+ argv++;
+ break;
+ }
+ else if (!strcmp (*argv, "--verbose"))
+ {
+ verbose++;
+ argc--;
+ argv++;
+ }
+ else if (!strcmp (*argv, "--debug"))
+ {
+ verbose = debug = 1;
+ argc--;
+ argv++;
+ }
+ }
+ for (unsigned i = 0; i < DIM (test_vecs); i++)
+ {
+ gcry_md_hd_t hd, hd2;
+ enum gcry_md_algos algo = test_vecs[i].algo;
+ test_vec_t *test = &test_vecs[i];
+ unsigned char result_buf[256];
+ unsigned char result_buf2[256];
+ void *compare_buf, *data_buf;
+ size_t compare_len, data_len;
+ /* vary the secure flag in each test */
+ int flags = i % 2 ? GCRY_MD_FLAG_SECURE : 0;
+ err = gcry_md_open (&hd, algo, flags);
+ if (err)
+ {
+ fail (
+ "algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err));
+ goto leave;
+ }
+ if (strlen (test->n))
+ {
+ err = gcry_md_ctl(
+ hd, GCRYCTL_CSHAKE_N, (unsigned char*) test->n, strlen (test->n));
+ if (err)
+ {
+ fail ("algo %d, gcry_md_set_add_input (N) failed: %s\n",
+ algo,
+ gpg_strerror (err));
+ goto leave;
+ }
+ }
+ if (strlen (test->s))
+ {
+ err = gcry_md_ctl(
+ hd, GCRYCTL_CSHAKE_S, (unsigned char*) test->s, strlen (test->s));
+ if (err)
+ {
+ fail ("algo %d, gcry_md_set_add_input (S) failed: %s\n",
+ algo,
+ gpg_strerror (err));
+ goto leave;
+ }
+ }
+ {
+ gcry_err_code_t exp_err = GPG_ERR_INV_STATE;
+ if (strlen (test->n))
+ {
+ /* try to set n or s again */
+ exp_err = gcry_md_ctl(
+ hd, GCRYCTL_CSHAKE_N, (unsigned char*) test->n, strlen (test->n));
+ }
+ else if (strlen (test->s))
+ {
+ exp_err = gcry_md_ctl(
+ hd, GCRYCTL_CSHAKE_S, (unsigned char*) test->s, strlen (test->s));
+ }
+
+ if (exp_err != gpg_error(GPG_ERR_INV_STATE))
+ {
+ fail ("algo %d: wrong error code when setting additional "
+ "input in wrong order: "
+ "%d (%s), but "
+ "expected %d (%s)\n",
+ algo,
+ exp_err,
+ gpg_strerror (exp_err),
+ gpg_error(GPG_ERR_INV_STATE),
+ gpg_strerror (GPG_ERR_INV_STATE));
+ }
+ }
+ data_buf = hex2buffer (test->data_hex, &data_len);
+ gcry_md_write (hd, data_buf, data_len);
+ err = gcry_md_copy (&hd2, hd);
+ if (err)
+ {
+ fail ("algo %d, problem with copying of hash context object\n",
+ algo);
+ }
+ else
+ {
+ gcry_md_extract (hd2, algo, result_buf2, test->output_size_bytes);
+ }
+ gcry_md_extract (hd, algo, result_buf, test->output_size_bytes);
+ if (!err)
+ {
+ if (memcmp (result_buf, result_buf2, test->output_size_bytes))
+ {
+ fail ("algo %d, result comparison with that copied of copied MD "
+ "CTX object failed in test %u\n",
+ algo,
+ i);
+ }
+ }
+ /* restore the clean error state after the copy operation */
+ err = GPG_ERR_NO_ERROR;
+ compare_buf = hex2buffer (test->expected_output_hex, &compare_len);
+ test_cnt++;
+ if (compare_len != test->output_size_bytes)
+ {
+ fail ("algo %d, internal problem with test data lengths\n", algo);
+ goto leave;
+ }
+ if (memcmp (compare_buf, result_buf, test->output_size_bytes))
+ {
+
+ fail ("algo %d, result comparison failed in test %u\n", algo, i);
+ }
+ xfree (compare_buf);
+ xfree (data_buf);
+ gcry_md_close (hd);
+ gcry_md_close (hd2);
+ }
+
+
+ if (verbose)
+ fprintf (stderr, "\nAll %u tests completed. \n", test_cnt);
+ if (error_count || verbose)
+ {
+ fprintf (stderr, "\nThere were %i errors\n", error_count);
+ }
+leave:
+ return err;
+}
--
2.30.2


_______________________________________________
Gcrypt-devel mailing list
Gcrypt-devel@gnupg.org
https://lists.gnupg.org/mailman/listinfo/gcrypt-devel