summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2015-08-08 10:47:55 +0200
committerWerner Koch <wk@gnupg.org>2015-08-08 10:47:55 +0200
commit0e17f7a05bba309a87811992aa47a77af9935b99 (patch)
tree5d1c8cc673a6cd4cfb16d2cf154f2f9987d64d05
parent10789e3cdda7b944acb4b59624c34a2ccfaea6e5 (diff)
downloadlibgcrypt-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.am1
-rw-r--r--cipher/hmac-tests.c11
-rw-r--r--cipher/keccak.c264
-rw-r--r--cipher/mac-hmac.c8
-rw-r--r--cipher/md.c8
-rw-r--r--cipher/pubkey-util.c4
-rw-r--r--configure.ac20
-rw-r--r--src/cipher.h6
-rw-r--r--src/fips.c4
-rw-r--r--src/gcrypt.h.in11
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;
diff --git a/src/fips.c b/src/fips.c
index c90e4b69..7939abd7 100644
--- a/src/fips.c
+++ b/src/fips.c
@@ -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,