diff --git a/cipher/arcfour.c b/cipher/arcfour.c index 9e71857c..353de00b 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -1,215 +1,216 @@ /* arcfour.c - The arcfour stream cipher * Copyright (C) 2000, 2001, 2002, 2003 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * For a description of the algorithm, see: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. * ISBN 0-471-11709-9. Pages 397 ff. */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" +#include "cipher-internal.h" /* USE_AMD64_ASM indicates whether to use AMD64 assembly code. */ #undef USE_AMD64_ASM #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AMD64_ASM 1 #endif static const char *selftest(void); #ifdef USE_AMD64_ASM typedef struct { u32 sbox[256]; u32 idx_i, idx_j; } ARCFOUR_context; void _gcry_arcfour_amd64(void *key, size_t len, const byte *indata, byte *outdata); static void encrypt_stream (void *context, byte *outbuf, const byte *inbuf, size_t length) { _gcry_arcfour_amd64 (context, length, inbuf, outbuf ); } #else /*!USE_AMD64_ASM*/ typedef struct { byte sbox[256]; int idx_i, idx_j; } ARCFOUR_context; static void do_encrypt_stream( ARCFOUR_context *ctx, byte *outbuf, const byte *inbuf, size_t length ) { #ifndef __i386__ register unsigned int i = ctx->idx_i; register byte j = ctx->idx_j; register byte *sbox = ctx->sbox; register byte t, u; while ( length-- ) { i++; t = sbox[(byte)i]; j += t; u = sbox[j]; sbox[(byte)i] = u; u += t; sbox[j] = t; *outbuf++ = sbox[u] ^ *inbuf++; } ctx->idx_i = (byte)i; ctx->idx_j = (byte)j; #else /*__i386__*/ /* Old implementation of arcfour is faster on i386 than the version above. * This is because version above increases register pressure which on i386 * would push some of the variables to memory/stack. Therefore keep this * version for i386 to avoid regressing performance. */ register int i = ctx->idx_i; register int j = ctx->idx_j; register byte *sbox = ctx->sbox; register int t; while ( length-- ) { i++; i = i & 255; /* The and-op seems to be faster than the mod-op. */ j += sbox[i]; j &= 255; t = sbox[i]; sbox[i] = sbox[j]; sbox[j] = t; *outbuf++ = *inbuf++ ^ sbox[(sbox[i] + sbox[j]) & 255]; } ctx->idx_i = i; ctx->idx_j = j; #endif } static void encrypt_stream (void *context, byte *outbuf, const byte *inbuf, size_t length) { ARCFOUR_context *ctx = (ARCFOUR_context *) context; do_encrypt_stream (ctx, outbuf, inbuf, length ); _gcry_burn_stack (64); } #endif /*!USE_AMD64_ASM*/ static gcry_err_code_t do_arcfour_setkey (void *context, const byte *key, unsigned int keylen) { static int initialized; static const char* selftest_failed; int i, j; byte karr[256]; ARCFOUR_context *ctx = (ARCFOUR_context *) context; if (!initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) log_error ("ARCFOUR selftest failed (%s)\n", selftest_failed ); } if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; if( keylen < 40/8 ) /* we want at least 40 bits */ return GPG_ERR_INV_KEYLEN; ctx->idx_i = ctx->idx_j = 0; for (i=0; i < 256; i++ ) ctx->sbox[i] = i; for (i=j=0; i < 256; i++,j++ ) { if (j >= keylen) j = 0; karr[i] = key[j]; } for (i=j=0; i < 256; i++ ) { int t; j = (j + ctx->sbox[i] + karr[i]) & 255; t = ctx->sbox[i]; ctx->sbox[i] = ctx->sbox[j]; ctx->sbox[j] = t; } wipememory( karr, sizeof(karr) ); return GPG_ERR_NO_ERROR; } static gcry_err_code_t arcfour_setkey ( void *context, const byte *key, unsigned int keylen, cipher_bulk_ops_t *bulk_ops ) { ARCFOUR_context *ctx = (ARCFOUR_context *) context; gcry_err_code_t rc = do_arcfour_setkey (ctx, key, keylen ); (void)bulk_ops; return rc; } static const char* selftest(void) { ARCFOUR_context ctx; byte scratch[16]; /* Test vector from Cryptlib labeled there: "from the State/Commerce Department". */ static const byte key_1[] = { 0x61, 0x8A, 0x63, 0xD2, 0xFB }; static const byte plaintext_1[] = { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C }; static const byte ciphertext_1[] = { 0xF1, 0x38, 0x29, 0xC9, 0xDE }; arcfour_setkey( &ctx, key_1, sizeof(key_1), NULL); encrypt_stream( &ctx, scratch, plaintext_1, sizeof(plaintext_1)); if ( memcmp (scratch, ciphertext_1, sizeof (ciphertext_1))) return "Arcfour encryption test 1 failed."; arcfour_setkey( &ctx, key_1, sizeof(key_1), NULL); encrypt_stream(&ctx, scratch, scratch, sizeof(plaintext_1)); /* decrypt */ if ( memcmp (scratch, plaintext_1, sizeof (plaintext_1))) return "Arcfour decryption test 1 failed."; return NULL; } gcry_cipher_spec_t _gcry_cipher_spec_arcfour = { GCRY_CIPHER_ARCFOUR, {0, 0}, "ARCFOUR", NULL, NULL, 1, 128, sizeof (ARCFOUR_context), arcfour_setkey, NULL, NULL, encrypt_stream, encrypt_stream, }; diff --git a/cipher/gost28147.c b/cipher/gost28147.c index 1bafe317..9445b378 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -1,552 +1,553 @@ /* 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 "cipher-internal.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/idea.c b/cipher/idea.c index a503c08f..0a810818 100644 --- a/cipher/idea.c +++ b/cipher/idea.c @@ -1,381 +1,382 @@ /* idea.c - IDEA function * Copyright 1997, 1998, 1999, 2001 Werner Koch (dd9jn) * Copyright 2013 g10 Code GmbH * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * WERNER KOCH BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * Except as contained in this notice, the name of Werner Koch shall not be * used in advertising or otherwise to promote the sale, use or other dealings * in this Software without prior written authorization from Werner Koch. * * Patents on IDEA have expired: * Europe: EP0482154 on 2011-05-16, * Japan: JP3225440 on 2011-05-16, * U.S.: 5,214,703 on 2012-01-07. */ /* * Please see http://www.noepatents.org/ to learn why software patents * are bad for society and what you can do to fight them. * * The code herein is based on the one from: * Bruce Schneier: Applied Cryptography. John Wiley & Sons, 1996. * ISBN 0-471-11709-9. */ #include #include #include #include #include #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" +#include "cipher-internal.h" #define IDEA_KEYSIZE 16 #define IDEA_BLOCKSIZE 8 #define IDEA_ROUNDS 8 #define IDEA_KEYLEN (6*IDEA_ROUNDS+4) typedef struct { u16 ek[IDEA_KEYLEN]; u16 dk[IDEA_KEYLEN]; int have_dk; } IDEA_context; static const char *selftest(void); static u16 mul_inv( u16 x ) { u16 t0, t1; u16 q, y; if( x < 2 ) return x; t1 = 0x10001UL / x; y = 0x10001UL % x; if( y == 1 ) return (1-t1) & 0xffff; t0 = 1; do { q = x / y; x = x % y; t0 += q * t1; if( x == 1 ) return t0; q = y / x; y = y % x; t1 += q * t0; } while( y != 1 ); return (1-t1) & 0xffff; } static void expand_key( const byte *userkey, u16 *ek ) { int i,j; for(j=0; j < 8; j++ ) { ek[j] = (*userkey << 8) + userkey[1]; userkey += 2; } for(i=0; j < IDEA_KEYLEN; j++ ) { i++; ek[i+7] = ek[i&7] << 9 | ek[(i+1)&7] >> 7; ek += i & 8; i &= 7; } } static void invert_key( u16 *ek, u16 dk[IDEA_KEYLEN] ) { int i; u16 t1, t2, t3; u16 temp[IDEA_KEYLEN]; u16 *p = temp + IDEA_KEYLEN; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t3; *--p = t2; *--p = t1; for(i=0; i < IDEA_ROUNDS-1; i++ ) { t1 = *ek++; *--p = *ek++; *--p = t1; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t2; *--p = t3; *--p = t1; } t1 = *ek++; *--p = *ek++; *--p = t1; t1 = mul_inv( *ek++ ); t2 = -*ek++; t3 = -*ek++; *--p = mul_inv( *ek++ ); *--p = t3; *--p = t2; *--p = t1; memcpy(dk, temp, sizeof(temp) ); wipememory(temp, sizeof(temp)); } static void cipher( byte *outbuf, const byte *inbuf, u16 *key ) { u16 s2, s3; u16 in[4]; int r = IDEA_ROUNDS; #define x1 (in[0]) #define x2 (in[1]) #define x3 (in[2]) #define x4 (in[3]) #define MUL(x,y) \ do {u16 _t16; u32 _t32; \ if( (_t16 = (y)) ) { \ if( (x = (x)&0xffff) ) { \ _t32 = (u32)x * _t16; \ x = _t32 & 0xffff; \ _t16 = _t32 >> 16; \ x = ((x)-_t16) + (x<_t16?1:0); \ } \ else { \ x = 1 - _t16; \ } \ } \ else { \ x = 1 - x; \ } \ } while(0) memcpy (in, inbuf, sizeof in); #ifndef WORDS_BIGENDIAN x1 = (x1>>8) | (x1<<8); x2 = (x2>>8) | (x2<<8); x3 = (x3>>8) | (x3<<8); x4 = (x4>>8) | (x4<<8); #endif do { MUL(x1, *key++); x2 += *key++; x3 += *key++; MUL(x4, *key++ ); s3 = x3; x3 ^= x1; MUL(x3, *key++); s2 = x2; x2 ^=x4; x2 += x3; MUL(x2, *key++); x3 += x2; x1 ^= x2; x4 ^= x3; x2 ^= s3; x3 ^= s2; } while( --r ); MUL(x1, *key++); x3 += *key++; x2 += *key++; MUL(x4, *key); #ifndef WORDS_BIGENDIAN x1 = (x1>>8) | (x1<<8); x2 = (x2>>8) | (x2<<8); x3 = (x3>>8) | (x3<<8); x4 = (x4>>8) | (x4<<8); #endif memcpy (outbuf+0, &x1, 2); memcpy (outbuf+2, &x3, 2); memcpy (outbuf+4, &x2, 2); memcpy (outbuf+6, &x4, 2); #undef MUL #undef x1 #undef x2 #undef x3 #undef x4 } static int do_setkey( IDEA_context *c, const byte *key, unsigned int keylen ) { static int initialized = 0; static const char *selftest_failed = 0; if( !initialized ) { initialized = 1; selftest_failed = selftest(); if( selftest_failed ) log_error( "%s\n", selftest_failed ); } if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; assert(keylen == 16); c->have_dk = 0; expand_key( key, c->ek ); invert_key( c->ek, c->dk ); return 0; } static gcry_err_code_t idea_setkey (void *context, const byte *key, unsigned int keylen, cipher_bulk_ops_t *bulk_ops) { IDEA_context *ctx = context; int rc = do_setkey (ctx, key, keylen); (void)bulk_ops; _gcry_burn_stack (23+6*sizeof(void*)); return rc; } static void encrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) { cipher( outbuf, inbuf, c->ek ); } static unsigned int idea_encrypt (void *context, byte *out, const byte *in) { IDEA_context *ctx = context; encrypt_block (ctx, out, in); return /*burn_stack*/ (24+3*sizeof (void*)); } static void decrypt_block( IDEA_context *c, byte *outbuf, const byte *inbuf ) { if( !c->have_dk ) { c->have_dk = 1; invert_key( c->ek, c->dk ); } cipher( outbuf, inbuf, c->dk ); } static unsigned int idea_decrypt (void *context, byte *out, const byte *in) { IDEA_context *ctx = context; decrypt_block (ctx, out, in); return /*burn_stack*/ (24+3*sizeof (void*)); } static const char * selftest( void ) { static struct { byte key[16]; byte plain[8]; byte cipher[8]; } test_vectors[] = { { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x03 }, { 0x11, 0xFB, 0xED, 0x2B, 0x01, 0x98, 0x6D, 0xE5 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x54, 0x0E, 0x5F, 0xEA, 0x18, 0xC2, 0xF8, 0xB1 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x00, 0x19, 0x32, 0x4B, 0x64, 0x7D, 0x96, 0xAF }, { 0x9F, 0x0A, 0x0A, 0xB6, 0xE1, 0x0C, 0xED, 0x78 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0xF5, 0x20, 0x2D, 0x5B, 0x9C, 0x67, 0x1B, 0x08 }, { 0xCF, 0x18, 0xFD, 0x73, 0x55, 0xE2, 0xC5, 0xC5 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0xFA, 0xE6, 0xD2, 0xBE, 0xAA, 0x96, 0x82, 0x6E }, { 0x85, 0xDF, 0x52, 0x00, 0x56, 0x08, 0x19, 0x3D } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x0A, 0x14, 0x1E, 0x28, 0x32, 0x3C, 0x46, 0x50 }, { 0x2F, 0x7D, 0xE7, 0x50, 0x21, 0x2F, 0xB7, 0x34 } }, { { 0x00, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00, 0x07, 0x00, 0x08 }, { 0x05, 0x0A, 0x0F, 0x14, 0x19, 0x1E, 0x23, 0x28 }, { 0x7B, 0x73, 0x14, 0x92, 0x5D, 0xE5, 0x9C, 0x09 } }, { { 0x00, 0x05, 0x00, 0x0A, 0x00, 0x0F, 0x00, 0x14, 0x00, 0x19, 0x00, 0x1E, 0x00, 0x23, 0x00, 0x28 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x3E, 0xC0, 0x47, 0x80, 0xBE, 0xFF, 0x6E, 0x20 } }, { { 0x3A, 0x98, 0x4E, 0x20, 0x00, 0x19, 0x5D, 0xB3, 0x2E, 0xE5, 0x01, 0xC8, 0xC4, 0x7C, 0xEA, 0x60 }, { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 }, { 0x97, 0xBC, 0xD8, 0x20, 0x07, 0x80, 0xDA, 0x86 } }, { { 0x00, 0x64, 0x00, 0xC8, 0x01, 0x2C, 0x01, 0x90, 0x01, 0xF4, 0x02, 0x58, 0x02, 0xBC, 0x03, 0x20 }, { 0x05, 0x32, 0x0A, 0x64, 0x14, 0xC8, 0x19, 0xFA }, { 0x65, 0xBE, 0x87, 0xE7, 0xA2, 0x53, 0x8A, 0xED } }, { { 0x9D, 0x40, 0x75, 0xC1, 0x03, 0xBC, 0x32, 0x2A, 0xFB, 0x03, 0xE7, 0xBE, 0x6A, 0xB3, 0x00, 0x06 }, { 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08 }, { 0xF5, 0xDB, 0x1A, 0xC4, 0x5E, 0x5E, 0xF9, 0xF9 } } }; IDEA_context c; byte buffer[8]; int i; for(i=0; i < DIM(test_vectors); i++ ) { do_setkey( &c, test_vectors[i].key, 16 ); encrypt_block( &c, buffer, test_vectors[i].plain ); if( memcmp( buffer, test_vectors[i].cipher, 8 ) ) return "IDEA test encryption failed."; decrypt_block( &c, buffer, test_vectors[i].cipher ); if( memcmp( buffer, test_vectors[i].plain, 8 ) ) return "IDEA test decryption failed."; } return NULL; } gcry_cipher_spec_t _gcry_cipher_spec_idea = { GCRY_CIPHER_IDEA, {0, 0}, "IDEA", NULL, NULL, IDEA_BLOCKSIZE, 128, sizeof (IDEA_context), idea_setkey, idea_encrypt, idea_decrypt }; diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c index d4760bc2..8d5d5ca3 100644 --- a/cipher/mac-cmac.c +++ b/cipher/mac-cmac.c @@ -1,524 +1,524 @@ /* mac-cmac.c - CMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * 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 "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 secure = (h->magic == CTX_MAC_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)); } /* Check one CMAC with MAC ALGO using the regular MAC * API. (DATA,DATALEN) is the data to be MACed, (KEY,KEYLEN) the key * and (EXPECT,EXPECTLEN) the expected result. Returns NULL on * success or a string describing the failure. */ static const char * check_one (int algo, const char *data, size_t datalen, const char *key, size_t keylen, const char *expect, size_t expectlen) { gcry_mac_hd_t hd; unsigned char mac[512]; /* hardcoded to avoid allocation */ unsigned int maclen; size_t macoutlen; int i; gcry_error_t err = 0; err = _gcry_mac_open (&hd, algo, 0, NULL); if (err) return "gcry_mac_open failed"; i = _gcry_mac_get_algo (hd); if (i != algo) return "gcry_mac_get_algo failed"; maclen = _gcry_mac_get_algo_maclen (algo); if (maclen < 1 || maclen > 500) return "gcry_mac_get_algo_maclen failed"; if (maclen != expectlen) return "invalid tests data"; err = _gcry_mac_setkey (hd, key, keylen); if (err) { _gcry_mac_close (hd); return "gcry_mac_setkey failed"; } err = _gcry_mac_write (hd, data, datalen); if (err) { _gcry_mac_close (hd); return "gcry_mac_write failed"; } err = _gcry_mac_verify (hd, expect, maclen); if (err) { _gcry_mac_close (hd); return "gcry_mac_verify failed"; } macoutlen = maclen; err = _gcry_mac_read (hd, mac, &macoutlen); _gcry_mac_close (hd); if (err) return "gcry_mac_read failed"; if (memcmp (mac, expect, maclen)) return "does not match"; return NULL; } /* * CMAC AES and DES test vectors are from * http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica \ * tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ static gpg_err_code_t selftests_cmac_3des (int extended, selftest_report_func_t report) { static const struct { const char *desc; const char *data; const char *key; const char *expect; } tv[] = { { "Basic 3DES", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x74\x3d\xdb\xe0\xce\x2d\xc2\xed" }, { "Extended 3DES #1", "", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\xb7\xa6\x88\xe1\x22\xff\xaf\x95" }, { "Extended 3DES #2", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x8e\x8f\x29\x31\x36\x28\x37\x97" }, { "Extended 3DES #3", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", "\x8a\xa8\x3b\xf8\xcb\xda\x10\x62\x0b\xc1\xbf\x19\xfb\xb6\xcd\x58" "\xbc\x31\x3d\x4a\x37\x1c\xa8\xb5", "\x33\xe6\xb1\x09\x24\x00\xea\xe5" }, { "Extended 3DES #4", "", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\xbd\x2e\xbf\x9a\x3b\xa0\x03\x61" }, { "Extended 3DES #5", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x4f\xf2\xab\x81\x3c\x53\xce\x83" }, { "Extended 3DES #6", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x62\xdd\x1b\x47\x19\x02\xbd\x4e" }, { "Extended 3DES #7", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51", "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5\x8a\x3d\x10\xba\x80\x57\x0d\x38" "\x4c\xf1\x51\x34\xa2\x85\x0d\xd5", "\x31\xb1\xe4\x31\xda\xbc\x4e\xb8" }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MAC_CMAC_3DES, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, 8); if (errtxt) goto failed; if (!extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("cmac", GCRY_MAC_CMAC_3DES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t selftests_cmac_aes (int extended, selftest_report_func_t report) { static const struct { const char *desc; const char *data; const char *key; const char *expect; } tv[] = { { "Basic AES128", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\xdf\xa6\x67\x47\xde\x9a\xe6\x30\x30\xca\x32\x61\x14\x97\xc8\x27" }, { "Basic AES192", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\x8a\x1d\xe5\xbe\x2e\xb3\x1a\xad\x08\x9a\x82\xe6\xee\x90\x8b\x0e" }, { "Basic AES256", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\xaa\xf3\xd8\xf1\xde\x56\x40\xc2\x32\xf5\xb1\x69\xb9\xc9\x11\xe6" }, { "Extended AES #1", "", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\xbb\x1d\x69\x29\xe9\x59\x37\x28\x7f\xa3\x7d\x12\x9b\x75\x67\x46" }, { "Extended AES #2", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\x9e\x99\xa7\xbf\x31\xe7\x10\x90\x06\x62\xf6\x5e\x61\x7c\x51\x84" }, { "Extended AES #3", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\xe1\x99\x21\x90\x54\x9f\x6e\xd5\x69\x6a\x2c\x05\x6c\x31\x54\x10" }, { "Extended AES #4", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\x07\x0a\x16\xb4\x6b\x4d\x41\x44\xf7\x9b\xdd\x9d\xd0\x4a\x28\x7c" }, { "Extended AES #5", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", "\x51\xf0\xbe\xbf\x7e\x3b\x9d\x92\xfc\x49\x74\x17\x79\x36\x3c\xfe" }, { "Extended AES #6", "", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\xd1\x7d\xdf\x46\xad\xaa\xcd\xe5\x31\xca\xc4\x83\xde\x7a\x93\x67" }, { "Extended AES #7", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a" "\xae\x2d\x8a\x57\x1e\x03\xac\x9c\x9e\xb7\x6f\xac\x45\xaf\x8e\x51" "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11\xe5\xfb\xc1\x19\x1a\x0a\x52\xef" "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17\xad\x2b\x41\x7b\xe6\x6c\x37\x10", "\x8e\x73\xb0\xf7\xda\x0e\x64\x52\xc8\x10\xf3\x2b\x80\x90\x79\xe5" "\x62\xf8\xea\xd2\x52\x2c\x6b\x7b", "\xa1\xd5\xdf\x0e\xed\x79\x0f\x79\x4d\x77\x58\x96\x59\xf3\x9a\x11" }, { "Extended AES #8", "", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\x02\x89\x62\xf6\x1b\x7b\xf8\x9e\xfc\x6b\x55\x1f\x46\x67\xd9\x83" }, { "Extended AES #9", "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96\xe9\x3d\x7e\x11\x73\x93\x17\x2a", "\x60\x3d\xeb\x10\x15\xca\x71\xbe\x2b\x73\xae\xf0\x85\x7d\x77\x81" "\x1f\x35\x2c\x07\x3b\x61\x08\xd7\x2d\x98\x10\xa3\x09\x14\xdf\xf4", "\x28\xa7\x02\x3f\x45\x2e\x8f\x82\xbd\x4b\xf2\x8d\x8c\x37\xc3\x5c" }, { NULL } }; const char *what; const char *errtxt; int tvidx; for (tvidx=0; tv[tvidx].desc; tvidx++) { what = tv[tvidx].desc; errtxt = check_one (GCRY_MAC_CMAC_AES, tv[tvidx].data, strlen (tv[tvidx].data), tv[tvidx].key, strlen (tv[tvidx].key), tv[tvidx].expect, strlen (tv[tvidx].expect)); if (errtxt) goto failed; if (tvidx >= 2 && !extended) break; } return 0; /* Succeeded. */ failed: if (report) report ("cmac", GCRY_MAC_CMAC_AES, what, errtxt); return GPG_ERR_SELFTEST_FAILED; } static gpg_err_code_t cmac_selftest (int algo, int extended, selftest_report_func_t report) { gpg_err_code_t ec; switch (algo) { case GCRY_MAC_CMAC_3DES: ec = selftests_cmac_3des (extended, report); break; case GCRY_MAC_CMAC_AES: ec = selftests_cmac_aes (extended, report); break; default: ec = GPG_ERR_MAC_ALGO; break; } return ec; } 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, cmac_selftest }; #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 b9805eea..e04c6d1e 100644 --- a/cipher/mac-gmac.c +++ b/cipher/mac-gmac.c @@ -1,187 +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 secure = (h->magic == CTX_MAC_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 e38a74c9..4e10dd2c 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -1,1495 +1,1495 @@ /* mac-hmac.c - HMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * 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 "g10lib.h" #include "./mac-internal.h" #include "bufhelp.h" #include "cipher.h" #include "hmac256.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); + int secure = (h->magic == CTX_MAC_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; } } /* 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; } 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, 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 d907a46f..e49885be 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -1,275 +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 +#define CTX_MAC_MAGIC_NORMAL 0x59d9b8af +#define CTX_MAC_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 d27a31c6..46ea735f 100644 --- a/cipher/mac-poly1305.c +++ b/cipher/mac-poly1305.c @@ -1,364 +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); + int secure = (h->magic == CTX_MAC_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, }; 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 e274b356..babe99e3 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -1,808 +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->magic = secure ? CTX_MAC_MAGIC_SECURE : CTX_MAC_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/cipher/rfc2268.c b/cipher/rfc2268.c index 348c4d41..f018b640 100644 --- a/cipher/rfc2268.c +++ b/cipher/rfc2268.c @@ -1,377 +1,378 @@ /* rfc2268.c - The cipher described in rfc2268; aka Ron's Cipher 2. * Copyright (C) 2003 Nikos Mavroyanopoulos * Copyright (C) 2004 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */ /* This implementation was written by Nikos Mavroyanopoulos for GNUTLS * as a Libgcrypt module (gnutls/lib/x509/rc2.c) and later adapted for * direct use by Libgcrypt by Werner Koch. This implementation is * only useful for pkcs#12 decryption. * * The implementation here is based on Peter Gutmann's RRC.2 paper. */ #include #include #include #include #include "g10lib.h" #include "types.h" #include "cipher.h" +#include "cipher-internal.h" #define RFC2268_BLOCKSIZE 8 typedef struct { u16 S[64]; } RFC2268_context; static const unsigned char rfc2268_sbox[] = { 217, 120, 249, 196, 25, 221, 181, 237, 40, 233, 253, 121, 74, 160, 216, 157, 198, 126, 55, 131, 43, 118, 83, 142, 98, 76, 100, 136, 68, 139, 251, 162, 23, 154, 89, 245, 135, 179, 79, 19, 97, 69, 109, 141, 9, 129, 125, 50, 189, 143, 64, 235, 134, 183, 123, 11, 240, 149, 33, 34, 92, 107, 78, 130, 84, 214, 101, 147, 206, 96, 178, 28, 115, 86, 192, 20, 167, 140, 241, 220, 18, 117, 202, 31, 59, 190, 228, 209, 66, 61, 212, 48, 163, 60, 182, 38, 111, 191, 14, 218, 70, 105, 7, 87, 39, 242, 29, 155, 188, 148, 67, 3, 248, 17, 199, 246, 144, 239, 62, 231, 6, 195, 213, 47, 200, 102, 30, 215, 8, 232, 234, 222, 128, 82, 238, 247, 132, 170, 114, 172, 53, 77, 106, 42, 150, 26, 210, 113, 90, 21, 73, 116, 75, 159, 208, 94, 4, 24, 164, 236, 194, 224, 65, 110, 15, 81, 203, 204, 36, 145, 175, 80, 161, 244, 112, 57, 153, 124, 58, 133, 35, 184, 180, 122, 252, 2, 54, 91, 37, 85, 151, 49, 45, 93, 250, 152, 227, 138, 146, 174, 5, 223, 41, 16, 103, 108, 186, 201, 211, 0, 230, 207, 225, 158, 168, 44, 99, 22, 1, 63, 88, 226, 137, 169, 13, 56, 52, 27, 171, 51, 255, 176, 187, 72, 12, 95, 185, 177, 205, 46, 197, 243, 219, 71, 229, 165, 156, 119, 10, 166, 32, 104, 254, 127, 193, 173 }; #define rotl16(x,n) (((x) << ((u16)(n))) | ((x) >> (16 - (u16)(n)))) #define rotr16(x,n) (((x) >> ((u16)(n))) | ((x) << (16 - (u16)(n)))) static const char *selftest (void); static void do_encrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) { RFC2268_context *ctx = context; register int i, j; u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; word0 = (word0 << 8) | inbuf[1]; word0 = (word0 << 8) | inbuf[0]; word1 = (word1 << 8) | inbuf[3]; word1 = (word1 << 8) | inbuf[2]; word2 = (word2 << 8) | inbuf[5]; word2 = (word2 << 8) | inbuf[4]; word3 = (word3 << 8) | inbuf[7]; word3 = (word3 << 8) | inbuf[6]; for (i = 0; i < 16; i++) { j = i * 4; /* For some reason I cannot combine those steps. */ word0 += (word1 & ~word3) + (word2 & word3) + ctx->S[j]; word0 = rotl16(word0, 1); word1 += (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; word1 = rotl16(word1, 2); word2 += (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; word2 = rotl16(word2, 3); word3 += (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; word3 = rotl16(word3, 5); if (i == 4 || i == 10) { word0 += ctx->S[word3 & 63]; word1 += ctx->S[word0 & 63]; word2 += ctx->S[word1 & 63]; word3 += ctx->S[word2 & 63]; } } outbuf[0] = word0 & 255; outbuf[1] = word0 >> 8; outbuf[2] = word1 & 255; outbuf[3] = word1 >> 8; outbuf[4] = word2 & 255; outbuf[5] = word2 >> 8; outbuf[6] = word3 & 255; outbuf[7] = word3 >> 8; } static unsigned int encrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) { do_encrypt (context, outbuf, inbuf); return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); } static void do_decrypt (void *context, unsigned char *outbuf, const unsigned char *inbuf) { RFC2268_context *ctx = context; register int i, j; u16 word0 = 0, word1 = 0, word2 = 0, word3 = 0; word0 = (word0 << 8) | inbuf[1]; word0 = (word0 << 8) | inbuf[0]; word1 = (word1 << 8) | inbuf[3]; word1 = (word1 << 8) | inbuf[2]; word2 = (word2 << 8) | inbuf[5]; word2 = (word2 << 8) | inbuf[4]; word3 = (word3 << 8) | inbuf[7]; word3 = (word3 << 8) | inbuf[6]; for (i = 15; i >= 0; i--) { j = i * 4; word3 = rotr16(word3, 5); word3 -= (word0 & ~word2) + (word1 & word2) + ctx->S[j + 3]; word2 = rotr16(word2, 3); word2 -= (word3 & ~word1) + (word0 & word1) + ctx->S[j + 2]; word1 = rotr16(word1, 2); word1 -= (word2 & ~word0) + (word3 & word0) + ctx->S[j + 1]; word0 = rotr16(word0, 1); word0 -= (word1 & ~word3) + (word2 & word3) + ctx->S[j]; if (i == 5 || i == 11) { word3 = word3 - ctx->S[word2 & 63]; word2 = word2 - ctx->S[word1 & 63]; word1 = word1 - ctx->S[word0 & 63]; word0 = word0 - ctx->S[word3 & 63]; } } outbuf[0] = word0 & 255; outbuf[1] = word0 >> 8; outbuf[2] = word1 & 255; outbuf[3] = word1 >> 8; outbuf[4] = word2 & 255; outbuf[5] = word2 >> 8; outbuf[6] = word3 & 255; outbuf[7] = word3 >> 8; } static unsigned int decrypt_block (void *context, unsigned char *outbuf, const unsigned char *inbuf) { do_decrypt (context, outbuf, inbuf); return /*burn_stack*/ (4 * sizeof(void *) + sizeof(void *) + sizeof(u32) * 4); } static gpg_err_code_t setkey_core (void *context, const unsigned char *key, unsigned int keylen, int with_phase2) { static int initialized; static const char *selftest_failed; RFC2268_context *ctx = context; unsigned int i; unsigned char *S, x; int len; int bits = keylen * 8; if (!initialized) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("RFC2268 selftest failed (%s).\n", selftest_failed); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen < 40 / 8) /* We want at least 40 bits. */ return GPG_ERR_INV_KEYLEN; S = (unsigned char *) ctx->S; for (i = 0; i < keylen; i++) S[i] = key[i]; for (i = keylen; i < 128; i++) S[i] = rfc2268_sbox[(S[i - keylen] + S[i - 1]) & 255]; S[0] = rfc2268_sbox[S[0]]; /* Phase 2 - reduce effective key size to "bits". This was not * discussed in Gutmann's paper. I've copied that from the public * domain code posted in sci.crypt. */ if (with_phase2) { len = (bits + 7) >> 3; i = 128 - len; x = rfc2268_sbox[S[i] & (255 >> (7 & -bits))]; S[i] = x; while (i--) { x = rfc2268_sbox[x ^ S[i + len]]; S[i] = x; } } /* Make the expanded key, endian independent. */ for (i = 0; i < 64; i++) ctx->S[i] = ( (u16) S[i * 2] | (((u16) S[i * 2 + 1]) << 8)); return 0; } static gpg_err_code_t do_setkey (void *context, const unsigned char *key, unsigned int keylen, cipher_bulk_ops_t *bulk_ops) { (void)bulk_ops; return setkey_core (context, key, keylen, 1); } static const char * selftest (void) { RFC2268_context ctx; unsigned char scratch[16]; /* Test vectors from Peter Gutmann's paper. */ static unsigned char key_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char plaintext_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const unsigned char ciphertext_1[] = { 0x1C, 0x19, 0x8A, 0x83, 0x8D, 0xF0, 0x28, 0xB7 }; static unsigned char key_2[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }; static unsigned char plaintext_2[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char ciphertext_2[] = { 0x50, 0xDC, 0x01, 0x62, 0xBD, 0x75, 0x7F, 0x31 }; /* This one was checked against libmcrypt's RFC2268. */ static unsigned char key_3[] = { 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char plaintext_3[] = { 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static unsigned char ciphertext_3[] = { 0x8f, 0xd1, 0x03, 0x89, 0x33, 0x6b, 0xf9, 0x5e }; /* First test. */ setkey_core (&ctx, key_1, sizeof(key_1), 0); do_encrypt (&ctx, scratch, plaintext_1); if (memcmp (scratch, ciphertext_1, sizeof(ciphertext_1))) return "RFC2268 encryption test 1 failed."; setkey_core (&ctx, key_1, sizeof(key_1), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_1, sizeof(plaintext_1))) return "RFC2268 decryption test 1 failed."; /* Second test. */ setkey_core (&ctx, key_2, sizeof(key_2), 0); do_encrypt (&ctx, scratch, plaintext_2); if (memcmp (scratch, ciphertext_2, sizeof(ciphertext_2))) return "RFC2268 encryption test 2 failed."; setkey_core (&ctx, key_2, sizeof(key_2), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext_2, sizeof(plaintext_2))) return "RFC2268 decryption test 2 failed."; /* Third test. */ setkey_core(&ctx, key_3, sizeof(key_3), 0); do_encrypt(&ctx, scratch, plaintext_3); if (memcmp(scratch, ciphertext_3, sizeof(ciphertext_3))) return "RFC2268 encryption test 3 failed."; setkey_core (&ctx, key_3, sizeof(key_3), 0); do_decrypt (&ctx, scratch, scratch); if (memcmp(scratch, plaintext_3, sizeof(plaintext_3))) return "RFC2268 decryption test 3 failed."; return NULL; } static gcry_cipher_oid_spec_t oids_rfc2268_40[] = { /*{ "1.2.840.113549.3.2", GCRY_CIPHER_MODE_CBC },*/ /* pbeWithSHAAnd40BitRC2_CBC */ { "1.2.840.113549.1.12.1.6", GCRY_CIPHER_MODE_CBC }, { NULL } }; static gcry_cipher_oid_spec_t oids_rfc2268_128[] = { /* pbeWithSHAAnd128BitRC2_CBC */ { "1.2.840.113549.1.12.1.5", GCRY_CIPHER_MODE_CBC }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_40 = { GCRY_CIPHER_RFC2268_40, {0, 0}, "RFC2268_40", NULL, oids_rfc2268_40, RFC2268_BLOCKSIZE, 40, sizeof(RFC2268_context), do_setkey, encrypt_block, decrypt_block }; gcry_cipher_spec_t _gcry_cipher_spec_rfc2268_128 = { GCRY_CIPHER_RFC2268_128, {0, 0}, "RFC2268_128", NULL, oids_rfc2268_128, RFC2268_BLOCKSIZE, 128, sizeof(RFC2268_context), do_setkey, encrypt_block, decrypt_block }; diff --git a/cipher/salsa20.c b/cipher/salsa20.c index 58e2dc6f..d8c5c81f 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -1,599 +1,600 @@ /* salsa20.c - Bernstein's Salsa20 cipher * Copyright (C) 2012 Simon Josefsson, Niels Möller * Copyright (C) 2013 g10 Code GmbH * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . * * For a description of the algorithm, see: * http://cr.yp.to/snuffle/spec.pdf * http://cr.yp.to/snuffle/design.pdf */ /* The code is based on the code in Nettle (git commit id 9d2d8ddaee35b91a4e1a32ae77cba04bea3480e7) which in turn is based on salsa20-ref.c version 20051118 D. J. Bernstein Public domain. */ #include #include #include #include #include "types.h" #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" /* USE_AMD64 indicates whether to compile with AMD64 code. */ #undef USE_AMD64 #if defined(__x86_64__) && (defined(HAVE_COMPATIBLE_GCC_AMD64_PLATFORM_AS) || \ defined(HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS)) # define USE_AMD64 1 #endif /* USE_ARM_NEON_ASM indicates whether to enable ARM NEON assembly code. */ #undef USE_ARM_NEON_ASM #ifdef ENABLE_NEON_SUPPORT # if defined(HAVE_ARM_ARCH_V6) && defined(__ARMEL__) \ && defined(HAVE_COMPATIBLE_GCC_ARM_PLATFORM_AS) \ && defined(HAVE_GCC_INLINE_ASM_NEON) # define USE_ARM_NEON_ASM 1 # endif #endif /*ENABLE_NEON_SUPPORT*/ #define SALSA20_MIN_KEY_SIZE 16 /* Bytes. */ #define SALSA20_MAX_KEY_SIZE 32 /* Bytes. */ #define SALSA20_BLOCK_SIZE 64 /* Bytes. */ #define SALSA20_IV_SIZE 8 /* Bytes. */ #define SALSA20_INPUT_LENGTH 16 /* Bytes. */ /* Number of rounds. The standard uses 20 rounds. In any case the number of rounds must be even. */ #define SALSA20_ROUNDS 20 #define SALSA20R12_ROUNDS 12 struct SALSA20_context_s; typedef unsigned int (*salsa20_core_t) (u32 *dst, struct SALSA20_context_s *ctx, unsigned int rounds); typedef void (* salsa20_keysetup_t)(struct SALSA20_context_s *ctx, const byte *key, int keylen); typedef void (* salsa20_ivsetup_t)(struct SALSA20_context_s *ctx, const byte *iv); typedef struct SALSA20_context_s { /* Indices 1-4 and 11-14 holds the key (two identical copies for the shorter key size), indices 0, 5, 10, 15 are constant, indices 6, 7 are the IV, and indices 8, 9 are the block counter: C K K K K C I I B B C K K K K C */ u32 input[SALSA20_INPUT_LENGTH]; u32 pad[SALSA20_INPUT_LENGTH]; unsigned int unused; /* bytes in the pad. */ #ifdef USE_ARM_NEON_ASM int use_neon; #endif salsa20_keysetup_t keysetup; salsa20_ivsetup_t ivsetup; salsa20_core_t core; } SALSA20_context_t; /* The masking of the right shift is needed to allow n == 0 (using just 32 - n and 64 - n results in undefined behaviour). Most uses of these macros use a constant and non-zero rotation count. */ #define ROTL32(n,x) (((x)<<(n)) | ((x)>>((-(n)&31)))) #define LE_SWAP32(v) le_bswap32(v) #define LE_READ_UINT32(p) buf_get_le32(p) static void salsa20_setiv (void *context, const byte *iv, size_t ivlen); static const char *selftest (void); #ifdef USE_AMD64 /* Assembly implementations use SystemV ABI, ABI conversion and additional * stack to store XMM6-XMM15 needed on Win64. */ #ifdef HAVE_COMPATIBLE_GCC_WIN64_PLATFORM_AS # define ASM_FUNC_ABI __attribute__((sysv_abi)) # define ASM_EXTRA_STACK (10 * 16) #else # define ASM_FUNC_ABI # define ASM_EXTRA_STACK 0 #endif /* AMD64 assembly implementations of Salsa20. */ void _gcry_salsa20_amd64_keysetup(u32 *ctxinput, const void *key, int keybits) ASM_FUNC_ABI; void _gcry_salsa20_amd64_ivsetup(u32 *ctxinput, const void *iv) ASM_FUNC_ABI; unsigned int _gcry_salsa20_amd64_encrypt_blocks(u32 *ctxinput, const void *src, void *dst, size_t len, int rounds) ASM_FUNC_ABI; static void salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen) { _gcry_salsa20_amd64_keysetup(ctx->input, key, keylen * 8); } static void salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv) { _gcry_salsa20_amd64_ivsetup(ctx->input, iv); } static unsigned int salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds) { memset(dst, 0, SALSA20_BLOCK_SIZE); return _gcry_salsa20_amd64_encrypt_blocks(ctx->input, dst, dst, 1, rounds) + ASM_EXTRA_STACK; } #else /* USE_AMD64 */ #if 0 # define SALSA20_CORE_DEBUG(i) do { \ unsigned debug_j; \ for (debug_j = 0; debug_j < 16; debug_j++) \ { \ if (debug_j == 0) \ fprintf(stderr, "%2d:", (i)); \ else if (debug_j % 4 == 0) \ fprintf(stderr, "\n "); \ fprintf(stderr, " %8x", pad[debug_j]); \ } \ fprintf(stderr, "\n"); \ } while (0) #else # define SALSA20_CORE_DEBUG(i) #endif #define QROUND(x0, x1, x2, x3) \ do { \ x1 ^= ROTL32 ( 7, x0 + x3); \ x2 ^= ROTL32 ( 9, x1 + x0); \ x3 ^= ROTL32 (13, x2 + x1); \ x0 ^= ROTL32 (18, x3 + x2); \ } while(0) static unsigned int salsa20_core (u32 *dst, SALSA20_context_t *ctx, unsigned rounds) { u32 pad[SALSA20_INPUT_LENGTH], *src = ctx->input; unsigned int i; memcpy (pad, src, sizeof(pad)); for (i = 0; i < rounds; i += 2) { SALSA20_CORE_DEBUG (i); QROUND (pad[0], pad[4], pad[8], pad[12]); QROUND (pad[5], pad[9], pad[13], pad[1] ); QROUND (pad[10], pad[14], pad[2], pad[6] ); QROUND (pad[15], pad[3], pad[7], pad[11]); SALSA20_CORE_DEBUG (i+1); QROUND (pad[0], pad[1], pad[2], pad[3] ); QROUND (pad[5], pad[6], pad[7], pad[4] ); QROUND (pad[10], pad[11], pad[8], pad[9] ); QROUND (pad[15], pad[12], pad[13], pad[14]); } SALSA20_CORE_DEBUG (i); for (i = 0; i < SALSA20_INPUT_LENGTH; i++) { u32 t = pad[i] + src[i]; dst[i] = LE_SWAP32 (t); } /* Update counter. */ if (!++src[8]) src[9]++; /* burn_stack */ return ( 3*sizeof (void*) \ + 2*sizeof (void*) \ + 64 \ + sizeof (unsigned int) \ + sizeof (u32) ); } #undef QROUND #undef SALSA20_CORE_DEBUG static void salsa20_keysetup(SALSA20_context_t *ctx, const byte *key, int keylen) { /* These constants are the little endian encoding of the string "expand 32-byte k". For the 128 bit variant, the "32" in that string will be fixed up to "16". */ ctx->input[0] = 0x61707865; /* "apxe" */ ctx->input[5] = 0x3320646e; /* "3 dn" */ ctx->input[10] = 0x79622d32; /* "yb-2" */ ctx->input[15] = 0x6b206574; /* "k et" */ ctx->input[1] = LE_READ_UINT32(key + 0); ctx->input[2] = LE_READ_UINT32(key + 4); ctx->input[3] = LE_READ_UINT32(key + 8); ctx->input[4] = LE_READ_UINT32(key + 12); if (keylen == SALSA20_MAX_KEY_SIZE) /* 256 bits */ { ctx->input[11] = LE_READ_UINT32(key + 16); ctx->input[12] = LE_READ_UINT32(key + 20); ctx->input[13] = LE_READ_UINT32(key + 24); ctx->input[14] = LE_READ_UINT32(key + 28); } else /* 128 bits */ { ctx->input[11] = ctx->input[1]; ctx->input[12] = ctx->input[2]; ctx->input[13] = ctx->input[3]; ctx->input[14] = ctx->input[4]; ctx->input[5] -= 0x02000000; /* Change to "1 dn". */ ctx->input[10] += 0x00000004; /* Change to "yb-6". */ } } static void salsa20_ivsetup(SALSA20_context_t *ctx, const byte *iv) { ctx->input[6] = LE_READ_UINT32(iv + 0); ctx->input[7] = LE_READ_UINT32(iv + 4); /* Reset the block counter. */ ctx->input[8] = 0; ctx->input[9] = 0; } #endif /*!USE_AMD64*/ #ifdef USE_ARM_NEON_ASM /* ARM NEON implementation of Salsa20. */ unsigned int _gcry_arm_neon_salsa20_encrypt(void *c, const void *m, unsigned int nblks, void *k, unsigned int rounds); static unsigned int salsa20_core_neon (u32 *dst, SALSA20_context_t *ctx, unsigned int rounds) { return _gcry_arm_neon_salsa20_encrypt(dst, NULL, 1, ctx->input, rounds); } static void salsa20_ivsetup_neon(SALSA20_context_t *ctx, const byte *iv) { memcpy(ctx->input + 8, iv, 8); /* Reset the block counter. */ memset(ctx->input + 10, 0, 8); } static void salsa20_keysetup_neon(SALSA20_context_t *ctx, const byte *key, int klen) { static const unsigned char sigma32[16] = "expand 32-byte k"; static const unsigned char sigma16[16] = "expand 16-byte k"; if (klen == 16) { memcpy (ctx->input, key, 16); memcpy (ctx->input + 4, key, 16); /* Duplicate 128-bit key. */ memcpy (ctx->input + 12, sigma16, 16); } else { /* 32-byte key */ memcpy (ctx->input, key, 32); memcpy (ctx->input + 12, sigma32, 16); } } #endif /*USE_ARM_NEON_ASM*/ static gcry_err_code_t salsa20_do_setkey (SALSA20_context_t *ctx, const byte *key, unsigned int keylen) { static int initialized; static const char *selftest_failed; if (!initialized ) { initialized = 1; selftest_failed = selftest (); if (selftest_failed) log_error ("SALSA20 selftest failed (%s)\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != SALSA20_MIN_KEY_SIZE && keylen != SALSA20_MAX_KEY_SIZE) return GPG_ERR_INV_KEYLEN; /* Default ops. */ ctx->keysetup = salsa20_keysetup; ctx->ivsetup = salsa20_ivsetup; ctx->core = salsa20_core; #ifdef USE_ARM_NEON_ASM ctx->use_neon = (_gcry_get_hw_features () & HWF_ARM_NEON) != 0; if (ctx->use_neon) { /* Use ARM NEON ops instead. */ ctx->keysetup = salsa20_keysetup_neon; ctx->ivsetup = salsa20_ivsetup_neon; ctx->core = salsa20_core_neon; } #endif ctx->keysetup (ctx, key, keylen); /* We default to a zero nonce. */ salsa20_setiv (ctx, NULL, 0); return 0; } static gcry_err_code_t salsa20_setkey (void *context, const byte *key, unsigned int keylen, cipher_bulk_ops_t *bulk_ops) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; gcry_err_code_t rc = salsa20_do_setkey (ctx, key, keylen); (void)bulk_ops; _gcry_burn_stack (4 + sizeof (void *) + 4 * sizeof (void *)); return rc; } static void salsa20_setiv (void *context, const byte *iv, size_t ivlen) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; byte tmp[SALSA20_IV_SIZE]; if (iv && ivlen != SALSA20_IV_SIZE) log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen); if (!iv || ivlen != SALSA20_IV_SIZE) memset (tmp, 0, sizeof(tmp)); else memcpy (tmp, iv, SALSA20_IV_SIZE); ctx->ivsetup (ctx, tmp); /* Reset the unused pad bytes counter. */ ctx->unused = 0; wipememory (tmp, sizeof(tmp)); } /* Note: This function requires LENGTH > 0. */ static void salsa20_do_encrypt_stream (SALSA20_context_t *ctx, byte *outbuf, const byte *inbuf, size_t length, unsigned rounds) { unsigned int nburn, burn = 0; if (ctx->unused) { unsigned char *p = (void*)ctx->pad; size_t n; gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE); n = ctx->unused; if (n > length) n = length; buf_xor (outbuf, inbuf, p + SALSA20_BLOCK_SIZE - ctx->unused, n); length -= n; outbuf += n; inbuf += n; ctx->unused -= n; if (!length) return; gcry_assert (!ctx->unused); } #ifdef USE_AMD64 if (length >= SALSA20_BLOCK_SIZE) { size_t nblocks = length / SALSA20_BLOCK_SIZE; burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf, nblocks, rounds); burn += ASM_EXTRA_STACK; length -= SALSA20_BLOCK_SIZE * nblocks; outbuf += SALSA20_BLOCK_SIZE * nblocks; inbuf += SALSA20_BLOCK_SIZE * nblocks; } #endif #ifdef USE_ARM_NEON_ASM if (ctx->use_neon && length >= SALSA20_BLOCK_SIZE) { unsigned int nblocks = length / SALSA20_BLOCK_SIZE; _gcry_arm_neon_salsa20_encrypt (outbuf, inbuf, nblocks, ctx->input, rounds); length -= SALSA20_BLOCK_SIZE * nblocks; outbuf += SALSA20_BLOCK_SIZE * nblocks; inbuf += SALSA20_BLOCK_SIZE * nblocks; } #endif while (length > 0) { /* Create the next pad and bump the block counter. Note that it is the user's duty to change to another nonce not later than after 2^70 processed bytes. */ nburn = ctx->core (ctx->pad, ctx, rounds); burn = nburn > burn ? nburn : burn; if (length <= SALSA20_BLOCK_SIZE) { buf_xor (outbuf, inbuf, ctx->pad, length); ctx->unused = SALSA20_BLOCK_SIZE - length; break; } buf_xor (outbuf, inbuf, ctx->pad, SALSA20_BLOCK_SIZE); length -= SALSA20_BLOCK_SIZE; outbuf += SALSA20_BLOCK_SIZE; inbuf += SALSA20_BLOCK_SIZE; } _gcry_burn_stack (burn); } static void salsa20_encrypt_stream (void *context, byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; if (length) salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20_ROUNDS); } static void salsa20r12_encrypt_stream (void *context, byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; if (length) salsa20_do_encrypt_stream (ctx, outbuf, inbuf, length, SALSA20R12_ROUNDS); } static const char* selftest (void) { byte ctxbuf[sizeof(SALSA20_context_t) + 15]; SALSA20_context_t *ctx; byte scratch[8+1]; byte buf[256+64+4]; int i; static byte key_1[] = { 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte nonce_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte plaintext_1[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const byte ciphertext_1[] = { 0xE3, 0xBE, 0x8F, 0xDD, 0x8B, 0xEC, 0xA2, 0xE3}; /* 16-byte alignment required for amd64 implementation. */ ctx = (SALSA20_context_t *)((uintptr_t)(ctxbuf + 15) & ~(uintptr_t)15); salsa20_setkey (ctx, key_1, sizeof key_1, NULL); salsa20_setiv (ctx, nonce_1, sizeof nonce_1); scratch[8] = 0; salsa20_encrypt_stream (ctx, scratch, plaintext_1, sizeof plaintext_1); if (memcmp (scratch, ciphertext_1, sizeof ciphertext_1)) return "Salsa20 encryption test 1 failed."; if (scratch[8]) return "Salsa20 wrote too much."; salsa20_setkey( ctx, key_1, sizeof(key_1), NULL); salsa20_setiv (ctx, nonce_1, sizeof nonce_1); salsa20_encrypt_stream (ctx, scratch, scratch, sizeof plaintext_1); if (memcmp (scratch, plaintext_1, sizeof plaintext_1)) return "Salsa20 decryption test 1 failed."; for (i = 0; i < sizeof buf; i++) buf[i] = i; salsa20_setkey (ctx, key_1, sizeof key_1, NULL); salsa20_setiv (ctx, nonce_1, sizeof nonce_1); /*encrypt*/ salsa20_encrypt_stream (ctx, buf, buf, sizeof buf); /*decrypt*/ salsa20_setkey (ctx, key_1, sizeof key_1, NULL); salsa20_setiv (ctx, nonce_1, sizeof nonce_1); salsa20_encrypt_stream (ctx, buf, buf, 1); salsa20_encrypt_stream (ctx, buf+1, buf+1, (sizeof buf)-1-1); salsa20_encrypt_stream (ctx, buf+(sizeof buf)-1, buf+(sizeof buf)-1, 1); for (i = 0; i < sizeof buf; i++) if (buf[i] != (byte)i) return "Salsa20 encryption test 2 failed."; return NULL; } gcry_cipher_spec_t _gcry_cipher_spec_salsa20 = { GCRY_CIPHER_SALSA20, {0, 0}, /* flags */ "SALSA20", /* name */ NULL, /* aliases */ NULL, /* oids */ 1, /* blocksize in bytes. */ SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */ sizeof (SALSA20_context_t), salsa20_setkey, NULL, NULL, salsa20_encrypt_stream, salsa20_encrypt_stream, NULL, NULL, salsa20_setiv }; gcry_cipher_spec_t _gcry_cipher_spec_salsa20r12 = { GCRY_CIPHER_SALSA20R12, {0, 0}, /* flags */ "SALSA20R12", /* name */ NULL, /* aliases */ NULL, /* oids */ 1, /* blocksize in bytes. */ SALSA20_MAX_KEY_SIZE*8, /* standard key length in bits. */ sizeof (SALSA20_context_t), salsa20_setkey, NULL, NULL, salsa20r12_encrypt_stream, salsa20r12_encrypt_stream, NULL, NULL, salsa20_setiv }; diff --git a/cipher/seed.c b/cipher/seed.c index c8ae4a01..2c8958fa 100644 --- a/cipher/seed.c +++ b/cipher/seed.c @@ -1,477 +1,478 @@ /* SEED for libgcrypt * Copyright (C) 2006 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, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * * -- * This implementation was provided for libgcrypt in public domain * by Hye-Shik Chang , July 2006. */ #include #include #include #include "types.h" /* for byte and u32 typedefs */ #include "g10lib.h" #include "cipher.h" #include "bufhelp.h" +#include "cipher-internal.h" #define NUMKC 16 #define GETU32(pt) buf_get_be32(pt) #define PUTU32(ct, st) buf_put_be32(ct, st) union wordbuf { u32 w; byte b[4]; }; #ifdef WORDS_BIGENDIAN #define b0 b[3] #define b1 b[2] #define b2 b[1] #define b3 b[0] #else #define b0 b[0] #define b1 b[1] #define b2 b[2] #define b3 b[3] #endif static const char *selftest(void); typedef struct { u32 keyschedule[32]; } SEED_context; static const u32 SS0[256] = { 0x2989a1a8, 0x05858184, 0x16c6d2d4, 0x13c3d3d0, 0x14445054, 0x1d0d111c, 0x2c8ca0ac, 0x25052124, 0x1d4d515c, 0x03434340, 0x18081018, 0x1e0e121c, 0x11415150, 0x3cccf0fc, 0x0acac2c8, 0x23436360, 0x28082028, 0x04444044, 0x20002020, 0x1d8d919c, 0x20c0e0e0, 0x22c2e2e0, 0x08c8c0c8, 0x17071314, 0x2585a1a4, 0x0f8f838c, 0x03030300, 0x3b4b7378, 0x3b8bb3b8, 0x13031310, 0x12c2d2d0, 0x2ecee2ec, 0x30407070, 0x0c8c808c, 0x3f0f333c, 0x2888a0a8, 0x32023230, 0x1dcdd1dc, 0x36c6f2f4, 0x34447074, 0x2ccce0ec, 0x15859194, 0x0b0b0308, 0x17475354, 0x1c4c505c, 0x1b4b5358, 0x3d8db1bc, 0x01010100, 0x24042024, 0x1c0c101c, 0x33437370, 0x18889098, 0x10001010, 0x0cccc0cc, 0x32c2f2f0, 0x19c9d1d8, 0x2c0c202c, 0x27c7e3e4, 0x32427270, 0x03838380, 0x1b8b9398, 0x11c1d1d0, 0x06868284, 0x09c9c1c8, 0x20406060, 0x10405050, 0x2383a3a0, 0x2bcbe3e8, 0x0d0d010c, 0x3686b2b4, 0x1e8e929c, 0x0f4f434c, 0x3787b3b4, 0x1a4a5258, 0x06c6c2c4, 0x38487078, 0x2686a2a4, 0x12021210, 0x2f8fa3ac, 0x15c5d1d4, 0x21416160, 0x03c3c3c0, 0x3484b0b4, 0x01414140, 0x12425250, 0x3d4d717c, 0x0d8d818c, 0x08080008, 0x1f0f131c, 0x19899198, 0x00000000, 0x19091118, 0x04040004, 0x13435350, 0x37c7f3f4, 0x21c1e1e0, 0x3dcdf1fc, 0x36467274, 0x2f0f232c, 0x27072324, 0x3080b0b0, 0x0b8b8388, 0x0e0e020c, 0x2b8ba3a8, 0x2282a2a0, 0x2e4e626c, 0x13839390, 0x0d4d414c, 0x29496168, 0x3c4c707c, 0x09090108, 0x0a0a0208, 0x3f8fb3bc, 0x2fcfe3ec, 0x33c3f3f0, 0x05c5c1c4, 0x07878384, 0x14041014, 0x3ecef2fc, 0x24446064, 0x1eced2dc, 0x2e0e222c, 0x0b4b4348, 0x1a0a1218, 0x06060204, 0x21012120, 0x2b4b6368, 0x26466264, 0x02020200, 0x35c5f1f4, 0x12829290, 0x0a8a8288, 0x0c0c000c, 0x3383b3b0, 0x3e4e727c, 0x10c0d0d0, 0x3a4a7278, 0x07474344, 0x16869294, 0x25c5e1e4, 0x26062224, 0x00808080, 0x2d8da1ac, 0x1fcfd3dc, 0x2181a1a0, 0x30003030, 0x37073334, 0x2e8ea2ac, 0x36063234, 0x15051114, 0x22022220, 0x38083038, 0x34c4f0f4, 0x2787a3a4, 0x05454144, 0x0c4c404c, 0x01818180, 0x29c9e1e8, 0x04848084, 0x17879394, 0x35053134, 0x0bcbc3c8, 0x0ecec2cc, 0x3c0c303c, 0x31417170, 0x11011110, 0x07c7c3c4, 0x09898188, 0x35457174, 0x3bcbf3f8, 0x1acad2d8, 0x38c8f0f8, 0x14849094, 0x19495158, 0x02828280, 0x04c4c0c4, 0x3fcff3fc, 0x09494148, 0x39093138, 0x27476364, 0x00c0c0c0, 0x0fcfc3cc, 0x17c7d3d4, 0x3888b0b8, 0x0f0f030c, 0x0e8e828c, 0x02424240, 0x23032320, 0x11819190, 0x2c4c606c, 0x1bcbd3d8, 0x2484a0a4, 0x34043034, 0x31c1f1f0, 0x08484048, 0x02c2c2c0, 0x2f4f636c, 0x3d0d313c, 0x2d0d212c, 0x00404040, 0x3e8eb2bc, 0x3e0e323c, 0x3c8cb0bc, 0x01c1c1c0, 0x2a8aa2a8, 0x3a8ab2b8, 0x0e4e424c, 0x15455154, 0x3b0b3338, 0x1cccd0dc, 0x28486068, 0x3f4f737c, 0x1c8c909c, 0x18c8d0d8, 0x0a4a4248, 0x16465254, 0x37477374, 0x2080a0a0, 0x2dcde1ec, 0x06464244, 0x3585b1b4, 0x2b0b2328, 0x25456164, 0x3acaf2f8, 0x23c3e3e0, 0x3989b1b8, 0x3181b1b0, 0x1f8f939c, 0x1e4e525c, 0x39c9f1f8, 0x26c6e2e4, 0x3282b2b0, 0x31013130, 0x2acae2e8, 0x2d4d616c, 0x1f4f535c, 0x24c4e0e4, 0x30c0f0f0, 0x0dcdc1cc, 0x08888088, 0x16061214, 0x3a0a3238, 0x18485058, 0x14c4d0d4, 0x22426260, 0x29092128, 0x07070304, 0x33033330, 0x28c8e0e8, 0x1b0b1318, 0x05050104, 0x39497178, 0x10809090, 0x2a4a6268, 0x2a0a2228, 0x1a8a9298, }; static const u32 SS1[256] = { 0x38380830, 0xe828c8e0, 0x2c2d0d21, 0xa42686a2, 0xcc0fcfc3, 0xdc1eced2, 0xb03383b3, 0xb83888b0, 0xac2f8fa3, 0x60204060, 0x54154551, 0xc407c7c3, 0x44044440, 0x6c2f4f63, 0x682b4b63, 0x581b4b53, 0xc003c3c3, 0x60224262, 0x30330333, 0xb43585b1, 0x28290921, 0xa02080a0, 0xe022c2e2, 0xa42787a3, 0xd013c3d3, 0x90118191, 0x10110111, 0x04060602, 0x1c1c0c10, 0xbc3c8cb0, 0x34360632, 0x480b4b43, 0xec2fcfe3, 0x88088880, 0x6c2c4c60, 0xa82888a0, 0x14170713, 0xc404c4c0, 0x14160612, 0xf434c4f0, 0xc002c2c2, 0x44054541, 0xe021c1e1, 0xd416c6d2, 0x3c3f0f33, 0x3c3d0d31, 0x8c0e8e82, 0x98188890, 0x28280820, 0x4c0e4e42, 0xf436c6f2, 0x3c3e0e32, 0xa42585a1, 0xf839c9f1, 0x0c0d0d01, 0xdc1fcfd3, 0xd818c8d0, 0x282b0b23, 0x64264662, 0x783a4a72, 0x24270723, 0x2c2f0f23, 0xf031c1f1, 0x70324272, 0x40024242, 0xd414c4d0, 0x40014141, 0xc000c0c0, 0x70334373, 0x64274763, 0xac2c8ca0, 0x880b8b83, 0xf437c7f3, 0xac2d8da1, 0x80008080, 0x1c1f0f13, 0xc80acac2, 0x2c2c0c20, 0xa82a8aa2, 0x34340430, 0xd012c2d2, 0x080b0b03, 0xec2ecee2, 0xe829c9e1, 0x5c1d4d51, 0x94148490, 0x18180810, 0xf838c8f0, 0x54174753, 0xac2e8ea2, 0x08080800, 0xc405c5c1, 0x10130313, 0xcc0dcdc1, 0x84068682, 0xb83989b1, 0xfc3fcff3, 0x7c3d4d71, 0xc001c1c1, 0x30310131, 0xf435c5f1, 0x880a8a82, 0x682a4a62, 0xb03181b1, 0xd011c1d1, 0x20200020, 0xd417c7d3, 0x00020202, 0x20220222, 0x04040400, 0x68284860, 0x70314171, 0x04070703, 0xd81bcbd3, 0x9c1d8d91, 0x98198991, 0x60214161, 0xbc3e8eb2, 0xe426c6e2, 0x58194951, 0xdc1dcdd1, 0x50114151, 0x90108090, 0xdc1cccd0, 0x981a8a92, 0xa02383a3, 0xa82b8ba3, 0xd010c0d0, 0x80018181, 0x0c0f0f03, 0x44074743, 0x181a0a12, 0xe023c3e3, 0xec2ccce0, 0x8c0d8d81, 0xbc3f8fb3, 0x94168692, 0x783b4b73, 0x5c1c4c50, 0xa02282a2, 0xa02181a1, 0x60234363, 0x20230323, 0x4c0d4d41, 0xc808c8c0, 0x9c1e8e92, 0x9c1c8c90, 0x383a0a32, 0x0c0c0c00, 0x2c2e0e22, 0xb83a8ab2, 0x6c2e4e62, 0x9c1f8f93, 0x581a4a52, 0xf032c2f2, 0x90128292, 0xf033c3f3, 0x48094941, 0x78384870, 0xcc0cccc0, 0x14150511, 0xf83bcbf3, 0x70304070, 0x74354571, 0x7c3f4f73, 0x34350531, 0x10100010, 0x00030303, 0x64244460, 0x6c2d4d61, 0xc406c6c2, 0x74344470, 0xd415c5d1, 0xb43484b0, 0xe82acae2, 0x08090901, 0x74364672, 0x18190911, 0xfc3ecef2, 0x40004040, 0x10120212, 0xe020c0e0, 0xbc3d8db1, 0x04050501, 0xf83acaf2, 0x00010101, 0xf030c0f0, 0x282a0a22, 0x5c1e4e52, 0xa82989a1, 0x54164652, 0x40034343, 0x84058581, 0x14140410, 0x88098981, 0x981b8b93, 0xb03080b0, 0xe425c5e1, 0x48084840, 0x78394971, 0x94178793, 0xfc3cccf0, 0x1c1e0e12, 0x80028282, 0x20210121, 0x8c0c8c80, 0x181b0b13, 0x5c1f4f53, 0x74374773, 0x54144450, 0xb03282b2, 0x1c1d0d11, 0x24250521, 0x4c0f4f43, 0x00000000, 0x44064642, 0xec2dcde1, 0x58184850, 0x50124252, 0xe82bcbe3, 0x7c3e4e72, 0xd81acad2, 0xc809c9c1, 0xfc3dcdf1, 0x30300030, 0x94158591, 0x64254561, 0x3c3c0c30, 0xb43686b2, 0xe424c4e0, 0xb83b8bb3, 0x7c3c4c70, 0x0c0e0e02, 0x50104050, 0x38390931, 0x24260622, 0x30320232, 0x84048480, 0x68294961, 0x90138393, 0x34370733, 0xe427c7e3, 0x24240420, 0xa42484a0, 0xc80bcbc3, 0x50134353, 0x080a0a02, 0x84078783, 0xd819c9d1, 0x4c0c4c40, 0x80038383, 0x8c0f8f83, 0xcc0ecec2, 0x383b0b33, 0x480a4a42, 0xb43787b3, }; static const u32 SS2[256] = { 0xa1a82989, 0x81840585, 0xd2d416c6, 0xd3d013c3, 0x50541444, 0x111c1d0d, 0xa0ac2c8c, 0x21242505, 0x515c1d4d, 0x43400343, 0x10181808, 0x121c1e0e, 0x51501141, 0xf0fc3ccc, 0xc2c80aca, 0x63602343, 0x20282808, 0x40440444, 0x20202000, 0x919c1d8d, 0xe0e020c0, 0xe2e022c2, 0xc0c808c8, 0x13141707, 0xa1a42585, 0x838c0f8f, 0x03000303, 0x73783b4b, 0xb3b83b8b, 0x13101303, 0xd2d012c2, 0xe2ec2ece, 0x70703040, 0x808c0c8c, 0x333c3f0f, 0xa0a82888, 0x32303202, 0xd1dc1dcd, 0xf2f436c6, 0x70743444, 0xe0ec2ccc, 0x91941585, 0x03080b0b, 0x53541747, 0x505c1c4c, 0x53581b4b, 0xb1bc3d8d, 0x01000101, 0x20242404, 0x101c1c0c, 0x73703343, 0x90981888, 0x10101000, 0xc0cc0ccc, 0xf2f032c2, 0xd1d819c9, 0x202c2c0c, 0xe3e427c7, 0x72703242, 0x83800383, 0x93981b8b, 0xd1d011c1, 0x82840686, 0xc1c809c9, 0x60602040, 0x50501040, 0xa3a02383, 0xe3e82bcb, 0x010c0d0d, 0xb2b43686, 0x929c1e8e, 0x434c0f4f, 0xb3b43787, 0x52581a4a, 0xc2c406c6, 0x70783848, 0xa2a42686, 0x12101202, 0xa3ac2f8f, 0xd1d415c5, 0x61602141, 0xc3c003c3, 0xb0b43484, 0x41400141, 0x52501242, 0x717c3d4d, 0x818c0d8d, 0x00080808, 0x131c1f0f, 0x91981989, 0x00000000, 0x11181909, 0x00040404, 0x53501343, 0xf3f437c7, 0xe1e021c1, 0xf1fc3dcd, 0x72743646, 0x232c2f0f, 0x23242707, 0xb0b03080, 0x83880b8b, 0x020c0e0e, 0xa3a82b8b, 0xa2a02282, 0x626c2e4e, 0x93901383, 0x414c0d4d, 0x61682949, 0x707c3c4c, 0x01080909, 0x02080a0a, 0xb3bc3f8f, 0xe3ec2fcf, 0xf3f033c3, 0xc1c405c5, 0x83840787, 0x10141404, 0xf2fc3ece, 0x60642444, 0xd2dc1ece, 0x222c2e0e, 0x43480b4b, 0x12181a0a, 0x02040606, 0x21202101, 0x63682b4b, 0x62642646, 0x02000202, 0xf1f435c5, 0x92901282, 0x82880a8a, 0x000c0c0c, 0xb3b03383, 0x727c3e4e, 0xd0d010c0, 0x72783a4a, 0x43440747, 0x92941686, 0xe1e425c5, 0x22242606, 0x80800080, 0xa1ac2d8d, 0xd3dc1fcf, 0xa1a02181, 0x30303000, 0x33343707, 0xa2ac2e8e, 0x32343606, 0x11141505, 0x22202202, 0x30383808, 0xf0f434c4, 0xa3a42787, 0x41440545, 0x404c0c4c, 0x81800181, 0xe1e829c9, 0x80840484, 0x93941787, 0x31343505, 0xc3c80bcb, 0xc2cc0ece, 0x303c3c0c, 0x71703141, 0x11101101, 0xc3c407c7, 0x81880989, 0x71743545, 0xf3f83bcb, 0xd2d81aca, 0xf0f838c8, 0x90941484, 0x51581949, 0x82800282, 0xc0c404c4, 0xf3fc3fcf, 0x41480949, 0x31383909, 0x63642747, 0xc0c000c0, 0xc3cc0fcf, 0xd3d417c7, 0xb0b83888, 0x030c0f0f, 0x828c0e8e, 0x42400242, 0x23202303, 0x91901181, 0x606c2c4c, 0xd3d81bcb, 0xa0a42484, 0x30343404, 0xf1f031c1, 0x40480848, 0xc2c002c2, 0x636c2f4f, 0x313c3d0d, 0x212c2d0d, 0x40400040, 0xb2bc3e8e, 0x323c3e0e, 0xb0bc3c8c, 0xc1c001c1, 0xa2a82a8a, 0xb2b83a8a, 0x424c0e4e, 0x51541545, 0x33383b0b, 0xd0dc1ccc, 0x60682848, 0x737c3f4f, 0x909c1c8c, 0xd0d818c8, 0x42480a4a, 0x52541646, 0x73743747, 0xa0a02080, 0xe1ec2dcd, 0x42440646, 0xb1b43585, 0x23282b0b, 0x61642545, 0xf2f83aca, 0xe3e023c3, 0xb1b83989, 0xb1b03181, 0x939c1f8f, 0x525c1e4e, 0xf1f839c9, 0xe2e426c6, 0xb2b03282, 0x31303101, 0xe2e82aca, 0x616c2d4d, 0x535c1f4f, 0xe0e424c4, 0xf0f030c0, 0xc1cc0dcd, 0x80880888, 0x12141606, 0x32383a0a, 0x50581848, 0xd0d414c4, 0x62602242, 0x21282909, 0x03040707, 0x33303303, 0xe0e828c8, 0x13181b0b, 0x01040505, 0x71783949, 0x90901080, 0x62682a4a, 0x22282a0a, 0x92981a8a, }; static const u32 SS3[256] = { 0x08303838, 0xc8e0e828, 0x0d212c2d, 0x86a2a426, 0xcfc3cc0f, 0xced2dc1e, 0x83b3b033, 0x88b0b838, 0x8fa3ac2f, 0x40606020, 0x45515415, 0xc7c3c407, 0x44404404, 0x4f636c2f, 0x4b63682b, 0x4b53581b, 0xc3c3c003, 0x42626022, 0x03333033, 0x85b1b435, 0x09212829, 0x80a0a020, 0xc2e2e022, 0x87a3a427, 0xc3d3d013, 0x81919011, 0x01111011, 0x06020406, 0x0c101c1c, 0x8cb0bc3c, 0x06323436, 0x4b43480b, 0xcfe3ec2f, 0x88808808, 0x4c606c2c, 0x88a0a828, 0x07131417, 0xc4c0c404, 0x06121416, 0xc4f0f434, 0xc2c2c002, 0x45414405, 0xc1e1e021, 0xc6d2d416, 0x0f333c3f, 0x0d313c3d, 0x8e828c0e, 0x88909818, 0x08202828, 0x4e424c0e, 0xc6f2f436, 0x0e323c3e, 0x85a1a425, 0xc9f1f839, 0x0d010c0d, 0xcfd3dc1f, 0xc8d0d818, 0x0b23282b, 0x46626426, 0x4a72783a, 0x07232427, 0x0f232c2f, 0xc1f1f031, 0x42727032, 0x42424002, 0xc4d0d414, 0x41414001, 0xc0c0c000, 0x43737033, 0x47636427, 0x8ca0ac2c, 0x8b83880b, 0xc7f3f437, 0x8da1ac2d, 0x80808000, 0x0f131c1f, 0xcac2c80a, 0x0c202c2c, 0x8aa2a82a, 0x04303434, 0xc2d2d012, 0x0b03080b, 0xcee2ec2e, 0xc9e1e829, 0x4d515c1d, 0x84909414, 0x08101818, 0xc8f0f838, 0x47535417, 0x8ea2ac2e, 0x08000808, 0xc5c1c405, 0x03131013, 0xcdc1cc0d, 0x86828406, 0x89b1b839, 0xcff3fc3f, 0x4d717c3d, 0xc1c1c001, 0x01313031, 0xc5f1f435, 0x8a82880a, 0x4a62682a, 0x81b1b031, 0xc1d1d011, 0x00202020, 0xc7d3d417, 0x02020002, 0x02222022, 0x04000404, 0x48606828, 0x41717031, 0x07030407, 0xcbd3d81b, 0x8d919c1d, 0x89919819, 0x41616021, 0x8eb2bc3e, 0xc6e2e426, 0x49515819, 0xcdd1dc1d, 0x41515011, 0x80909010, 0xccd0dc1c, 0x8a92981a, 0x83a3a023, 0x8ba3a82b, 0xc0d0d010, 0x81818001, 0x0f030c0f, 0x47434407, 0x0a12181a, 0xc3e3e023, 0xcce0ec2c, 0x8d818c0d, 0x8fb3bc3f, 0x86929416, 0x4b73783b, 0x4c505c1c, 0x82a2a022, 0x81a1a021, 0x43636023, 0x03232023, 0x4d414c0d, 0xc8c0c808, 0x8e929c1e, 0x8c909c1c, 0x0a32383a, 0x0c000c0c, 0x0e222c2e, 0x8ab2b83a, 0x4e626c2e, 0x8f939c1f, 0x4a52581a, 0xc2f2f032, 0x82929012, 0xc3f3f033, 0x49414809, 0x48707838, 0xccc0cc0c, 0x05111415, 0xcbf3f83b, 0x40707030, 0x45717435, 0x4f737c3f, 0x05313435, 0x00101010, 0x03030003, 0x44606424, 0x4d616c2d, 0xc6c2c406, 0x44707434, 0xc5d1d415, 0x84b0b434, 0xcae2e82a, 0x09010809, 0x46727436, 0x09111819, 0xcef2fc3e, 0x40404000, 0x02121012, 0xc0e0e020, 0x8db1bc3d, 0x05010405, 0xcaf2f83a, 0x01010001, 0xc0f0f030, 0x0a22282a, 0x4e525c1e, 0x89a1a829, 0x46525416, 0x43434003, 0x85818405, 0x04101414, 0x89818809, 0x8b93981b, 0x80b0b030, 0xc5e1e425, 0x48404808, 0x49717839, 0x87939417, 0xccf0fc3c, 0x0e121c1e, 0x82828002, 0x01212021, 0x8c808c0c, 0x0b13181b, 0x4f535c1f, 0x47737437, 0x44505414, 0x82b2b032, 0x0d111c1d, 0x05212425, 0x4f434c0f, 0x00000000, 0x46424406, 0xcde1ec2d, 0x48505818, 0x42525012, 0xcbe3e82b, 0x4e727c3e, 0xcad2d81a, 0xc9c1c809, 0xcdf1fc3d, 0x00303030, 0x85919415, 0x45616425, 0x0c303c3c, 0x86b2b436, 0xc4e0e424, 0x8bb3b83b, 0x4c707c3c, 0x0e020c0e, 0x40505010, 0x09313839, 0x06222426, 0x02323032, 0x84808404, 0x49616829, 0x83939013, 0x07333437, 0xc7e3e427, 0x04202424, 0x84a0a424, 0xcbc3c80b, 0x43535013, 0x0a02080a, 0x87838407, 0xc9d1d819, 0x4c404c0c, 0x83838003, 0x8f838c0f, 0xcec2cc0e, 0x0b33383b, 0x4a42480a, 0x87b3b437, }; static const u32 KC[NUMKC] = { 0x9e3779b9, 0x3c6ef373, 0x78dde6e6, 0xf1bbcdcc, 0xe3779b99, 0xc6ef3733, 0x8dde6e67, 0x1bbcdccf, 0x3779b99e, 0x6ef3733c, 0xdde6e678, 0xbbcdccf1, 0x779b99e3, 0xef3733c6, 0xde6e678d, 0xbcdccf1b, }; /* Perform the key setup. */ static gcry_err_code_t do_setkey (SEED_context *ctx, const byte *key, const unsigned keylen) { static int initialized = 0; static const char *selftest_failed=0; u32 x1, x2, x3, x4; union wordbuf t0, t1; u32 *keyout = ctx->keyschedule; int i; if (!initialized) { initialized = 1; selftest_failed = selftest (); if( selftest_failed ) log_error ("%s\n", selftest_failed ); } if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; if (keylen != 16) return GPG_ERR_INV_KEYLEN; x1 = GETU32 (key); x2 = GETU32 (key+4); x3 = GETU32 (key+8); x4 = GETU32 (key+12); for (i = 0; i < NUMKC; i++) { t0.w = x1 + x3 - KC[i]; t1.w = x2 + KC[i] - x4; *(keyout++) = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; *(keyout++) = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; if (i % 2 == 0) { t0.w = x1; x1 = (x1>>8) ^ (x2<<24); x2 = (x2>>8) ^ (t0.w<<24); } else { t0.w = x3; x3 = (x3<<8) ^ (x4>>24); x4 = (x4<<8) ^ (t0.w>>24); } } return 0; } static gcry_err_code_t seed_setkey (void *context, const byte *key, const unsigned keylen, cipher_bulk_ops_t *bulk_ops) { SEED_context *ctx = context; int rc = do_setkey (ctx, key, keylen); (void)bulk_ops; _gcry_burn_stack (4*6 + sizeof(void*)*2 + sizeof(int)*2); return rc; } #define OP(X1, X2, X3, X4, rbase) \ t0.w = X3 ^ ctx->keyschedule[rbase]; \ t1.w = X4 ^ ctx->keyschedule[rbase+1]; \ t1.w ^= t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ t0.w = SS0[t0.b0] ^ SS1[t0.b1] ^ SS2[t0.b2] ^ SS3[t0.b3]; \ t1.w += t0.w; \ t1.w = SS0[t1.b0] ^ SS1[t1.b1] ^ SS2[t1.b2] ^ SS3[t1.b3]; \ t0.w += t1.w; \ X1 ^= t0.w; \ X2 ^= t1.w; /* Encrypt one block. inbuf and outbuf may be the same. */ static void do_encrypt (const SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 0); OP (x3, x4, x1, x2, 2); OP (x1, x2, x3, x4, 4); OP (x3, x4, x1, x2, 6); OP (x1, x2, x3, x4, 8); OP (x3, x4, x1, x2, 10); OP (x1, x2, x3, x4, 12); OP (x3, x4, x1, x2, 14); OP (x1, x2, x3, x4, 16); OP (x3, x4, x1, x2, 18); OP (x1, x2, x3, x4, 20); OP (x3, x4, x1, x2, 22); OP (x1, x2, x3, x4, 24); OP (x3, x4, x1, x2, 26); OP (x1, x2, x3, x4, 28); OP (x3, x4, x1, x2, 30); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_encrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_encrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Decrypt one block. inbuf and outbuf may be the same. */ static void do_decrypt (SEED_context *ctx, byte *outbuf, const byte *inbuf) { u32 x1, x2, x3, x4; union wordbuf t0, t1; x1 = GETU32 (inbuf); x2 = GETU32 (inbuf+4); x3 = GETU32 (inbuf+8); x4 = GETU32 (inbuf+12); OP (x1, x2, x3, x4, 30); OP (x3, x4, x1, x2, 28); OP (x1, x2, x3, x4, 26); OP (x3, x4, x1, x2, 24); OP (x1, x2, x3, x4, 22); OP (x3, x4, x1, x2, 20); OP (x1, x2, x3, x4, 18); OP (x3, x4, x1, x2, 16); OP (x1, x2, x3, x4, 14); OP (x3, x4, x1, x2, 12); OP (x1, x2, x3, x4, 10); OP (x3, x4, x1, x2, 8); OP (x1, x2, x3, x4, 6); OP (x3, x4, x1, x2, 4); OP (x1, x2, x3, x4, 2); OP (x3, x4, x1, x2, 0); PUTU32 (outbuf, x3); PUTU32 (outbuf+4, x4); PUTU32 (outbuf+8, x1); PUTU32 (outbuf+12, x2); } static unsigned int seed_decrypt (void *context, byte *outbuf, const byte *inbuf) { SEED_context *ctx = context; do_decrypt (ctx, outbuf, inbuf); return /*burn_stack*/ (4*6); } /* Test a single encryption and decryption with each key size. */ static const char* selftest (void) { SEED_context ctx; byte scratch[16]; /* The test vector is taken from the appendix section B.3 of RFC4269. */ static const byte plaintext[16] = { 0x83, 0xA2, 0xF8, 0xA2, 0x88, 0x64, 0x1F, 0xB9, 0xA4, 0xE9, 0xA5, 0xCC, 0x2F, 0x13, 0x1C, 0x7D }; static const byte key[16] = { 0x47, 0x06, 0x48, 0x08, 0x51, 0xE6, 0x1B, 0xE8, 0x5D, 0x74, 0xBF, 0xB3, 0xFD, 0x95, 0x61, 0x85 }; static const byte ciphertext[16] = { 0xEE, 0x54, 0xD1, 0x3E, 0xBC, 0xAE, 0x70, 0x6D, 0x22, 0x6B, 0xC3, 0x14, 0x2C, 0xD4, 0x0D, 0x4A, }; seed_setkey (&ctx, key, sizeof(key), NULL); seed_encrypt (&ctx, scratch, plaintext); if (memcmp (scratch, ciphertext, sizeof (ciphertext))) return "SEED test encryption failed."; seed_decrypt (&ctx, scratch, scratch); if (memcmp (scratch, plaintext, sizeof (plaintext))) return "SEED test decryption failed."; return NULL; } static gcry_cipher_oid_spec_t seed_oids[] = { { "1.2.410.200004.1.3", GCRY_CIPHER_MODE_ECB }, { "1.2.410.200004.1.4", GCRY_CIPHER_MODE_CBC }, { "1.2.410.200004.1.5", GCRY_CIPHER_MODE_CFB }, { "1.2.410.200004.1.6", GCRY_CIPHER_MODE_OFB }, { NULL } }; gcry_cipher_spec_t _gcry_cipher_spec_seed = { GCRY_CIPHER_SEED, {0, 0}, "SEED", NULL, seed_oids, 16, 128, sizeof (SEED_context), seed_setkey, seed_encrypt, seed_decrypt, }; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index bb16d48d..f9fbb553 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -1,280 +1,280 @@ /* cipher-proto.h - Internal declarations * Copyright (C) 2008, 2011 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 . */ /* This file has been factored out from cipher.h so that it can be used standalone in visibility.c . */ #ifndef G10_CIPHER_PROTO_H #define G10_CIPHER_PROTO_H enum pk_encoding; /* Definition of a function used to report selftest failures. DOMAIN is a string describing the function block: "cipher", "digest", "pubkey or "random", ALGO is the algorithm under test, WHAT is a string describing what has been tested, DESC is a string describing the error. */ typedef void (*selftest_report_func_t)(const char *domain, int algo, const char *what, const char *errdesc); /* Definition of the selftest functions. */ typedef gpg_err_code_t (*selftest_func_t) (int algo, int extended, selftest_report_func_t report); /* * * Public key related definitions. * */ /* Type for the pk_generate function. */ typedef gcry_err_code_t (*gcry_pk_generate_t) (gcry_sexp_t genparms, gcry_sexp_t *r_skey); /* Type for the pk_check_secret_key function. */ typedef gcry_err_code_t (*gcry_pk_check_secret_key_t) (gcry_sexp_t keyparms); /* Type for the pk_encrypt function. */ typedef gcry_err_code_t (*gcry_pk_encrypt_t) (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_decrypt function. */ typedef gcry_err_code_t (*gcry_pk_decrypt_t) (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_sign function. */ typedef gcry_err_code_t (*gcry_pk_sign_t) (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_verify function. */ typedef gcry_err_code_t (*gcry_pk_verify_t) (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms); /* Type for the pk_get_nbits function. */ typedef unsigned (*gcry_pk_get_nbits_t) (gcry_sexp_t keyparms); /* The type used to compute the keygrip. */ typedef gpg_err_code_t (*pk_comp_keygrip_t) (gcry_md_hd_t md, gcry_sexp_t keyparm); /* The type used to query an ECC curve name. */ typedef const char *(*pk_get_curve_t)(gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits); /* The type used to query ECC curve parameters by name. */ typedef gcry_sexp_t (*pk_get_curve_param_t)(const char *name); /* Module specification structure for public key algorithms. */ typedef struct gcry_pk_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; int use; const char *name; const char **aliases; const char *elements_pkey; const char *elements_skey; const char *elements_enc; const char *elements_sig; const char *elements_grip; gcry_pk_generate_t generate; gcry_pk_check_secret_key_t check_secret_key; gcry_pk_encrypt_t encrypt; gcry_pk_decrypt_t decrypt; gcry_pk_sign_t sign; gcry_pk_verify_t verify; gcry_pk_get_nbits_t get_nbits; selftest_func_t selftest; pk_comp_keygrip_t comp_keygrip; pk_get_curve_t get_curve; pk_get_curve_param_t get_curve_param; } gcry_pk_spec_t; /* * * Symmetric cipher related definitions. * */ -typedef struct cipher_bulk_ops cipher_bulk_ops_t; +struct cipher_bulk_ops; /* Type for the cipher_setkey function. */ typedef gcry_err_code_t (*gcry_cipher_setkey_t) (void *c, const unsigned char *key, unsigned keylen, - cipher_bulk_ops_t *bulk_ops); + struct cipher_bulk_ops *bulk_ops); /* Type for the cipher_encrypt function. */ typedef unsigned int (*gcry_cipher_encrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf); /* Type for the cipher_decrypt function. */ typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf); /* Type for the cipher_stencrypt function. */ typedef void (*gcry_cipher_stencrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, size_t n); /* Type for the cipher_stdecrypt function. */ typedef void (*gcry_cipher_stdecrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, size_t n); /* The type used to convey additional information to a cipher. */ typedef gpg_err_code_t (*cipher_set_extra_info_t) (void *c, int what, const void *buffer, size_t buflen); /* The type used to set an IV directly in the algorithm module. */ typedef void (*cipher_setiv_func_t)(void *c, const byte *iv, size_t ivlen); /* A structure to map OIDs to encryption modes. */ typedef struct gcry_cipher_oid_spec { const char *oid; int mode; } gcry_cipher_oid_spec_t; /* Module specification structure for ciphers. */ typedef struct gcry_cipher_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; const char **aliases; gcry_cipher_oid_spec_t *oids; size_t blocksize; size_t keylen; size_t contextsize; gcry_cipher_setkey_t setkey; gcry_cipher_encrypt_t encrypt; gcry_cipher_decrypt_t decrypt; gcry_cipher_stencrypt_t stencrypt; gcry_cipher_stdecrypt_t stdecrypt; selftest_func_t selftest; cipher_set_extra_info_t set_extra_info; cipher_setiv_func_t setiv; } gcry_cipher_spec_t; /* * * Message digest related definitions. * */ /* Type for the md_init function. */ typedef void (*gcry_md_init_t) (void *c, unsigned int flags); /* Type for the md_write function. */ typedef void (*gcry_md_write_t) (void *c, const void *buf, size_t nbytes); /* Type for the md_final function. */ typedef void (*gcry_md_final_t) (void *c); /* Type for the md_read function. */ typedef unsigned char *(*gcry_md_read_t) (void *c); /* Type for the md_extract function. */ typedef void (*gcry_md_extract_t) (void *c, void *outbuf, size_t nbytes); /* Type for the md_hash_buffer function. */ typedef void (*gcry_md_hash_buffer_t) (void *outbuf, const void *buffer, size_t length); /* Type for the md_hash_buffers function. */ typedef void (*gcry_md_hash_buffers_t) (void *outbuf, const gcry_buffer_t *iov, int iovcnt); typedef struct gcry_md_oid_spec { const char *oidstring; } gcry_md_oid_spec_t; /* Module specification structure for message digests. */ typedef struct gcry_md_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; unsigned char *asnoid; int asnlen; gcry_md_oid_spec_t *oids; int mdlen; gcry_md_init_t init; gcry_md_write_t write; gcry_md_final_t final; gcry_md_read_t read; gcry_md_extract_t extract; gcry_md_hash_buffer_t hash_buffer; gcry_md_hash_buffers_t hash_buffers; size_t contextsize; /* allocate this amount of context */ selftest_func_t selftest; } gcry_md_spec_t; /* The selftest functions. */ gcry_error_t _gcry_cipher_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_md_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_pk_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_mac_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_kdf_selftest (int algo, int extended, selftest_report_func_t report); gcry_error_t _gcry_random_selftest (selftest_report_func_t report); #endif /*G10_CIPHER_PROTO_H*/