keccak.c also provides SHA-3 and SHAKE128.

Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
This commit is contained in:
NIIBE Yutaka 2024-04-18 14:09:57 +09:00
parent 6814773294
commit 739f17781c
No known key found for this signature in database
GPG Key ID: 640114AF89DE6054
7 changed files with 161 additions and 57 deletions

View File

@ -1,3 +1,9 @@
2024-04-18 NIIBE Yutaka <gniibe@fsij.org>
* 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 <gniibe@fsij.org>
* src/modinv.c (modinv_normalize): Fix the computation.

View File

@ -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 =

View File

@ -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 <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -41,7 +41,7 @@
#include <string.h>
#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];

View File

@ -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 <gniibe@fsij.org>
*
* 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 <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@ -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 <stdint.h>
#include <string.h>
#include "shake256.h"
#include <stdarg.h>
#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);
}

24
src/keccak.h Normal file
View File

@ -0,0 +1,24 @@
#include <stdint.h>
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);

View File

@ -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 <gniibe@fsij.org>
*
@ -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);

View File

@ -1,13 +0,0 @@
#include <stdint.h>
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);