diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2015-08-10 22:09:56 +0300 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2015-08-10 22:09:56 +0300 |
commit | 434ba17d1d5ad59c70d721ad3ecb376c2403a7e5 (patch) | |
tree | 155d2fb6f8e4ab7e75e1b85a8623447439201ce8 | |
parent | 49f52c67fb42c0656c8f9af655087f444562ca82 (diff) | |
download | libgcrypt-434ba17d1d5ad59c70d721ad3ecb376c2403a7e5.tar.gz |
Add generic SHA3 implementation
* cipher/hash-common.h (MD_BLOCK_MAX_BLOCKSIZE): Increase blocksize
USE_SHA3 enabled.
* cipher/keccak.c (SHA3_DELIMITED_SUFFIX, SHAKE_DELIMITED_SUFFIX): New.
(KECCAK_STATE): Add proper state.
(KECCAK_CONTEXT): Add 'outlen'.
(rol64, keccak_f1600_state_permute, transform_blk, transform): New.
(keccak_init): Add proper initialization.
(keccak_final): Add proper finalization.
(selftests_keccak): Add selftests.
(oid_spec_sha3_224, oid_spec_sha3_256, oid_spec_sha3_384)
(oid_spec_sha3_512): Add OID.
(_gcry_digest_spec_sha3_224, _gcry_digest_spec_sha3_256)
(_gcry_digest_spec_sha3_384, _gcry_digest_spec_sha3_512): Fix output
length.
* cipher/mac-hmac.c (map_mac_algo_to_md): Fix mapping for SHA3-512.
(hmac_get_keylen): Return proper blocksizes for SHA3 algorithms.
[USE_SHA3] (_gcry_mac_type_spec_hmac_sha3_224)
(_gcry_mac_type_spec_hmac_sha3_256, _gcry_mac_type_spec_hmac_sha3_384)
(_gcry_mac_type_spec_hmac_sha3_512): New.
* cipher/mac-internal [USE_SHA3] (_gcry_mac_type_spec_hmac_sha3_224)
(_gcry_mac_type_spec_hmac_sha3_256, _gcry_mac_type_spec_hmac_sha3_384)
(_gcry_mac_type_spec_hmac_sha3_512): New.
* cipher/mac.c (mac_list) [USE_SHA3]: Add SHA3 algorithms.
* cipher/md.c (md_open): Use proper SHA-3 blocksizes for HMAC macpads.
* tests/basic.c (check_digests): Add SHA3 test vectors.
--
Patch adds generic implementation for SHA3. Currently missing with this
patch:
- HMAC SHA3 test vectors, not available from NIST (yet?)
- ASNs
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
-rw-r--r-- | cipher/hash-common.h | 12 | ||||
-rw-r--r-- | cipher/keccak.c | 429 | ||||
-rw-r--r-- | cipher/mac-hmac.c | 31 | ||||
-rw-r--r-- | cipher/mac-internal.h | 6 | ||||
-rw-r--r-- | cipher/mac.c | 6 | ||||
-rw-r--r-- | cipher/md.c | 14 | ||||
-rw-r--r-- | tests/basic.c | 83 |
7 files changed, 536 insertions, 45 deletions
diff --git a/cipher/hash-common.h b/cipher/hash-common.h index c9491913..e1ae5a24 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -33,9 +33,15 @@ typedef unsigned int (*_gcry_md_block_write_t) (void *c, const unsigned char *blks, size_t nblks); -#if defined(HAVE_U64_TYPEDEF) && (defined(USE_SHA512) || defined(USE_WHIRLPOOL)) -/* SHA-512 needs u64 and larger buffer. Whirlpool needs u64. */ -# define MD_BLOCK_MAX_BLOCKSIZE 128 +#if defined(HAVE_U64_TYPEDEF) && (defined(USE_SHA512) || defined(USE_SHA3) || \ + defined(USE_WHIRLPOOL)) +/* SHA-512, SHA-3 and Whirlpool needs u64. SHA-512 and SHA3 need larger + * buffer. */ +# ifdef USE_SHA3 +# define MD_BLOCK_MAX_BLOCKSIZE (1152 / 8) +# else +# define MD_BLOCK_MAX_BLOCKSIZE 128 +# endif # define MD_NBLOCKS_TYPE u64 #else # define MD_BLOCK_MAX_BLOCKSIZE 64 diff --git a/cipher/keccak.c b/cipher/keccak.c index 625c5c72..4ca8dbde 100644 --- a/cipher/keccak.c +++ b/cipher/keccak.c @@ -27,10 +27,20 @@ #include "hash-common.h" +/* The code is based on public-domain/CC0 "Keccak-readable-and-compact.c" + * implementation by the Keccak, Keyak and Ketje Teams, namely, Guido Bertoni, + * Joan Daemen, Michaël Peeters, Gilles Van Assche and Ronny Van Keer. From: + * https://github.com/gvanas/KeccakCodePackage + */ + + +#define SHA3_DELIMITED_SUFFIX 0x06 +#define SHAKE_DELIMITED_SUFFIX 0x1F + typedef struct { - u64 h0; + u64 state[5][5]; } KECCAK_STATE; @@ -38,9 +48,212 @@ typedef struct { gcry_md_block_ctx_t bctx; KECCAK_STATE state; + unsigned int outlen; } KECCAK_CONTEXT; +static inline u64 +rol64 (u64 x, unsigned int n) +{ + return ((x << n) | (x >> (64 - n))); +} + +/* Function that computes the Keccak-f[1600] permutation on the given state. */ +static unsigned int keccak_f1600_state_permute(KECCAK_STATE *hd) +{ + static const u64 round_consts[24] = + { + U64_C(0x0000000000000001), U64_C(0x0000000000008082), + U64_C(0x800000000000808A), U64_C(0x8000000080008000), + U64_C(0x000000000000808B), U64_C(0x0000000080000001), + U64_C(0x8000000080008081), U64_C(0x8000000000008009), + U64_C(0x000000000000008A), U64_C(0x0000000000000088), + U64_C(0x0000000080008009), U64_C(0x000000008000000A), + U64_C(0x000000008000808B), U64_C(0x800000000000008B), + U64_C(0x8000000000008089), U64_C(0x8000000000008003), + U64_C(0x8000000000008002), U64_C(0x8000000000000080), + U64_C(0x000000000000800A), U64_C(0x800000008000000A), + U64_C(0x8000000080008081), U64_C(0x8000000000008080), + U64_C(0x0000000080000001), U64_C(0x8000000080008008) + }; + unsigned int round; + + for (round = 0; round < 24; round++) + { + { + /* θ step (see [Keccak Reference, Section 2.3.2]) === */ + u64 C[5], D[5]; + + /* Compute the parity of the columns */ + C[0] = hd->state[0][0] ^ hd->state[1][0] ^ hd->state[2][0] + ^ hd->state[3][0] ^ hd->state[4][0]; + C[1] = hd->state[0][1] ^ hd->state[1][1] ^ hd->state[2][1] + ^ hd->state[3][1] ^ hd->state[4][1]; + C[2] = hd->state[0][2] ^ hd->state[1][2] ^ hd->state[2][2] + ^ hd->state[3][2] ^ hd->state[4][2]; + C[3] = hd->state[0][3] ^ hd->state[1][3] ^ hd->state[2][3] + ^ hd->state[3][3] ^ hd->state[4][3]; + C[4] = hd->state[0][4] ^ hd->state[1][4] ^ hd->state[2][4] + ^ hd->state[3][4] ^ hd->state[4][4]; + + /* Compute the θ effect for a given column */ + D[0] = C[4] ^ rol64(C[1], 1); + D[1] = C[0] ^ rol64(C[2], 1); + D[2] = C[1] ^ rol64(C[3], 1); + D[4] = C[2] ^ rol64(C[4], 1); + D[5] = C[3] ^ rol64(C[0], 1); + + /* Add the θ effect to the whole column */ + hd->state[0][0] ^= D[0]; + hd->state[1][0] ^= D[0]; + hd->state[2][0] ^= D[0]; + hd->state[3][0] ^= D[0]; + hd->state[4][0] ^= D[0]; + + /* Add the θ effect to the whole column */ + hd->state[0][1] ^= D[1]; + hd->state[1][1] ^= D[1]; + hd->state[2][1] ^= D[1]; + hd->state[3][1] ^= D[1]; + hd->state[4][1] ^= D[1]; + + /* Add the θ effect to the whole column */ + hd->state[0][2] ^= D[2]; + hd->state[1][2] ^= D[2]; + hd->state[2][2] ^= D[2]; + hd->state[3][2] ^= D[2]; + hd->state[4][2] ^= D[2]; + + /* Add the θ effect to the whole column */ + hd->state[0][3] ^= D[4]; + hd->state[1][3] ^= D[4]; + hd->state[2][3] ^= D[4]; + hd->state[3][3] ^= D[4]; + hd->state[4][3] ^= D[4]; + + /* Add the θ effect to the whole column */ + hd->state[0][4] ^= D[5]; + hd->state[1][4] ^= D[5]; + hd->state[2][4] ^= D[5]; + hd->state[3][4] ^= D[5]; + hd->state[4][4] ^= D[5]; + } + + { + /* ρ and π steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) */ + u64 current, temp; + +#define do_swap_n_rol(x, y, r) \ + temp = hd->state[y][x]; \ + hd->state[y][x] = rol64(current, r); \ + current = temp; + + /* Start at coordinates (1 0) */ + current = hd->state[0][1]; + + /* Iterate over ((0 1)(2 3))^t * (1 0) for 0 ≤ t ≤ 23 */ + do_swap_n_rol(0, 2, 1); + do_swap_n_rol(2, 1, 3); + do_swap_n_rol(1, 2, 6); + do_swap_n_rol(2, 3, 10); + do_swap_n_rol(3, 3, 15); + do_swap_n_rol(3, 0, 21); + do_swap_n_rol(0, 1, 28); + do_swap_n_rol(1, 3, 36); + do_swap_n_rol(3, 1, 45); + do_swap_n_rol(1, 4, 55); + do_swap_n_rol(4, 4, 2); + do_swap_n_rol(4, 0, 14); + do_swap_n_rol(0, 3, 27); + do_swap_n_rol(3, 4, 41); + do_swap_n_rol(4, 3, 56); + do_swap_n_rol(3, 2, 8); + do_swap_n_rol(2, 2, 25); + do_swap_n_rol(2, 0, 43); + do_swap_n_rol(0, 4, 62); + do_swap_n_rol(4, 2, 18); + do_swap_n_rol(2, 4, 39); + do_swap_n_rol(4, 1, 61); + do_swap_n_rol(1, 1, 20); + do_swap_n_rol(1, 0, 44); + +#undef do_swap_n_rol + } + + { + /* χ step (see [Keccak Reference, Section 2.3.1]) */ + u64 temp[5]; + +#define do_x_step_for_plane(y) \ + /* Take a copy of the plane */ \ + temp[0] = hd->state[y][0]; \ + temp[1] = hd->state[y][1]; \ + temp[2] = hd->state[y][2]; \ + temp[3] = hd->state[y][3]; \ + temp[4] = hd->state[y][4]; \ + \ + /* Compute χ on the plane */ \ + hd->state[y][0] = temp[0] ^ ((~temp[1]) & temp[2]); \ + hd->state[y][1] = temp[1] ^ ((~temp[2]) & temp[3]); \ + hd->state[y][2] = temp[2] ^ ((~temp[3]) & temp[4]); \ + hd->state[y][3] = temp[3] ^ ((~temp[4]) & temp[0]); \ + hd->state[y][4] = temp[4] ^ ((~temp[0]) & temp[1]); + + do_x_step_for_plane(0); + do_x_step_for_plane(1); + do_x_step_for_plane(2); + do_x_step_for_plane(3); + do_x_step_for_plane(4); + +#undef do_x_step_for_plane + } + + { + /* ι step (see [Keccak Reference, Section 2.3.5]) */ + + hd->state[0][0] ^= round_consts[round]; + } + } + + return sizeof(void *) * 4 + sizeof(u64) * 10; +} + + +static unsigned int +transform_blk (void *context, const unsigned char *data) +{ + KECCAK_CONTEXT *ctx = context; + KECCAK_STATE *hd = &ctx->state; + u64 *state = (u64 *)hd->state; + const size_t bsize = ctx->bctx.blocksize; + unsigned int i; + + /* Absorb input block. */ + for (i = 0; i < bsize / 8; i++) + state[i] ^= buf_get_le64(data + i * 8); + + return keccak_f1600_state_permute(hd) + 4 * sizeof(void *); +} + + +static unsigned int +transform (void *context, const unsigned char *data, size_t nblks) +{ + KECCAK_CONTEXT *ctx = context; + const size_t bsize = ctx->bctx.blocksize; + unsigned int burn; + + /* Absorb full blocks. */ + do + { + burn = transform_blk (context, data); + data += bsize; + } + while (--nblks); + + return burn; +} + static void keccak_init (int algo, void *context, unsigned int flags) @@ -50,16 +263,38 @@ keccak_init (int algo, void *context, unsigned int flags) unsigned int features = _gcry_get_hw_features (); (void)flags; + (void)features; memset (hd, 0, sizeof *hd); ctx->bctx.nblocks = 0; ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; - ctx->bctx.blocksize = 128; - ctx->bctx.bwrite = NULL; + ctx->bctx.bwrite = transform; - (void)features; + /* Set input block size, in Keccak terms this is called 'rate'. */ + + switch (algo) + { + case GCRY_MD_SHA3_224: + ctx->bctx.blocksize = 1152 / 8; + ctx->outlen = 224 / 8; + break; + case GCRY_MD_SHA3_256: + ctx->bctx.blocksize = 1088 / 8; + ctx->outlen = 256 / 8; + break; + case GCRY_MD_SHA3_384: + ctx->bctx.blocksize = 832 / 8; + ctx->outlen = 384 / 8; + break; + case GCRY_MD_SHA3_512: + ctx->bctx.blocksize = 576 / 8; + ctx->outlen = 512 / 8; + break; + default: + BUG(); + } } static void @@ -97,10 +332,69 @@ sha3_512_init (void *context, unsigned int flags) static void keccak_final (void *context) { - KECCAK_CONTEXT *hd = context; + KECCAK_CONTEXT *ctx = context; + KECCAK_STATE *hd = &ctx->state; + const size_t bsize = ctx->bctx.blocksize; + const byte suffix = SHA3_DELIMITED_SUFFIX; + u64 *state = (u64 *)hd->state; unsigned int stack_burn_depth; + unsigned int lastbytes; + unsigned int i; + byte *buf; + + _gcry_md_block_write (context, NULL, 0); /* flush */ - _gcry_md_block_write (context, NULL, 0); /* flush */ ; + buf = ctx->bctx.buf; + lastbytes = ctx->bctx.count; + + /* Absorb remaining bytes. */ + for (i = 0; i < lastbytes / 8; i++) + { + state[i] ^= buf_get_le64(buf); + buf += 8; + } + + for (i = 0; i < lastbytes % 8; i++) + { + state[lastbytes / 8] ^= (u64)*buf << (i * 8); + buf++; + } + + /* Do the padding and switch to the squeezing phase */ + + /* Absorb the last few bits and add the first bit of padding (which + coincides with the delimiter in delimited suffix) */ + state[lastbytes / 8] ^= (u64)suffix << ((lastbytes % 8) * 8); + + /* Add the second bit of padding. */ + state[(bsize - 1) / 8] ^= (u64)0x80 << (((bsize - 1) % 8) * 8); + + /* Switch to the squeezing phase. */ + stack_burn_depth = keccak_f1600_state_permute(hd); + + /* Squeeze out all the output blocks */ + if (ctx->outlen < bsize) + { + /* Output SHA3 digest. */ + buf = ctx->bctx.buf; + for (i = 0; i < ctx->outlen / 8; i++) + { + buf_put_le64(buf, state[i]); + buf += 8; + } + for (i = 0; i < ctx->outlen % 8; i++) + { + *buf = state[ctx->outlen / 8] >> (i * 8); + buf++; + } + } + else + { + /* Output SHAKE digest. */ + BUG(); + } + + _gcry_burn_stack (stack_burn_depth); } @@ -121,19 +415,83 @@ keccak_read (void *context) static gpg_err_code_t selftests_keccak (int algo, int extended, selftest_report_func_t report) { - return 0; -#if 0 const char *what; const char *errtxt; + const char *short_hash; + const char *long_hash; + const char *one_million_a_hash; + int hash_len; + + switch (algo) + { + default: + BUG(); + + case GCRY_MD_SHA3_224: + short_hash = + "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" + "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf"; + long_hash = + "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5" + "\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc"; + one_million_a_hash = + "\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c" + "\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c"; + hash_len = 28; + break; + + case GCRY_MD_SHA3_256: + short_hash = + "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd" + "\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32"; + long_hash = + "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb" + "\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18"; + one_million_a_hash = + "\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6" + "\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1"; + hash_len = 32; + break; + + case GCRY_MD_SHA3_384: + short_hash = + "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d" + "\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2" + "\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25"; + long_hash = + "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91" + "\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc" + "\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7"; + one_million_a_hash = + "\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad" + "\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84" + "\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40"; + hash_len = 48; + break; + + case GCRY_MD_SHA3_512: + short_hash = + "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e" + "\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e" + "\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40" + "\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0"; + long_hash = + "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9" + "\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa" + "\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89" + "\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85"; + one_million_a_hash = + "\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e" + "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" + "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" + "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87"; + hash_len = 64; + break; + } - /* FIXME: Add a switch(algo) or use several functions. */ what = "short string"; - errtxt = _gcry_hash_selftest_check_one - (GCRY_MD_SHA3_384, 0, - "abc", 3, - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 48); + errtxt = _gcry_hash_selftest_check_one (algo, 0, "abc", 3, short_hash, + hash_len); if (errtxt) goto failed; @@ -141,33 +499,26 @@ selftests_keccak (int algo, int extended, selftest_report_func_t report) { what = "long string"; errtxt = _gcry_hash_selftest_check_one - (GCRY_MD_SHA3_384, 0, - "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" - "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",48); + (algo, 0, + "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", 112, + long_hash, hash_len); if (errtxt) - goto failed; + goto failed; what = "one million \"a\""; - errtxt = _gcry_hash_selftest_check_one - (GCRY_MD_SHA3_384, 1, - NULL, 0, - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00" - "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00",48); + errtxt = _gcry_hash_selftest_check_one (algo, 1, NULL, 0, + one_million_a_hash, hash_len); if (errtxt) - goto failed; + goto failed; } return 0; /* Succeeded. */ - failed: +failed: if (report) report ("digest", algo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; -#endif } @@ -188,8 +539,8 @@ run_selftests (int algo, int extended, selftest_report_func_t report) default: ec = GPG_ERR_DIGEST_ALGO; break; - } + return ec; } @@ -199,7 +550,7 @@ run_selftests (int algo, int extended, selftest_report_func_t report) static byte sha3_224_asn[] = { 0x30 }; static gcry_md_oid_spec_t oid_spec_sha3_224[] = { - { "?" }, + { "2.16.840.1.101.3.4.2.7" }, /* PKCS#1 sha3_224WithRSAEncryption */ { "?" }, { NULL } @@ -207,7 +558,7 @@ static gcry_md_oid_spec_t oid_spec_sha3_224[] = static byte sha3_256_asn[] = { 0x30 }; static gcry_md_oid_spec_t oid_spec_sha3_256[] = { - { "?" }, + { "2.16.840.1.101.3.4.2.8" }, /* PKCS#1 sha3_256WithRSAEncryption */ { "?" }, { NULL } @@ -215,7 +566,7 @@ static gcry_md_oid_spec_t oid_spec_sha3_256[] = static byte sha3_384_asn[] = { 0x30 }; static gcry_md_oid_spec_t oid_spec_sha3_384[] = { - { "?" }, + { "2.16.840.1.101.3.4.2.9" }, /* PKCS#1 sha3_384WithRSAEncryption */ { "?" }, { NULL } @@ -223,7 +574,7 @@ static gcry_md_oid_spec_t oid_spec_sha3_384[] = static byte sha3_512_asn[] = { 0x30 }; static gcry_md_oid_spec_t oid_spec_sha3_512[] = { - { "?" }, + { "2.16.840.1.101.3.4.2.10" }, /* PKCS#1 sha3_512WithRSAEncryption */ { "?" }, { NULL } @@ -233,7 +584,7 @@ static gcry_md_oid_spec_t oid_spec_sha3_512[] = gcry_md_spec_t _gcry_digest_spec_sha3_224 = { GCRY_MD_SHA3_224, {0, 1}, - "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 64, + "SHA3-224", sha3_224_asn, DIM (sha3_224_asn), oid_spec_sha3_224, 28, sha3_224_init, _gcry_md_block_write, keccak_final, keccak_read, sizeof (KECCAK_CONTEXT), run_selftests @@ -241,7 +592,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_224 = gcry_md_spec_t _gcry_digest_spec_sha3_256 = { GCRY_MD_SHA3_256, {0, 1}, - "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 64, + "SHA3-256", sha3_256_asn, DIM (sha3_256_asn), oid_spec_sha3_256, 32, sha3_256_init, _gcry_md_block_write, keccak_final, keccak_read, sizeof (KECCAK_CONTEXT), run_selftests @@ -249,7 +600,7 @@ gcry_md_spec_t _gcry_digest_spec_sha3_256 = gcry_md_spec_t _gcry_digest_spec_sha3_384 = { GCRY_MD_SHA3_384, {0, 1}, - "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 64, + "SHA3-384", sha3_384_asn, DIM (sha3_384_asn), oid_spec_sha3_384, 48, sha3_384_init, _gcry_md_block_write, keccak_final, keccak_read, sizeof (KECCAK_CONTEXT), run_selftests diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c index eeab1307..9379f4b6 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -58,7 +58,7 @@ map_mac_algo_to_md (int mac_algo) case GCRY_MAC_HMAC_SHA3_384: return GCRY_MD_SHA3_384; case GCRY_MAC_HMAC_SHA3_512: - return GCRY_MD_SHA512; + return GCRY_MD_SHA3_512; case GCRY_MAC_HMAC_RMD160: return GCRY_MD_RMD160; case GCRY_MAC_HMAC_TIGER1: @@ -180,6 +180,14 @@ hmac_get_keylen (int algo) /* Return blocksize for default key length. */ switch (algo) { + case GCRY_MD_SHA3_224: + return 1152 / 8; + case GCRY_MD_SHA3_256: + return 1088 / 8; + case GCRY_MD_SHA3_384: + return 832 / 8; + case GCRY_MD_SHA3_512: + return 576 / 8; case GCRY_MAC_HMAC_SHA384: case GCRY_MAC_HMAC_SHA512: return 128; @@ -233,6 +241,27 @@ gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = { &hmac_ops }; #endif +#if USE_SHA3 +gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = { + GCRY_MAC_HMAC_SHA3_224, {0, 1}, "HMAC_SHA3_224", + &hmac_ops +}; + +gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = { + GCRY_MAC_HMAC_SHA3_256, {0, 1}, "HMAC_SHA3_256", + &hmac_ops +}; + +gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = { + GCRY_MAC_HMAC_SHA3_384, {0, 1}, "HMAC_SHA3_384", + &hmac_ops +}; + +gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = { + GCRY_MAC_HMAC_SHA3_512, {0, 1}, "HMAC_SHA3_512", + &hmac_ops +}; +#endif #ifdef USE_GOST_R_3411_94 gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = { GCRY_MAC_HMAC_GOSTR3411_94, {0, 0}, "HMAC_GOSTR3411_94", diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index f65a8ae5..2beb2843 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -134,6 +134,12 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384; #endif +#if USE_SHA3 +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224; +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256; +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384; +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512; +#endif #ifdef USE_GOST_R_3411_94 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; #endif diff --git a/cipher/mac.c b/cipher/mac.c index e5131ed8..9bb360c6 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -41,6 +41,12 @@ static gcry_mac_spec_t *mac_list[] = { &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, #endif +#if USE_SHA3 + &_gcry_mac_type_spec_hmac_sha3_224, + &_gcry_mac_type_spec_hmac_sha3_256, + &_gcry_mac_type_spec_hmac_sha3_384, + &_gcry_mac_type_spec_hmac_sha3_512, +#endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, #endif diff --git a/cipher/md.c b/cipher/md.c index 0c669caa..19b2c9bc 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -337,10 +337,20 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags) { switch (algo) { - case GCRY_MD_SHA384: - case GCRY_MD_SHA512: + case GCRY_MD_SHA3_224: + ctx->macpads_Bsize = 1152 / 8; + break; + case GCRY_MD_SHA3_256: + ctx->macpads_Bsize = 1088 / 8; + break; case GCRY_MD_SHA3_384: + ctx->macpads_Bsize = 832 / 8; + break; case GCRY_MD_SHA3_512: + ctx->macpads_Bsize = 576 / 8; + break; + case GCRY_MD_SHA384: + case GCRY_MD_SHA512: ctx->macpads_Bsize = 128; break; case GCRY_MD_GOSTR3411_94: diff --git a/tests/basic.c b/tests/basic.c index 3ad05a45..fd32f168 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -5524,6 +5524,89 @@ check_digests (void) "\x8e\x1f\x98\xb1\x3b\x20\x44\x28\x56\x32\xa8\x03\xaf\xa9\x73\xeb" "\xde\x0f\xf2\x44\x87\x7e\xa6\x0a\x4c\xb0\x43\x2c\xe5\x77\xc3\x1b" "\xeb\x00\x9c\x5c\x2c\x49\xaa\x2e\x4e\xad\xb2\x17\xad\x8c\xc0\x9b" }, + { GCRY_MD_SHA3_224, "abc", + "\xe6\x42\x82\x4c\x3f\x8c\xf2\x4a\xd0\x92\x34\xee\x7d\x3c\x76\x6f" + "\xc9\xa3\xa5\x16\x8d\x0c\x94\xad\x73\xb4\x6f\xdf" }, + { GCRY_MD_SHA3_256, "abc", + "\x3a\x98\x5d\xa7\x4f\xe2\x25\xb2\x04\x5c\x17\x2d\x6b\xd3\x90\xbd" + "\x85\x5f\x08\x6e\x3e\x9d\x52\x5b\x46\xbf\xe2\x45\x11\x43\x15\x32" }, + { GCRY_MD_SHA3_384, "abc", + "\xec\x01\x49\x82\x88\x51\x6f\xc9\x26\x45\x9f\x58\xe2\xc6\xad\x8d" + "\xf9\xb4\x73\xcb\x0f\xc0\x8c\x25\x96\xda\x7c\xf0\xe4\x9b\xe4\xb2" + "\x98\xd8\x8c\xea\x92\x7a\xc7\xf5\x39\xf1\xed\xf2\x28\x37\x6d\x25" }, + { GCRY_MD_SHA3_512, "abc", + "\xb7\x51\x85\x0b\x1a\x57\x16\x8a\x56\x93\xcd\x92\x4b\x6b\x09\x6e" + "\x08\xf6\x21\x82\x74\x44\xf7\x0d\x88\x4f\x5d\x02\x40\xd2\x71\x2e" + "\x10\xe1\x16\xe9\x19\x2a\xf3\xc9\x1a\x7e\xc5\x76\x47\xe3\x93\x40" + "\x57\x34\x0b\x4c\xf4\x08\xd5\xa5\x65\x92\xf8\x27\x4e\xec\x53\xf0" }, + { GCRY_MD_SHA3_224, "", + "\x6b\x4e\x03\x42\x36\x67\xdb\xb7\x3b\x6e\x15\x45\x4f\x0e\xb1\xab" + "\xd4\x59\x7f\x9a\x1b\x07\x8e\x3f\x5b\x5a\x6b\xc7" }, + { GCRY_MD_SHA3_256, "", + "\xa7\xff\xc6\xf8\xbf\x1e\xd7\x66\x51\xc1\x47\x56\xa0\x61\xd6\x62" + "\xf5\x80\xff\x4d\xe4\x3b\x49\xfa\x82\xd8\x0a\x4b\x80\xf8\x43\x4a" }, + { GCRY_MD_SHA3_384, "", + "\x0c\x63\xa7\x5b\x84\x5e\x4f\x7d\x01\x10\x7d\x85\x2e\x4c\x24\x85" + "\xc5\x1a\x50\xaa\xaa\x94\xfc\x61\x99\x5e\x71\xbb\xee\x98\x3a\x2a" + "\xc3\x71\x38\x31\x26\x4a\xdb\x47\xfb\x6b\xd1\xe0\x58\xd5\xf0\x04" }, + { GCRY_MD_SHA3_512, "", + "\xa6\x9f\x73\xcc\xa2\x3a\x9a\xc5\xc8\xb5\x67\xdc\x18\x5a\x75\x6e" + "\x97\xc9\x82\x16\x4f\xe2\x58\x59\xe0\xd1\xdc\xc1\x47\x5c\x80\xa6" + "\x15\xb2\x12\x3a\xf1\xf5\xf9\x4c\x11\xe3\xe9\x40\x2c\x3a\xc5\x58" + "\xf5\x00\x19\x9d\x95\xb6\xd3\xe3\x01\x75\x85\x86\x28\x1d\xcd\x26" }, + { GCRY_MD_SHA3_224, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm" + "nomnopnopq", + "\x8a\x24\x10\x8b\x15\x4a\xda\x21\xc9\xfd\x55\x74\x49\x44\x79\xba" + "\x5c\x7e\x7a\xb7\x6e\xf2\x64\xea\xd0\xfc\xce\x33" }, + { GCRY_MD_SHA3_256, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm" + "nomnopnopq", + "\x41\xc0\xdb\xa2\xa9\xd6\x24\x08\x49\x10\x03\x76\xa8\x23\x5e\x2c" + "\x82\xe1\xb9\x99\x8a\x99\x9e\x21\xdb\x32\xdd\x97\x49\x6d\x33\x76" }, + { GCRY_MD_SHA3_384, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm" + "nomnopnopq", + "\x99\x1c\x66\x57\x55\xeb\x3a\x4b\x6b\xbd\xfb\x75\xc7\x8a\x49\x2e" + "\x8c\x56\xa2\x2c\x5c\x4d\x7e\x42\x9b\xfd\xbc\x32\xb9\xd4\xad\x5a" + "\xa0\x4a\x1f\x07\x6e\x62\xfe\xa1\x9e\xef\x51\xac\xd0\x65\x7c\x22" }, + { GCRY_MD_SHA3_512, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlm" + "nomnopnopq", + "\x04\xa3\x71\xe8\x4e\xcf\xb5\xb8\xb7\x7c\xb4\x86\x10\xfc\xa8\x18" + "\x2d\xd4\x57\xce\x6f\x32\x6a\x0f\xd3\xd7\xec\x2f\x1e\x91\x63\x6d" + "\xee\x69\x1f\xbe\x0c\x98\x53\x02\xba\x1b\x0d\x8d\xc7\x8c\x08\x63" + "\x46\xb5\x33\xb4\x9c\x03\x0d\x99\xa2\x7d\xaf\x11\x39\xd6\xe7\x5e" }, + { GCRY_MD_SHA3_224, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk" + "lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x54\x3e\x68\x68\xe1\x66\x6c\x1a\x64\x36\x30\xdf\x77\x36\x7a\xe5" + "\xa6\x2a\x85\x07\x0a\x51\xc1\x4c\xbf\x66\x5c\xbc" }, + { GCRY_MD_SHA3_256, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk" + "lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x91\x6f\x60\x61\xfe\x87\x97\x41\xca\x64\x69\xb4\x39\x71\xdf\xdb" + "\x28\xb1\xa3\x2d\xc3\x6c\xb3\x25\x4e\x81\x2b\xe2\x7a\xad\x1d\x18" }, + { GCRY_MD_SHA3_384, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk" + "lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\x79\x40\x7d\x3b\x59\x16\xb5\x9c\x3e\x30\xb0\x98\x22\x97\x47\x91" + "\xc3\x13\xfb\x9e\xcc\x84\x9e\x40\x6f\x23\x59\x2d\x04\xf6\x25\xdc" + "\x8c\x70\x9b\x98\xb4\x3b\x38\x52\xb3\x37\x21\x61\x79\xaa\x7f\xc7" }, + { GCRY_MD_SHA3_512, "abcdefghbcdefghicdefghijdefghijkefghijklfghijk" + "lmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu", + "\xaf\xeb\xb2\xef\x54\x2e\x65\x79\xc5\x0c\xad\x06\xd2\xe5\x78\xf9" + "\xf8\xdd\x68\x81\xd7\xdc\x82\x4d\x26\x36\x0f\xee\xbf\x18\xa4\xfa" + "\x73\xe3\x26\x11\x22\x94\x8e\xfc\xfd\x49\x2e\x74\xe8\x2e\x21\x89" + "\xed\x0f\xb4\x40\xd1\x87\xf3\x82\x27\x0c\xb4\x55\xf2\x1d\xd1\x85" }, + { GCRY_MD_SHA3_224, "!", + "\xd6\x93\x35\xb9\x33\x25\x19\x2e\x51\x6a\x91\x2e\x6d\x19\xa1\x5c" + "\xb5\x1c\x6e\xd5\xc1\x52\x43\xe7\xa7\xfd\x65\x3c" }, + { GCRY_MD_SHA3_256, "!", + "\x5c\x88\x75\xae\x47\x4a\x36\x34\xba\x4f\xd5\x5e\xc8\x5b\xff\xd6" + "\x61\xf3\x2a\xca\x75\xc6\xd6\x99\xd0\xcd\xcb\x6c\x11\x58\x91\xc1" }, + { GCRY_MD_SHA3_384, "!", + "\xee\xe9\xe2\x4d\x78\xc1\x85\x53\x37\x98\x34\x51\xdf\x97\xc8\xad" + "\x9e\xed\xf2\x56\xc6\x33\x4f\x8e\x94\x8d\x25\x2d\x5e\x0e\x76\x84" + "\x7a\xa0\x77\x4d\xdb\x90\xa8\x42\x19\x0d\x2c\x55\x8b\x4b\x83\x40" }, + { GCRY_MD_SHA3_512, "!", + "\x3c\x3a\x87\x6d\xa1\x40\x34\xab\x60\x62\x7c\x07\x7b\xb9\x8f\x7e" + "\x12\x0a\x2a\x53\x70\x21\x2d\xff\xb3\x38\x5a\x18\xd4\xf3\x88\x59" + "\xed\x31\x1d\x0a\x9d\x51\x41\xce\x9c\xc5\xc6\x6e\xe6\x89\xb2\x66" + "\xa8\xaa\x18\xac\xe8\x28\x2a\x0e\x0d\xb5\x96\xc9\x0b\x0a\x7b\x87" }, { GCRY_MD_RMD160, "", "\x9c\x11\x85\xa5\xc5\xe9\xfc\x54\x61\x28" "\x08\x97\x7e\xe8\xf5\x48\xb2\x25\x8d\x31" }, |