diff options
author | Werner Koch <wk@gnupg.org> | 2015-08-08 10:47:55 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2015-08-08 10:47:55 +0200 |
commit | 0e17f7a05bba309a87811992aa47a77af9935b99 (patch) | |
tree | 5d1c8cc673a6cd4cfb16d2cf154f2f9987d64d05 | |
parent | 10789e3cdda7b944acb4b59624c34a2ccfaea6e5 (diff) | |
download | libgcrypt-0e17f7a05bba309a87811992aa47a77af9935b99.tar.gz |
Add framework to eventually support SHA3.
* src/gcrypt.h.in (GCRY_MD_SHA3_224, GCRY_MD_SHA3_256)
(GCRY_MD_SHA3_384, GCRY_MD_SHA3_512): New.
(GCRY_MAC_HMAC_SHA3_224, GCRY_MAC_HMAC_SHA3_256)
(GCRY_MAC_HMAC_SHA3_384, GCRY_MAC_HMAC_SHA3_512): New.
* cipher/keccak.c: New with stub functions.
* cipher/Makefile.am (EXTRA_libcipher_la_SOURCES): Add keccak.c.
* configure.ac (available_digests): Add sha3.
(USE_SHA3): New.
* src/fips.c (run_hmac_selftests): Add SHA3 to the required selftests.
* cipher/md.c (digest_list) [USE_SHA3]: Add standard SHA3 algos.
(md_open): Ditto for hmac processing.
* cipher/mac-hmac.c (map_mac_algo_to_md): Add mapping.
* cipher/hmac-tests.c (run_selftests): Prepare for tests.
* cipher/pubkey-util.c (get_hash_algo): Add "sha3-xxx".
--
Note that the algo GCRY_MD_SHA3_xxx are prelimanry. We should try to
sync them with OpenPGP.
Signed-off-by: Werner Koch <wk@gnupg.org>
-rw-r--r-- | cipher/Makefile.am | 1 | ||||
-rw-r--r-- | cipher/hmac-tests.c | 11 | ||||
-rw-r--r-- | cipher/keccak.c | 264 | ||||
-rw-r--r-- | cipher/mac-hmac.c | 8 | ||||
-rw-r--r-- | cipher/md.c | 8 | ||||
-rw-r--r-- | cipher/pubkey-util.c | 4 | ||||
-rw-r--r-- | configure.ac | 20 | ||||
-rw-r--r-- | src/cipher.h | 6 | ||||
-rw-r--r-- | src/fips.c | 4 | ||||
-rw-r--r-- | src/gcrypt.h.in | 11 |
10 files changed, 334 insertions, 3 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 33a68ffb..b08c9a97 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -90,6 +90,7 @@ sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \ sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S sha256-avx2-bmi2-amd64.S \ sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S sha512-avx2-bmi2-amd64.S \ sha512-armv7-neon.S \ +keccak.c \ stribog.c \ tiger.c \ whirlpool.c whirlpool-sse2-amd64.S \ diff --git a/cipher/hmac-tests.c b/cipher/hmac-tests.c index 7c27342c..46e1b22e 100644 --- a/cipher/hmac-tests.c +++ b/cipher/hmac-tests.c @@ -701,6 +701,17 @@ run_selftests (int algo, int extended, selftest_report_func_t report) case GCRY_MD_SHA512: ec = selftests_sha512 (extended, report); break; + + case GCRY_MD_SHA3_224: + case GCRY_MD_SHA3_256: + case GCRY_MD_SHA3_384: + case GCRY_MD_SHA3_512: + ec = 0; /* FIXME: Add selftests. */ +#ifdef __GNUC__ +# warning Please add the self text functions +#endif + break; + default: ec = GPG_ERR_DIGEST_ALGO; break; diff --git a/cipher/keccak.c b/cipher/keccak.c new file mode 100644 index 00000000..625c5c72 --- /dev/null +++ b/cipher/keccak.c @@ -0,0 +1,264 @@ +/* keccak.c - SHA3 hash functions + * Copyright (C) 2015 g10 Code GmbH + * + * 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 <string.h> +#include "g10lib.h" +#include "bithelp.h" +#include "bufhelp.h" +#include "cipher.h" +#include "hash-common.h" + + + +typedef struct +{ + u64 h0; +} KECCAK_STATE; + + +typedef struct +{ + gcry_md_block_ctx_t bctx; + KECCAK_STATE state; +} KECCAK_CONTEXT; + + + +static void +keccak_init (int algo, void *context, unsigned int flags) +{ + KECCAK_CONTEXT *ctx = context; + KECCAK_STATE *hd = &ctx->state; + unsigned int features = _gcry_get_hw_features (); + + (void)flags; + + 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; + + (void)features; +} + +static void +sha3_224_init (void *context, unsigned int flags) +{ + keccak_init (GCRY_MD_SHA3_224, context, flags); +} + +static void +sha3_256_init (void *context, unsigned int flags) +{ + keccak_init (GCRY_MD_SHA3_256, context, flags); +} + +static void +sha3_384_init (void *context, unsigned int flags) +{ + keccak_init (GCRY_MD_SHA3_384, context, flags); +} + +static void +sha3_512_init (void *context, unsigned int flags) +{ + keccak_init (GCRY_MD_SHA3_512, 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 + * handle will the destroy the returned buffer. + * Returns: 64 bytes representing the digest. When used for sha384, + * we take the leftmost 48 of those bytes. + */ +static void +keccak_final (void *context) +{ + KECCAK_CONTEXT *hd = context; + unsigned int stack_burn_depth; + + _gcry_md_block_write (context, NULL, 0); /* flush */ ; +} + + +static byte * +keccak_read (void *context) +{ + KECCAK_CONTEXT *hd = (KECCAK_CONTEXT *) context; + return hd->bctx.buf; +} + + + +/* + Self-test section. + */ + + +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; + + /* 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); + if (errtxt) + goto failed; + + if (extended) + { + 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); + if (errtxt) + 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); + if (errtxt) + goto failed; + } + + return 0; /* Succeeded. */ + + failed: + if (report) + report ("digest", algo, what, errtxt); + return GPG_ERR_SELFTEST_FAILED; +#endif +} + + +/* Run a full self-test for ALGO and return 0 on success. */ +static gpg_err_code_t +run_selftests (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MD_SHA3_224: + case GCRY_MD_SHA3_256: + case GCRY_MD_SHA3_384: + case GCRY_MD_SHA3_512: + ec = selftests_keccak (algo, extended, report); + break; + default: + ec = GPG_ERR_DIGEST_ALGO; + break; + + } + return ec; +} + + + + +static byte sha3_224_asn[] = { 0x30 }; +static gcry_md_oid_spec_t oid_spec_sha3_224[] = + { + { "?" }, + /* PKCS#1 sha3_224WithRSAEncryption */ + { "?" }, + { NULL } + }; +static byte sha3_256_asn[] = { 0x30 }; +static gcry_md_oid_spec_t oid_spec_sha3_256[] = + { + { "?" }, + /* PKCS#1 sha3_256WithRSAEncryption */ + { "?" }, + { NULL } + }; +static byte sha3_384_asn[] = { 0x30 }; +static gcry_md_oid_spec_t oid_spec_sha3_384[] = + { + { "?" }, + /* PKCS#1 sha3_384WithRSAEncryption */ + { "?" }, + { NULL } + }; +static byte sha3_512_asn[] = { 0x30 }; +static gcry_md_oid_spec_t oid_spec_sha3_512[] = + { + { "?" }, + /* PKCS#1 sha3_512WithRSAEncryption */ + { "?" }, + { NULL } + }; + + +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_init, _gcry_md_block_write, keccak_final, keccak_read, + sizeof (KECCAK_CONTEXT), + run_selftests + }; +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_init, _gcry_md_block_write, keccak_final, keccak_read, + sizeof (KECCAK_CONTEXT), + run_selftests + }; +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_init, _gcry_md_block_write, keccak_final, keccak_read, + sizeof (KECCAK_CONTEXT), + run_selftests + }; +gcry_md_spec_t _gcry_digest_spec_sha3_512 = + { + GCRY_MD_SHA3_512, {0, 1}, + "SHA3-512", sha3_512_asn, DIM (sha3_512_asn), oid_spec_sha3_512, 64, + sha3_512_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 2c660e98..eeab1307 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -51,6 +51,14 @@ map_mac_algo_to_md (int mac_algo) return GCRY_MD_SHA384; case GCRY_MAC_HMAC_SHA512: return GCRY_MD_SHA512; + case GCRY_MAC_HMAC_SHA3_224: + return GCRY_MD_SHA3_224; + case GCRY_MAC_HMAC_SHA3_256: + return GCRY_MD_SHA3_256; + case GCRY_MAC_HMAC_SHA3_384: + return GCRY_MD_SHA3_384; + case GCRY_MAC_HMAC_SHA3_512: + return GCRY_MD_SHA512; case GCRY_MAC_HMAC_RMD160: return GCRY_MD_RMD160; case GCRY_MAC_HMAC_TIGER1: diff --git a/cipher/md.c b/cipher/md.c index 3ab46efc..0c669caa 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -51,6 +51,12 @@ static gcry_md_spec_t *digest_list[] = &_gcry_digest_spec_sha512, &_gcry_digest_spec_sha384, #endif +#if USE_SHA3 + &_gcry_digest_spec_sha3_224, + &_gcry_digest_spec_sha3_256, + &_gcry_digest_spec_sha3_384, + &_gcry_digest_spec_sha3_512, +#endif #ifdef USE_GOST_R_3411_94 &_gcry_digest_spec_gost3411_94, &_gcry_digest_spec_gost3411_cp, @@ -333,6 +339,8 @@ md_open (gcry_md_hd_t *h, int algo, unsigned int flags) { case GCRY_MD_SHA384: case GCRY_MD_SHA512: + case GCRY_MD_SHA3_384: + case GCRY_MD_SHA3_512: ctx->macpads_Bsize = 128; break; case GCRY_MD_GOSTR3411_94: diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index b958e7d2..d0d6003a 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -217,6 +217,10 @@ get_hash_algo (const char *s, size_t n) { "md4", GCRY_MD_MD4 }, { "tiger", GCRY_MD_TIGER }, { "haval", GCRY_MD_HAVAL }, + { "sha3-224", GCRY_MD_SHA3_224 }, + { "sha3-256", GCRY_MD_SHA3_256 }, + { "sha3-384", GCRY_MD_SHA3_384 }, + { "sha3-512", GCRY_MD_SHA3_512 }, { NULL, 0 } }; int algo; diff --git a/configure.ac b/configure.ac index 0f16175b..48e21794 100644 --- a/configure.ac +++ b/configure.ac @@ -198,7 +198,7 @@ enabled_pubkey_ciphers="" # Definitions for message digests. available_digests="crc gostr3411-94 md2 md4 md5 rmd160 sha1 sha256" -available_digests_64="sha512 tiger whirlpool stribog" +available_digests_64="sha512 sha3 tiger whirlpool stribog" enabled_digests="" # Definitions for kdfs (optional ones) @@ -2094,6 +2094,24 @@ if test "$found" = "1" ; then fi fi +LIST_MEMBER(sha3, $enabled_digests) +if test "$found" = "1" ; then + GCRYPT_DIGESTS="$GCRYPT_DIGESTS keccak.lo" + AC_DEFINE(USE_SHA3, 1, [Defined if this module should be included]) + + case "${host}" in + x86_64-*-*) + # Build with the assembly implementation + : + ;; + esac + + if test x"$neonsupport" = xyes ; then + # Build with the NEON implementation + : + fi +fi + LIST_MEMBER(tiger, $enabled_digests) if test "$found" = "1" ; then GCRYPT_DIGESTS="$GCRYPT_DIGESTS tiger.lo" diff --git a/src/cipher.h b/src/cipher.h index 89ae2e2d..d96fdb9b 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -289,8 +289,12 @@ extern gcry_md_spec_t _gcry_digest_spec_rmd160; extern gcry_md_spec_t _gcry_digest_spec_sha1; extern gcry_md_spec_t _gcry_digest_spec_sha224; extern gcry_md_spec_t _gcry_digest_spec_sha256; -extern gcry_md_spec_t _gcry_digest_spec_sha512; extern gcry_md_spec_t _gcry_digest_spec_sha384; +extern gcry_md_spec_t _gcry_digest_spec_sha512; +extern gcry_md_spec_t _gcry_digest_spec_sha3_224; +extern gcry_md_spec_t _gcry_digest_spec_sha3_256; +extern gcry_md_spec_t _gcry_digest_spec_sha3_512; +extern gcry_md_spec_t _gcry_digest_spec_sha3_384; extern gcry_md_spec_t _gcry_digest_spec_tiger; extern gcry_md_spec_t _gcry_digest_spec_tiger1; extern gcry_md_spec_t _gcry_digest_spec_tiger2; @@ -518,6 +518,10 @@ run_hmac_selftests (int extended) GCRY_MD_SHA256, GCRY_MD_SHA384, GCRY_MD_SHA512, + GCRY_MD_SHA3_224, + GCRY_MD_SHA3_256, + GCRY_MD_SHA3_384, + GCRY_MD_SHA3_512, 0 }; int idx; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 0984d111..4b4646b4 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1158,7 +1158,12 @@ enum gcry_md_algos GCRY_MD_SHA384 = 9, GCRY_MD_SHA512 = 10, GCRY_MD_SHA224 = 11, - GCRY_MD_MD4 = 301, + GCRY_MD_SHA3_224= 12, + GCRY_MD_SHA3_256= 13, + GCRY_MD_SHA3_384= 14, + GCRY_MD_SHA3_512= 15, + + GCRY_MD_MD4 = 301, GCRY_MD_CRC32 = 302, GCRY_MD_CRC32_RFC1510 = 303, GCRY_MD_CRC24_RFC2440 = 304, @@ -1345,6 +1350,10 @@ enum gcry_mac_algos GCRY_MAC_HMAC_STRIBOG256 = 112, GCRY_MAC_HMAC_STRIBOG512 = 113, GCRY_MAC_HMAC_MD2 = 114, + GCRY_MAC_HMAC_SHA3_224 = 115, + GCRY_MAC_HMAC_SHA3_256 = 116, + GCRY_MAC_HMAC_SHA3_384 = 117, + GCRY_MAC_HMAC_SHA3_512 = 118, GCRY_MAC_CMAC_AES = 201, GCRY_MAC_CMAC_3DES = 202, |