From 739f17781cacc53df8fba07986b609fe129e7412 Mon Sep 17 00:00:00 2001 From: NIIBE Yutaka Date: Thu, 18 Apr 2024 14:09:57 +0900 Subject: [PATCH] keccak.c also provides SHA-3 and SHAKE128. Signed-off-by: NIIBE Yutaka --- ChangeLog | 6 ++ src/Makefile | 2 +- src/ecc-ed448.c | 6 +- src/{shake256.c => keccak.c} | 159 +++++++++++++++++++++++++++-------- src/keccak.h | 24 ++++++ src/openpgp-do.c | 8 +- src/shake256.h | 13 --- 7 files changed, 161 insertions(+), 57 deletions(-) rename src/{shake256.c => keccak.c} (54%) create mode 100644 src/keccak.h delete mode 100644 src/shake256.h diff --git a/ChangeLog b/ChangeLog index cff35d7..d998e7d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2024-04-18 NIIBE Yutaka + + * src/keccak.c, src/keccak.h: Rename. Also offer SHA-3. + * src/ecc-ed448.c (ed448_sign): Use keccak_context. + * src/openpgp-do.c (proc_key_import, gpg_do_keygen): Likewise. + 2024-02-02 NIIBE Yutaka * src/modinv.c (modinv_normalize): Fix the computation. diff --git a/src/Makefile b/src/Makefile index 1ba515b..e4a5e21 100644 --- a/src/Makefile +++ b/src/Makefile @@ -13,7 +13,7 @@ CSRC = main.c \ modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \ mod25638.c ecc-ed25519.c ecc-x25519.c sha512.c \ p448.c ecc-x448.c \ - ecc-ed448.c shake256.c \ + ecc-ed448.c keccak.c \ random.c neug.c sha256.c INCDIR = diff --git a/src/ecc-ed448.c b/src/ecc-ed448.c index 70141c4..9a3d42a 100644 --- a/src/ecc-ed448.c +++ b/src/ecc-ed448.c @@ -3,7 +3,7 @@ * the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2 * d = -39081 * - * Copyright (C) 2021 Free Software Initiative of Japan + * Copyright (C) 2021, 2024 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -41,7 +41,7 @@ #include #include "p448.h" -#include "shake256.h" +#include "keccak.h" #define C_WORDS 7 @@ -761,7 +761,7 @@ ed448_sign (uint8_t *out, const uint8_t *input, unsigned int ilen, const uint8_t *a_in, const uint8_t *seed, const uint8_t *pk) { bn448 a[1], k[1], s[1]; - shake_context ctx; + keccak_context ctx; const unsigned char x_olen[2] = { 0, 0 }; uint32_t hash[BN912_WORDS]; uint8_t r[57]; diff --git a/src/shake256.c b/src/keccak.c similarity index 54% rename from src/shake256.c rename to src/keccak.c index c1cfa60..9994aac 100644 --- a/src/shake256.c +++ b/src/keccak.c @@ -1,7 +1,7 @@ /* - * shake256.c -- Compute SHAKE hash. + * keccak.c -- Compute Keccak hash. * - * Copyright (C) 2021 Free Software Initiative of Japan + * Copyright (C) 2021, 2024 Free Software Initiative of Japan * Author: NIIBE Yutaka * * This file is a part of Gnuk, a GnuPG USB Token implementation. @@ -17,7 +17,7 @@ * License for more details. * * You should have received a copy of the GNU General Public License - * along with this program. If not, see . + * along with this program. If not, see . * */ @@ -29,8 +29,25 @@ * August 2015. */ -#define SHAKE_BITS 256 -#define SHAKE_INDEX_MAX (200 - (SHAKE_BITS >> 2)) +#define INDEX_MAX(cap) (200 - (cap >> 3)) + +#define SHAKE256_CAPACITY 512 +#define SHAKE256_INDEX_MAX INDEX_MAX (SHAKE256_CAPACITY) + +#define SHAKE128_CAPACITY 256 +#define SHAKE128_INDEX_MAX INDEX_MAX (SHAKE128_CAPACITY) + +#define SHA3_512_CAPACITY 1024 +#define SHA3_512_INDEX_MAX INDEX_MAX (SHA3_512_CAPACITY) + +/* + * SHAKE is defined appending 11 at the end to RawSHAKE, + * RawSHAKE is defined adding 11 at the end to KECCAK, + * and KECCACK uses pad10*1 at the end. + * This means adding 111110*1 at the end. + */ +#define SHAKE_SUFFIX 0x1F +#define SHA3_SUFFIX 0x06 /* * b=1600 @@ -43,7 +60,8 @@ #include #include -#include "shake256.h" +#include +#include "keccak.h" /* Round constants in iota step. */ static const uint64_t rc[24] = { @@ -144,59 +162,128 @@ keccak_f1600 (uint64_t s[25]) } } -void -shake256_start (struct shake_context *shake) -{ - memset (shake, 0, sizeof (shake_context)); -} - -void -shake256_update (struct shake_context *shake, - const unsigned char *src, unsigned int size) +static void +keccak_update (struct keccak_context *keccak, + const unsigned char *src, unsigned int size) { if (size == 0) return; while (1) { - absorb (shake->state, shake->index, *src++); - if (++shake->index == SHAKE_INDEX_MAX) + absorb (keccak->state, keccak->index, *src++); + if (++keccak->index == keccak->index_max) { - keccak_f1600 (shake->state); - shake->index = 0; + keccak_f1600 (keccak->state); + keccak->index = 0; } if (--size == 0) break; } } -void -shake256_finish (struct shake_context *shake, - unsigned char *dst, unsigned int size) +static void +keccak_finish (struct keccak_context *keccak, + unsigned char *dst, unsigned int size, uint8_t suffix) { if (size == 0) return; - /* - * SHAKE is defined appending 11 at the end to RawSHAKE, - * RawSHAKE is defined adding 11 at the end to KECCAK, - * and KECCACK uses pad10*1 at the end. - * This means adding 111110*1 at the end. - */ - absorb (shake->state, shake->index, 0x1F); - absorb (shake->state, SHAKE_INDEX_MAX - 1, 0x80); - keccak_f1600 (shake->state); - shake->index = 0; + absorb (keccak->state, keccak->index, suffix); + absorb (keccak->state, keccak->index_max - 1, 0x80); + keccak_f1600 (keccak->state); + keccak->index = 0; while (1) { - *dst++ = squeeze (shake->state, shake->index); + *dst++ = squeeze (keccak->state, keccak->index); if (--size == 0) break; - if (++shake->index == SHAKE_INDEX_MAX) + if (++keccak->index == keccak->index_max) { - keccak_f1600 (shake->state); - shake->index = 0; + keccak_f1600 (keccak->state); + keccak->index = 0; } } } + +void +shake128_start (struct keccak_context *shake) +{ + memset (shake, 0, sizeof (keccak_context)); + shake->index_max = SHAKE128_INDEX_MAX; +} + +void +shake256_start (struct keccak_context *shake) +{ + memset (shake, 0, sizeof (keccak_context)); + shake->index_max = SHAKE256_INDEX_MAX; +} + +void +shake128_update (struct keccak_context *shake, + const unsigned char *src, unsigned int size) +{ + keccak_update (shake, src, size); +} + +void +shake256_update (struct keccak_context *shake, + const unsigned char *src, unsigned int size) +{ + keccak_update (shake, src, size); +} + +void +shake128_finish (struct keccak_context *shake, + unsigned char *dst, unsigned int size) +{ + keccak_finish (shake, dst, size, SHAKE_SUFFIX); +} + +void +shake256_finish (struct keccak_context *shake, + unsigned char *dst, unsigned int size) +{ + keccak_finish (shake, dst, size, SHAKE_SUFFIX); +} + +void +shake256v (uint8_t *out, size_t outlen, ...) +{ + struct keccak_context ctx; + va_list ap; + void *p; + size_t len; + + shake256_start (&ctx); + + va_start (ap, outlen); + while (1) + { + p = va_arg (ap, void *); + len = va_arg (ap, size_t); + if (!p) + break; + + shake256_update (&ctx, p, len); + } + va_end (ap); + + shake256_finish (&ctx, out, outlen); +} + +void +sha3_512 (uint8_t h[64], const uint8_t *in, size_t inlen) + +{ + struct keccak_context ctx; + + memset (&ctx, 0, sizeof (keccak_context)); + ctx.index_max = SHA3_512_INDEX_MAX; + + keccak_update (&ctx, in, inlen); + + keccak_finish (&ctx, h, 64, SHA3_SUFFIX); +} diff --git a/src/keccak.h b/src/keccak.h new file mode 100644 index 0000000..9f8daa6 --- /dev/null +++ b/src/keccak.h @@ -0,0 +1,24 @@ +#include + +struct keccak_context { + uint64_t state[25]; + uint32_t index : 8; + uint32_t index_max : 8; +}; +typedef struct keccak_context keccak_context; + +void shake128_start (struct keccak_context *keccak); +void shake128_update (struct keccak_context *keccak, + const unsigned char *src, unsigned int size); +void shake128_finish (struct keccak_context *keccak, + unsigned char *dst, unsigned int size); + +void shake256_start (struct keccak_context *keccak); +void shake256_update (struct keccak_context *keccak, + const unsigned char *src, unsigned int size); +void shake256_finish (struct keccak_context *keccak, + unsigned char *dst, unsigned int size); + +void shake256v (uint8_t *out, size_t outlen, ...); + +void sha3_512 (uint8_t h[64], const uint8_t *in, size_t inlen); diff --git a/src/openpgp-do.c b/src/openpgp-do.c index 500f567..2ad7853 100644 --- a/src/openpgp-do.c +++ b/src/openpgp-do.c @@ -2,7 +2,7 @@ * openpgp-do.c -- OpenPGP card Data Objects (DO) handling * * Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, - * 2020, 2021, 2022 + * 2020, 2021, 2022, 2024 * Free Software Initiative of Japan * Author: NIIBE Yutaka * @@ -34,7 +34,7 @@ #include "random.h" #include "aes.h" #include "sha512.h" -#include "shake256.h" +#include "keccak.h" /* Forward declaration */ #define CLEAN_PAGE_FULL 1 @@ -1567,7 +1567,7 @@ proc_key_import (const uint8_t *data, int len) } else if (attr == ALGO_ED448) { - shake_context ctx; + keccak_context ctx; uint8_t hash[128]; if (len - 12 != 57) @@ -2348,7 +2348,7 @@ gpg_do_keygen (uint8_t *buf) } else if (attr == ALGO_ED448) { - shake_context ctx; + keccak_context ctx; rnd = random_bytes_get (); shake256_start (&ctx); shake256_update (&ctx, rnd, 32); diff --git a/src/shake256.h b/src/shake256.h deleted file mode 100644 index 4a4a210..0000000 --- a/src/shake256.h +++ /dev/null @@ -1,13 +0,0 @@ -#include - -struct shake_context { - uint64_t state[25]; - uint32_t index; -}; -typedef struct shake_context shake_context; - -void shake256_start (struct shake_context *shake); -void shake256_update (struct shake_context *shake, - const unsigned char *src, unsigned int size); -void shake256_finish (struct shake_context *shake, - unsigned char *dst, unsigned int size);