diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 4798d456..eca87d1a 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -1,254 +1,253 @@ # Makefile for cipher modules # Copyright (C) 1998, 1999, 2000, 2001, 2002, # 2003, 2009 Free Software Foundation, Inc. # # 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 . # Process this file with automake to produce Makefile.in # Need to include ../src in addition to top_srcdir because gcrypt.h is # a built header. AM_CPPFLAGS = -I../src -I$(top_srcdir)/src -I../mpi -I$(top_srcdir)/mpi AM_CFLAGS = $(GPG_ERROR_CFLAGS) AM_CCASFLAGS = $(NOEXECSTACK_FLAGS) -EXTRA_DIST = gost-s-box.c +EXTRA_DIST = gost-s-box.c hmac-tests.c CLEANFILES = gost-s-box DISTCLEANFILES = gost-sb.h noinst_LTLIBRARIES = libcipher.la GCRYPT_MODULES = @GCRYPT_CIPHERS@ @GCRYPT_PUBKEY_CIPHERS@ \ @GCRYPT_DIGESTS@ @GCRYPT_KDFS@ libcipher_la_DEPENDENCIES = $(GCRYPT_MODULES) libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c \ cipher-cfb.c \ cipher-ofb.c \ cipher-ctr.c \ cipher-aeswrap.c \ cipher-ccm.c \ cipher-cmac.c \ cipher-gcm.c cipher-gcm-intel-pclmul.c cipher-gcm-armv7-neon.S \ cipher-gcm-armv8-aarch32-ce.S cipher-gcm-armv8-aarch64-ce.S \ cipher-poly1305.c \ cipher-ocb.c \ cipher-xts.c \ cipher-eax.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ mac-hmac.c mac-cmac.c mac-gmac.c mac-poly1305.c \ poly1305.c poly1305-internal.h \ kdf.c kdf-internal.h \ - hmac-tests.c \ bithelp.h \ bufhelp.h \ primegen.c \ hash-common.c hash-common.h \ dsa-common.c rsa-common.c \ sha1.h EXTRA_libcipher_la_SOURCES = \ asm-common-aarch64.h \ asm-common-amd64.h \ asm-poly1305-aarch64.h \ asm-poly1305-amd64.h \ arcfour.c arcfour-amd64.S \ blowfish.c blowfish-amd64.S blowfish-arm.S \ cast5.c cast5-amd64.S cast5-arm.S \ chacha20.c chacha20-amd64-ssse3.S chacha20-amd64-avx2.S \ chacha20-armv7-neon.S chacha20-aarch64.S \ chacha20-ppc.c \ crc.c crc-intel-pclmul.c crc-armv8-ce.c \ crc-armv8-aarch64-ce.S \ crc-ppc.c \ des.c des-amd64.S \ dsa.c \ elgamal.c \ ecc.c ecc-curves.c ecc-misc.c ecc-common.h \ ecc-ecdh.c ecc-ecdsa.c ecc-eddsa.c ecc-gost.c ecc-sm2.c \ idea.c \ gost28147.c gost.h \ gostr3411-94.c \ md4.c \ md5.c \ rijndael.c rijndael-internal.h rijndael-tables.h \ rijndael-aesni.c rijndael-padlock.c \ rijndael-amd64.S rijndael-arm.S \ rijndael-ssse3-amd64.c rijndael-ssse3-amd64-asm.S \ rijndael-armv8-ce.c rijndael-armv8-aarch32-ce.S \ rijndael-armv8-aarch64-ce.S rijndael-aarch64.S \ rijndael-ppc.c rijndael-ppc9le.c \ rijndael-ppc-common.h rijndael-ppc-functions.h \ rmd160.c \ rsa.c \ salsa20.c salsa20-amd64.S salsa20-armv7-neon.S \ scrypt.c \ seed.c \ serpent.c serpent-sse2-amd64.S \ sm4.c sm4-aesni-avx-amd64.S sm4-aesni-avx2-amd64.S \ serpent-avx2-amd64.S serpent-armv7-neon.S \ sha1.c sha1-ssse3-amd64.S sha1-avx-amd64.S sha1-avx-bmi2-amd64.S \ sha1-avx2-bmi2-amd64.S sha1-armv7-neon.S sha1-armv8-aarch32-ce.S \ sha1-armv8-aarch64-ce.S sha1-intel-shaext.c \ sha256.c sha256-ssse3-amd64.S sha256-avx-amd64.S \ sha256-avx2-bmi2-amd64.S \ sha256-armv8-aarch32-ce.S sha256-armv8-aarch64-ce.S \ sha256-intel-shaext.c sha256-ppc.c \ sha512.c sha512-ssse3-amd64.S sha512-avx-amd64.S \ sha512-avx2-bmi2-amd64.S \ sha512-armv7-neon.S sha512-arm.S \ sha512-ppc.c sha512-ssse3-i386.c \ sm3.c \ keccak.c keccak_permute_32.h keccak_permute_64.h keccak-armv7-neon.S \ stribog.c \ tiger.c \ whirlpool.c whirlpool-sse2-amd64.S \ twofish.c twofish-amd64.S twofish-arm.S twofish-aarch64.S \ twofish-avx2-amd64.S \ rfc2268.c \ camellia.c camellia.h camellia-glue.c camellia-aesni-avx-amd64.S \ camellia-aesni-avx2-amd64.S camellia-arm.S camellia-aarch64.S \ blake2.c \ blake2b-amd64-avx2.S blake2s-amd64-avx.S gost28147.lo: gost-sb.h gost-sb.h: gost-s-box ./gost-s-box $@ gost-s-box: gost-s-box.c $(CC_FOR_BUILD) $(CFLAGS_FOR_BUILD) $(LDFLAGS_FOR_BUILD) \ $(CPPFLAGS_FOR_BUILD)-o $@ $(srcdir)/gost-s-box.c if ENABLE_O_FLAG_MUNGING o_flag_munging = sed -e 's/-O\([2-9s][2-9s]*\)/-O1/' -e 's/-Ofast/-O1/g' else o_flag_munging = cat endif # We need to lower the optimization for this module. tiger.o: $(srcdir)/tiger.c Makefile `echo $(COMPILE) -c $< | $(o_flag_munging) ` tiger.lo: $(srcdir)/tiger.c Makefile `echo $(LTCOMPILE) -c $< | $(o_flag_munging) ` # We need to disable instrumentation for these modules as they use cc as # thin assembly front-end and do not tolerate in-between function calls # inserted by compiler as those functions may clobber the XMM registers. if ENABLE_INSTRUMENTATION_MUNGING instrumentation_munging = sed \ -e 's/-fsanitize[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g' \ -e 's/-fprofile[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g' \ -e 's/-fcoverage[=,\-][=,a-z,A-Z,0-9,\,,\-]*//g' else instrumentation_munging = cat endif rijndael-aesni.o: $(srcdir)/rijndael-aesni.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` rijndael-aesni.lo: $(srcdir)/rijndael-aesni.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` rijndael-ssse3-amd64.o: $(srcdir)/rijndael-ssse3-amd64.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` rijndael-ssse3-amd64.lo: $(srcdir)/rijndael-ssse3-amd64.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` cipher-gcm-intel-pclmul.o: $(srcdir)/cipher-gcm-intel-pclmul.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` cipher-gcm-intel-pclmul.lo: $(srcdir)/cipher-gcm-intel-pclmul.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` sha1-intel-shaext.o: $(srcdir)/sha1-intel-shaext.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` sha1-intel-shaext.lo: $(srcdir)/sha1-intel-shaext.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` sha256-intel-shaext.o: $(srcdir)/sha256-intel-shaext.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` sha256-intel-shaext.lo: $(srcdir)/sha256-intel-shaext.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` sha256-ssse3-i386.o: $(srcdir)/sha256-ssse3-i386.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` sha256-ssse3-i386.lo: $(srcdir)/sha256-ssse3-i386.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` crc-intel-pclmul.o: $(srcdir)/crc-intel-pclmul.c Makefile `echo $(COMPILE) -c $< | $(instrumentation_munging) ` crc-intel-pclmul.lo: $(srcdir)/crc-intel-pclmul.c Makefile `echo $(LTCOMPILE) -c $< | $(instrumentation_munging) ` if ENABLE_PPC_VCRYPTO_EXTRA_CFLAGS ppc_vcrypto_cflags = -maltivec -mvsx -mcrypto else ppc_vcrypto_cflags = endif rijndael-ppc.o: $(srcdir)/rijndael-ppc.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` rijndael-ppc.lo: $(srcdir)/rijndael-ppc.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` rijndael-ppc9le.o: $(srcdir)/rijndael-ppc9le.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` rijndael-ppc9le.lo: $(srcdir)/rijndael-ppc9le.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` sha256-ppc.o: $(srcdir)/sha256-ppc.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` sha256-ppc.lo: $(srcdir)/sha256-ppc.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` sha512-ppc.o: $(srcdir)/sha512-ppc.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` sha512-ppc.lo: $(srcdir)/sha512-ppc.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` chacha20-ppc.o: $(srcdir)/chacha20-ppc.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` chacha20-ppc.lo: $(srcdir)/chacha20-ppc.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` crc-ppc.o: $(srcdir)/crc-ppc.c Makefile `echo $(COMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` crc-ppc.lo: $(srcdir)/crc-ppc.c Makefile `echo $(LTCOMPILE) $(ppc_vcrypto_cflags) -c $< | $(instrumentation_munging) ` diff --git a/cipher/gost28147.c b/cipher/gost28147.c index df16c3c6..1bafe317 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -1,551 +1,552 @@ /* gost28147.c - GOST 28147-89 implementation for Libgcrypt * Copyright (C) 2012 Free Software Foundation, Inc. * * 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 . */ /* GOST 28147-89 defines several modes of encryption: * - ECB which should be used only for key transfer * - CFB mode * - OFB-like mode with additional transformation on keystream * RFC 5830 names this 'counter encryption' mode * Original GOST text uses the term 'gammirovanie' * - MAC mode ('imitovstavka') * * This implementation handles ECB and CFB modes via usual libgcrypt handling. * OFB-like modes are unsupported. */ #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "mac-internal.h" #include "bufhelp.h" #include "gost.h" #include "gost-sb.h" static void gost_do_set_sbox (GOST28147_context *ctx, unsigned int index) { ctx->sbox = gost_oid_map[index].sbox; ctx->mesh_limit = gost_oid_map[index].keymeshing ? 1024 : 0; } static gcry_err_code_t gost_setkey (void *c, const byte *key, unsigned keylen, cipher_bulk_ops_t *bulk_ops) { int i; GOST28147_context *ctx = c; (void)bulk_ops; if (keylen != 256 / 8) return GPG_ERR_INV_KEYLEN; if (!ctx->sbox) gost_do_set_sbox (ctx, 0); for (i = 0; i < 8; i++) { ctx->key[i] = buf_get_le32(&key[4*i]); } ctx->mesh_counter = 0; return GPG_ERR_NO_ERROR; } static inline u32 gost_val (u32 subkey, u32 cm1, const u32 *sbox) { cm1 += subkey; cm1 = sbox[0*256 + ((cm1 >> 0) & 0xff)] | sbox[1*256 + ((cm1 >> 8) & 0xff)] | sbox[2*256 + ((cm1 >> 16) & 0xff)] | sbox[3*256 + ((cm1 >> 24) & 0xff)]; return cm1; } static unsigned int _gost_encrypt_data (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2) { n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[7], n1, sbox); n1 ^= gost_val (key[6], n2, sbox); n2 ^= gost_val (key[5], n1, sbox); n1 ^= gost_val (key[4], n2, sbox); n2 ^= gost_val (key[3], n1, sbox); n1 ^= gost_val (key[2], n2, sbox); n2 ^= gost_val (key[1], n1, sbox); n1 ^= gost_val (key[0], n2, sbox); *o1 = n2; *o2 = n1; return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static unsigned int gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; unsigned int burn; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); buf_put_le32 (outbuf+0, n1); buf_put_le32 (outbuf+4, n2); return /* burn_stack */ burn + 6*sizeof(void*) /* func call */; } unsigned int _gcry_gost_enc_data (const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2, int cryptopro) { const u32 *sbox; if (cryptopro) sbox = sbox_CryptoPro_3411; else sbox = sbox_test_3411; return _gost_encrypt_data (sbox, key, o1, o2, n1, n2) + 7 * sizeof(void *); } static unsigned int gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; const u32 *sbox = ctx->sbox; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); n2 ^= gost_val (ctx->key[0], n1, sbox); n1 ^= gost_val (ctx->key[1], n2, sbox); n2 ^= gost_val (ctx->key[2], n1, sbox); n1 ^= gost_val (ctx->key[3], n2, sbox); n2 ^= gost_val (ctx->key[4], n1, sbox); n1 ^= gost_val (ctx->key[5], n2, sbox); n2 ^= gost_val (ctx->key[6], n1, sbox); n1 ^= gost_val (ctx->key[7], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); n2 ^= gost_val (ctx->key[7], n1, sbox); n1 ^= gost_val (ctx->key[6], n2, sbox); n2 ^= gost_val (ctx->key[5], n1, sbox); n1 ^= gost_val (ctx->key[4], n2, sbox); n2 ^= gost_val (ctx->key[3], n1, sbox); n1 ^= gost_val (ctx->key[2], n2, sbox); n2 ^= gost_val (ctx->key[1], n1, sbox); n1 ^= gost_val (ctx->key[0], n2, sbox); buf_put_le32 (outbuf+0, n2); buf_put_le32 (outbuf+4, n1); return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static gpg_err_code_t gost_set_sbox (GOST28147_context *ctx, const char *oid) { int i; for (i = 0; gost_oid_map[i].oid; i++) { if (!strcmp(gost_oid_map[i].oid, oid)) { gost_do_set_sbox (ctx, i); return 0; } } return GPG_ERR_VALUE_NOT_FOUND; } static gpg_err_code_t gost_set_extra_info (void *c, int what, const void *buffer, size_t buflen) { GOST28147_context *ctx = c; gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case GCRYCTL_SET_SBOX: ec = gost_set_sbox (ctx, buffer); break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static const byte CryptoProKeyMeshingKey[] = { 0x69, 0x00, 0x72, 0x22, 0x64, 0xC9, 0x04, 0x23, 0x8D, 0x3A, 0xDB, 0x96, 0x46, 0xE9, 0x2A, 0xC4, 0x18, 0xFE, 0xAC, 0x94, 0x00, 0xED, 0x07, 0x12, 0xC0, 0x86, 0xDC, 0xC2, 0xEF, 0x4C, 0xA9, 0x2B }; /* Implements key meshing algorithm by modifing ctx and returning new IV. Thanks to Dmitry Belyavskiy. */ static void cryptopro_key_meshing (GOST28147_context *ctx) { unsigned char newkey[32]; unsigned int i; /* "Decrypt" the static keymeshing key */ for (i = 0; i < 4; i++) { gost_decrypt_block (ctx, newkey + i*8, CryptoProKeyMeshingKey + i*8); } /* Set new key */ for (i = 0; i < 8; i++) { ctx->key[i] = buf_get_le32(&newkey[4*i]); } ctx->mesh_counter = 0; } static unsigned int gost_encrypt_block_mesh (void *c, byte *outbuf, const byte *inbuf) { GOST28147_context *ctx = c; u32 n1, n2; unsigned int burn; n1 = buf_get_le32 (inbuf); n2 = buf_get_le32 (inbuf+4); if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit)) { cryptopro_key_meshing (ctx); /* Yes, encrypt twice: once for KeyMeshing procedure per RFC 4357, * once for block encryption */ _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); } burn = _gost_encrypt_data(ctx->sbox, ctx->key, &n1, &n2, n1, n2); ctx->mesh_counter += 8; buf_put_le32 (outbuf+0, n1); buf_put_le32 (outbuf+4, n2); return /* burn_stack */ burn + 6*sizeof(void*) /* func call */; } static gcry_cipher_oid_spec_t oids_gost28147_mesh[] = { { "1.2.643.2.2.21", GCRY_CIPHER_MODE_CFB }, /* { "1.2.643.2.2.31.0", GCRY_CIPHER_MODE_CNTGOST }, */ { "1.2.643.2.2.31.1", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.2", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.3", GCRY_CIPHER_MODE_CFB }, { "1.2.643.2.2.31.4", GCRY_CIPHER_MODE_CFB }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_gost28147 = { GCRY_CIPHER_GOST28147, {0, 0}, "GOST28147", NULL, NULL, 8, 256, sizeof (GOST28147_context), gost_setkey, gost_encrypt_block, gost_decrypt_block, NULL, NULL, NULL, gost_set_extra_info, }; /* Meshing is used only for CFB, so no need to have separate * gost_decrypt_block_mesh. * Moreover key meshing is specified as encrypting the block (IV). Decrypting * it afterwards would be meaningless. */ gcry_cipher_spec_t _gcry_cipher_spec_gost28147_mesh = { GCRY_CIPHER_GOST28147_MESH, {0, 0}, "GOST28147_MESH", NULL, oids_gost28147_mesh, 8, 256, sizeof (GOST28147_context), gost_setkey, gost_encrypt_block_mesh, gost_decrypt_block, NULL, NULL, NULL, gost_set_extra_info, }; static gcry_err_code_t gost_imit_open (gcry_mac_hd_t h) { memset(&h->u.imit, 0, sizeof(h->u.imit)); return 0; } static void gost_imit_close (gcry_mac_hd_t h) { (void) h; } static gcry_err_code_t gost_imit_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { int i; if (keylen != 256 / 8) return GPG_ERR_INV_KEYLEN; if (!h->u.imit.ctx.sbox) h->u.imit.ctx.sbox = sbox_CryptoPro_A; for (i = 0; i < 8; i++) { h->u.imit.ctx.key[i] = buf_get_le32(&key[4*i]); } return 0; } static gcry_err_code_t gost_imit_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { if (ivlen != 8) return GPG_ERR_INV_LENGTH; h->u.imit.n1 = buf_get_le32 (iv + 0); h->u.imit.n2 = buf_get_le32 (iv + 4); return 0; } static gcry_err_code_t gost_imit_reset (gcry_mac_hd_t h) { h->u.imit.n1 = h->u.imit.n2 = 0; h->u.imit.unused = 0; return 0; } static unsigned int _gost_imit_block (const u32 *sbox, const u32 *key, u32 *o1, u32 *o2, u32 n1, u32 n2) { n1 ^= *o1; n2 ^= *o2; n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); n2 ^= gost_val (key[0], n1, sbox); n1 ^= gost_val (key[1], n2, sbox); n2 ^= gost_val (key[2], n1, sbox); n1 ^= gost_val (key[3], n2, sbox); n2 ^= gost_val (key[4], n1, sbox); n1 ^= gost_val (key[5], n2, sbox); n2 ^= gost_val (key[6], n1, sbox); n1 ^= gost_val (key[7], n2, sbox); *o1 = n1; *o2 = n2; return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + 4*sizeof(void*) /* gost_val call */; } static inline unsigned int gost_imit_block (GOST28147_context *ctx, u32 *n1, u32 *n2, const unsigned char *buf) { if (ctx->mesh_limit && (ctx->mesh_counter == ctx->mesh_limit)) cryptopro_key_meshing (ctx); return _gost_imit_block (ctx->sbox, ctx->key, n1, n2, buf_get_le32 (buf+0), buf_get_le32 (buf+4)); } static gcry_err_code_t gost_imit_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { const int blocksize = 8; unsigned int burn = 0; if (!buflen || !buf) return GPG_ERR_NO_ERROR; if (h->u.imit.unused) { for (; buflen && h->u.imit.unused < blocksize; buflen --) h->u.imit.lastiv[h->u.imit.unused++] = *buf++; if (h->u.imit.unused < blocksize) return GPG_ERR_NO_ERROR; h->u.imit.count ++; burn = gost_imit_block (&h->u.imit.ctx, &h->u.imit.n1, &h->u.imit.n2, h->u.imit.lastiv); h->u.imit.unused = 0; } while (buflen >= blocksize) { h->u.imit.count ++; burn = gost_imit_block (&h->u.imit.ctx, &h->u.imit.n1, &h->u.imit.n2, buf); buf += blocksize; buflen -= blocksize; } for (; buflen; buflen--) h->u.imit.lastiv[h->u.imit.unused++] = *buf++; _gcry_burn_stack (burn); return GPG_ERR_NO_ERROR; } static void gost_imit_finish (gcry_mac_hd_t h) { static const unsigned char zero[8] = {0}; /* Fill till full block */ if (h->u.imit.unused) gost_imit_write(h, zero, 8 - h->u.imit.unused); if (h->u.imit.count == 1) gost_imit_write(h, zero, 8); } static gcry_err_code_t gost_imit_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { unsigned int dlen = 8; unsigned char digest[8]; gost_imit_finish (h); buf_put_le32 (digest+0, h->u.imit.n1); buf_put_le32 (digest+4, h->u.imit.n2); if (*outlen <= dlen) buf_cpy (outbuf, digest, *outlen); else { buf_cpy (outbuf, digest, dlen); *outlen = dlen; } return 0; } static gcry_err_code_t gost_imit_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { unsigned char tbuf[8]; gost_imit_finish (h); buf_put_le32 (tbuf+0, h->u.imit.n1); buf_put_le32 (tbuf+4, h->u.imit.n2); return buf_eq_const(tbuf, buf, buflen) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } static unsigned int gost_imit_get_maclen (int algo) { (void) algo; return 4; /* or 8 */ } static unsigned int gost_imit_get_keylen (int algo) { (void) algo; return 256 / 8; } static gpg_err_code_t gost_imit_set_extra_info (gcry_mac_hd_t hd, int what, const void *buffer, size_t buflen) { gpg_err_code_t ec = 0; (void)buffer; (void)buflen; switch (what) { case GCRYCTL_SET_SBOX: ec = gost_set_sbox (&hd->u.imit.ctx, buffer); break; default: ec = GPG_ERR_INV_OP; break; } return ec; } static gcry_mac_spec_ops_t gost_imit_ops = { gost_imit_open, gost_imit_close, gost_imit_setkey, gost_imit_setiv, gost_imit_reset, gost_imit_write, gost_imit_read, gost_imit_verify, gost_imit_get_maclen, gost_imit_get_keylen, gost_imit_set_extra_info, + NULL }; gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit = { GCRY_MAC_GOST28147_IMIT, {0, 0}, "GOST28147_IMIT", &gost_imit_ops }; diff --git a/cipher/hmac-tests.c b/cipher/hmac-tests.c index 78d260a1..4ca93536 100644 --- a/cipher/hmac-tests.c +++ b/cipher/hmac-tests.c @@ -1,1160 +1,1162 @@ /* hmac-tests.c - HMAC selftests. * Copyright (C) 2008 Free Software Foundation, Inc. * * 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 . */ /* Although algorithm self-tests are usually implemented in the module implementing the algorithm, the case for HMAC is different because HMAC is implemented on a higher level using a special feature of the gcry_md_ functions. It would be possible to do this also in the digest algorithm modules, but that would blow up the code too much and spread the hmac tests over several modules. Thus we implement all HMAC tests in this test module and provide a function to run the tests. To run all the Libgcrypt selftest in a verbose mode, use $ tests/basic --selftest */ #include #include #include #include #ifdef HAVE_STDINT_H # include #endif #include "g10lib.h" #include "cipher.h" #include "hmac256.h" /* Check one HMAC with digest ALGO using the regualr HAMC * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key * and (EXPECT,EXPECTLEN) the expected result. If TRUNC is set, the * EXPECTLEN may be less than the digest length. Returns NULL on * success or a string describing the failure. */ static const char * check_one (int algo, const void *data, size_t datalen, const void *key, size_t keylen, const void *expect, size_t expectlen, int trunc) { gcry_md_hd_t hd; const unsigned char *digest; /* printf ("HMAC algo %d\n", algo); */ if (trunc) { if (_gcry_md_get_algo_dlen (algo) < expectlen) return "invalid tests data"; } else { if (_gcry_md_get_algo_dlen (algo) != expectlen) return "invalid tests data"; } if (_gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC)) return "gcry_md_open failed"; if (_gcry_md_setkey (hd, key, keylen)) { _gcry_md_close (hd); return "gcry_md_setkey failed"; } _gcry_md_write (hd, data, datalen); digest = _gcry_md_read (hd, algo); if (!digest) { _gcry_md_close (hd); return "gcry_md_read failed"; } if (memcmp (digest, expect, expectlen)) { /* int i; */ /* fputs (" {", stdout); */ /* for (i=0; i < expectlen-1; i++) */ /* { */ /* if (i && !(i % 8)) */ /* fputs ("\n ", stdout); */ /* printf (" 0x%02x,", digest[i]); */ /* } */ /* printf (" 0x%02x } },\n", digest[i]); */ _gcry_md_close (hd); return "does not match"; } _gcry_md_close (hd); return NULL; } static gpg_err_code_t selftests_sha1 (int extended, selftest_report_func_t report) { const char *what; const char *errtxt; unsigned char key[128]; int i, j; what = "FIPS-198a, A.1"; for (i=0; i < 64; i++) key[i] = i; errtxt = check_one (GCRY_MD_SHA1, "Sample #1", 9, key, 64, "\x4f\x4c\xa3\xd5\xd6\x8b\xa7\xcc\x0a\x12" "\x08\xc9\xc6\x1e\x9c\x5d\xa0\x40\x3c\x0a", 20, 0); if (errtxt) goto failed; if (extended) { what = "FIPS-198a, A.2"; for (i=0, j=0x30; i < 20; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #2", 9, key, 20, "\x09\x22\xd3\x40\x5f\xaa\x3d\x19\x4f\x82" "\xa4\x58\x30\x73\x7d\x5c\xc6\xc7\x5d\x24", 20, 0); if (errtxt) goto failed; what = "FIPS-198a, A.3"; for (i=0, j=0x50; i < 100; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #3", 9, key, 100, "\xbc\xf4\x1e\xab\x8b\xb2\xd8\x02\xf3\xd0" "\x5c\xaf\x7c\xb0\x92\xec\xf8\xd1\xa3\xaa", 20, 0); if (errtxt) goto failed; what = "FIPS-198a, A.4"; for (i=0, j=0x70; i < 49; i++) key[i] = j++; errtxt = check_one (GCRY_MD_SHA1, "Sample #4", 9, key, 49, "\x9e\xa8\x86\xef\xe2\x68\xdb\xec\xce\x42" "\x0c\x75\x24\xdf\x32\xe0\x75\x1a\x2a\x26", 20, 0); if (errtxt) goto failed; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA1, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha224 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[28]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0xa3, 0x0e, 0x01, 0x09, 0x8b, 0xc6, 0xdb, 0xbf, 0x45, 0x69, 0x0f, 0x3a, 0x7e, 0x9e, 0x6d, 0x0f, 0x8b, 0xbe, 0xa2, 0xa3, 0x9e, 0x61, 0x48, 0x00, 0x8f, 0xd0, 0x5e, 0x44 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x89, 0x6f, 0xb1, 0x12, 0x8a, 0xbb, 0xdf, 0x19, 0x68, 0x32, 0x10, 0x7c, 0xd4, 0x9d, 0xf3, 0x3f, 0x47, 0xb4, 0xb1, 0x16, 0x99, 0x12, 0xba, 0x4f, 0x53, 0x68, 0x4b, 0x22 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x7f, 0xb3, 0xcb, 0x35, 0x88, 0xc6, 0xc1, 0xf6, 0xff, 0xa9, 0x69, 0x4d, 0x7d, 0x6a, 0xd2, 0x64, 0x93, 0x65, 0xb0, 0xc1, 0xf6, 0x5d, 0x69, 0xd1, 0xec, 0x83, 0x33, 0xea } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x6c, 0x11, 0x50, 0x68, 0x74, 0x01, 0x3c, 0xac, 0x6a, 0x2a, 0xbc, 0x1b, 0xb3, 0x82, 0x62, 0x7c, 0xec, 0x6a, 0x90, 0xd8, 0x6e, 0xfc, 0x01, 0x2d, 0xe7, 0xaf, 0xec, 0x5a } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x95, 0xe9, 0xa0, 0xdb, 0x96, 0x20, 0x95, 0xad, 0xae, 0xbe, 0x9b, 0x2d, 0x6f, 0x0d, 0xbc, 0xe2, 0xd4, 0x99, 0xf1, 0x12, 0xf2, 0xd2, 0xb7, 0x27, 0x3f, 0xa6, 0x87, 0x0e } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x3a, 0x85, 0x41, 0x66, 0xac, 0x5d, 0x9f, 0x02, 0x3f, 0x54, 0xd5, 0x17, 0xd0, 0xb3, 0x9d, 0xbd, 0x94, 0x67, 0x70, 0xdb, 0x9c, 0x2b, 0x95, 0xc9, 0xf6, 0xf5, 0x65, 0xd1 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA224, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA224, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha256 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[32]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0x5b, 0xdc, 0xc1, 0x46, 0xbf, 0x60, 0x75, 0x4e, 0x6a, 0x04, 0x24, 0x26, 0x08, 0x95, 0x75, 0xc7, 0x5a, 0x00, 0x3f, 0x08, 0x9d, 0x27, 0x39, 0x83, 0x9d, 0xec, 0x58, 0xb9, 0x64, 0xec, 0x38, 0x43 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0xb0, 0x34, 0x4c, 0x61, 0xd8, 0xdb, 0x38, 0x53, 0x5c, 0xa8, 0xaf, 0xce, 0xaf, 0x0b, 0xf1, 0x2b, 0x88, 0x1d, 0xc2, 0x00, 0xc9, 0x83, 0x3d, 0xa7, 0x26, 0xe9, 0x37, 0x6c, 0x2e, 0x32, 0xcf, 0xf7 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x77, 0x3e, 0xa9, 0x1e, 0x36, 0x80, 0x0e, 0x46, 0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7, 0x29, 0x59, 0x09, 0x8b, 0x3e, 0xf8, 0xc1, 0x22, 0xd9, 0x63, 0x55, 0x14, 0xce, 0xd5, 0x65, 0xfe } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x82, 0x55, 0x8a, 0x38, 0x9a, 0x44, 0x3c, 0x0e, 0xa4, 0xcc, 0x81, 0x98, 0x99, 0xf2, 0x08, 0x3a, 0x85, 0xf0, 0xfa, 0xa3, 0xe5, 0x78, 0xf8, 0x07, 0x7a, 0x2e, 0x3f, 0xf4, 0x67, 0x29, 0x66, 0x5b } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x60, 0xe4, 0x31, 0x59, 0x1e, 0xe0, 0xb6, 0x7f, 0x0d, 0x8a, 0x26, 0xaa, 0xcb, 0xf5, 0xb7, 0x7f, 0x8e, 0x0b, 0xc6, 0x21, 0x37, 0x28, 0xc5, 0x14, 0x05, 0x46, 0x04, 0x0f, 0x0e, 0xe3, 0x7f, 0x54 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x9b, 0x09, 0xff, 0xa7, 0x1b, 0x94, 0x2f, 0xcb, 0x27, 0x63, 0x5f, 0xbc, 0xd5, 0xb0, 0xe9, 0x44, 0xbf, 0xdc, 0x63, 0x64, 0x4f, 0x07, 0x13, 0x93, 0x8a, 0x7f, 0x51, 0x53, 0x5c, 0x3a, 0x35, 0xe2 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { hmac256_context_t hmachd; const unsigned char *digest; size_t dlen; what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA256, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; hmachd = _gcry_hmac256_new (tv[tvidx].key, strlen (tv[tvidx].key)); if (!hmachd) { errtxt = "_gcry_hmac256_new failed"; goto failed; } _gcry_hmac256_update (hmachd, tv[tvidx].data, strlen (tv[tvidx].data)); digest = _gcry_hmac256_finalize (hmachd, &dlen); if (!digest) { errtxt = "_gcry_hmac256_finalize failed"; _gcry_hmac256_release (hmachd); goto failed; } if (dlen != DIM (tv[tvidx].expect) || memcmp (digest, tv[tvidx].expect, DIM (tv[tvidx].expect))) { errtxt = "does not match in second implementation"; _gcry_hmac256_release (hmachd); goto failed; } _gcry_hmac256_release (hmachd); if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA256, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha384 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[48]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0xaf, 0x45, 0xd2, 0xe3, 0x76, 0x48, 0x40, 0x31, 0x61, 0x7f, 0x78, 0xd2, 0xb5, 0x8a, 0x6b, 0x1b, 0x9c, 0x7e, 0xf4, 0x64, 0xf5, 0xa0, 0x1b, 0x47, 0xe4, 0x2e, 0xc3, 0x73, 0x63, 0x22, 0x44, 0x5e, 0x8e, 0x22, 0x40, 0xca, 0x5e, 0x69, 0xe2, 0xc7, 0x8b, 0x32, 0x39, 0xec, 0xfa, 0xb2, 0x16, 0x49 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0xaf, 0xd0, 0x39, 0x44, 0xd8, 0x48, 0x95, 0x62, 0x6b, 0x08, 0x25, 0xf4, 0xab, 0x46, 0x90, 0x7f, 0x15, 0xf9, 0xda, 0xdb, 0xe4, 0x10, 0x1e, 0xc6, 0x82, 0xaa, 0x03, 0x4c, 0x7c, 0xeb, 0xc5, 0x9c, 0xfa, 0xea, 0x9e, 0xa9, 0x07, 0x6e, 0xde, 0x7f, 0x4a, 0xf1, 0x52, 0xe8, 0xb2, 0xfa, 0x9c, 0xb6 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x88, 0x06, 0x26, 0x08, 0xd3, 0xe6, 0xad, 0x8a, 0x0a, 0xa2, 0xac, 0xe0, 0x14, 0xc8, 0xa8, 0x6f, 0x0a, 0xa6, 0x35, 0xd9, 0x47, 0xac, 0x9f, 0xeb, 0xe8, 0x3e, 0xf4, 0xe5, 0x59, 0x66, 0x14, 0x4b, 0x2a, 0x5a, 0xb3, 0x9d, 0xc1, 0x38, 0x14, 0xb9, 0x4e, 0x3a, 0xb6, 0xe1, 0x01, 0xa3, 0x4f, 0x27 } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0x3e, 0x8a, 0x69, 0xb7, 0x78, 0x3c, 0x25, 0x85, 0x19, 0x33, 0xab, 0x62, 0x90, 0xaf, 0x6c, 0xa7, 0x7a, 0x99, 0x81, 0x48, 0x08, 0x50, 0x00, 0x9c, 0xc5, 0x57, 0x7c, 0x6e, 0x1f, 0x57, 0x3b, 0x4e, 0x68, 0x01, 0xdd, 0x23, 0xc4, 0xa7, 0xd6, 0x79, 0xcc, 0xf8, 0xa3, 0x86, 0xc6, 0x74, 0xcf, 0xfb } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x4e, 0xce, 0x08, 0x44, 0x85, 0x81, 0x3e, 0x90, 0x88, 0xd2, 0xc6, 0x3a, 0x04, 0x1b, 0xc5, 0xb4, 0x4f, 0x9e, 0xf1, 0x01, 0x2a, 0x2b, 0x58, 0x8f, 0x3c, 0xd1, 0x1f, 0x05, 0x03, 0x3a, 0xc4, 0xc6, 0x0c, 0x2e, 0xf6, 0xab, 0x40, 0x30, 0xfe, 0x82, 0x96, 0x24, 0x8d, 0xf1, 0x63, 0xf4, 0x49, 0x52 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x66, 0x17, 0x17, 0x8e, 0x94, 0x1f, 0x02, 0x0d, 0x35, 0x1e, 0x2f, 0x25, 0x4e, 0x8f, 0xd3, 0x2c, 0x60, 0x24, 0x20, 0xfe, 0xb0, 0xb8, 0xfb, 0x9a, 0xdc, 0xce, 0xbb, 0x82, 0x46, 0x1e, 0x99, 0xc5, 0xa6, 0x78, 0xcc, 0x31, 0xe7, 0x99, 0x17, 0x6d, 0x38, 0x60, 0xe6, 0x11, 0x0c, 0x46, 0x52, 0x3e } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA384, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA384, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_sha512 (int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect[64]; } tv[] = { { "data-28 key-4", "what do ya want for nothing?", "Jefe", { 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2, 0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3, 0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6, 0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54, 0x97, 0x58, 0xbf, 0x75, 0xc0, 0x5a, 0x99, 0x4a, 0x6d, 0x03, 0x4f, 0x65, 0xf8, 0xf0, 0xe6, 0xfd, 0xca, 0xea, 0xb1, 0xa3, 0x4d, 0x4a, 0x6b, 0x4b, 0x63, 0x6e, 0x07, 0x0a, 0x38, 0xbc, 0xe7, 0x37 } }, { "data-9 key-20", "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d, 0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0, 0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78, 0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde, 0xda, 0xa8, 0x33, 0xb7, 0xd6, 0xb8, 0xa7, 0x02, 0x03, 0x8b, 0x27, 0x4e, 0xae, 0xa3, 0xf4, 0xe4, 0xbe, 0x9d, 0x91, 0x4e, 0xeb, 0x61, 0xf1, 0x70, 0x2e, 0x69, 0x6c, 0x20, 0x3a, 0x12, 0x68, 0x54 } }, { "data-50 key-20", "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84, 0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9, 0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36, 0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39, 0xbf, 0x3e, 0x84, 0x82, 0x79, 0xa7, 0x22, 0xc8, 0x06, 0xb4, 0x85, 0xa4, 0x7e, 0x67, 0xc8, 0x07, 0xb9, 0x46, 0xa3, 0x37, 0xbe, 0xe8, 0x94, 0x26, 0x74, 0x27, 0x88, 0x59, 0xe1, 0x32, 0x92, 0xfb } }, { "data-50 key-26", "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0xb0, 0xba, 0x46, 0x56, 0x37, 0x45, 0x8c, 0x69, 0x90, 0xe5, 0xa8, 0xc5, 0xf6, 0x1d, 0x4a, 0xf7, 0xe5, 0x76, 0xd9, 0x7f, 0xf9, 0x4b, 0x87, 0x2d, 0xe7, 0x6f, 0x80, 0x50, 0x36, 0x1e, 0xe3, 0xdb, 0xa9, 0x1c, 0xa5, 0xc1, 0x1a, 0xa2, 0x5e, 0xb4, 0xd6, 0x79, 0x27, 0x5c, 0xc5, 0x78, 0x80, 0x63, 0xa5, 0xf1, 0x97, 0x41, 0x12, 0x0c, 0x4f, 0x2d, 0xe2, 0xad, 0xeb, 0xeb, 0x10, 0xa2, 0x98, 0xdd } }, { "data-54 key-131", "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x80, 0xb2, 0x42, 0x63, 0xc7, 0xc1, 0xa3, 0xeb, 0xb7, 0x14, 0x93, 0xc1, 0xdd, 0x7b, 0xe8, 0xb4, 0x9b, 0x46, 0xd1, 0xf4, 0x1b, 0x4a, 0xee, 0xc1, 0x12, 0x1b, 0x01, 0x37, 0x83, 0xf8, 0xf3, 0x52, 0x6b, 0x56, 0xd0, 0x37, 0xe0, 0x5f, 0x25, 0x98, 0xbd, 0x0f, 0xd2, 0x21, 0x5d, 0x6a, 0x1e, 0x52, 0x95, 0xe6, 0x4f, 0x73, 0xf6, 0x3f, 0x0a, 0xec, 0x8b, 0x91, 0x5a, 0x98, 0x5d, 0x78, 0x65, 0x98 } }, { "data-152 key-131", "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xe3, 0x7b, 0x6a, 0x77, 0x5d, 0xc8, 0x7d, 0xba, 0xa4, 0xdf, 0xa9, 0xf9, 0x6e, 0x5e, 0x3f, 0xfd, 0xde, 0xbd, 0x71, 0xf8, 0x86, 0x72, 0x89, 0x86, 0x5d, 0xf5, 0xa3, 0x2d, 0x20, 0xcd, 0xc9, 0x44, 0xb6, 0x02, 0x2c, 0xac, 0x3c, 0x49, 0x82, 0xb1, 0x0d, 0x5e, 0xeb, 0x55, 0xc3, 0xe4, 0xde, 0x15, 0x13, 0x46, 0x76, 0xfb, 0x6d, 0xe0, 0x44, 0x60, 0x65, 0xc9, 0x74, 0x40, 0xfa, 0x8c, 0x6a, 0x58 } }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MD_SHA512, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, DIM (tv[tvidx].expect), 0); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", GCRY_MD_SHA512, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } /* Test for the SHA3 algorithms. Vectors taken on 2017-07-18 from * http://www.wolfgang-ehrhardt.de/hmac-sha3-testvectors.html */ static gpg_err_code_t selftests_sha3 (int hashalgo, int extended, selftest_report_func_t report) { static struct { const char * const desc; const char * const data; const char * const key; const char expect_224[28]; const char expect_256[32]; const char expect_384[48]; const char expect_512[64]; unsigned char trunc; } tv[] = { { "data-9 key-20", /* Test 1 */ "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b\x0b", { 0x3b, 0x16, 0x54, 0x6b, 0xbc, 0x7b, 0xe2, 0x70, 0x6a, 0x03, 0x1d, 0xca, 0xfd, 0x56, 0x37, 0x3d, 0x98, 0x84, 0x36, 0x76, 0x41, 0xd8, 0xc5, 0x9a, 0xf3, 0xc8, 0x60, 0xf7 }, { 0xba, 0x85, 0x19, 0x23, 0x10, 0xdf, 0xfa, 0x96, 0xe2, 0xa3, 0xa4, 0x0e, 0x69, 0x77, 0x43, 0x51, 0x14, 0x0b, 0xb7, 0x18, 0x5e, 0x12, 0x02, 0xcd, 0xcc, 0x91, 0x75, 0x89, 0xf9, 0x5e, 0x16, 0xbb }, { 0x68, 0xd2, 0xdc, 0xf7, 0xfd, 0x4d, 0xdd, 0x0a, 0x22, 0x40, 0xc8, 0xa4, 0x37, 0x30, 0x5f, 0x61, 0xfb, 0x73, 0x34, 0xcf, 0xb5, 0xd0, 0x22, 0x6e, 0x1b, 0xc2, 0x7d, 0xc1, 0x0a, 0x2e, 0x72, 0x3a, 0x20, 0xd3, 0x70, 0xb4, 0x77, 0x43, 0x13, 0x0e, 0x26, 0xac, 0x7e, 0x3d, 0x53, 0x28, 0x86, 0xbd }, { 0xeb, 0x3f, 0xbd, 0x4b, 0x2e, 0xaa, 0xb8, 0xf5, 0xc5, 0x04, 0xbd, 0x3a, 0x41, 0x46, 0x5a, 0xac, 0xec, 0x15, 0x77, 0x0a, 0x7c, 0xab, 0xac, 0x53, 0x1e, 0x48, 0x2f, 0x86, 0x0b, 0x5e, 0xc7, 0xba, 0x47, 0xcc, 0xb2, 0xc6, 0xf2, 0xaf, 0xce, 0x8f, 0x88, 0xd2, 0x2b, 0x6d, 0xc6, 0x13, 0x80, 0xf2, 0x3a, 0x66, 0x8f, 0xd3, 0x88, 0x8b, 0xb8, 0x05, 0x37, 0xc0, 0xa0, 0xb8, 0x64, 0x07, 0x68, 0x9e } }, { "data-28 key-4", /* Test 2 */ /* Test with a key shorter than the length of the HMAC output. */ "what do ya want for nothing?", "Jefe", { 0x7f, 0xdb, 0x8d, 0xd8, 0x8b, 0xd2, 0xf6, 0x0d, 0x1b, 0x79, 0x86, 0x34, 0xad, 0x38, 0x68, 0x11, 0xc2, 0xcf, 0xc8, 0x5b, 0xfa, 0xf5, 0xd5, 0x2b, 0xba, 0xce, 0x5e, 0x66 }, { 0xc7, 0xd4, 0x07, 0x2e, 0x78, 0x88, 0x77, 0xae, 0x35, 0x96, 0xbb, 0xb0, 0xda, 0x73, 0xb8, 0x87, 0xc9, 0x17, 0x1f, 0x93, 0x09, 0x5b, 0x29, 0x4a, 0xe8, 0x57, 0xfb, 0xe2, 0x64, 0x5e, 0x1b, 0xa5 }, { 0xf1, 0x10, 0x1f, 0x8c, 0xbf, 0x97, 0x66, 0xfd, 0x67, 0x64, 0xd2, 0xed, 0x61, 0x90, 0x3f, 0x21, 0xca, 0x9b, 0x18, 0xf5, 0x7c, 0xf3, 0xe1, 0xa2, 0x3c, 0xa1, 0x35, 0x08, 0xa9, 0x32, 0x43, 0xce, 0x48, 0xc0, 0x45, 0xdc, 0x00, 0x7f, 0x26, 0xa2, 0x1b, 0x3f, 0x5e, 0x0e, 0x9d, 0xf4, 0xc2, 0x0a }, { 0x5a, 0x4b, 0xfe, 0xab, 0x61, 0x66, 0x42, 0x7c, 0x7a, 0x36, 0x47, 0xb7, 0x47, 0x29, 0x2b, 0x83, 0x84, 0x53, 0x7c, 0xdb, 0x89, 0xaf, 0xb3, 0xbf, 0x56, 0x65, 0xe4, 0xc5, 0xe7, 0x09, 0x35, 0x0b, 0x28, 0x7b, 0xae, 0xc9, 0x21, 0xfd, 0x7c, 0xa0, 0xee, 0x7a, 0x0c, 0x31, 0xd0, 0x22, 0xa9, 0x5e, 0x1f, 0xc9, 0x2b, 0xa9, 0xd7, 0x7d, 0xf8, 0x83, 0x96, 0x02, 0x75, 0xbe, 0xb4, 0xe6, 0x20, 0x24 } }, { "data-50 key-20", /* Test 3 */ /* Test with a combined length of key and data that is larger * than 64 bytes (= block-size of SHA-224 and SHA-256). */ "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa", { 0x67, 0x6c, 0xfc, 0x7d, 0x16, 0x15, 0x36, 0x38, 0x78, 0x03, 0x90, 0x69, 0x2b, 0xe1, 0x42, 0xd2, 0xdf, 0x7c, 0xe9, 0x24, 0xb9, 0x09, 0xc0, 0xc0, 0x8d, 0xbf, 0xdc, 0x1a }, { 0x84, 0xec, 0x79, 0x12, 0x4a, 0x27, 0x10, 0x78, 0x65, 0xce, 0xdd, 0x8b, 0xd8, 0x2d, 0xa9, 0x96, 0x5e, 0x5e, 0xd8, 0xc3, 0x7b, 0x0a, 0xc9, 0x80, 0x05, 0xa7, 0xf3, 0x9e, 0xd5, 0x8a, 0x42, 0x07 }, { 0x27, 0x5c, 0xd0, 0xe6, 0x61, 0xbb, 0x8b, 0x15, 0x1c, 0x64, 0xd2, 0x88, 0xf1, 0xf7, 0x82, 0xfb, 0x91, 0xa8, 0xab, 0xd5, 0x68, 0x58, 0xd7, 0x2b, 0xab, 0xb2, 0xd4, 0x76, 0xf0, 0x45, 0x83, 0x73, 0xb4, 0x1b, 0x6a, 0xb5, 0xbf, 0x17, 0x4b, 0xec, 0x42, 0x2e, 0x53, 0xfc, 0x31, 0x35, 0xac, 0x6e }, { 0x30, 0x9e, 0x99, 0xf9, 0xec, 0x07, 0x5e, 0xc6, 0xc6, 0xd4, 0x75, 0xed, 0xa1, 0x18, 0x06, 0x87, 0xfc, 0xf1, 0x53, 0x11, 0x95, 0x80, 0x2a, 0x99, 0xb5, 0x67, 0x74, 0x49, 0xa8, 0x62, 0x51, 0x82, 0x85, 0x1c, 0xb3, 0x32, 0xaf, 0xb6, 0xa8, 0x9c, 0x41, 0x13, 0x25, 0xfb, 0xcb, 0xcd, 0x42, 0xaf, 0xcb, 0x7b, 0x6e, 0x5a, 0xab, 0x7e, 0xa4, 0x2c, 0x66, 0x0f, 0x97, 0xfd, 0x85, 0x84, 0xbf, 0x03 } }, { "data-50 key-25", /* Test 4 */ /* Test with a combined length of key and data that is larger * than 64 bytes (= block-size of SHA-224 and SHA-256). */ "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd", "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" "\x11\x12\x13\x14\x15\x16\x17\x18\x19", { 0xa9, 0xd7, 0x68, 0x5a, 0x19, 0xc4, 0xe0, 0xdb, 0xd9, 0xdf, 0x25, 0x56, 0xcc, 0x8a, 0x7d, 0x2a, 0x77, 0x33, 0xb6, 0x76, 0x25, 0xce, 0x59, 0x4c, 0x78, 0x27, 0x0e, 0xeb }, { 0x57, 0x36, 0x6a, 0x45, 0xe2, 0x30, 0x53, 0x21, 0xa4, 0xbc, 0x5a, 0xa5, 0xfe, 0x2e, 0xf8, 0xa9, 0x21, 0xf6, 0xaf, 0x82, 0x73, 0xd7, 0xfe, 0x7b, 0xe6, 0xcf, 0xed, 0xb3, 0xf0, 0xae, 0xa6, 0xd7 }, { 0x3a, 0x5d, 0x7a, 0x87, 0x97, 0x02, 0xc0, 0x86, 0xbc, 0x96, 0xd1, 0xdd, 0x8a, 0xa1, 0x5d, 0x9c, 0x46, 0x44, 0x6b, 0x95, 0x52, 0x13, 0x11, 0xc6, 0x06, 0xfd, 0xc4, 0xe3, 0x08, 0xf4, 0xb9, 0x84, 0xda, 0x2d, 0x0f, 0x94, 0x49, 0xb3, 0xba, 0x84, 0x25, 0xec, 0x7f, 0xb8, 0xc3, 0x1b, 0xc1, 0x36 }, { 0xb2, 0x7e, 0xab, 0x1d, 0x6e, 0x8d, 0x87, 0x46, 0x1c, 0x29, 0xf7, 0xf5, 0x73, 0x9d, 0xd5, 0x8e, 0x98, 0xaa, 0x35, 0xf8, 0xe8, 0x23, 0xad, 0x38, 0xc5, 0x49, 0x2a, 0x20, 0x88, 0xfa, 0x02, 0x81, 0x99, 0x3b, 0xbf, 0xff, 0x9a, 0x0e, 0x9c, 0x6b, 0xf1, 0x21, 0xae, 0x9e, 0xc9, 0xbb, 0x09, 0xd8, 0x4a, 0x5e, 0xba, 0xc8, 0x17, 0x18, 0x2e, 0xa9, 0x74, 0x67, 0x3f, 0xb1, 0x33, 0xca, 0x0d, 0x1d } }, { "data-20 key-20 trunc", /* Test 5 */ /* Test with a truncation of output to 128 bits. */ "Test With Truncation", "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" "\x0c\x0c\x0c\x0c", { 0x49, 0xfd, 0xd3, 0xab, 0xd0, 0x05, 0xeb, 0xb8, 0xae, 0x63, 0xfe, 0xa9, 0x46, 0xd1, 0x88, 0x3c }, { 0x6e, 0x02, 0xc6, 0x45, 0x37, 0xfb, 0x11, 0x80, 0x57, 0xab, 0xb7, 0xfb, 0x66, 0xa2, 0x3b, 0x3c }, { 0x47, 0xc5, 0x1a, 0xce, 0x1f, 0xfa, 0xcf, 0xfd, 0x74, 0x94, 0x72, 0x46, 0x82, 0x61, 0x57, 0x83 }, { 0x0f, 0xa7, 0x47, 0x59, 0x48, 0xf4, 0x3f, 0x48, 0xca, 0x05, 0x16, 0x67, 0x1e, 0x18, 0x97, 0x8c }, 16 }, { "data-54 key-131", /* Test 6 */ /* Test with a key larger than 128 bytes (= block-size of * SHA-384 and SHA-512). */ "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xb4, 0xa1, 0xf0, 0x4c, 0x00, 0x28, 0x7a, 0x9b, 0x7f, 0x60, 0x75, 0xb3, 0x13, 0xd2, 0x79, 0xb8, 0x33, 0xbc, 0x8f, 0x75, 0x12, 0x43, 0x52, 0xd0, 0x5f, 0xb9, 0x99, 0x5f }, { 0xed, 0x73, 0xa3, 0x74, 0xb9, 0x6c, 0x00, 0x52, 0x35, 0xf9, 0x48, 0x03, 0x2f, 0x09, 0x67, 0x4a, 0x58, 0xc0, 0xce, 0x55, 0x5c, 0xfc, 0x1f, 0x22, 0x3b, 0x02, 0x35, 0x65, 0x60, 0x31, 0x2c, 0x3b }, { 0x0f, 0xc1, 0x95, 0x13, 0xbf, 0x6b, 0xd8, 0x78, 0x03, 0x70, 0x16, 0x70, 0x6a, 0x0e, 0x57, 0xbc, 0x52, 0x81, 0x39, 0x83, 0x6b, 0x9a, 0x42, 0xc3, 0xd4, 0x19, 0xe4, 0x98, 0xe0, 0xe1, 0xfb, 0x96, 0x16, 0xfd, 0x66, 0x91, 0x38, 0xd3, 0x3a, 0x11, 0x05, 0xe0, 0x7c, 0x72, 0xb6, 0x95, 0x3b, 0xcc }, { 0x00, 0xf7, 0x51, 0xa9, 0xe5, 0x06, 0x95, 0xb0, 0x90, 0xed, 0x69, 0x11, 0xa4, 0xb6, 0x55, 0x24, 0x95, 0x1c, 0xdc, 0x15, 0xa7, 0x3a, 0x5d, 0x58, 0xbb, 0x55, 0x21, 0x5e, 0xa2, 0xcd, 0x83, 0x9a, 0xc7, 0x9d, 0x2b, 0x44, 0xa3, 0x9b, 0xaf, 0xab, 0x27, 0xe8, 0x3f, 0xde, 0x9e, 0x11, 0xf6, 0x34, 0x0b, 0x11, 0xd9, 0x91, 0xb1, 0xb9, 0x1b, 0xf2, 0xee, 0xe7, 0xfc, 0x87, 0x24, 0x26, 0xc3, 0xa4 } }, { "data-54 key-147", /* Test 6a */ /* Test with a key larger than 144 bytes (= block-size of * SHA3-224). */ "Test Using Larger Than Block-Size Key - Hash Key First", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xb9, 0x6d, 0x73, 0x0c, 0x14, 0x8c, 0x2d, 0xaa, 0xd8, 0x64, 0x9d, 0x83, 0xde, 0xfa, 0xa3, 0x71, 0x97, 0x38, 0xd3, 0x47, 0x75, 0x39, 0x7b, 0x75, 0x71, 0xc3, 0x85, 0x15 }, { 0xa6, 0x07, 0x2f, 0x86, 0xde, 0x52, 0xb3, 0x8b, 0xb3, 0x49, 0xfe, 0x84, 0xcd, 0x6d, 0x97, 0xfb, 0x6a, 0x37, 0xc4, 0xc0, 0xf6, 0x2a, 0xae, 0x93, 0x98, 0x11, 0x93, 0xa7, 0x22, 0x9d, 0x34, 0x67 }, { 0x71, 0x3d, 0xff, 0x03, 0x02, 0xc8, 0x50, 0x86, 0xec, 0x5a, 0xd0, 0x76, 0x8d, 0xd6, 0x5a, 0x13, 0xdd, 0xd7, 0x90, 0x68, 0xd8, 0xd4, 0xc6, 0x21, 0x2b, 0x71, 0x2e, 0x41, 0x64, 0x94, 0x49, 0x11, 0x14, 0x80, 0x23, 0x00, 0x44, 0x18, 0x5a, 0x99, 0x10, 0x3e, 0xd8, 0x20, 0x04, 0xdd, 0xbf, 0xcc }, { 0xb1, 0x48, 0x35, 0xc8, 0x19, 0xa2, 0x90, 0xef, 0xb0, 0x10, 0xac, 0xe6, 0xd8, 0x56, 0x8d, 0xc6, 0xb8, 0x4d, 0xe6, 0x0b, 0xc4, 0x9b, 0x00, 0x4c, 0x3b, 0x13, 0xed, 0xa7, 0x63, 0x58, 0x94, 0x51, 0xe5, 0xdd, 0x74, 0x29, 0x28, 0x84, 0xd1, 0xbd, 0xce, 0x64, 0xe6, 0xb9, 0x19, 0xdd, 0x61, 0xdc, 0x9c, 0x56, 0xa2, 0x82, 0xa8, 0x1c, 0x0b, 0xd1, 0x4f, 0x1f, 0x36, 0x5b, 0x49, 0xb8, 0x3a, 0x5b } }, { "data-152 key-131", /* Test 7 */ /* Test with a key and data that is larger than 128 bytes (= * block-size of SHA-384 and SHA-512). */ "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0x05, 0xd8, 0xcd, 0x6d, 0x00, 0xfa, 0xea, 0x8d, 0x1e, 0xb6, 0x8a, 0xde, 0x28, 0x73, 0x0b, 0xbd, 0x3c, 0xba, 0xb6, 0x92, 0x9f, 0x0a, 0x08, 0x6b, 0x29, 0xcd, 0x62, 0xa0 }, { 0x65, 0xc5, 0xb0, 0x6d, 0x4c, 0x3d, 0xe3, 0x2a, 0x7a, 0xef, 0x87, 0x63, 0x26, 0x1e, 0x49, 0xad, 0xb6, 0xe2, 0x29, 0x3e, 0xc8, 0xe7, 0xc6, 0x1e, 0x8d, 0xe6, 0x17, 0x01, 0xfc, 0x63, 0xe1, 0x23 }, { 0x02, 0x6f, 0xdf, 0x6b, 0x50, 0x74, 0x1e, 0x37, 0x38, 0x99, 0xc9, 0xf7, 0xd5, 0x40, 0x6d, 0x4e, 0xb0, 0x9f, 0xc6, 0x66, 0x56, 0x36, 0xfc, 0x1a, 0x53, 0x00, 0x29, 0xdd, 0xf5, 0xcf, 0x3c, 0xa5, 0xa9, 0x00, 0xed, 0xce, 0x01, 0xf5, 0xf6, 0x1e, 0x2f, 0x40, 0x8c, 0xdf, 0x2f, 0xd3, 0xe7, 0xe8 }, { 0x38, 0xa4, 0x56, 0xa0, 0x04, 0xbd, 0x10, 0xd3, 0x2c, 0x9a, 0xb8, 0x33, 0x66, 0x84, 0x11, 0x28, 0x62, 0xc3, 0xdb, 0x61, 0xad, 0xcc, 0xa3, 0x18, 0x29, 0x35, 0x5e, 0xaf, 0x46, 0xfd, 0x5c, 0x73, 0xd0, 0x6a, 0x1f, 0x0d, 0x13, 0xfe, 0xc9, 0xa6, 0x52, 0xfb, 0x38, 0x11, 0xb5, 0x77, 0xb1, 0xb1, 0xd1, 0xb9, 0x78, 0x9f, 0x97, 0xae, 0x5b, 0x83, 0xc6, 0xf4, 0x4d, 0xfc, 0xf1, 0xd6, 0x7e, 0xba } }, { "data-152 key-147", /* Test 7a */ /* Test with a key larger than 144 bytes (= block-size of * SHA3-224). */ "This is a test using a larger than block-size key and a larger " "than block-size data. The key needs to be hashed before being " "used by the HMAC algorithm.", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa", { 0xc7, 0x9c, 0x9b, 0x09, 0x34, 0x24, 0xe5, 0x88, 0xa9, 0x87, 0x8b, 0xbc, 0xb0, 0x89, 0xe0, 0x18, 0x27, 0x00, 0x96, 0xe9, 0xb4, 0xb1, 0xa9, 0xe8, 0x22, 0x0c, 0x86, 0x6a }, { 0xe6, 0xa3, 0x6d, 0x9b, 0x91, 0x5f, 0x86, 0xa0, 0x93, 0xca, 0xc7, 0xd1, 0x10, 0xe9, 0xe0, 0x4c, 0xf1, 0xd6, 0x10, 0x0d, 0x30, 0x47, 0x55, 0x09, 0xc2, 0x47, 0x5f, 0x57, 0x1b, 0x75, 0x8b, 0x5a }, { 0xca, 0xd1, 0x8a, 0x8f, 0xf6, 0xc4, 0xcc, 0x3a, 0xd4, 0x87, 0xb9, 0x5f, 0x97, 0x69, 0xe9, 0xb6, 0x1c, 0x06, 0x2a, 0xef, 0xd6, 0x95, 0x25, 0x69, 0xe6, 0xe6, 0x42, 0x18, 0x97, 0x05, 0x4c, 0xfc, 0x70, 0xb5, 0xfd, 0xc6, 0x60, 0x5c, 0x18, 0x45, 0x71, 0x12, 0xfc, 0x6a, 0xaa, 0xd4, 0x55, 0x85 }, { 0xdc, 0x03, 0x0e, 0xe7, 0x88, 0x70, 0x34, 0xf3, 0x2c, 0xf4, 0x02, 0xdf, 0x34, 0x62, 0x2f, 0x31, 0x1f, 0x3e, 0x6c, 0xf0, 0x48, 0x60, 0xc6, 0xbb, 0xd7, 0xfa, 0x48, 0x86, 0x74, 0x78, 0x2b, 0x46, 0x59, 0xfd, 0xbd, 0xf3, 0xfd, 0x87, 0x78, 0x52, 0x88, 0x5c, 0xfe, 0x6e, 0x22, 0x18, 0x5f, 0xe7, 0xb2, 0xee, 0x95, 0x20, 0x43, 0x62, 0x9b, 0xc9, 0xd5, 0xf3, 0x29, 0x8a, 0x41, 0xd0, 0x2c, 0x66 } }/*,*/ /* Our API does not allow to specify a bit count and thus we * can't use the following test. */ /* { "data-5bit key-4", /\* Test 8 *\/ */ /* /\* Test with data bit size no multiple of 8, the data bits are */ /* * '11001' from the NIST example using SHA-3 order (= 5 bits */ /* * from LSB hex byte 13 or 5 bits from MSB hex byte c8). *\/ */ /* "\xc8", */ /* "Jefe", */ /* { 0x5f, 0x8c, 0x0e, 0xa7, 0xfa, 0xfe, 0xcd, 0x0c, */ /* 0x34, 0x63, 0xaa, 0xd0, 0x97, 0x42, 0xce, 0xce, */ /* 0xb1, 0x42, 0xfe, 0x0a, 0xb6, 0xf4, 0x53, 0x94, */ /* 0x38, 0xc5, 0x9d, 0xe8 }, */ /* { 0xec, 0x82, 0x22, 0x77, 0x3f, 0xac, 0x68, 0xb3, */ /* 0xd3, 0xdc, 0xb1, 0x82, 0xae, 0xc8, 0xb0, 0x50, */ /* 0x7a, 0xce, 0x44, 0x48, 0xd2, 0x0a, 0x11, 0x47, */ /* 0xe6, 0x82, 0x11, 0x8d, 0xa4, 0xe3, 0xf4, 0x4c }, */ /* { 0x21, 0xfb, 0xd3, 0xbf, 0x3e, 0xbb, 0xa3, 0xcf, */ /* 0xc9, 0xef, 0x64, 0xc0, 0x59, 0x1c, 0x92, 0xc5, */ /* 0xac, 0xb2, 0x65, 0xe9, 0x2d, 0x87, 0x61, 0xd1, */ /* 0xf9, 0x1a, 0x52, 0xa1, 0x03, 0xa6, 0xc7, 0x96, */ /* 0x94, 0xcf, 0xd6, 0x7a, 0x9a, 0x2a, 0xc1, 0x32, */ /* 0x4f, 0x02, 0xfe, 0xa6, 0x3b, 0x81, 0xef, 0xfc }, */ /* { 0x27, 0xf9, 0x38, 0x8c, 0x15, 0x67, 0xef, 0x4e, */ /* 0xf2, 0x00, 0x60, 0x2a, 0x6c, 0xf8, 0x71, 0xd6, */ /* 0x8a, 0x6f, 0xb0, 0x48, 0xd4, 0x73, 0x7a, 0xc4, */ /* 0x41, 0x8a, 0x2f, 0x02, 0x12, 0x89, 0xd1, 0x3d, */ /* 0x1f, 0xd1, 0x12, 0x0f, 0xec, 0xb9, 0xcf, 0x96, */ /* 0x4c, 0x5b, 0x11, 0x7a, 0xb5, 0xb1, 0x1c, 0x61, */ /* 0x4b, 0x2d, 0xa3, 0x9d, 0xad, 0xd5, 0x1f, 0x2f, */ /* 0x5e, 0x22, 0xaa, 0xcc, 0xec, 0x7d, 0x57, 0x6e } */ /* } */ }; const char *what; const char *errtxt; int tvidx; const char *expect; int nexpect; for (tvidx=0; tvidx < DIM(tv); tvidx++) { what = tv[tvidx].desc; if (hashalgo == GCRY_MD_SHA3_224) { expect = tv[tvidx].expect_224; nexpect = DIM (tv[tvidx].expect_224); } else if (hashalgo == GCRY_MD_SHA3_256) { expect = tv[tvidx].expect_256; nexpect = DIM (tv[tvidx].expect_256); } else if (hashalgo == GCRY_MD_SHA3_384) { expect = tv[tvidx].expect_384; nexpect = DIM (tv[tvidx].expect_384); } else if (hashalgo == GCRY_MD_SHA3_512) { expect = tv[tvidx].expect_512; nexpect = DIM (tv[tvidx].expect_512); } else BUG(); if (tv[tvidx].trunc && tv[tvidx].trunc < nexpect) nexpect = tv[tvidx].trunc; errtxt = check_one (hashalgo, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), expect, nexpect, !!tv[tvidx].trunc); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("hmac", hashalgo, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } +#if 0 /* 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_SHA1: ec = selftests_sha1 (extended, report); break; case GCRY_MD_SHA224: ec = selftests_sha224 (extended, report); break; case GCRY_MD_SHA256: ec = selftests_sha256 (extended, report); break; case GCRY_MD_SHA384: ec = selftests_sha384 (extended, report); break; 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 = selftests_sha3 (algo, extended, report); break; default: ec = GPG_ERR_DIGEST_ALGO; break; } return ec; } /* Run the selftests for HMAC with digest algorithm ALGO with optional reporting function REPORT. */ gpg_error_t _gcry_hmac_selftest (int algo, int extended, selftest_report_func_t report) { gcry_err_code_t ec = 0; if (!_gcry_md_test_algo (algo)) { ec = run_selftests (algo, extended, report); } else { ec = GPG_ERR_DIGEST_ALGO; if (report) report ("hmac", algo, "module", "algorithm not available"); } return gpg_error (ec); } +#endif diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c index 120fa3df..f4d0ce59 100644 --- a/cipher/mac-cmac.c +++ b/cipher/mac-cmac.c @@ -1,235 +1,236 @@ /* mac-cmac.c - CMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_CMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_CMAC_3DES: return GCRY_CIPHER_3DES; case GCRY_MAC_CMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_CMAC_IDEA: return GCRY_CIPHER_IDEA; case GCRY_MAC_CMAC_CAST5: return GCRY_CIPHER_CAST5; case GCRY_MAC_CMAC_BLOWFISH: return GCRY_CIPHER_BLOWFISH; case GCRY_MAC_CMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_CMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_CMAC_SEED: return GCRY_CIPHER_SEED; case GCRY_MAC_CMAC_RFC2268: return GCRY_CIPHER_RFC2268_128; case GCRY_MAC_CMAC_GOST28147: return GCRY_CIPHER_GOST28147; case GCRY_MAC_CMAC_SM4: return GCRY_CIPHER_SM4; } } static gcry_err_code_t cmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_cipher_hd_t hd; int secure = (h->magic == CTX_MAGIC_SECURE); int cipher_algo; unsigned int flags; cipher_algo = map_mac_algo_to_cipher (h->spec->algo); flags = (secure ? GCRY_CIPHER_SECURE : 0); err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC, flags); if (err) return err; h->u.cmac.cipher_algo = cipher_algo; h->u.cmac.ctx = hd; h->u.cmac.blklen = _gcry_cipher_get_algo_blklen (cipher_algo); return 0; } static void cmac_close (gcry_mac_hd_t h) { _gcry_cipher_close (h->u.cmac.ctx); h->u.cmac.ctx = NULL; } static gcry_err_code_t cmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_cipher_setkey (h->u.cmac.ctx, key, keylen); } static gcry_err_code_t cmac_reset (gcry_mac_hd_t h) { return _gcry_cipher_reset (h->u.cmac.ctx); } static gcry_err_code_t cmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_cmac_authenticate (h->u.cmac.ctx, buf, buflen); } static gcry_err_code_t cmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { if (*outlen > h->u.cmac.blklen) *outlen = h->u.cmac.blklen; return _gcry_cipher_cmac_get_tag (h->u.cmac.ctx, outbuf, *outlen); } static gcry_err_code_t cmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_cmac_check_tag (h->u.cmac.ctx, buf, buflen); } static unsigned int cmac_get_maclen (int algo) { return _gcry_cipher_get_algo_blklen (map_mac_algo_to_cipher (algo)); } static unsigned int cmac_get_keylen (int algo) { return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); } static gcry_mac_spec_ops_t cmac_ops = { cmac_open, cmac_close, cmac_setkey, NULL, cmac_reset, cmac_write, cmac_read, cmac_verify, cmac_get_maclen, cmac_get_keylen, + NULL, NULL }; #if USE_BLOWFISH gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish = { GCRY_MAC_CMAC_BLOWFISH, {0, 0}, "CMAC_BLOWFISH", &cmac_ops }; #endif #if USE_DES gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes = { GCRY_MAC_CMAC_3DES, {0, 1}, "CMAC_3DES", &cmac_ops }; #endif #if USE_CAST5 gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5 = { GCRY_MAC_CMAC_CAST5, {0, 0}, "CMAC_CAST5", &cmac_ops }; #endif #if USE_AES gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes = { GCRY_MAC_CMAC_AES, {0, 1}, "CMAC_AES", &cmac_ops }; #endif #if USE_TWOFISH gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish = { GCRY_MAC_CMAC_TWOFISH, {0, 0}, "CMAC_TWOFISH", &cmac_ops }; #endif #if USE_SERPENT gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent = { GCRY_MAC_CMAC_SERPENT, {0, 0}, "CMAC_SERPENT", &cmac_ops }; #endif #if USE_RFC2268 gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268 = { GCRY_MAC_CMAC_RFC2268, {0, 0}, "CMAC_RFC2268", &cmac_ops }; #endif #if USE_SEED gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed = { GCRY_MAC_CMAC_SEED, {0, 0}, "CMAC_SEED", &cmac_ops }; #endif #if USE_CAMELLIA gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia = { GCRY_MAC_CMAC_CAMELLIA, {0, 0}, "CMAC_CAMELLIA", &cmac_ops }; #endif #ifdef USE_IDEA gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea = { GCRY_MAC_CMAC_IDEA, {0, 0}, "CMAC_IDEA", &cmac_ops }; #endif #if USE_GOST28147 gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147 = { GCRY_MAC_CMAC_GOST28147, {0, 0}, "CMAC_GOST28147", &cmac_ops }; #endif #if USE_SM4 gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4 = { GCRY_MAC_CMAC_SM4, {0, 0}, "CMAC_SM4", &cmac_ops }; #endif diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c index aa78c7e3..b9805eea 100644 --- a/cipher/mac-gmac.c +++ b/cipher/mac-gmac.c @@ -1,186 +1,187 @@ /* mac-gmac.c - GMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_GMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_GMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_GMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_GMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_GMAC_SEED: return GCRY_CIPHER_SEED; } } static gcry_err_code_t gmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_cipher_hd_t hd; int secure = (h->magic == CTX_MAGIC_SECURE); int cipher_algo; unsigned int flags; cipher_algo = map_mac_algo_to_cipher (h->spec->algo); flags = (secure ? GCRY_CIPHER_SECURE : 0); err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM, flags); if (err) return err; h->u.gmac.cipher_algo = cipher_algo; h->u.gmac.ctx = hd; return 0; } static void gmac_close (gcry_mac_hd_t h) { _gcry_cipher_close (h->u.gmac.ctx); h->u.gmac.ctx = NULL; } static gcry_err_code_t gmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_cipher_setkey (h->u.gmac.ctx, key, keylen); } static gcry_err_code_t gmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { return _gcry_cipher_setiv (h->u.gmac.ctx, iv, ivlen); } static gcry_err_code_t gmac_reset (gcry_mac_hd_t h) { return _gcry_cipher_reset (h->u.gmac.ctx); } static gcry_err_code_t gmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_authenticate (h->u.gmac.ctx, buf, buflen); } static gcry_err_code_t gmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { if (*outlen > GCRY_GCM_BLOCK_LEN) *outlen = GCRY_GCM_BLOCK_LEN; return _gcry_cipher_gettag (h->u.gmac.ctx, outbuf, *outlen); } static gcry_err_code_t gmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { return _gcry_cipher_checktag (h->u.gmac.ctx, buf, buflen); } static unsigned int gmac_get_maclen (int algo) { (void)algo; return GCRY_GCM_BLOCK_LEN; } static unsigned int gmac_get_keylen (int algo) { return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); } static gcry_mac_spec_ops_t gmac_ops = { gmac_open, gmac_close, gmac_setkey, gmac_setiv, gmac_reset, gmac_write, gmac_read, gmac_verify, gmac_get_maclen, gmac_get_keylen, + NULL, NULL }; #if USE_AES gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = { GCRY_MAC_GMAC_AES, {0, 1}, "GMAC_AES", &gmac_ops }; #endif #if USE_TWOFISH gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = { GCRY_MAC_GMAC_TWOFISH, {0, 0}, "GMAC_TWOFISH", &gmac_ops }; #endif #if USE_SERPENT gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = { GCRY_MAC_GMAC_SERPENT, {0, 0}, "GMAC_SERPENT", &gmac_ops }; #endif #if USE_SEED gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = { GCRY_MAC_GMAC_SEED, {0, 0}, "GMAC_SEED", &gmac_ops }; #endif #if USE_CAMELLIA gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = { GCRY_MAC_GMAC_CAMELLIA, {0, 0}, "GMAC_CAMELLIA", &gmac_ops }; #endif diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c index d0cc5775..2dca4253 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -1,397 +1,441 @@ /* mac-hmac.c - HMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "./mac-internal.h" #include "bufhelp.h" static int map_mac_algo_to_md (int mac_algo) { switch (mac_algo) { default: return GCRY_MD_NONE; case GCRY_MAC_HMAC_MD2: return GCRY_MD_MD2; case GCRY_MAC_HMAC_MD4: return GCRY_MD_MD4; case GCRY_MAC_HMAC_MD5: return GCRY_MD_MD5; case GCRY_MAC_HMAC_SHA1: return GCRY_MD_SHA1; case GCRY_MAC_HMAC_SHA224: return GCRY_MD_SHA224; case GCRY_MAC_HMAC_SHA256: return GCRY_MD_SHA256; case GCRY_MAC_HMAC_SHA384: return GCRY_MD_SHA384; case GCRY_MAC_HMAC_SHA512: return GCRY_MD_SHA512; case GCRY_MAC_HMAC_SHA512_256: return GCRY_MD_SHA512_256; case GCRY_MAC_HMAC_SHA512_224: return GCRY_MD_SHA512_224; 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_SHA3_512; case GCRY_MAC_HMAC_RMD160: return GCRY_MD_RMD160; case GCRY_MAC_HMAC_TIGER1: return GCRY_MD_TIGER1; case GCRY_MAC_HMAC_WHIRLPOOL: return GCRY_MD_WHIRLPOOL; case GCRY_MAC_HMAC_GOSTR3411_94: return GCRY_MD_GOSTR3411_94; case GCRY_MAC_HMAC_GOSTR3411_CP: return GCRY_MD_GOSTR3411_CP; case GCRY_MAC_HMAC_STRIBOG256: return GCRY_MD_STRIBOG256; case GCRY_MAC_HMAC_STRIBOG512: return GCRY_MD_STRIBOG512; case GCRY_MAC_HMAC_BLAKE2B_512: return GCRY_MD_BLAKE2B_512; case GCRY_MAC_HMAC_BLAKE2B_384: return GCRY_MD_BLAKE2B_384; case GCRY_MAC_HMAC_BLAKE2B_256: return GCRY_MD_BLAKE2B_256; case GCRY_MAC_HMAC_BLAKE2B_160: return GCRY_MD_BLAKE2B_160; case GCRY_MAC_HMAC_BLAKE2S_256: return GCRY_MD_BLAKE2S_256; case GCRY_MAC_HMAC_BLAKE2S_224: return GCRY_MD_BLAKE2S_224; case GCRY_MAC_HMAC_BLAKE2S_160: return GCRY_MD_BLAKE2S_160; case GCRY_MAC_HMAC_BLAKE2S_128: return GCRY_MD_BLAKE2S_128; case GCRY_MAC_HMAC_SM3: return GCRY_MD_SM3; } } static gcry_err_code_t hmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_md_hd_t hd; int secure = (h->magic == CTX_MAGIC_SECURE); unsigned int flags; int md_algo; md_algo = map_mac_algo_to_md (h->spec->algo); flags = GCRY_MD_FLAG_HMAC; flags |= (secure ? GCRY_MD_FLAG_SECURE : 0); err = _gcry_md_open (&hd, md_algo, flags); if (err) return err; h->u.hmac.md_algo = md_algo; h->u.hmac.md_ctx = hd; return 0; } static void hmac_close (gcry_mac_hd_t h) { _gcry_md_close (h->u.hmac.md_ctx); h->u.hmac.md_ctx = NULL; } static gcry_err_code_t hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_md_setkey (h->u.hmac.md_ctx, key, keylen); } static gcry_err_code_t hmac_reset (gcry_mac_hd_t h) { _gcry_md_reset (h->u.hmac.md_ctx); return 0; } static gcry_err_code_t hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { _gcry_md_write (h->u.hmac.md_ctx, buf, buflen); return 0; } static gcry_err_code_t hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (*outlen <= dlen) buf_cpy (outbuf, digest, *outlen); else { buf_cpy (outbuf, digest, dlen); *outlen = dlen; } return 0; } static gcry_err_code_t hmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (buflen > dlen) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, digest, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int hmac_get_maclen (int algo) { return _gcry_md_get_algo_dlen (map_mac_algo_to_md (algo)); } static unsigned int 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; case GCRY_MAC_HMAC_GOSTR3411_94: return 32; default: return 64; } } +#include "hmac-tests.c" + +static gpg_err_code_t +hmac_selftest (int algo, int extended, selftest_report_func_t report) +{ + gpg_err_code_t ec; + + switch (algo) + { + case GCRY_MAC_HMAC_SHA1: + ec = selftests_sha1 (extended, report); + break; + case GCRY_MAC_HMAC_SHA224: + ec = selftests_sha224 (extended, report); + break; + case GCRY_MAC_HMAC_SHA256: + ec = selftests_sha256 (extended, report); + break; + case GCRY_MAC_HMAC_SHA384: + ec = selftests_sha384 (extended, report); + break; + case GCRY_MAC_HMAC_SHA512: + ec = selftests_sha512 (extended, report); + break; + + case GCRY_MAC_HMAC_SHA3_224: + case GCRY_MAC_HMAC_SHA3_256: + case GCRY_MAC_HMAC_SHA3_384: + case GCRY_MAC_HMAC_SHA3_512: + { + int md_algo = map_mac_algo_to_md (algo); + ec = selftests_sha3 (md_algo, extended, report); + } + break; + + default: + ec = GPG_ERR_MAC_ALGO; + break; + } + + return ec; +} + static const gcry_mac_spec_ops_t hmac_ops = { hmac_open, hmac_close, hmac_setkey, NULL, hmac_reset, hmac_write, hmac_read, hmac_verify, hmac_get_maclen, hmac_get_keylen, - NULL + NULL, + hmac_selftest }; #if USE_SHA1 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = { GCRY_MAC_HMAC_SHA1, {0, 1}, "HMAC_SHA1", &hmac_ops }; #endif #if USE_SHA256 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = { GCRY_MAC_HMAC_SHA256, {0, 1}, "HMAC_SHA256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = { GCRY_MAC_HMAC_SHA224, {0, 1}, "HMAC_SHA224", &hmac_ops }; #endif #if USE_SHA512 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = { GCRY_MAC_HMAC_SHA512, {0, 1}, "HMAC_SHA512", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = { GCRY_MAC_HMAC_SHA384, {0, 1}, "HMAC_SHA384", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = { GCRY_MAC_HMAC_SHA512_256, {0, 1}, "HMAC_SHA512_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224 = { GCRY_MAC_HMAC_SHA512_224, {0, 1}, "HMAC_SHA512_224", &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", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp = { GCRY_MAC_HMAC_GOSTR3411_CP, {0, 0}, "HMAC_GOSTR3411_CP", &hmac_ops }; #endif #ifdef USE_GOST_R_3411_12 gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = { GCRY_MAC_HMAC_STRIBOG256, {0, 0}, "HMAC_STRIBOG256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = { GCRY_MAC_HMAC_STRIBOG512, {0, 0}, "HMAC_STRIBOG512", &hmac_ops }; #endif #if USE_WHIRLPOOL gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = { GCRY_MAC_HMAC_WHIRLPOOL, {0, 0}, "HMAC_WHIRLPOOL", &hmac_ops }; #endif #if USE_RMD160 gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = { GCRY_MAC_HMAC_RMD160, {0, 0}, "HMAC_RIPEMD160", &hmac_ops }; #endif #if USE_TIGER gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = { GCRY_MAC_HMAC_TIGER1, {0, 0}, "HMAC_TIGER", &hmac_ops }; #endif #if USE_MD5 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = { GCRY_MAC_HMAC_MD5, {0, 0}, "HMAC_MD5", &hmac_ops }; #endif #if USE_MD4 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = { GCRY_MAC_HMAC_MD4, {0, 0}, "HMAC_MD4", &hmac_ops }; #endif #if USE_MD2 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = { GCRY_MAC_HMAC_MD2, {0, 0}, "HMAC_MD2", &hmac_ops }; #endif #if USE_BLAKE2 gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = { GCRY_MAC_HMAC_BLAKE2B_512, {0, 0}, "HMAC_BLAKE2B_512", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = { GCRY_MAC_HMAC_BLAKE2B_384, {0, 0}, "HMAC_BLAKE2B_384", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = { GCRY_MAC_HMAC_BLAKE2B_256, {0, 0}, "HMAC_BLAKE2B_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = { GCRY_MAC_HMAC_BLAKE2B_160, {0, 0}, "HMAC_BLAKE2B_160", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = { GCRY_MAC_HMAC_BLAKE2S_256, {0, 0}, "HMAC_BLAKE2S_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = { GCRY_MAC_HMAC_BLAKE2S_224, {0, 0}, "HMAC_BLAKE2S_224", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = { GCRY_MAC_HMAC_BLAKE2S_160, {0, 0}, "HMAC_BLAKE2S_160", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128 = { GCRY_MAC_HMAC_BLAKE2S_128, {0, 0}, "HMAC_BLAKE2S_128", &hmac_ops }; #endif #if USE_SM3 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = { GCRY_MAC_HMAC_SM3, {0, 0}, "HMAC_SM3", &hmac_ops }; #endif diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 8c13520b..d907a46f 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -1,273 +1,275 @@ /* mac-internal.h - Internal defs for mac.c * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include "g10lib.h" +#include "cipher-proto.h" #include "gost.h" /* The data object used to hold a handle to an encryption object. */ struct gcry_mac_handle; /* The data object used to hold poly1305-mac context. */ struct poly1305mac_context_s; /* * * Message authentication code related definitions. * */ /* Magic values for the context structure. */ #define CTX_MAGIC_NORMAL 0x59d9b8af #define CTX_MAGIC_SECURE 0x12c27cd0 /* MAC module functions. */ typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h); typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h, const unsigned char *key, size_t keylen); typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen); typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen); typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo); typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo); /* The type used to convey additional information to a MAC. */ typedef gpg_err_code_t (*gcry_mac_set_extra_info_t) (gcry_mac_hd_t h, int what, const void *buffer, size_t buflen); typedef struct gcry_mac_spec_ops { gcry_mac_open_func_t open; gcry_mac_close_func_t close; gcry_mac_setkey_func_t setkey; gcry_mac_setiv_func_t setiv; gcry_mac_reset_func_t reset; gcry_mac_write_func_t write; gcry_mac_read_func_t read; gcry_mac_verify_func_t verify; gcry_mac_get_maclen_func_t get_maclen; gcry_mac_get_keylen_func_t get_keylen; gcry_mac_set_extra_info_t set_extra_info; + selftest_func_t selftest; } gcry_mac_spec_ops_t; /* Module specification structure for message authentication codes. */ typedef struct gcry_mac_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; const gcry_mac_spec_ops_t *ops; } gcry_mac_spec_t; /* The handle structure. */ struct gcry_mac_handle { int magic; int algo; const gcry_mac_spec_t *spec; gcry_ctx_t gcry_ctx; union { struct { gcry_md_hd_t md_ctx; int md_algo; } hmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; unsigned int blklen; } cmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; } gmac; struct { struct poly1305mac_context_s *ctx; } poly1305mac; struct { GOST28147_context ctx; u32 n1, n2; unsigned int unused; unsigned int count; unsigned char lastiv[8]; /* IMIT blocksize */ } imit; } u; }; /* * The HMAC algorithm specifications (mac-hmac.c). */ #if USE_SHA1 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1; #endif #if USE_SHA256 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224; #endif #if USE_SHA512 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256; #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; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp; #endif #ifdef USE_GOST_R_3411_12 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512; #endif #if USE_WHIRLPOOL extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool; #endif #if USE_RMD160 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160; #endif #if USE_TIGER extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1; #endif #if USE_MD5 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; #endif #if USE_MD4 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; #endif #if USE_BLAKE2 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128; #endif #if USE_SM3 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3; #endif /* * The CMAC algorithm specifications (mac-cmac.c). */ #if USE_BLOWFISH extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish; #endif #if USE_DES extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes; #endif #if USE_CAST5 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5; #endif #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent; #endif #if USE_RFC2268 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia; #endif #ifdef USE_IDEA extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; #endif #if USE_GOST28147 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; #endif #if USE_GOST28147 extern gcry_mac_spec_t _gcry_mac_type_spec_gost28147_imit; #endif #if USE_SM4 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_sm4; #endif /* * The GMAC algorithm specifications (mac-gmac.c). */ #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; #endif /* * The Poly1305 MAC algorithm specifications (mac-poly1305.c). */ extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed; #endif diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c index 39ba790f..d27a31c6 100644 --- a/cipher/mac-poly1305.c +++ b/cipher/mac-poly1305.c @@ -1,363 +1,364 @@ /* mac-poly1305.c - Poly1305 based MACs * Copyright (C) 2014 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" #include "poly1305-internal.h" struct poly1305mac_context_s { poly1305_context_t ctx; gcry_cipher_hd_t hd; struct { unsigned int key_set:1; unsigned int nonce_set:1; unsigned int tag:1; } marks; byte tag[POLY1305_TAGLEN]; byte key[POLY1305_KEYLEN]; }; static gcry_err_code_t poly1305mac_open (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx; int secure = (h->magic == CTX_MAGIC_SECURE); unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0); gcry_err_code_t err; int cipher_algo; if (secure) mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx)); else mac_ctx = xtrycalloc (1, sizeof(*mac_ctx)); if (!mac_ctx) return gpg_err_code_from_syserror (); h->u.poly1305mac.ctx = mac_ctx; switch (h->spec->algo) { default: /* already checked. */ case GCRY_MAC_POLY1305: /* plain Poly1305. */ cipher_algo = -1; return 0; case GCRY_MAC_POLY1305_AES: cipher_algo = GCRY_CIPHER_AES; break; case GCRY_MAC_POLY1305_CAMELLIA: cipher_algo = GCRY_CIPHER_CAMELLIA128; break; case GCRY_MAC_POLY1305_TWOFISH: cipher_algo = GCRY_CIPHER_TWOFISH; break; case GCRY_MAC_POLY1305_SERPENT: cipher_algo = GCRY_CIPHER_SERPENT128; break; case GCRY_MAC_POLY1305_SEED: cipher_algo = GCRY_CIPHER_SEED; break; } err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo, GCRY_CIPHER_MODE_ECB, flags); if (err) goto err_free; return 0; err_free: xfree(h->u.poly1305mac.ctx); return err; } static void poly1305mac_close (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (h->spec->algo != GCRY_MAC_POLY1305) _gcry_cipher_close (mac_ctx->hd); xfree(mac_ctx); } static gcry_err_code_t poly1305mac_prepare_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; size_t block_keylen = keylen - 16; /* Need at least 16 + 1 byte key. */ if (keylen <= 16) return GPG_ERR_INV_KEYLEN; /* For Poly1305-AES, first part of key is passed to Poly1305 as is. */ memcpy (mac_ctx->key, key + block_keylen, 16); /* Remaining part is used as key for the block cipher. */ return _gcry_cipher_setkey (mac_ctx->hd, key, block_keylen); } static gcry_err_code_t poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); mac_ctx->marks.key_set = 0; mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; if (h->spec->algo != GCRY_MAC_POLY1305) { err = poly1305mac_prepare_key (h, key, keylen); if (err) return err; /* Poly1305-AES/etc also need nonce. */ mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 0; } else { /* For plain Poly1305, key is the nonce and setup is complete now. */ if (keylen != POLY1305_KEYLEN) return GPG_ERR_INV_KEYLEN; memcpy (mac_ctx->key, key, keylen); err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) { memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); return err; } mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; } return 0; } static gcry_err_code_t poly1305mac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; if (h->spec->algo == GCRY_MAC_POLY1305) return GPG_ERR_INV_ARG; if (ivlen != 16) return GPG_ERR_INV_ARG; if (!mac_ctx->marks.key_set) return 0; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; /* Prepare second part of the poly1305 key. */ err = _gcry_cipher_encrypt (mac_ctx->hd, mac_ctx->key + 16, 16, iv, 16); if (err) return err; err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) return err; mac_ctx->marks.nonce_set = 1; return 0; } static gcry_err_code_t poly1305mac_reset (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; mac_ctx->marks.tag = 0; return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); } static gcry_err_code_t poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set || mac_ctx->marks.tag) return GPG_ERR_INV_STATE; _gcry_poly1305_update (&mac_ctx->ctx, buf, buflen); return 0; } static gcry_err_code_t poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; if (!mac_ctx->marks.tag) { _gcry_poly1305_finish(&mac_ctx->ctx, mac_ctx->tag); memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); mac_ctx->marks.tag = 1; } if (*outlen == 0) return 0; if (*outlen <= POLY1305_TAGLEN) buf_cpy (outbuf, mac_ctx->tag, *outlen); else { buf_cpy (outbuf, mac_ctx->tag, POLY1305_TAGLEN); *outlen = POLY1305_TAGLEN; } return 0; } static gcry_err_code_t poly1305mac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; size_t outlen = 0; /* Check and finalize tag. */ err = poly1305mac_read(h, NULL, &outlen); if (err) return err; if (buflen > POLY1305_TAGLEN) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, mac_ctx->tag, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int poly1305mac_get_maclen (int algo) { (void)algo; return POLY1305_TAGLEN; } static unsigned int poly1305mac_get_keylen (int algo) { (void)algo; return POLY1305_KEYLEN; } static gcry_mac_spec_ops_t poly1305mac_ops = { poly1305mac_open, poly1305mac_close, poly1305mac_setkey, poly1305mac_setiv, poly1305mac_reset, poly1305mac_write, poly1305mac_read, poly1305mac_verify, poly1305mac_get_maclen, poly1305mac_get_keylen, - NULL + NULL, + NULL, }; gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { GCRY_MAC_POLY1305, {0, 0}, "POLY1305", &poly1305mac_ops }; #if USE_AES gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = { GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES", &poly1305mac_ops }; #endif #if USE_CAMELLIA gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = { GCRY_MAC_POLY1305_CAMELLIA, {0, 0}, "POLY1305_CAMELLIA", &poly1305mac_ops }; #endif #if USE_TWOFISH gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = { GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH", &poly1305mac_ops }; #endif #if USE_SERPENT gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = { GCRY_MAC_POLY1305_SERPENT, {0, 0}, "POLY1305_SERPENT", &poly1305mac_ops }; #endif #if USE_SEED gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = { GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED", &poly1305mac_ops }; #endif diff --git a/cipher/mac.c b/cipher/mac.c index 933be74c..e274b356 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -1,783 +1,808 @@ /* mac.c - message authentication code dispatcher * Copyright (C) 2013 Jussi Kivilinna * * 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 . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" /* This is the list of the digest implementations included in libgcrypt. */ static gcry_mac_spec_t * const mac_list[] = { #if USE_SHA1 &_gcry_mac_type_spec_hmac_sha1, #endif #if USE_SHA256 &_gcry_mac_type_spec_hmac_sha256, &_gcry_mac_type_spec_hmac_sha224, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #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, &_gcry_mac_type_spec_hmac_gost3411_cp, #endif #ifdef USE_GOST_R_3411_12 &_gcry_mac_type_spec_hmac_stribog256, &_gcry_mac_type_spec_hmac_stribog512, #endif #if USE_WHIRLPOOL &_gcry_mac_type_spec_hmac_whirlpool, #endif #if USE_RMD160 &_gcry_mac_type_spec_hmac_rmd160, #endif #if USE_TIGER &_gcry_mac_type_spec_hmac_tiger1, #endif #if USE_MD5 &_gcry_mac_type_spec_hmac_md5, #endif #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #endif #if USE_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #endif #if USE_BLOWFISH &_gcry_mac_type_spec_cmac_blowfish, #endif #if USE_DES &_gcry_mac_type_spec_cmac_tripledes, #endif #if USE_CAST5 &_gcry_mac_type_spec_cmac_cast5, #endif #if USE_AES &_gcry_mac_type_spec_cmac_aes, &_gcry_mac_type_spec_gmac_aes, &_gcry_mac_type_spec_poly1305mac_aes, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, &_gcry_mac_type_spec_gmac_twofish, &_gcry_mac_type_spec_poly1305mac_twofish, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, &_gcry_mac_type_spec_gmac_serpent, &_gcry_mac_type_spec_poly1305mac_serpent, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, #endif #if USE_SEED &_gcry_mac_type_spec_cmac_seed, &_gcry_mac_type_spec_gmac_seed, &_gcry_mac_type_spec_poly1305mac_seed, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, &_gcry_mac_type_spec_gmac_camellia, &_gcry_mac_type_spec_poly1305mac_camellia, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, &_gcry_mac_type_spec_gost28147_imit, #endif &_gcry_mac_type_spec_poly1305mac, #if USE_SM4 &_gcry_mac_type_spec_cmac_sm4, #endif NULL, }; /* HMAC implementations start with index 101 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo101[] = { #if USE_SHA256 &_gcry_mac_type_spec_hmac_sha256, &_gcry_mac_type_spec_hmac_sha224, #else NULL, NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, #else NULL, NULL, #endif #if USE_SHA1 &_gcry_mac_type_spec_hmac_sha1, #else NULL, #endif #if USE_MD5 &_gcry_mac_type_spec_hmac_md5, #else NULL, #endif #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #else NULL, #endif #if USE_RMD160 &_gcry_mac_type_spec_hmac_rmd160, #else NULL, #endif #if USE_TIGER &_gcry_mac_type_spec_hmac_tiger1, #else NULL, #endif #if USE_WHIRLPOOL &_gcry_mac_type_spec_hmac_whirlpool, #else NULL, #endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, #else NULL, #endif #ifdef USE_GOST_R_3411_12 &_gcry_mac_type_spec_hmac_stribog256, &_gcry_mac_type_spec_hmac_stribog512, #else NULL, NULL, #endif #if USE_MD2 &_gcry_mac_type_spec_hmac_md2, #else NULL, #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, #else NULL, NULL, NULL, NULL, #endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_cp, #else NULL, #endif #if USE_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #else NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #else NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #else NULL, NULL, #endif }; /* CMAC implementations start with index 201 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo201[] = { #if USE_AES &_gcry_mac_type_spec_cmac_aes, #else NULL, #endif #if USE_DES &_gcry_mac_type_spec_cmac_tripledes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, #else NULL, #endif #if USE_CAST5 &_gcry_mac_type_spec_cmac_cast5, #else NULL, #endif #if USE_BLOWFISH &_gcry_mac_type_spec_cmac_blowfish, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_cmac_seed, #else NULL, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, #else NULL, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, #else NULL, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, #else NULL, #endif #if USE_SM4 &_gcry_mac_type_spec_cmac_sm4 #else NULL #endif }; /* GMAC implementations start with index 401 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo401[] = { #if USE_AES &_gcry_mac_type_spec_gmac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_gmac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_gmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_gmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_gmac_seed #else NULL #endif }; /* Poly1305-MAC implementations start with index 501 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo501[] = { &_gcry_mac_type_spec_poly1305mac, #if USE_AES &_gcry_mac_type_spec_poly1305mac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_poly1305mac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_poly1305mac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_poly1305mac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_poly1305mac_seed #else NULL #endif }; /* Explicitly initialize this module. */ gcry_err_code_t _gcry_mac_init (void) { if (fips_mode()) { /* disable algorithms that are disallowed in fips */ int idx; gcry_mac_spec_t *spec; for (idx = 0; (spec = mac_list[idx]); idx++) if (!spec->flags.fips) spec->flags.disabled = 1; } return 0; } /* Return the spec structure for the MAC algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_mac_spec_t * spec_from_algo (int algo) { gcry_mac_spec_t *spec = NULL; if (algo >= 101 && algo < 101 + DIM(mac_list_algo101)) spec = mac_list_algo101[algo - 101]; else if (algo >= 201 && algo < 201 + DIM(mac_list_algo201)) spec = mac_list_algo201[algo - 201]; else if (algo >= 401 && algo < 401 + DIM(mac_list_algo401)) spec = mac_list_algo401[algo - 401]; else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501)) spec = mac_list_algo501[algo - 501]; #ifdef USE_GOST28147 else if (algo == GCRY_MAC_GOST28147_IMIT) spec = &_gcry_mac_type_spec_gost28147_imit; #endif if (spec) gcry_assert (spec->algo == algo); return spec; } /* Lookup a mac's spec by its name. */ static gcry_mac_spec_t * spec_from_name (const char *name) { gcry_mac_spec_t *spec; int idx; for (idx = 0; (spec = mac_list[idx]); idx++) if (!stricmp (name, spec->name)) return spec; return NULL; } /**************** * Map a string to the mac algo */ int _gcry_mac_map_name (const char *string) { gcry_mac_spec_t *spec; if (!string) return 0; /* Not found, search a matching mac name. */ spec = spec_from_name (string); if (spec) return spec->algo; return 0; } /**************** * This function simply returns the name of the algorithm or some constant * string when there is no algo. It will never return NULL. * Use the macro gcry_mac_test_algo() to check whether the algorithm * is valid. */ const char * _gcry_mac_algo_name (int algorithm) { gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); return spec ? spec->name : "?"; } static gcry_err_code_t check_mac_algo (int algorithm) { gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); if (spec && !spec->flags.disabled) return 0; return GPG_ERR_MAC_ALGO; } /**************** * Open a message digest handle for use with algorithm ALGO. */ static gcry_err_code_t mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx) { gcry_mac_spec_t *spec; gcry_err_code_t err; gcry_mac_hd_t h; spec = spec_from_algo (algo); if (!spec) return GPG_ERR_MAC_ALGO; else if (spec->flags.disabled) return GPG_ERR_MAC_ALGO; else if (!spec->ops) return GPG_ERR_MAC_ALGO; else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey || !spec->ops->read || !spec->ops->verify || !spec->ops->reset) return GPG_ERR_MAC_ALGO; if (secure) h = xtrycalloc_secure (1, sizeof (*h)); else h = xtrycalloc (1, sizeof (*h)); if (!h) return gpg_err_code_from_syserror (); h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; h->spec = spec; h->algo = algo; h->gcry_ctx = ctx; err = h->spec->ops->open (h); if (err) xfree (h); else *hd = h; return err; } static gcry_err_code_t mac_reset (gcry_mac_hd_t hd) { if (hd->spec->ops->reset) return hd->spec->ops->reset (hd); return 0; } static void mac_close (gcry_mac_hd_t hd) { if (hd->spec->ops->close) hd->spec->ops->close (hd); wipememory (hd, sizeof (*hd)); xfree (hd); } static gcry_err_code_t mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) { if (!hd->spec->ops->setkey) return GPG_ERR_INV_ARG; if (keylen > 0 && !key) return GPG_ERR_INV_ARG; return hd->spec->ops->setkey (hd, key, keylen); } static gcry_err_code_t mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) { if (!hd->spec->ops->setiv) return GPG_ERR_INV_ARG; if (ivlen > 0 && !iv) return GPG_ERR_INV_ARG; return hd->spec->ops->setiv (hd, iv, ivlen); } static gcry_err_code_t mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) { if (!hd->spec->ops->write) return GPG_ERR_INV_ARG; if (inlen > 0 && !inbuf) return GPG_ERR_INV_ARG; return hd->spec->ops->write (hd, inbuf, inlen); } static gcry_err_code_t mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen) { if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read) return GPG_ERR_INV_ARG; return hd->spec->ops->read (hd, outbuf, outlen); } static gcry_err_code_t mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) { if (!buf || buflen == 0 || !hd->spec->ops->verify) return GPG_ERR_INV_ARG; return hd->spec->ops->verify (hd, buf, buflen); } /* Create a MAC object for algorithm ALGO. FLAGS may be given as an bitwise OR of the gcry_mac_flags values. H is guaranteed to be a valid handle or NULL on error. */ gpg_err_code_t _gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_mac_hd_t hd = NULL; if ((flags & ~GCRY_MAC_FLAG_SECURE)) rc = GPG_ERR_INV_ARG; else rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx); *h = rc ? NULL : hd; return rc; } void _gcry_mac_close (gcry_mac_hd_t hd) { if (hd) mac_close (hd); } gcry_err_code_t _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) { return mac_setkey (hd, key, keylen); } gcry_err_code_t _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) { return mac_setiv (hd, iv, ivlen); } gcry_err_code_t _gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) { return mac_write (hd, inbuf, inlen); } gcry_err_code_t _gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen) { return mac_read (hd, outbuf, outlen); } gcry_err_code_t _gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) { return mac_verify (hd, buf, buflen); } int _gcry_mac_get_algo (gcry_mac_hd_t hd) { return hd->algo; } unsigned int _gcry_mac_get_algo_maclen (int algo) { gcry_mac_spec_t *spec; spec = spec_from_algo (algo); if (!spec || !spec->ops || !spec->ops->get_maclen) return 0; return spec->ops->get_maclen (algo); } unsigned int _gcry_mac_get_algo_keylen (int algo) { gcry_mac_spec_t *spec; spec = spec_from_algo (algo); if (!spec || !spec->ops || !spec->ops->get_keylen) return 0; return spec->ops->get_keylen (algo); } gcry_err_code_t _gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc; /* Currently not used. */ (void) hd; (void) buffer; (void) buflen; switch (cmd) { case GCRYCTL_RESET: rc = mac_reset (hd); break; case GCRYCTL_SET_SBOX: if (hd->spec->ops->set_extra_info) rc = hd->spec->ops->set_extra_info (hd, GCRYCTL_SET_SBOX, buffer, buflen); else rc = GPG_ERR_NOT_SUPPORTED; break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the given MAC algorithm ALGO. GCRYCTL_TEST_ALGO: Returns 0 if the specified algorithm ALGO is available for use. BUFFER and NBYTES must be zero. Note: Because this function is in most cases used to return an integer value, we can make it easier for the caller to just look at the return value. The caller will in all cases consult the value and thereby detecting whether a error occurred or not (i.e. while checking the block size) */ gcry_err_code_t _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes) { gcry_err_code_t rc = 0; unsigned int ui; switch (what) { case GCRYCTL_GET_KEYLEN: if (buffer || (!nbytes)) rc = GPG_ERR_INV_ARG; else { ui = _gcry_mac_get_algo_keylen (algo); if (ui > 0) *nbytes = (size_t) ui; else /* The only reason for an error is an invalid algo. */ rc = GPG_ERR_MAC_ALGO; } break; case GCRYCTL_TEST_ALGO: if (buffer || nbytes) rc = GPG_ERR_INV_ARG; else rc = check_mac_algo (algo); break; default: rc = GPG_ERR_INV_OP; } return rc; } + + +/* Run the self-tests for the MAC. */ +gpg_error_t +_gcry_mac_selftest (int algo, int extended, selftest_report_func_t report) +{ + gcry_err_code_t ec; + gcry_mac_spec_t *spec; + + spec = spec_from_algo (algo); + if (spec && !spec->flags.disabled && spec->ops && spec->ops->selftest) + ec = spec->ops->selftest (algo, extended, report); + else + { + ec = GPG_ERR_MAC_ALGO; + if (report) + report ("mac", algo, "module", + spec && !spec->flags.disabled? + "no selftest available" : + spec? "algorithm disabled" : + "algorithm not found"); + } + + return gpg_error (ec); +} diff --git a/src/fips.c b/src/fips.c index 1ac7f477..94ffbd20 100644 --- a/src/fips.c +++ b/src/fips.c @@ -1,856 +1,856 @@ /* fips.c - FIPS mode management * Copyright (C) 2008 Free Software Foundation, Inc. * * 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 . */ #include #include #include #include #include #include #ifdef ENABLE_HMAC_BINARY_CHECK # include #endif #ifdef HAVE_SYSLOG # include #endif /*HAVE_SYSLOG*/ #include "g10lib.h" #include "cipher-proto.h" #include "hmac256.h" /* The name of the file used to force libgcrypt into fips mode. */ #define FIPS_FORCE_FILE "/etc/gcrypt/fips_enabled" /* The states of the finite state machine used in fips mode. */ enum module_states { /* POWEROFF cannot be represented. */ STATE_POWERON = 0, STATE_INIT, STATE_SELFTEST, STATE_OPERATIONAL, STATE_ERROR, STATE_FATALERROR, STATE_SHUTDOWN }; /* Flag telling whether we are in fips mode. It uses inverse logic so that fips mode is the default unless changed by the initialization code. To check whether fips mode is enabled, use the function fips_mode()! */ int _gcry_no_fips_mode_required; /* Flag to indicate that we are in the enforced FIPS mode. */ static int enforced_fips_mode; /* If this flag is set, the application may no longer assume that the process is running in FIPS mode. This flag is protected by the FSM_LOCK. */ static int inactive_fips_mode; /* This is the lock we use to protect the FSM. */ GPGRT_LOCK_DEFINE (fsm_lock); /* The current state of the FSM. The whole state machinery is only used while in fips mode. Change this only while holding fsm_lock. */ static enum module_states current_state; static void fips_new_state (enum module_states new_state); /* Convert lowercase hex digits; assumes valid hex digits. */ #define loxtoi_1(p) (*(p) <= '9'? (*(p)- '0'): (*(p)-'a'+10)) #define loxtoi_2(p) ((loxtoi_1(p) * 16) + loxtoi_1((p)+1)) /* Returns true if P points to a lowercase hex digit. */ #define loxdigit_p(p) !!strchr ("01234567890abcdef", *(p)) /* Check whether the OS is in FIPS mode and record that in a module local variable. If FORCE is passed as true, fips mode will be enabled anyway. Note: This function is not thread-safe and should be called before any threads are created. This function may only be called once. */ void _gcry_initialize_fips_mode (int force) { static int done; gpg_error_t err; /* Make sure we are not accidentally called twice. */ if (done) { if ( fips_mode () ) { fips_new_state (STATE_FATALERROR); fips_noreturn (); } /* If not in fips mode an assert is sufficient. */ gcry_assert (!done); } done = 1; /* If the calling application explicitly requested fipsmode, do so. */ if (force) { gcry_assert (!_gcry_no_fips_mode_required); goto leave; } /* For testing the system it is useful to override the system provided detection of the FIPS mode and force FIPS mode using a file. The filename is hardwired so that there won't be any confusion on whether /etc/gcrypt/ or /usr/local/etc/gcrypt/ is actually used. The file itself may be empty. */ if ( !access (FIPS_FORCE_FILE, F_OK) ) { gcry_assert (!_gcry_no_fips_mode_required); goto leave; } /* Checking based on /proc file properties. */ { static const char procfname[] = "/proc/sys/crypto/fips_enabled"; FILE *fp; int saved_errno; fp = fopen (procfname, "r"); if (fp) { char line[256]; if (fgets (line, sizeof line, fp) && atoi (line)) { /* System is in fips mode. */ fclose (fp); gcry_assert (!_gcry_no_fips_mode_required); goto leave; } fclose (fp); } else if ((saved_errno = errno) != ENOENT && saved_errno != EACCES && !access ("/proc/version", F_OK) ) { /* Problem reading the fips file despite that we have the proc file system. We better stop right away. */ log_info ("FATAL: error reading `%s' in libgcrypt: %s\n", procfname, strerror (saved_errno)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "reading `%s' failed: %s - abort", procfname, strerror (saved_errno)); #endif /*HAVE_SYSLOG*/ abort (); } } /* Fips not not requested, set flag. */ _gcry_no_fips_mode_required = 1; leave: if (!_gcry_no_fips_mode_required) { /* Yes, we are in FIPS mode. */ FILE *fp; /* Intitialize the lock to protect the FSM. */ err = gpgrt_lock_init (&fsm_lock); if (err) { /* If that fails we can't do anything but abort the process. We need to use log_info so that the FSM won't get involved. */ log_info ("FATAL: failed to create the FSM lock in libgcrypt: %s\n", gpg_strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "creating FSM lock failed: %s - abort", gpg_strerror (err)); #endif /*HAVE_SYSLOG*/ abort (); } /* If the FIPS force files exists, is readable and has a number != 0 on its first line, we enable the enforced fips mode. */ fp = fopen (FIPS_FORCE_FILE, "r"); if (fp) { char line[256]; if (fgets (line, sizeof line, fp) && atoi (line)) enforced_fips_mode = 1; fclose (fp); } /* Now get us into the INIT state. */ fips_new_state (STATE_INIT); } return; } static void lock_fsm (void) { gpg_error_t err; err = gpgrt_lock_lock (&fsm_lock); if (err) { log_info ("FATAL: failed to acquire the FSM lock in libgrypt: %s\n", gpg_strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "acquiring FSM lock failed: %s - abort", gpg_strerror (err)); #endif /*HAVE_SYSLOG*/ abort (); } } static void unlock_fsm (void) { gpg_error_t err; err = gpgrt_lock_unlock (&fsm_lock); if (err) { log_info ("FATAL: failed to release the FSM lock in libgrypt: %s\n", gpg_strerror (err)); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "releasing FSM lock failed: %s - abort", gpg_strerror (err)); #endif /*HAVE_SYSLOG*/ abort (); } } /* Return a flag telling whether we are in the enforced fips mode. */ int _gcry_enforced_fips_mode (void) { if (!fips_mode ()) return 0; return enforced_fips_mode; } /* Set a flag telling whether we are in the enforced fips mode. */ void _gcry_set_enforced_fips_mode (void) { enforced_fips_mode = 1; } /* If we do not want to enforce the fips mode, we can set a flag so that the application may check whether it is still in fips mode. TEXT will be printed as part of a syslog message. This function may only be be called if in fips mode. */ void _gcry_inactivate_fips_mode (const char *text) { gcry_assert (fips_mode ()); if (_gcry_enforced_fips_mode () ) { /* Get us into the error state. */ fips_signal_error (text); return; } lock_fsm (); if (!inactive_fips_mode) { inactive_fips_mode = 1; unlock_fsm (); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_WARNING, "Libgcrypt warning: " "%s - FIPS mode inactivated", text); #endif /*HAVE_SYSLOG*/ } else unlock_fsm (); } /* Return the FIPS mode inactive flag. If it is true the FIPS mode is not anymore active. */ int _gcry_is_fips_mode_inactive (void) { int flag; if (!fips_mode ()) return 0; lock_fsm (); flag = inactive_fips_mode; unlock_fsm (); return flag; } static const char * state2str (enum module_states state) { const char *s; switch (state) { case STATE_POWERON: s = "Power-On"; break; case STATE_INIT: s = "Init"; break; case STATE_SELFTEST: s = "Self-Test"; break; case STATE_OPERATIONAL: s = "Operational"; break; case STATE_ERROR: s = "Error"; break; case STATE_FATALERROR: s = "Fatal-Error"; break; case STATE_SHUTDOWN: s = "Shutdown"; break; default: s = "?"; break; } return s; } /* Return true if the library is in the operational state. */ int _gcry_fips_is_operational (void) { int result; if (!fips_mode ()) result = 1; else { lock_fsm (); if (current_state == STATE_INIT) { /* If we are still in the INIT state, we need to run the selftests so that the FSM can eventually get into operational state. Given that we would need a 2-phase initialization of libgcrypt, but that has traditionally not been enforced, we use this on demand self-test checking. Note that Proper applications would do the application specific libgcrypt initialization between a gcry_check_version() and gcry_control (GCRYCTL_INITIALIZATION_FINISHED) where the latter will run the selftests. The drawback of these on-demand self-tests are a small chance that self-tests are performed by several threads; that is no problem because our FSM make sure that we won't oversee any error. */ unlock_fsm (); _gcry_fips_run_selftests (0); lock_fsm (); } result = (current_state == STATE_OPERATIONAL); unlock_fsm (); } return result; } /* This is test on whether the library is in the operational state. In contrast to _gcry_fips_is_operational this function won't do a state transition on the fly. */ int _gcry_fips_test_operational (void) { int result; if (!fips_mode ()) result = 1; else { lock_fsm (); result = (current_state == STATE_OPERATIONAL); unlock_fsm (); } return result; } /* This is a test on whether the library is in the error or operational state. */ int _gcry_fips_test_error_or_operational (void) { int result; if (!fips_mode ()) result = 1; else { lock_fsm (); result = (current_state == STATE_OPERATIONAL || current_state == STATE_ERROR); unlock_fsm (); } return result; } static void reporter (const char *domain, int algo, const char *what, const char *errtxt) { if (!errtxt && !_gcry_log_verbosity (2)) return; log_info ("libgcrypt selftest: %s %s%s (%d): %s%s%s%s\n", !strcmp (domain, "hmac")? "digest":domain, !strcmp (domain, "hmac")? "HMAC-":"", !strcmp (domain, "cipher")? _gcry_cipher_algo_name (algo) : !strcmp (domain, "digest")? _gcry_md_algo_name (algo) : !strcmp (domain, "hmac")? _gcry_md_algo_name (algo) : !strcmp (domain, "pubkey")? _gcry_pk_algo_name (algo) : "", algo, errtxt? errtxt:"Okay", what?" (":"", what? what:"", what?")":""); } /* Run self-tests for all required cipher algorithms. Return 0 on success. */ static int run_cipher_selftests (int extended) { static int algos[] = { GCRY_CIPHER_3DES, GCRY_CIPHER_AES128, GCRY_CIPHER_AES192, GCRY_CIPHER_AES256, 0 }; int idx; gpg_error_t err; int anyerr = 0; for (idx=0; algos[idx]; idx++) { err = _gcry_cipher_selftest (algos[idx], extended, reporter); reporter ("cipher", algos[idx], NULL, err? gpg_strerror (err):NULL); if (err) anyerr = 1; } return anyerr; } /* Run self-tests for all required hash algorithms. Return 0 on success. */ static int run_digest_selftests (int extended) { static int algos[] = { GCRY_MD_SHA1, GCRY_MD_SHA224, GCRY_MD_SHA256, GCRY_MD_SHA384, GCRY_MD_SHA512, 0 }; int idx; gpg_error_t err; int anyerr = 0; for (idx=0; algos[idx]; idx++) { err = _gcry_md_selftest (algos[idx], extended, reporter); reporter ("digest", algos[idx], NULL, err? gpg_strerror (err):NULL); if (err) anyerr = 1; } return anyerr; } -/* Run self-tests for all HMAC algorithms. Return 0 on success. */ +/* Run self-tests for MAC algorithms. Return 0 on success. */ static int -run_hmac_selftests (int extended) +run_mac_selftests (int extended) { static int algos[] = { - GCRY_MD_SHA1, - GCRY_MD_SHA224, - 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, + GCRY_MAC_HMAC_SHA1, + GCRY_MAC_HMAC_SHA224, + GCRY_MAC_HMAC_SHA256, + GCRY_MAC_HMAC_SHA384, + GCRY_MAC_HMAC_SHA512, + GCRY_MAC_HMAC_SHA3_224, + GCRY_MAC_HMAC_SHA3_256, + GCRY_MAC_HMAC_SHA3_384, + GCRY_MAC_HMAC_SHA3_512, 0 }; int idx; gpg_error_t err; int anyerr = 0; for (idx=0; algos[idx]; idx++) { - err = _gcry_hmac_selftest (algos[idx], extended, reporter); - reporter ("hmac", algos[idx], NULL, + err = _gcry_mac_selftest (algos[idx], extended, reporter); + reporter ("mac", algos[idx], NULL, err? gpg_strerror (err):NULL); if (err) anyerr = 1; } return anyerr; } /* Run self-tests for all required public key algorithms. Return 0 on success. */ static int run_pubkey_selftests (int extended) { static int algos[] = { GCRY_PK_RSA, GCRY_PK_DSA, GCRY_PK_ECC, 0 }; int idx; gpg_error_t err; int anyerr = 0; for (idx=0; algos[idx]; idx++) { err = _gcry_pk_selftest (algos[idx], extended, reporter); reporter ("pubkey", algos[idx], NULL, err? gpg_strerror (err):NULL); if (err) anyerr = 1; } return anyerr; } /* Run self-tests for the random number generator. Returns 0 on success. */ static int run_random_selftests (void) { gpg_error_t err; err = _gcry_random_selftest (reporter); reporter ("random", 0, NULL, err? gpg_strerror (err):NULL); return !!err; } /* Run an integrity check on the binary. Returns 0 on success. */ static int check_binary_integrity (void) { #ifdef ENABLE_HMAC_BINARY_CHECK gpg_error_t err; Dl_info info; unsigned char digest[32]; int dlen; char *fname = NULL; const char key[] = "What am I, a doctor or a moonshuttle conductor?"; if (!dladdr ("gcry_check_version", &info)) err = gpg_error_from_syserror (); else { dlen = _gcry_hmac256_file (digest, sizeof digest, info.dli_fname, key, strlen (key)); if (dlen < 0) err = gpg_error_from_syserror (); else if (dlen != 32) err = gpg_error (GPG_ERR_INTERNAL); else { fname = xtrymalloc (strlen (info.dli_fname) + 1 + 5 + 1 ); if (!fname) err = gpg_error_from_syserror (); else { FILE *fp; char *p; /* Prefix the basename with a dot. */ strcpy (fname, info.dli_fname); p = strrchr (fname, '/'); if (p) p++; else p = fname; memmove (p+1, p, strlen (p)+1); *p = '.'; strcat (fname, ".hmac"); /* Open the file. */ fp = fopen (fname, "r"); if (!fp) err = gpg_error_from_syserror (); else { /* A buffer of 64 bytes plus one for a LF and one to detect garbage. */ unsigned char buffer[64+1+1]; const unsigned char *s; int n; /* The HMAC files consists of lowercase hex digits with an optional trailing linefeed or optional with two trailing spaces. The latter format allows the use of the usual sha1sum format. Fail if there is any garbage. */ err = gpg_error (GPG_ERR_SELFTEST_FAILED); n = fread (buffer, 1, sizeof buffer, fp); if (n == 64 || (n == 65 && buffer[64] == '\n') || (n == 66 && buffer[64] == ' ' && buffer[65] == ' ')) { buffer[64] = 0; for (n=0, s= buffer; n < 32 && loxdigit_p (s) && loxdigit_p (s+1); n++, s += 2) buffer[n] = loxtoi_2 (s); if ( n == 32 && !memcmp (digest, buffer, 32) ) err = 0; } fclose (fp); } } } } reporter ("binary", 0, fname, err? gpg_strerror (err):NULL); #ifdef HAVE_SYSLOG if (err) syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "integrity check using `%s' failed: %s", fname? fname:"[?]", gpg_strerror (err)); #endif /*HAVE_SYSLOG*/ xfree (fname); return !!err; #else return 0; #endif } /* Run the self-tests. If EXTENDED is true, extended versions of the selftest are run, that is more tests than required by FIPS. */ gpg_err_code_t _gcry_fips_run_selftests (int extended) { enum module_states result = STATE_ERROR; gcry_err_code_t ec = GPG_ERR_SELFTEST_FAILED; if (fips_mode ()) fips_new_state (STATE_SELFTEST); if (run_cipher_selftests (extended)) goto leave; if (run_digest_selftests (extended)) goto leave; - if (run_hmac_selftests (extended)) + if (run_mac_selftests (extended)) goto leave; /* Run random tests before the pubkey tests because the latter require random. */ if (run_random_selftests ()) goto leave; if (run_pubkey_selftests (extended)) goto leave; if (fips_mode ()) { /* Now check the integrity of the binary. We do this this after having checked the HMAC code. */ if (check_binary_integrity ()) goto leave; } /* All selftests passed. */ result = STATE_OPERATIONAL; ec = 0; leave: if (fips_mode ()) fips_new_state (result); return ec; } /* This function is used to tell the FSM about errors in the library. The FSM will be put into an error state. This function should not be called directly but by one of the macros fips_signal_error (description) fips_signal_fatal_error (description) where DESCRIPTION is a string describing the error. */ void _gcry_fips_signal_error (const char *srcfile, int srcline, const char *srcfunc, int is_fatal, const char *description) { if (!fips_mode ()) return; /* Not required. */ /* Set new state before printing an error. */ fips_new_state (is_fatal? STATE_FATALERROR : STATE_ERROR); /* Print error. */ log_info ("%serror in libgcrypt, file %s, line %d%s%s: %s\n", is_fatal? "fatal ":"", srcfile, srcline, srcfunc? ", function ":"", srcfunc? srcfunc:"", description? description : "no description available"); #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: " "%serror in file %s, line %d%s%s: %s", is_fatal? "fatal ":"", srcfile, srcline, srcfunc? ", function ":"", srcfunc? srcfunc:"", description? description : "no description available"); #endif /*HAVE_SYSLOG*/ } /* Perform a state transition to NEW_STATE. If this is an invalid transition, the module will go into a fatal error state. */ static void fips_new_state (enum module_states new_state) { int ok = 0; enum module_states last_state; lock_fsm (); last_state = current_state; switch (current_state) { case STATE_POWERON: if (new_state == STATE_INIT || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_INIT: if (new_state == STATE_SELFTEST || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_SELFTEST: if (new_state == STATE_OPERATIONAL || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_OPERATIONAL: if (new_state == STATE_SHUTDOWN || new_state == STATE_SELFTEST || new_state == STATE_ERROR || new_state == STATE_FATALERROR) ok = 1; break; case STATE_ERROR: if (new_state == STATE_SHUTDOWN || new_state == STATE_ERROR || new_state == STATE_FATALERROR || new_state == STATE_SELFTEST) ok = 1; break; case STATE_FATALERROR: if (new_state == STATE_SHUTDOWN ) ok = 1; break; case STATE_SHUTDOWN: /* We won't see any transition *from* Shutdown because the only allowed new state is Power-Off and that one can't be represented. */ break; } if (ok) { current_state = new_state; } unlock_fsm (); if (!ok || _gcry_log_verbosity (2)) log_info ("libgcrypt state transition %s => %s %s\n", state2str (last_state), state2str (new_state), ok? "granted":"denied"); if (!ok) { /* Invalid state transition. Halting library. */ #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt error: invalid state transition %s => %s", state2str (last_state), state2str (new_state)); #endif /*HAVE_SYSLOG*/ fips_noreturn (); } else if (new_state == STATE_ERROR || new_state == STATE_FATALERROR) { #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_WARNING, "Libgcrypt notice: state transition %s => %s", state2str (last_state), state2str (new_state)); #endif /*HAVE_SYSLOG*/ } } /* This function should be called to ensure that the execution shall not continue. */ void _gcry_fips_noreturn (void) { #ifdef HAVE_SYSLOG syslog (LOG_USER|LOG_ERR, "Libgcrypt terminated the application"); #endif /*HAVE_SYSLOG*/ fflush (NULL); abort (); /*NOTREACHED*/ }