From jussi.kivilinna at iki.fi Fri Nov 1 14:35:22 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 01 Nov 2013 15:35:22 +0200 Subject: [PATCH] Add CMAC mode (Cipher-based MAC) In-Reply-To: <871u31mqlv.fsf@vigenere.g10code.de> References: <871u31mqlv.fsf@vigenere.g10code.de> Message-ID: <20131101133430.25415.20522.stgit@localhost6.localdomain6> On 31.10.2013 17:01, Werner Koch wrote: > On Thu, 31 Oct 2013 13:41, jussi.kivilinna at iki.fi said: > > > Patch adds CMAC (Cipher-based MAC) mode as defined in RFC 4493 and NIST > > Special Publication 800-38B. > > > > Example of usage: > > /* Message 1 is split to two buffers, buf1_a and buf1_b. */ > > gcry_cipher_setkey(h, key, len(key)); > > I wonder whether it is a good idea to put MAC algorithms into the cipher > module. It is a bit of surprise because a MAC has IMHO more of a hash > algorithm than of a cipher algorithm. Also, we already have HMAC in > gcry_md_*. Right, there is quite some overlap now with the > authenticated methods. The later are however justified in gcry_cipher > because their main purpose is encryption. > > Opinions? I actually initially made patch that adds CMAC to gcry_md_*, because HMAC existing there already. I've attached this patch below. Problem with this is how to define CMAC.. should it be defined as one 'hash' with some method to select underlying block cipher. How do we map block cipher names to hash names, etc? Or do we select limited set of block ciphers that each provide new hash algorithm (as done in the patch below; GCRY_MD_CMAC_AES, _DES, _CAMELLIA, selected because existing documentation/test vectors). This obviously limits chooses for library user. Whatever that's good or bad, I don't know. The patch below also adds new cmac hacks to core gcry_md code which is why I don't particularly like the approach. Since adding GCM mode kind of adds GHASH to gcry_cipher as side product and CBC-MAC already is provided in gcry_cipher, adding CMAC to gcry_cipher seems much cleaner option. -Jussi --- cipher/Makefile.am | 1 cipher/cmac.c | 344 ++++++++++++++++++++++++++++++++++++++++++++++++++++ cipher/md.c | 76 +++++++++++ src/cipher.h | 15 ++ src/gcrypt.h.in | 6 + tests/basic.c | 232 +++++++++++++++++++++++++++++------ tests/benchmark.c | 57 ++++++++- 7 files changed, 677 insertions(+), 54 deletions(-) create mode 100644 cipher/cmac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 87f693e..ffe8294 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -46,6 +46,7 @@ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ kdf.c kdf-internal.h \ hmac-tests.c \ +cmac.c \ bithelp.h \ bufhelp.h \ primegen.c \ diff --git a/cipher/cmac.c b/cipher/cmac.c new file mode 100644 index 0000000..03994b3 --- /dev/null +++ b/cipher/cmac.c @@ -0,0 +1,344 @@ +/* cmac.c - CMAC, Cipher-based MAC. + * Copyright ? 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 "g10lib.h" +#include "cipher.h" +#include "cipher-internal.h" +#include "bufhelp.h" + + +#define MAX_BLOCKSIZE 16 +#define MAX_KEYLEN 32 + +struct cmac_context { + gcry_cipher_hd_t hd; + unsigned int blocksize, count, initialized; + int keylen, md_algo, secure; + byte buf[MAX_BLOCKSIZE], key[MAX_KEYLEN]; + byte k[2][MAX_BLOCKSIZE]; +}; + + +static int +cmac_md_to_cipher (int md_algo) +{ + switch (md_algo) { + case GCRY_MD_CMAC_AES: + return GCRY_CIPHER_AES; + case GCRY_MD_CMAC_3DES: + return GCRY_CIPHER_3DES; + case GCRY_MD_CMAC_CAMELLIA: + return GCRY_CIPHER_CAMELLIA128; + default: + return -1; + } +} + + +gcry_err_code_t +_gcry_cmac_init (void *_ctx, int md_algo, int secure) +{ + struct cmac_context *ctx = _ctx; + gcry_err_code_t err; + int flags, cipher_algo; + unsigned int blocksize; + + memset (ctx, 0, sizeof(*ctx)); + + flags = GCRY_CIPHER_CBC_MAC; + if (secure) + flags |= GCRY_CIPHER_SECURE; + + cipher_algo = cmac_md_to_cipher(md_algo); + if (cipher_algo <= 0) + return GPG_ERR_INV_ARG; + + /* Only blocksizes 8 and 16 are supported. */ + blocksize = gcry_cipher_get_algo_blklen(cipher_algo); + if (blocksize != 8 && blocksize != 16) + return GPG_ERR_INV_ARG; + + err = _gcry_cipher_open (&ctx->hd, cipher_algo, GCRY_CIPHER_MODE_CBC, flags); + if (err) + return err; + + ctx->count = 0; + ctx->blocksize = blocksize; + ctx->initialized = 1; + ctx->keylen = -1; + ctx->md_algo = md_algo; + + return GPG_ERR_NO_ERROR; +} + + +void +_gcry_cmac_close (void *_ctx) +{ + struct cmac_context *ctx = _ctx; + + if (!ctx->initialized) + return; + + _gcry_cipher_close (ctx->hd); + + wipememory (ctx, sizeof(*ctx)); + ctx->hd = 0; + ctx->keylen = -1; + ctx->initialized = 0; + ctx->count = 0; +} + + +gcry_error_t +_gcry_cmac_setkey (void *_ctx, const byte *key, unsigned int keylen) +{ + struct cmac_context *ctx = _ctx; + unsigned int blocksize = ctx->blocksize; + gcry_err_code_t err; + byte buf[MAX_BLOCKSIZE]; + int j, i; + unsigned int t, bi, carry, rb; + + if (!ctx->initialized || keylen > MAX_KEYLEN) + return GPG_ERR_INV_ARG; + + err = _gcry_cipher_setkey (ctx->hd, key, keylen); + if (err) + return err; + + memcpy (ctx->key, key, keylen); + ctx->keylen = keylen; + + /* encrypt zero block */ + memset (ctx->hd->u_iv.iv, 0, blocksize); + memset (buf, 0, blocksize); + err = _gcry_cipher_cbc_encrypt (ctx->hd, buf, blocksize, buf, blocksize); + if (err) + BUG(); + + rb = blocksize == 16 ? 0x87 : 0x1B /*blocksize == 8*/; + + for (j = 0; j < 2; j++) + { + /* Generate subkeys K1 and K2 */ + carry = 0; + for (i = blocksize - 1; i >= 0; i--) + { + bi = buf[i]; + t = carry | (bi << 1); + carry = bi >> 7; + ctx->k[j][i] = buf[i] = t & 0xff; + } + ctx->k[j][blocksize - 1] = buf[blocksize - 1] ^= carry ? rb : 0; + } + + /* set C_0 to zero */ + memset (ctx->hd->u_iv.iv, 0, blocksize); + + wipememory(buf, sizeof(buf)); + + return err; +} + + +gcry_err_code_t +_gcry_cmac_reset (void *_ctx) +{ + struct cmac_context *ctx = _ctx; + gcry_err_code_t err; + int keylen, md_algo, secure; + byte key[MAX_KEYLEN]; + + keylen = ctx->keylen; + md_algo = ctx->md_algo; + secure = ctx->secure; + if (keylen >= 0) + memcpy (key, ctx->key, keylen); + + if (!ctx->initialized) + _gcry_cmac_close (ctx); + + err = _gcry_cmac_init (ctx, md_algo, secure); + if (err) + return err; + + if (keylen >= 0) + _gcry_cmac_setkey(ctx, key, keylen); + + wipememory (key, sizeof(key)); + + return err; +} + + +gcry_err_code_t +_gcry_cmac_copy_context (void *_new_ctx, void *_old_ctx) +{ + struct cmac_context *new_ctx = _new_ctx; + struct cmac_context *old_ctx = _old_ctx; + gcry_err_code_t err; + + new_ctx->hd = NULL; + new_ctx->initialized = 0; + + err = _gcry_cmac_reset(new_ctx); + if (err) + return err; + + new_ctx->count = old_ctx->count; + memcpy(new_ctx->buf, old_ctx->buf, sizeof(old_ctx->buf)); + + if (new_ctx->initialized && old_ctx->initialized) + memcpy(new_ctx->hd->u_iv.iv, old_ctx->hd->u_iv.iv, new_ctx->blocksize); + + return err; +} + + +static void +cmac_write (void *_ctx, const void *_buf, size_t inlen) +{ + struct cmac_context *ctx = _ctx; + unsigned int blocksize = ctx->blocksize; + const byte *inbuf = _buf; + gcry_err_code_t err; + byte outbuf[MAX_BLOCKSIZE]; + unsigned int nb; + + if (ctx->keylen < 0) + BUG(); + + if (!inlen || !inbuf) + return; + + /* Last block is needed for cmac_final. */ + if (ctx->count + inlen <= blocksize) + { + for (; inlen && ctx->count < blocksize; inlen--) + ctx->buf[ctx->count++] = *inbuf++; + return; + } + + if (ctx->count) + { + for (; inlen && ctx->count < blocksize; inlen--) + ctx->buf[ctx->count++] = *inbuf++; + + err = _gcry_cipher_cbc_encrypt (ctx->hd, outbuf, blocksize, ctx->buf, + blocksize); + if (err) + BUG(); + ctx->count = 0; + } + + if (inlen > blocksize) + { + nb = inlen / blocksize; + nb -= (nb * blocksize == inlen); + err = _gcry_cipher_cbc_encrypt (ctx->hd, outbuf, blocksize, inbuf, + nb * blocksize); + if (err) + BUG(); + inlen -= nb * blocksize; + inbuf += nb * blocksize; + } + + if (inlen == 0) + BUG(); + for (; inlen && ctx->count < blocksize; inlen--) + ctx->buf[ctx->count++] = *inbuf++; + + wipememory(outbuf, sizeof(outbuf)); +} + + +static void +cmac_final (void *_ctx) +{ + struct cmac_context *ctx = _ctx; + unsigned int blocksize = ctx->blocksize; + unsigned int count = ctx->count; + gcry_err_code_t err; + byte *subkey; + + if (count == blocksize) + subkey = ctx->k[0]; /* K1 */ + else + { + subkey = ctx->k[1]; /* K2 */ + ctx->buf[count++] = 0x80; + while (count < blocksize) + ctx->buf[count++] = 0; + } + + buf_xor( ctx->buf, ctx->buf, subkey, blocksize); + + err = _gcry_cipher_cbc_encrypt (ctx->hd, ctx->buf, blocksize, ctx->buf, + blocksize); + if (err) + BUG(); + + ctx->count = 0; +} + + +static byte * +cmac_read (void *_ctx) +{ + struct cmac_context *ctx = _ctx; + + return ctx->buf; +} + + +#ifdef USE_AES +gcry_md_spec_t _gcry_digest_spec_cmac_aes = + { + GCRY_MD_CMAC_AES, {0, 0}, + "CMAC_AES", NULL, 0, NULL, 16, + NULL, cmac_write, cmac_final, cmac_read, + sizeof (struct cmac_context) + }; +#endif + +#ifdef USE_DES +gcry_md_spec_t _gcry_digest_spec_cmac_3des = + { + GCRY_MD_CMAC_3DES, {0, 0}, + "CMAC_3DES", NULL, 0, NULL, 8, + NULL, cmac_write, cmac_final, cmac_read, + sizeof (struct cmac_context) + }; +#endif + +#ifdef USE_CAMELLIA +gcry_md_spec_t _gcry_digest_spec_cmac_camellia = + { + GCRY_MD_CMAC_CAMELLIA, {0, 0}, + "CMAC_CAMELLIA", NULL, 0, NULL, 16, + NULL, cmac_write, cmac_final, cmac_read, + sizeof (struct cmac_context) + }; +#endif diff --git a/cipher/md.c b/cipher/md.c index 5c66397..fab73db 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -76,6 +76,16 @@ static gcry_md_spec_t *digest_list[] = #if USE_MD4 &_gcry_digest_spec_md4, #endif +/* CMAC algorithms. */ +#if USE_AES + &_gcry_digest_spec_cmac_aes, +#endif +#if USE_DES + &_gcry_digest_spec_cmac_3des, +#endif +#if USE_CAMELLIA + &_gcry_digest_spec_cmac_camellia, +#endif NULL }; @@ -97,6 +107,7 @@ struct gcry_md_context int secure; FILE *debug; int finalized; + int is_cmac; GcryDigestEntry *list; byte *macpads; int macpads_Bsize; /* Blocksize as used for the HMAC pads. */ @@ -118,6 +129,16 @@ static void md_stop_debug ( gcry_md_hd_t a ); static int +is_algo_cmac(int algo) +{ + return algo == GCRY_MD_CMAC_AES || + algo == GCRY_MD_CMAC_3DES || + algo == GCRY_MD_CMAC_CAMELLIA; +} + + + +static int map_algo (int algo) { return algo; @@ -371,6 +392,8 @@ gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) if ((flags & ~(GCRY_MD_FLAG_SECURE | GCRY_MD_FLAG_HMAC))) err = GPG_ERR_INV_ARG; + else if ((flags & GCRY_MD_FLAG_HMAC) && is_algo_cmac(algo)) + err = GPG_ERR_INV_ARG; else { err = md_open (&hd, algo, (flags & GCRY_MD_FLAG_SECURE), @@ -382,7 +405,6 @@ gcry_md_open (gcry_md_hd_t *h, int algo, unsigned int flags) } - static gcry_err_code_t md_enable (gcry_md_hd_t hd, int algorithm) { @@ -391,6 +413,12 @@ md_enable (gcry_md_hd_t hd, int algorithm) GcryDigestEntry *entry; gcry_err_code_t err = 0; + if (h->list != NULL && (h->is_cmac || is_algo_cmac(algorithm))) + return GPG_ERR_DIGEST_ALGO; /* Allow only one CMAC. */ + + if (!h->is_cmac && is_algo_cmac(algorithm)) + h->is_cmac = 1; + for (entry = h->list; entry; entry = entry->next) if (entry->spec->algo == algorithm) return 0; /* Already enabled */ @@ -436,7 +464,10 @@ md_enable (gcry_md_hd_t hd, int algorithm) h->list = entry; /* And init this instance. */ - entry->spec->init (&entry->context.c); + if (h->is_cmac) + err = _gcry_cmac_init (&entry->context.c, algorithm, h->secure); + else + entry->spec->init (&entry->context.c); } } @@ -520,8 +551,17 @@ md_copy (gcry_md_hd_t ahd, gcry_md_hd_t *b_hd) memcpy (br, ar, (sizeof (*br) + ar->spec->contextsize - sizeof (ar->context))); + br->next = b->list; b->list = br; + + if (a->is_cmac) + { + err = _gcry_cmac_copy_context (br->context.c, ar->context.c); + if (err) + md_close (bhd); + break; /* Only one CMAC. */ + } } } @@ -560,6 +600,13 @@ gcry_md_reset (gcry_md_hd_t a) a->bufpos = a->ctx->finalized = 0; + if (a->ctx->is_cmac && a->ctx->list) + { + r = a->ctx->list; + _gcry_cmac_reset (&r->context.c); + return; + } + for (r = a->ctx->list; r; r = r->next) { memset (r->context.c, 0, r->spec->contextsize); @@ -579,6 +626,13 @@ md_close (gcry_md_hd_t a) return; if (a->ctx->debug) md_stop_debug (a); + + if (a->ctx->is_cmac && a->ctx->list) + { + r = a->ctx->list; + _gcry_cmac_close (&r->context.c); + } + for (r = a->ctx->list; r; r = r2) { r2 = r->next; @@ -742,7 +796,12 @@ gcry_md_setkey (gcry_md_hd_t hd, const void *key, size_t keylen) { gcry_err_code_t rc; - if (!hd->ctx->macpads) + if (hd->ctx->is_cmac && hd->ctx->list) + { + GcryDigestEntry *r = hd->ctx->list; + rc = _gcry_cmac_setkey (&r->context.c, key, keylen); + } + else if (!hd->ctx->macpads) rc = GPG_ERR_CONFLICT; else { @@ -885,6 +944,8 @@ gcry_md_hash_buffer (int algo, void *digest, this function into a HMAC function; the first item in IOV is then used as the key. + For CMAC functions, the first item in IOV is used as the key. + On success 0 is returned and resulting hash or HMAC is stored at DIGEST which must have been provided by the caller with an appropriate length. */ @@ -892,7 +953,7 @@ gpg_err_code_t gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, const gcry_buffer_t *iov, int iovcnt) { - int hmac; + int hmac, cmac; if (!iov || iovcnt < 0) return GPG_ERR_INV_ARG; @@ -900,7 +961,10 @@ gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, return GPG_ERR_INV_ARG; hmac = !!(flags & GCRY_MD_FLAG_HMAC); - if (hmac && iovcnt < 1) + cmac = is_algo_cmac(algo); + if (hmac && cmac) + return GPG_ERR_INV_ARG; + if ((hmac || cmac) && iovcnt < 1) return GPG_ERR_INV_ARG; if (algo == GCRY_MD_SHA1 && !hmac) @@ -927,7 +991,7 @@ gcry_md_hash_buffers (int algo, unsigned int flags, void *digest, if (rc) return rc; - if (hmac) + if (hmac || cmac) { rc = gcry_err_code (gcry_md_setkey (h, (const char*)iov[0].data + iov[0].off, diff --git a/src/cipher.h b/src/cipher.h index 551dc66..a7796b8 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -94,6 +94,18 @@ void _gcry_sha1_hash_buffer (void *outbuf, void _gcry_sha1_hash_buffers (void *outbuf, const gcry_buffer_t *iov, int iovcnt); +/*-- cmac.c --*/ +gcry_err_code_t _gcry_cmac_init (void *_ctx, int md_algo, int secure); + +void _gcry_cmac_close (void *_ctx); + +gcry_err_code_t _gcry_cmac_reset (void *_ctx); + +gcry_err_code_t _gcry_cmac_copy_context (void *_new_ctx, void *_old_ctx); + +gcry_error_t _gcry_cmac_setkey (void *_ctx, const byte *key, + unsigned int keylen); + /*-- rijndael.c --*/ void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf, const void *inbuf, @@ -233,6 +245,9 @@ extern gcry_md_spec_t _gcry_digest_spec_tiger; extern gcry_md_spec_t _gcry_digest_spec_tiger1; extern gcry_md_spec_t _gcry_digest_spec_tiger2; extern gcry_md_spec_t _gcry_digest_spec_whirlpool; +extern gcry_md_spec_t _gcry_digest_spec_cmac_aes; +extern gcry_md_spec_t _gcry_digest_spec_cmac_3des; +extern gcry_md_spec_t _gcry_digest_spec_cmac_camellia; /* Declarations for the pubkey cipher specifications. */ extern gcry_pk_spec_t _gcry_pubkey_spec_rsa; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 2d27fdb..ffe03f3 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1127,7 +1127,11 @@ enum gcry_md_algos GCRY_MD_TIGER2 = 307, /* TIGER2 variant. */ GCRY_MD_GOSTR3411_94 = 308, /* GOST R 34.11-94. */ GCRY_MD_STRIBOG256 = 309, /* GOST R 34.11-2012, 256 bit. */ - GCRY_MD_STRIBOG512 = 310 /* GOST R 34.11-2012, 512 bit. */ + GCRY_MD_STRIBOG512 = 310, /* GOST R 34.11-2012, 512 bit. */ + /* CMAC algorithms */ + GCRY_MD_CMAC_AES = 311, + GCRY_MD_CMAC_3DES = 312, + GCRY_MD_CMAC_CAMELLIA = 313, }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index f89895a..0142979 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -3957,8 +3957,8 @@ check_digests (void) } static void -check_one_hmac (int algo, const char *data, int datalen, - const char *key, int keylen, const char *expect) +check_one_md_mac (int algo, int flags, const char *data, int datalen, + const char *key, int keylen, const char *expect) { gcry_md_hd_t hd, hd2; unsigned char *p; @@ -3966,7 +3966,7 @@ check_one_hmac (int algo, const char *data, int datalen, int i; gcry_error_t err = 0; - err = gcry_md_open (&hd, algo, GCRY_MD_FLAG_HMAC); + err = gcry_md_open (&hd, algo, flags); if (err) { fail ("algo %d, gcry_md_open failed: %s\n", algo, gpg_strerror (err)); @@ -4013,30 +4013,33 @@ check_one_hmac (int algo, const char *data, int datalen, } static void -check_hmac (void) +check_md_mac (void) { static const struct algos { int md; + int flags; const char *data; const char *key; const char *expect; } algos[] = { - { GCRY_MD_MD5, "what do ya want for nothing?", "Jefe", + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, + "what do ya want for nothing?", + "Jefe", "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" }, - { GCRY_MD_MD5, + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" }, - { GCRY_MD_MD5, + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" }, - { GCRY_MD_MD5, + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" @@ -4044,10 +4047,12 @@ check_hmac (void) "\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", "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" }, - { GCRY_MD_MD5, "Test With Truncation", + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, + "Test With Truncation", "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" }, - { GCRY_MD_MD5, "Test Using Larger Than Block-Size Key - Hash Key First", + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, + "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" @@ -4055,7 +4060,7 @@ check_hmac (void) "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa", "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" }, - { GCRY_MD_MD5, + { GCRY_MD_MD5, GCRY_MD_FLAG_HMAC, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" @@ -4064,16 +4069,18 @@ check_hmac (void) "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" "\xaa\xaa\xaa\xaa\xaa", "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", }, - { GCRY_MD_SHA256, "what do ya want for nothing?", "Jefe", + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, + "what do ya want for nothing?", + "Jefe", "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a" "\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" }, - { GCRY_MD_SHA256, + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88" "\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" }, - { GCRY_MD_SHA256, + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" @@ -4082,7 +4089,7 @@ check_hmac (void) "\xAA\xAA\xAA\xAA", "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7" "\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" }, - { GCRY_MD_SHA256, + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" @@ -4091,7 +4098,7 @@ check_hmac (void) "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08" "\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" }, - { GCRY_MD_SHA256, + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, "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" @@ -4104,7 +4111,7 @@ check_hmac (void) "\xaa\xaa\xaa", "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f" "\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" }, - { GCRY_MD_SHA256, + { GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC, "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" @@ -4117,16 +4124,18 @@ check_hmac (void) "\xaa\xaa\xaa", "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44" "\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" }, - { GCRY_MD_SHA224, "what do ya want for nothing?", "Jefe", + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, + "what do ya want for nothing?", + "Jefe", "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" }, - { GCRY_MD_SHA224, + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47" "\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" }, - { GCRY_MD_SHA224, + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" @@ -4135,7 +4144,7 @@ check_hmac (void) "\xAA\xAA\xAA\xAA", "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64" "\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" }, - { GCRY_MD_SHA224, + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" @@ -4144,7 +4153,7 @@ check_hmac (void) "\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19", "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62" "\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" }, - { GCRY_MD_SHA224, + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, "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" @@ -4157,7 +4166,7 @@ check_hmac (void) "\xaa\xaa\xaa", "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" }, - { GCRY_MD_SHA224, + { GCRY_MD_SHA224, GCRY_MD_FLAG_HMAC, "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" @@ -4170,18 +4179,19 @@ check_hmac (void) "\xaa\xaa\xaa", "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" "\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" }, - { GCRY_MD_SHA384, "what do ya want for nothing?", "Jefe", + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, + "what do ya want for nothing?", "Jefe", "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e" "\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" }, - { GCRY_MD_SHA384, + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15" "\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea" "\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" }, - { GCRY_MD_SHA384, + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" @@ -4191,7 +4201,7 @@ check_hmac (void) "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f" "\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b" "\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" }, - { GCRY_MD_SHA384, + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" @@ -4201,7 +4211,7 @@ check_hmac (void) "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7" "\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e" "\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" }, - { GCRY_MD_SHA384, + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, "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" @@ -4215,7 +4225,7 @@ check_hmac (void) "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" "\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" }, - { GCRY_MD_SHA384, + { GCRY_MD_SHA384, GCRY_MD_FLAG_HMAC, "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" @@ -4229,12 +4239,14 @@ check_hmac (void) "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5" "\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" }, - { GCRY_MD_SHA512, "what do ya want for nothing?", "Jefe", + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, + "what do ya want for nothing?", + "Jefe", "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" "\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54" "\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" }, - { GCRY_MD_SHA512, + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, "Hi There", "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" "\x0b\x0b\x0b", @@ -4242,7 +4254,7 @@ check_hmac (void) "\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" }, - { GCRY_MD_SHA512, + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" @@ -4253,7 +4265,7 @@ check_hmac (void) "\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39" "\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07" "\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" }, - { GCRY_MD_SHA512, + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" @@ -4264,7 +4276,7 @@ check_hmac (void) "\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb" "\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63" "\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" }, - { GCRY_MD_SHA512, + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, "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" @@ -4279,7 +4291,7 @@ check_hmac (void) "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52" "\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" }, - { GCRY_MD_SHA512, + { GCRY_MD_SHA512, GCRY_MD_FLAG_HMAC, "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" @@ -4294,6 +4306,146 @@ check_hmac (void) "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + /* CMAC AES and DES test vectors from + http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publications/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ + { GCRY_MD_CMAC_AES, 0, + "", + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "", + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "", + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_AES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "", + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "", + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + { GCRY_MD_CMAC_3DES, 0, + "\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" }, + /* CMAC Camellia test vectors from + http://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */ + { GCRY_MD_CMAC_CAMELLIA, 0, + "", + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\xba\x92\x57\x82\xaa\xa1\xf5\xd9\xa0\x0f\x89\x64\x80\x94\xfc\x71" }, + { GCRY_MD_CMAC_CAMELLIA, 0, + "\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", + "\x6d\x96\x28\x54\xa3\xb9\xfd\xa5\x6d\x7d\x45\xa9\x5e\xe1\x79\x93" }, + { GCRY_MD_CMAC_CAMELLIA, 0, + "\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", + "\x5c\x18\xd1\x19\xcc\xd6\x76\x61\x44\xac\x18\x66\x13\x1d\x9f\x22" }, + { GCRY_MD_CMAC_CAMELLIA, 0, + "\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", + "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" }, { 0 }, }; int i; @@ -4318,14 +4470,14 @@ check_hmac (void) algos[i].md, strlen(algos[i].key), strlen(algos[i].data)); - check_one_hmac (algos[i].md, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), - algos[i].expect); + check_one_md_mac (algos[i].md, algos[i].flags, algos[i].data, + strlen (algos[i].data), algos[i].key, + strlen (algos[i].key), algos[i].expect); } if (verbose) fprintf (stderr, "Completed hashed MAC checks.\n"); - } +} /* Check that the signature SIG matches the hash HASH. PKEY is the public key used for the verification. BADHASH is a hash value which @@ -5282,7 +5434,7 @@ main (int argc, char **argv) check_cipher_modes (); check_bulk_cipher_modes (); check_digests (); - check_hmac (); + check_md_mac (); check_pubkey (); } diff --git a/tests/benchmark.c b/tests/benchmark.c index 8326ab2..7d4d2bb 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -328,15 +328,19 @@ md_bench ( const char *algoname ) { int algo; gcry_md_hd_t hd; - int i, j, repcount; + int i, j, repcount, cmac; char buf_base[1000+15]; size_t bufsize = 1000; char *buf; char *largebuf_base; char *largebuf; char digest[512/8]; + unsigned int keylen; + char key[192/8]; gcry_error_t err = GPG_ERR_NO_ERROR; + cmac = 0; + if (!algoname) { for (i=1; i < 400; i++) @@ -366,7 +370,25 @@ md_bench ( const char *algoname ) for (i=0; i < bufsize; i++) buf[i] = i; - printf ("%-12s", gcry_md_algo_name (algo)); + printf ("%-13s", gcry_md_algo_name (algo)); + + /* CMAC algorithms require key. */ + if (algo == GCRY_MD_CMAC_AES || + algo == GCRY_MD_CMAC_3DES || + algo == GCRY_MD_CMAC_CAMELLIA) + { + keylen = ((algo == GCRY_MD_CMAC_3DES) ? 192 : 128) / 8; + cmac = 1; + for (i = 0; i < keylen; i++) + key[i] = i ^ 0xff; + err = gcry_md_setkey (hd, key, keylen); + if (err) + { + fprintf (stderr, PGM ": could not set key for CMAC algorithm `%s'\n", + algoname); + exit (1); + } + } start_timer (); for (repcount=0; repcount < hash_repetitions; repcount++) @@ -423,11 +445,32 @@ md_bench ( const char *algoname ) for (i=0; i < 10000; i++) largebuf[i] = i; - start_timer (); - for (repcount=0; repcount < hash_repetitions; repcount++) - for (i=0; i < 100; i++) - gcry_md_hash_buffer (algo, digest, largebuf, 10000); - stop_timer (); + if (cmac) + { + gcry_buffer_t iovs[2]; + + iovs[0].data = key; + iovs[0].off = 0; + iovs[0].len = keylen; + + iovs[1].data = largebuf; + iovs[1].off = 0; + iovs[1].len = 10000; + + start_timer (); + for (repcount=0; repcount < hash_repetitions; repcount++) + for (i=0; i < 100; i++) + gcry_md_hash_buffers (algo, 0, digest, iovs, 2); + stop_timer (); + } + else + { + start_timer (); + for (repcount=0; repcount < hash_repetitions; repcount++) + for (i=0; i < 100; i++) + gcry_md_hash_buffer (algo, digest, largebuf, 10000); + stop_timer (); + } printf (" %s", elapsed_time ()); free (largebuf_base); From jussi.kivilinna at iki.fi Mon Nov 4 14:00:21 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 04 Nov 2013 15:00:21 +0200 Subject: [PATCH] Optimize Blowfish weak key check Message-ID: <20131104130021.2782.91896.stgit@localhost6.localdomain6> * cipher/blowfish.c (hashset_elem, val_to_hidx, add_val): New. (do_bf_setkey): Use faster algorithm for detecting weak keys. -- Patch optimizes the weak key check for Blowfish. Instead of iterating through sbox-tables for duplicates, insert values to hash-set and detect collisions. Old check code was taking slightly longer time than the actual key setup of Blowfish, which by itself is already quite slow. After: $ tests/benchmark --cipher-with-keysetup --cipher-repetitions 10 cipher blowfish Running each test 10 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- BLOWFISH 410ms 440ms 430ms 370ms 440ms 370ms 430ms 440ms 370ms 370ms - - Before: $ tests/benchmark --cipher-with-keysetup --cipher-repetitions 10 cipher blowfish Running each test 10 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- BLOWFISH 780ms 770ms 780ms 730ms 780ms 730ms 780ms 790ms 720ms 730ms - - Without key-setup: $ tests/benchmark --cipher-repetitions 10 cipher blowfish Running each test 10 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- BLOWFISH 70ms 70ms 80ms 30ms 80ms 30ms 80ms 90ms 20ms 30ms - - Signed-off-by: Jussi Kivilinna --- cipher/blowfish.c | 98 ++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 3b6bf6b..287fc03 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -857,11 +857,67 @@ selftest(void) } +struct hashset_elem { + u32 val; + short nidx; + char used; +}; + +static inline byte +val_to_hidx(u32 val) +{ + /* bf sboxes are quite random already. */ + return (val >> 24) ^ (val >> 16) ^ (val >> 8) ^ val; +} + +static inline int +add_val(struct hashset_elem hset[256], u32 val, int *midx, + struct hashset_elem *mpool) +{ + struct hashset_elem *elem; + byte hidx; + + hidx = val_to_hidx(val); + elem = &hset[hidx]; + + /* Check if first is in use. */ + if (elem->used == 0) + { + elem->val = val; + elem->nidx = -1; + elem->used = 1; + return 0; + } + + /* Check if first matches. */ + if (elem->val == val) + return 1; + + for (; elem->nidx >= 0; elem = &mpool[elem->nidx]) + { + /* Check if elem matches. */ + if (elem->val == val) + return 1; + } + + elem->nidx = (*midx)++; + elem = &mpool[elem->nidx]; + + elem->val = val; + elem->nidx = -1; + elem->used = 1; + + return 0; +} static gcry_err_code_t do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) { - int i, j; + struct hashset_elem mempool[4 * 255]; /* Enough entries for the worst case. */ + struct hashset_elem hset[4][256]; + int memidx = 0; + int weak = 0; + int i, j, ret; u32 data, datal, datar; static int initialized; static const char *selftest_failed; @@ -876,6 +932,8 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) if( selftest_failed ) return GPG_ERR_SELFTEST_FAILED; + memset(hset, 0, sizeof(hset)); + for(i=0; i < BLOWFISH_ROUNDS+2; i++ ) c->p[i] = ps[i]; for(i=0; i < 256; i++ ) @@ -908,38 +966,58 @@ do_bf_setkey (BLOWFISH_context *c, const byte *key, unsigned keylen) do_encrypt( c, &datal, &datar ); c->s0[i] = datal; c->s0[i+1] = datar; + + /* Add values to hashset, detect duplicates (weak keys). */ + ret = add_val (hset[0], datal, &memidx, mempool); + weak = ret ? 1 : weak; + ret = add_val (hset[0], datar, &memidx, mempool); + weak = ret ? 1 : weak; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s1[i] = datal; c->s1[i+1] = datar; + + /* Add values to hashset, detect duplicates (weak keys). */ + ret = add_val (hset[1], datal, &memidx, mempool); + weak = ret ? 1 : weak; + ret = add_val (hset[1], datar, &memidx, mempool); + weak = ret ? 1 : weak; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s2[i] = datal; c->s2[i+1] = datar; + + /* Add values to hashset, detect duplicates (weak keys). */ + ret = add_val (hset[2], datal, &memidx, mempool); + weak = ret ? 1 : weak; + ret = add_val (hset[2], datar, &memidx, mempool); + weak = ret ? 1 : weak; } for(i=0; i < 256; i += 2 ) { do_encrypt( c, &datal, &datar ); c->s3[i] = datal; c->s3[i+1] = datar; + + /* Add values to hashset, detect duplicates (weak keys). */ + ret = add_val (hset[3], datal, &memidx, mempool); + weak = ret ? 1 : weak; + ret = add_val (hset[3], datar, &memidx, mempool); + weak = ret ? 1 : weak; } + /* Clear stack. */ + wipememory(hset, sizeof(hset)); + wipememory(mempool, sizeof(mempool[0]) * memidx); /* Check for weak key. A weak key is a key in which a value in the P-array (here c) occurs more than once per table. */ - for(i=0; i < 255; i++ ) - { - for( j=i+1; j < 256; j++) - { - if( (c->s0[i] == c->s0[j]) || (c->s1[i] == c->s1[j]) || - (c->s2[i] == c->s2[j]) || (c->s3[i] == c->s3[j]) ) - return GPG_ERR_WEAK_KEY; - } - } + if (weak) + return GPG_ERR_WEAK_KEY; return GPG_ERR_NO_ERROR; } From jussi.kivilinna at iki.fi Mon Nov 4 14:01:08 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 04 Nov 2013 15:01:08 +0200 Subject: [PATCH] Make jump labels local in Salsa20 assembly Message-ID: <20131104130108.3072.51333.stgit@localhost6.localdomain6> * cipher/salsa20-amd64.S: Rename '._labels' to '.L_labels'. * cipher/salsa20-armv7-neon.S: Ditto. -- Signed-off-by: Jussi Kivilinna --- cipher/salsa20-amd64.S | 40 +++++++++++++++++----------------- cipher/salsa20-armv7-neon.S | 50 ++++++++++++++++++++++--------------------- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/cipher/salsa20-amd64.S b/cipher/salsa20-amd64.S index 691df58..e79da4e 100644 --- a/cipher/salsa20-amd64.S +++ b/cipher/salsa20-amd64.S @@ -42,8 +42,8 @@ _gcry_salsa20_amd64_keysetup: movl %eax,60(%rdi) movl %r10d,48(%rdi) cmp $256,%rdx - jb ._kbits128 -._kbits256: + jb .L_kbits128 +.L_kbits256: movl 16(%rsi),%edx movl 20(%rsi),%ecx movl 24(%rsi),%r8d @@ -60,8 +60,8 @@ _gcry_salsa20_amd64_keysetup: movl %edx,4(%rdi) movl %ecx,8(%rdi) movl %r8d,12(%rdi) - jmp ._keysetupdone -._kbits128: + jmp .L_keysetupdone +.L_kbits128: movl 0(%rsi),%edx movl 4(%rsi),%ecx movl 8(%rsi),%r8d @@ -78,7 +78,7 @@ _gcry_salsa20_amd64_keysetup: movl %edx,4(%rdi) movl %ecx,8(%rdi) movl %r8d,12(%rdi) -._keysetupdone: +.L_keysetupdone: ret .align 8 @@ -117,10 +117,10 @@ _gcry_salsa20_amd64_encrypt_blocks: mov %rdx,%rdi mov %rcx,%rdx cmp $0,%rdx - jbe ._done -._start: + jbe .L_done +.L_start: cmp $256,%rdx - jb ._bytes_are_64_128_or_192 + jb .L_bytes_are_64_128_or_192 movdqa 0(%r8),%xmm0 pshufd $0x55,%xmm0,%xmm1 pshufd $0xaa,%xmm0,%xmm2 @@ -153,7 +153,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa %xmm1,176(%rsp) movdqa %xmm2,192(%rsp) movdqa %xmm0,208(%rsp) -._bytesatleast256: +.L_bytesatleast256: movl 32(%r8),%ecx movl 52(%r8),%r9d movl %ecx,224(%rsp) @@ -192,7 +192,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 96(%rsp),%xmm13 movdqa 176(%rsp),%xmm14 movdqa 224(%rsp),%xmm15 -._mainloop1: +.L_mainloop1: movdqa %xmm1,256(%rsp) movdqa %xmm2,272(%rsp) movdqa %xmm13,%xmm1 @@ -434,7 +434,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 256(%rsp),%xmm12 movdqa 272(%rsp),%xmm0 sub $2,%rdx - ja ._mainloop1 + ja .L_mainloop1 paddd 48(%rsp),%xmm12 paddd 112(%rsp),%xmm7 paddd 160(%rsp),%xmm10 @@ -696,10 +696,10 @@ _gcry_salsa20_amd64_encrypt_blocks: add $256,%rsi add $256,%rdi cmp $256,%rdx - jae ._bytesatleast256 + jae .L_bytesatleast256 cmp $0,%rdx - jbe ._done -._bytes_are_64_128_or_192: + jbe .L_done +.L_bytes_are_64_128_or_192: movq %rdx,288(%rsp) movdqa 0(%r8),%xmm0 movdqa 16(%r8),%xmm1 @@ -707,7 +707,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 48(%r8),%xmm3 movdqa %xmm1,%xmm4 mov %rbx,%rdx -._mainloop2: +.L_mainloop2: paddd %xmm0,%xmm4 movdqa %xmm0,%xmm5 movdqa %xmm4,%xmm6 @@ -834,7 +834,7 @@ _gcry_salsa20_amd64_encrypt_blocks: pxor %xmm5,%xmm0 pshufd $0x39,%xmm3,%xmm3 pxor %xmm6,%xmm0 - ja ._mainloop2 + ja .L_mainloop2 paddd 0(%r8),%xmm0 paddd 16(%r8),%xmm1 paddd 32(%r8),%xmm2 @@ -907,17 +907,17 @@ _gcry_salsa20_amd64_encrypt_blocks: movl %ecx,32(%r8) movl %eax,52(%r8) cmp $64,%rdx - ja ._bytes_are_128_or_192 -._done: + ja .L_bytes_are_128_or_192 +.L_done: add %r11,%rsp mov %r11,%rax pop %rbx ret -._bytes_are_128_or_192: +.L_bytes_are_128_or_192: sub $64,%rdx add $64,%rdi add $64,%rsi - jmp ._bytes_are_64_128_or_192 + jmp .L_bytes_are_64_128_or_192 .size _gcry_salsa20_amd64_encrypt_blocks,.-_gcry_salsa20_amd64_encrypt_blocks; #endif /*defined(USE_SALSA20)*/ diff --git a/cipher/salsa20-armv7-neon.S b/cipher/salsa20-armv7-neon.S index 7d31e9f..8a9d9c4 100644 --- a/cipher/salsa20-armv7-neon.S +++ b/cipher/salsa20-armv7-neon.S @@ -117,8 +117,8 @@ _gcry_arm_neon_salsa20_encrypt: strd r8,[sp,#88] nop cmp r0,#192 - blo ._mlenlowbelow192 -._mlenatleast192: + blo .L_mlenlowbelow192 +.L_mlenatleast192: ldrd r2,[sp,#48] vext.32 d7,d6,d6,#1 vmov q8,q1 @@ -157,7 +157,7 @@ _gcry_arm_neon_salsa20_encrypt: ldrd r2,[sp,#56] vst1.8 {d14-d15},[r6,: 128] ldrd r6,[sp,#40] -._mainloop2: +.L_mainloop2: str r12,[sp,#248] vadd.i32 q4,q10,q8 vadd.i32 q9,q13,q11 @@ -505,7 +505,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r9,r9,r14,ROR #14 veor q11,q9,q4 subs r12,r12,#4 - bhi ._mainloop2 + bhi .L_mainloop2 strd r8,[sp,#112] ldrd r8,[sp,#64] strd r2,[sp,#120] @@ -526,7 +526,7 @@ _gcry_arm_neon_salsa20_encrypt: add r6,r6,r10 add r7,r7,r11 cmp r12,#0 - beq ._nomessage1 + beq .L_nomessage1 ldr r8,[r12,#0] ldr r9,[r12,#4] ldr r10,[r12,#8] @@ -543,7 +543,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r5,r5,r9 eor r6,r6,r10 eor r7,r7,r11 -._nomessage1: +.L_nomessage1: ldr r14,[sp,#232] vadd.i32 q4,q8,q1 str r0,[r14,#0] @@ -592,7 +592,7 @@ _gcry_arm_neon_salsa20_encrypt: add r5,r11,r5 add r8,r14,#64 cmp r12,#0 - beq ._nomessage2 + beq .L_nomessage2 ldr r9,[r12,#32] ldr r10,[r12,#36] ldr r11,[r12,#40] @@ -618,7 +618,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r1,r1,r14 vld1.8 {d20-d21},[r12]! veor q9,q9,q10 -._nomessage2: +.L_nomessage2: vst1.8 {d8-d9},[r8]! vst1.8 {d10-d11},[r8]! vmov.i64 q4,#0xff @@ -654,7 +654,7 @@ _gcry_arm_neon_salsa20_encrypt: vadd.i64 q3,q3,q4 sub r0,r0,#192 cmp r12,#0 - beq ._nomessage21 + beq .L_nomessage21 vld1.8 {d16-d17},[r12]! veor q2,q2,q8 vld1.8 {d16-d17},[r12]! @@ -663,7 +663,7 @@ _gcry_arm_neon_salsa20_encrypt: veor q6,q6,q8 vld1.8 {d16-d17},[r12]! veor q7,q7,q8 -._nomessage21: +.L_nomessage21: vst1.8 {d4-d5},[r8]! vst1.8 {d10-d11},[r8]! vst1.8 {d12-d13},[r8]! @@ -673,15 +673,15 @@ _gcry_arm_neon_salsa20_encrypt: add r12,sp,#256 str r8,[sp,#232] cmp r0,#192 - bhs ._mlenatleast192 -._mlenlowbelow192: + bhs .L_mlenatleast192 +.L_mlenlowbelow192: cmp r0,#0 - beq ._done - b ._mlenatleast1 -._nextblock: + beq .L_done + b .L_mlenatleast1 +.L_nextblock: sub r0,r0,#64 -._mlenatleast1: -._handleblock: +.L_mlenatleast1: +.L_handleblock: str r0,[sp,#248] ldrd r2,[sp,#48] ldrd r6,[sp,#32] @@ -694,7 +694,7 @@ _gcry_arm_neon_salsa20_encrypt: ldrd r2,[sp,#56] ldrd r6,[sp,#40] ldr r12,[sp,#244] -._mainloop1: +.L_mainloop1: str r12,[sp,#252] add r12,r0,r2 add r14,r5,r1 @@ -778,7 +778,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r9,r9,r14,ROR #14 ldr r12,[sp,#252] subs r12,r12,#2 - bhi ._mainloop1 + bhi .L_mainloop1 strd r6,[sp,#128] strd r2,[sp,#120] strd r10,[sp,#112] @@ -799,7 +799,7 @@ _gcry_arm_neon_salsa20_encrypt: add r7,r7,r11 ldr r12,[sp,#236] cmp r12,#0 - beq ._nomessage10 + beq .L_nomessage10 ldr r8,[r12,#0] ldr r9,[r12,#4] ldr r10,[r12,#8] @@ -816,7 +816,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r5,r5,r9 eor r6,r6,r10 eor r7,r7,r11 -._nomessage10: +.L_nomessage10: ldr r14,[sp,#232] str r0,[r14,#0] str r1,[r14,#4] @@ -846,7 +846,7 @@ _gcry_arm_neon_salsa20_encrypt: add r0,r8,r0 add r1,r9,r1 cmp r12,#0 - beq ._nomessage11 + beq .L_nomessage11 ldr r4,[r12,#32] ldr r5,[r12,#36] ldr r8,[r12,#40] @@ -865,7 +865,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r1,r1,r9 add r4,r12,#64 str r4,[sp,#236] -._nomessage11: +.L_nomessage11: str r6,[r14,#32] str r7,[r14,#36] str r10,[r14,#40] @@ -878,8 +878,8 @@ _gcry_arm_neon_salsa20_encrypt: str r0,[sp,#232] ldr r0,[sp,#248] cmp r0,#64 - bhi ._nextblock -._done: + bhi .L_nextblock +.L_done: ldr r2,[sp,#160] ldrd r4,[sp,#0] ldrd r6,[sp,#8] From cvs at cvs.gnupg.org Mon Nov 4 15:04:25 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Mon, 04 Nov 2013 15:04:25 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-350-gd469786 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via d4697862266f3c96b6946dc92139dd8f3e81e5f6 (commit) from d1cadd145199040299538891ab2ccd1208f7776e (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d4697862266f3c96b6946dc92139dd8f3e81e5f6 Author: Jussi Kivilinna Date: Sun Nov 3 22:11:30 2013 +0200 Make jump labels local in Salsa20 assembly * cipher/salsa20-amd64.S: Rename '._labels' to '.L_labels'. * cipher/salsa20-armv7-neon.S: Ditto. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/salsa20-amd64.S b/cipher/salsa20-amd64.S index 691df58..e79da4e 100644 --- a/cipher/salsa20-amd64.S +++ b/cipher/salsa20-amd64.S @@ -42,8 +42,8 @@ _gcry_salsa20_amd64_keysetup: movl %eax,60(%rdi) movl %r10d,48(%rdi) cmp $256,%rdx - jb ._kbits128 -._kbits256: + jb .L_kbits128 +.L_kbits256: movl 16(%rsi),%edx movl 20(%rsi),%ecx movl 24(%rsi),%r8d @@ -60,8 +60,8 @@ _gcry_salsa20_amd64_keysetup: movl %edx,4(%rdi) movl %ecx,8(%rdi) movl %r8d,12(%rdi) - jmp ._keysetupdone -._kbits128: + jmp .L_keysetupdone +.L_kbits128: movl 0(%rsi),%edx movl 4(%rsi),%ecx movl 8(%rsi),%r8d @@ -78,7 +78,7 @@ _gcry_salsa20_amd64_keysetup: movl %edx,4(%rdi) movl %ecx,8(%rdi) movl %r8d,12(%rdi) -._keysetupdone: +.L_keysetupdone: ret .align 8 @@ -117,10 +117,10 @@ _gcry_salsa20_amd64_encrypt_blocks: mov %rdx,%rdi mov %rcx,%rdx cmp $0,%rdx - jbe ._done -._start: + jbe .L_done +.L_start: cmp $256,%rdx - jb ._bytes_are_64_128_or_192 + jb .L_bytes_are_64_128_or_192 movdqa 0(%r8),%xmm0 pshufd $0x55,%xmm0,%xmm1 pshufd $0xaa,%xmm0,%xmm2 @@ -153,7 +153,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa %xmm1,176(%rsp) movdqa %xmm2,192(%rsp) movdqa %xmm0,208(%rsp) -._bytesatleast256: +.L_bytesatleast256: movl 32(%r8),%ecx movl 52(%r8),%r9d movl %ecx,224(%rsp) @@ -192,7 +192,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 96(%rsp),%xmm13 movdqa 176(%rsp),%xmm14 movdqa 224(%rsp),%xmm15 -._mainloop1: +.L_mainloop1: movdqa %xmm1,256(%rsp) movdqa %xmm2,272(%rsp) movdqa %xmm13,%xmm1 @@ -434,7 +434,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 256(%rsp),%xmm12 movdqa 272(%rsp),%xmm0 sub $2,%rdx - ja ._mainloop1 + ja .L_mainloop1 paddd 48(%rsp),%xmm12 paddd 112(%rsp),%xmm7 paddd 160(%rsp),%xmm10 @@ -696,10 +696,10 @@ _gcry_salsa20_amd64_encrypt_blocks: add $256,%rsi add $256,%rdi cmp $256,%rdx - jae ._bytesatleast256 + jae .L_bytesatleast256 cmp $0,%rdx - jbe ._done -._bytes_are_64_128_or_192: + jbe .L_done +.L_bytes_are_64_128_or_192: movq %rdx,288(%rsp) movdqa 0(%r8),%xmm0 movdqa 16(%r8),%xmm1 @@ -707,7 +707,7 @@ _gcry_salsa20_amd64_encrypt_blocks: movdqa 48(%r8),%xmm3 movdqa %xmm1,%xmm4 mov %rbx,%rdx -._mainloop2: +.L_mainloop2: paddd %xmm0,%xmm4 movdqa %xmm0,%xmm5 movdqa %xmm4,%xmm6 @@ -834,7 +834,7 @@ _gcry_salsa20_amd64_encrypt_blocks: pxor %xmm5,%xmm0 pshufd $0x39,%xmm3,%xmm3 pxor %xmm6,%xmm0 - ja ._mainloop2 + ja .L_mainloop2 paddd 0(%r8),%xmm0 paddd 16(%r8),%xmm1 paddd 32(%r8),%xmm2 @@ -907,17 +907,17 @@ _gcry_salsa20_amd64_encrypt_blocks: movl %ecx,32(%r8) movl %eax,52(%r8) cmp $64,%rdx - ja ._bytes_are_128_or_192 -._done: + ja .L_bytes_are_128_or_192 +.L_done: add %r11,%rsp mov %r11,%rax pop %rbx ret -._bytes_are_128_or_192: +.L_bytes_are_128_or_192: sub $64,%rdx add $64,%rdi add $64,%rsi - jmp ._bytes_are_64_128_or_192 + jmp .L_bytes_are_64_128_or_192 .size _gcry_salsa20_amd64_encrypt_blocks,.-_gcry_salsa20_amd64_encrypt_blocks; #endif /*defined(USE_SALSA20)*/ diff --git a/cipher/salsa20-armv7-neon.S b/cipher/salsa20-armv7-neon.S index 7d31e9f..8a9d9c4 100644 --- a/cipher/salsa20-armv7-neon.S +++ b/cipher/salsa20-armv7-neon.S @@ -117,8 +117,8 @@ _gcry_arm_neon_salsa20_encrypt: strd r8,[sp,#88] nop cmp r0,#192 - blo ._mlenlowbelow192 -._mlenatleast192: + blo .L_mlenlowbelow192 +.L_mlenatleast192: ldrd r2,[sp,#48] vext.32 d7,d6,d6,#1 vmov q8,q1 @@ -157,7 +157,7 @@ _gcry_arm_neon_salsa20_encrypt: ldrd r2,[sp,#56] vst1.8 {d14-d15},[r6,: 128] ldrd r6,[sp,#40] -._mainloop2: +.L_mainloop2: str r12,[sp,#248] vadd.i32 q4,q10,q8 vadd.i32 q9,q13,q11 @@ -505,7 +505,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r9,r9,r14,ROR #14 veor q11,q9,q4 subs r12,r12,#4 - bhi ._mainloop2 + bhi .L_mainloop2 strd r8,[sp,#112] ldrd r8,[sp,#64] strd r2,[sp,#120] @@ -526,7 +526,7 @@ _gcry_arm_neon_salsa20_encrypt: add r6,r6,r10 add r7,r7,r11 cmp r12,#0 - beq ._nomessage1 + beq .L_nomessage1 ldr r8,[r12,#0] ldr r9,[r12,#4] ldr r10,[r12,#8] @@ -543,7 +543,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r5,r5,r9 eor r6,r6,r10 eor r7,r7,r11 -._nomessage1: +.L_nomessage1: ldr r14,[sp,#232] vadd.i32 q4,q8,q1 str r0,[r14,#0] @@ -592,7 +592,7 @@ _gcry_arm_neon_salsa20_encrypt: add r5,r11,r5 add r8,r14,#64 cmp r12,#0 - beq ._nomessage2 + beq .L_nomessage2 ldr r9,[r12,#32] ldr r10,[r12,#36] ldr r11,[r12,#40] @@ -618,7 +618,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r1,r1,r14 vld1.8 {d20-d21},[r12]! veor q9,q9,q10 -._nomessage2: +.L_nomessage2: vst1.8 {d8-d9},[r8]! vst1.8 {d10-d11},[r8]! vmov.i64 q4,#0xff @@ -654,7 +654,7 @@ _gcry_arm_neon_salsa20_encrypt: vadd.i64 q3,q3,q4 sub r0,r0,#192 cmp r12,#0 - beq ._nomessage21 + beq .L_nomessage21 vld1.8 {d16-d17},[r12]! veor q2,q2,q8 vld1.8 {d16-d17},[r12]! @@ -663,7 +663,7 @@ _gcry_arm_neon_salsa20_encrypt: veor q6,q6,q8 vld1.8 {d16-d17},[r12]! veor q7,q7,q8 -._nomessage21: +.L_nomessage21: vst1.8 {d4-d5},[r8]! vst1.8 {d10-d11},[r8]! vst1.8 {d12-d13},[r8]! @@ -673,15 +673,15 @@ _gcry_arm_neon_salsa20_encrypt: add r12,sp,#256 str r8,[sp,#232] cmp r0,#192 - bhs ._mlenatleast192 -._mlenlowbelow192: + bhs .L_mlenatleast192 +.L_mlenlowbelow192: cmp r0,#0 - beq ._done - b ._mlenatleast1 -._nextblock: + beq .L_done + b .L_mlenatleast1 +.L_nextblock: sub r0,r0,#64 -._mlenatleast1: -._handleblock: +.L_mlenatleast1: +.L_handleblock: str r0,[sp,#248] ldrd r2,[sp,#48] ldrd r6,[sp,#32] @@ -694,7 +694,7 @@ _gcry_arm_neon_salsa20_encrypt: ldrd r2,[sp,#56] ldrd r6,[sp,#40] ldr r12,[sp,#244] -._mainloop1: +.L_mainloop1: str r12,[sp,#252] add r12,r0,r2 add r14,r5,r1 @@ -778,7 +778,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r9,r9,r14,ROR #14 ldr r12,[sp,#252] subs r12,r12,#2 - bhi ._mainloop1 + bhi .L_mainloop1 strd r6,[sp,#128] strd r2,[sp,#120] strd r10,[sp,#112] @@ -799,7 +799,7 @@ _gcry_arm_neon_salsa20_encrypt: add r7,r7,r11 ldr r12,[sp,#236] cmp r12,#0 - beq ._nomessage10 + beq .L_nomessage10 ldr r8,[r12,#0] ldr r9,[r12,#4] ldr r10,[r12,#8] @@ -816,7 +816,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r5,r5,r9 eor r6,r6,r10 eor r7,r7,r11 -._nomessage10: +.L_nomessage10: ldr r14,[sp,#232] str r0,[r14,#0] str r1,[r14,#4] @@ -846,7 +846,7 @@ _gcry_arm_neon_salsa20_encrypt: add r0,r8,r0 add r1,r9,r1 cmp r12,#0 - beq ._nomessage11 + beq .L_nomessage11 ldr r4,[r12,#32] ldr r5,[r12,#36] ldr r8,[r12,#40] @@ -865,7 +865,7 @@ _gcry_arm_neon_salsa20_encrypt: eor r1,r1,r9 add r4,r12,#64 str r4,[sp,#236] -._nomessage11: +.L_nomessage11: str r6,[r14,#32] str r7,[r14,#36] str r10,[r14,#40] @@ -878,8 +878,8 @@ _gcry_arm_neon_salsa20_encrypt: str r0,[sp,#232] ldr r0,[sp,#248] cmp r0,#64 - bhi ._nextblock -._done: + bhi .L_nextblock +.L_done: ldr r2,[sp,#160] ldrd r4,[sp,#0] ldrd r6,[sp,#8] ----------------------------------------------------------------------- Summary of changes: cipher/salsa20-amd64.S | 40 +++++++++++++++++----------------- cipher/salsa20-armv7-neon.S | 50 +++++++++++++++++++++---------------------- 2 files changed, 45 insertions(+), 45 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Mon Nov 4 15:19:06 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 04 Nov 2013 16:19:06 +0200 Subject: [PATCH] Make test vectors 'static const' Message-ID: <20131104141906.16243.57168.stgit@localhost6.localdomain6> * cipher/arcfour.c (selftest): Change test vectors to 'static const'. * cipher/blowfish.c (selftest): Ditto. * cipher/camellia-glue.c (selftest): Ditto. * cipher/cast5.c (selftest): Ditto. * cipher/des.c (selftest): Ditto. * cipher/rijndael.c (selftest): Ditto. * tests/basic.c (cipher_cbc_mac_cipher, check_aes128_cbc_cts_cipher) (check_ctr_cipher, check_cfb_cipher, check_ofb_cipher) (check_ccm_cipher, check_stream_cipher) (check_stream_cipher_large_block, check_bulk_cipher_modes) (check_ciphers, check_digests, check_hmac, check_pubkey_sign) (check_pubkey_sign_ecdsa, check_pubkey_crypt, check_pubkey): Ditto. -- Some test vectors have been defined without 'static' and thus end up being initialized on runtime. Change these to 'static'. Also change test vectors const where possible. Signed-off-by: Jussi Kivilinna --- cipher/arcfour.c | 4 ++-- cipher/blowfish.c | 9 ++++++--- cipher/camellia-glue.c | 14 +++++++------- cipher/cast5.c | 9 ++++++--- cipher/des.c | 3 ++- cipher/rijndael.c | 2 +- tests/basic.c | 36 ++++++++++++++++++------------------ 7 files changed, 42 insertions(+), 35 deletions(-) diff --git a/cipher/arcfour.c b/cipher/arcfour.c index e8a5484..89936f4 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -159,9 +159,9 @@ selftest(void) /* Test vector from Cryptlib labeled there: "from the State/Commerce Department". */ - static byte key_1[] = + static const byte key_1[] = { 0x61, 0x8A, 0x63, 0xD2, 0xFB }; - static byte plaintext_1[] = + static const byte plaintext_1[] = { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C }; static const byte ciphertext_1[] = { 0xF1, 0x38, 0x29, 0xC9, 0xDE }; diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 3b6bf6b..84fa9d3 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -822,9 +822,12 @@ selftest(void) BLOWFISH_context c; byte plain[] = "BLOWFISH"; byte buffer[8]; - byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; - byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; - byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; + static const byte plain3[] = + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; + static const byte key3[] = + { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; + static const byte cipher3[] = + { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; const char *r; bf_setkey( (void *) &c, diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 8c217a7..42b62d2 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -582,38 +582,38 @@ selftest(void) const char *r; /* These test vectors are from RFC-3713 */ - const byte plaintext[]= + static const byte plaintext[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; - const byte key_128[]= + static const byte key_128[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; - const byte ciphertext_128[]= + static const byte ciphertext_128[]= { 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 }; - const byte key_192[]= + static const byte key_192[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98, 0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77 }; - const byte ciphertext_192[]= + static const byte ciphertext_192[]= { 0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8, 0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9 }; - const byte key_256[]= + static const byte key_256[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba, 0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55, 0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; - const byte ciphertext_256[]= + static const byte ciphertext_256[]= { 0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c, 0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09 diff --git a/cipher/cast5.c b/cipher/cast5.c index 0df7886..8d14183 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -796,10 +796,13 @@ static const char* selftest(void) { CAST5_context c; - byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + static const byte key[16] = + { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; - byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; - byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; + static const byte plain[8] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + static const byte cipher[8] = + { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; byte buffer[8]; const char *r; diff --git a/cipher/des.c b/cipher/des.c index 3464d53..6611fd3 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -893,7 +893,8 @@ selftest (void) * thanks to Jeroen C. van Gelderen. */ { - struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { + static const struct { byte key[24]; byte plain[8]; byte cipher[8]; } + testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, diff --git a/cipher/rijndael.c b/cipher/rijndael.c index e8733c9..b8cc18b 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -2308,7 +2308,7 @@ selftest (void) static const char * selftest_fips_128_38a (int requested_mode) { - struct tv + static const struct tv { int mode; const unsigned char key[16]; diff --git a/tests/basic.c b/tests/basic.c index 21af21d..99d63ae 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -139,7 +139,7 @@ progress_handler (void *cb_data, const char *what, int printchar, static void check_cbc_mac_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -264,10 +264,10 @@ check_cbc_mac_cipher (void) static void check_aes128_cbc_cts_cipher (void) { - char key[128 / 8] = "chicken teriyaki"; - unsigned char plaintext[] = + static const char key[128 / 8] = "chicken teriyaki"; + static const unsigned char plaintext[] = "I would like the General Gau's Chicken, please, and wonton soup."; - struct tv + static const struct tv { unsigned char out[MAX_DATA_LEN]; int inlen; @@ -378,7 +378,7 @@ check_aes128_cbc_cts_cipher (void) static void check_ctr_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -734,7 +734,7 @@ check_ctr_cipher (void) static void check_cfb_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -905,7 +905,7 @@ check_cfb_cipher (void) static void check_ofb_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -1911,7 +1911,7 @@ check_ccm_cipher (void) static void check_stream_cipher (void) { - struct tv + static const struct tv { const char *name; int algo; @@ -2252,7 +2252,7 @@ check_stream_cipher (void) static void check_stream_cipher_large_block (void) { - struct tv + static const struct tv { const char *name; int algo; @@ -2690,7 +2690,7 @@ check_stream_cipher_large_block (void) static void check_bulk_cipher_modes (void) { - struct + static const struct { int algo; int mode; @@ -3110,7 +3110,7 @@ check_one_cipher (int algo, int mode, int flags) static void check_ciphers (void) { - static int algos[] = { + static const int algos[] = { #if USE_BLOWFISH GCRY_CIPHER_BLOWFISH, #endif @@ -3154,7 +3154,7 @@ check_ciphers (void) #endif 0 }; - static int algos2[] = { + static const int algos2[] = { #if USE_ARCFOUR GCRY_CIPHER_ARCFOUR, #endif @@ -3364,7 +3364,7 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect) static void check_digests (void) { - static struct algos + static const struct algos { int md; const char *data; @@ -3728,7 +3728,7 @@ check_one_hmac (int algo, const char *data, int datalen, static void check_hmac (void) { - static struct algos + static const struct algos { int md; const char *data; @@ -4070,7 +4070,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) static const char baddata[] = "(data\n (flags pkcs1)\n" " (hash sha1 #11223344556677889900AABBCCDDEEFF10203041#))\n"; - static struct + static const struct { const char *data; int algo; @@ -4173,7 +4173,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey) gcry_sexp_t sig, badhash, hash; unsigned int nbits; int dataidx; - static struct + static const struct { unsigned int nbits; const char *data; @@ -4285,7 +4285,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) gcry_sexp_t ciph = NULL; gcry_sexp_t data = NULL; int dataidx; - static struct + static const struct { int algo; /* If not 0 run test only if ALGO matches. */ const char *data; @@ -4599,7 +4599,7 @@ check_one_pubkey_new (int n) static void check_pubkey (void) { - test_spec_pubkey_t pubkeys[] = { + static const test_spec_pubkey_t pubkeys[] = { { GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN, { From cvs at cvs.gnupg.org Tue Nov 5 16:34:57 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Tue, 05 Nov 2013 16:34:57 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-351-gd50a88d Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via d50a88d1e29124d038196fec6082fd093e922604 (commit) from d4697862266f3c96b6946dc92139dd8f3e81e5f6 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit d50a88d1e29124d038196fec6082fd093e922604 Author: Jussi Kivilinna Date: Sun Oct 13 12:42:32 2013 +0300 Make test vectors 'static const' * cipher/arcfour.c (selftest): Change test vectors to 'static const'. * cipher/blowfish.c (selftest): Ditto. * cipher/camellia-glue.c (selftest): Ditto. * cipher/cast5.c (selftest): Ditto. * cipher/des.c (selftest): Ditto. * cipher/rijndael.c (selftest): Ditto. * tests/basic.c (cipher_cbc_mac_cipher, check_aes128_cbc_cts_cipher) (check_ctr_cipher, check_cfb_cipher, check_ofb_cipher) (check_ccm_cipher, check_stream_cipher) (check_stream_cipher_large_block, check_bulk_cipher_modes) (check_ciphers, check_digests, check_hmac, check_pubkey_sign) (check_pubkey_sign_ecdsa, check_pubkey_crypt, check_pubkey): Ditto. -- Some test vectors have been defined without 'static' and thus end up being initialized on runtime. Change these to 'static'. Also change test vectors const where possible. Signed-off-by: Jussi Kivilinna diff --git a/cipher/arcfour.c b/cipher/arcfour.c index e8a5484..89936f4 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -159,9 +159,9 @@ selftest(void) /* Test vector from Cryptlib labeled there: "from the State/Commerce Department". */ - static byte key_1[] = + static const byte key_1[] = { 0x61, 0x8A, 0x63, 0xD2, 0xFB }; - static byte plaintext_1[] = + static const byte plaintext_1[] = { 0xDC, 0xEE, 0x4C, 0xF9, 0x2C }; static const byte ciphertext_1[] = { 0xF1, 0x38, 0x29, 0xC9, 0xDE }; diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 3b6bf6b..84fa9d3 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -822,9 +822,12 @@ selftest(void) BLOWFISH_context c; byte plain[] = "BLOWFISH"; byte buffer[8]; - byte plain3[] = { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; - byte key3[] = { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; - byte cipher3[] = { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; + static const byte plain3[] = + { 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10 }; + static const byte key3[] = + { 0x41, 0x79, 0x6E, 0xA0, 0x52, 0x61, 0x6E, 0xE4 }; + static const byte cipher3[] = + { 0xE1, 0x13, 0xF4, 0x10, 0x2C, 0xFC, 0xCE, 0x43 }; const char *r; bf_setkey( (void *) &c, diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 8c217a7..42b62d2 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -582,38 +582,38 @@ selftest(void) const char *r; /* These test vectors are from RFC-3713 */ - const byte plaintext[]= + static const byte plaintext[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; - const byte key_128[]= + static const byte key_128[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10 }; - const byte ciphertext_128[]= + static const byte ciphertext_128[]= { 0x67,0x67,0x31,0x38,0x54,0x96,0x69,0x73, 0x08,0x57,0x06,0x56,0x48,0xea,0xbe,0x43 }; - const byte key_192[]= + static const byte key_192[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba,0x98, 0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77 }; - const byte ciphertext_192[]= + static const byte ciphertext_192[]= { 0xb4,0x99,0x34,0x01,0xb3,0xe9,0x96,0xf8, 0x4e,0xe5,0xce,0xe7,0xd7,0x9b,0x09,0xb9 }; - const byte key_256[]= + static const byte key_256[]= { 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef,0xfe,0xdc,0xba, 0x98,0x76,0x54,0x32,0x10,0x00,0x11,0x22,0x33,0x44,0x55, 0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; - const byte ciphertext_256[]= + static const byte ciphertext_256[]= { 0x9a,0xcc,0x23,0x7d,0xff,0x16,0xd7,0x6c, 0x20,0xef,0x7c,0x91,0x9e,0x3a,0x75,0x09 diff --git a/cipher/cast5.c b/cipher/cast5.c index 0df7886..8d14183 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -796,10 +796,13 @@ static const char* selftest(void) { CAST5_context c; - byte key[16] = { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, + static const byte key[16] = + { 0x01, 0x23, 0x45, 0x67, 0x12, 0x34, 0x56, 0x78, 0x23, 0x45, 0x67, 0x89, 0x34, 0x56, 0x78, 0x9A }; - byte plain[8] = { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; - byte cipher[8]= { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; + static const byte plain[8] = + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }; + static const byte cipher[8] = + { 0x23, 0x8B, 0x4F, 0xE5, 0x84, 0x7E, 0x44, 0xB2 }; byte buffer[8]; const char *r; diff --git a/cipher/des.c b/cipher/des.c index 3464d53..6611fd3 100644 --- a/cipher/des.c +++ b/cipher/des.c @@ -893,7 +893,8 @@ selftest (void) * thanks to Jeroen C. van Gelderen. */ { - struct { byte key[24]; byte plain[8]; byte cipher[8]; } testdata[] = { + static const struct { byte key[24]; byte plain[8]; byte cipher[8]; } + testdata[] = { { { 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01, 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01 }, diff --git a/cipher/rijndael.c b/cipher/rijndael.c index e8733c9..b8cc18b 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -2308,7 +2308,7 @@ selftest (void) static const char * selftest_fips_128_38a (int requested_mode) { - struct tv + static const struct tv { int mode; const unsigned char key[16]; diff --git a/tests/basic.c b/tests/basic.c index 21af21d..99d63ae 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -139,7 +139,7 @@ progress_handler (void *cb_data, const char *what, int printchar, static void check_cbc_mac_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -264,10 +264,10 @@ check_cbc_mac_cipher (void) static void check_aes128_cbc_cts_cipher (void) { - char key[128 / 8] = "chicken teriyaki"; - unsigned char plaintext[] = + static const char key[128 / 8] = "chicken teriyaki"; + static const unsigned char plaintext[] = "I would like the General Gau's Chicken, please, and wonton soup."; - struct tv + static const struct tv { unsigned char out[MAX_DATA_LEN]; int inlen; @@ -378,7 +378,7 @@ check_aes128_cbc_cts_cipher (void) static void check_ctr_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -734,7 +734,7 @@ check_ctr_cipher (void) static void check_cfb_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -905,7 +905,7 @@ check_cfb_cipher (void) static void check_ofb_cipher (void) { - struct tv + static const struct tv { int algo; char key[MAX_DATA_LEN]; @@ -1911,7 +1911,7 @@ check_ccm_cipher (void) static void check_stream_cipher (void) { - struct tv + static const struct tv { const char *name; int algo; @@ -2252,7 +2252,7 @@ check_stream_cipher (void) static void check_stream_cipher_large_block (void) { - struct tv + static const struct tv { const char *name; int algo; @@ -2690,7 +2690,7 @@ check_stream_cipher_large_block (void) static void check_bulk_cipher_modes (void) { - struct + static const struct { int algo; int mode; @@ -3110,7 +3110,7 @@ check_one_cipher (int algo, int mode, int flags) static void check_ciphers (void) { - static int algos[] = { + static const int algos[] = { #if USE_BLOWFISH GCRY_CIPHER_BLOWFISH, #endif @@ -3154,7 +3154,7 @@ check_ciphers (void) #endif 0 }; - static int algos2[] = { + static const int algos2[] = { #if USE_ARCFOUR GCRY_CIPHER_ARCFOUR, #endif @@ -3364,7 +3364,7 @@ check_one_md_multi (int algo, const char *data, int len, const char *expect) static void check_digests (void) { - static struct algos + static const struct algos { int md; const char *data; @@ -3728,7 +3728,7 @@ check_one_hmac (int algo, const char *data, int datalen, static void check_hmac (void) { - static struct algos + static const struct algos { int md; const char *data; @@ -4070,7 +4070,7 @@ check_pubkey_sign (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) static const char baddata[] = "(data\n (flags pkcs1)\n" " (hash sha1 #11223344556677889900AABBCCDDEEFF10203041#))\n"; - static struct + static const struct { const char *data; int algo; @@ -4173,7 +4173,7 @@ check_pubkey_sign_ecdsa (int n, gcry_sexp_t skey, gcry_sexp_t pkey) gcry_sexp_t sig, badhash, hash; unsigned int nbits; int dataidx; - static struct + static const struct { unsigned int nbits; const char *data; @@ -4285,7 +4285,7 @@ check_pubkey_crypt (int n, gcry_sexp_t skey, gcry_sexp_t pkey, int algo) gcry_sexp_t ciph = NULL; gcry_sexp_t data = NULL; int dataidx; - static struct + static const struct { int algo; /* If not 0 run test only if ALGO matches. */ const char *data; @@ -4599,7 +4599,7 @@ check_one_pubkey_new (int n) static void check_pubkey (void) { - test_spec_pubkey_t pubkeys[] = { + static const test_spec_pubkey_t pubkeys[] = { { GCRY_PK_RSA, FLAG_CRYPT | FLAG_SIGN, { ----------------------------------------------------------------------- Summary of changes: cipher/arcfour.c | 4 ++-- cipher/blowfish.c | 9 ++++++--- cipher/camellia-glue.c | 14 +++++++------- cipher/cast5.c | 9 ++++++--- cipher/des.c | 3 ++- cipher/rijndael.c | 2 +- tests/basic.c | 36 ++++++++++++++++++------------------ 7 files changed, 42 insertions(+), 35 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Tue Nov 5 16:57:35 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:57:35 +0200 Subject: [PATCH 1/7] Tweak bench-slope parameters Message-ID: <20131105155735.6543.78655.stgit@localhost6.localdomain6> * tests/bench-slope.c (BUF_STEP_SIZE): Half step size to 64. (NUM_MEASUREMENT_REPETITIONS): Double repetitions to 64. -- Tweak parameters for better repeatability of results with fast ciphers (AES-NI). Signed-off-by: Jussi Kivilinna --- tests/bench-slope.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 5687bf1..79b868c 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -55,12 +55,12 @@ static double cpu_ghz = -1; * (SUPERCOP). */ #define BUF_END_SIZE (BUF_START_SIZE + 4096) -/* With 128 byte steps, we get (4096)/128 = 32 data points. */ -#define BUF_STEP_SIZE 128 +/* With 128 byte steps, we get (4096)/64 = 64 data points. */ +#define BUF_STEP_SIZE 64 /* Number of repeated measurements at each data point. The median of these * measurements is selected as data point further analysis. */ -#define NUM_MEASUREMENT_REPETITIONS 32 +#define NUM_MEASUREMENT_REPETITIONS 64 /**************************************************** High-resolution timers. */ From jussi.kivilinna at iki.fi Tue Nov 5 16:57:56 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:57:56 +0200 Subject: [PATCH 5/7] Improve Serpent key setup speed In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155756.6543.21177.stgit@localhost6.localdomain6> * cipher/serpent.c (SBOX, SBOX_INVERSE): Remove index argument. (serpent_subkeys_generate): Use smaller temporary arrays for subkey generation and perform stack clearing locally. (serpent_setkey_internal): Use wipememory to clear stack and remove _gcry_burn_stack. (serpent_setkey): Remove unneeded _gcry_burn_stack. -- Avoid using large arrays and large stack burning to gain extra speed for key setup. Signed-off-by: Jussi Kivilinna --- cipher/serpent.c | 134 +++++++++++++++++++++++++----------------------------- 1 file changed, 62 insertions(+), 72 deletions(-) diff --git a/cipher/serpent.c b/cipher/serpent.c index cfda742..4a24ddd 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -468,23 +468,17 @@ static const char *serpent_test (void); block_dst[3] = block_src[3]; \ } -/* Apply SBOX number WHICH to to the block found in ARRAY0 at index - INDEX, writing the output to the block found in ARRAY1 at index - INDEX. */ -#define SBOX(which, array0, array1, index) \ - SBOX##which (array0[index + 0], array0[index + 1], \ - array0[index + 2], array0[index + 3], \ - array1[index + 0], array1[index + 1], \ - array1[index + 2], array1[index + 3]); - -/* Apply inverse SBOX number WHICH to to the block found in ARRAY0 at - index INDEX, writing the output to the block found in ARRAY1 at - index INDEX. */ -#define SBOX_INVERSE(which, array0, array1, index) \ - SBOX##which##_INVERSE (array0[index + 0], array0[index + 1], \ - array0[index + 2], array0[index + 3], \ - array1[index + 0], array1[index + 1], \ - array1[index + 2], array1[index + 3]); +/* Apply SBOX number WHICH to to the block found in ARRAY0, writing + the output to the block found in ARRAY1. */ +#define SBOX(which, array0, array1) \ + SBOX##which (array0[0], array0[1], array0[2], array0[3], \ + array1[0], array1[1], array1[2], array1[3]); + +/* Apply inverse SBOX number WHICH to to the block found in ARRAY0, writing + the output to the block found in ARRAY1. */ +#define SBOX_INVERSE(which, array0, array1) \ + SBOX##which##_INVERSE (array0[0], array0[1], array0[2], array0[3], \ + array1[0], array1[1], array1[2], array1[3]); /* Apply the linear transformation to BLOCK. */ #define LINEAR_TRANSFORMATION(block) \ @@ -523,7 +517,7 @@ static const char *serpent_test (void); { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ - SBOX (which, block, block_tmp, 0); \ + SBOX (which, block, block_tmp); \ LINEAR_TRANSFORMATION (block_tmp); \ BLOCK_COPY (block, block_tmp); \ } @@ -536,7 +530,7 @@ static const char *serpent_test (void); { \ BLOCK_XOR (block, subkeys[round]); \ round++; \ - SBOX (which, block, block_tmp, 0); \ + SBOX (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round++; \ } @@ -547,7 +541,7 @@ static const char *serpent_test (void); #define ROUND_INVERSE(which, subkey, block, block_tmp) \ { \ LINEAR_TRANSFORMATION_INVERSE (block); \ - SBOX_INVERSE (which, block, block_tmp, 0); \ + SBOX_INVERSE (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkey[round]); \ round--; \ BLOCK_COPY (block, block_tmp); \ @@ -561,7 +555,7 @@ static const char *serpent_test (void); { \ BLOCK_XOR (block, subkeys[round]); \ round--; \ - SBOX_INVERSE (which, block, block_tmp, 0); \ + SBOX_INVERSE (which, block, block_tmp); \ BLOCK_XOR (block_tmp, subkeys[round]); \ round--; \ } @@ -594,58 +588,57 @@ serpent_key_prepare (const byte *key, unsigned int key_length, static void serpent_subkeys_generate (serpent_key_t key, serpent_subkeys_t subkeys) { - u32 w_real[140]; /* The `prekey'. */ - u32 k[132]; - u32 *w = &w_real[8]; - int i, j; + u32 w[8]; /* The `prekey'. */ + u32 ws[4]; + u32 wt[4]; /* Initialize with key values. */ - for (i = 0; i < 8; i++) - w[i - 8] = key[i]; + w[0] = key[0]; + w[1] = key[1]; + w[2] = key[2]; + w[3] = key[3]; + w[4] = key[4]; + w[5] = key[5]; + w[6] = key[6]; + w[7] = key[7]; /* Expand to intermediate key using the affine recurrence. */ - for (i = 0; i < 132; i++) - w[i] = rol (w[i - 8] ^ w[i - 5] ^ w[i - 3] ^ w[i - 1] ^ PHI ^ i, 11); +#define EXPAND_KEY4(wo, r) \ + wo[0] = w[(r+0)%8] = \ + rol (w[(r+0)%8] ^ w[(r+3)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ PHI ^ (r+0), 11); \ + wo[1] = w[(r+1)%8] = \ + rol (w[(r+1)%8] ^ w[(r+4)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ PHI ^ (r+1), 11); \ + wo[2] = w[(r+2)%8] = \ + rol (w[(r+2)%8] ^ w[(r+5)%8] ^ w[(r+7)%8] ^ w[(r+1)%8] ^ PHI ^ (r+2), 11); \ + wo[3] = w[(r+3)%8] = \ + rol (w[(r+3)%8] ^ w[(r+6)%8] ^ w[(r+0)%8] ^ w[(r+2)%8] ^ PHI ^ (r+3), 11); + +#define EXPAND_KEY(r) \ + EXPAND_KEY4(ws, (r)); \ + EXPAND_KEY4(wt, (r + 4)); /* Calculate subkeys via S-Boxes, in bitslice mode. */ - SBOX (3, w, k, 0); - SBOX (2, w, k, 4); - SBOX (1, w, k, 8); - SBOX (0, w, k, 12); - SBOX (7, w, k, 16); - SBOX (6, w, k, 20); - SBOX (5, w, k, 24); - SBOX (4, w, k, 28); - SBOX (3, w, k, 32); - SBOX (2, w, k, 36); - SBOX (1, w, k, 40); - SBOX (0, w, k, 44); - SBOX (7, w, k, 48); - SBOX (6, w, k, 52); - SBOX (5, w, k, 56); - SBOX (4, w, k, 60); - SBOX (3, w, k, 64); - SBOX (2, w, k, 68); - SBOX (1, w, k, 72); - SBOX (0, w, k, 76); - SBOX (7, w, k, 80); - SBOX (6, w, k, 84); - SBOX (5, w, k, 88); - SBOX (4, w, k, 92); - SBOX (3, w, k, 96); - SBOX (2, w, k, 100); - SBOX (1, w, k, 104); - SBOX (0, w, k, 108); - SBOX (7, w, k, 112); - SBOX (6, w, k, 116); - SBOX (5, w, k, 120); - SBOX (4, w, k, 124); - SBOX (3, w, k, 128); - - /* Renumber subkeys. */ - for (i = 0; i < ROUNDS + 1; i++) - for (j = 0; j < 4; j++) - subkeys[i][j] = k[4 * i + j]; + EXPAND_KEY (0); SBOX (3, ws, subkeys[0]); SBOX (2, wt, subkeys[1]); + EXPAND_KEY (8); SBOX (1, ws, subkeys[2]); SBOX (0, wt, subkeys[3]); + EXPAND_KEY (16); SBOX (7, ws, subkeys[4]); SBOX (6, wt, subkeys[5]); + EXPAND_KEY (24); SBOX (5, ws, subkeys[6]); SBOX (4, wt, subkeys[7]); + EXPAND_KEY (32); SBOX (3, ws, subkeys[8]); SBOX (2, wt, subkeys[9]); + EXPAND_KEY (40); SBOX (1, ws, subkeys[10]); SBOX (0, wt, subkeys[11]); + EXPAND_KEY (48); SBOX (7, ws, subkeys[12]); SBOX (6, wt, subkeys[13]); + EXPAND_KEY (56); SBOX (5, ws, subkeys[14]); SBOX (4, wt, subkeys[15]); + EXPAND_KEY (64); SBOX (3, ws, subkeys[16]); SBOX (2, wt, subkeys[17]); + EXPAND_KEY (72); SBOX (1, ws, subkeys[18]); SBOX (0, wt, subkeys[19]); + EXPAND_KEY (80); SBOX (7, ws, subkeys[20]); SBOX (6, wt, subkeys[21]); + EXPAND_KEY (88); SBOX (5, ws, subkeys[22]); SBOX (4, wt, subkeys[23]); + EXPAND_KEY (96); SBOX (3, ws, subkeys[24]); SBOX (2, wt, subkeys[25]); + EXPAND_KEY (104); SBOX (1, ws, subkeys[26]); SBOX (0, wt, subkeys[27]); + EXPAND_KEY (112); SBOX (7, ws, subkeys[28]); SBOX (6, wt, subkeys[29]); + EXPAND_KEY (120); SBOX (5, ws, subkeys[30]); SBOX (4, wt, subkeys[31]); + EXPAND_KEY4 (ws, 128); SBOX (3, ws, subkeys[32]); + + wipememory (ws, sizeof (ws)); + wipememory (wt, sizeof (wt)); + wipememory (w, sizeof (w)); } /* Initialize CONTEXT with the key KEY of KEY_LENGTH bits. */ @@ -674,7 +667,7 @@ serpent_setkey_internal (serpent_context_t *context, } #endif - _gcry_burn_stack (272 * sizeof (u32)); + wipememory (key_prepared, sizeof(key_prepared)); } /* Initialize CTX with the key KEY of KEY_LENGTH bytes. */ @@ -699,10 +692,7 @@ serpent_setkey (void *ctx, if (serpent_test_ret) ret = GPG_ERR_SELFTEST_FAILED; else - { - serpent_setkey_internal (context, key, key_length); - _gcry_burn_stack (sizeof (serpent_key_t)); - } + serpent_setkey_internal (context, key, key_length); return ret; } From jussi.kivilinna at iki.fi Tue Nov 5 16:57:41 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:57:41 +0200 Subject: [PATCH 2/7] Tweak AES-NI bulk CTR mode slightly In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155741.6543.54745.stgit@localhost6.localdomain6> * cipher/rijndael.c [USE_AESNI] (aesni_cleanup_2_5): Rename to... (aesni_cleanup_2_6): ...this and clear also 'xmm6'. [USE_AESNI && __i386__] (do_aesni_ctr, do_aesni_ctr_4): Prevent inlining only on i386, allow on AMD64. [USE_AESNI] (do_aesni_ctr, do_aesni_ctr_4): Use counter block from 'xmm5' and byte-swap mask from 'xmm6'. (_gcry_aes_ctr_enc) [USE_AESNI]: Preload counter block to 'xmm5' and byte-swap mask to 'xmm6'. (_gcry_aes_ctr_enc, _gcry_aes_cfb_dec, _gcry_aes_cbc_dec): Use 'aesni_cleanup_2_6'. -- Small tweak that yeilds ~5% more speed on Intel Core i5-4570. After: AES | nanosecs/byte mebibytes/sec cycles/byte CTR enc | 0.274 ns/B 3482.5 MiB/s 0.877 c/B CTR dec | 0.274 ns/B 3486.8 MiB/s 0.876 c/B Before: AES | nanosecs/byte mebibytes/sec cycles/byte CTR enc | 0.288 ns/B 3312.5 MiB/s 0.922 c/B CTR dec | 0.288 ns/B 3312.6 MiB/s 0.922 c/B Signed-off-by: Jussi Kivilinna --- cipher/rijndael.c | 83 +++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/cipher/rijndael.c b/cipher/rijndael.c index b8cc18b..645cf37 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -189,11 +189,12 @@ typedef struct do { asm volatile ("pxor %%xmm0, %%xmm0\n\t" \ "pxor %%xmm1, %%xmm1\n" :: ); \ } while (0) -# define aesni_cleanup_2_5() \ +# define aesni_cleanup_2_6() \ do { asm volatile ("pxor %%xmm2, %%xmm2\n\t" \ "pxor %%xmm3, %%xmm3\n" \ "pxor %%xmm4, %%xmm4\n" \ - "pxor %%xmm5, %%xmm5\n":: ); \ + "pxor %%xmm5, %%xmm5\n" \ + "pxor %%xmm6, %%xmm6\n":: ); \ } while (0) #else # define aesni_prepare() do { } while (0) @@ -207,8 +208,8 @@ typedef struct /* Function prototypes. */ -#ifdef USE_AESNI -/* We don't want to inline these functions to help gcc allocate enough +#if defined(__i386__) && defined(USE_AESNI) +/* We don't want to inline these functions on i386 to help gcc allocate enough registers. */ static void do_aesni_ctr (const RIJNDAEL_context *ctx, unsigned char *ctr, unsigned char *b, const unsigned char *a) @@ -1165,15 +1166,13 @@ do_aesni_ctr (const RIJNDAEL_context *ctx, { #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" - static unsigned char be_mask[16] __attribute__ ((aligned (16))) = - { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - asm volatile ("movdqa (%[ctr]), %%xmm0\n\t" /* xmm0, xmm2 := CTR */ - "movaps %%xmm0, %%xmm2\n\t" + asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0, xmm2 := CTR (xmm5) */ + "movdqa %%xmm0, %%xmm2\n\t" "pcmpeqd %%xmm1, %%xmm1\n\t" "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */ - "pshufb %[mask], %%xmm2\n\t" + "pshufb %%xmm6, %%xmm2\n\t" "psubq %%xmm1, %%xmm2\n\t" /* xmm2++ (big endian) */ /* detect if 64-bit carry handling is needed */ @@ -1187,11 +1186,10 @@ do_aesni_ctr (const RIJNDAEL_context *ctx, ".Lno_carry%=:\n\t" - "pshufb %[mask], %%xmm2\n\t" - "movdqa %%xmm2, (%[ctr])\n" /* Update CTR. */ + "pshufb %%xmm6, %%xmm2\n\t" + "movdqa %%xmm2, (%[ctr])\n\t" /* Update CTR (mem). */ - "movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */ - "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ + "pxor (%[key]), %%xmm0\n\t" /* xmm1 ^= key[0] */ "movdqa 0x10(%[key]), %%xmm1\n\t" aesenc_xmm1_xmm0 "movdqa 0x20(%[key]), %%xmm1\n\t" @@ -1234,8 +1232,7 @@ do_aesni_ctr (const RIJNDAEL_context *ctx, : [src] "m" (*a), [ctr] "r" (ctr), [key] "r" (ctx->keyschenc), - [rounds] "g" (ctx->rounds), - [mask] "m" (*be_mask) + [rounds] "g" (ctx->rounds) : "cc", "memory"); #undef aesenc_xmm1_xmm0 #undef aesenclast_xmm1_xmm0 @@ -1256,9 +1253,6 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, #define aesenclast_xmm1_xmm3 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xd9\n\t" #define aesenclast_xmm1_xmm4 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xe1\n\t" - static unsigned char be_mask[16] __attribute__ ((aligned (16))) = - { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - /* Register usage: esi keyschedule xmm0 CTR-0 @@ -1266,21 +1260,22 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, xmm2 CTR-1 xmm3 CTR-2 xmm4 CTR-3 - xmm5 temp + xmm5 copy of *ctr + xmm6 endian swapping mask */ - asm volatile ("movdqa (%[ctr]), %%xmm0\n\t" /* xmm0, xmm2 := CTR */ - "movaps %%xmm0, %%xmm2\n\t" + asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0, xmm2 := CTR (xmm5) */ + "movdqa %%xmm0, %%xmm2\n\t" "pcmpeqd %%xmm1, %%xmm1\n\t" "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */ - "pshufb %[mask], %%xmm2\n\t" /* xmm2 := le(xmm2) */ + "pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := le(xmm2) */ "psubq %%xmm1, %%xmm2\n\t" /* xmm2++ */ - "movaps %%xmm2, %%xmm3\n\t" /* xmm3 := xmm2 */ + "movdqa %%xmm2, %%xmm3\n\t" /* xmm3 := xmm2 */ "psubq %%xmm1, %%xmm3\n\t" /* xmm3++ */ - "movaps %%xmm3, %%xmm4\n\t" /* xmm4 := xmm3 */ + "movdqa %%xmm3, %%xmm4\n\t" /* xmm4 := xmm3 */ "psubq %%xmm1, %%xmm4\n\t" /* xmm4++ */ - "movaps %%xmm4, %%xmm5\n\t" /* xmm5 := xmm4 */ + "movdqa %%xmm4, %%xmm5\n\t" /* xmm5 := xmm4 */ "psubq %%xmm1, %%xmm5\n\t" /* xmm5++ */ /* detect if 64-bit carry handling is needed */ @@ -1307,13 +1302,15 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, "psubq %%xmm1, %%xmm5\n\t" ".Lno_carry%=:\n\t" - "pshufb %[mask], %%xmm2\n\t" /* xmm2 := be(xmm2) */ - "pshufb %[mask], %%xmm3\n\t" /* xmm3 := be(xmm3) */ - "pshufb %[mask], %%xmm4\n\t" /* xmm4 := be(xmm4) */ - "pshufb %[mask], %%xmm5\n\t" /* xmm5 := be(xmm5) */ - "movdqa %%xmm5, (%[ctr])\n" /* Update CTR. */ - "movdqa (%[key]), %%xmm1\n\t" /* xmm1 := key[0] */ + "movl %[rounds], %%esi\n\t" + + "pshufb %%xmm6, %%xmm2\n\t" /* xmm2 := be(xmm2) */ + "pshufb %%xmm6, %%xmm3\n\t" /* xmm3 := be(xmm3) */ + "pshufb %%xmm6, %%xmm4\n\t" /* xmm4 := be(xmm4) */ + "pshufb %%xmm6, %%xmm5\n\t" /* xmm5 := be(xmm5) */ + "movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */ + "pxor %%xmm1, %%xmm0\n\t" /* xmm0 ^= key[0] */ "pxor %%xmm1, %%xmm2\n\t" /* xmm2 ^= key[0] */ "pxor %%xmm1, %%xmm3\n\t" /* xmm3 ^= key[0] */ @@ -1364,7 +1361,7 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, aesenc_xmm1_xmm3 aesenc_xmm1_xmm4 "movdqa 0xa0(%[key]), %%xmm1\n\t" - "cmpl $10, %[rounds]\n\t" + "cmpl $10, %%esi\n\t" "jz .Lenclast%=\n\t" aesenc_xmm1_xmm0 aesenc_xmm1_xmm2 @@ -1376,7 +1373,7 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, aesenc_xmm1_xmm3 aesenc_xmm1_xmm4 "movdqa 0xc0(%[key]), %%xmm1\n\t" - "cmpl $12, %[rounds]\n\t" + "cmpl $12, %%esi\n\t" "jz .Lenclast%=\n\t" aesenc_xmm1_xmm0 aesenc_xmm1_xmm2 @@ -1416,8 +1413,7 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, [src] "r" (a), [dst] "r" (b), [key] "r" (ctx->keyschenc), - [rounds] "g" (ctx->rounds), - [mask] "m" (*be_mask) + [rounds] "g" (ctx->rounds) : "%esi", "cc", "memory"); #undef aesenc_xmm1_xmm0 #undef aesenc_xmm1_xmm2 @@ -1653,7 +1649,18 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, #ifdef USE_AESNI else if (ctx->use_aesni) { + static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + aesni_prepare (); + + asm volatile ("movdqa %[mask], %%xmm6\n\t" /* Preload mask */ + "movdqa %[ctr], %%xmm5\n\t" /* Preload CTR */ + : /* No output */ + : [mask] "m" (*be_mask), + [ctr] "m" (*ctr) + : "memory"); + for ( ;nblocks > 3 ; nblocks -= 4 ) { do_aesni_ctr_4 (ctx, ctr, outbuf, inbuf); @@ -1667,7 +1674,7 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, inbuf += BLOCKSIZE; } aesni_cleanup (); - aesni_cleanup_2_5 (); + aesni_cleanup_2_6 (); } #endif /*USE_AESNI*/ else @@ -1953,7 +1960,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, inbuf += BLOCKSIZE; } aesni_cleanup (); - aesni_cleanup_2_5 (); + aesni_cleanup_2_6 (); } #endif /*USE_AESNI*/ else @@ -2074,7 +2081,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, : "memory"); aesni_cleanup (); - aesni_cleanup_2_5 (); + aesni_cleanup_2_6 (); } #endif /*USE_AESNI*/ else From jussi.kivilinna at iki.fi Tue Nov 5 16:58:06 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:58:06 +0200 Subject: [PATCH 7/7] Avoid burn stack in Arcfour setkey In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155806.6543.18085.stgit@localhost6.localdomain6> * cipher/arcfour.c (arcfour_setkey): Remove stack burning. -- Stack is already cleared in do_arcfour_setkey and GCC is inlining do_arcfour_setkey to arcfour_setkey which renders this _gcry_burn_stack broken anyways. Signed-off-by: Jussi Kivilinna --- cipher/arcfour.c | 1 - 1 file changed, 1 deletion(-) diff --git a/cipher/arcfour.c b/cipher/arcfour.c index 89936f4..64f7204 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -146,7 +146,6 @@ arcfour_setkey ( void *context, const byte *key, unsigned int keylen ) { ARCFOUR_context *ctx = (ARCFOUR_context *) context; gcry_err_code_t rc = do_arcfour_setkey (ctx, key, keylen ); - _gcry_burn_stack (300); return rc; } From jussi.kivilinna at iki.fi Tue Nov 5 16:57:51 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:57:51 +0200 Subject: [PATCH 4/7] Modify encrypt/decrypt arguments for in-place In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155751.6543.51617.stgit@localhost6.localdomain6> * cipher/cipher.c (gcry_cipher_encrypt, gcry_cipher_decrypt): Modify local arguments if in-place operation. -- Modify encrypt/decrypt argument variables instead of calling subfunction with different arguments. This allows compiler to inline the subfunction for small speedup. Signed-off-by: Jussi Kivilinna --- cipher/cipher.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/cipher/cipher.c b/cipher/cipher.c index 73a97b1..705696c 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -758,9 +758,12 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, gcry_err_code_t err; if (!in) /* Caller requested in-place encryption. */ - err = cipher_encrypt (h, out, outsize, out, outsize); - else - err = cipher_encrypt (h, out, outsize, in, inlen); + { + in = out; + inlen = outsize; + } + + err = cipher_encrypt (h, out, outsize, in, inlen); /* Failsafe: Make sure that the plaintext will never make it into OUT if the encryption returned an error. */ @@ -851,9 +854,12 @@ gcry_cipher_decrypt (gcry_cipher_hd_t h, void *out, size_t outsize, gcry_err_code_t err; if (!in) /* Caller requested in-place encryption. */ - err = cipher_decrypt (h, out, outsize, out, outsize); - else - err = cipher_decrypt (h, out, outsize, in, inlen); + { + in = out; + inlen = outsize; + } + + err = cipher_decrypt (h, out, outsize, in, inlen); return gcry_error (err); } From jussi.kivilinna at iki.fi Tue Nov 5 16:58:01 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:58:01 +0200 Subject: [PATCH 6/7] Avoid burn_stack in CAST5 setkey In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155801.6543.78551.stgit@localhost6.localdomain6> * cipher/cast5.c (do_cast_setkey): Use wipememory instead of memset. (cast_setkey): Remove stack burning. -- Burning stack does not work properly when compiler inlines static functions, therefore use wipememory to clear stack after use instead of relying on _gcry_burn_stack. Signed-off-by: Jussi Kivilinna --- cipher/cast5.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cipher/cast5.c b/cipher/cast5.c index 8d14183..09c9691 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -962,9 +962,9 @@ do_cast_setkey( CAST5_context *c, const byte *key, unsigned keylen ) } #endif - memset(&x,0, sizeof x); - memset(&z,0, sizeof z); - memset(&k,0, sizeof k); + wipememory(x, sizeof x); + wipememory(z, sizeof z); + wipememory(k, sizeof k); #undef xi #undef zi @@ -976,7 +976,6 @@ cast_setkey (void *context, const byte *key, unsigned keylen ) { CAST5_context *c = (CAST5_context *) context; gcry_err_code_t rc = do_cast_setkey (c, key, keylen); - _gcry_burn_stack (96+7*sizeof(void*)); return rc; } From jussi.kivilinna at iki.fi Tue Nov 5 16:57:46 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 05 Nov 2013 17:57:46 +0200 Subject: [PATCH 3/7] Speed up Stribog In-Reply-To: <20131105155735.6543.78655.stgit@localhost6.localdomain6> References: <20131105155735.6543.78655.stgit@localhost6.localdomain6> Message-ID: <20131105155746.6543.50411.stgit@localhost6.localdomain6> * cipher/stribog.c (STRIBOG_TABLES): Remove. (Pi): Remove. [!STRIBOG_TABLES] (A, strido): Remove. (stribog_table): New table pre-reordered with Pi values. (strido): Rewrite for new table. (LPSX): Rewrite for new table. (xor): Remove. (g): Small tweaks. -- Patch optimizes the table-lookup implementation a bit. Patch also removes the unused non-table implementation from source. On Intel Core i5-4570 (amd64, 3.2Ghz): After: | nanosecs/byte mebibytes/sec cycles/byte STRIBOG256 | 9.22 ns/B 103.4 MiB/s 29.53 c/B STRIBOG512 | 9.23 ns/B 103.4 MiB/s 29.53 c/B Before: | nanosecs/byte mebibytes/sec cycles/byte STRIBOG256 | 30.17 ns/B 31.61 MiB/s 96.56 c/B STRIBOG512 | 30.20 ns/B 31.57 MiB/s 96.68 c/B Signed-off-by: Jussi Kivilinna --- cipher/stribog.c | 2222 ++++++++++++++++++++++++++---------------------------- 1 file changed, 1070 insertions(+), 1152 deletions(-) diff --git a/cipher/stribog.c b/cipher/stribog.c index 7dcdfd6..a3cab36 100644 --- a/cipher/stribog.c +++ b/cipher/stribog.c @@ -17,9 +17,6 @@ * License along with this program; if not, see . */ -/* Undefine symbol to trade memory for speed */ -#define STRIBOG_TABLES 1 - #include #include #include @@ -31,6 +28,7 @@ #include "cipher.h" #include "hash-common.h" + typedef struct { gcry_md_block_ctx_t bctx; @@ -43,1134 +41,1044 @@ typedef struct u64 Sigma[8]; } STRIBOG_CONTEXT; -static const byte Pi[256] = -{ - 252, 238, 221, 17, 207, 110, 49, 22, 251, 196, 250, 218, 35, 197, 4, 77, 233, 119, 240, - 219, 147, 46, 153, 186, 23, 54, 241, 187, 20, 205, 95, 193, 249, 24, 101, 90, 226, 92, 239, - 33, 129, 28, 60, 66, 139, 1, 142, 79, 5, 132, 2, 174, 227, 106, 143, 160, 6, 11, 237, 152, 127, - 212, 211, 31, 235, 52, 44, 81, 234, 200, 72, 171, 242, 42, 104, 162, 253, 58, 206, 204, 181, - 112, 14, 86, 8, 12, 118, 18, 191, 114, 19, 71, 156, 183, 93, 135, 21, 161, 150, 41, 16, 123, - 154, 199, 243, 145, 120, 111, 157, 158, 178, 177, 50, 117, 25, 61, 255, 53, 138, 126, 109, - 84, 198, 128, 195, 189, 13, 87, 223, 245, 36, 169, 62, 168, 67, 201, 215, 121, 214, 246, 124, - 34, 185, 3, 224, 15, 236, 222, 122, 148, 176, 188, 220, 232, 40, 80, 78, 51, 10, 74, 167, 151, - 96, 115, 30, 0, 98, 68, 26, 184, 56, 130, 100, 159, 38, 65, 173, 69, 70, 146, 39, 94, 85, 47, - 140, 163, 165, 125, 105, 213, 149, 59, 7, 88, 179, 64, 134, 172, 29, 247, 48, 55, 107, 228, - 136, 217, 231, 137, 225, 27, 131, 73, 76, 63, 248, 254, 141, 83, 170, 144, 202, 216, 133, 97, - 32, 113, 103, 164, 45, 43, 9, 91, 203, 155, 37, 208, 190, 229, 108, 82, 89, 166, 116, 210, - 230, 244, 180, 192, 209, 102, 175, 194, 57, 75, 99, 182 -}; -#ifndef STRIBOG_TABLES -static const u64 A[64] = -{ - U64_C(0x641c314b2b8ee083), U64_C(0xc83862965601dd1b), - U64_C(0x8d70c431ac02a736), U64_C(0x07e095624504536c), - U64_C(0x0edd37c48a08a6d8), U64_C(0x1ca76e95091051ad), - U64_C(0x3853dc371220a247), U64_C(0x70a6a56e2440598e), - U64_C(0xa48b474f9ef5dc18), U64_C(0x550b8e9e21f7a530), - U64_C(0xaa16012142f35760), U64_C(0x492c024284fbaec0), - U64_C(0x9258048415eb419d), U64_C(0x39b008152acb8227), - U64_C(0x727d102a548b194e), U64_C(0xe4fa2054a80b329c), - U64_C(0xf97d86d98a327728), U64_C(0xeffa11af0964ee50), - U64_C(0xc3e9224312c8c1a0), U64_C(0x9bcf4486248d9f5d), - U64_C(0x2b838811480723ba), U64_C(0x561b0d22900e4669), - U64_C(0xac361a443d1c8cd2), U64_C(0x456c34887a3805b9), - U64_C(0x5b068c651810a89e), U64_C(0xb60c05ca30204d21), - U64_C(0x71180a8960409a42), U64_C(0xe230140fc0802984), - U64_C(0xd960281e9d1d5215), U64_C(0xafc0503c273aa42a), - U64_C(0x439da0784e745554), U64_C(0x86275df09ce8aaa8), - U64_C(0x0321658cba93c138), U64_C(0x0642ca05693b9f70), - U64_C(0x0c84890ad27623e0), U64_C(0x18150f14b9ec46dd), - U64_C(0x302a1e286fc58ca7), U64_C(0x60543c50de970553), - U64_C(0xc0a878a0a1330aa6), U64_C(0x9d4df05d5f661451), - U64_C(0xaccc9ca9328a8950), U64_C(0x4585254f64090fa0), - U64_C(0x8a174a9ec8121e5d), U64_C(0x092e94218d243cba), - U64_C(0x125c354207487869), U64_C(0x24b86a840e90f0d2), - U64_C(0x486dd4151c3dfdb9), U64_C(0x90dab52a387ae76f), - U64_C(0x46b60f011a83988e), U64_C(0x8c711e02341b2d01), - U64_C(0x05e23c0468365a02), U64_C(0x0ad97808d06cb404), - U64_C(0x14aff010bdd87508), U64_C(0x2843fd2067adea10), - U64_C(0x5086e740ce47c920), U64_C(0xa011d380818e8f40), - U64_C(0x83478b07b2468764), U64_C(0x1b8e0b0e798c13c8), - U64_C(0x3601161cf205268d), U64_C(0x6c022c38f90a4c07), - U64_C(0xd8045870ef14980e), U64_C(0xad08b0e0c3282d1c), - U64_C(0x47107ddd9b505a38), U64_C(0x8e20faa72ba0b470), -}; -static u64 strido (u64 l) -{ - u64 t = 0; -#if 0 - int j; - for (j = 0; j < 64; j++, l >>= 1) - { - if (l & 1) - t ^= A[j]; - } -#else -#define X(k) if (l & (1LL << k)) t ^= A[k]; - X(000); X(001); X(002); X(003); X(004); X(005); X(006); X(007); - X(010); X(011); X(012); X(013); X(014); X(015); X(016); X(017); - X(020); X(021); X(022); X(023); X(024); X(025); X(026); X(027); - X(030); X(031); X(032); X(033); X(034); X(035); X(036); X(037); - X(040); X(041); X(042); X(043); X(044); X(045); X(046); X(047); - X(050); X(051); X(052); X(053); X(054); X(055); X(056); X(057); - X(060); X(061); X(062); X(063); X(064); X(065); X(066); X(067); - X(070); X(071); X(072); X(073); X(074); X(075); X(076); X(077); -#undef X -#endif - return t; -} -#else -/* Pre-computed results of multiplication of bytes on A */ +/* Pre-computed results of multiplication of bytes on A and reordered with + Pi[]. */ static const u64 stribog_table[8][256] = { /* 0 */ - { U64_C(0x0000000000000000), U64_C(0x641c314b2b8ee083), - U64_C(0xc83862965601dd1b), U64_C(0xac2453dd7d8f3d98), - U64_C(0x8d70c431ac02a736), U64_C(0xe96cf57a878c47b5), - U64_C(0x4548a6a7fa037a2d), U64_C(0x215497ecd18d9aae), - U64_C(0x07e095624504536c), U64_C(0x63fca4296e8ab3ef), - U64_C(0xcfd8f7f413058e77), U64_C(0xabc4c6bf388b6ef4), - U64_C(0x8a905153e906f45a), U64_C(0xee8c6018c28814d9), - U64_C(0x42a833c5bf072941), U64_C(0x26b4028e9489c9c2), - U64_C(0x0edd37c48a08a6d8), U64_C(0x6ac1068fa186465b), - U64_C(0xc6e55552dc097bc3), U64_C(0xa2f96419f7879b40), - U64_C(0x83adf3f5260a01ee), U64_C(0xe7b1c2be0d84e16d), - U64_C(0x4b959163700bdcf5), U64_C(0x2f89a0285b853c76), - U64_C(0x093da2a6cf0cf5b4), U64_C(0x6d2193ede4821537), - U64_C(0xc105c030990d28af), U64_C(0xa519f17bb283c82c), - U64_C(0x844d6697630e5282), U64_C(0xe05157dc4880b201), - U64_C(0x4c750401350f8f99), U64_C(0x2869354a1e816f1a), - U64_C(0x1ca76e95091051ad), U64_C(0x78bb5fde229eb12e), - U64_C(0xd49f0c035f118cb6), U64_C(0xb0833d48749f6c35), - U64_C(0x91d7aaa4a512f69b), U64_C(0xf5cb9bef8e9c1618), - U64_C(0x59efc832f3132b80), U64_C(0x3df3f979d89dcb03), - U64_C(0x1b47fbf74c1402c1), U64_C(0x7f5bcabc679ae242), - U64_C(0xd37f99611a15dfda), U64_C(0xb763a82a319b3f59), - U64_C(0x96373fc6e016a5f7), U64_C(0xf22b0e8dcb984574), - U64_C(0x5e0f5d50b61778ec), U64_C(0x3a136c1b9d99986f), - U64_C(0x127a59518318f775), U64_C(0x7666681aa89617f6), - U64_C(0xda423bc7d5192a6e), U64_C(0xbe5e0a8cfe97caed), - U64_C(0x9f0a9d602f1a5043), U64_C(0xfb16ac2b0494b0c0), - U64_C(0x5732fff6791b8d58), U64_C(0x332ecebd52956ddb), - U64_C(0x159acc33c61ca419), U64_C(0x7186fd78ed92449a), - U64_C(0xdda2aea5901d7902), U64_C(0xb9be9feebb939981), - U64_C(0x98ea08026a1e032f), U64_C(0xfcf639494190e3ac), - U64_C(0x50d26a943c1fde34), U64_C(0x34ce5bdf17913eb7), - U64_C(0x3853dc371220a247), U64_C(0x5c4fed7c39ae42c4), - U64_C(0xf06bbea144217f5c), U64_C(0x94778fea6faf9fdf), - U64_C(0xb5231806be220571), U64_C(0xd13f294d95ace5f2), - U64_C(0x7d1b7a90e823d86a), U64_C(0x19074bdbc3ad38e9), - U64_C(0x3fb349555724f12b), U64_C(0x5baf781e7caa11a8), - U64_C(0xf78b2bc301252c30), U64_C(0x93971a882aabccb3), - U64_C(0xb2c38d64fb26561d), U64_C(0xd6dfbc2fd0a8b69e), - U64_C(0x7afbeff2ad278b06), U64_C(0x1ee7deb986a96b85), - U64_C(0x368eebf39828049f), U64_C(0x5292dab8b3a6e41c), - U64_C(0xfeb68965ce29d984), U64_C(0x9aaab82ee5a73907), - U64_C(0xbbfe2fc2342aa3a9), U64_C(0xdfe21e891fa4432a), - U64_C(0x73c64d54622b7eb2), U64_C(0x17da7c1f49a59e31), - U64_C(0x316e7e91dd2c57f3), U64_C(0x55724fdaf6a2b770), - U64_C(0xf9561c078b2d8ae8), U64_C(0x9d4a2d4ca0a36a6b), - U64_C(0xbc1ebaa0712ef0c5), U64_C(0xd8028beb5aa01046), - U64_C(0x7426d836272f2dde), U64_C(0x103ae97d0ca1cd5d), - U64_C(0x24f4b2a21b30f3ea), U64_C(0x40e883e930be1369), - U64_C(0xecccd0344d312ef1), U64_C(0x88d0e17f66bfce72), - U64_C(0xa9847693b73254dc), U64_C(0xcd9847d89cbcb45f), - U64_C(0x61bc1405e13389c7), U64_C(0x05a0254ecabd6944), - U64_C(0x231427c05e34a086), U64_C(0x4708168b75ba4005), - U64_C(0xeb2c455608357d9d), U64_C(0x8f30741d23bb9d1e), - U64_C(0xae64e3f1f23607b0), U64_C(0xca78d2bad9b8e733), - U64_C(0x665c8167a437daab), U64_C(0x0240b02c8fb93a28), - U64_C(0x2a29856691385532), U64_C(0x4e35b42dbab6b5b1), - U64_C(0xe211e7f0c7398829), U64_C(0x860dd6bbecb768aa), - U64_C(0xa75941573d3af204), U64_C(0xc345701c16b41287), - U64_C(0x6f6123c16b3b2f1f), U64_C(0x0b7d128a40b5cf9c), - U64_C(0x2dc91004d43c065e), U64_C(0x49d5214fffb2e6dd), - U64_C(0xe5f17292823ddb45), U64_C(0x81ed43d9a9b33bc6), - U64_C(0xa0b9d435783ea168), U64_C(0xc4a5e57e53b041eb), - U64_C(0x6881b6a32e3f7c73), U64_C(0x0c9d87e805b19cf0), - U64_C(0x70a6a56e2440598e), U64_C(0x14ba94250fceb90d), - U64_C(0xb89ec7f872418495), U64_C(0xdc82f6b359cf6416), - U64_C(0xfdd6615f8842feb8), U64_C(0x99ca5014a3cc1e3b), - U64_C(0x35ee03c9de4323a3), U64_C(0x51f23282f5cdc320), - U64_C(0x7746300c61440ae2), U64_C(0x135a01474acaea61), - U64_C(0xbf7e529a3745d7f9), U64_C(0xdb6263d11ccb377a), - U64_C(0xfa36f43dcd46add4), U64_C(0x9e2ac576e6c84d57), - U64_C(0x320e96ab9b4770cf), U64_C(0x5612a7e0b0c9904c), - U64_C(0x7e7b92aaae48ff56), U64_C(0x1a67a3e185c61fd5), - U64_C(0xb643f03cf849224d), U64_C(0xd25fc177d3c7c2ce), - U64_C(0xf30b569b024a5860), U64_C(0x971767d029c4b8e3), - U64_C(0x3b33340d544b857b), U64_C(0x5f2f05467fc565f8), - U64_C(0x799b07c8eb4cac3a), U64_C(0x1d873683c0c24cb9), - U64_C(0xb1a3655ebd4d7121), U64_C(0xd5bf541596c391a2), - U64_C(0xf4ebc3f9474e0b0c), U64_C(0x90f7f2b26cc0eb8f), - U64_C(0x3cd3a16f114fd617), U64_C(0x58cf90243ac13694), - U64_C(0x6c01cbfb2d500823), U64_C(0x081dfab006dee8a0), - U64_C(0xa439a96d7b51d538), U64_C(0xc025982650df35bb), - U64_C(0xe1710fca8152af15), U64_C(0x856d3e81aadc4f96), - U64_C(0x29496d5cd753720e), U64_C(0x4d555c17fcdd928d), - U64_C(0x6be15e9968545b4f), U64_C(0x0ffd6fd243dabbcc), - U64_C(0xa3d93c0f3e558654), U64_C(0xc7c50d4415db66d7), - U64_C(0xe6919aa8c456fc79), U64_C(0x828dabe3efd81cfa), - U64_C(0x2ea9f83e92572162), U64_C(0x4ab5c975b9d9c1e1), - U64_C(0x62dcfc3fa758aefb), U64_C(0x06c0cd748cd64e78), - U64_C(0xaae49ea9f15973e0), U64_C(0xcef8afe2dad79363), - U64_C(0xefac380e0b5a09cd), U64_C(0x8bb0094520d4e94e), - U64_C(0x27945a985d5bd4d6), U64_C(0x43886bd376d53455), - U64_C(0x653c695de25cfd97), U64_C(0x01205816c9d21d14), - U64_C(0xad040bcbb45d208c), U64_C(0xc9183a809fd3c00f), - U64_C(0xe84cad6c4e5e5aa1), U64_C(0x8c509c2765d0ba22), - U64_C(0x2074cffa185f87ba), U64_C(0x4468feb133d16739), - U64_C(0x48f579593660fbc9), U64_C(0x2ce948121dee1b4a), - U64_C(0x80cd1bcf606126d2), U64_C(0xe4d12a844befc651), - U64_C(0xc585bd689a625cff), U64_C(0xa1998c23b1ecbc7c), - U64_C(0x0dbddffecc6381e4), U64_C(0x69a1eeb5e7ed6167), - U64_C(0x4f15ec3b7364a8a5), U64_C(0x2b09dd7058ea4826), - U64_C(0x872d8ead256575be), U64_C(0xe331bfe60eeb953d), - U64_C(0xc265280adf660f93), U64_C(0xa6791941f4e8ef10), - U64_C(0x0a5d4a9c8967d288), U64_C(0x6e417bd7a2e9320b), - U64_C(0x46284e9dbc685d11), U64_C(0x22347fd697e6bd92), - U64_C(0x8e102c0bea69800a), U64_C(0xea0c1d40c1e76089), - U64_C(0xcb588aac106afa27), U64_C(0xaf44bbe73be41aa4), - U64_C(0x0360e83a466b273c), U64_C(0x677cd9716de5c7bf), - U64_C(0x41c8dbfff96c0e7d), U64_C(0x25d4eab4d2e2eefe), - U64_C(0x89f0b969af6dd366), U64_C(0xedec882284e333e5), - U64_C(0xccb81fce556ea94b), U64_C(0xa8a42e857ee049c8), - U64_C(0x04807d58036f7450), U64_C(0x609c4c1328e194d3), - U64_C(0x545217cc3f70aa64), U64_C(0x304e268714fe4ae7), - U64_C(0x9c6a755a6971777f), U64_C(0xf876441142ff97fc), - U64_C(0xd922d3fd93720d52), U64_C(0xbd3ee2b6b8fcedd1), - U64_C(0x111ab16bc573d049), U64_C(0x75068020eefd30ca), - U64_C(0x53b282ae7a74f908), U64_C(0x37aeb3e551fa198b), - U64_C(0x9b8ae0382c752413), U64_C(0xff96d17307fbc490), - U64_C(0xdec2469fd6765e3e), U64_C(0xbade77d4fdf8bebd), - U64_C(0x16fa240980778325), U64_C(0x72e61542abf963a6), - U64_C(0x5a8f2008b5780cbc), U64_C(0x3e9311439ef6ec3f), - U64_C(0x92b7429ee379d1a7), U64_C(0xf6ab73d5c8f73124), - U64_C(0xd7ffe439197aab8a), U64_C(0xb3e3d57232f44b09), - U64_C(0x1fc786af4f7b7691), U64_C(0x7bdbb7e464f59612), - U64_C(0x5d6fb56af07c5fd0), U64_C(0x39738421dbf2bf53), - U64_C(0x9557d7fca67d82cb), U64_C(0xf14be6b78df36248), - U64_C(0xd01f715b5c7ef8e6), U64_C(0xb403401077f01865), - U64_C(0x182713cd0a7f25fd), U64_C(0x7c3b228621f1c57e) }, + { U64_C(0xd01f715b5c7ef8e6), U64_C(0x16fa240980778325), + U64_C(0xa8a42e857ee049c8), U64_C(0x6ac1068fa186465b), + U64_C(0x6e417bd7a2e9320b), U64_C(0x665c8167a437daab), + U64_C(0x7666681aa89617f6), U64_C(0x4b959163700bdcf5), + U64_C(0xf14be6b78df36248), U64_C(0xc585bd689a625cff), + U64_C(0x9557d7fca67d82cb), U64_C(0x89f0b969af6dd366), + U64_C(0xb0833d48749f6c35), U64_C(0xa1998c23b1ecbc7c), + U64_C(0x8d70c431ac02a736), U64_C(0xd6dfbc2fd0a8b69e), + U64_C(0x37aeb3e551fa198b), U64_C(0x0b7d128a40b5cf9c), + U64_C(0x5a8f2008b5780cbc), U64_C(0xedec882284e333e5), + U64_C(0xd25fc177d3c7c2ce), U64_C(0x5e0f5d50b61778ec), + U64_C(0x1d873683c0c24cb9), U64_C(0xad040bcbb45d208c), + U64_C(0x2f89a0285b853c76), U64_C(0x5732fff6791b8d58), + U64_C(0x3e9311439ef6ec3f), U64_C(0xc9183a809fd3c00f), + U64_C(0x83adf3f5260a01ee), U64_C(0xa6791941f4e8ef10), + U64_C(0x103ae97d0ca1cd5d), U64_C(0x2ce948121dee1b4a), + U64_C(0x39738421dbf2bf53), U64_C(0x093da2a6cf0cf5b4), + U64_C(0xcd9847d89cbcb45f), U64_C(0xf9561c078b2d8ae8), + U64_C(0x9c6a755a6971777f), U64_C(0xbc1ebaa0712ef0c5), + U64_C(0x72e61542abf963a6), U64_C(0x78bb5fde229eb12e), + U64_C(0x14ba94250fceb90d), U64_C(0x844d6697630e5282), + U64_C(0x98ea08026a1e032f), U64_C(0xf06bbea144217f5c), + U64_C(0xdb6263d11ccb377a), U64_C(0x641c314b2b8ee083), + U64_C(0x320e96ab9b4770cf), U64_C(0x1ee7deb986a96b85), + U64_C(0xe96cf57a878c47b5), U64_C(0xfdd6615f8842feb8), + U64_C(0xc83862965601dd1b), U64_C(0x2ea9f83e92572162), + U64_C(0xf876441142ff97fc), U64_C(0xeb2c455608357d9d), + U64_C(0x5612a7e0b0c9904c), U64_C(0x6c01cbfb2d500823), + U64_C(0x4548a6a7fa037a2d), U64_C(0xabc4c6bf388b6ef4), + U64_C(0xbade77d4fdf8bebd), U64_C(0x799b07c8eb4cac3a), + U64_C(0x0c9d87e805b19cf0), U64_C(0xcb588aac106afa27), + U64_C(0xea0c1d40c1e76089), U64_C(0x2869354a1e816f1a), + U64_C(0xff96d17307fbc490), U64_C(0x9f0a9d602f1a5043), + U64_C(0x96373fc6e016a5f7), U64_C(0x5292dab8b3a6e41c), + U64_C(0x9b8ae0382c752413), U64_C(0x4f15ec3b7364a8a5), + U64_C(0x3fb349555724f12b), U64_C(0xc7c50d4415db66d7), + U64_C(0x92b7429ee379d1a7), U64_C(0xd37f99611a15dfda), + U64_C(0x231427c05e34a086), U64_C(0xa439a96d7b51d538), + U64_C(0xb403401077f01865), U64_C(0xdda2aea5901d7902), + U64_C(0x0a5d4a9c8967d288), U64_C(0xc265280adf660f93), + U64_C(0x8bb0094520d4e94e), U64_C(0x2a29856691385532), + U64_C(0x42a833c5bf072941), U64_C(0x73c64d54622b7eb2), + U64_C(0x07e095624504536c), U64_C(0x8a905153e906f45a), + U64_C(0x6f6123c16b3b2f1f), U64_C(0xc6e55552dc097bc3), + U64_C(0x4468feb133d16739), U64_C(0xe211e7f0c7398829), + U64_C(0xa2f96419f7879b40), U64_C(0x19074bdbc3ad38e9), + U64_C(0xf4ebc3f9474e0b0c), U64_C(0x43886bd376d53455), + U64_C(0xd8028beb5aa01046), U64_C(0x51f23282f5cdc320), + U64_C(0xe7b1c2be0d84e16d), U64_C(0x081dfab006dee8a0), + U64_C(0x3b33340d544b857b), U64_C(0x7f5bcabc679ae242), + U64_C(0x0edd37c48a08a6d8), U64_C(0x81ed43d9a9b33bc6), + U64_C(0xb1a3655ebd4d7121), U64_C(0x69a1eeb5e7ed6167), + U64_C(0xf6ab73d5c8f73124), U64_C(0x1a67a3e185c61fd5), + U64_C(0x2dc91004d43c065e), U64_C(0x0240b02c8fb93a28), + U64_C(0x90f7f2b26cc0eb8f), U64_C(0x3cd3a16f114fd617), + U64_C(0xaae49ea9f15973e0), U64_C(0x06c0cd748cd64e78), + U64_C(0xda423bc7d5192a6e), U64_C(0xc345701c16b41287), + U64_C(0x6d2193ede4821537), U64_C(0xfcf639494190e3ac), + U64_C(0x7c3b228621f1c57e), U64_C(0xfb16ac2b0494b0c0), + U64_C(0xbf7e529a3745d7f9), U64_C(0x6881b6a32e3f7c73), + U64_C(0xca78d2bad9b8e733), U64_C(0xbbfe2fc2342aa3a9), + U64_C(0x0dbddffecc6381e4), U64_C(0x70a6a56e2440598e), + U64_C(0xe4d12a844befc651), U64_C(0x8c509c2765d0ba22), + U64_C(0xee8c6018c28814d9), U64_C(0x17da7c1f49a59e31), + U64_C(0x609c4c1328e194d3), U64_C(0xb3e3d57232f44b09), + U64_C(0x91d7aaa4a512f69b), U64_C(0x0ffd6fd243dabbcc), + U64_C(0x50d26a943c1fde34), U64_C(0x6be15e9968545b4f), + U64_C(0x94778fea6faf9fdf), U64_C(0x2b09dd7058ea4826), + U64_C(0x677cd9716de5c7bf), U64_C(0x49d5214fffb2e6dd), + U64_C(0x0360e83a466b273c), U64_C(0x1fc786af4f7b7691), + U64_C(0xa0b9d435783ea168), U64_C(0xd49f0c035f118cb6), + U64_C(0x01205816c9d21d14), U64_C(0xac2453dd7d8f3d98), + U64_C(0x545217cc3f70aa64), U64_C(0x26b4028e9489c9c2), + U64_C(0xdec2469fd6765e3e), U64_C(0x04807d58036f7450), + U64_C(0xe5f17292823ddb45), U64_C(0xf30b569b024a5860), + U64_C(0x62dcfc3fa758aefb), U64_C(0xe84cad6c4e5e5aa1), + U64_C(0xccb81fce556ea94b), U64_C(0x53b282ae7a74f908), + U64_C(0x1b47fbf74c1402c1), U64_C(0x368eebf39828049f), + U64_C(0x7afbeff2ad278b06), U64_C(0xbe5e0a8cfe97caed), + U64_C(0xcfd8f7f413058e77), U64_C(0xf78b2bc301252c30), + U64_C(0x4d555c17fcdd928d), U64_C(0x5f2f05467fc565f8), + U64_C(0x24f4b2a21b30f3ea), U64_C(0x860dd6bbecb768aa), + U64_C(0x4c750401350f8f99), U64_C(0x0000000000000000), + U64_C(0xecccd0344d312ef1), U64_C(0xb5231806be220571), + U64_C(0xc105c030990d28af), U64_C(0x653c695de25cfd97), + U64_C(0x159acc33c61ca419), U64_C(0xb89ec7f872418495), + U64_C(0xa9847693b73254dc), U64_C(0x58cf90243ac13694), + U64_C(0x59efc832f3132b80), U64_C(0x5c4fed7c39ae42c4), + U64_C(0x828dabe3efd81cfa), U64_C(0xd13f294d95ace5f2), + U64_C(0x7d1b7a90e823d86a), U64_C(0xb643f03cf849224d), + U64_C(0x3df3f979d89dcb03), U64_C(0x7426d836272f2dde), + U64_C(0xdfe21e891fa4432a), U64_C(0x3a136c1b9d99986f), + U64_C(0xfa36f43dcd46add4), U64_C(0xc025982650df35bb), + U64_C(0x856d3e81aadc4f96), U64_C(0xc4a5e57e53b041eb), + U64_C(0x4708168b75ba4005), U64_C(0xaf44bbe73be41aa4), + U64_C(0x971767d029c4b8e3), U64_C(0xb9be9feebb939981), + U64_C(0x215497ecd18d9aae), U64_C(0x316e7e91dd2c57f3), + U64_C(0xcef8afe2dad79363), U64_C(0x3853dc371220a247), + U64_C(0x35ee03c9de4323a3), U64_C(0xe6919aa8c456fc79), + U64_C(0xe05157dc4880b201), U64_C(0x7bdbb7e464f59612), + U64_C(0x127a59518318f775), U64_C(0x332ecebd52956ddb), + U64_C(0x8f30741d23bb9d1e), U64_C(0xd922d3fd93720d52), + U64_C(0x7746300c61440ae2), U64_C(0x25d4eab4d2e2eefe), + U64_C(0x75068020eefd30ca), U64_C(0x135a01474acaea61), + U64_C(0x304e268714fe4ae7), U64_C(0xa519f17bb283c82c), + U64_C(0xdc82f6b359cf6416), U64_C(0x5baf781e7caa11a8), + U64_C(0xb2c38d64fb26561d), U64_C(0x34ce5bdf17913eb7), + U64_C(0x5d6fb56af07c5fd0), U64_C(0x182713cd0a7f25fd), + U64_C(0x9e2ac576e6c84d57), U64_C(0x9aaab82ee5a73907), + U64_C(0xa3d93c0f3e558654), U64_C(0x7e7b92aaae48ff56), + U64_C(0x872d8ead256575be), U64_C(0x41c8dbfff96c0e7d), + U64_C(0x99ca5014a3cc1e3b), U64_C(0x40e883e930be1369), + U64_C(0x1ca76e95091051ad), U64_C(0x4e35b42dbab6b5b1), + U64_C(0x05a0254ecabd6944), U64_C(0xe1710fca8152af15), + U64_C(0xf22b0e8dcb984574), U64_C(0xb763a82a319b3f59), + U64_C(0x63fca4296e8ab3ef), U64_C(0x9d4a2d4ca0a36a6b), + U64_C(0xe331bfe60eeb953d), U64_C(0xd5bf541596c391a2), + U64_C(0xf5cb9bef8e9c1618), U64_C(0x46284e9dbc685d11), + U64_C(0x2074cffa185f87ba), U64_C(0xbd3ee2b6b8fcedd1), + U64_C(0xae64e3f1f23607b0), U64_C(0xfeb68965ce29d984), + U64_C(0x55724fdaf6a2b770), U64_C(0x29496d5cd753720e), + U64_C(0xa75941573d3af204), U64_C(0x8e102c0bea69800a), + U64_C(0x111ab16bc573d049), U64_C(0xd7ffe439197aab8a), + U64_C(0xefac380e0b5a09cd), U64_C(0x48f579593660fbc9), + U64_C(0x22347fd697e6bd92), U64_C(0x61bc1405e13389c7), + U64_C(0x4ab5c975b9d9c1e1), U64_C(0x80cd1bcf606126d2), + U64_C(0x7186fd78ed92449a), U64_C(0x93971a882aabccb3), + U64_C(0x88d0e17f66bfce72), U64_C(0x27945a985d5bd4d6) }, /* 1 */ - { U64_C(0x0000000000000000), U64_C(0xa48b474f9ef5dc18), - U64_C(0x550b8e9e21f7a530), U64_C(0xf180c9d1bf027928), - U64_C(0xaa16012142f35760), U64_C(0x0e9d466edc068b78), - U64_C(0xff1d8fbf6304f250), U64_C(0x5b96c8f0fdf12e48), - U64_C(0x492c024284fbaec0), U64_C(0xeda7450d1a0e72d8), - U64_C(0x1c278cdca50c0bf0), U64_C(0xb8accb933bf9d7e8), - U64_C(0xe33a0363c608f9a0), U64_C(0x47b1442c58fd25b8), - U64_C(0xb6318dfde7ff5c90), U64_C(0x12bacab2790a8088), - U64_C(0x9258048415eb419d), U64_C(0x36d343cb8b1e9d85), - U64_C(0xc7538a1a341ce4ad), U64_C(0x63d8cd55aae938b5), - U64_C(0x384e05a5571816fd), U64_C(0x9cc542eac9edcae5), - U64_C(0x6d458b3b76efb3cd), U64_C(0xc9cecc74e81a6fd5), - U64_C(0xdb7406c69110ef5d), U64_C(0x7fff41890fe53345), - U64_C(0x8e7f8858b0e74a6d), U64_C(0x2af4cf172e129675), - U64_C(0x716207e7d3e3b83d), U64_C(0xd5e940a84d166425), - U64_C(0x24698979f2141d0d), U64_C(0x80e2ce366ce1c115), - U64_C(0x39b008152acb8227), U64_C(0x9d3b4f5ab43e5e3f), - U64_C(0x6cbb868b0b3c2717), U64_C(0xc830c1c495c9fb0f), - U64_C(0x93a609346838d547), U64_C(0x372d4e7bf6cd095f), - U64_C(0xc6ad87aa49cf7077), U64_C(0x6226c0e5d73aac6f), - U64_C(0x709c0a57ae302ce7), U64_C(0xd4174d1830c5f0ff), - U64_C(0x259784c98fc789d7), U64_C(0x811cc386113255cf), - U64_C(0xda8a0b76ecc37b87), U64_C(0x7e014c397236a79f), - U64_C(0x8f8185e8cd34deb7), U64_C(0x2b0ac2a753c102af), - U64_C(0xabe80c913f20c3ba), U64_C(0x0f634bdea1d51fa2), - U64_C(0xfee3820f1ed7668a), U64_C(0x5a68c5408022ba92), - U64_C(0x01fe0db07dd394da), U64_C(0xa5754affe32648c2), - U64_C(0x54f5832e5c2431ea), U64_C(0xf07ec461c2d1edf2), - U64_C(0xe2c40ed3bbdb6d7a), U64_C(0x464f499c252eb162), - U64_C(0xb7cf804d9a2cc84a), U64_C(0x1344c70204d91452), - U64_C(0x48d20ff2f9283a1a), U64_C(0xec5948bd67dde602), - U64_C(0x1dd9816cd8df9f2a), U64_C(0xb952c623462a4332), - U64_C(0x727d102a548b194e), U64_C(0xd6f65765ca7ec556), - U64_C(0x27769eb4757cbc7e), U64_C(0x83fdd9fbeb896066), - U64_C(0xd86b110b16784e2e), U64_C(0x7ce05644888d9236), - U64_C(0x8d609f95378feb1e), U64_C(0x29ebd8daa97a3706), - U64_C(0x3b511268d070b78e), U64_C(0x9fda55274e856b96), - U64_C(0x6e5a9cf6f18712be), U64_C(0xcad1dbb96f72cea6), - U64_C(0x914713499283e0ee), U64_C(0x35cc54060c763cf6), - U64_C(0xc44c9dd7b37445de), U64_C(0x60c7da982d8199c6), - U64_C(0xe02514ae416058d3), U64_C(0x44ae53e1df9584cb), - U64_C(0xb52e9a306097fde3), U64_C(0x11a5dd7ffe6221fb), - U64_C(0x4a33158f03930fb3), U64_C(0xeeb852c09d66d3ab), - U64_C(0x1f389b112264aa83), U64_C(0xbbb3dc5ebc91769b), - U64_C(0xa90916ecc59bf613), U64_C(0x0d8251a35b6e2a0b), - U64_C(0xfc029872e46c5323), U64_C(0x5889df3d7a998f3b), - U64_C(0x031f17cd8768a173), U64_C(0xa7945082199d7d6b), - U64_C(0x56149953a69f0443), U64_C(0xf29fde1c386ad85b), - U64_C(0x4bcd183f7e409b69), U64_C(0xef465f70e0b54771), - U64_C(0x1ec696a15fb73e59), U64_C(0xba4dd1eec142e241), - U64_C(0xe1db191e3cb3cc09), U64_C(0x45505e51a2461011), - U64_C(0xb4d097801d446939), U64_C(0x105bd0cf83b1b521), - U64_C(0x02e11a7dfabb35a9), U64_C(0xa66a5d32644ee9b1), - U64_C(0x57ea94e3db4c9099), U64_C(0xf361d3ac45b94c81), - U64_C(0xa8f71b5cb84862c9), U64_C(0x0c7c5c1326bdbed1), - U64_C(0xfdfc95c299bfc7f9), U64_C(0x5977d28d074a1be1), - U64_C(0xd9951cbb6babdaf4), U64_C(0x7d1e5bf4f55e06ec), - U64_C(0x8c9e92254a5c7fc4), U64_C(0x2815d56ad4a9a3dc), - U64_C(0x73831d9a29588d94), U64_C(0xd7085ad5b7ad518c), - U64_C(0x2688930408af28a4), U64_C(0x8203d44b965af4bc), - U64_C(0x90b91ef9ef507434), U64_C(0x343259b671a5a82c), - U64_C(0xc5b29067cea7d104), U64_C(0x6139d72850520d1c), - U64_C(0x3aaf1fd8ada32354), U64_C(0x9e2458973356ff4c), - U64_C(0x6fa491468c548664), U64_C(0xcb2fd60912a15a7c), - U64_C(0xe4fa2054a80b329c), U64_C(0x4071671b36feee84), - U64_C(0xb1f1aeca89fc97ac), U64_C(0x157ae98517094bb4), - U64_C(0x4eec2175eaf865fc), U64_C(0xea67663a740db9e4), - U64_C(0x1be7afebcb0fc0cc), U64_C(0xbf6ce8a455fa1cd4), - U64_C(0xadd622162cf09c5c), U64_C(0x095d6559b2054044), - U64_C(0xf8ddac880d07396c), U64_C(0x5c56ebc793f2e574), - U64_C(0x07c023376e03cb3c), U64_C(0xa34b6478f0f61724), - U64_C(0x52cbada94ff46e0c), U64_C(0xf640eae6d101b214), - U64_C(0x76a224d0bde07301), U64_C(0xd229639f2315af19), - U64_C(0x23a9aa4e9c17d631), U64_C(0x8722ed0102e20a29), - U64_C(0xdcb425f1ff132461), U64_C(0x783f62be61e6f879), - U64_C(0x89bfab6fdee48151), U64_C(0x2d34ec2040115d49), - U64_C(0x3f8e2692391bddc1), U64_C(0x9b0561dda7ee01d9), - U64_C(0x6a85a80c18ec78f1), U64_C(0xce0eef438619a4e9), - U64_C(0x959827b37be88aa1), U64_C(0x311360fce51d56b9), - U64_C(0xc093a92d5a1f2f91), U64_C(0x6418ee62c4eaf389), - U64_C(0xdd4a284182c0b0bb), U64_C(0x79c16f0e1c356ca3), - U64_C(0x8841a6dfa337158b), U64_C(0x2ccae1903dc2c993), - U64_C(0x775c2960c033e7db), U64_C(0xd3d76e2f5ec63bc3), - U64_C(0x2257a7fee1c442eb), U64_C(0x86dce0b17f319ef3), - U64_C(0x94662a03063b1e7b), U64_C(0x30ed6d4c98cec263), - U64_C(0xc16da49d27ccbb4b), U64_C(0x65e6e3d2b9396753), - U64_C(0x3e702b2244c8491b), U64_C(0x9afb6c6dda3d9503), - U64_C(0x6b7ba5bc653fec2b), U64_C(0xcff0e2f3fbca3033), - U64_C(0x4f122cc5972bf126), U64_C(0xeb996b8a09de2d3e), - U64_C(0x1a19a25bb6dc5416), U64_C(0xbe92e5142829880e), - U64_C(0xe5042de4d5d8a646), U64_C(0x418f6aab4b2d7a5e), - U64_C(0xb00fa37af42f0376), U64_C(0x1484e4356adadf6e), - U64_C(0x063e2e8713d05fe6), U64_C(0xa2b569c88d2583fe), - U64_C(0x5335a0193227fad6), U64_C(0xf7bee756acd226ce), - U64_C(0xac282fa651230886), U64_C(0x08a368e9cfd6d49e), - U64_C(0xf923a13870d4adb6), U64_C(0x5da8e677ee2171ae), - U64_C(0x9687307efc802bd2), U64_C(0x320c77316275f7ca), - U64_C(0xc38cbee0dd778ee2), U64_C(0x6707f9af438252fa), - U64_C(0x3c91315fbe737cb2), U64_C(0x981a76102086a0aa), - U64_C(0x699abfc19f84d982), U64_C(0xcd11f88e0171059a), - U64_C(0xdfab323c787b8512), U64_C(0x7b207573e68e590a), - U64_C(0x8aa0bca2598c2022), U64_C(0x2e2bfbedc779fc3a), - U64_C(0x75bd331d3a88d272), U64_C(0xd1367452a47d0e6a), - U64_C(0x20b6bd831b7f7742), U64_C(0x843dfacc858aab5a), - U64_C(0x04df34fae96b6a4f), U64_C(0xa05473b5779eb657), - U64_C(0x51d4ba64c89ccf7f), U64_C(0xf55ffd2b56691367), - U64_C(0xaec935dbab983d2f), U64_C(0x0a427294356de137), - U64_C(0xfbc2bb458a6f981f), U64_C(0x5f49fc0a149a4407), - U64_C(0x4df336b86d90c48f), U64_C(0xe97871f7f3651897), - U64_C(0x18f8b8264c6761bf), U64_C(0xbc73ff69d292bda7), - U64_C(0xe7e537992f6393ef), U64_C(0x436e70d6b1964ff7), - U64_C(0xb2eeb9070e9436df), U64_C(0x1665fe489061eac7), - U64_C(0xaf37386bd64ba9f5), U64_C(0x0bbc7f2448be75ed), - U64_C(0xfa3cb6f5f7bc0cc5), U64_C(0x5eb7f1ba6949d0dd), - U64_C(0x0521394a94b8fe95), U64_C(0xa1aa7e050a4d228d), - U64_C(0x502ab7d4b54f5ba5), U64_C(0xf4a1f09b2bba87bd), - U64_C(0xe61b3a2952b00735), U64_C(0x42907d66cc45db2d), - U64_C(0xb310b4b77347a205), U64_C(0x179bf3f8edb27e1d), - U64_C(0x4c0d3b0810435055), U64_C(0xe8867c478eb68c4d), - U64_C(0x1906b59631b4f565), U64_C(0xbd8df2d9af41297d), - U64_C(0x3d6f3cefc3a0e868), U64_C(0x99e47ba05d553470), - U64_C(0x6864b271e2574d58), U64_C(0xcceff53e7ca29140), - U64_C(0x97793dce8153bf08), U64_C(0x33f27a811fa66310), - U64_C(0xc272b350a0a41a38), U64_C(0x66f9f41f3e51c620), - U64_C(0x74433ead475b46a8), U64_C(0xd0c879e2d9ae9ab0), - U64_C(0x2148b03366ace398), U64_C(0x85c3f77cf8593f80), - U64_C(0xde553f8c05a811c8), U64_C(0x7ade78c39b5dcdd0), - U64_C(0x8b5eb112245fb4f8), U64_C(0x2fd5f65dbaaa68e0) }, + { U64_C(0xde553f8c05a811c8), U64_C(0x1906b59631b4f565), + U64_C(0x436e70d6b1964ff7), U64_C(0x36d343cb8b1e9d85), + U64_C(0x843dfacc858aab5a), U64_C(0xfdfc95c299bfc7f9), + U64_C(0x0f634bdea1d51fa2), U64_C(0x6d458b3b76efb3cd), + U64_C(0x85c3f77cf8593f80), U64_C(0x3c91315fbe737cb2), + U64_C(0x2148b03366ace398), U64_C(0x18f8b8264c6761bf), + U64_C(0xc830c1c495c9fb0f), U64_C(0x981a76102086a0aa), + U64_C(0xaa16012142f35760), U64_C(0x35cc54060c763cf6), + U64_C(0x42907d66cc45db2d), U64_C(0x8203d44b965af4bc), + U64_C(0x3d6f3cefc3a0e868), U64_C(0xbc73ff69d292bda7), + U64_C(0x8722ed0102e20a29), U64_C(0x8f8185e8cd34deb7), + U64_C(0x9b0561dda7ee01d9), U64_C(0x5335a0193227fad6), + U64_C(0xc9cecc74e81a6fd5), U64_C(0x54f5832e5c2431ea), + U64_C(0x99e47ba05d553470), U64_C(0xf7bee756acd226ce), + U64_C(0x384e05a5571816fd), U64_C(0xd1367452a47d0e6a), + U64_C(0xf29fde1c386ad85b), U64_C(0x320c77316275f7ca), + U64_C(0xd0c879e2d9ae9ab0), U64_C(0xdb7406c69110ef5d), + U64_C(0x45505e51a2461011), U64_C(0xfc029872e46c5323), + U64_C(0xfa3cb6f5f7bc0cc5), U64_C(0x031f17cd8768a173), + U64_C(0xbd8df2d9af41297d), U64_C(0x9d3b4f5ab43e5e3f), + U64_C(0x4071671b36feee84), U64_C(0x716207e7d3e3b83d), + U64_C(0x48d20ff2f9283a1a), U64_C(0x27769eb4757cbc7e), + U64_C(0x5c56ebc793f2e574), U64_C(0xa48b474f9ef5dc18), + U64_C(0x52cbada94ff46e0c), U64_C(0x60c7da982d8199c6), + U64_C(0x0e9d466edc068b78), U64_C(0x4eec2175eaf865fc), + U64_C(0x550b8e9e21f7a530), U64_C(0x6b7ba5bc653fec2b), + U64_C(0x5eb7f1ba6949d0dd), U64_C(0x57ea94e3db4c9099), + U64_C(0xf640eae6d101b214), U64_C(0xdd4a284182c0b0bb), + U64_C(0xff1d8fbf6304f250), U64_C(0xb8accb933bf9d7e8), + U64_C(0xe8867c478eb68c4d), U64_C(0x3f8e2692391bddc1), + U64_C(0xcb2fd60912a15a7c), U64_C(0xaec935dbab983d2f), + U64_C(0xf55ffd2b56691367), U64_C(0x80e2ce366ce1c115), + U64_C(0x179bf3f8edb27e1d), U64_C(0x01fe0db07dd394da), + U64_C(0xda8a0b76ecc37b87), U64_C(0x44ae53e1df9584cb), + U64_C(0xb310b4b77347a205), U64_C(0xdfab323c787b8512), + U64_C(0x3b511268d070b78e), U64_C(0x65e6e3d2b9396753), + U64_C(0x6864b271e2574d58), U64_C(0x259784c98fc789d7), + U64_C(0x02e11a7dfabb35a9), U64_C(0x8841a6dfa337158b), + U64_C(0x7ade78c39b5dcdd0), U64_C(0xb7cf804d9a2cc84a), + U64_C(0x20b6bd831b7f7742), U64_C(0x75bd331d3a88d272), + U64_C(0x418f6aab4b2d7a5e), U64_C(0xd9951cbb6babdaf4), + U64_C(0xb6318dfde7ff5c90), U64_C(0x1f389b112264aa83), + U64_C(0x492c024284fbaec0), U64_C(0xe33a0363c608f9a0), + U64_C(0x2688930408af28a4), U64_C(0xc7538a1a341ce4ad), + U64_C(0x5da8e677ee2171ae), U64_C(0x8c9e92254a5c7fc4), + U64_C(0x63d8cd55aae938b5), U64_C(0x29ebd8daa97a3706), + U64_C(0x959827b37be88aa1), U64_C(0x1484e4356adadf6e), + U64_C(0xa7945082199d7d6b), U64_C(0xbf6ce8a455fa1cd4), + U64_C(0x9cc542eac9edcae5), U64_C(0x79c16f0e1c356ca3), + U64_C(0x89bfab6fdee48151), U64_C(0xd4174d1830c5f0ff), + U64_C(0x9258048415eb419d), U64_C(0x6139d72850520d1c), + U64_C(0x6a85a80c18ec78f1), U64_C(0xcd11f88e0171059a), + U64_C(0xcceff53e7ca29140), U64_C(0xd229639f2315af19), + U64_C(0x90b91ef9ef507434), U64_C(0x5977d28d074a1be1), + U64_C(0x311360fce51d56b9), U64_C(0xc093a92d5a1f2f91), + U64_C(0x1a19a25bb6dc5416), U64_C(0xeb996b8a09de2d3e), + U64_C(0xfee3820f1ed7668a), U64_C(0xd7085ad5b7ad518c), + U64_C(0x7fff41890fe53345), U64_C(0xec5948bd67dde602), + U64_C(0x2fd5f65dbaaa68e0), U64_C(0xa5754affe32648c2), + U64_C(0xf8ddac880d07396c), U64_C(0x6fa491468c548664), + U64_C(0x0c7c5c1326bdbed1), U64_C(0x4a33158f03930fb3), + U64_C(0x699abfc19f84d982), U64_C(0xe4fa2054a80b329c), + U64_C(0x6707f9af438252fa), U64_C(0x08a368e9cfd6d49e), + U64_C(0x47b1442c58fd25b8), U64_C(0xbbb3dc5ebc91769b), + U64_C(0x1665fe489061eac7), U64_C(0x33f27a811fa66310), + U64_C(0x93a609346838d547), U64_C(0x30ed6d4c98cec263), + U64_C(0x1dd9816cd8df9f2a), U64_C(0x94662a03063b1e7b), + U64_C(0x83fdd9fbeb896066), U64_C(0x7b207573e68e590a), + U64_C(0x5f49fc0a149a4407), U64_C(0x343259b671a5a82c), + U64_C(0xfbc2bb458a6f981f), U64_C(0xc272b350a0a41a38), + U64_C(0x3aaf1fd8ada32354), U64_C(0x6cbb868b0b3c2717), + U64_C(0xa2b569c88d2583fe), U64_C(0xf180c9d1bf027928), + U64_C(0xaf37386bd64ba9f5), U64_C(0x12bacab2790a8088), + U64_C(0x4c0d3b0810435055), U64_C(0xb2eeb9070e9436df), + U64_C(0xc5b29067cea7d104), U64_C(0xdcb425f1ff132461), + U64_C(0x4f122cc5972bf126), U64_C(0xac282fa651230886), + U64_C(0xe7e537992f6393ef), U64_C(0xe61b3a2952b00735), + U64_C(0x709c0a57ae302ce7), U64_C(0xe02514ae416058d3), + U64_C(0xc44c9dd7b37445de), U64_C(0x5a68c5408022ba92), + U64_C(0x1c278cdca50c0bf0), U64_C(0x6e5a9cf6f18712be), + U64_C(0x86dce0b17f319ef3), U64_C(0x2d34ec2040115d49), + U64_C(0x4bcd183f7e409b69), U64_C(0x2815d56ad4a9a3dc), + U64_C(0x24698979f2141d0d), U64_C(0x0000000000000000), + U64_C(0x1ec696a15fb73e59), U64_C(0xd86b110b16784e2e), + U64_C(0x8e7f8858b0e74a6d), U64_C(0x063e2e8713d05fe6), + U64_C(0xe2c40ed3bbdb6d7a), U64_C(0xb1f1aeca89fc97ac), + U64_C(0xe1db191e3cb3cc09), U64_C(0x6418ee62c4eaf389), + U64_C(0xc6ad87aa49cf7077), U64_C(0xd6f65765ca7ec556), + U64_C(0x9afb6c6dda3d9503), U64_C(0x7ce05644888d9236), + U64_C(0x8d609f95378feb1e), U64_C(0x23a9aa4e9c17d631), + U64_C(0x6226c0e5d73aac6f), U64_C(0x56149953a69f0443), + U64_C(0xeeb852c09d66d3ab), U64_C(0x2b0ac2a753c102af), + U64_C(0x07c023376e03cb3c), U64_C(0x2ccae1903dc2c993), + U64_C(0xd3d76e2f5ec63bc3), U64_C(0x9e2458973356ff4c), + U64_C(0xa66a5d32644ee9b1), U64_C(0x0a427294356de137), + U64_C(0x783f62be61e6f879), U64_C(0x1344c70204d91452), + U64_C(0x5b96c8f0fdf12e48), U64_C(0xa90916ecc59bf613), + U64_C(0xbe92e5142829880e), U64_C(0x727d102a548b194e), + U64_C(0x1be7afebcb0fc0cc), U64_C(0x3e702b2244c8491b), + U64_C(0xd5e940a84d166425), U64_C(0x66f9f41f3e51c620), + U64_C(0xabe80c913f20c3ba), U64_C(0xf07ec461c2d1edf2), + U64_C(0xf361d3ac45b94c81), U64_C(0x0521394a94b8fe95), + U64_C(0xadd622162cf09c5c), U64_C(0xe97871f7f3651897), + U64_C(0xf4a1f09b2bba87bd), U64_C(0x095d6559b2054044), + U64_C(0x0bbc7f2448be75ed), U64_C(0x2af4cf172e129675), + U64_C(0x157ae98517094bb4), U64_C(0x9fda55274e856b96), + U64_C(0x914713499283e0ee), U64_C(0xb952c623462a4332), + U64_C(0x74433ead475b46a8), U64_C(0x8b5eb112245fb4f8), + U64_C(0xa34b6478f0f61724), U64_C(0x11a5dd7ffe6221fb), + U64_C(0xc16da49d27ccbb4b), U64_C(0x76a224d0bde07301), + U64_C(0x8aa0bca2598c2022), U64_C(0x4df336b86d90c48f), + U64_C(0xea67663a740db9e4), U64_C(0xef465f70e0b54771), + U64_C(0x39b008152acb8227), U64_C(0x7d1e5bf4f55e06ec), + U64_C(0x105bd0cf83b1b521), U64_C(0x775c2960c033e7db), + U64_C(0x7e014c397236a79f), U64_C(0x811cc386113255cf), + U64_C(0xeda7450d1a0e72d8), U64_C(0x5889df3d7a998f3b), + U64_C(0x2e2bfbedc779fc3a), U64_C(0xce0eef438619a4e9), + U64_C(0x372d4e7bf6cd095f), U64_C(0x04df34fae96b6a4f), + U64_C(0xf923a13870d4adb6), U64_C(0xa1aa7e050a4d228d), + U64_C(0xa8f71b5cb84862c9), U64_C(0xb52e9a306097fde3), + U64_C(0x0d8251a35b6e2a0b), U64_C(0x2257a7fee1c442eb), + U64_C(0x73831d9a29588d94), U64_C(0x51d4ba64c89ccf7f), + U64_C(0x502ab7d4b54f5ba5), U64_C(0x97793dce8153bf08), + U64_C(0xe5042de4d5d8a646), U64_C(0x9687307efc802bd2), + U64_C(0xa05473b5779eb657), U64_C(0xb4d097801d446939), + U64_C(0xcff0e2f3fbca3033), U64_C(0xc38cbee0dd778ee2), + U64_C(0x464f499c252eb162), U64_C(0xcad1dbb96f72cea6), + U64_C(0xba4dd1eec142e241), U64_C(0xb00fa37af42f0376) }, /* 2 */ - { U64_C(0x0000000000000000), U64_C(0xf97d86d98a327728), - U64_C(0xeffa11af0964ee50), U64_C(0x1687977683569978), - U64_C(0xc3e9224312c8c1a0), U64_C(0x3a94a49a98fab688), - U64_C(0x2c1333ec1bac2ff0), U64_C(0xd56eb535919e58d8), - U64_C(0x9bcf4486248d9f5d), U64_C(0x62b2c25faebfe875), - U64_C(0x743555292de9710d), U64_C(0x8d48d3f0a7db0625), - U64_C(0x582666c536455efd), U64_C(0xa15be01cbc7729d5), - U64_C(0xb7dc776a3f21b0ad), U64_C(0x4ea1f1b3b513c785), - U64_C(0x2b838811480723ba), U64_C(0xd2fe0ec8c2355492), - U64_C(0xc47999be4163cdea), U64_C(0x3d041f67cb51bac2), - U64_C(0xe86aaa525acfe21a), U64_C(0x11172c8bd0fd9532), - U64_C(0x0790bbfd53ab0c4a), U64_C(0xfeed3d24d9997b62), - U64_C(0xb04ccc976c8abce7), U64_C(0x49314a4ee6b8cbcf), - U64_C(0x5fb6dd3865ee52b7), U64_C(0xa6cb5be1efdc259f), - U64_C(0x73a5eed47e427d47), U64_C(0x8ad8680df4700a6f), - U64_C(0x9c5fff7b77269317), U64_C(0x652279a2fd14e43f), - U64_C(0x561b0d22900e4669), U64_C(0xaf668bfb1a3c3141), - U64_C(0xb9e11c8d996aa839), U64_C(0x409c9a541358df11), - U64_C(0x95f22f6182c687c9), U64_C(0x6c8fa9b808f4f0e1), - U64_C(0x7a083ece8ba26999), U64_C(0x8375b81701901eb1), - U64_C(0xcdd449a4b483d934), U64_C(0x34a9cf7d3eb1ae1c), - U64_C(0x222e580bbde73764), U64_C(0xdb53ded237d5404c), - U64_C(0x0e3d6be7a64b1894), U64_C(0xf740ed3e2c796fbc), - U64_C(0xe1c77a48af2ff6c4), U64_C(0x18bafc91251d81ec), - U64_C(0x7d988533d80965d3), U64_C(0x84e503ea523b12fb), - U64_C(0x9262949cd16d8b83), U64_C(0x6b1f12455b5ffcab), - U64_C(0xbe71a770cac1a473), U64_C(0x470c21a940f3d35b), - U64_C(0x518bb6dfc3a54a23), U64_C(0xa8f6300649973d0b), - U64_C(0xe657c1b5fc84fa8e), U64_C(0x1f2a476c76b68da6), - U64_C(0x09add01af5e014de), U64_C(0xf0d056c37fd263f6), - U64_C(0x25bee3f6ee4c3b2e), U64_C(0xdcc3652f647e4c06), - U64_C(0xca44f259e728d57e), U64_C(0x333974806d1aa256), - U64_C(0xac361a443d1c8cd2), U64_C(0x554b9c9db72efbfa), - U64_C(0x43cc0beb34786282), U64_C(0xbab18d32be4a15aa), - U64_C(0x6fdf38072fd44d72), U64_C(0x96a2bedea5e63a5a), - U64_C(0x802529a826b0a322), U64_C(0x7958af71ac82d40a), - U64_C(0x37f95ec21991138f), U64_C(0xce84d81b93a364a7), - U64_C(0xd8034f6d10f5fddf), U64_C(0x217ec9b49ac78af7), - U64_C(0xf4107c810b59d22f), U64_C(0x0d6dfa58816ba507), - U64_C(0x1bea6d2e023d3c7f), U64_C(0xe297ebf7880f4b57), - U64_C(0x87b59255751baf68), U64_C(0x7ec8148cff29d840), - U64_C(0x684f83fa7c7f4138), U64_C(0x91320523f64d3610), - U64_C(0x445cb01667d36ec8), U64_C(0xbd2136cfede119e0), - U64_C(0xaba6a1b96eb78098), U64_C(0x52db2760e485f7b0), - U64_C(0x1c7ad6d351963035), U64_C(0xe507500adba4471d), - U64_C(0xf380c77c58f2de65), U64_C(0x0afd41a5d2c0a94d), - U64_C(0xdf93f490435ef195), U64_C(0x26ee7249c96c86bd), - U64_C(0x3069e53f4a3a1fc5), U64_C(0xc91463e6c00868ed), - U64_C(0xfa2d1766ad12cabb), U64_C(0x035091bf2720bd93), - U64_C(0x15d706c9a47624eb), U64_C(0xecaa80102e4453c3), - U64_C(0x39c43525bfda0b1b), U64_C(0xc0b9b3fc35e87c33), - U64_C(0xd63e248ab6bee54b), U64_C(0x2f43a2533c8c9263), - U64_C(0x61e253e0899f55e6), U64_C(0x989fd53903ad22ce), - U64_C(0x8e18424f80fbbbb6), U64_C(0x7765c4960ac9cc9e), - U64_C(0xa20b71a39b579446), U64_C(0x5b76f77a1165e36e), - U64_C(0x4df1600c92337a16), U64_C(0xb48ce6d518010d3e), - U64_C(0xd1ae9f77e515e901), U64_C(0x28d319ae6f279e29), - U64_C(0x3e548ed8ec710751), U64_C(0xc729080166437079), - U64_C(0x1247bd34f7dd28a1), U64_C(0xeb3a3bed7def5f89), - U64_C(0xfdbdac9bfeb9c6f1), U64_C(0x04c02a42748bb1d9), - U64_C(0x4a61dbf1c198765c), U64_C(0xb31c5d284baa0174), - U64_C(0xa59bca5ec8fc980c), U64_C(0x5ce64c8742ceef24), - U64_C(0x8988f9b2d350b7fc), U64_C(0x70f57f6b5962c0d4), - U64_C(0x6672e81dda3459ac), U64_C(0x9f0f6ec450062e84), - U64_C(0x456c34887a3805b9), U64_C(0xbc11b251f00a7291), - U64_C(0xaa962527735cebe9), U64_C(0x53eba3fef96e9cc1), - U64_C(0x868516cb68f0c419), U64_C(0x7ff89012e2c2b331), - U64_C(0x697f076461942a49), U64_C(0x900281bdeba65d61), - U64_C(0xdea3700e5eb59ae4), U64_C(0x27def6d7d487edcc), - U64_C(0x315961a157d174b4), U64_C(0xc824e778dde3039c), - U64_C(0x1d4a524d4c7d5b44), U64_C(0xe437d494c64f2c6c), - U64_C(0xf2b043e24519b514), U64_C(0x0bcdc53bcf2bc23c), - U64_C(0x6eefbc99323f2603), U64_C(0x97923a40b80d512b), - U64_C(0x8115ad363b5bc853), U64_C(0x78682befb169bf7b), - U64_C(0xad069eda20f7e7a3), U64_C(0x547b1803aac5908b), - U64_C(0x42fc8f75299309f3), U64_C(0xbb8109aca3a17edb), - U64_C(0xf520f81f16b2b95e), U64_C(0x0c5d7ec69c80ce76), - U64_C(0x1adae9b01fd6570e), U64_C(0xe3a76f6995e42026), - U64_C(0x36c9da5c047a78fe), U64_C(0xcfb45c858e480fd6), - U64_C(0xd933cbf30d1e96ae), U64_C(0x204e4d2a872ce186), - U64_C(0x137739aaea3643d0), U64_C(0xea0abf73600434f8), - U64_C(0xfc8d2805e352ad80), U64_C(0x05f0aedc6960daa8), - U64_C(0xd09e1be9f8fe8270), U64_C(0x29e39d3072ccf558), - U64_C(0x3f640a46f19a6c20), U64_C(0xc6198c9f7ba81b08), - U64_C(0x88b87d2ccebbdc8d), U64_C(0x71c5fbf54489aba5), - U64_C(0x67426c83c7df32dd), U64_C(0x9e3fea5a4ded45f5), - U64_C(0x4b515f6fdc731d2d), U64_C(0xb22cd9b656416a05), - U64_C(0xa4ab4ec0d517f37d), U64_C(0x5dd6c8195f258455), - U64_C(0x38f4b1bba231606a), U64_C(0xc189376228031742), - U64_C(0xd70ea014ab558e3a), U64_C(0x2e7326cd2167f912), - U64_C(0xfb1d93f8b0f9a1ca), U64_C(0x026015213acbd6e2), - U64_C(0x14e78257b99d4f9a), U64_C(0xed9a048e33af38b2), - U64_C(0xa33bf53d86bcff37), U64_C(0x5a4673e40c8e881f), - U64_C(0x4cc1e4928fd81167), U64_C(0xb5bc624b05ea664f), - U64_C(0x60d2d77e94743e97), U64_C(0x99af51a71e4649bf), - U64_C(0x8f28c6d19d10d0c7), U64_C(0x765540081722a7ef), - U64_C(0xe95a2ecc4724896b), U64_C(0x1027a815cd16fe43), - U64_C(0x06a03f634e40673b), U64_C(0xffddb9bac4721013), - U64_C(0x2ab30c8f55ec48cb), U64_C(0xd3ce8a56dfde3fe3), - U64_C(0xc5491d205c88a69b), U64_C(0x3c349bf9d6bad1b3), - U64_C(0x72956a4a63a91636), U64_C(0x8be8ec93e99b611e), - U64_C(0x9d6f7be56acdf866), U64_C(0x6412fd3ce0ff8f4e), - U64_C(0xb17c48097161d796), U64_C(0x4801ced0fb53a0be), - U64_C(0x5e8659a6780539c6), U64_C(0xa7fbdf7ff2374eee), - U64_C(0xc2d9a6dd0f23aad1), U64_C(0x3ba420048511ddf9), - U64_C(0x2d23b77206474481), U64_C(0xd45e31ab8c7533a9), - U64_C(0x0130849e1deb6b71), U64_C(0xf84d024797d91c59), - U64_C(0xeeca9531148f8521), U64_C(0x17b713e89ebdf209), - U64_C(0x5916e25b2bae358c), U64_C(0xa06b6482a19c42a4), - U64_C(0xb6ecf3f422cadbdc), U64_C(0x4f91752da8f8acf4), - U64_C(0x9affc0183966f42c), U64_C(0x638246c1b3548304), - U64_C(0x7505d1b730021a7c), U64_C(0x8c78576eba306d54), - U64_C(0xbf4123eed72acf02), U64_C(0x463ca5375d18b82a), - U64_C(0x50bb3241de4e2152), U64_C(0xa9c6b498547c567a), - U64_C(0x7ca801adc5e20ea2), U64_C(0x85d587744fd0798a), - U64_C(0x93521002cc86e0f2), U64_C(0x6a2f96db46b497da), - U64_C(0x248e6768f3a7505f), U64_C(0xddf3e1b179952777), - U64_C(0xcb7476c7fac3be0f), U64_C(0x3209f01e70f1c927), - U64_C(0xe767452be16f91ff), U64_C(0x1e1ac3f26b5de6d7), - U64_C(0x089d5484e80b7faf), U64_C(0xf1e0d25d62390887), - U64_C(0x94c2abff9f2decb8), U64_C(0x6dbf2d26151f9b90), - U64_C(0x7b38ba50964902e8), U64_C(0x82453c891c7b75c0), - U64_C(0x572b89bc8de52d18), U64_C(0xae560f6507d75a30), - U64_C(0xb8d198138481c348), U64_C(0x41ac1eca0eb3b460), - U64_C(0x0f0def79bba073e5), U64_C(0xf67069a0319204cd), - U64_C(0xe0f7fed6b2c49db5), U64_C(0x198a780f38f6ea9d), - U64_C(0xcce4cd3aa968b245), U64_C(0x35994be3235ac56d), - U64_C(0x231edc95a00c5c15), U64_C(0xda635a4c2a3e2b3d) }, + { U64_C(0xcce4cd3aa968b245), U64_C(0x089d5484e80b7faf), + U64_C(0x638246c1b3548304), U64_C(0xd2fe0ec8c2355492), + U64_C(0xa7fbdf7ff2374eee), U64_C(0x4df1600c92337a16), + U64_C(0x84e503ea523b12fb), U64_C(0x0790bbfd53ab0c4a), + U64_C(0x198a780f38f6ea9d), U64_C(0x2ab30c8f55ec48cb), + U64_C(0xe0f7fed6b2c49db5), U64_C(0xb6ecf3f422cadbdc), + U64_C(0x409c9a541358df11), U64_C(0xd3ce8a56dfde3fe3), + U64_C(0xc3e9224312c8c1a0), U64_C(0x0d6dfa58816ba507), + U64_C(0xddf3e1b179952777), U64_C(0x04c02a42748bb1d9), + U64_C(0x94c2abff9f2decb8), U64_C(0x4f91752da8f8acf4), + U64_C(0x78682befb169bf7b), U64_C(0xe1c77a48af2ff6c4), + U64_C(0x0c5d7ec69c80ce76), U64_C(0x4cc1e4928fd81167), + U64_C(0xfeed3d24d9997b62), U64_C(0x518bb6dfc3a54a23), + U64_C(0x6dbf2d26151f9b90), U64_C(0xb5bc624b05ea664f), + U64_C(0xe86aaa525acfe21a), U64_C(0x4801ced0fb53a0be), + U64_C(0xc91463e6c00868ed), U64_C(0x1027a815cd16fe43), + U64_C(0xf67069a0319204cd), U64_C(0xb04ccc976c8abce7), + U64_C(0xc0b9b3fc35e87c33), U64_C(0xf380c77c58f2de65), + U64_C(0x50bb3241de4e2152), U64_C(0xdf93f490435ef195), + U64_C(0xf1e0d25d62390887), U64_C(0xaf668bfb1a3c3141), + U64_C(0xbc11b251f00a7291), U64_C(0x73a5eed47e427d47), + U64_C(0x25bee3f6ee4c3b2e), U64_C(0x43cc0beb34786282), + U64_C(0xc824e778dde3039c), U64_C(0xf97d86d98a327728), + U64_C(0xf2b043e24519b514), U64_C(0xe297ebf7880f4b57), + U64_C(0x3a94a49a98fab688), U64_C(0x868516cb68f0c419), + U64_C(0xeffa11af0964ee50), U64_C(0xa4ab4ec0d517f37d), + U64_C(0xa9c6b498547c567a), U64_C(0x8e18424f80fbbbb6), + U64_C(0x0bcdc53bcf2bc23c), U64_C(0x137739aaea3643d0), + U64_C(0x2c1333ec1bac2ff0), U64_C(0x8d48d3f0a7db0625), + U64_C(0x1e1ac3f26b5de6d7), U64_C(0xf520f81f16b2b95e), + U64_C(0x9f0f6ec450062e84), U64_C(0x0130849e1deb6b71), + U64_C(0xd45e31ab8c7533a9), U64_C(0x652279a2fd14e43f), + U64_C(0x3209f01e70f1c927), U64_C(0xbe71a770cac1a473), + U64_C(0x0e3d6be7a64b1894), U64_C(0x7ec8148cff29d840), + U64_C(0xcb7476c7fac3be0f), U64_C(0x72956a4a63a91636), + U64_C(0x37f95ec21991138f), U64_C(0x9e3fea5a4ded45f5), + U64_C(0x7b38ba50964902e8), U64_C(0x222e580bbde73764), + U64_C(0x61e253e0899f55e6), U64_C(0xfc8d2805e352ad80), + U64_C(0x35994be3235ac56d), U64_C(0x09add01af5e014de), + U64_C(0x5e8659a6780539c6), U64_C(0xb17c48097161d796), + U64_C(0x026015213acbd6e2), U64_C(0xd1ae9f77e515e901), + U64_C(0xb7dc776a3f21b0ad), U64_C(0xaba6a1b96eb78098), + U64_C(0x9bcf4486248d9f5d), U64_C(0x582666c536455efd), + U64_C(0xfdbdac9bfeb9c6f1), U64_C(0xc47999be4163cdea), + U64_C(0x765540081722a7ef), U64_C(0x3e548ed8ec710751), + U64_C(0x3d041f67cb51bac2), U64_C(0x7958af71ac82d40a), + U64_C(0x36c9da5c047a78fe), U64_C(0xed9a048e33af38b2), + U64_C(0x26ee7249c96c86bd), U64_C(0x900281bdeba65d61), + U64_C(0x11172c8bd0fd9532), U64_C(0xea0abf73600434f8), + U64_C(0x42fc8f75299309f3), U64_C(0x34a9cf7d3eb1ae1c), + U64_C(0x2b838811480723ba), U64_C(0x5ce64c8742ceef24), + U64_C(0x1adae9b01fd6570e), U64_C(0x3c349bf9d6bad1b3), + U64_C(0x82453c891c7b75c0), U64_C(0x97923a40b80d512b), + U64_C(0x4a61dbf1c198765c), U64_C(0xb48ce6d518010d3e), + U64_C(0xcfb45c858e480fd6), U64_C(0xd933cbf30d1e96ae), + U64_C(0xd70ea014ab558e3a), U64_C(0xc189376228031742), + U64_C(0x9262949cd16d8b83), U64_C(0xeb3a3bed7def5f89), + U64_C(0x49314a4ee6b8cbcf), U64_C(0xdcc3652f647e4c06), + U64_C(0xda635a4c2a3e2b3d), U64_C(0x470c21a940f3d35b), + U64_C(0x315961a157d174b4), U64_C(0x6672e81dda3459ac), + U64_C(0x5b76f77a1165e36e), U64_C(0x445cb01667d36ec8), + U64_C(0xc5491d205c88a69b), U64_C(0x456c34887a3805b9), + U64_C(0xffddb9bac4721013), U64_C(0x99af51a71e4649bf), + U64_C(0xa15be01cbc7729d5), U64_C(0x52db2760e485f7b0), + U64_C(0x8c78576eba306d54), U64_C(0xae560f6507d75a30), + U64_C(0x95f22f6182c687c9), U64_C(0x71c5fbf54489aba5), + U64_C(0xca44f259e728d57e), U64_C(0x88b87d2ccebbdc8d), + U64_C(0xbab18d32be4a15aa), U64_C(0x8be8ec93e99b611e), + U64_C(0x17b713e89ebdf209), U64_C(0xb31c5d284baa0174), + U64_C(0xeeca9531148f8521), U64_C(0xb8d198138481c348), + U64_C(0x8988f9b2d350b7fc), U64_C(0xb9e11c8d996aa839), + U64_C(0x5a4673e40c8e881f), U64_C(0x1687977683569978), + U64_C(0xbf4123eed72acf02), U64_C(0x4ea1f1b3b513c785), + U64_C(0xe767452be16f91ff), U64_C(0x7505d1b730021a7c), + U64_C(0xa59bca5ec8fc980c), U64_C(0xad069eda20f7e7a3), + U64_C(0x38f4b1bba231606a), U64_C(0x60d2d77e94743e97), + U64_C(0x9affc0183966f42c), U64_C(0x248e6768f3a7505f), + U64_C(0xcdd449a4b483d934), U64_C(0x87b59255751baf68), + U64_C(0x1bea6d2e023d3c7f), U64_C(0x6b1f12455b5ffcab), + U64_C(0x743555292de9710d), U64_C(0xd8034f6d10f5fddf), + U64_C(0xc6198c9f7ba81b08), U64_C(0xbb8109aca3a17edb), + U64_C(0xfa2d1766ad12cabb), U64_C(0xc729080166437079), + U64_C(0x9c5fff7b77269317), U64_C(0x0000000000000000), + U64_C(0x15d706c9a47624eb), U64_C(0x6fdf38072fd44d72), + U64_C(0x5fb6dd3865ee52b7), U64_C(0xa33bf53d86bcff37), + U64_C(0xe657c1b5fc84fa8e), U64_C(0xaa962527735cebe9), + U64_C(0x39c43525bfda0b1b), U64_C(0x204e4d2a872ce186), + U64_C(0x7a083ece8ba26999), U64_C(0x554b9c9db72efbfa), + U64_C(0xb22cd9b656416a05), U64_C(0x96a2bedea5e63a5a), + U64_C(0x802529a826b0a322), U64_C(0x8115ad363b5bc853), + U64_C(0x8375b81701901eb1), U64_C(0x3069e53f4a3a1fc5), + U64_C(0xbd2136cfede119e0), U64_C(0x18bafc91251d81ec), + U64_C(0x1d4a524d4c7d5b44), U64_C(0x05f0aedc6960daa8), + U64_C(0x29e39d3072ccf558), U64_C(0x70f57f6b5962c0d4), + U64_C(0x989fd53903ad22ce), U64_C(0xf84d024797d91c59), + U64_C(0x547b1803aac5908b), U64_C(0xf0d056c37fd263f6), + U64_C(0xd56eb535919e58d8), U64_C(0x1c7ad6d351963035), + U64_C(0x2e7326cd2167f912), U64_C(0xac361a443d1c8cd2), + U64_C(0x697f076461942a49), U64_C(0x4b515f6fdc731d2d), + U64_C(0x8ad8680df4700a6f), U64_C(0x41ac1eca0eb3b460), + U64_C(0x7d988533d80965d3), U64_C(0xa8f6300649973d0b), + U64_C(0x7765c4960ac9cc9e), U64_C(0x7ca801adc5e20ea2), + U64_C(0xdea3700e5eb59ae4), U64_C(0xa06b6482a19c42a4), + U64_C(0x6a2f96db46b497da), U64_C(0x27def6d7d487edcc), + U64_C(0x463ca5375d18b82a), U64_C(0xa6cb5be1efdc259f), + U64_C(0x53eba3fef96e9cc1), U64_C(0xce84d81b93a364a7), + U64_C(0xf4107c810b59d22f), U64_C(0x333974806d1aa256), + U64_C(0x0f0def79bba073e5), U64_C(0x231edc95a00c5c15), + U64_C(0xe437d494c64f2c6c), U64_C(0x91320523f64d3610), + U64_C(0x67426c83c7df32dd), U64_C(0x6eefbc99323f2603), + U64_C(0x9d6f7be56acdf866), U64_C(0x5916e25b2bae358c), + U64_C(0x7ff89012e2c2b331), U64_C(0x035091bf2720bd93), + U64_C(0x561b0d22900e4669), U64_C(0x28d319ae6f279e29), + U64_C(0x2f43a2533c8c9263), U64_C(0xd09e1be9f8fe8270), + U64_C(0xf740ed3e2c796fbc), U64_C(0xdb53ded237d5404c), + U64_C(0x62b2c25faebfe875), U64_C(0x0afd41a5d2c0a94d), + U64_C(0x6412fd3ce0ff8f4e), U64_C(0xe3a76f6995e42026), + U64_C(0x6c8fa9b808f4f0e1), U64_C(0xc2d9a6dd0f23aad1), + U64_C(0x8f28c6d19d10d0c7), U64_C(0x85d587744fd0798a), + U64_C(0xa20b71a39b579446), U64_C(0x684f83fa7c7f4138), + U64_C(0xe507500adba4471d), U64_C(0x3f640a46f19a6c20), + U64_C(0x1247bd34f7dd28a1), U64_C(0x2d23b77206474481), + U64_C(0x93521002cc86e0f2), U64_C(0x572b89bc8de52d18), + U64_C(0xfb1d93f8b0f9a1ca), U64_C(0xe95a2ecc4724896b), + U64_C(0x3ba420048511ddf9), U64_C(0xd63e248ab6bee54b), + U64_C(0x5dd6c8195f258455), U64_C(0x06a03f634e40673b), + U64_C(0x1f2a476c76b68da6), U64_C(0x217ec9b49ac78af7), + U64_C(0xecaa80102e4453c3), U64_C(0x14e78257b99d4f9a) }, /* 3 */ - { U64_C(0x0000000000000000), U64_C(0x5b068c651810a89e), - U64_C(0xb60c05ca30204d21), U64_C(0xed0a89af2830e5bf), - U64_C(0x71180a8960409a42), U64_C(0x2a1e86ec785032dc), - U64_C(0xc7140f435060d763), U64_C(0x9c12832648707ffd), - U64_C(0xe230140fc0802984), U64_C(0xb936986ad890811a), - U64_C(0x543c11c5f0a064a5), U64_C(0x0f3a9da0e8b0cc3b), - U64_C(0x93281e86a0c0b3c6), U64_C(0xc82e92e3b8d01b58), - U64_C(0x25241b4c90e0fee7), U64_C(0x7e22972988f05679), - U64_C(0xd960281e9d1d5215), U64_C(0x8266a47b850dfa8b), - U64_C(0x6f6c2dd4ad3d1f34), U64_C(0x346aa1b1b52db7aa), - U64_C(0xa8782297fd5dc857), U64_C(0xf37eaef2e54d60c9), - U64_C(0x1e74275dcd7d8576), U64_C(0x4572ab38d56d2de8), - U64_C(0x3b503c115d9d7b91), U64_C(0x6056b074458dd30f), - U64_C(0x8d5c39db6dbd36b0), U64_C(0xd65ab5be75ad9e2e), - U64_C(0x4a4836983ddde1d3), U64_C(0x114ebafd25cd494d), - U64_C(0xfc4433520dfdacf2), U64_C(0xa742bf3715ed046c), - U64_C(0xafc0503c273aa42a), U64_C(0xf4c6dc593f2a0cb4), - U64_C(0x19cc55f6171ae90b), U64_C(0x42cad9930f0a4195), - U64_C(0xded85ab5477a3e68), U64_C(0x85ded6d05f6a96f6), - U64_C(0x68d45f7f775a7349), U64_C(0x33d2d31a6f4adbd7), - U64_C(0x4df04433e7ba8dae), U64_C(0x16f6c856ffaa2530), - U64_C(0xfbfc41f9d79ac08f), U64_C(0xa0facd9ccf8a6811), - U64_C(0x3ce84eba87fa17ec), U64_C(0x67eec2df9feabf72), - U64_C(0x8ae44b70b7da5acd), U64_C(0xd1e2c715afcaf253), - U64_C(0x76a07822ba27f63f), U64_C(0x2da6f447a2375ea1), - U64_C(0xc0ac7de88a07bb1e), U64_C(0x9baaf18d92171380), - U64_C(0x07b872abda676c7d), U64_C(0x5cbefecec277c4e3), - U64_C(0xb1b47761ea47215c), U64_C(0xeab2fb04f25789c2), - U64_C(0x94906c2d7aa7dfbb), U64_C(0xcf96e04862b77725), - U64_C(0x229c69e74a87929a), U64_C(0x799ae58252973a04), - U64_C(0xe58866a41ae745f9), U64_C(0xbe8eeac102f7ed67), - U64_C(0x5384636e2ac708d8), U64_C(0x0882ef0b32d7a046), - U64_C(0x439da0784e745554), U64_C(0x189b2c1d5664fdca), - U64_C(0xf591a5b27e541875), U64_C(0xae9729d76644b0eb), - U64_C(0x3285aaf12e34cf16), U64_C(0x6983269436246788), - U64_C(0x8489af3b1e148237), U64_C(0xdf8f235e06042aa9), - U64_C(0xa1adb4778ef47cd0), U64_C(0xfaab381296e4d44e), - U64_C(0x17a1b1bdbed431f1), U64_C(0x4ca73dd8a6c4996f), - U64_C(0xd0b5befeeeb4e692), U64_C(0x8bb3329bf6a44e0c), - U64_C(0x66b9bb34de94abb3), U64_C(0x3dbf3751c684032d), - U64_C(0x9afd8866d3690741), U64_C(0xc1fb0403cb79afdf), - U64_C(0x2cf18dace3494a60), U64_C(0x77f701c9fb59e2fe), - U64_C(0xebe582efb3299d03), U64_C(0xb0e30e8aab39359d), - U64_C(0x5de987258309d022), U64_C(0x06ef0b409b1978bc), - U64_C(0x78cd9c6913e92ec5), U64_C(0x23cb100c0bf9865b), - U64_C(0xcec199a323c963e4), U64_C(0x95c715c63bd9cb7a), - U64_C(0x09d596e073a9b487), U64_C(0x52d31a856bb91c19), - U64_C(0xbfd9932a4389f9a6), U64_C(0xe4df1f4f5b995138), - U64_C(0xec5df044694ef17e), U64_C(0xb75b7c21715e59e0), - U64_C(0x5a51f58e596ebc5f), U64_C(0x015779eb417e14c1), - U64_C(0x9d45facd090e6b3c), U64_C(0xc64376a8111ec3a2), - U64_C(0x2b49ff07392e261d), U64_C(0x704f7362213e8e83), - U64_C(0x0e6de44ba9ced8fa), U64_C(0x556b682eb1de7064), - U64_C(0xb861e18199ee95db), U64_C(0xe3676de481fe3d45), - U64_C(0x7f75eec2c98e42b8), U64_C(0x247362a7d19eea26), - U64_C(0xc979eb08f9ae0f99), U64_C(0x927f676de1bea707), - U64_C(0x353dd85af453a36b), U64_C(0x6e3b543fec430bf5), - U64_C(0x8331dd90c473ee4a), U64_C(0xd83751f5dc6346d4), - U64_C(0x4425d2d394133929), U64_C(0x1f235eb68c0391b7), - U64_C(0xf229d719a4337408), U64_C(0xa92f5b7cbc23dc96), - U64_C(0xd70dcc5534d38aef), U64_C(0x8c0b40302cc32271), - U64_C(0x6101c99f04f3c7ce), U64_C(0x3a0745fa1ce36f50), - U64_C(0xa615c6dc549310ad), U64_C(0xfd134ab94c83b833), - U64_C(0x1019c31664b35d8c), U64_C(0x4b1f4f737ca3f512), - U64_C(0x86275df09ce8aaa8), U64_C(0xdd21d19584f80236), - U64_C(0x302b583aacc8e789), U64_C(0x6b2dd45fb4d84f17), - U64_C(0xf73f5779fca830ea), U64_C(0xac39db1ce4b89874), - U64_C(0x413352b3cc887dcb), U64_C(0x1a35ded6d498d555), - U64_C(0x641749ff5c68832c), U64_C(0x3f11c59a44782bb2), - U64_C(0xd21b4c356c48ce0d), U64_C(0x891dc05074586693), - U64_C(0x150f43763c28196e), U64_C(0x4e09cf132438b1f0), - U64_C(0xa30346bc0c08544f), U64_C(0xf805cad91418fcd1), - U64_C(0x5f4775ee01f5f8bd), U64_C(0x0441f98b19e55023), - U64_C(0xe94b702431d5b59c), U64_C(0xb24dfc4129c51d02), - U64_C(0x2e5f7f6761b562ff), U64_C(0x7559f30279a5ca61), - U64_C(0x98537aad51952fde), U64_C(0xc355f6c849858740), - U64_C(0xbd7761e1c175d139), U64_C(0xe671ed84d96579a7), - U64_C(0x0b7b642bf1559c18), U64_C(0x507de84ee9453486), - U64_C(0xcc6f6b68a1354b7b), U64_C(0x9769e70db925e3e5), - U64_C(0x7a636ea29115065a), U64_C(0x2165e2c78905aec4), - U64_C(0x29e70dccbbd20e82), U64_C(0x72e181a9a3c2a61c), - U64_C(0x9feb08068bf243a3), U64_C(0xc4ed846393e2eb3d), - U64_C(0x58ff0745db9294c0), U64_C(0x03f98b20c3823c5e), - U64_C(0xeef3028febb2d9e1), U64_C(0xb5f58eeaf3a2717f), - U64_C(0xcbd719c37b522706), U64_C(0x90d195a663428f98), - U64_C(0x7ddb1c094b726a27), U64_C(0x26dd906c5362c2b9), - U64_C(0xbacf134a1b12bd44), U64_C(0xe1c99f2f030215da), - U64_C(0x0cc316802b32f065), U64_C(0x57c59ae5332258fb), - U64_C(0xf08725d226cf5c97), U64_C(0xab81a9b73edff409), - U64_C(0x468b201816ef11b6), U64_C(0x1d8dac7d0effb928), - U64_C(0x819f2f5b468fc6d5), U64_C(0xda99a33e5e9f6e4b), - U64_C(0x37932a9176af8bf4), U64_C(0x6c95a6f46ebf236a), - U64_C(0x12b731dde64f7513), U64_C(0x49b1bdb8fe5fdd8d), - U64_C(0xa4bb3417d66f3832), U64_C(0xffbdb872ce7f90ac), - U64_C(0x63af3b54860fef51), U64_C(0x38a9b7319e1f47cf), - U64_C(0xd5a33e9eb62fa270), U64_C(0x8ea5b2fbae3f0aee), - U64_C(0xc5bafd88d29cfffc), U64_C(0x9ebc71edca8c5762), - U64_C(0x73b6f842e2bcb2dd), U64_C(0x28b07427faac1a43), - U64_C(0xb4a2f701b2dc65be), U64_C(0xefa47b64aacccd20), - U64_C(0x02aef2cb82fc289f), U64_C(0x59a87eae9aec8001), - U64_C(0x278ae987121cd678), U64_C(0x7c8c65e20a0c7ee6), - U64_C(0x9186ec4d223c9b59), U64_C(0xca8060283a2c33c7), - U64_C(0x5692e30e725c4c3a), U64_C(0x0d946f6b6a4ce4a4), - U64_C(0xe09ee6c4427c011b), U64_C(0xbb986aa15a6ca985), - U64_C(0x1cdad5964f81ade9), U64_C(0x47dc59f357910577), - U64_C(0xaad6d05c7fa1e0c8), U64_C(0xf1d05c3967b14856), - U64_C(0x6dc2df1f2fc137ab), U64_C(0x36c4537a37d19f35), - U64_C(0xdbcedad51fe17a8a), U64_C(0x80c856b007f1d214), - U64_C(0xfeeac1998f01846d), U64_C(0xa5ec4dfc97112cf3), - U64_C(0x48e6c453bf21c94c), U64_C(0x13e04836a73161d2), - U64_C(0x8ff2cb10ef411e2f), U64_C(0xd4f44775f751b6b1), - U64_C(0x39fecedadf61530e), U64_C(0x62f842bfc771fb90), - U64_C(0x6a7aadb4f5a65bd6), U64_C(0x317c21d1edb6f348), - U64_C(0xdc76a87ec58616f7), U64_C(0x8770241bdd96be69), - U64_C(0x1b62a73d95e6c194), U64_C(0x40642b588df6690a), - U64_C(0xad6ea2f7a5c68cb5), U64_C(0xf6682e92bdd6242b), - U64_C(0x884ab9bb35267252), U64_C(0xd34c35de2d36dacc), - U64_C(0x3e46bc7105063f73), U64_C(0x654030141d1697ed), - U64_C(0xf952b3325566e810), U64_C(0xa2543f574d76408e), - U64_C(0x4f5eb6f86546a531), U64_C(0x14583a9d7d560daf), - U64_C(0xb31a85aa68bb09c3), U64_C(0xe81c09cf70aba15d), - U64_C(0x05168060589b44e2), U64_C(0x5e100c05408bec7c), - U64_C(0xc2028f2308fb9381), U64_C(0x9904034610eb3b1f), - U64_C(0x740e8ae938dbdea0), U64_C(0x2f08068c20cb763e), - U64_C(0x512a91a5a83b2047), U64_C(0x0a2c1dc0b02b88d9), - U64_C(0xe726946f981b6d66), U64_C(0xbc20180a800bc5f8), - U64_C(0x20329b2cc87bba05), U64_C(0x7b341749d06b129b), - U64_C(0x963e9ee6f85bf724), U64_C(0xcd381283e04b5fba) }, + { U64_C(0x20329b2cc87bba05), U64_C(0x4f5eb6f86546a531), + U64_C(0xd4f44775f751b6b1), U64_C(0x8266a47b850dfa8b), + U64_C(0xbb986aa15a6ca985), U64_C(0xc979eb08f9ae0f99), + U64_C(0x2da6f447a2375ea1), U64_C(0x1e74275dcd7d8576), + U64_C(0xbc20180a800bc5f8), U64_C(0xb4a2f701b2dc65be), + U64_C(0xe726946f981b6d66), U64_C(0x48e6c453bf21c94c), + U64_C(0x42cad9930f0a4195), U64_C(0xefa47b64aacccd20), + U64_C(0x71180a8960409a42), U64_C(0x8bb3329bf6a44e0c), + U64_C(0xd34c35de2d36dacc), U64_C(0xa92f5b7cbc23dc96), + U64_C(0xb31a85aa68bb09c3), U64_C(0x13e04836a73161d2), + U64_C(0xb24dfc4129c51d02), U64_C(0x8ae44b70b7da5acd), + U64_C(0xe671ed84d96579a7), U64_C(0xa4bb3417d66f3832), + U64_C(0x4572ab38d56d2de8), U64_C(0xb1b47761ea47215c), + U64_C(0xe81c09cf70aba15d), U64_C(0xffbdb872ce7f90ac), + U64_C(0xa8782297fd5dc857), U64_C(0x0d946f6b6a4ce4a4), + U64_C(0xe4df1f4f5b995138), U64_C(0x9ebc71edca8c5762), + U64_C(0x0a2c1dc0b02b88d9), U64_C(0x3b503c115d9d7b91), + U64_C(0xc64376a8111ec3a2), U64_C(0xcec199a323c963e4), + U64_C(0xdc76a87ec58616f7), U64_C(0x09d596e073a9b487), + U64_C(0x14583a9d7d560daf), U64_C(0xf4c6dc593f2a0cb4), + U64_C(0xdd21d19584f80236), U64_C(0x4a4836983ddde1d3), + U64_C(0xe58866a41ae745f9), U64_C(0xf591a5b27e541875), + U64_C(0x891dc05074586693), U64_C(0x5b068c651810a89e), + U64_C(0xa30346bc0c08544f), U64_C(0x3dbf3751c684032d), + U64_C(0x2a1e86ec785032dc), U64_C(0xf73f5779fca830ea), + U64_C(0xb60c05ca30204d21), U64_C(0x0cc316802b32f065), + U64_C(0x8770241bdd96be69), U64_C(0xb861e18199ee95db), + U64_C(0xf805cad91418fcd1), U64_C(0x29e70dccbbd20e82), + U64_C(0xc7140f435060d763), U64_C(0x0f3a9da0e8b0cc3b), + U64_C(0xa2543f574d76408e), U64_C(0xbd7761e1c175d139), + U64_C(0x4b1f4f737ca3f512), U64_C(0x6dc2df1f2fc137ab), + U64_C(0xf1d05c3967b14856), U64_C(0xa742bf3715ed046c), + U64_C(0x654030141d1697ed), U64_C(0x07b872abda676c7d), + U64_C(0x3ce84eba87fa17ec), U64_C(0xc1fb0403cb79afdf), + U64_C(0x3e46bc7105063f73), U64_C(0x278ae987121cd678), + U64_C(0xa1adb4778ef47cd0), U64_C(0x26dd906c5362c2b9), + U64_C(0x05168060589b44e2), U64_C(0xfbfc41f9d79ac08f), + U64_C(0x0e6de44ba9ced8fa), U64_C(0x9feb08068bf243a3), + U64_C(0x7b341749d06b129b), U64_C(0x229c69e74a87929a), + U64_C(0xe09ee6c4427c011b), U64_C(0x5692e30e725c4c3a), + U64_C(0xda99a33e5e9f6e4b), U64_C(0x353dd85af453a36b), + U64_C(0x25241b4c90e0fee7), U64_C(0x5de987258309d022), + U64_C(0xe230140fc0802984), U64_C(0x93281e86a0c0b3c6), + U64_C(0xf229d719a4337408), U64_C(0x6f6c2dd4ad3d1f34), + U64_C(0x8ea5b2fbae3f0aee), U64_C(0x8331dd90c473ee4a), + U64_C(0x346aa1b1b52db7aa), U64_C(0xdf8f235e06042aa9), + U64_C(0xcc6f6b68a1354b7b), U64_C(0x6c95a6f46ebf236a), + U64_C(0x52d31a856bb91c19), U64_C(0x1a35ded6d498d555), + U64_C(0xf37eaef2e54d60c9), U64_C(0x72e181a9a3c2a61c), + U64_C(0x98537aad51952fde), U64_C(0x16f6c856ffaa2530), + U64_C(0xd960281e9d1d5215), U64_C(0x3a0745fa1ce36f50), + U64_C(0x0b7b642bf1559c18), U64_C(0x59a87eae9aec8001), + U64_C(0x5e100c05408bec7c), U64_C(0x0441f98b19e55023), + U64_C(0xd70dcc5534d38aef), U64_C(0x927f676de1bea707), + U64_C(0x9769e70db925e3e5), U64_C(0x7a636ea29115065a), + U64_C(0x468b201816ef11b6), U64_C(0xab81a9b73edff409), + U64_C(0xc0ac7de88a07bb1e), U64_C(0x1f235eb68c0391b7), + U64_C(0x6056b074458dd30f), U64_C(0xbe8eeac102f7ed67), + U64_C(0xcd381283e04b5fba), U64_C(0x5cbefecec277c4e3), + U64_C(0xd21b4c356c48ce0d), U64_C(0x1019c31664b35d8c), + U64_C(0x247362a7d19eea26), U64_C(0xebe582efb3299d03), + U64_C(0x02aef2cb82fc289f), U64_C(0x86275df09ce8aaa8), + U64_C(0x28b07427faac1a43), U64_C(0x38a9b7319e1f47cf), + U64_C(0xc82e92e3b8d01b58), U64_C(0x06ef0b409b1978bc), + U64_C(0x62f842bfc771fb90), U64_C(0x9904034610eb3b1f), + U64_C(0xded85ab5477a3e68), U64_C(0x90d195a663428f98), + U64_C(0x5384636e2ac708d8), U64_C(0xcbd719c37b522706), + U64_C(0xae9729d76644b0eb), U64_C(0x7c8c65e20a0c7ee6), + U64_C(0x80c856b007f1d214), U64_C(0x8c0b40302cc32271), + U64_C(0xdbcedad51fe17a8a), U64_C(0x740e8ae938dbdea0), + U64_C(0xa615c6dc549310ad), U64_C(0x19cc55f6171ae90b), + U64_C(0x49b1bdb8fe5fdd8d), U64_C(0xed0a89af2830e5bf), + U64_C(0x6a7aadb4f5a65bd6), U64_C(0x7e22972988f05679), + U64_C(0xf952b3325566e810), U64_C(0x39fecedadf61530e), + U64_C(0x6101c99f04f3c7ce), U64_C(0x2e5f7f6761b562ff), + U64_C(0xf08725d226cf5c97), U64_C(0x63af3b54860fef51), + U64_C(0x8ff2cb10ef411e2f), U64_C(0x884ab9bb35267252), + U64_C(0x4df04433e7ba8dae), U64_C(0x9afd8866d3690741), + U64_C(0x66b9bb34de94abb3), U64_C(0x9baaf18d92171380), + U64_C(0x543c11c5f0a064a5), U64_C(0x17a1b1bdbed431f1), + U64_C(0xb5f58eeaf3a2717f), U64_C(0xc355f6c849858740), + U64_C(0xec5df044694ef17e), U64_C(0xd83751f5dc6346d4), + U64_C(0xfc4433520dfdacf2), U64_C(0x0000000000000000), + U64_C(0x5a51f58e596ebc5f), U64_C(0x3285aaf12e34cf16), + U64_C(0x8d5c39db6dbd36b0), U64_C(0x12b731dde64f7513), + U64_C(0x94906c2d7aa7dfbb), U64_C(0x302b583aacc8e789), + U64_C(0x9d45facd090e6b3c), U64_C(0x2165e2c78905aec4), + U64_C(0x68d45f7f775a7349), U64_C(0x189b2c1d5664fdca), + U64_C(0xe1c99f2f030215da), U64_C(0x6983269436246788), + U64_C(0x8489af3b1e148237), U64_C(0xe94b702431d5b59c), + U64_C(0x33d2d31a6f4adbd7), U64_C(0xbfd9932a4389f9a6), + U64_C(0xb0e30e8aab39359d), U64_C(0xd1e2c715afcaf253), + U64_C(0x150f43763c28196e), U64_C(0xc4ed846393e2eb3d), + U64_C(0x03f98b20c3823c5e), U64_C(0xfd134ab94c83b833), + U64_C(0x556b682eb1de7064), U64_C(0x36c4537a37d19f35), + U64_C(0x7559f30279a5ca61), U64_C(0x799ae58252973a04), + U64_C(0x9c12832648707ffd), U64_C(0x78cd9c6913e92ec5), + U64_C(0x1d8dac7d0effb928), U64_C(0x439da0784e745554), + U64_C(0x413352b3cc887dcb), U64_C(0xbacf134a1b12bd44), + U64_C(0x114ebafd25cd494d), U64_C(0x2f08068c20cb763e), + U64_C(0x76a07822ba27f63f), U64_C(0xeab2fb04f25789c2), + U64_C(0xe3676de481fe3d45), U64_C(0x1b62a73d95e6c194), + U64_C(0x641749ff5c68832c), U64_C(0xa5ec4dfc97112cf3), + U64_C(0xf6682e92bdd6242b), U64_C(0x3f11c59a44782bb2), + U64_C(0x317c21d1edb6f348), U64_C(0xd65ab5be75ad9e2e), + U64_C(0x6b2dd45fb4d84f17), U64_C(0xfaab381296e4d44e), + U64_C(0xd0b5befeeeb4e692), U64_C(0x0882ef0b32d7a046), + U64_C(0x512a91a5a83b2047), U64_C(0x963e9ee6f85bf724), + U64_C(0x4e09cf132438b1f0), U64_C(0x77f701c9fb59e2fe), + U64_C(0x7ddb1c094b726a27), U64_C(0x5f4775ee01f5f8bd), + U64_C(0x9186ec4d223c9b59), U64_C(0xfeeac1998f01846d), + U64_C(0xac39db1ce4b89874), U64_C(0xb75b7c21715e59e0), + U64_C(0xafc0503c273aa42a), U64_C(0x6e3b543fec430bf5), + U64_C(0x704f7362213e8e83), U64_C(0x58ff0745db9294c0), + U64_C(0x67eec2df9feabf72), U64_C(0xa0facd9ccf8a6811), + U64_C(0xb936986ad890811a), U64_C(0x95c715c63bd9cb7a), + U64_C(0xca8060283a2c33c7), U64_C(0x507de84ee9453486), + U64_C(0x85ded6d05f6a96f6), U64_C(0x1cdad5964f81ade9), + U64_C(0xd5a33e9eb62fa270), U64_C(0x40642b588df6690a), + U64_C(0x7f75eec2c98e42b8), U64_C(0x2cf18dace3494a60), + U64_C(0x23cb100c0bf9865b), U64_C(0xeef3028febb2d9e1), + U64_C(0x4425d2d394133929), U64_C(0xaad6d05c7fa1e0c8), + U64_C(0xad6ea2f7a5c68cb5), U64_C(0xc2028f2308fb9381), + U64_C(0x819f2f5b468fc6d5), U64_C(0xc5bafd88d29cfffc), + U64_C(0x47dc59f357910577), U64_C(0x2b49ff07392e261d), + U64_C(0x57c59ae5332258fb), U64_C(0x73b6f842e2bcb2dd), + U64_C(0xcf96e04862b77725), U64_C(0x4ca73dd8a6c4996f), + U64_C(0x015779eb417e14c1), U64_C(0x37932a9176af8bf4) }, /* 4 */ - { U64_C(0x0000000000000000), U64_C(0x0321658cba93c138), - U64_C(0x0642ca05693b9f70), U64_C(0x0563af89d3a85e48), - U64_C(0x0c84890ad27623e0), U64_C(0x0fa5ec8668e5e2d8), - U64_C(0x0ac6430fbb4dbc90), U64_C(0x09e7268301de7da8), - U64_C(0x18150f14b9ec46dd), U64_C(0x1b346a98037f87e5), - U64_C(0x1e57c511d0d7d9ad), U64_C(0x1d76a09d6a441895), - U64_C(0x1491861e6b9a653d), U64_C(0x17b0e392d109a405), - U64_C(0x12d34c1b02a1fa4d), U64_C(0x11f22997b8323b75), - U64_C(0x302a1e286fc58ca7), U64_C(0x330b7ba4d5564d9f), - U64_C(0x3668d42d06fe13d7), U64_C(0x3549b1a1bc6dd2ef), - U64_C(0x3cae9722bdb3af47), U64_C(0x3f8ff2ae07206e7f), - U64_C(0x3aec5d27d4883037), U64_C(0x39cd38ab6e1bf10f), - U64_C(0x283f113cd629ca7a), U64_C(0x2b1e74b06cba0b42), - U64_C(0x2e7ddb39bf12550a), U64_C(0x2d5cbeb505819432), - U64_C(0x24bb9836045fe99a), U64_C(0x279afdbabecc28a2), - U64_C(0x22f952336d6476ea), U64_C(0x21d837bfd7f7b7d2), - U64_C(0x60543c50de970553), U64_C(0x637559dc6404c46b), - U64_C(0x6616f655b7ac9a23), U64_C(0x653793d90d3f5b1b), - U64_C(0x6cd0b55a0ce126b3), U64_C(0x6ff1d0d6b672e78b), - U64_C(0x6a927f5f65dab9c3), U64_C(0x69b31ad3df4978fb), - U64_C(0x78413344677b438e), U64_C(0x7b6056c8dde882b6), - U64_C(0x7e03f9410e40dcfe), U64_C(0x7d229ccdb4d31dc6), - U64_C(0x74c5ba4eb50d606e), U64_C(0x77e4dfc20f9ea156), - U64_C(0x7287704bdc36ff1e), U64_C(0x71a615c766a53e26), - U64_C(0x507e2278b15289f4), U64_C(0x535f47f40bc148cc), - U64_C(0x563ce87dd8691684), U64_C(0x551d8df162fad7bc), - U64_C(0x5cfaab726324aa14), U64_C(0x5fdbcefed9b76b2c), - U64_C(0x5ab861770a1f3564), U64_C(0x599904fbb08cf45c), - U64_C(0x486b2d6c08becf29), U64_C(0x4b4a48e0b22d0e11), - U64_C(0x4e29e76961855059), U64_C(0x4d0882e5db169161), - U64_C(0x44efa466dac8ecc9), U64_C(0x47cec1ea605b2df1), - U64_C(0x42ad6e63b3f373b9), U64_C(0x418c0bef0960b281), - U64_C(0xc0a878a0a1330aa6), U64_C(0xc3891d2c1ba0cb9e), - U64_C(0xc6eab2a5c80895d6), U64_C(0xc5cbd729729b54ee), - U64_C(0xcc2cf1aa73452946), U64_C(0xcf0d9426c9d6e87e), - U64_C(0xca6e3baf1a7eb636), U64_C(0xc94f5e23a0ed770e), - U64_C(0xd8bd77b418df4c7b), U64_C(0xdb9c1238a24c8d43), - U64_C(0xdeffbdb171e4d30b), U64_C(0xddded83dcb771233), - U64_C(0xd439febecaa96f9b), U64_C(0xd7189b32703aaea3), - U64_C(0xd27b34bba392f0eb), U64_C(0xd15a5137190131d3), - U64_C(0xf0826688cef68601), U64_C(0xf3a3030474654739), - U64_C(0xf6c0ac8da7cd1971), U64_C(0xf5e1c9011d5ed849), - U64_C(0xfc06ef821c80a5e1), U64_C(0xff278a0ea61364d9), - U64_C(0xfa44258775bb3a91), U64_C(0xf965400bcf28fba9), - U64_C(0xe897699c771ac0dc), U64_C(0xebb60c10cd8901e4), - U64_C(0xeed5a3991e215fac), U64_C(0xedf4c615a4b29e94), - U64_C(0xe413e096a56ce33c), U64_C(0xe732851a1fff2204), - U64_C(0xe2512a93cc577c4c), U64_C(0xe1704f1f76c4bd74), - U64_C(0xa0fc44f07fa40ff5), U64_C(0xa3dd217cc537cecd), - U64_C(0xa6be8ef5169f9085), U64_C(0xa59feb79ac0c51bd), - U64_C(0xac78cdfaadd22c15), U64_C(0xaf59a8761741ed2d), - U64_C(0xaa3a07ffc4e9b365), U64_C(0xa91b62737e7a725d), - U64_C(0xb8e94be4c6484928), U64_C(0xbbc82e687cdb8810), - U64_C(0xbeab81e1af73d658), U64_C(0xbd8ae46d15e01760), - U64_C(0xb46dc2ee143e6ac8), U64_C(0xb74ca762aeadabf0), - U64_C(0xb22f08eb7d05f5b8), U64_C(0xb10e6d67c7963480), - U64_C(0x90d65ad810618352), U64_C(0x93f73f54aaf2426a), - U64_C(0x969490dd795a1c22), U64_C(0x95b5f551c3c9dd1a), - U64_C(0x9c52d3d2c217a0b2), U64_C(0x9f73b65e7884618a), - U64_C(0x9a1019d7ab2c3fc2), U64_C(0x99317c5b11bffefa), - U64_C(0x88c355cca98dc58f), U64_C(0x8be23040131e04b7), - U64_C(0x8e819fc9c0b65aff), U64_C(0x8da0fa457a259bc7), - U64_C(0x8447dcc67bfbe66f), U64_C(0x8766b94ac1682757), - U64_C(0x820516c312c0791f), U64_C(0x8124734fa853b827), - U64_C(0x9d4df05d5f661451), U64_C(0x9e6c95d1e5f5d569), - U64_C(0x9b0f3a58365d8b21), U64_C(0x982e5fd48cce4a19), - U64_C(0x91c979578d1037b1), U64_C(0x92e81cdb3783f689), - U64_C(0x978bb352e42ba8c1), U64_C(0x94aad6de5eb869f9), - U64_C(0x8558ff49e68a528c), U64_C(0x86799ac55c1993b4), - U64_C(0x831a354c8fb1cdfc), U64_C(0x803b50c035220cc4), - U64_C(0x89dc764334fc716c), U64_C(0x8afd13cf8e6fb054), - U64_C(0x8f9ebc465dc7ee1c), U64_C(0x8cbfd9cae7542f24), - U64_C(0xad67ee7530a398f6), U64_C(0xae468bf98a3059ce), - U64_C(0xab25247059980786), U64_C(0xa80441fce30bc6be), - U64_C(0xa1e3677fe2d5bb16), U64_C(0xa2c202f358467a2e), - U64_C(0xa7a1ad7a8bee2466), U64_C(0xa480c8f6317de55e), - U64_C(0xb572e161894fde2b), U64_C(0xb65384ed33dc1f13), - U64_C(0xb3302b64e074415b), U64_C(0xb0114ee85ae78063), - U64_C(0xb9f6686b5b39fdcb), U64_C(0xbad70de7e1aa3cf3), - U64_C(0xbfb4a26e320262bb), U64_C(0xbc95c7e28891a383), - U64_C(0xfd19cc0d81f11102), U64_C(0xfe38a9813b62d03a), - U64_C(0xfb5b0608e8ca8e72), U64_C(0xf87a638452594f4a), - U64_C(0xf19d4507538732e2), U64_C(0xf2bc208be914f3da), - U64_C(0xf7df8f023abcad92), U64_C(0xf4feea8e802f6caa), - U64_C(0xe50cc319381d57df), U64_C(0xe62da695828e96e7), - U64_C(0xe34e091c5126c8af), U64_C(0xe06f6c90ebb50997), - U64_C(0xe9884a13ea6b743f), U64_C(0xeaa92f9f50f8b507), - U64_C(0xefca80168350eb4f), U64_C(0xecebe59a39c32a77), - U64_C(0xcd33d225ee349da5), U64_C(0xce12b7a954a75c9d), - U64_C(0xcb711820870f02d5), U64_C(0xc8507dac3d9cc3ed), - U64_C(0xc1b75b2f3c42be45), U64_C(0xc2963ea386d17f7d), - U64_C(0xc7f5912a55792135), U64_C(0xc4d4f4a6efeae00d), - U64_C(0xd526dd3157d8db78), U64_C(0xd607b8bded4b1a40), - U64_C(0xd36417343ee34408), U64_C(0xd04572b884708530), - U64_C(0xd9a2543b85aef898), U64_C(0xda8331b73f3d39a0), - U64_C(0xdfe09e3eec9567e8), U64_C(0xdcc1fbb25606a6d0), - U64_C(0x5de588fdfe551ef7), U64_C(0x5ec4ed7144c6dfcf), - U64_C(0x5ba742f8976e8187), U64_C(0x588627742dfd40bf), - U64_C(0x516101f72c233d17), U64_C(0x5240647b96b0fc2f), - U64_C(0x5723cbf24518a267), U64_C(0x5402ae7eff8b635f), - U64_C(0x45f087e947b9582a), U64_C(0x46d1e265fd2a9912), - U64_C(0x43b24dec2e82c75a), U64_C(0x4093286094110662), - U64_C(0x49740ee395cf7bca), U64_C(0x4a556b6f2f5cbaf2), - U64_C(0x4f36c4e6fcf4e4ba), U64_C(0x4c17a16a46672582), - U64_C(0x6dcf96d591909250), U64_C(0x6eeef3592b035368), - U64_C(0x6b8d5cd0f8ab0d20), U64_C(0x68ac395c4238cc18), - U64_C(0x614b1fdf43e6b1b0), U64_C(0x626a7a53f9757088), - U64_C(0x6709d5da2add2ec0), U64_C(0x6428b056904eeff8), - U64_C(0x75da99c1287cd48d), U64_C(0x76fbfc4d92ef15b5), - U64_C(0x739853c441474bfd), U64_C(0x70b93648fbd48ac5), - U64_C(0x795e10cbfa0af76d), U64_C(0x7a7f754740993655), - U64_C(0x7f1cdace9331681d), U64_C(0x7c3dbf4229a2a925), - U64_C(0x3db1b4ad20c21ba4), U64_C(0x3e90d1219a51da9c), - U64_C(0x3bf37ea849f984d4), U64_C(0x38d21b24f36a45ec), - U64_C(0x31353da7f2b43844), U64_C(0x3214582b4827f97c), - U64_C(0x3777f7a29b8fa734), U64_C(0x3456922e211c660c), - U64_C(0x25a4bbb9992e5d79), U64_C(0x2685de3523bd9c41), - U64_C(0x23e671bcf015c209), U64_C(0x20c714304a860331), - U64_C(0x292032b34b587e99), U64_C(0x2a01573ff1cbbfa1), - U64_C(0x2f62f8b62263e1e9), U64_C(0x2c439d3a98f020d1), - U64_C(0x0d9baa854f079703), U64_C(0x0ebacf09f594563b), - U64_C(0x0bd96080263c0873), U64_C(0x08f8050c9cafc94b), - U64_C(0x011f238f9d71b4e3), U64_C(0x023e460327e275db), - U64_C(0x075de98af44a2b93), U64_C(0x047c8c064ed9eaab), - U64_C(0x158ea591f6ebd1de), U64_C(0x16afc01d4c7810e6), - U64_C(0x13cc6f949fd04eae), U64_C(0x10ed0a1825438f96), - U64_C(0x190a2c9b249df23e), U64_C(0x1a2b49179e0e3306), - U64_C(0x1f48e69e4da66d4e), U64_C(0x1c698312f735ac76) }, + { U64_C(0x190a2c9b249df23e), U64_C(0x2f62f8b62263e1e9), + U64_C(0x7a7f754740993655), U64_C(0x330b7ba4d5564d9f), + U64_C(0x4c17a16a46672582), U64_C(0xb22f08eb7d05f5b8), + U64_C(0x535f47f40bc148cc), U64_C(0x3aec5d27d4883037), + U64_C(0x10ed0a1825438f96), U64_C(0x516101f72c233d17), + U64_C(0x13cc6f949fd04eae), U64_C(0x739853c441474bfd), + U64_C(0x653793d90d3f5b1b), U64_C(0x5240647b96b0fc2f), + U64_C(0x0c84890ad27623e0), U64_C(0xd7189b32703aaea3), + U64_C(0x2685de3523bd9c41), U64_C(0x99317c5b11bffefa), + U64_C(0x0d9baa854f079703), U64_C(0x70b93648fbd48ac5), + U64_C(0xa80441fce30bc6be), U64_C(0x7287704bdc36ff1e), + U64_C(0xb65384ed33dc1f13), U64_C(0xd36417343ee34408), + U64_C(0x39cd38ab6e1bf10f), U64_C(0x5ab861770a1f3564), + U64_C(0x0ebacf09f594563b), U64_C(0xd04572b884708530), + U64_C(0x3cae9722bdb3af47), U64_C(0x4a556b6f2f5cbaf2), + U64_C(0xe1704f1f76c4bd74), U64_C(0x5ec4ed7144c6dfcf), + U64_C(0x16afc01d4c7810e6), U64_C(0x283f113cd629ca7a), + U64_C(0xaf59a8761741ed2d), U64_C(0xeed5a3991e215fac), + U64_C(0x3bf37ea849f984d4), U64_C(0xe413e096a56ce33c), + U64_C(0x2c439d3a98f020d1), U64_C(0x637559dc6404c46b), + U64_C(0x9e6c95d1e5f5d569), U64_C(0x24bb9836045fe99a), + U64_C(0x44efa466dac8ecc9), U64_C(0xc6eab2a5c80895d6), + U64_C(0x803b50c035220cc4), U64_C(0x0321658cba93c138), + U64_C(0x8f9ebc465dc7ee1c), U64_C(0xd15a5137190131d3), + U64_C(0x0fa5ec8668e5e2d8), U64_C(0x91c979578d1037b1), + U64_C(0x0642ca05693b9f70), U64_C(0xefca80168350eb4f), + U64_C(0x38d21b24f36a45ec), U64_C(0xbeab81e1af73d658), + U64_C(0x8cbfd9cae7542f24), U64_C(0xfd19cc0d81f11102), + U64_C(0x0ac6430fbb4dbc90), U64_C(0x1d76a09d6a441895), + U64_C(0x2a01573ff1cbbfa1), U64_C(0xb572e161894fde2b), + U64_C(0x8124734fa853b827), U64_C(0x614b1fdf43e6b1b0), + U64_C(0x68ac395c4238cc18), U64_C(0x21d837bfd7f7b7d2), + U64_C(0x20c714304a860331), U64_C(0x5cfaab726324aa14), + U64_C(0x74c5ba4eb50d606e), U64_C(0xf3a3030474654739), + U64_C(0x23e671bcf015c209), U64_C(0x45f087e947b9582a), + U64_C(0xd8bd77b418df4c7b), U64_C(0xe06f6c90ebb50997), + U64_C(0x0bd96080263c0873), U64_C(0x7e03f9410e40dcfe), + U64_C(0xb8e94be4c6484928), U64_C(0xfb5b0608e8ca8e72), + U64_C(0x1a2b49179e0e3306), U64_C(0x4e29e76961855059), + U64_C(0x4f36c4e6fcf4e4ba), U64_C(0x49740ee395cf7bca), + U64_C(0xc2963ea386d17f7d), U64_C(0x90d65ad810618352), + U64_C(0x12d34c1b02a1fa4d), U64_C(0xfa44258775bb3a91), + U64_C(0x18150f14b9ec46dd), U64_C(0x1491861e6b9a653d), + U64_C(0x9a1019d7ab2c3fc2), U64_C(0x3668d42d06fe13d7), + U64_C(0xdcc1fbb25606a6d0), U64_C(0x969490dd795a1c22), + U64_C(0x3549b1a1bc6dd2ef), U64_C(0xc94f5e23a0ed770e), + U64_C(0xb9f6686b5b39fdcb), U64_C(0xc4d4f4a6efeae00d), + U64_C(0xe732851a1fff2204), U64_C(0x94aad6de5eb869f9), + U64_C(0x3f8ff2ae07206e7f), U64_C(0xfe38a9813b62d03a), + U64_C(0xa7a1ad7a8bee2466), U64_C(0x7b6056c8dde882b6), + U64_C(0x302a1e286fc58ca7), U64_C(0x8da0fa457a259bc7), + U64_C(0xb3302b64e074415b), U64_C(0x5402ae7eff8b635f), + U64_C(0x08f8050c9cafc94b), U64_C(0xae468bf98a3059ce), + U64_C(0x88c355cca98dc58f), U64_C(0xb10e6d67c7963480), + U64_C(0xbad70de7e1aa3cf3), U64_C(0xbfb4a26e320262bb), + U64_C(0xcb711820870f02d5), U64_C(0xce12b7a954a75c9d), + U64_C(0x563ce87dd8691684), U64_C(0x9f73b65e7884618a), + U64_C(0x2b1e74b06cba0b42), U64_C(0x47cec1ea605b2df1), + U64_C(0x1c698312f735ac76), U64_C(0x5fdbcefed9b76b2c), + U64_C(0x831a354c8fb1cdfc), U64_C(0x820516c312c0791f), + U64_C(0xb74ca762aeadabf0), U64_C(0xfc06ef821c80a5e1), + U64_C(0x5723cbf24518a267), U64_C(0x9d4df05d5f661451), + U64_C(0x588627742dfd40bf), U64_C(0xda8331b73f3d39a0), + U64_C(0x17b0e392d109a405), U64_C(0xf965400bcf28fba9), + U64_C(0x7c3dbf4229a2a925), U64_C(0x023e460327e275db), + U64_C(0x6cd0b55a0ce126b3), U64_C(0xe62da695828e96e7), + U64_C(0x42ad6e63b3f373b9), U64_C(0xe50cc319381d57df), + U64_C(0xc5cbd729729b54ee), U64_C(0x46d1e265fd2a9912), + U64_C(0x6428b056904eeff8), U64_C(0x8be23040131e04b7), + U64_C(0x6709d5da2add2ec0), U64_C(0x075de98af44a2b93), + U64_C(0x8447dcc67bfbe66f), U64_C(0x6616f655b7ac9a23), + U64_C(0xd607b8bded4b1a40), U64_C(0x0563af89d3a85e48), + U64_C(0x3db1b4ad20c21ba4), U64_C(0x11f22997b8323b75), + U64_C(0x292032b34b587e99), U64_C(0x7f1cdace9331681d), + U64_C(0x8e819fc9c0b65aff), U64_C(0xa1e3677fe2d5bb16), + U64_C(0xcd33d225ee349da5), U64_C(0xd9a2543b85aef898), + U64_C(0x795e10cbfa0af76d), U64_C(0x25a4bbb9992e5d79), + U64_C(0x78413344677b438e), U64_C(0xf0826688cef68601), + U64_C(0xd27b34bba392f0eb), U64_C(0x551d8df162fad7bc), + U64_C(0x1e57c511d0d7d9ad), U64_C(0xdeffbdb171e4d30b), + U64_C(0xf4feea8e802f6caa), U64_C(0xa480c8f6317de55e), + U64_C(0xa0fc44f07fa40ff5), U64_C(0x95b5f551c3c9dd1a), + U64_C(0x22f952336d6476ea), U64_C(0x0000000000000000), + U64_C(0xa6be8ef5169f9085), U64_C(0xcc2cf1aa73452946), + U64_C(0x2e7ddb39bf12550a), U64_C(0xd526dd3157d8db78), + U64_C(0x486b2d6c08becf29), U64_C(0x9b0f3a58365d8b21), + U64_C(0xac78cdfaadd22c15), U64_C(0xbc95c7e28891a383), + U64_C(0x6a927f5f65dab9c3), U64_C(0xc3891d2c1ba0cb9e), + U64_C(0xeaa92f9f50f8b507), U64_C(0xcf0d9426c9d6e87e), + U64_C(0xca6e3baf1a7eb636), U64_C(0xab25247059980786), + U64_C(0x69b31ad3df4978fb), U64_C(0xe2512a93cc577c4c), + U64_C(0xff278a0ea61364d9), U64_C(0x71a615c766a53e26), + U64_C(0x89dc764334fc716c), U64_C(0xf87a638452594f4a), + U64_C(0xf2bc208be914f3da), U64_C(0x8766b94ac1682757), + U64_C(0xbbc82e687cdb8810), U64_C(0x626a7a53f9757088), + U64_C(0xa2c202f358467a2e), U64_C(0x4d0882e5db169161), + U64_C(0x09e7268301de7da8), U64_C(0xe897699c771ac0dc), + U64_C(0xc8507dac3d9cc3ed), U64_C(0xc0a878a0a1330aa6), + U64_C(0x978bb352e42ba8c1), U64_C(0xe9884a13ea6b743f), + U64_C(0x279afdbabecc28a2), U64_C(0x047c8c064ed9eaab), + U64_C(0x507e2278b15289f4), U64_C(0x599904fbb08cf45c), + U64_C(0xbd8ae46d15e01760), U64_C(0x31353da7f2b43844), + U64_C(0x8558ff49e68a528c), U64_C(0x76fbfc4d92ef15b5), + U64_C(0x3456922e211c660c), U64_C(0x86799ac55c1993b4), + U64_C(0x3e90d1219a51da9c), U64_C(0x2d5cbeb505819432), + U64_C(0x982e5fd48cce4a19), U64_C(0xdb9c1238a24c8d43), + U64_C(0xd439febecaa96f9b), U64_C(0x418c0bef0960b281), + U64_C(0x158ea591f6ebd1de), U64_C(0x1f48e69e4da66d4e), + U64_C(0x8afd13cf8e6fb054), U64_C(0xf5e1c9011d5ed849), + U64_C(0xe34e091c5126c8af), U64_C(0xad67ee7530a398f6), + U64_C(0x43b24dec2e82c75a), U64_C(0x75da99c1287cd48d), + U64_C(0x92e81cdb3783f689), U64_C(0xa3dd217cc537cecd), + U64_C(0x60543c50de970553), U64_C(0x93f73f54aaf2426a), + U64_C(0xa91b62737e7a725d), U64_C(0xf19d4507538732e2), + U64_C(0x77e4dfc20f9ea156), U64_C(0x7d229ccdb4d31dc6), + U64_C(0x1b346a98037f87e5), U64_C(0xedf4c615a4b29e94), + U64_C(0x4093286094110662), U64_C(0xb0114ee85ae78063), + U64_C(0x6ff1d0d6b672e78b), U64_C(0x6dcf96d591909250), + U64_C(0xdfe09e3eec9567e8), U64_C(0x3214582b4827f97c), + U64_C(0xb46dc2ee143e6ac8), U64_C(0xf6c0ac8da7cd1971), + U64_C(0xebb60c10cd8901e4), U64_C(0xf7df8f023abcad92), + U64_C(0x9c52d3d2c217a0b2), U64_C(0x6b8d5cd0f8ab0d20), + U64_C(0x3777f7a29b8fa734), U64_C(0x011f238f9d71b4e3), + U64_C(0xc1b75b2f3c42be45), U64_C(0x5de588fdfe551ef7), + U64_C(0x6eeef3592b035368), U64_C(0xaa3a07ffc4e9b365), + U64_C(0xecebe59a39c32a77), U64_C(0x5ba742f8976e8187), + U64_C(0x4b4a48e0b22d0e11), U64_C(0xddded83dcb771233), + U64_C(0xa59feb79ac0c51bd), U64_C(0xc7f5912a55792135) }, /* 5 */ - { U64_C(0x0000000000000000), U64_C(0xaccc9ca9328a8950), - U64_C(0x4585254f64090fa0), U64_C(0xe949b9e6568386f0), - U64_C(0x8a174a9ec8121e5d), U64_C(0x26dbd637fa98970d), - U64_C(0xcf926fd1ac1b11fd), U64_C(0x635ef3789e9198ad), - U64_C(0x092e94218d243cba), U64_C(0xa5e20888bfaeb5ea), - U64_C(0x4cabb16ee92d331a), U64_C(0xe0672dc7dba7ba4a), - U64_C(0x8339debf453622e7), U64_C(0x2ff5421677bcabb7), - U64_C(0xc6bcfbf0213f2d47), U64_C(0x6a70675913b5a417), - U64_C(0x125c354207487869), U64_C(0xbe90a9eb35c2f139), - U64_C(0x57d9100d634177c9), U64_C(0xfb158ca451cbfe99), - U64_C(0x984b7fdccf5a6634), U64_C(0x3487e375fdd0ef64), - U64_C(0xddce5a93ab536994), U64_C(0x7102c63a99d9e0c4), - U64_C(0x1b72a1638a6c44d3), U64_C(0xb7be3dcab8e6cd83), - U64_C(0x5ef7842cee654b73), U64_C(0xf23b1885dcefc223), - U64_C(0x9165ebfd427e5a8e), U64_C(0x3da9775470f4d3de), - U64_C(0xd4e0ceb22677552e), U64_C(0x782c521b14fddc7e), - U64_C(0x24b86a840e90f0d2), U64_C(0x8874f62d3c1a7982), - U64_C(0x613d4fcb6a99ff72), U64_C(0xcdf1d36258137622), - U64_C(0xaeaf201ac682ee8f), U64_C(0x0263bcb3f40867df), - U64_C(0xeb2a0555a28be12f), U64_C(0x47e699fc9001687f), - U64_C(0x2d96fea583b4cc68), U64_C(0x815a620cb13e4538), - U64_C(0x6813dbeae7bdc3c8), U64_C(0xc4df4743d5374a98), - U64_C(0xa781b43b4ba6d235), U64_C(0x0b4d2892792c5b65), - U64_C(0xe20491742fafdd95), U64_C(0x4ec80ddd1d2554c5), - U64_C(0x36e45fc609d888bb), U64_C(0x9a28c36f3b5201eb), - U64_C(0x73617a896dd1871b), U64_C(0xdfade6205f5b0e4b), - U64_C(0xbcf31558c1ca96e6), U64_C(0x103f89f1f3401fb6), - U64_C(0xf9763017a5c39946), U64_C(0x55baacbe97491016), - U64_C(0x3fcacbe784fcb401), U64_C(0x9306574eb6763d51), - U64_C(0x7a4feea8e0f5bba1), U64_C(0xd6837201d27f32f1), - U64_C(0xb5dd81794ceeaa5c), U64_C(0x19111dd07e64230c), - U64_C(0xf058a43628e7a5fc), U64_C(0x5c94389f1a6d2cac), - U64_C(0x486dd4151c3dfdb9), U64_C(0xe4a148bc2eb774e9), - U64_C(0x0de8f15a7834f219), U64_C(0xa1246df34abe7b49), - U64_C(0xc27a9e8bd42fe3e4), U64_C(0x6eb60222e6a56ab4), - U64_C(0x87ffbbc4b026ec44), U64_C(0x2b33276d82ac6514), - U64_C(0x414340349119c103), U64_C(0xed8fdc9da3934853), - U64_C(0x04c6657bf510cea3), U64_C(0xa80af9d2c79a47f3), - U64_C(0xcb540aaa590bdf5e), U64_C(0x679896036b81560e), - U64_C(0x8ed12fe53d02d0fe), U64_C(0x221db34c0f8859ae), - U64_C(0x5a31e1571b7585d0), U64_C(0xf6fd7dfe29ff0c80), - U64_C(0x1fb4c4187f7c8a70), U64_C(0xb37858b14df60320), - U64_C(0xd026abc9d3679b8d), U64_C(0x7cea3760e1ed12dd), - U64_C(0x95a38e86b76e942d), U64_C(0x396f122f85e41d7d), - U64_C(0x531f75769651b96a), U64_C(0xffd3e9dfa4db303a), - U64_C(0x169a5039f258b6ca), U64_C(0xba56cc90c0d23f9a), - U64_C(0xd9083fe85e43a737), U64_C(0x75c4a3416cc92e67), - U64_C(0x9c8d1aa73a4aa897), U64_C(0x3041860e08c021c7), - U64_C(0x6cd5be9112ad0d6b), U64_C(0xc01922382027843b), - U64_C(0x29509bde76a402cb), U64_C(0x859c0777442e8b9b), - U64_C(0xe6c2f40fdabf1336), U64_C(0x4a0e68a6e8359a66), - U64_C(0xa347d140beb61c96), U64_C(0x0f8b4de98c3c95c6), - U64_C(0x65fb2ab09f8931d1), U64_C(0xc937b619ad03b881), - U64_C(0x207e0ffffb803e71), U64_C(0x8cb29356c90ab721), - U64_C(0xefec602e579b2f8c), U64_C(0x4320fc876511a6dc), - U64_C(0xaa6945613392202c), U64_C(0x06a5d9c80118a97c), - U64_C(0x7e898bd315e57502), U64_C(0xd245177a276ffc52), - U64_C(0x3b0cae9c71ec7aa2), U64_C(0x97c032354366f3f2), - U64_C(0xf49ec14dddf76b5f), U64_C(0x58525de4ef7de20f), - U64_C(0xb11be402b9fe64ff), U64_C(0x1dd778ab8b74edaf), - U64_C(0x77a71ff298c149b8), U64_C(0xdb6b835baa4bc0e8), - U64_C(0x32223abdfcc84618), U64_C(0x9eeea614ce42cf48), - U64_C(0xfdb0556c50d357e5), U64_C(0x517cc9c56259deb5), - U64_C(0xb835702334da5845), U64_C(0x14f9ec8a0650d115), - U64_C(0x90dab52a387ae76f), U64_C(0x3c1629830af06e3f), - U64_C(0xd55f90655c73e8cf), U64_C(0x79930ccc6ef9619f), - U64_C(0x1acdffb4f068f932), U64_C(0xb601631dc2e27062), - U64_C(0x5f48dafb9461f692), U64_C(0xf3844652a6eb7fc2), - U64_C(0x99f4210bb55edbd5), U64_C(0x3538bda287d45285), - U64_C(0xdc710444d157d475), U64_C(0x70bd98ede3dd5d25), - U64_C(0x13e36b957d4cc588), U64_C(0xbf2ff73c4fc64cd8), - U64_C(0x56664eda1945ca28), U64_C(0xfaaad2732bcf4378), - U64_C(0x828680683f329f06), U64_C(0x2e4a1cc10db81656), - U64_C(0xc703a5275b3b90a6), U64_C(0x6bcf398e69b119f6), - U64_C(0x0891caf6f720815b), U64_C(0xa45d565fc5aa080b), - U64_C(0x4d14efb993298efb), U64_C(0xe1d87310a1a307ab), - U64_C(0x8ba81449b216a3bc), U64_C(0x276488e0809c2aec), - U64_C(0xce2d3106d61fac1c), U64_C(0x62e1adafe495254c), - U64_C(0x01bf5ed77a04bde1), U64_C(0xad73c27e488e34b1), - U64_C(0x443a7b981e0db241), U64_C(0xe8f6e7312c873b11), - U64_C(0xb462dfae36ea17bd), U64_C(0x18ae430704609eed), - U64_C(0xf1e7fae152e3181d), U64_C(0x5d2b66486069914d), - U64_C(0x3e759530fef809e0), U64_C(0x92b90999cc7280b0), - U64_C(0x7bf0b07f9af10640), U64_C(0xd73c2cd6a87b8f10), - U64_C(0xbd4c4b8fbbce2b07), U64_C(0x1180d7268944a257), - U64_C(0xf8c96ec0dfc724a7), U64_C(0x5405f269ed4dadf7), - U64_C(0x375b011173dc355a), U64_C(0x9b979db84156bc0a), - U64_C(0x72de245e17d53afa), U64_C(0xde12b8f7255fb3aa), - U64_C(0xa63eeaec31a26fd4), U64_C(0x0af276450328e684), - U64_C(0xe3bbcfa355ab6074), U64_C(0x4f77530a6721e924), - U64_C(0x2c29a072f9b07189), U64_C(0x80e53cdbcb3af8d9), - U64_C(0x69ac853d9db97e29), U64_C(0xc5601994af33f779), - U64_C(0xaf107ecdbc86536e), U64_C(0x03dce2648e0cda3e), - U64_C(0xea955b82d88f5cce), U64_C(0x4659c72bea05d59e), - U64_C(0x2507345374944d33), U64_C(0x89cba8fa461ec463), - U64_C(0x6082111c109d4293), U64_C(0xcc4e8db52217cbc3), - U64_C(0xd8b7613f24471ad6), U64_C(0x747bfd9616cd9386), - U64_C(0x9d324470404e1576), U64_C(0x31fed8d972c49c26), - U64_C(0x52a02ba1ec55048b), U64_C(0xfe6cb708dedf8ddb), - U64_C(0x17250eee885c0b2b), U64_C(0xbbe99247bad6827b), - U64_C(0xd199f51ea963266c), U64_C(0x7d5569b79be9af3c), - U64_C(0x941cd051cd6a29cc), U64_C(0x38d04cf8ffe0a09c), - U64_C(0x5b8ebf8061713831), U64_C(0xf742232953fbb161), - U64_C(0x1e0b9acf05783791), U64_C(0xb2c7066637f2bec1), - U64_C(0xcaeb547d230f62bf), U64_C(0x6627c8d41185ebef), - U64_C(0x8f6e713247066d1f), U64_C(0x23a2ed9b758ce44f), - U64_C(0x40fc1ee3eb1d7ce2), U64_C(0xec30824ad997f5b2), - U64_C(0x05793bac8f147342), U64_C(0xa9b5a705bd9efa12), - U64_C(0xc3c5c05cae2b5e05), U64_C(0x6f095cf59ca1d755), - U64_C(0x8640e513ca2251a5), U64_C(0x2a8c79baf8a8d8f5), - U64_C(0x49d28ac266394058), U64_C(0xe51e166b54b3c908), - U64_C(0x0c57af8d02304ff8), U64_C(0xa09b332430bac6a8), - U64_C(0xfc0f0bbb2ad7ea04), U64_C(0x50c39712185d6354), - U64_C(0xb98a2ef44edee5a4), U64_C(0x1546b25d7c546cf4), - U64_C(0x76184125e2c5f459), U64_C(0xdad4dd8cd04f7d09), - U64_C(0x339d646a86ccfbf9), U64_C(0x9f51f8c3b44672a9), - U64_C(0xf5219f9aa7f3d6be), U64_C(0x59ed033395795fee), - U64_C(0xb0a4bad5c3fad91e), U64_C(0x1c68267cf170504e), - U64_C(0x7f36d5046fe1c8e3), U64_C(0xd3fa49ad5d6b41b3), - U64_C(0x3ab3f04b0be8c743), U64_C(0x967f6ce239624e13), - U64_C(0xee533ef92d9f926d), U64_C(0x429fa2501f151b3d), - U64_C(0xabd61bb649969dcd), U64_C(0x071a871f7b1c149d), - U64_C(0x64447467e58d8c30), U64_C(0xc888e8ced7070560), - U64_C(0x21c1512881848390), U64_C(0x8d0dcd81b30e0ac0), - U64_C(0xe77daad8a0bbaed7), U64_C(0x4bb1367192312787), - U64_C(0xa2f88f97c4b2a177), U64_C(0x0e34133ef6382827), - U64_C(0x6d6ae04668a9b08a), U64_C(0xc1a67cef5a2339da), - U64_C(0x28efc5090ca0bf2a), U64_C(0x842359a03e2a367a) }, + { U64_C(0x6d6ae04668a9b08a), U64_C(0x3ab3f04b0be8c743), + U64_C(0xe51e166b54b3c908), U64_C(0xbe90a9eb35c2f139), + U64_C(0xb2c7066637f2bec1), U64_C(0xaa6945613392202c), + U64_C(0x9a28c36f3b5201eb), U64_C(0xddce5a93ab536994), + U64_C(0x0e34133ef6382827), U64_C(0x52a02ba1ec55048b), + U64_C(0xa2f88f97c4b2a177), U64_C(0x8640e513ca2251a5), + U64_C(0xcdf1d36258137622), U64_C(0xfe6cb708dedf8ddb), + U64_C(0x8a174a9ec8121e5d), U64_C(0x679896036b81560e), + U64_C(0x59ed033395795fee), U64_C(0x1dd778ab8b74edaf), + U64_C(0xee533ef92d9f926d), U64_C(0x2a8c79baf8a8d8f5), + U64_C(0x6bcf398e69b119f6), U64_C(0xe20491742fafdd95), + U64_C(0x276488e0809c2aec), U64_C(0xea955b82d88f5cce), + U64_C(0x7102c63a99d9e0c4), U64_C(0xf9763017a5c39946), + U64_C(0x429fa2501f151b3d), U64_C(0x4659c72bea05d59e), + U64_C(0x984b7fdccf5a6634), U64_C(0xf742232953fbb161), + U64_C(0x3041860e08c021c7), U64_C(0x747bfd9616cd9386), + U64_C(0x4bb1367192312787), U64_C(0x1b72a1638a6c44d3), + U64_C(0x4a0e68a6e8359a66), U64_C(0x169a5039f258b6ca), + U64_C(0xb98a2ef44edee5a4), U64_C(0xd9083fe85e43a737), + U64_C(0x967f6ce239624e13), U64_C(0x8874f62d3c1a7982), + U64_C(0x3c1629830af06e3f), U64_C(0x9165ebfd427e5a8e), + U64_C(0xb5dd81794ceeaa5c), U64_C(0x0de8f15a7834f219), + U64_C(0x70bd98ede3dd5d25), U64_C(0xaccc9ca9328a8950), + U64_C(0x56664eda1945ca28), U64_C(0x221db34c0f8859ae), + U64_C(0x26dbd637fa98970d), U64_C(0x1acdffb4f068f932), + U64_C(0x4585254f64090fa0), U64_C(0x72de245e17d53afa), + U64_C(0x1546b25d7c546cf4), U64_C(0x207e0ffffb803e71), + U64_C(0xfaaad2732bcf4378), U64_C(0xb462dfae36ea17bd), + U64_C(0xcf926fd1ac1b11fd), U64_C(0xe0672dc7dba7ba4a), + U64_C(0xd3fa49ad5d6b41b3), U64_C(0x8ba81449b216a3bc), + U64_C(0x14f9ec8a0650d115), U64_C(0x40fc1ee3eb1d7ce2), + U64_C(0x23a2ed9b758ce44f), U64_C(0x782c521b14fddc7e), + U64_C(0x1c68267cf170504e), U64_C(0xbcf31558c1ca96e6), + U64_C(0xa781b43b4ba6d235), U64_C(0xf6fd7dfe29ff0c80), + U64_C(0xb0a4bad5c3fad91e), U64_C(0xd199f51ea963266c), + U64_C(0x414340349119c103), U64_C(0x5405f269ed4dadf7), + U64_C(0xabd61bb649969dcd), U64_C(0x6813dbeae7bdc3c8), + U64_C(0x65fb2ab09f8931d1), U64_C(0xf1e7fae152e3181d), + U64_C(0xc1a67cef5a2339da), U64_C(0x7a4feea8e0f5bba1), + U64_C(0x1e0b9acf05783791), U64_C(0x5b8ebf8061713831), + U64_C(0x80e53cdbcb3af8d9), U64_C(0x7e898bd315e57502), + U64_C(0xc6bcfbf0213f2d47), U64_C(0x95a38e86b76e942d), + U64_C(0x092e94218d243cba), U64_C(0x8339debf453622e7), + U64_C(0xb11be402b9fe64ff), U64_C(0x57d9100d634177c9), + U64_C(0xcc4e8db52217cbc3), U64_C(0x3b0cae9c71ec7aa2), + U64_C(0xfb158ca451cbfe99), U64_C(0x2b33276d82ac6514), + U64_C(0x01bf5ed77a04bde1), U64_C(0xc5601994af33f779), + U64_C(0x75c4a3416cc92e67), U64_C(0xf3844652a6eb7fc2), + U64_C(0x3487e375fdd0ef64), U64_C(0x18ae430704609eed), + U64_C(0x4d14efb993298efb), U64_C(0x815a620cb13e4538), + U64_C(0x125c354207487869), U64_C(0x9eeea614ce42cf48), + U64_C(0xce2d3106d61fac1c), U64_C(0xbbe99247bad6827b), + U64_C(0x071a871f7b1c149d), U64_C(0x2e4a1cc10db81656), + U64_C(0x77a71ff298c149b8), U64_C(0x06a5d9c80118a97c), + U64_C(0xad73c27e488e34b1), U64_C(0x443a7b981e0db241), + U64_C(0xe3bbcfa355ab6074), U64_C(0x0af276450328e684), + U64_C(0x73617a896dd1871b), U64_C(0x58525de4ef7de20f), + U64_C(0xb7be3dcab8e6cd83), U64_C(0x19111dd07e64230c), + U64_C(0x842359a03e2a367a), U64_C(0x103f89f1f3401fb6), + U64_C(0xdc710444d157d475), U64_C(0xb835702334da5845), + U64_C(0x4320fc876511a6dc), U64_C(0xd026abc9d3679b8d), + U64_C(0x17250eee885c0b2b), U64_C(0x90dab52a387ae76f), + U64_C(0x31fed8d972c49c26), U64_C(0x89cba8fa461ec463), + U64_C(0x2ff5421677bcabb7), U64_C(0x396f122f85e41d7d), + U64_C(0xa09b332430bac6a8), U64_C(0xc888e8ced7070560), + U64_C(0xaeaf201ac682ee8f), U64_C(0x1180d7268944a257), + U64_C(0xf058a43628e7a5fc), U64_C(0xbd4c4b8fbbce2b07), + U64_C(0xa1246df34abe7b49), U64_C(0x7d5569b79be9af3c), + U64_C(0xa9b5a705bd9efa12), U64_C(0xdb6b835baa4bc0e8), + U64_C(0x05793bac8f147342), U64_C(0x21c1512881848390), + U64_C(0xfdb0556c50d357e5), U64_C(0x613d4fcb6a99ff72), + U64_C(0x03dce2648e0cda3e), U64_C(0xe949b9e6568386f0), + U64_C(0xfc0f0bbb2ad7ea04), U64_C(0x6a70675913b5a417), + U64_C(0x7f36d5046fe1c8e3), U64_C(0x0c57af8d02304ff8), + U64_C(0x32223abdfcc84618), U64_C(0x0891caf6f720815b), + U64_C(0xa63eeaec31a26fd4), U64_C(0x2507345374944d33), + U64_C(0x49d28ac266394058), U64_C(0xf5219f9aa7f3d6be), + U64_C(0x2d96fea583b4cc68), U64_C(0x5a31e1571b7585d0), + U64_C(0x8ed12fe53d02d0fe), U64_C(0xdfade6205f5b0e4b), + U64_C(0x4cabb16ee92d331a), U64_C(0x04c6657bf510cea3), + U64_C(0xd73c2cd6a87b8f10), U64_C(0xe1d87310a1a307ab), + U64_C(0x6cd5be9112ad0d6b), U64_C(0x97c032354366f3f2), + U64_C(0xd4e0ceb22677552e), U64_C(0x0000000000000000), + U64_C(0x29509bde76a402cb), U64_C(0xc27a9e8bd42fe3e4), + U64_C(0x5ef7842cee654b73), U64_C(0xaf107ecdbc86536e), + U64_C(0x3fcacbe784fcb401), U64_C(0xd55f90655c73e8cf), + U64_C(0xe6c2f40fdabf1336), U64_C(0xe8f6e7312c873b11), + U64_C(0xeb2a0555a28be12f), U64_C(0xe4a148bc2eb774e9), + U64_C(0x9b979db84156bc0a), U64_C(0x6eb60222e6a56ab4), + U64_C(0x87ffbbc4b026ec44), U64_C(0xc703a5275b3b90a6), + U64_C(0x47e699fc9001687f), U64_C(0x9c8d1aa73a4aa897), + U64_C(0x7cea3760e1ed12dd), U64_C(0x4ec80ddd1d2554c5), + U64_C(0x13e36b957d4cc588), U64_C(0x5d2b66486069914d), + U64_C(0x92b90999cc7280b0), U64_C(0x517cc9c56259deb5), + U64_C(0xc937b619ad03b881), U64_C(0xec30824ad997f5b2), + U64_C(0xa45d565fc5aa080b), U64_C(0xd6837201d27f32f1), + U64_C(0x635ef3789e9198ad), U64_C(0x531f75769651b96a), + U64_C(0x4f77530a6721e924), U64_C(0x486dd4151c3dfdb9), + U64_C(0x5f48dafb9461f692), U64_C(0x375b011173dc355a), + U64_C(0x3da9775470f4d3de), U64_C(0x8d0dcd81b30e0ac0), + U64_C(0x36e45fc609d888bb), U64_C(0x55baacbe97491016), + U64_C(0x8cb29356c90ab721), U64_C(0x76184125e2c5f459), + U64_C(0x99f4210bb55edbd5), U64_C(0x6f095cf59ca1d755), + U64_C(0x9f51f8c3b44672a9), U64_C(0x3538bda287d45285), + U64_C(0x50c39712185d6354), U64_C(0xf23b1885dcefc223), + U64_C(0x79930ccc6ef9619f), U64_C(0xed8fdc9da3934853), + U64_C(0xcb540aaa590bdf5e), U64_C(0x5c94389f1a6d2cac), + U64_C(0xe77daad8a0bbaed7), U64_C(0x28efc5090ca0bf2a), + U64_C(0xbf2ff73c4fc64cd8), U64_C(0xb37858b14df60320), + U64_C(0xf8c96ec0dfc724a7), U64_C(0x828680683f329f06), + U64_C(0x941cd051cd6a29cc), U64_C(0xc3c5c05cae2b5e05), + U64_C(0xb601631dc2e27062), U64_C(0xc01922382027843b), + U64_C(0x24b86a840e90f0d2), U64_C(0xd245177a276ffc52), + U64_C(0x0f8b4de98c3c95c6), U64_C(0x3e759530fef809e0), + U64_C(0x0b4d2892792c5b65), U64_C(0xc4df4743d5374a98), + U64_C(0xa5e20888bfaeb5ea), U64_C(0xba56cc90c0d23f9a), + U64_C(0x38d04cf8ffe0a09c), U64_C(0x62e1adafe495254c), + U64_C(0x0263bcb3f40867df), U64_C(0xcaeb547d230f62bf), + U64_C(0x6082111c109d4293), U64_C(0xdad4dd8cd04f7d09), + U64_C(0xefec602e579b2f8c), U64_C(0x1fb4c4187f7c8a70), + U64_C(0xffd3e9dfa4db303a), U64_C(0x7bf0b07f9af10640), + U64_C(0xf49ec14dddf76b5f), U64_C(0x8f6e713247066d1f), + U64_C(0x339d646a86ccfbf9), U64_C(0x64447467e58d8c30), + U64_C(0x2c29a072f9b07189), U64_C(0xd8b7613f24471ad6), + U64_C(0x6627c8d41185ebef), U64_C(0xa347d140beb61c96), + U64_C(0xde12b8f7255fb3aa), U64_C(0x9d324470404e1576), + U64_C(0x9306574eb6763d51), U64_C(0xa80af9d2c79a47f3), + U64_C(0x859c0777442e8b9b), U64_C(0x69ac853d9db97e29) }, /* 6 */ - { U64_C(0x0000000000000000), U64_C(0x46b60f011a83988e), - U64_C(0x8c711e02341b2d01), U64_C(0xcac711032e98b58f), - U64_C(0x05e23c0468365a02), U64_C(0x4354330572b5c28c), - U64_C(0x899322065c2d7703), U64_C(0xcf252d0746aeef8d), - U64_C(0x0ad97808d06cb404), U64_C(0x4c6f7709caef2c8a), - U64_C(0x86a8660ae4779905), U64_C(0xc01e690bfef4018b), - U64_C(0x0f3b440cb85aee06), U64_C(0x498d4b0da2d97688), - U64_C(0x834a5a0e8c41c307), U64_C(0xc5fc550f96c25b89), - U64_C(0x14aff010bdd87508), U64_C(0x5219ff11a75bed86), - U64_C(0x98deee1289c35809), U64_C(0xde68e1139340c087), - U64_C(0x114dcc14d5ee2f0a), U64_C(0x57fbc315cf6db784), - U64_C(0x9d3cd216e1f5020b), U64_C(0xdb8add17fb769a85), - U64_C(0x1e7688186db4c10c), U64_C(0x58c0871977375982), - U64_C(0x9207961a59afec0d), U64_C(0xd4b1991b432c7483), - U64_C(0x1b94b41c05829b0e), U64_C(0x5d22bb1d1f010380), - U64_C(0x97e5aa1e3199b60f), U64_C(0xd153a51f2b1a2e81), - U64_C(0x2843fd2067adea10), U64_C(0x6ef5f2217d2e729e), - U64_C(0xa432e32253b6c711), U64_C(0xe284ec2349355f9f), - U64_C(0x2da1c1240f9bb012), U64_C(0x6b17ce251518289c), - U64_C(0xa1d0df263b809d13), U64_C(0xe766d0272103059d), - U64_C(0x229a8528b7c15e14), U64_C(0x642c8a29ad42c69a), - U64_C(0xaeeb9b2a83da7315), U64_C(0xe85d942b9959eb9b), - U64_C(0x2778b92cdff70416), U64_C(0x61ceb62dc5749c98), - U64_C(0xab09a72eebec2917), U64_C(0xedbfa82ff16fb199), - U64_C(0x3cec0d30da759f18), U64_C(0x7a5a0231c0f60796), - U64_C(0xb09d1332ee6eb219), U64_C(0xf62b1c33f4ed2a97), - U64_C(0x390e3134b243c51a), U64_C(0x7fb83e35a8c05d94), - U64_C(0xb57f2f368658e81b), U64_C(0xf3c920379cdb7095), - U64_C(0x363575380a192b1c), U64_C(0x70837a39109ab392), - U64_C(0xba446b3a3e02061d), U64_C(0xfcf2643b24819e93), - U64_C(0x33d7493c622f711e), U64_C(0x7561463d78ace990), - U64_C(0xbfa6573e56345c1f), U64_C(0xf910583f4cb7c491), - U64_C(0x5086e740ce47c920), U64_C(0x1630e841d4c451ae), - U64_C(0xdcf7f942fa5ce421), U64_C(0x9a41f643e0df7caf), - U64_C(0x5564db44a6719322), U64_C(0x13d2d445bcf20bac), - U64_C(0xd915c546926abe23), U64_C(0x9fa3ca4788e926ad), - U64_C(0x5a5f9f481e2b7d24), U64_C(0x1ce9904904a8e5aa), - U64_C(0xd62e814a2a305025), U64_C(0x90988e4b30b3c8ab), - U64_C(0x5fbda34c761d2726), U64_C(0x190bac4d6c9ebfa8), - U64_C(0xd3ccbd4e42060a27), U64_C(0x957ab24f588592a9), - U64_C(0x44291750739fbc28), U64_C(0x029f1851691c24a6), - U64_C(0xc858095247849129), U64_C(0x8eee06535d0709a7), - U64_C(0x41cb2b541ba9e62a), U64_C(0x077d2455012a7ea4), - U64_C(0xcdba35562fb2cb2b), U64_C(0x8b0c3a57353153a5), - U64_C(0x4ef06f58a3f3082c), U64_C(0x08466059b97090a2), - U64_C(0xc281715a97e8252d), U64_C(0x84377e5b8d6bbda3), - U64_C(0x4b12535ccbc5522e), U64_C(0x0da45c5dd146caa0), - U64_C(0xc7634d5effde7f2f), U64_C(0x81d5425fe55de7a1), - U64_C(0x78c51a60a9ea2330), U64_C(0x3e731561b369bbbe), - U64_C(0xf4b404629df10e31), U64_C(0xb2020b63877296bf), - U64_C(0x7d272664c1dc7932), U64_C(0x3b912965db5fe1bc), - U64_C(0xf1563866f5c75433), U64_C(0xb7e03767ef44ccbd), - U64_C(0x721c626879869734), U64_C(0x34aa6d6963050fba), - U64_C(0xfe6d7c6a4d9dba35), U64_C(0xb8db736b571e22bb), - U64_C(0x77fe5e6c11b0cd36), U64_C(0x3148516d0b3355b8), - U64_C(0xfb8f406e25abe037), U64_C(0xbd394f6f3f2878b9), - U64_C(0x6c6aea7014325638), U64_C(0x2adce5710eb1ceb6), - U64_C(0xe01bf47220297b39), U64_C(0xa6adfb733aaae3b7), - U64_C(0x6988d6747c040c3a), U64_C(0x2f3ed975668794b4), - U64_C(0xe5f9c876481f213b), U64_C(0xa34fc777529cb9b5), - U64_C(0x66b39278c45ee23c), U64_C(0x20059d79dedd7ab2), - U64_C(0xeac28c7af045cf3d), U64_C(0xac74837beac657b3), - U64_C(0x6351ae7cac68b83e), U64_C(0x25e7a17db6eb20b0), - U64_C(0xef20b07e9873953f), U64_C(0xa996bf7f82f00db1), - U64_C(0xa011d380818e8f40), U64_C(0xe6a7dc819b0d17ce), - U64_C(0x2c60cd82b595a241), U64_C(0x6ad6c283af163acf), - U64_C(0xa5f3ef84e9b8d542), U64_C(0xe345e085f33b4dcc), - U64_C(0x2982f186dda3f843), U64_C(0x6f34fe87c72060cd), - U64_C(0xaac8ab8851e23b44), U64_C(0xec7ea4894b61a3ca), - U64_C(0x26b9b58a65f91645), U64_C(0x600fba8b7f7a8ecb), - U64_C(0xaf2a978c39d46146), U64_C(0xe99c988d2357f9c8), - U64_C(0x235b898e0dcf4c47), U64_C(0x65ed868f174cd4c9), - U64_C(0xb4be23903c56fa48), U64_C(0xf2082c9126d562c6), - U64_C(0x38cf3d92084dd749), U64_C(0x7e79329312ce4fc7), - U64_C(0xb15c1f945460a04a), U64_C(0xf7ea10954ee338c4), - U64_C(0x3d2d0196607b8d4b), U64_C(0x7b9b0e977af815c5), - U64_C(0xbe675b98ec3a4e4c), U64_C(0xf8d15499f6b9d6c2), - U64_C(0x3216459ad821634d), U64_C(0x74a04a9bc2a2fbc3), - U64_C(0xbb85679c840c144e), U64_C(0xfd33689d9e8f8cc0), - U64_C(0x37f4799eb017394f), U64_C(0x7142769faa94a1c1), - U64_C(0x88522ea0e6236550), U64_C(0xcee421a1fca0fdde), - U64_C(0x042330a2d2384851), U64_C(0x42953fa3c8bbd0df), - U64_C(0x8db012a48e153f52), U64_C(0xcb061da59496a7dc), - U64_C(0x01c10ca6ba0e1253), U64_C(0x477703a7a08d8add), - U64_C(0x828b56a8364fd154), U64_C(0xc43d59a92ccc49da), - U64_C(0x0efa48aa0254fc55), U64_C(0x484c47ab18d764db), - U64_C(0x87696aac5e798b56), U64_C(0xc1df65ad44fa13d8), - U64_C(0x0b1874ae6a62a657), U64_C(0x4dae7baf70e13ed9), - U64_C(0x9cfddeb05bfb1058), U64_C(0xda4bd1b1417888d6), - U64_C(0x108cc0b26fe03d59), U64_C(0x563acfb37563a5d7), - U64_C(0x991fe2b433cd4a5a), U64_C(0xdfa9edb5294ed2d4), - U64_C(0x156efcb607d6675b), U64_C(0x53d8f3b71d55ffd5), - U64_C(0x9624a6b88b97a45c), U64_C(0xd092a9b991143cd2), - U64_C(0x1a55b8babf8c895d), U64_C(0x5ce3b7bba50f11d3), - U64_C(0x93c69abce3a1fe5e), U64_C(0xd57095bdf92266d0), - U64_C(0x1fb784bed7bad35f), U64_C(0x59018bbfcd394bd1), - U64_C(0xf09734c04fc94660), U64_C(0xb6213bc1554adeee), - U64_C(0x7ce62ac27bd26b61), U64_C(0x3a5025c36151f3ef), - U64_C(0xf57508c427ff1c62), U64_C(0xb3c307c53d7c84ec), - U64_C(0x790416c613e43163), U64_C(0x3fb219c70967a9ed), - U64_C(0xfa4e4cc89fa5f264), U64_C(0xbcf843c985266aea), - U64_C(0x763f52caabbedf65), U64_C(0x30895dcbb13d47eb), - U64_C(0xffac70ccf793a866), U64_C(0xb91a7fcded1030e8), - U64_C(0x73dd6ecec3888567), U64_C(0x356b61cfd90b1de9), - U64_C(0xe438c4d0f2113368), U64_C(0xa28ecbd1e892abe6), - U64_C(0x6849dad2c60a1e69), U64_C(0x2effd5d3dc8986e7), - U64_C(0xe1daf8d49a27696a), U64_C(0xa76cf7d580a4f1e4), - U64_C(0x6dabe6d6ae3c446b), U64_C(0x2b1de9d7b4bfdce5), - U64_C(0xeee1bcd8227d876c), U64_C(0xa857b3d938fe1fe2), - U64_C(0x6290a2da1666aa6d), U64_C(0x2426addb0ce532e3), - U64_C(0xeb0380dc4a4bdd6e), U64_C(0xadb58fdd50c845e0), - U64_C(0x67729ede7e50f06f), U64_C(0x21c491df64d368e1), - U64_C(0xd8d4c9e02864ac70), U64_C(0x9e62c6e132e734fe), - U64_C(0x54a5d7e21c7f8171), U64_C(0x1213d8e306fc19ff), - U64_C(0xdd36f5e44052f672), U64_C(0x9b80fae55ad16efc), - U64_C(0x5147ebe67449db73), U64_C(0x17f1e4e76eca43fd), - U64_C(0xd20db1e8f8081874), U64_C(0x94bbbee9e28b80fa), - U64_C(0x5e7cafeacc133575), U64_C(0x18caa0ebd690adfb), - U64_C(0xd7ef8dec903e4276), U64_C(0x915982ed8abddaf8), - U64_C(0x5b9e93eea4256f77), U64_C(0x1d289cefbea6f7f9), - U64_C(0xcc7b39f095bcd978), U64_C(0x8acd36f18f3f41f6), - U64_C(0x400a27f2a1a7f479), U64_C(0x06bc28f3bb246cf7), - U64_C(0xc99905f4fd8a837a), U64_C(0x8f2f0af5e7091bf4), - U64_C(0x45e81bf6c991ae7b), U64_C(0x035e14f7d31236f5), - U64_C(0xc6a241f845d06d7c), U64_C(0x80144ef95f53f5f2), - U64_C(0x4ad35ffa71cb407d), U64_C(0x0c6550fb6b48d8f3), - U64_C(0xc3407dfc2de6377e), U64_C(0x85f672fd3765aff0), - U64_C(0x4f3163fe19fd1a7f), U64_C(0x09876cff037e82f1) }, + { U64_C(0xc3407dfc2de6377e), U64_C(0x5b9e93eea4256f77), + U64_C(0xadb58fdd50c845e0), U64_C(0x5219ff11a75bed86), + U64_C(0x356b61cfd90b1de9), U64_C(0xfb8f406e25abe037), + U64_C(0x7a5a0231c0f60796), U64_C(0x9d3cd216e1f5020b), + U64_C(0x0c6550fb6b48d8f3), U64_C(0xf57508c427ff1c62), + U64_C(0x4ad35ffa71cb407d), U64_C(0x6290a2da1666aa6d), + U64_C(0xe284ec2349355f9f), U64_C(0xb3c307c53d7c84ec), + U64_C(0x05e23c0468365a02), U64_C(0x190bac4d6c9ebfa8), + U64_C(0x94bbbee9e28b80fa), U64_C(0xa34fc777529cb9b5), + U64_C(0xcc7b39f095bcd978), U64_C(0x2426addb0ce532e3), + U64_C(0x7e79329312ce4fc7), U64_C(0xab09a72eebec2917), + U64_C(0xf8d15499f6b9d6c2), U64_C(0x1a55b8babf8c895d), + U64_C(0xdb8add17fb769a85), U64_C(0xb57f2f368658e81b), + U64_C(0x8acd36f18f3f41f6), U64_C(0x5ce3b7bba50f11d3), + U64_C(0x114dcc14d5ee2f0a), U64_C(0xb91a7fcded1030e8), + U64_C(0x81d5425fe55de7a1), U64_C(0xb6213bc1554adeee), + U64_C(0x80144ef95f53f5f2), U64_C(0x1e7688186db4c10c), + U64_C(0x3b912965db5fe1bc), U64_C(0xc281715a97e8252d), + U64_C(0x54a5d7e21c7f8171), U64_C(0x4b12535ccbc5522e), + U64_C(0x1d289cefbea6f7f9), U64_C(0x6ef5f2217d2e729e), + U64_C(0xe6a7dc819b0d17ce), U64_C(0x1b94b41c05829b0e), + U64_C(0x33d7493c622f711e), U64_C(0xdcf7f942fa5ce421), + U64_C(0x600fba8b7f7a8ecb), U64_C(0x46b60f011a83988e), + U64_C(0x235b898e0dcf4c47), U64_C(0x957ab24f588592a9), + U64_C(0x4354330572b5c28c), U64_C(0xa5f3ef84e9b8d542), + U64_C(0x8c711e02341b2d01), U64_C(0x0b1874ae6a62a657), + U64_C(0x1213d8e306fc19ff), U64_C(0xfe6d7c6a4d9dba35), + U64_C(0x65ed868f174cd4c9), U64_C(0x88522ea0e6236550), + U64_C(0x899322065c2d7703), U64_C(0xc01e690bfef4018b), + U64_C(0x915982ed8abddaf8), U64_C(0xbe675b98ec3a4e4c), + U64_C(0xa996bf7f82f00db1), U64_C(0xe1daf8d49a27696a), + U64_C(0x2effd5d3dc8986e7), U64_C(0xd153a51f2b1a2e81), + U64_C(0x18caa0ebd690adfb), U64_C(0x390e3134b243c51a), + U64_C(0x2778b92cdff70416), U64_C(0x029f1851691c24a6), + U64_C(0x5e7cafeacc133575), U64_C(0xfa4e4cc89fa5f264), + U64_C(0x5a5f9f481e2b7d24), U64_C(0x484c47ab18d764db), + U64_C(0x400a27f2a1a7f479), U64_C(0xaeeb9b2a83da7315), + U64_C(0x721c626879869734), U64_C(0x042330a2d2384851), + U64_C(0x85f672fd3765aff0), U64_C(0xba446b3a3e02061d), + U64_C(0x73dd6ecec3888567), U64_C(0xffac70ccf793a866), + U64_C(0xdfa9edb5294ed2d4), U64_C(0x6c6aea7014325638), + U64_C(0x834a5a0e8c41c307), U64_C(0xcdba35562fb2cb2b), + U64_C(0x0ad97808d06cb404), U64_C(0x0f3b440cb85aee06), + U64_C(0xe5f9c876481f213b), U64_C(0x98deee1289c35809), + U64_C(0x59018bbfcd394bd1), U64_C(0xe01bf47220297b39), + U64_C(0xde68e1139340c087), U64_C(0x9fa3ca4788e926ad), + U64_C(0xbb85679c840c144e), U64_C(0x53d8f3b71d55ffd5), + U64_C(0x0da45c5dd146caa0), U64_C(0x6f34fe87c72060cd), + U64_C(0x57fbc315cf6db784), U64_C(0xcee421a1fca0fdde), + U64_C(0x3d2d0196607b8d4b), U64_C(0x642c8a29ad42c69a), + U64_C(0x14aff010bdd87508), U64_C(0xac74837beac657b3), + U64_C(0x3216459ad821634d), U64_C(0x3fb219c70967a9ed), + U64_C(0x06bc28f3bb246cf7), U64_C(0xf2082c9126d562c6), + U64_C(0x66b39278c45ee23c), U64_C(0xbd394f6f3f2878b9), + U64_C(0xfd33689d9e8f8cc0), U64_C(0x37f4799eb017394f), + U64_C(0x108cc0b26fe03d59), U64_C(0xda4bd1b1417888d6), + U64_C(0xb09d1332ee6eb219), U64_C(0x2f3ed975668794b4), + U64_C(0x58c0871977375982), U64_C(0x7561463d78ace990), + U64_C(0x09876cff037e82f1), U64_C(0x7fb83e35a8c05d94), + U64_C(0x26b9b58a65f91645), U64_C(0xef20b07e9873953f), + U64_C(0x3148516d0b3355b8), U64_C(0x41cb2b541ba9e62a), + U64_C(0x790416c613e43163), U64_C(0xa011d380818e8f40), + U64_C(0x3a5025c36151f3ef), U64_C(0xd57095bdf92266d0), + U64_C(0x498d4b0da2d97688), U64_C(0x8b0c3a57353153a5), + U64_C(0x21c491df64d368e1), U64_C(0x8f2f0af5e7091bf4), + U64_C(0x2da1c1240f9bb012), U64_C(0xc43d59a92ccc49da), + U64_C(0xbfa6573e56345c1f), U64_C(0x828b56a8364fd154), + U64_C(0x9a41f643e0df7caf), U64_C(0xbcf843c985266aea), + U64_C(0x2b1de9d7b4bfdce5), U64_C(0x20059d79dedd7ab2), + U64_C(0x6dabe6d6ae3c446b), U64_C(0x45e81bf6c991ae7b), + U64_C(0x6351ae7cac68b83e), U64_C(0xa432e32253b6c711), + U64_C(0xd092a9b991143cd2), U64_C(0xcac711032e98b58f), + U64_C(0xd8d4c9e02864ac70), U64_C(0xc5fc550f96c25b89), + U64_C(0xd7ef8dec903e4276), U64_C(0x67729ede7e50f06f), + U64_C(0xeac28c7af045cf3d), U64_C(0xb15c1f945460a04a), + U64_C(0x9cfddeb05bfb1058), U64_C(0x93c69abce3a1fe5e), + U64_C(0xeb0380dc4a4bdd6e), U64_C(0xd20db1e8f8081874), + U64_C(0x229a8528b7c15e14), U64_C(0x44291750739fbc28), + U64_C(0xd3ccbd4e42060a27), U64_C(0xf62b1c33f4ed2a97), + U64_C(0x86a8660ae4779905), U64_C(0xd62e814a2a305025), + U64_C(0x477703a7a08d8add), U64_C(0x7b9b0e977af815c5), + U64_C(0x78c51a60a9ea2330), U64_C(0xa6adfb733aaae3b7), + U64_C(0x97e5aa1e3199b60f), U64_C(0x0000000000000000), + U64_C(0xf4b404629df10e31), U64_C(0x5564db44a6719322), + U64_C(0x9207961a59afec0d), U64_C(0x9624a6b88b97a45c), + U64_C(0x363575380a192b1c), U64_C(0x2c60cd82b595a241), + U64_C(0x7d272664c1dc7932), U64_C(0x7142769faa94a1c1), + U64_C(0xa1d0df263b809d13), U64_C(0x1630e841d4c451ae), + U64_C(0xc1df65ad44fa13d8), U64_C(0x13d2d445bcf20bac), + U64_C(0xd915c546926abe23), U64_C(0x38cf3d92084dd749), + U64_C(0xe766d0272103059d), U64_C(0xc7634d5effde7f2f), + U64_C(0x077d2455012a7ea4), U64_C(0xedbfa82ff16fb199), + U64_C(0xaf2a978c39d46146), U64_C(0x42953fa3c8bbd0df), + U64_C(0xcb061da59496a7dc), U64_C(0x25e7a17db6eb20b0), + U64_C(0x34aa6d6963050fba), U64_C(0xa76cf7d580a4f1e4), + U64_C(0xf7ea10954ee338c4), U64_C(0xfcf2643b24819e93), + U64_C(0xcf252d0746aeef8d), U64_C(0x4ef06f58a3f3082c), + U64_C(0x563acfb37563a5d7), U64_C(0x5086e740ce47c920), + U64_C(0x2982f186dda3f843), U64_C(0x87696aac5e798b56), + U64_C(0x5d22bb1d1f010380), U64_C(0x035e14f7d31236f5), + U64_C(0x3cec0d30da759f18), U64_C(0xf3c920379cdb7095), + U64_C(0xb8db736b571e22bb), U64_C(0xdd36f5e44052f672), + U64_C(0xaac8ab8851e23b44), U64_C(0xa857b3d938fe1fe2), + U64_C(0x17f1e4e76eca43fd), U64_C(0xec7ea4894b61a3ca), + U64_C(0x9e62c6e132e734fe), U64_C(0xd4b1991b432c7483), + U64_C(0x6ad6c283af163acf), U64_C(0x1ce9904904a8e5aa), + U64_C(0x5fbda34c761d2726), U64_C(0xf910583f4cb7c491), + U64_C(0xc6a241f845d06d7c), U64_C(0x4f3163fe19fd1a7f), + U64_C(0xe99c988d2357f9c8), U64_C(0x8eee06535d0709a7), + U64_C(0x0efa48aa0254fc55), U64_C(0xb4be23903c56fa48), + U64_C(0x763f52caabbedf65), U64_C(0xeee1bcd8227d876c), + U64_C(0xe345e085f33b4dcc), U64_C(0x3e731561b369bbbe), + U64_C(0x2843fd2067adea10), U64_C(0x2adce5710eb1ceb6), + U64_C(0xb7e03767ef44ccbd), U64_C(0x8db012a48e153f52), + U64_C(0x61ceb62dc5749c98), U64_C(0xe85d942b9959eb9b), + U64_C(0x4c6f7709caef2c8a), U64_C(0x84377e5b8d6bbda3), + U64_C(0x30895dcbb13d47eb), U64_C(0x74a04a9bc2a2fbc3), + U64_C(0x6b17ce251518289c), U64_C(0xe438c4d0f2113368), + U64_C(0x1fb784bed7bad35f), U64_C(0x9b80fae55ad16efc), + U64_C(0x77fe5e6c11b0cd36), U64_C(0xc858095247849129), + U64_C(0x08466059b97090a2), U64_C(0x01c10ca6ba0e1253), + U64_C(0x6988d6747c040c3a), U64_C(0x6849dad2c60a1e69), + U64_C(0x5147ebe67449db73), U64_C(0xc99905f4fd8a837a), + U64_C(0x991fe2b433cd4a5a), U64_C(0xf09734c04fc94660), + U64_C(0xa28ecbd1e892abe6), U64_C(0xf1563866f5c75433), + U64_C(0x4dae7baf70e13ed9), U64_C(0x7ce62ac27bd26b61), + U64_C(0x70837a39109ab392), U64_C(0x90988e4b30b3c8ab), + U64_C(0xb2020b63877296bf), U64_C(0x156efcb607d6675b) }, /* 7 */ - { U64_C(0x0000000000000000), U64_C(0x83478b07b2468764), - U64_C(0x1b8e0b0e798c13c8), U64_C(0x98c98009cbca94ac), - U64_C(0x3601161cf205268d), U64_C(0xb5469d1b4043a1e9), - U64_C(0x2d8f1d128b893545), U64_C(0xaec8961539cfb221), - U64_C(0x6c022c38f90a4c07), U64_C(0xef45a73f4b4ccb63), - U64_C(0x778c273680865fcf), U64_C(0xf4cbac3132c0d8ab), - U64_C(0x5a033a240b0f6a8a), U64_C(0xd944b123b949edee), - U64_C(0x418d312a72837942), U64_C(0xc2caba2dc0c5fe26), - U64_C(0xd8045870ef14980e), U64_C(0x5b43d3775d521f6a), - U64_C(0xc38a537e96988bc6), U64_C(0x40cdd87924de0ca2), - U64_C(0xee054e6c1d11be83), U64_C(0x6d42c56baf5739e7), - U64_C(0xf58b4562649dad4b), U64_C(0x76ccce65d6db2a2f), - U64_C(0xb4067448161ed409), U64_C(0x3741ff4fa458536d), - U64_C(0xaf887f466f92c7c1), U64_C(0x2ccff441ddd440a5), - U64_C(0x82076254e41bf284), U64_C(0x0140e953565d75e0), - U64_C(0x9989695a9d97e14c), U64_C(0x1acee25d2fd16628), - U64_C(0xad08b0e0c3282d1c), U64_C(0x2e4f3be7716eaa78), - U64_C(0xb686bbeebaa43ed4), U64_C(0x35c130e908e2b9b0), - U64_C(0x9b09a6fc312d0b91), U64_C(0x184e2dfb836b8cf5), - U64_C(0x8087adf248a11859), U64_C(0x03c026f5fae79f3d), - U64_C(0xc10a9cd83a22611b), U64_C(0x424d17df8864e67f), - U64_C(0xda8497d643ae72d3), U64_C(0x59c31cd1f1e8f5b7), - U64_C(0xf70b8ac4c8274796), U64_C(0x744c01c37a61c0f2), - U64_C(0xec8581cab1ab545e), U64_C(0x6fc20acd03edd33a), - U64_C(0x750ce8902c3cb512), U64_C(0xf64b63979e7a3276), - U64_C(0x6e82e39e55b0a6da), U64_C(0xedc56899e7f621be), - U64_C(0x430dfe8cde39939f), U64_C(0xc04a758b6c7f14fb), - U64_C(0x5883f582a7b58057), U64_C(0xdbc47e8515f30733), - U64_C(0x190ec4a8d536f915), U64_C(0x9a494faf67707e71), - U64_C(0x0280cfa6acbaeadd), U64_C(0x81c744a11efc6db9), - U64_C(0x2f0fd2b42733df98), U64_C(0xac4859b3957558fc), - U64_C(0x3481d9ba5ebfcc50), U64_C(0xb7c652bdecf94b34), - U64_C(0x47107ddd9b505a38), U64_C(0xc457f6da2916dd5c), - U64_C(0x5c9e76d3e2dc49f0), U64_C(0xdfd9fdd4509ace94), - U64_C(0x71116bc169557cb5), U64_C(0xf256e0c6db13fbd1), - U64_C(0x6a9f60cf10d96f7d), U64_C(0xe9d8ebc8a29fe819), - U64_C(0x2b1251e5625a163f), U64_C(0xa855dae2d01c915b), - U64_C(0x309c5aeb1bd605f7), U64_C(0xb3dbd1eca9908293), - U64_C(0x1d1347f9905f30b2), U64_C(0x9e54ccfe2219b7d6), - U64_C(0x069d4cf7e9d3237a), U64_C(0x85dac7f05b95a41e), - U64_C(0x9f1425ad7444c236), U64_C(0x1c53aeaac6024552), - U64_C(0x849a2ea30dc8d1fe), U64_C(0x07dda5a4bf8e569a), - U64_C(0xa91533b18641e4bb), U64_C(0x2a52b8b6340763df), - U64_C(0xb29b38bfffcdf773), U64_C(0x31dcb3b84d8b7017), - U64_C(0xf31609958d4e8e31), U64_C(0x705182923f080955), - U64_C(0xe898029bf4c29df9), U64_C(0x6bdf899c46841a9d), - U64_C(0xc5171f897f4ba8bc), U64_C(0x4650948ecd0d2fd8), - U64_C(0xde99148706c7bb74), U64_C(0x5dde9f80b4813c10), - U64_C(0xea18cd3d58787724), U64_C(0x695f463aea3ef040), - U64_C(0xf196c63321f464ec), U64_C(0x72d14d3493b2e388), - U64_C(0xdc19db21aa7d51a9), U64_C(0x5f5e5026183bd6cd), - U64_C(0xc797d02fd3f14261), U64_C(0x44d05b2861b7c505), - U64_C(0x861ae105a1723b23), U64_C(0x055d6a021334bc47), - U64_C(0x9d94ea0bd8fe28eb), U64_C(0x1ed3610c6ab8af8f), - U64_C(0xb01bf71953771dae), U64_C(0x335c7c1ee1319aca), - U64_C(0xab95fc172afb0e66), U64_C(0x28d2771098bd8902), - U64_C(0x321c954db76cef2a), U64_C(0xb15b1e4a052a684e), - U64_C(0x29929e43cee0fce2), U64_C(0xaad515447ca67b86), - U64_C(0x041d83514569c9a7), U64_C(0x875a0856f72f4ec3), - U64_C(0x1f93885f3ce5da6f), U64_C(0x9cd403588ea35d0b), - U64_C(0x5e1eb9754e66a32d), U64_C(0xdd593272fc202449), - U64_C(0x4590b27b37eab0e5), U64_C(0xc6d7397c85ac3781), - U64_C(0x681faf69bc6385a0), U64_C(0xeb58246e0e2502c4), - U64_C(0x7391a467c5ef9668), U64_C(0xf0d62f6077a9110c), - U64_C(0x8e20faa72ba0b470), U64_C(0x0d6771a099e63314), - U64_C(0x95aef1a9522ca7b8), U64_C(0x16e97aaee06a20dc), - U64_C(0xb821ecbbd9a592fd), U64_C(0x3b6667bc6be31599), - U64_C(0xa3afe7b5a0298135), U64_C(0x20e86cb2126f0651), - U64_C(0xe222d69fd2aaf877), U64_C(0x61655d9860ec7f13), - U64_C(0xf9acdd91ab26ebbf), U64_C(0x7aeb569619606cdb), - U64_C(0xd423c08320afdefa), U64_C(0x57644b8492e9599e), - U64_C(0xcfadcb8d5923cd32), U64_C(0x4cea408aeb654a56), - U64_C(0x5624a2d7c4b42c7e), U64_C(0xd56329d076f2ab1a), - U64_C(0x4daaa9d9bd383fb6), U64_C(0xceed22de0f7eb8d2), - U64_C(0x6025b4cb36b10af3), U64_C(0xe3623fcc84f78d97), - U64_C(0x7babbfc54f3d193b), U64_C(0xf8ec34c2fd7b9e5f), - U64_C(0x3a268eef3dbe6079), U64_C(0xb96105e88ff8e71d), - U64_C(0x21a885e1443273b1), U64_C(0xa2ef0ee6f674f4d5), - U64_C(0x0c2798f3cfbb46f4), U64_C(0x8f6013f47dfdc190), - U64_C(0x17a993fdb637553c), U64_C(0x94ee18fa0471d258), - U64_C(0x23284a47e888996c), U64_C(0xa06fc1405ace1e08), - U64_C(0x38a6414991048aa4), U64_C(0xbbe1ca4e23420dc0), - U64_C(0x15295c5b1a8dbfe1), U64_C(0x966ed75ca8cb3885), - U64_C(0x0ea757556301ac29), U64_C(0x8de0dc52d1472b4d), - U64_C(0x4f2a667f1182d56b), U64_C(0xcc6ded78a3c4520f), - U64_C(0x54a46d71680ec6a3), U64_C(0xd7e3e676da4841c7), - U64_C(0x792b7063e387f3e6), U64_C(0xfa6cfb6451c17482), - U64_C(0x62a57b6d9a0be02e), U64_C(0xe1e2f06a284d674a), - U64_C(0xfb2c1237079c0162), U64_C(0x786b9930b5da8606), - U64_C(0xe0a219397e1012aa), U64_C(0x63e5923ecc5695ce), - U64_C(0xcd2d042bf59927ef), U64_C(0x4e6a8f2c47dfa08b), - U64_C(0xd6a30f258c153427), U64_C(0x55e484223e53b343), - U64_C(0x972e3e0ffe964d65), U64_C(0x1469b5084cd0ca01), - U64_C(0x8ca03501871a5ead), U64_C(0x0fe7be06355cd9c9), - U64_C(0xa12f28130c936be8), U64_C(0x2268a314bed5ec8c), - U64_C(0xbaa1231d751f7820), U64_C(0x39e6a81ac759ff44), - U64_C(0xc930877ab0f0ee48), U64_C(0x4a770c7d02b6692c), - U64_C(0xd2be8c74c97cfd80), U64_C(0x51f907737b3a7ae4), - U64_C(0xff31916642f5c8c5), U64_C(0x7c761a61f0b34fa1), - U64_C(0xe4bf9a683b79db0d), U64_C(0x67f8116f893f5c69), - U64_C(0xa532ab4249faa24f), U64_C(0x26752045fbbc252b), - U64_C(0xbebca04c3076b187), U64_C(0x3dfb2b4b823036e3), - U64_C(0x9333bd5ebbff84c2), U64_C(0x1074365909b903a6), - U64_C(0x88bdb650c273970a), U64_C(0x0bfa3d577035106e), - U64_C(0x1134df0a5fe47646), U64_C(0x9273540deda2f122), - U64_C(0x0abad4042668658e), U64_C(0x89fd5f03942ee2ea), - U64_C(0x2735c916ade150cb), U64_C(0xa47242111fa7d7af), - U64_C(0x3cbbc218d46d4303), U64_C(0xbffc491f662bc467), - U64_C(0x7d36f332a6ee3a41), U64_C(0xfe71783514a8bd25), - U64_C(0x66b8f83cdf622989), U64_C(0xe5ff733b6d24aeed), - U64_C(0x4b37e52e54eb1ccc), U64_C(0xc8706e29e6ad9ba8), - U64_C(0x50b9ee202d670f04), U64_C(0xd3fe65279f218860), - U64_C(0x6438379a73d8c354), U64_C(0xe77fbc9dc19e4430), - U64_C(0x7fb63c940a54d09c), U64_C(0xfcf1b793b81257f8), - U64_C(0x5239218681dde5d9), U64_C(0xd17eaa81339b62bd), - U64_C(0x49b72a88f851f611), U64_C(0xcaf0a18f4a177175), - U64_C(0x083a1ba28ad28f53), U64_C(0x8b7d90a538940837), - U64_C(0x13b410acf35e9c9b), U64_C(0x90f39bab41181bff), - U64_C(0x3e3b0dbe78d7a9de), U64_C(0xbd7c86b9ca912eba), - U64_C(0x25b506b0015bba16), U64_C(0xa6f28db7b31d3d72), - U64_C(0xbc3c6fea9ccc5b5a), U64_C(0x3f7be4ed2e8adc3e), - U64_C(0xa7b264e4e5404892), U64_C(0x24f5efe35706cff6), - U64_C(0x8a3d79f66ec97dd7), U64_C(0x097af2f1dc8ffab3), - U64_C(0x91b372f817456e1f), U64_C(0x12f4f9ffa503e97b), - U64_C(0xd03e43d265c6175d), U64_C(0x5379c8d5d7809039), - U64_C(0xcbb048dc1c4a0495), U64_C(0x48f7c3dbae0c83f1), - U64_C(0xe63f55ce97c331d0), U64_C(0x6578dec92585b6b4), - U64_C(0xfdb15ec0ee4f2218), U64_C(0x7ef6d5c75c09a57c) }, + { U64_C(0xe63f55ce97c331d0), U64_C(0x25b506b0015bba16), + U64_C(0xc8706e29e6ad9ba8), U64_C(0x5b43d3775d521f6a), + U64_C(0x0bfa3d577035106e), U64_C(0xab95fc172afb0e66), + U64_C(0xf64b63979e7a3276), U64_C(0xf58b4562649dad4b), + U64_C(0x48f7c3dbae0c83f1), U64_C(0xff31916642f5c8c5), + U64_C(0xcbb048dc1c4a0495), U64_C(0x66b8f83cdf622989), + U64_C(0x35c130e908e2b9b0), U64_C(0x7c761a61f0b34fa1), + U64_C(0x3601161cf205268d), U64_C(0x9e54ccfe2219b7d6), + U64_C(0x8b7d90a538940837), U64_C(0x9cd403588ea35d0b), + U64_C(0xbc3c6fea9ccc5b5a), U64_C(0xe5ff733b6d24aeed), + U64_C(0xceed22de0f7eb8d2), U64_C(0xec8581cab1ab545e), + U64_C(0xb96105e88ff8e71d), U64_C(0x8ca03501871a5ead), + U64_C(0x76ccce65d6db2a2f), U64_C(0x5883f582a7b58057), + U64_C(0x3f7be4ed2e8adc3e), U64_C(0x0fe7be06355cd9c9), + U64_C(0xee054e6c1d11be83), U64_C(0x1074365909b903a6), + U64_C(0x5dde9f80b4813c10), U64_C(0x4a770c7d02b6692c), + U64_C(0x5379c8d5d7809039), U64_C(0xb4067448161ed409), + U64_C(0x5f5e5026183bd6cd), U64_C(0xe898029bf4c29df9), + U64_C(0x7fb63c940a54d09c), U64_C(0xc5171f897f4ba8bc), + U64_C(0xa6f28db7b31d3d72), U64_C(0x2e4f3be7716eaa78), + U64_C(0x0d6771a099e63314), U64_C(0x82076254e41bf284), + U64_C(0x2f0fd2b42733df98), U64_C(0x5c9e76d3e2dc49f0), + U64_C(0x7aeb569619606cdb), U64_C(0x83478b07b2468764), + U64_C(0xcfadcb8d5923cd32), U64_C(0x85dac7f05b95a41e), + U64_C(0xb5469d1b4043a1e9), U64_C(0xb821ecbbd9a592fd), + U64_C(0x1b8e0b0e798c13c8), U64_C(0x62a57b6d9a0be02e), + U64_C(0xfcf1b793b81257f8), U64_C(0x9d94ea0bd8fe28eb), + U64_C(0x4cea408aeb654a56), U64_C(0x23284a47e888996c), + U64_C(0x2d8f1d128b893545), U64_C(0xf4cbac3132c0d8ab), + U64_C(0xbd7c86b9ca912eba), U64_C(0x3a268eef3dbe6079), + U64_C(0xf0d62f6077a9110c), U64_C(0x2735c916ade150cb), + U64_C(0x89fd5f03942ee2ea), U64_C(0x1acee25d2fd16628), + U64_C(0x90f39bab41181bff), U64_C(0x430dfe8cde39939f), + U64_C(0xf70b8ac4c8274796), U64_C(0x1c53aeaac6024552), + U64_C(0x13b410acf35e9c9b), U64_C(0xa532ab4249faa24f), + U64_C(0x2b1251e5625a163f), U64_C(0xd7e3e676da4841c7), + U64_C(0xa7b264e4e5404892), U64_C(0xda8497d643ae72d3), + U64_C(0x861ae105a1723b23), U64_C(0x38a6414991048aa4), + U64_C(0x6578dec92585b6b4), U64_C(0x0280cfa6acbaeadd), + U64_C(0x88bdb650c273970a), U64_C(0x9333bd5ebbff84c2), + U64_C(0x4e6a8f2c47dfa08b), U64_C(0x321c954db76cef2a), + U64_C(0x418d312a72837942), U64_C(0xb29b38bfffcdf773), + U64_C(0x6c022c38f90a4c07), U64_C(0x5a033a240b0f6a8a), + U64_C(0x1f93885f3ce5da6f), U64_C(0xc38a537e96988bc6), + U64_C(0x39e6a81ac759ff44), U64_C(0x29929e43cee0fce2), + U64_C(0x40cdd87924de0ca2), U64_C(0xe9d8ebc8a29fe819), + U64_C(0x0c2798f3cfbb46f4), U64_C(0x55e484223e53b343), + U64_C(0x4650948ecd0d2fd8), U64_C(0x20e86cb2126f0651), + U64_C(0x6d42c56baf5739e7), U64_C(0xa06fc1405ace1e08), + U64_C(0x7babbfc54f3d193b), U64_C(0x424d17df8864e67f), + U64_C(0xd8045870ef14980e), U64_C(0xc6d7397c85ac3781), + U64_C(0x21a885e1443273b1), U64_C(0x67f8116f893f5c69), + U64_C(0x24f5efe35706cff6), U64_C(0xd56329d076f2ab1a), + U64_C(0x5e1eb9754e66a32d), U64_C(0x28d2771098bd8902), + U64_C(0x8f6013f47dfdc190), U64_C(0x17a993fdb637553c), + U64_C(0xe0a219397e1012aa), U64_C(0x786b9930b5da8606), + U64_C(0x6e82e39e55b0a6da), U64_C(0x875a0856f72f4ec3), + U64_C(0x3741ff4fa458536d), U64_C(0xac4859b3957558fc), + U64_C(0x7ef6d5c75c09a57c), U64_C(0xc04a758b6c7f14fb), + U64_C(0xf9acdd91ab26ebbf), U64_C(0x7391a467c5ef9668), + U64_C(0x335c7c1ee1319aca), U64_C(0xa91533b18641e4bb), + U64_C(0xe4bf9a683b79db0d), U64_C(0x8e20faa72ba0b470), + U64_C(0x51f907737b3a7ae4), U64_C(0x2268a314bed5ec8c), + U64_C(0xd944b123b949edee), U64_C(0x31dcb3b84d8b7017), + U64_C(0xd3fe65279f218860), U64_C(0x097af2f1dc8ffab3), + U64_C(0x9b09a6fc312d0b91), U64_C(0xcc6ded78a3c4520f), + U64_C(0x3481d9ba5ebfcc50), U64_C(0x4f2a667f1182d56b), + U64_C(0xdfd9fdd4509ace94), U64_C(0x26752045fbbc252b), + U64_C(0xbffc491f662bc467), U64_C(0xdd593272fc202449), + U64_C(0x3cbbc218d46d4303), U64_C(0x91b372f817456e1f), + U64_C(0x681faf69bc6385a0), U64_C(0xb686bbeebaa43ed4), + U64_C(0x1469b5084cd0ca01), U64_C(0x98c98009cbca94ac), + U64_C(0x6438379a73d8c354), U64_C(0xc2caba2dc0c5fe26), + U64_C(0x3e3b0dbe78d7a9de), U64_C(0x50b9ee202d670f04), + U64_C(0x4590b27b37eab0e5), U64_C(0x6025b4cb36b10af3), + U64_C(0xfb2c1237079c0162), U64_C(0xa12f28130c936be8), + U64_C(0x4b37e52e54eb1ccc), U64_C(0x083a1ba28ad28f53), + U64_C(0xc10a9cd83a22611b), U64_C(0x9f1425ad7444c236), + U64_C(0x069d4cf7e9d3237a), U64_C(0xedc56899e7f621be), + U64_C(0x778c273680865fcf), U64_C(0x309c5aeb1bd605f7), + U64_C(0x8de0dc52d1472b4d), U64_C(0xf8ec34c2fd7b9e5f), + U64_C(0xea18cd3d58787724), U64_C(0xaad515447ca67b86), + U64_C(0x9989695a9d97e14c), U64_C(0x0000000000000000), + U64_C(0xf196c63321f464ec), U64_C(0x71116bc169557cb5), + U64_C(0xaf887f466f92c7c1), U64_C(0x972e3e0ffe964d65), + U64_C(0x190ec4a8d536f915), U64_C(0x95aef1a9522ca7b8), + U64_C(0xdc19db21aa7d51a9), U64_C(0x94ee18fa0471d258), + U64_C(0x8087adf248a11859), U64_C(0xc457f6da2916dd5c), + U64_C(0xfa6cfb6451c17482), U64_C(0xf256e0c6db13fbd1), + U64_C(0x6a9f60cf10d96f7d), U64_C(0x4daaa9d9bd383fb6), + U64_C(0x03c026f5fae79f3d), U64_C(0xde99148706c7bb74), + U64_C(0x2a52b8b6340763df), U64_C(0x6fc20acd03edd33a), + U64_C(0xd423c08320afdefa), U64_C(0xbbe1ca4e23420dc0), + U64_C(0x966ed75ca8cb3885), U64_C(0xeb58246e0e2502c4), + U64_C(0x055d6a021334bc47), U64_C(0xa47242111fa7d7af), + U64_C(0xe3623fcc84f78d97), U64_C(0x81c744a11efc6db9), + U64_C(0xaec8961539cfb221), U64_C(0xf31609958d4e8e31), + U64_C(0x63e5923ecc5695ce), U64_C(0x47107ddd9b505a38), + U64_C(0xa3afe7b5a0298135), U64_C(0x792b7063e387f3e6), + U64_C(0x0140e953565d75e0), U64_C(0x12f4f9ffa503e97b), + U64_C(0x750ce8902c3cb512), U64_C(0xdbc47e8515f30733), + U64_C(0x1ed3610c6ab8af8f), U64_C(0x5239218681dde5d9), + U64_C(0xe222d69fd2aaf877), U64_C(0xfe71783514a8bd25), + U64_C(0xcaf0a18f4a177175), U64_C(0x61655d9860ec7f13), + U64_C(0xe77fbc9dc19e4430), U64_C(0x2ccff441ddd440a5), + U64_C(0x16e97aaee06a20dc), U64_C(0xa855dae2d01c915b), + U64_C(0x1d1347f9905f30b2), U64_C(0xb7c652bdecf94b34), + U64_C(0xd03e43d265c6175d), U64_C(0xfdb15ec0ee4f2218), + U64_C(0x57644b8492e9599e), U64_C(0x07dda5a4bf8e569a), + U64_C(0x54a46d71680ec6a3), U64_C(0x5624a2d7c4b42c7e), + U64_C(0xbebca04c3076b187), U64_C(0x7d36f332a6ee3a41), + U64_C(0x3b6667bc6be31599), U64_C(0x695f463aea3ef040), + U64_C(0xad08b0e0c3282d1c), U64_C(0xb15b1e4a052a684e), + U64_C(0x44d05b2861b7c505), U64_C(0x15295c5b1a8dbfe1), + U64_C(0x744c01c37a61c0f2), U64_C(0x59c31cd1f1e8f5b7), + U64_C(0xef45a73f4b4ccb63), U64_C(0x6bdf899c46841a9d), + U64_C(0x3dfb2b4b823036e3), U64_C(0xa2ef0ee6f674f4d5), + U64_C(0x184e2dfb836b8cf5), U64_C(0x1134df0a5fe47646), + U64_C(0xbaa1231d751f7820), U64_C(0xd17eaa81339b62bd), + U64_C(0xb01bf71953771dae), U64_C(0x849a2ea30dc8d1fe), + U64_C(0x705182923f080955), U64_C(0x0ea757556301ac29), + U64_C(0x041d83514569c9a7), U64_C(0x0abad4042668658e), + U64_C(0x49b72a88f851f611), U64_C(0x8a3d79f66ec97dd7), + U64_C(0xcd2d042bf59927ef), U64_C(0xc930877ab0f0ee48), + U64_C(0x9273540deda2f122), U64_C(0xc797d02fd3f14261), + U64_C(0xe1e2f06a284d674a), U64_C(0xd2be8c74c97cfd80), + U64_C(0x9a494faf67707e71), U64_C(0xb3dbd1eca9908293), + U64_C(0x72d14d3493b2e388), U64_C(0xd6a30f258c153427) }, }; -static u64 strido (u64 l) -{ - u64 t = 0; - t^= stribog_table[0][(l >> 0) & 255]; - t^= stribog_table[1][(l >> 8) & 255]; - t^= stribog_table[2][(l >> 16) & 255]; - t^= stribog_table[3][(l >> 24) & 255]; - t^= stribog_table[4][(l >> 32) & 255]; - t^= stribog_table[5][(l >> 40) & 255]; - t^= stribog_table[6][(l >> 48) & 255]; - t^= stribog_table[7][(l >> 56) & 255]; - return t; -} -#endif static const u64 C16[13][16] = { @@ -1225,38 +1133,40 @@ static const u64 C16[13][16] = }; -static void LPSX (u64 *out, u64 *a, const u64 *b) -{ - int i; - u64 temp[8]; - for (i = 0; i < 8; i++) - temp[i] = a[i] ^ b[i]; - for (i = 0; i < 8; i++) - { - u64 l = - ((u64) Pi[ (temp[7] >> (i * 8)) & 0xff] << (7 * 8)) | - ((u64) Pi[ (temp[6] >> (i * 8)) & 0xff] << (6 * 8)) | - ((u64) Pi[ (temp[5] >> (i * 8)) & 0xff] << (5 * 8)) | - ((u64) Pi[ (temp[4] >> (i * 8)) & 0xff] << (4 * 8)) | - ((u64) Pi[ (temp[3] >> (i * 8)) & 0xff] << (3 * 8)) | - ((u64) Pi[ (temp[2] >> (i * 8)) & 0xff] << (2 * 8)) | - ((u64) Pi[ (temp[1] >> (i * 8)) & 0xff] << (1 * 8)) | - ((u64) Pi[ (temp[0] >> (i * 8)) & 0xff] << (0 * 8)) | - 0; - - out[i] = strido(l); - } -} +#define strido(out, temp, i) do { \ + u64 t; \ + t = stribog_table[0][(temp[0] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[1][(temp[1] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[2][(temp[2] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[3][(temp[3] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[4][(temp[4] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[5][(temp[5] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[6][(temp[6] >> (i * 8)) & 0xff]; \ + t ^= stribog_table[7][(temp[7] >> (i * 8)) & 0xff]; \ + out[i] = t; } while(0) -static void xor (u64 *out, u64 *in) +static void LPSX (u64 *out, const u64 *a, const u64 *b) { - int i; - for (i = 0; i < 8; i++) - out[i] ^= in[i]; + u64 temp[8]; + temp[0] = a[0] ^ b[0]; + temp[1] = a[1] ^ b[1]; + temp[2] = a[2] ^ b[2]; + temp[3] = a[3] ^ b[3]; + temp[4] = a[4] ^ b[4]; + temp[5] = a[5] ^ b[5]; + temp[6] = a[6] ^ b[6]; + temp[7] = a[7] ^ b[7]; + strido (out, temp, 0); + strido (out, temp, 1); + strido (out, temp, 2); + strido (out, temp, 3); + strido (out, temp, 4); + strido (out, temp, 5); + strido (out, temp, 6); + strido (out, temp, 7); } - -static void g (u64 *h, u64 *m, u64 *N) +static inline void g (u64 *h, u64 *m, u64 *N) { u64 K[8]; u64 T[8]; @@ -1264,14 +1174,22 @@ static void g (u64 *h, u64 *m, u64 *N) LPSX (K, h, N); - for (i = 0; i < 12; i++) + LPSX (T, K, m); + LPSX (K, K, C16[0]); + for (i = 1; i < 12; i++) { - LPSX (T, K, i == 0 ? m : T); + LPSX (T, K, T); LPSX (K, K, C16[i]); } - xor (T, K); - xor (T, m); - xor (h, T); + + h[0] ^= T[0] ^ K[0] ^ m[0]; + h[1] ^= T[1] ^ K[1] ^ m[1]; + h[2] ^= T[2] ^ K[2] ^ m[2]; + h[3] ^= T[3] ^ K[3] ^ m[3]; + h[4] ^= T[4] ^ K[4] ^ m[4]; + h[5] ^= T[5] ^ K[5] ^ m[5]; + h[6] ^= T[6] ^ K[6] ^ m[6]; + h[7] ^= T[7] ^ K[7] ^ m[7]; } From cvs at cvs.gnupg.org Tue Nov 5 17:31:45 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 05 Nov 2013 17:31:45 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-353-gf09ffe8 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via f09ffe8a4802af65a116e79eceeb1cb4ed4fa2f4 (commit) via 630aca794ddf057fb7265b7dc346374743036af4 (commit) from d50a88d1e29124d038196fec6082fd093e922604 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit f09ffe8a4802af65a116e79eceeb1cb4ed4fa2f4 Author: Werner Koch Date: Tue Nov 5 17:25:02 2013 +0100 ecc: Fully implement Ed25519 compression in ECDSA mode. * src/ec-context.h (mpi_ec_ctx_s): Add field FLAGS. * mpi/ec.c (ec_p_init): Add arg FLAGS. Change all callers to pass it. * cipher/ecc-curves.c (point_from_keyparam): Add arg EC, parse as opaque mpi and use eddsa decoding depending on the flag. (_gcry_mpi_ec_new): Rearrange to parse Q and D after knowing the curve. Signed-off-by: Werner Koch diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index fb0db3b..1bd3679 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -545,28 +545,36 @@ mpi_from_keyparam (gcry_mpi_t *r_a, gcry_sexp_t keyparam, const char *name) /* Helper to extract a point from key parameters. If no parameter with NAME is found, the functions tries to find a non-encoded point by appending ".x", ".y" and ".z" to NAME. ".z" is in this case - optional and defaults to 1. */ + optional and defaults to 1. EC is the context which at this point + may not be fully initialized. */ static gpg_err_code_t point_from_keyparam (gcry_mpi_point_t *r_a, - gcry_sexp_t keyparam, const char *name) + gcry_sexp_t keyparam, const char *name, mpi_ec_t ec) { - gcry_err_code_t ec; - gcry_mpi_t a = NULL; + gcry_err_code_t rc; + gcry_sexp_t l1; gcry_mpi_point_t point; - ec = mpi_from_keyparam (&a, keyparam, name); - if (ec) - return ec; - - if (a) + l1 = gcry_sexp_find_token (keyparam, name, 0); + if (l1) { + gcry_mpi_t a; + + a = _gcry_sexp_nth_opaque_mpi (l1, 1); + gcry_sexp_release (l1); + if (!a) + return GPG_ERR_INV_OBJ; + point = gcry_mpi_point_new (0); - ec = _gcry_ecc_os2ec (point, a); + if (ec && ec->dialect == ECC_DIALECT_ED25519) + rc = _gcry_ecc_eddsa_decodepoint (a, ec, point, NULL, NULL); + else + rc = _gcry_ecc_os2ec (point, a); mpi_free (a); - if (ec) + if (rc) { gcry_mpi_point_release (point); - return ec; + return rc; } } else @@ -580,28 +588,28 @@ point_from_keyparam (gcry_mpi_point_t *r_a, if (!tmpname) return gpg_err_code_from_syserror (); strcpy (stpcpy (tmpname, name), ".x"); - ec = mpi_from_keyparam (&x, keyparam, tmpname); - if (ec) + rc = mpi_from_keyparam (&x, keyparam, tmpname); + if (rc) { gcry_free (tmpname); - return ec; + return rc; } strcpy (stpcpy (tmpname, name), ".y"); - ec = mpi_from_keyparam (&y, keyparam, tmpname); - if (ec) + rc = mpi_from_keyparam (&y, keyparam, tmpname); + if (rc) { mpi_free (x); gcry_free (tmpname); - return ec; + return rc; } strcpy (stpcpy (tmpname, name), ".z"); - ec = mpi_from_keyparam (&z, keyparam, tmpname); - if (ec) + rc = mpi_from_keyparam (&z, keyparam, tmpname); + if (rc) { mpi_free (y); mpi_free (x); gcry_free (tmpname); - return ec; + return rc; } if (!z) z = mpi_set_ui (NULL, 1); @@ -645,35 +653,43 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_mpi_t n = NULL; gcry_mpi_point_t Q = NULL; gcry_mpi_t d = NULL; + int flags = 0; gcry_sexp_t l1; *r_ctx = NULL; if (keyparam) { - errc = mpi_from_keyparam (&p, keyparam, "p"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&a, keyparam, "a"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&b, keyparam, "b"); - if (errc) - goto leave; - errc = point_from_keyparam (&G, keyparam, "g"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&n, keyparam, "n"); - if (errc) - goto leave; - errc = point_from_keyparam (&Q, keyparam, "q"); - if (errc) - goto leave; - errc = mpi_from_keyparam (&d, keyparam, "d"); - if (errc) - goto leave; - } + /* Parse an optional flags list. */ + l1 = gcry_sexp_find_token (keyparam, "flags", 0); + if (l1) + { + errc = _gcry_pk_util_parse_flaglist (l1, &flags, NULL); + gcry_sexp_release (l1); + l1 = NULL; + if (errc) + goto leave; + } + if (!(flags & PUBKEY_FLAG_NOPARAM)) + { + errc = mpi_from_keyparam (&p, keyparam, "p"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&a, keyparam, "a"); + if (errc) + goto leave; + errc = mpi_from_keyparam (&b, keyparam, "b"); + if (errc) + goto leave; + errc = point_from_keyparam (&G, keyparam, "g", NULL); + if (errc) + goto leave; + errc = mpi_from_keyparam (&n, keyparam, "n"); + if (errc) + goto leave; + } + } /* Check whether a curve parameter is available and use that to fill in missing values. If no curve parameter is available try an @@ -751,7 +767,8 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, gcry_free (E); } - errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, p, a, b); + + errc = _gcry_mpi_ec_p_new (&ctx, model, dialect, flags, p, a, b); if (!errc) { mpi_ec_t ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); @@ -771,6 +788,22 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, ec->n = n; n = NULL; } + + /* Now that we now the curve name we can look for the public key + Q. point_from_keyparam needs to know the curve parameters so + that it is able to use the correct decompression. Parsing + the private key D could have been done earlier but it is less + surprising if we do it here as well. */ + if (keyparam) + { + errc = point_from_keyparam (&Q, keyparam, "q", ec); + if (errc) + goto leave; + errc = mpi_from_keyparam (&d, keyparam, "d"); + if (errc) + goto leave; + } + if (Q) { ec->Q = Q; @@ -783,9 +816,11 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, } *r_ctx = ctx; + ctx = NULL; } leave: + gcry_ctx_release (ctx); mpi_free (p); mpi_free (a); mpi_free (b); @@ -814,7 +849,10 @@ _gcry_ecc_get_param (const char *name, gcry_mpi_t *pkey) g_x = mpi_new (0); g_y = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (0, ECC_DIALECT_STANDARD, E.p, E.a, NULL); + ctx = _gcry_mpi_ec_p_internal_new (MPI_EC_WEIERSTRASS, + ECC_DIALECT_STANDARD, + 0, + E.p, E.a, NULL); if (_gcry_mpi_ec_get_affine (g_x, g_y, &E.G, ctx)) log_fatal ("ecc get param: Failed to get affine coordinates\n"); _gcry_mpi_ec_free (ctx); diff --git a/cipher/ecc-ecdsa.c b/cipher/ecc-ecdsa.c index 70dfe38..7663623 100644 --- a/cipher/ecc-ecdsa.c +++ b/cipher/ecc-ecdsa.c @@ -78,7 +78,7 @@ _gcry_ecc_ecdsa_sign (gcry_mpi_t input, ECC_secret_key *skey, x = mpi_alloc (0); point_init (&I); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0, skey->E.p, skey->E.a, skey->E.b); /* Two loops to avoid R or S are zero. This is more of a joke than @@ -179,7 +179,7 @@ _gcry_ecc_ecdsa_verify (gcry_mpi_t input, ECC_public_key *pkey, point_init (&Q1); point_init (&Q2); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0, pkey->E.p, pkey->E.a, pkey->E.b); /* h = s^(-1) (mod n) */ diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c index 22f2702..d83b7c6 100644 --- a/cipher/ecc-eddsa.c +++ b/cipher/ecc-eddsa.c @@ -441,7 +441,7 @@ _gcry_ecc_eddsa_sign (gcry_mpi_t input, ECC_secret_key *skey, x = mpi_new (0); y = mpi_new (0); r = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0, skey->E.p, skey->E.a, skey->E.b); b = (ctx->nbits+7)/8; if (b != 256/8) @@ -618,7 +618,7 @@ _gcry_ecc_eddsa_verify (gcry_mpi_t input, ECC_public_key *pkey, h = mpi_new (0); s = mpi_new (0); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0, pkey->E.p, pkey->E.a, pkey->E.b); b = ctx->nbits/8; if (b != 256/8) diff --git a/cipher/ecc-gost.c b/cipher/ecc-gost.c index a40459c..ce3e921 100644 --- a/cipher/ecc-gost.c +++ b/cipher/ecc-gost.c @@ -77,7 +77,7 @@ _gcry_ecc_gost_sign (gcry_mpi_t input, ECC_secret_key *skey, x = mpi_alloc (0); point_init (&I); - ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (skey->E.model, skey->E.dialect, 0, skey->E.p, skey->E.a, skey->E.b); mpi_mod (e, input, skey->E.n); /* e = hash mod n */ @@ -164,7 +164,7 @@ _gcry_ecc_gost_verify (gcry_mpi_t input, ECC_public_key *pkey, point_init (&Q1); point_init (&Q2); - ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (pkey->E.model, pkey->E.dialect, 0, pkey->E.p, pkey->E.a, pkey->E.b); mpi_mod (e, input, pkey->E.n); /* e = hash mod n */ diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index fa0bded..6c75e75 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -26,6 +26,7 @@ #include "g10lib.h" #include "mpi.h" +#include "cipher.h" #include "context.h" #include "ec-context.h" #include "ecc-common.h" @@ -263,67 +264,62 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec) if (ec->model == MPI_EC_TWISTEDEDWARDS && !ec->b) return NULL; - switch (ec->dialect) + if (ec->dialect == ECC_DIALECT_ED25519 + && !(ec->flags & PUBKEY_FLAG_ECDSA)) { - case ECC_DIALECT_ED25519: - { - gcry_mpi_t a; - unsigned char *rawmpi = NULL; - unsigned int rawmpilen; - unsigned char *digest; - gcry_buffer_t hvec[2]; - int b = (ec->nbits+7)/8; - - gcry_assert (b >= 32); - digest = gcry_calloc_secure (2, b); - if (!digest) + gcry_mpi_t a; + unsigned char *rawmpi = NULL; + unsigned int rawmpilen; + unsigned char *digest; + gcry_buffer_t hvec[2]; + int b = (ec->nbits+7)/8; + + gcry_assert (b >= 32); + digest = gcry_calloc_secure (2, b); + if (!digest) + return NULL; + memset (hvec, 0, sizeof hvec); + + rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL); + if (!rawmpi) + return NULL; + memset (digest, 0, b); + hvec[0].data = digest; + hvec[0].off = 0; + hvec[0].len = b > rawmpilen? b - rawmpilen : 0; + hvec[1].data = rawmpi; + hvec[1].off = 0; + hvec[1].len = rawmpilen; + /* FIXME: Put and take the hash algo from the context. */ + rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, digest, hvec, 2); + gcry_free (rawmpi); + if (rc) + { + gcry_free (digest); return NULL; - memset (hvec, 0, sizeof hvec); + } - rawmpi = _gcry_mpi_get_buffer (ec->d, 0, &rawmpilen, NULL); - if (!rawmpi) - return NULL; - memset (digest, 0, b); - hvec[0].data = digest; - hvec[0].off = 0; - hvec[0].len = b > rawmpilen? b - rawmpilen : 0; - hvec[1].data = rawmpi; - hvec[1].off = 0; - hvec[1].len = rawmpilen; - /* FIXME: Put and take the hash algo from the context. */ - rc = _gcry_md_hash_buffers (GCRY_MD_SHA512, 0, digest, hvec, 2); - gcry_free (rawmpi); - if (rc) - { - gcry_free (digest); - return NULL; - } - - /* Compute the A value. */ - reverse_buffer (digest, 32); /* Only the first half of the hash. */ - digest[0] = (digest[0] & 0x7f) | 0x40; - digest[31] &= 0xf8; - a = mpi_snew (0); - _gcry_mpi_set_buffer (a, digest, 32, 0); - gcry_free (digest); - - /* And finally the public key. */ - if (!Q) - Q = gcry_mpi_point_new (0); - if (Q) - _gcry_mpi_ec_mul_point (Q, a, ec->G, ec); - mpi_free (a); - } - break; - - default: - { - if (!Q) - Q = gcry_mpi_point_new (0); - if (Q) - _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); - } - break; + /* Compute the A value. */ + reverse_buffer (digest, 32); /* Only the first half of the hash. */ + digest[0] = (digest[0] & 0x7f) | 0x40; + digest[31] &= 0xf8; + a = mpi_snew (0); + _gcry_mpi_set_buffer (a, digest, 32, 0); + gcry_free (digest); + + /* And finally the public key. */ + if (!Q) + Q = gcry_mpi_point_new (0); + if (Q) + _gcry_mpi_ec_mul_point (Q, a, ec->G, ec); + mpi_free (a); + } + else + { + if (!Q) + Q = gcry_mpi_point_new (0); + if (Q) + _gcry_mpi_ec_mul_point (Q, ec->d, ec->G, ec); } return Q; diff --git a/cipher/ecc.c b/cipher/ecc.c index 752dfc1..8bc8ea6 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -312,7 +312,7 @@ check_secret_key (ECC_secret_key * sk) goto leave; } - ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, + ctx = _gcry_mpi_ec_p_internal_new (sk->E.model, sk->E.dialect, 0, sk->E.p, sk->E.a, sk->E.b); _gcry_mpi_ec_mul_point (&Q, sk->E.n, &sk->E.G, ctx); @@ -469,7 +469,7 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) else random_level = GCRY_VERY_STRONG_RANDOM; - ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, E.p, E.a, E.b); + ctx = _gcry_mpi_ec_p_internal_new (E.model, E.dialect, 0, E.p, E.a, E.b); x = mpi_new (0); y = mpi_new (0); @@ -984,7 +984,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) /* Fixme: Factor the curve context setup out of eddsa_verify and ecdsa_verify. So that we don't do it twice. */ - ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, + ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0, pk.E.p, pk.E.a, pk.E.b); rc = _gcry_ecc_eddsa_decodepoint (mpi_q, ec, &pk.Q, NULL, NULL); @@ -1169,7 +1169,7 @@ ecc_encrypt_raw (gcry_sexp_t *r_ciph, gcry_sexp_t s_data, gcry_sexp_t keyparms) } /* Compute the encrypted value. */ - ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, + ec = _gcry_mpi_ec_p_internal_new (pk.E.model, pk.E.dialect, 0, pk.E.p, pk.E.a, pk.E.b); /* The following is false: assert( mpi_cmp_ui( R.x, 1 )==0 );, so */ @@ -1338,7 +1338,7 @@ ecc_decrypt_raw (gcry_sexp_t *r_plain, gcry_sexp_t s_data, gcry_sexp_t keyparms) return rc; } - ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, + ec = _gcry_mpi_ec_p_internal_new (sk.E.model, sk.E.dialect, 0, sk.E.p, sk.E.a, sk.E.b); /* R = dkG */ diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 76cf0bd..9c695e0 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2278,7 +2278,7 @@ For ECC key generation do not return the domain parameters but only the name of the curve. For ECC signing and verification ignore any provided domain parameters of the public or private key and use only the curve name. It is more secure to rely on the curve name and thus -use the curve parameters as known by Libgcrypt. This option shouild +use the curve parameters as known by Libgcrypt. This option should have been the default but for backward compatibility reasons this is not possible. It is best to always use this flag with ECC keys. diff --git a/mpi/ec.c b/mpi/ec.c index 39ab5eb..57396ce 100644 --- a/mpi/ec.c +++ b/mpi/ec.c @@ -350,6 +350,7 @@ ec_get_two_inv_p (mpi_ec_t ec) static void ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, enum ecc_dialects dialect, + int flags, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { int i; @@ -367,6 +368,7 @@ ec_p_init (mpi_ec_t ctx, enum gcry_mpi_ec_models model, ctx->model = model; ctx->dialect = dialect; + ctx->flags = flags; if (dialect == ECC_DIALECT_ED25519) ctx->nbits = 256; else @@ -454,12 +456,13 @@ ec_deinit (void *opaque) mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, enum ecc_dialects dialect, + int flags, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { mpi_ec_t ctx; ctx = gcry_xcalloc (1, sizeof *ctx); - ec_p_init (ctx, model, dialect, p, a, b); + ec_p_init (ctx, model, dialect, flags, p, a, b); return ctx; } @@ -476,6 +479,7 @@ gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, enum gcry_mpi_ec_models model, enum ecc_dialects dialect, + int flags, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b) { gcry_ctx_t ctx; @@ -489,7 +493,7 @@ _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, if (!ctx) return gpg_err_code_from_syserror (); ec = _gcry_ctx_get_pointer (ctx, CONTEXT_TYPE_EC); - ec_p_init (ec, model, dialect, p, a, b); + ec_p_init (ec, model, dialect, flags, p, a, b); *r_ctx = ctx; return 0; diff --git a/src/ec-context.h b/src/ec-context.h index a118608..60ca759 100644 --- a/src/ec-context.h +++ b/src/ec-context.h @@ -27,6 +27,8 @@ struct mpi_ec_ctx_s enum ecc_dialects dialect; /* The ECC dialect used with the curve. */ + int flags; /* Public key flags (not always used). */ + unsigned int nbits; /* Number of bits. */ /* Domain parameters. Note that they may not all be set and if set diff --git a/src/mpi.h b/src/mpi.h index 15fb542..a5d805e 100644 --- a/src/mpi.h +++ b/src/mpi.h @@ -312,10 +312,12 @@ void _gcry_mpi_point_log (const char *name, mpi_point_t point, mpi_ec_t ctx); mpi_ec_t _gcry_mpi_ec_p_internal_new (enum gcry_mpi_ec_models model, enum ecc_dialects dialect, + int flags, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); gpg_err_code_t _gcry_mpi_ec_p_new (gcry_ctx_t *r_ctx, enum gcry_mpi_ec_models model, enum ecc_dialects dialect, + int flags, gcry_mpi_t p, gcry_mpi_t a, gcry_mpi_t b); void _gcry_mpi_ec_free (mpi_ec_t ctx); commit 630aca794ddf057fb7265b7dc346374743036af4 Author: Werner Koch Date: Mon Nov 4 16:47:13 2013 +0100 mpi: Add function gcry_mpi_set_opaque_copy. * src/gcrypt.h.in (gcry_mpi_set_opaque_copy): New. * src/visibility.c (gcry_mpi_set_opaque_copy): New. * src/visibility.h (gcry_mpi_set_opaque_copy): Mark visible. * src/libgcrypt.def, src/libgcrypt.vers: Add new API. * tests/mpitests.c (test_opaque): Add test. Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index d60e067..8010c37 100644 --- a/NEWS +++ b/NEWS @@ -75,6 +75,7 @@ Noteworthy changes in version 1.6.0 (unreleased) gcry_mpi_neg NEW. gcry_mpi_abs NEW. gcry_mpi_snatch NEW. + gcry_mpi_set_opaque_copy NEW. gcry_mpi_point_t NEW. gcry_mpi_point_new NEW. gcry_mpi_point_release NEW. diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 4a202dd..76cf0bd 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -4467,6 +4467,13 @@ valid functions are gcry_mpi_get_opaque and gcry_mpi_release. Use gcry_mpi_scan to convert a string of arbitrary bytes into an MPI. @end deftypefun + at deftypefun gcry_mpi_t gcry_mpi_set_opaque_copy (@w{gcry_mpi_t @var{a}}, @w{const void *@var{p}}, @w{unsigned int @var{nbits}}) + +Same as @code{gcry_mpi_set_opaque} but ownership of @var{p} is not +taken instead a copy of @var{p} is used. + at end deftypefun + + @deftypefun {void *} gcry_mpi_get_opaque (@w{gcry_mpi_t @var{a}}, @w{unsigned int *@var{nbits}}) Return a pointer to an opaque value stored in @var{a} and return its diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 2742556..234e8a4 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -726,10 +726,18 @@ void gcry_mpi_rshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n); void gcry_mpi_lshift (gcry_mpi_t x, gcry_mpi_t a, unsigned int n); /* Store NBITS of the value P points to in A and mark A as an opaque - value. WARNING: Never use an opaque MPI for anything thing else than + value. On success A received the the ownership of the value P. + WARNING: Never use an opaque MPI for anything thing else than gcry_mpi_release, gcry_mpi_get_opaque. */ gcry_mpi_t gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits); +/* Store NBITS of the value P points to in A and mark A as an opaque + value. The function takes a copy of the provided value P. + WARNING: Never use an opaque MPI for anything thing else than + gcry_mpi_release, gcry_mpi_get_opaque. */ +gcry_mpi_t gcry_mpi_set_opaque_copy (gcry_mpi_t a, + const void *p, unsigned int nbits); + /* Return a pointer to an opaque value stored in A and return its size in NBITS. Note that the returned pointer is still owned by A and that the function should never be used for an non-opaque MPI. */ diff --git a/src/libgcrypt.def b/src/libgcrypt.def index 64ba370..e2aba2b 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -259,5 +259,7 @@ EXPORTS gcry_cipher_gettag @227 gcry_cipher_checktag @228 + gcry_mpi_set_opaque_copy @229 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index 93eaa93..c3a09b8 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -88,7 +88,8 @@ GCRYPT_1.6 { gcry_mpi_mul_2exp; gcry_mpi_mul_ui; gcry_mpi_mulm; gcry_mpi_new; gcry_mpi_powm; gcry_mpi_print; gcry_mpi_randomize; gcry_mpi_release; gcry_mpi_rshift; gcry_mpi_scan; gcry_mpi_set; gcry_mpi_set_bit; - gcry_mpi_set_flag; gcry_mpi_set_highbit; gcry_mpi_set_opaque; + gcry_mpi_set_flag; gcry_mpi_set_highbit; + gcry_mpi_set_opaque; gcry_mpi_set_opaque_copy; gcry_mpi_set_ui; gcry_mpi_snew; gcry_mpi_sub; gcry_mpi_sub_ui; gcry_mpi_subm; gcry_mpi_swap; gcry_mpi_test_bit; gcry_mpi_lshift; gcry_mpi_snatch; diff --git a/src/visibility.c b/src/visibility.c index 1f7bb3a..852bdf9 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -629,6 +629,12 @@ gcry_mpi_set_opaque (gcry_mpi_t a, void *p, unsigned int nbits) return _gcry_mpi_set_opaque (a, p, nbits); } +gcry_mpi_t +gcry_mpi_set_opaque_copy (gcry_mpi_t a, const void *p, unsigned int nbits) +{ + return _gcry_mpi_set_opaque_copy (a, p, nbits); +} + void * gcry_mpi_get_opaque (gcry_mpi_t a, unsigned int *nbits) { diff --git a/src/visibility.h b/src/visibility.h index b2fa4c0..438db5b 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -603,6 +603,7 @@ MARK_VISIBLE (gcry_mpi_set_bit) MARK_VISIBLE (gcry_mpi_set_flag) MARK_VISIBLE (gcry_mpi_set_highbit) MARK_VISIBLE (gcry_mpi_set_opaque) +MARK_VISIBLEX(gcry_mpi_set_opaque_copy) MARK_VISIBLE (gcry_mpi_set_ui) MARK_VISIBLE (gcry_mpi_snew) MARK_VISIBLE (gcry_mpi_sub) @@ -632,8 +633,8 @@ MARK_VISIBLEX(_gcry_mpi_get_const) between a public and an internal version is that the internal version use gpg_err_code_t and the public version gpg_error_t. */ -#define gcry_sexp_extract_param _gcry_USE_THE_UNDERSCORED_FUNCTION - +#define gcry_sexp_extract_param _gcry_USE_THE_UNDERSCORED_FUNCTION +#define gcry_mpi_set_opaque_copy _gcry_USE_THE_UNDERSCORED_FUNCTION #endif /*!_GCRY_INCLUDED_BY_VISIBILITY_C*/ diff --git a/tests/mpitests.c b/tests/mpitests.c index c5c60d7..1c4edb6 100644 --- a/tests/mpitests.c +++ b/tests/mpitests.c @@ -213,6 +213,24 @@ test_opaque (void) if (debug) gcry_log_debugmpi ("mpi", a); + p = gcry_xstrdup ("This is a test buffer"); + a = gcry_mpi_set_opaque_copy (NULL, p, 21*8+1); + gcry_free (p); + + if (!gcry_mpi_get_flag (a, GCRYMPI_FLAG_OPAQUE)) + die ("opaque flag not set\n"); + + p = gcry_mpi_get_opaque (a, &nbits); + if (!p) + die ("gcry_mpi_get_opaque returned NULL\n"); + if (nbits != 21*8+1) + die ("gcry_mpi_get_opaque returned a changed bit size\n"); + if (strcmp (p, "This is a test buffer")) + die ("gcry_mpi_get_opaque returned a changed buffer\n"); + + if (debug) + gcry_log_debugmpi ("mpi", a); + gcry_mpi_release (a); } ----------------------------------------------------------------------- Summary of changes: NEWS | 1 + cipher/ecc-curves.c | 128 +++++++++++++++++++++++++++++++++------------------ cipher/ecc-ecdsa.c | 4 +- cipher/ecc-eddsa.c | 4 +- cipher/ecc-gost.c | 4 +- cipher/ecc-misc.c | 112 ++++++++++++++++++++++---------------------- cipher/ecc.c | 10 ++-- doc/gcrypt.texi | 9 +++- mpi/ec.c | 8 +++- src/ec-context.h | 2 + src/gcrypt.h.in | 10 +++- src/libgcrypt.def | 2 + src/libgcrypt.vers | 3 +- src/mpi.h | 2 + src/visibility.c | 6 +++ src/visibility.h | 5 +- tests/mpitests.c | 18 ++++++++ 17 files changed, 207 insertions(+), 121 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Tue Nov 5 19:10:03 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Tue, 05 Nov 2013 19:10:03 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-354-gb9fd398 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via b9fd3988b54b50109f4e7179e7fe0739bb1d97c5 (commit) from f09ffe8a4802af65a116e79eceeb1cb4ed4fa2f4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b9fd3988b54b50109f4e7179e7fe0739bb1d97c5 Author: Werner Koch Date: Tue Nov 5 19:00:09 2013 +0100 ecc: Require "eddsa" flag for curve Ed25519. * src/cipher.h (PUBKEY_FLAG_ECDSA): Remove. * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Remove "ecdsa". * cipher/ecc.c (ecc_generate, ecc_sign, ecc_verify): Require "eddsa" flag. * cipher/ecc-misc.c (_gcry_ecc_compute_public): Depend "eddsa" flag. * tests/benchmark.c, tests/keygen.c, tests/pubkey.c * tests/t-ed25519.c, tests/t-mpi-point.c: Adjust for changed flags. -- This changes make using ECDSA signatures the default for all curves. If another signing algorithm is to be used, the corresponding flag needs to be given. In particular the flags "eddsa" is now always required with curve Ed25519 to comply with the specs. This change makes the code better readable by not assuming a certain signature algorithm depending on the curve. Signed-off-by: Werner Koch diff --git a/cipher/ecc-misc.c b/cipher/ecc-misc.c index 6c75e75..0eb3391 100644 --- a/cipher/ecc-misc.c +++ b/cipher/ecc-misc.c @@ -265,7 +265,7 @@ _gcry_ecc_compute_public (mpi_point_t Q, mpi_ec_t ec) return NULL; if (ec->dialect == ECC_DIALECT_ED25519 - && !(ec->flags & PUBKEY_FLAG_ECDSA)) + && (ec->flags & PUBKEY_FLAG_EDDSA)) { gcry_mpi_t a; unsigned char *rawmpi = NULL; diff --git a/cipher/ecc.c b/cipher/ecc.c index 8bc8ea6..5578e05 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -404,7 +404,6 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) gcry_mpi_t public = NULL; gcry_mpi_t secret = NULL; int flags = 0; - int ed25519_with_ecdsa = 0; memset (&E, 0, sizeof E); memset (&sk, 0, sizeof sk); @@ -473,24 +472,10 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) x = mpi_new (0); y = mpi_new (0); - switch (E.dialect) - { - case ECC_DIALECT_STANDARD: - rc = nist_generate_key (&sk, &E, ctx, random_level, nbits); - break; - case ECC_DIALECT_ED25519: - if ((flags & PUBKEY_FLAG_ECDSA)) - { - ed25519_with_ecdsa = 1; - rc = nist_generate_key (&sk, &E, ctx, random_level, nbits); - } - else - rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, random_level); - break; - default: - rc = GPG_ERR_INTERNAL; - break; - } + if ((flags & PUBKEY_FLAG_EDDSA)) + rc = _gcry_ecc_eddsa_genkey (&sk, &E, ctx, random_level); + else + rc = nist_generate_key (&sk, &E, ctx, random_level, nbits); if (rc) goto leave; @@ -524,15 +509,15 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) goto leave; } - if ((flags & PUBKEY_FLAG_NOPARAM) || ed25519_with_ecdsa) + if ((flags & PUBKEY_FLAG_NOPARAM) || (flags & PUBKEY_FLAG_EDDSA)) { rc = gcry_sexp_build (&curve_flags, NULL, - ((flags & PUBKEY_FLAG_NOPARAM) && ed25519_with_ecdsa)? - "(flags noparam ecdsa)" : + ((flags & PUBKEY_FLAG_NOPARAM) && (flags & PUBKEY_FLAG_EDDSA))? + "(flags noparam eddsa)" : ((flags & PUBKEY_FLAG_NOPARAM))? "(flags noparam)" : - "(flags ecdsa)"); + "(flags eddsa)"); if (rc) goto leave; } @@ -573,8 +558,8 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) log_printmpi ("ecgen result n", sk.E.n); log_printmpi ("ecgen result Q", public); log_printmpi ("ecgen result d", secret); - if (ed25519_with_ecdsa) - log_debug ("ecgen result using Ed25519/ECDSA\n"); + if ((flags & PUBKEY_FLAG_EDDSA)) + log_debug ("ecgen result using Ed25519+EdDSA\n"); } leave: @@ -773,8 +758,7 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) log_debug ("ecc_sign info: %s/%s%s\n", _gcry_ecc_model2str (sk.E.model), _gcry_ecc_dialect2str (sk.E.dialect), - (sk.E.dialect == ECC_DIALECT_ED25519 - && (ctx.flags & PUBKEY_FLAG_ECDSA))? "ECDSA":""); + (ctx.flags & PUBKEY_FLAG_EDDSA)? "+EdDSA":""); if (sk.E.name) log_debug ("ecc_sign name: %s\n", sk.E.name); log_printmpi ("ecc_sign p", sk.E.p); @@ -940,8 +924,7 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) log_debug ("ecc_verify info: %s/%s%s\n", _gcry_ecc_model2str (pk.E.model), _gcry_ecc_dialect2str (pk.E.dialect), - (pk.E.dialect == ECC_DIALECT_ED25519 - && !(sigflags & PUBKEY_FLAG_EDDSA))? "/ECDSA":""); + (sigflags & PUBKEY_FLAG_EDDSA)? "+EdDSA":""); if (pk.E.name) log_debug ("ecc_verify name: %s\n", pk.E.name); log_printmpi ("ecc_verify p", pk.E.p); diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index 88d6bb6..a91e66f 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -107,10 +107,6 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_RAW; flags |= PUBKEY_FLAG_EDDSA; } - else if (!memcmp (s, "ecdsa", 5)) - { - flags |= PUBKEY_FLAG_ECDSA; - } else if (!memcmp (s, "pkcs1", 5) && encoding == PUBKEY_ENC_UNKNOWN) { encoding = PUBKEY_ENC_PKCS1; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 9c695e0..03ace83 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2251,15 +2251,10 @@ Use RSA-OAEP padding for encryption. @cindex PSS Use RSA-PSS padding for signing. - at item ecdsa - at cindex ECDSA -Create an ECDSA public key instead of using the default key generation -of the specified curve. - @item eddsa @cindex EdDSA -Use the EdDSA scheme instead of the default signature algorithm of the -used curve. +Use the EdDSA scheme signing instead of the default ECDSA algorithm. +Note that the EdDSA uses a special form of the public key. @item rfc6979 @cindex RFC6979 @@ -2854,7 +2849,7 @@ is in general not recommended. @example (genkey (ecc - (flags noparam transient-key ecdsa))) + (flags noparam transient-key))) @end example @item transient-key @@ -2899,12 +2894,12 @@ elliptic curve key generation: (public-key (ecc (curve Ed25519) - (flags noparam) + (flags noparam eddsa) (q @var{q-value}))) (private-key (ecc (curve Ed25519) - (flags noparam) + (flags noparam eddsa) (q @var{q-value}) (d @var{d-value})))) @end example diff --git a/src/cipher.h b/src/cipher.h index 551dc66..5ac891e 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -35,11 +35,10 @@ #define PUBKEY_FLAG_USE_X931 (1 << 6) #define PUBKEY_FLAG_USE_FIPS186 (1 << 7) #define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) -#define PUBKEY_FLAG_ECDSA (1 << 9) -#define PUBKEY_FLAG_EDDSA (1 << 10) -#define PUBKEY_FLAG_GOST (1 << 11) -#define PUBKEY_FLAG_NOPARAM (1 << 12) -#define PUBKEY_FLAG_COMP (1 << 12) +#define PUBKEY_FLAG_NOPARAM (1 << 9) +#define PUBKEY_FLAG_COMP (1 << 10) +#define PUBKEY_FLAG_EDDSA (1 << 11) +#define PUBKEY_FLAG_GOST (1 << 12) enum pk_operation diff --git a/tests/benchmark.c b/tests/benchmark.c index 8326ab2..93874fa 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -997,7 +997,8 @@ ecc_bench (int iterations, int print_header) if (is_ed25519) err = gcry_sexp_build (&key_spec, NULL, - "(genkey (ecdsa (curve \"Ed25519\")))"); + "(genkey (ecdsa (curve \"Ed25519\")" + "(flags eddsa)))"); else if (is_gost) err = gcry_sexp_build (&key_spec, NULL, "(genkey (ecdsa (curve %s)))", diff --git a/tests/keygen.c b/tests/keygen.c index 18fe211..5879393 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -374,9 +374,14 @@ check_ecc_keys (void) { if (verbose) show ("creating ECC key using curve %s\n", curves[testno]); - rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve %s)(flags noparam)))", - curves[testno]); + if (!strcmp (curves[testno], "Ed25519")) + rc = gcry_sexp_build (&keyparm, NULL, + "(genkey(ecc(curve %s)(flags noparam eddsa)))", + curves[testno]); + else + rc = gcry_sexp_build (&keyparm, NULL, + "(genkey(ecc(curve %s)(flags noparam)))", + curves[testno]); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); @@ -398,8 +403,7 @@ check_ecc_keys (void) if (verbose) show ("creating ECC key using curve Ed25519 for ECDSA\n"); - rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve Ed25519)(flags ecdsa)))"); + rc = gcry_sexp_build (&keyparm, NULL, "(genkey(ecc(curve Ed25519)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); @@ -414,7 +418,7 @@ check_ecc_keys (void) if (verbose) show ("creating ECC key using curve Ed25519 for ECDSA\n"); rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve Ed25519)(flags noparam ecdsa)))"); + "(genkey(ecc(curve Ed25519)(flags noparam)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); diff --git a/tests/pubkey.c b/tests/pubkey.c index e41050c..4e12dfd 100644 --- a/tests/pubkey.c +++ b/tests/pubkey.c @@ -1057,7 +1057,7 @@ check_ed25519ecdsa_sample_key (void) " (q #047b57c2c1d3ded93332b52d588dd45863478b658387413a718779c0dd1a6d95#)" "))"; static const char hash_string[] = - "(data (flags ecdsa rfc6979)\n" + "(data (flags rfc6979)\n" " (hash sha256 #00112233445566778899AABBCCDDEEFF" /* */ "000102030405060708090A0B0C0D0E0F#))"; diff --git a/tests/t-ed25519.c b/tests/t-ed25519.c index be200fa..465a217 100644 --- a/tests/t-ed25519.c +++ b/tests/t-ed25519.c @@ -288,6 +288,7 @@ one_test (int testno, const char *sk, const char *pk, "(private-key" " (ecc" " (curve \"Ed25519\")" + " (flags eddsa)" " (q %b)" " (d %b)))", (int)buflen2, buffer2, @@ -297,6 +298,7 @@ one_test (int testno, const char *sk, const char *pk, "(private-key" " (ecc" " (curve \"Ed25519\")" + " (flags eddsa)" " (d %b)))", (int)buflen, buffer); if (err) @@ -310,6 +312,7 @@ one_test (int testno, const char *sk, const char *pk, "(public-key" " (ecc" " (curve \"Ed25519\")" + " (flags eddsa)" " (q %b)))", (int)buflen2, buffer2))) { fail ("error building s-exp for test %d, %s: %s", diff --git a/tests/t-mpi-point.c b/tests/t-mpi-point.c index a345cbc..ae52601 100644 --- a/tests/t-mpi-point.c +++ b/tests/t-mpi-point.c @@ -639,7 +639,7 @@ context_param (void) q = hex2mpi (sample_ed25519_q); gcry_sexp_release (keyparam); err = gcry_sexp_build (&keyparam, NULL, - "(public-key(ecc(curve %s)(q %m)))", + "(public-key(ecc(curve %s)(flags eddsa)(q %m)))", "Ed25519", q); if (err) die ("gcry_sexp_build failed: %s\n", gpg_strerror (err)); @@ -666,7 +666,7 @@ context_param (void) "Ed25519", ctx); get_and_cmp_mpi ("q at eddsa", sample_ed25519_q_eddsa, "Ed25519", ctx); - /* Set d tosee whether Q is correctly re-computed. */ + /* Set d to see whether Q is correctly re-computed. */ d = hex2mpi (sample_ed25519_d); err = gcry_mpi_ec_set_mpi ("d", d, ctx); if (err) ----------------------------------------------------------------------- Summary of changes: cipher/ecc-misc.c | 2 +- cipher/ecc.c | 41 ++++++++++++----------------------------- cipher/pubkey-util.c | 4 ---- doc/gcrypt.texi | 15 +++++---------- src/cipher.h | 9 ++++----- tests/benchmark.c | 3 ++- tests/keygen.c | 16 ++++++++++------ tests/pubkey.c | 2 +- tests/t-ed25519.c | 3 +++ tests/t-mpi-point.c | 4 ++-- 10 files changed, 40 insertions(+), 59 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Wed Nov 6 08:57:33 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Wed, 06 Nov 2013 08:57:33 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-355-g6d169b6 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 6d169b654c7ff04c10f73afe80b2c70cefa410c1 (commit) from b9fd3988b54b50109f4e7179e7fe0739bb1d97c5 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 6d169b654c7ff04c10f73afe80b2c70cefa410c1 Author: Werner Koch Date: Wed Nov 6 08:56:02 2013 +0100 pubkey: Add forward compatibility feature. * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Add "igninvflag". -- If future versions of Libgcrypt want to add optional flags to a pubkey s-expression, they may use the "igninvflag" flag to make the flag parser ignore flags it does not know about. Signed-off-by: Werner Koch diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index a91e66f..a591c0d 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -60,6 +60,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, int i; int encoding = PUBKEY_ENC_UNKNOWN; int flags = 0; + int igninvflag = 0; for (i=list?gcry_sexp_length (list)-1:0; i > 0; i--) { @@ -80,7 +81,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_RAW; flags |= PUBKEY_FLAG_RAW_FLAG; /* Explicitly given. */ } - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -97,7 +98,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_RAW; flags |= PUBKEY_FLAG_GOST; } - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -112,7 +113,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_PKCS1; flags |= PUBKEY_FLAG_FIXEDLEN; } - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -121,23 +122,28 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, flags |= PUBKEY_FLAG_RFC6979; else if (!memcmp (s, "noparam", 7)) flags |= PUBKEY_FLAG_NOPARAM; - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; case 8: if (!memcmp (s, "use-x931", 8)) flags |= PUBKEY_FLAG_USE_X931; - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; + case 10: + if (!memcmp (s, "igninvflag", 10)) + igninvflag = 1; + break; + case 11: if (!memcmp (s, "no-blinding", 11)) flags |= PUBKEY_FLAG_NO_BLINDING; else if (!memcmp (s, "use-fips186", 11)) flags |= PUBKEY_FLAG_USE_FIPS186; - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -146,12 +152,13 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, flags |= PUBKEY_FLAG_USE_FIPS186_2; else if (!memcmp (s, "transient-key", 13)) flags |= PUBKEY_FLAG_TRANSIENT_KEY; - else + else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; default: - rc = GPG_ERR_INV_FLAG; + if (!igninvflag) + rc = GPG_ERR_INV_FLAG; break; } } ----------------------------------------------------------------------- Summary of changes: cipher/pubkey-util.c | 23 +++++++++++++++-------- 1 file changed, 15 insertions(+), 8 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wachs at net.in.tum.de Wed Nov 6 14:38:43 2013 From: wachs at net.in.tum.de (Matthias Wachs) Date: Wed, 06 Nov 2013 14:38:43 +0100 Subject: compile errors with camellia Message-ID: <527A4663.5030608@net.in.tum.de> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi this compile issue occurs on two different systems: efikamx 2.6.31-008-efikamx #1 Sun Jun 27 18:38:00 CDT 2010 armv7l GNU/Linux ac_cv_build=armv7l-unknown-linux-gnueabi Darwin luke.net.in.tum.de 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 configure.log: ac_cv_build=x86_64-apple-darwin11.3.0 libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src - -I/opt/local/include -I/opt/local/include -g -O2 -Wall -Wcast-align - -Wshadow -Wstrict-prototypes -Wformat -Wno-format-y2k - -Wformat-security -W -Wextra -Wbad-function-cast -Wwrite-strings - -Wdeclaration-after-statement -Wno-missing-field-initializers - -Wno-sign-compare -Wpointer-arith -MT camellia.lo -MD -MP -MF .deps/camellia.Tpo -c camellia.c -fno-common -DPIC -o .libs/camellia.o camellia.c:32: error: redefinition of typedef 'u32' ../src/types.h:81: error: previous declaration of 'u32' was here Cheers, Matthias - -- Dipl.-Inf. Matthias Wachs Free Secure Network Systems Group Technische Universitaet Muenchen Chair for Network Architectures and Services Institute for Informatics / I8 Tel: +49 89 289 18037 Boltzmannstr. 3 / Room 03.05.042 Fax: +49 89 289 18033 D-85748 Garching b. Muenchen, Germany Email: wachs at net.in.tum.de -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSekZjAAoJEEFv6YGnAaM2+bMH/2indSCKEmihoQLkin1DzioT KRZv/yunrwaE78wiKswJqM+nP8HONGD7ofoy+SHHTmm2g4Rh0DV2t6IZnAYhCwvj U+gt5a3llCRphjoDDUZth7Oxy/xNiLc5tTP5ODVm4trCHo8QqQFNMtQzWc8HPBQo HYs8iXj7qV1ipoQIsoocjdvtJz0qD8WLgVuBG+/oZc4Pmkree2vgFTUrkqsUm7iP O8RN3CC9WSrL0iPfqN9NTZCSnHPrNo1pwCPvztGOxQO37HrdyNAYXBlkV2eETBUs D/lQeNSDSzJcZU76+VYewTd0UGRjF1+0FsCPxpm2EE9M3V1mydn6sH8MFGl+m04= =eeYD -----END PGP SIGNATURE----- From cvs at cvs.gnupg.org Wed Nov 6 15:52:46 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Wed, 06 Nov 2013 15:52:46 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-356-g84bcb40 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 84bcb400e7db7268abfc29b5ab1513b0c063b293 (commit) from 6d169b654c7ff04c10f73afe80b2c70cefa410c1 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 84bcb400e7db7268abfc29b5ab1513b0c063b293 Author: Jussi Kivilinna Date: Wed Nov 6 16:51:55 2013 +0200 Fix 'u32' build error with Camellia * cipher/camellia.c: Add include for and "types.h". (u32): Remove. (u8): Typedef as 'byte'. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia.c b/cipher/camellia.c index 9067246..e7085a7 100644 --- a/cipher/camellia.c +++ b/cipher/camellia.c @@ -22,15 +22,15 @@ * http://info.isl.ntt.co.jp/crypt/eng/camellia/specifications.html */ +#include #include #include +#include "types.h" #include "bufhelp.h" #include "camellia.h" -/* u32 must be 32bit word */ -typedef unsigned int u32; -typedef unsigned char u8; +typedef byte u8; /* key constants */ ----------------------------------------------------------------------- Summary of changes: cipher/camellia.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Wed Nov 6 15:57:25 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 06 Nov 2013 16:57:25 +0200 Subject: compile errors with camellia In-Reply-To: <527A4663.5030608@net.in.tum.de> References: <527A4663.5030608@net.in.tum.de> Message-ID: <527A58D5.7090205@iki.fi> On 06.11.2013 15:38, Matthias Wachs wrote: > Hi > > this compile issue occurs on two different systems: Hello, Recent addition of #include "bufhelp.h" seems to mess up things on some system. Does the attached patch help? I've pushed patch to libgcrypt repository too. -Jussi > > efikamx 2.6.31-008-efikamx #1 Sun Jun 27 18:38:00 CDT 2010 armv7l > GNU/Linux > ac_cv_build=armv7l-unknown-linux-gnueabi > > Darwin luke.net.in.tum.de 11.3.0 Darwin Kernel Version 11.3.0: Thu Jan > 12 18:47:41 PST 2012; root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 > > configure.log: > ac_cv_build=x86_64-apple-darwin11.3.0 > > > libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src -I../src > -I/opt/local/include -I/opt/local/include -g -O2 -Wall -Wcast-align > -Wshadow -Wstrict-prototypes -Wformat -Wno-format-y2k > -Wformat-security -W -Wextra -Wbad-function-cast -Wwrite-strings > -Wdeclaration-after-statement -Wno-missing-field-initializers > -Wno-sign-compare -Wpointer-arith -MT camellia.lo -MD -MP -MF > .deps/camellia.Tpo -c camellia.c -fno-common -DPIC -o .libs/camellia.o > camellia.c:32: error: redefinition of typedef 'u32' > ../src/types.h:81: error: previous declaration of 'u32' was here > > Cheers, > > Matthias > > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- A non-text attachment was scrubbed... Name: 10-fix-build-error-with-camellia.patch Type: text/x-patch Size: 820 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 730 bytes Desc: OpenPGP digital signature URL: From wachs at net.in.tum.de Wed Nov 6 16:29:17 2013 From: wachs at net.in.tum.de (Matthias Wachs) Date: Wed, 06 Nov 2013 16:29:17 +0100 Subject: compile errors with camellia In-Reply-To: <527A58D5.7090205@iki.fi> References: <527A4663.5030608@net.in.tum.de> <527A58D5.7090205@iki.fi> Message-ID: <527A604D.6060308@net.in.tum.de> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Hi thanks a lot! The patch fixed the issue. There are two more issues we have on our build systems: On our sparc machine: 3.2.0-4-sparc64-smp #1 SMP Debian 3.2.46-1 sparc64 ac_cv_build=sparc64-unknown-linux-gnu We get: libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden - -Wall -Wcast-align -Wshadow -Wstrict-prototypes -Wformat - -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast - -Wwrite-strings -Wdeclaration-after-statement - -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith -o .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so -L/usr/local/lib /usr/local/lib/libgpg-error.so ./.libs/libgcrypt.so: undefined reference to `__udiv_qrnnd' collect2: error: ld returned 1 exit status On our freebsd 9.1 machine: FreeBSD freebsd91 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec 4 09:23:10 UTC 2012 ac_cv_build=x86_64-unknown-freebsd9.1 libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden - -Wall -o .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so - -L/usr/local/lib /usr/local/lib/libgpg-error.so /usr/local/lib/libintl.so /usr/local/lib/libiconv.so -Wl,-rpath - -Wl,/usr/local/lib ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap32' ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap64' *** [mpicalc] Error code 1 The sparcbot may be an old known issue, but the issue on freebsd is recent... TIA! - -Matthias On 11/06/2013 03:57 PM, Jussi Kivilinna wrote: > On 06.11.2013 15:38, Matthias Wachs wrote: >> Hi >> >> this compile issue occurs on two different systems: > > Hello, > > Recent addition of #include "bufhelp.h" seems to mess up things on > some system. > > Does the attached patch help? > > I've pushed patch to libgcrypt repository too. > > -Jussi > >> >> efikamx 2.6.31-008-efikamx #1 Sun Jun 27 18:38:00 CDT 2010 >> armv7l GNU/Linux ac_cv_build=armv7l-unknown-linux-gnueabi >> >> Darwin luke.net.in.tum.de 11.3.0 Darwin Kernel Version 11.3.0: >> Thu Jan 12 18:47:41 PST 2012; >> root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 >> >> configure.log: ac_cv_build=x86_64-apple-darwin11.3.0 >> >> >> libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src >> -I../src -I/opt/local/include -I/opt/local/include -g -O2 -Wall >> -Wcast-align -Wshadow -Wstrict-prototypes -Wformat >> -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast >> -Wwrite-strings -Wdeclaration-after-statement >> -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith >> -MT camellia.lo -MD -MP -MF .deps/camellia.Tpo -c camellia.c >> -fno-common -DPIC -o .libs/camellia.o camellia.c:32: error: >> redefinition of typedef 'u32' ../src/types.h:81: error: previous >> declaration of 'u32' was here >> >> Cheers, >> >> Matthias >> >> >> >> _______________________________________________ Gcrypt-devel >> mailing list Gcrypt-devel at gnupg.org >> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >> > - -- Dipl.-Inf. Matthias Wachs Free Secure Network Systems Group Technische Universitaet Muenchen Chair for Network Architectures and Services Institute for Informatics / I8 Tel: +49 89 289 18037 Boltzmannstr. 3 / Room 03.05.042 Fax: +49 89 289 18033 D-85748 Garching b. Muenchen, Germany Email: wachs at net.in.tum.de -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) Comment: Using GnuPG with Thunderbird - http://www.enigmail.net/ iQEcBAEBAgAGBQJSemBMAAoJEEFv6YGnAaM20DoH+wa7XfnZdYkE48ePoMgQs7Mx SkZZcAd2U/4aBf3K6WGgp99atyv7RBD9il6s1h9NANMZsHp/4HctkFd2YV5w8Uwk gIwKI51ELQK3Byj8ydhmpEF9Ihd+yuTzty/z+aIT0F35XNtJTZTWjMIJoDrAJUZO bxkisqXEGRPSIwqC/smZfGsQUxCsFi863OuWwjPt57A8tIjsQPuhyMnJb0JgOeo2 FoU1g/D3GlxMcF2oKdKFqhhEcKlSRUj7GB94xtSO/v9eH4sdEvyUXfWoMBoOeEgx 1/3pbusQGQb3WzSS+pWZQmmMNUSXDPMTZvH2e+kFuYvy1LULNBYyT4z0b4UJN/o= =I2yX -----END PGP SIGNATURE----- From cvs at cvs.gnupg.org Wed Nov 6 18:22:37 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Wed, 06 Nov 2013 18:22:37 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-357-g2590a5d Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 2590a5df6f5fc884614c8c379324027d2d61b9b5 (commit) from 84bcb400e7db7268abfc29b5ab1513b0c063b293 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 2590a5df6f5fc884614c8c379324027d2d61b9b5 Author: Jussi Kivilinna Date: Wed Nov 6 19:05:09 2013 +0200 Fix __builtin_bswap32/64 checks * configure.ac (gcry_cv_have_builtin_bswap32) (gcry_cv_have_builtin_bswap64): Change compile checks to link checks. -- Patch changes compile checks to link checks for __builtin_bswap(32|64). Compiling obviously works with missing functions, linking not so much. Signed-off-by: Jussi Kivilinna diff --git a/configure.ac b/configure.ac index e3471d0..c4f8776 100644 --- a/configure.ac +++ b/configure.ac @@ -779,8 +779,8 @@ AC_SUBST(FALLBACK_SOCKLEN_T) AC_CACHE_CHECK(for __builtin_bswap32, [gcry_cv_have_builtin_bswap32], [gcry_cv_have_builtin_bswap32=no - AC_COMPILE_IFELSE([AC_LANG_SOURCE( - [[int foo(int x) { return __builtin_bswap32(x); }]])], + AC_LINK_IFELSE([AC_LANG_PROGRAM([], + [int x = 0; int y = __builtin_bswap32(x); return y;])], [gcry_cv_have_builtin_bswap32=yes])]) if test "$gcry_cv_have_builtin_bswap32" = "yes" ; then AC_DEFINE(HAVE_BUILTIN_BSWAP32,1, @@ -794,8 +794,8 @@ fi AC_CACHE_CHECK(for __builtin_bswap64, [gcry_cv_have_builtin_bswap64], [gcry_cv_have_builtin_bswap64=no - AC_COMPILE_IFELSE([AC_LANG_SOURCE( - [[int foo(int x) { return __builtin_bswap64(x); }]])], + AC_LINK_IFELSE([AC_LANG_PROGRAM([], + [long long x = 0; long long y = __builtin_bswap64(x); return y;])], [gcry_cv_have_builtin_bswap64=yes])]) if test "$gcry_cv_have_builtin_bswap64" = "yes" ; then AC_DEFINE(HAVE_BUILTIN_BSWAP64,1, ----------------------------------------------------------------------- Summary of changes: configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Wed Nov 6 21:09:47 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 06 Nov 2013 22:09:47 +0200 Subject: compile errors with camellia In-Reply-To: <527A604D.6060308@net.in.tum.de> References: <527A4663.5030608@net.in.tum.de> <527A58D5.7090205@iki.fi> <527A604D.6060308@net.in.tum.de> Message-ID: <527AA20B.8020601@iki.fi> On 06.11.2013 17:29, Matthias Wachs wrote: > Hi > > thanks a lot! The patch fixed the issue. > > There are two more issues we have on our build systems: > > On our sparc machine: > > 3.2.0-4-sparc64-smp #1 SMP Debian 3.2.46-1 sparc64 > ac_cv_build=sparc64-unknown-linux-gnu > > We get: > > libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden > -Wall -Wcast-align -Wshadow -Wstrict-prototypes -Wformat > -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast > -Wwrite-strings -Wdeclaration-after-statement > -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith -o > .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so -L/usr/local/lib > /usr/local/lib/libgpg-error.so > ./.libs/libgcrypt.so: undefined reference to `__udiv_qrnnd' > collect2: error: ld returned 1 exit status > Can you send the output of "gcc -dM -E - < /dev/null" on this machine? Also the output of 'configure' for libgcrypt would be interesting to see. > > On our freebsd 9.1 machine: > > FreeBSD freebsd91 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec > 4 09:23:10 UTC 2012 > ac_cv_build=x86_64-unknown-freebsd9.1 > > libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden > -Wall -o .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so > -L/usr/local/lib /usr/local/lib/libgpg-error.so > /usr/local/lib/libintl.so /usr/local/lib/libiconv.so -Wl,-rpath > -Wl,/usr/local/lib > ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap32' > ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap64' > *** [mpicalc] Error code 1 Fix for this one is in the repository now. -Jussi > > > The sparcbot may be an old known issue, but the issue on freebsd is > recent... > > TIA! > -Matthias > > > On 11/06/2013 03:57 PM, Jussi Kivilinna wrote: >> On 06.11.2013 15:38, Matthias Wachs wrote: >>> Hi >>> >>> this compile issue occurs on two different systems: > >> Hello, > >> Recent addition of #include "bufhelp.h" seems to mess up things on >> some system. > >> Does the attached patch help? > >> I've pushed patch to libgcrypt repository too. > >> -Jussi > >>> >>> efikamx 2.6.31-008-efikamx #1 Sun Jun 27 18:38:00 CDT 2010 >>> armv7l GNU/Linux ac_cv_build=armv7l-unknown-linux-gnueabi >>> >>> Darwin luke.net.in.tum.de 11.3.0 Darwin Kernel Version 11.3.0: >>> Thu Jan 12 18:47:41 PST 2012; >>> root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 >>> >>> configure.log: ac_cv_build=x86_64-apple-darwin11.3.0 >>> >>> >>> libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src >>> -I../src -I/opt/local/include -I/opt/local/include -g -O2 -Wall >>> -Wcast-align -Wshadow -Wstrict-prototypes -Wformat >>> -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast >>> -Wwrite-strings -Wdeclaration-after-statement >>> -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith >>> -MT camellia.lo -MD -MP -MF .deps/camellia.Tpo -c camellia.c >>> -fno-common -DPIC -o .libs/camellia.o camellia.c:32: error: >>> redefinition of typedef 'u32' ../src/types.h:81: error: previous >>> declaration of 'u32' was here >>> >>> Cheers, >>> >>> Matthias >>> >>> >>> >>> _______________________________________________ Gcrypt-devel >>> mailing list Gcrypt-devel at gnupg.org >>> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >>> > > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 730 bytes Desc: OpenPGP digital signature URL: From sftp.mtuci at gmail.com Wed Nov 6 20:45:26 2013 From: sftp.mtuci at gmail.com (Sergey V.) Date: Wed, 06 Nov 2013 23:45:26 +0400 Subject: cipher/gost28147: optimization: use precomputed S-box Message-ID: <5904457.oKotRVip6i@darkstar> Hi all. Some time ago I wrote gost28147-89 implementation [1]. Since I noteced that libgcrypt now has own implementation I want to implement optimization which I have in my code [2]. This optimisation composes 8->8 bit S-boxes from 4-4 S-boxes, then it makes bitwise shifts and bitwise rotate. So in the round function we no need to do this operations. First, I tryed to add S-box precomputation into gost_set_subst() function. But this approach didn't increase benchmark results. It seems small data portions used by benchmark for encryption, that way it reinitializes ctx and recompute S-boxes for each small portion of data, right? If i'm right then benchmark results are not objective. After that I removed S-boxes computing and gost_set_subst() function has been removed too and I add complete precomputed S-box tables instead. This approach has led to about 1.4 times increase of benchmark results. Patch in attachement. Before this patch: GOST28147 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 24.00 ns/B 39.74 MiB/s - c/B ECB dec | 26.41 ns/B 36.11 MiB/s - c/B CBC enc | 24.57 ns/B 38.81 MiB/s - c/B CBC dec | 26.58 ns/B 35.88 MiB/s - c/B CFB enc | 24.79 ns/B 38.46 MiB/s - c/B CFB dec | 24.72 ns/B 38.57 MiB/s - c/B OFB enc | 24.38 ns/B 39.12 MiB/s - c/B OFB dec | 24.35 ns/B 39.16 MiB/s - c/B CTR enc | 24.83 ns/B 38.41 MiB/s - c/B CTR dec | 25.27 ns/B 37.73 MiB/s - c/B After: GOST28147 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 16.29 ns/B 58.55 MiB/s - c/B ECB dec | 16.30 ns/B 58.50 MiB/s - c/B CBC enc | 16.94 ns/B 56.29 MiB/s - c/B CBC dec | 16.81 ns/B 56.72 MiB/s - c/B CFB enc | 17.13 ns/B 55.66 MiB/s - c/B CFB dec | 16.84 ns/B 56.63 MiB/s - c/B OFB enc | 16.69 ns/B 57.13 MiB/s - c/B OFB dec | 16.71 ns/B 57.08 MiB/s - c/B CTR enc | 17.01 ns/B 56.06 MiB/s - c/B CTR dec | 17.05 ns/B 55.93 MiB/s - c/B Thanks! [1] https://github.com/sftp/gost28147 [2] https://github.com/sftp/gost28147/commit/654804e -------------- next part -------------- A non-text attachment was scrubbed... Name: 0001-cipher-gost28147-optimization-use-precomputed-S-box.patch Type: text/x-patch Size: 19927 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: This is a digitally signed message part. URL: From wachs at net.in.tum.de Wed Nov 6 21:41:34 2013 From: wachs at net.in.tum.de (Matthias Wachs) Date: Wed, 06 Nov 2013 21:41:34 +0100 Subject: compile errors with camellia In-Reply-To: <527AA20B.8020601@iki.fi> References: <527A4663.5030608@net.in.tum.de> <527A58D5.7090205@iki.fi> <527A604D.6060308@net.in.tum.de> <527AA20B.8020601@iki.fi> Message-ID: <527AA97E.8030704@net.in.tum.de> The freebsd issue is fixed. You can find the logs attached. -Matthias On 11/06/2013 09:09 PM, Jussi Kivilinna wrote: > On 06.11.2013 17:29, Matthias Wachs wrote: >> Hi >> >> thanks a lot! The patch fixed the issue. >> >> There are two more issues we have on our build systems: >> >> On our sparc machine: >> >> 3.2.0-4-sparc64-smp #1 SMP Debian 3.2.46-1 sparc64 >> ac_cv_build=sparc64-unknown-linux-gnu >> >> We get: >> >> libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden >> -Wall -Wcast-align -Wshadow -Wstrict-prototypes -Wformat >> -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast >> -Wwrite-strings -Wdeclaration-after-statement >> -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith -o >> .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so -L/usr/local/lib >> /usr/local/lib/libgpg-error.so >> ./.libs/libgcrypt.so: undefined reference to `__udiv_qrnnd' >> collect2: error: ld returned 1 exit status >> > > Can you send the output of "gcc -dM -E - < /dev/null" on this machine? > > Also the output of 'configure' for libgcrypt would be interesting to > see. > >> >> On our freebsd 9.1 machine: >> >> FreeBSD freebsd91 9.1-RELEASE FreeBSD 9.1-RELEASE #0 r243825: Tue Dec >> 4 09:23:10 UTC 2012 >> ac_cv_build=x86_64-unknown-freebsd9.1 >> >> libtool: link: gcc -I/usr/local/include -g -O2 -fvisibility=hidden >> -Wall -o .libs/mpicalc mpicalc-mpicalc.o ./.libs/libgcrypt.so >> -L/usr/local/lib /usr/local/lib/libgpg-error.so >> /usr/local/lib/libintl.so /usr/local/lib/libiconv.so -Wl,-rpath >> -Wl,/usr/local/lib >> ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap32' >> ./.libs/libgcrypt.so: undefined reference to `__builtin_bswap64' >> *** [mpicalc] Error code 1 > > Fix for this one is in the repository now. > > -Jussi > >> >> >> The sparcbot may be an old known issue, but the issue on freebsd is >> recent... >> >> TIA! >> -Matthias >> >> >> On 11/06/2013 03:57 PM, Jussi Kivilinna wrote: >>> On 06.11.2013 15:38, Matthias Wachs wrote: >>>> Hi >>>> >>>> this compile issue occurs on two different systems: >> >>> Hello, >> >>> Recent addition of #include "bufhelp.h" seems to mess up things on >>> some system. >> >>> Does the attached patch help? >> >>> I've pushed patch to libgcrypt repository too. >> >>> -Jussi >> >>>> >>>> efikamx 2.6.31-008-efikamx #1 Sun Jun 27 18:38:00 CDT 2010 >>>> armv7l GNU/Linux ac_cv_build=armv7l-unknown-linux-gnueabi >>>> >>>> Darwin luke.net.in.tum.de 11.3.0 Darwin Kernel Version 11.3.0: >>>> Thu Jan 12 18:47:41 PST 2012; >>>> root:xnu-1699.24.23~1/RELEASE_X86_64 x86_64 >>>> >>>> configure.log: ac_cv_build=x86_64-apple-darwin11.3.0 >>>> >>>> >>>> libtool: compile: gcc -DHAVE_CONFIG_H -I. -I.. -I../src >>>> -I../src -I/opt/local/include -I/opt/local/include -g -O2 -Wall >>>> -Wcast-align -Wshadow -Wstrict-prototypes -Wformat >>>> -Wno-format-y2k -Wformat-security -W -Wextra -Wbad-function-cast >>>> -Wwrite-strings -Wdeclaration-after-statement >>>> -Wno-missing-field-initializers -Wno-sign-compare -Wpointer-arith >>>> -MT camellia.lo -MD -MP -MF .deps/camellia.Tpo -c camellia.c >>>> -fno-common -DPIC -o .libs/camellia.o camellia.c:32: error: >>>> redefinition of typedef 'u32' ../src/types.h:81: error: previous >>>> declaration of 'u32' was here >>>> >>>> Cheers, >>>> >>>> Matthias >>>> >>>> >>>> >>>> _______________________________________________ Gcrypt-devel >>>> mailing list Gcrypt-devel at gnupg.org >>>> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >>>> >> >> >> >> _______________________________________________ >> Gcrypt-devel mailing list >> Gcrypt-devel at gnupg.org >> http://lists.gnupg.org/mailman/listinfo/gcrypt-devel >> > > -------------- next part -------------- A non-text attachment was scrubbed... Name: config.log Type: text/x-log Size: 102253 bytes Desc: not available URL: -------------- next part -------------- root at mamasparc:~# gcc -dM -E - < /dev/null #define __DBL_MIN_EXP__ (-1021) #define __UINT_LEAST16_MAX__ 65535 #define __ATOMIC_ACQUIRE 2 #define __FLT_MIN__ 1.17549435082228750796873653722224568e-38F #define __UINT_LEAST8_TYPE__ unsigned char #define __INTMAX_C(c) c ## LL #define __CHAR_BIT__ 8 #define __UINT8_MAX__ 255 #define __WINT_MAX__ 4294967295U #define __ORDER_LITTLE_ENDIAN__ 1234 #define __SIZE_MAX__ 4294967295U #define __WCHAR_MAX__ 2147483647 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_1 1 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_2 1 #define __GCC_HAVE_SYNC_COMPARE_AND_SWAP_4 1 #define __DBL_DENORM_MIN__ ((double)4.94065645841246544176568792868221372e-324L) #define __GCC_ATOMIC_CHAR_LOCK_FREE 2 #define __FLT_EVAL_METHOD__ 0 #define __unix__ 1 #define __GCC_ATOMIC_CHAR32_T_LOCK_FREE 2 #define __UINT_FAST64_MAX__ 18446744073709551615ULL #define __SIG_ATOMIC_TYPE__ int #define __DBL_MIN_10_EXP__ (-307) #define __FINITE_MATH_ONLY__ 0 #define __GNUC_PATCHLEVEL__ 2 #define __UINT_FAST8_MAX__ 255 #define __DEC64_MAX_EXP__ 385 #define __INT8_C(c) c #define sparc 1 #define __UINT_LEAST64_MAX__ 18446744073709551615ULL #define __SHRT_MAX__ 32767 #define __LDBL_MAX__ 1.18973149535723176508575932662800702e+4932L #define __UINT_LEAST8_MAX__ 255 #define __GCC_ATOMIC_BOOL_LOCK_FREE 2 #define __UINTMAX_TYPE__ long long unsigned int #define __linux 1 #define __DEC32_EPSILON__ 1E-6DF #define __unix 1 #define __UINT32_MAX__ 4294967295U #define __LDBL_MAX_EXP__ 16384 #define __WINT_MIN__ 0U #define __linux__ 1 #define __SCHAR_MAX__ 127 #define __WCHAR_MIN__ (-__WCHAR_MAX__ - 1) #define __INT64_C(c) c ## LL #define __DBL_DIG__ 15 #define __GCC_ATOMIC_POINTER_LOCK_FREE 2 #define __SIZEOF_INT__ 4 #define __SIZEOF_POINTER__ 4 #define __USER_LABEL_PREFIX__ #define __STDC_HOSTED__ 1 #define __LDBL_HAS_INFINITY__ 1 #define __FLT_EPSILON__ 1.19209289550781250000000000000000000e-7F #define __LDBL_MIN__ 3.36210314311209350626267781732175260e-4932L #define __DEC32_MAX__ 9.999999E96DF #define __INT32_MAX__ 2147483647 #define __SIZEOF_LONG__ 4 #define __UINT16_C(c) c #define __DECIMAL_DIG__ 36 #define __gnu_linux__ 1 #define __LDBL_HAS_QUIET_NAN__ 1 #define __GNUC__ 4 #define __FLT_HAS_DENORM__ 1 #define __SIZEOF_LONG_DOUBLE__ 16 #define __BIGGEST_ALIGNMENT__ 8 #define __DBL_MAX__ ((double)1.79769313486231570814527423731704357e+308L) #define __INT_FAST32_MAX__ 2147483647 #define __DBL_HAS_INFINITY__ 1 #define __DEC32_MIN_EXP__ (-94) #define __INT_FAST16_TYPE__ int #define __LDBL_HAS_DENORM__ 1 #define __DEC128_MAX__ 9.999999999999999999999999999999999E6144DL #define __INT_LEAST32_MAX__ 2147483647 #define __DEC32_MIN__ 1E-95DF #define __DBL_MAX_EXP__ 1024 #define __DEC128_EPSILON__ 1E-33DL #define __PTRDIFF_MAX__ 2147483647 #define __LONG_LONG_MAX__ 9223372036854775807LL #define __SIZEOF_SIZE_T__ 4 #define __sparc__ 1 #define __SIZEOF_WINT_T__ 4 #define __GXX_ABI_VERSION 1002 #define __FLT_MIN_EXP__ (-125) #define __INT_FAST64_TYPE__ long long int #define __DBL_MIN__ ((double)2.22507385850720138309023271733240406e-308L) #define __DEC128_MIN__ 1E-6143DL #define __REGISTER_PREFIX__ #define __UINT16_MAX__ 65535 #define __DBL_HAS_DENORM__ 1 #define __UINT8_TYPE__ unsigned char #define __NO_INLINE__ 1 #define __FLT_MANT_DIG__ 24 #define __VERSION__ "4.7.2" #define __UINT64_C(c) c ## ULL #define __GCC_ATOMIC_INT_LOCK_FREE 2 #define __FLOAT_WORD_ORDER__ __ORDER_BIG_ENDIAN__ #define __sparc 1 #define __INT32_C(c) c #define __DEC64_EPSILON__ 1E-15DD #define __ORDER_PDP_ENDIAN__ 3412 #define __DEC128_MIN_EXP__ (-6142) #define __INT_FAST32_TYPE__ int #define __UINT_LEAST16_TYPE__ short unsigned int #define unix 1 #define __INT16_MAX__ 32767 #define __SIZE_TYPE__ unsigned int #define __UINT64_MAX__ 18446744073709551615ULL #define __INT8_TYPE__ signed char #define __ELF__ 1 #define __FLT_RADIX__ 2 #define __INT_LEAST16_TYPE__ short int #define __LDBL_EPSILON__ 1.92592994438723585305597794258492732e-34L #define __UINTMAX_C(c) c ## ULL #define __SIG_ATOMIC_MAX__ 2147483647 #define __GCC_ATOMIC_WCHAR_T_LOCK_FREE 2 #define __SIZEOF_PTRDIFF_T__ 4 #define __DEC32_SUBNORMAL_MIN__ 0.000001E-95DF #define __INT_FAST16_MAX__ 2147483647 #define __UINT_FAST32_MAX__ 4294967295U #define __UINT_LEAST64_TYPE__ long long unsigned int #define __FLT_HAS_QUIET_NAN__ 1 #define __FLT_MAX_10_EXP__ 38 #define __LONG_MAX__ 2147483647L #define __DEC128_SUBNORMAL_MIN__ 0.000000000000000000000000000000001E-6143DL #define __FLT_HAS_INFINITY__ 1 #define __UINT_FAST16_TYPE__ unsigned int #define __DEC64_MAX__ 9.999999999999999E384DD #define __CHAR16_TYPE__ short unsigned int #define __PRAGMA_REDEFINE_EXTNAME 1 #define __INT_LEAST16_MAX__ 32767 #define __DEC64_MANT_DIG__ 16 #define __INT64_MAX__ 9223372036854775807LL #define __UINT_LEAST32_MAX__ 4294967295U #define __GCC_ATOMIC_LONG_LOCK_FREE 2 #define __INT_LEAST64_TYPE__ long long int #define __INT16_TYPE__ short int #define __INT_LEAST8_TYPE__ signed char #define __DEC32_MAX_EXP__ 97 #define __INT_FAST8_MAX__ 127 #define __INTPTR_MAX__ 2147483647 #define linux 1 #define __LDBL_MANT_DIG__ 113 #define __DBL_HAS_QUIET_NAN__ 1 #define __SIG_ATOMIC_MIN__ (-__SIG_ATOMIC_MAX__ - 1) #define __INTPTR_TYPE__ int #define __UINT16_TYPE__ short unsigned int #define __WCHAR_TYPE__ int #define __SIZEOF_FLOAT__ 4 #define __UINTPTR_MAX__ 4294967295U #define __DEC64_MIN_EXP__ (-382) #define __INT_FAST64_MAX__ 9223372036854775807LL #define __GCC_ATOMIC_TEST_AND_SET_TRUEVAL 255 #define __FLT_DIG__ 6 #define __UINT_FAST64_TYPE__ long long unsigned int #define __INT_MAX__ 2147483647 #define __LONG_DOUBLE_128__ 1 #define __INT64_TYPE__ long long int #define __FLT_MAX_EXP__ 128 #define __DBL_MANT_DIG__ 53 #define __INT_LEAST64_MAX__ 9223372036854775807LL #define __GCC_ATOMIC_CHAR16_T_LOCK_FREE 2 #define __DEC64_MIN__ 1E-383DD #define __WINT_TYPE__ unsigned int #define __UINT_LEAST32_TYPE__ unsigned int #define __SIZEOF_SHORT__ 2 #define __LDBL_MIN_EXP__ (-16381) #define __INT_LEAST8_MAX__ 127 #define __LDBL_MAX_10_EXP__ 4932 #define __ATOMIC_RELAXED 0 #define __DBL_EPSILON__ ((double)2.22044604925031308084726333618164062e-16L) #define __UINT8_C(c) c #define __INT_LEAST32_TYPE__ int #define __SIZEOF_WCHAR_T__ 4 #define __UINT64_TYPE__ long long unsigned int #define __INT_FAST8_TYPE__ signed char #define __DBL_DECIMAL_DIG__ 17 #define __DEC_EVAL_METHOD__ 2 #define __ORDER_BIG_ENDIAN__ 4321 #define __UINT32_C(c) c ## U #define __INTMAX_MAX__ 9223372036854775807LL #define __BYTE_ORDER__ __ORDER_BIG_ENDIAN__ #define __FLT_DENORM_MIN__ 1.40129846432481707092372958328991613e-45F #define __INT8_MAX__ 127 #define __UINT_FAST32_TYPE__ unsigned int #define __CHAR32_TYPE__ unsigned int #define __FLT_MAX__ 3.40282346638528859811704183484516925e+38F #define __INT32_TYPE__ int #define __sparc_v9__ 1 #define __SIZEOF_DOUBLE__ 8 #define __FLT_MIN_10_EXP__ (-37) #define __INTMAX_TYPE__ long long int #define __DEC128_MAX_EXP__ 6145 #define __ATOMIC_CONSUME 1 #define __GNUC_MINOR__ 7 #define __UINTMAX_MAX__ 18446744073709551615ULL #define __DEC32_MANT_DIG__ 7 #define __DBL_MAX_10_EXP__ 308 #define __LDBL_DENORM_MIN__ 6.47517511943802511092443895822764655e-4966L #define __INT16_C(c) c #define __STDC__ 1 #define __PTRDIFF_TYPE__ int #define __ATOMIC_SEQ_CST 5 #define __UINT32_TYPE__ unsigned int #define __UINTPTR_TYPE__ unsigned int #define __DEC64_SUBNORMAL_MIN__ 0.000000000000001E-383DD #define __DEC128_MANT_DIG__ 34 #define __LDBL_MIN_10_EXP__ (-4931) #define __SIZEOF_LONG_LONG__ 8 #define __GCC_ATOMIC_LLONG_LOCK_FREE 1 #define __LDBL_DIG__ 33 #define __FLT_DECIMAL_DIG__ 9 #define __UINT_FAST16_MAX__ 4294967295U #define __GNUC_GNU_INLINE__ 1 #define __GCC_ATOMIC_SHORT_LOCK_FREE 2 #define __UINT_FAST8_TYPE__ unsigned char #define __ATOMIC_ACQ_REL 4 #define __ATOMIC_RELEASE 3 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 555 bytes Desc: OpenPGP digital signature URL: From jussi.kivilinna at iki.fi Wed Nov 6 22:00:38 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 06 Nov 2013 23:00:38 +0200 Subject: [PATCH] Speed-up AES-NI key setup Message-ID: <20131106210038.12668.87703.stgit@localhost6.localdomain6> * cipher/rijndael.c [USE_AESNI] (m128i_t): Remove. [USE_AESNI] (u128_t): New. [USE_AESNI] (aesni_do_setkey): New. (do_setkey) [USE_AESNI]: Move AES-NI accelerated key setup to 'aesni_do_setkey'. (do_setkey): Call _gcry_get_hw_features only once. Clear stack after use in generic key setup part. (rijndael_setkey): Remove stack burning. (prepare_decryption) [USE_AESNI]: Use 'u128_t' instead of 'm128i_t' to avoid compiler generated SSE2 instructions and XMM register usage, unroll 'aesimc' setup loop (prepare_decryption): Clear stack after use. [USE_AESNI] (do_aesni_enc_aligned): Update comment about alignment. (do_decrypt): Do not burning stack after prepare_decryption. -- Patch improves the speed of AES key setup with AES-NI instructions. Patch also removes problematic the use of vector typedef, which might cause interference with XMM register usage in AES-NI accelerated code. New: $ tests/benchmark --cipher-with-keysetup --cipher-repetitions 1000 cipher aes aes192 aes256 Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 520ms 590ms 1760ms 310ms 1640ms 300ms 1620ms 1610ms 350ms 360ms 2160ms 2140ms AES192 640ms 680ms 2030ms 370ms 1920ms 350ms 1890ms 1880ms 400ms 410ms 2490ms 2490ms AES256 730ms 780ms 2330ms 430ms 2210ms 420ms 2170ms 2180ms 470ms 480ms 2830ms 2840ms Old: $ tests/benchmark --cipher-with-keysetup --cipher-repetitions 1000 cipher aes aes192 aes256 Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 670ms 740ms 1910ms 470ms 1790ms 470ms 1770ms 1760ms 520ms 510ms 2310ms 2310ms AES192 820ms 860ms 2220ms 550ms 2110ms 540ms 2070ms 2070ms 600ms 590ms 2670ms 2680ms AES256 920ms 970ms 2510ms 620ms 2390ms 600ms 2360ms 2370ms 650ms 660ms 3020ms 3020ms Signed-off-by: Jussi Kivilinna --- cipher/rijndael.c | 399 ++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 300 insertions(+), 99 deletions(-) diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 645cf37..cbdbbd8 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -99,7 +99,7 @@ #endif /* ENABLE_AESNI_SUPPORT */ #ifdef USE_AESNI - typedef int m128i_t __attribute__ ((__vector_size__ (16))); + typedef struct u128_s { u32 a, b, c, d; } u128_t; #endif /*USE_AESNI*/ /* Define an u32 variant for the sake of gcc 4.4's strict aliasing. */ @@ -223,6 +223,239 @@ static const char *selftest(void); +#ifdef USE_AESNI +static void +aesni_do_setkey (RIJNDAEL_context *ctx, const byte *key) +{ + aesni_prepare(); + + if (ctx->rounds < 12) + { + /* 128-bit key */ +#define AESKEYGENASSIST_xmm1_xmm2(imm8) \ + ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t" +#define AESKEY_EXPAND128 \ + "pshufd $0xff, %%xmm2, %%xmm2\n\t" \ + "movdqa %%xmm1, %%xmm3\n\t" \ + "pslldq $4, %%xmm3\n\t" \ + "pxor %%xmm3, %%xmm1\n\t" \ + "pslldq $4, %%xmm3\n\t" \ + "pxor %%xmm3, %%xmm1\n\t" \ + "pslldq $4, %%xmm3\n\t" \ + "pxor %%xmm3, %%xmm2\n\t" \ + "pxor %%xmm2, %%xmm1\n\t" + + asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key */ + "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x01) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x02) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x04) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x08) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x10) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x20) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x40) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x80) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x1b) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x36) + AESKEY_EXPAND128 + "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */ + : + : [key] "r" (key), [ksch] "r" (ctx->keyschenc) + : "cc", "memory" ); +#undef AESKEYGENASSIST_xmm1_xmm2 +#undef AESKEY_EXPAND128 + } + else if (ctx->rounds == 12) + { + /* 192-bit key */ +#define AESKEYGENASSIST_xmm3_xmm2(imm8) \ + ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t" +#define AESKEY_EXPAND192 \ + "pshufd $0x55, %%xmm2, %%xmm2\n\t" \ + "movdqu %%xmm1, %%xmm4\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pxor %%xmm2, %%xmm1\n\t" \ + "pshufd $0xff, %%xmm1, %%xmm2\n\t" \ + "movdqu %%xmm3, %%xmm4\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm3\n\t" \ + "pxor %%xmm2, %%xmm3\n\t" + + asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */ + "movq 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..23] */ + "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */ + "movdqa %%xmm3, %%xmm5\n\t" + + AESKEYGENASSIST_xmm3_xmm2(0x01) + AESKEY_EXPAND192 + "shufpd $0, %%xmm1, %%xmm5\n\t" + "movdqa %%xmm5, 0x10(%[ksch])\n\t" /* ksch[1] := xmm5 */ + "movdqa %%xmm1, %%xmm6\n\t" + "shufpd $1, %%xmm3, %%xmm6\n\t" + "movdqa %%xmm6, 0x20(%[ksch])\n\t" /* ksch[2] := xmm6 */ + AESKEYGENASSIST_xmm3_xmm2(0x02) + AESKEY_EXPAND192 + "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */ + "movdqa %%xmm3, %%xmm5\n\t" + + AESKEYGENASSIST_xmm3_xmm2(0x04) + AESKEY_EXPAND192 + "shufpd $0, %%xmm1, %%xmm5\n\t" + "movdqa %%xmm5, 0x40(%[ksch])\n\t" /* ksch[4] := xmm5 */ + "movdqa %%xmm1, %%xmm6\n\t" + "shufpd $1, %%xmm3, %%xmm6\n\t" + "movdqa %%xmm6, 0x50(%[ksch])\n\t" /* ksch[5] := xmm6 */ + AESKEYGENASSIST_xmm3_xmm2(0x08) + AESKEY_EXPAND192 + "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */ + "movdqa %%xmm3, %%xmm5\n\t" + + AESKEYGENASSIST_xmm3_xmm2(0x10) + AESKEY_EXPAND192 + "shufpd $0, %%xmm1, %%xmm5\n\t" + "movdqa %%xmm5, 0x70(%[ksch])\n\t" /* ksch[7] := xmm5 */ + "movdqa %%xmm1, %%xmm6\n\t" + "shufpd $1, %%xmm3, %%xmm6\n\t" + "movdqa %%xmm6, 0x80(%[ksch])\n\t" /* ksch[8] := xmm6 */ + AESKEYGENASSIST_xmm3_xmm2(0x20) + AESKEY_EXPAND192 + "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */ + "movdqa %%xmm3, %%xmm5\n\t" + + AESKEYGENASSIST_xmm3_xmm2(0x40) + AESKEY_EXPAND192 + "shufpd $0, %%xmm1, %%xmm5\n\t" + "movdqa %%xmm5, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm5 */ + "movdqa %%xmm1, %%xmm6\n\t" + "shufpd $1, %%xmm3, %%xmm6\n\t" + "movdqa %%xmm6, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm6 */ + AESKEYGENASSIST_xmm3_xmm2(0x80) + AESKEY_EXPAND192 + "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */ + : + : [key] "r" (key), [ksch] "r" (ctx->keyschenc) + : "cc", "memory" ); +#undef AESKEYGENASSIST_xmm3_xmm2 +#undef AESKEY_EXPAND192 + } + else if (ctx->rounds > 12) + { + /* 256-bit key */ +#define AESKEYGENASSIST_xmm1_xmm2(imm8) \ + ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd1, " #imm8 " \n\t" +#define AESKEYGENASSIST_xmm3_xmm2(imm8) \ + ".byte 0x66, 0x0f, 0x3a, 0xdf, 0xd3, " #imm8 " \n\t" +#define AESKEY_EXPAND256_A \ + "pshufd $0xff, %%xmm2, %%xmm2\n\t" \ + "movdqa %%xmm1, %%xmm4\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm1\n\t" \ + "pxor %%xmm2, %%xmm1\n\t" +#define AESKEY_EXPAND256_B \ + "pshufd $0xaa, %%xmm2, %%xmm2\n\t" \ + "movdqa %%xmm3, %%xmm4\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm3\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm3\n\t" \ + "pslldq $4, %%xmm4\n\t" \ + "pxor %%xmm4, %%xmm3\n\t" \ + "pxor %%xmm2, %%xmm3\n\t" + + asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key[0..15] */ + "movdqu 16(%[key]), %%xmm3\n\t" /* xmm3 := key[16..31] */ + "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */ + "movdqa %%xmm3, 0x10(%[ksch])\n\t" /* ksch[1] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x01) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0x30(%[ksch])\n\t" /* ksch[3] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x02) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0x50(%[ksch])\n\t" /* ksch[5] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x04) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0x70(%[ksch])\n\t" /* ksch[7] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x08) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0x90(%[ksch])\n\t" /* ksch[9] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x10) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0xb0(%[ksch])\n\t" /* ksch[11] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x20) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0xc0(%[ksch])\n\t" /* ksch[12] := xmm1 */ + AESKEYGENASSIST_xmm1_xmm2(0x00) + AESKEY_EXPAND256_B + "movdqa %%xmm3, 0xd0(%[ksch])\n\t" /* ksch[13] := xmm3 */ + + AESKEYGENASSIST_xmm3_xmm2(0x40) + AESKEY_EXPAND256_A + "movdqa %%xmm1, 0xe0(%[ksch])\n\t" /* ksch[14] := xmm1 */ + + : + : [key] "r" (key), [ksch] "r" (ctx->keyschenc) + : "cc", "memory" ); +#undef AESKEYGENASSIST_xmm1_xmm2 +#undef AESKEYGENASSIST_xmm3_xmm2 +#undef AESKEY_EXPAND256_A +#undef AESKEY_EXPAND256_B + } + + aesni_cleanup(); + aesni_cleanup_2_6(); +} +#endif /*USE_AESNI*/ + + + /* Perform the key setup. */ static gcry_err_code_t do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) @@ -232,18 +465,7 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) int rounds; int i,j, r, t, rconpointer = 0; int KC; - union - { - PROPERLY_ALIGNED_TYPE dummy; - byte k[MAXKC][4]; - } k; -#define k k.k - union - { - PROPERLY_ALIGNED_TYPE dummy; - byte tk[MAXKC][4]; - } tk; -#define tk tk.tk + unsigned int hwfeatures; /* The on-the-fly self tests are only run in non-fips mode. In fips mode explicit self-tests are required. Actually the on-the-fly @@ -262,6 +484,10 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) if (selftest_failed) return GPG_ERR_SELFTEST_FAILED; +#if defined(USE_AESNI) || defined(USE_PADLOCK) + hwfeatures = _gcry_get_hw_features (); +#endif + ctx->decryption_prepared = 0; #ifdef USE_PADLOCK ctx->use_padlock = 0; @@ -278,14 +504,14 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) if (0) ; #ifdef USE_PADLOCK - else if ((_gcry_get_hw_features () & HWF_PADLOCK_AES)) + else if (hwfeatures & HWF_PADLOCK_AES) { ctx->use_padlock = 1; memcpy (ctx->padlockkey, key, keylen); } #endif #ifdef USE_AESNI - else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + else if (hwfeatures & HWF_INTEL_AESNI) { ctx->use_aesni = 1; } @@ -301,7 +527,7 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) ; } #ifdef USE_AESNI - else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + else if (hwfeatures & HWF_INTEL_AESNI) { ctx->use_aesni = 1; } @@ -317,7 +543,7 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) ; } #ifdef USE_AESNI - else if ((_gcry_get_hw_features () & HWF_INTEL_AESNI)) + else if (hwfeatures & HWF_INTEL_AESNI) { ctx->use_aesni = 1; } @@ -332,70 +558,19 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) if (0) ; -#ifdef USE_AESNI_is_disabled_here - else if (ctx->use_aesni && ctx->rounds == 10) - { - /* Note: This code works for AES-128 but it is not much better - than using the standard key schedule. We disable it for - now and don't put any effort into implementing this for - AES-192 and AES-256. */ - asm volatile ("movdqu (%[key]), %%xmm1\n\t" /* xmm1 := key */ - "movdqa %%xmm1, (%[ksch])\n\t" /* ksch[0] := xmm1 */ - "aeskeygenassist $0x01, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x10(%[ksch])\n\t" /* ksch[1] := xmm1 */ - "aeskeygenassist $0x02, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x20(%[ksch])\n\t" /* ksch[2] := xmm1 */ - "aeskeygenassist $0x04, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x30(%[ksch])\n\t" /* ksch[3] := xmm1 */ - "aeskeygenassist $0x08, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x40(%[ksch])\n\t" /* ksch[4] := xmm1 */ - "aeskeygenassist $0x10, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x50(%[ksch])\n\t" /* ksch[5] := xmm1 */ - "aeskeygenassist $0x20, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x60(%[ksch])\n\t" /* ksch[6] := xmm1 */ - "aeskeygenassist $0x40, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x70(%[ksch])\n\t" /* ksch[7] := xmm1 */ - "aeskeygenassist $0x80, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x80(%[ksch])\n\t" /* ksch[8] := xmm1 */ - "aeskeygenassist $0x1b, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0x90(%[ksch])\n\t" /* ksch[9] := xmm1 */ - "aeskeygenassist $0x36, %%xmm1, %%xmm2\n\t" - "call .Lexpand128_%=\n\t" - "movdqa %%xmm1, 0xa0(%[ksch])\n\t" /* ksch[10] := xmm1 */ - "jmp .Lleave%=\n" - - ".Lexpand128_%=:\n\t" - "pshufd $0xff, %%xmm2, %%xmm2\n\t" - "movdqa %%xmm1, %%xmm3\n\t" - "pslldq $4, %%xmm3\n\t" - "pxor %%xmm3, %%xmm1\n\t" - "pslldq $4, %%xmm3\n\t" - "pxor %%xmm3, %%xmm1\n\t" - "pslldq $4, %%xmm3\n\t" - "pxor %%xmm3, %%xmm2\n\t" - "pxor %%xmm2, %%xmm1\n\t" - "ret\n" - - ".Lleave%=:\n\t" - "pxor %%xmm1, %%xmm1\n\t" - "pxor %%xmm2, %%xmm2\n\t" - "pxor %%xmm3, %%xmm3\n" - : - : [key] "r" (key), [ksch] "r" (ctx->keyschenc) - : "cc", "memory" ); - } -#endif /*USE_AESNI*/ +#ifdef USE_AESNI + else if (ctx->use_aesni) + aesni_do_setkey(ctx, key); +#endif else { + union + { + PROPERLY_ALIGNED_TYPE dummy; + byte data[MAXKC][4]; + } k, tk; +#define k k.data +#define tk tk.data #define W (ctx->keyschenc) for (i = 0; i < keylen; i++) { @@ -470,11 +645,13 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) } } #undef W +#undef tk +#undef k + wipememory(&tk, sizeof(tk)); + wipememory(&t, sizeof(t)); } return 0; -#undef tk -#undef k } @@ -482,10 +659,7 @@ static gcry_err_code_t rijndael_setkey (void *context, const byte *key, const unsigned keylen) { RIJNDAEL_context *ctx = context; - - int rc = do_setkey (ctx, key, keylen); - _gcry_burn_stack ( 100 + 16*sizeof(int)); - return rc; + return do_setkey (ctx, key, keylen); } @@ -501,22 +675,49 @@ prepare_decryption( RIJNDAEL_context *ctx ) /* The AES-NI decrypt instructions use the Equivalent Inverse Cipher, thus we can't use the the standard decrypt key preparation. */ - m128i_t *ekey = (m128i_t*)ctx->keyschenc; - m128i_t *dkey = (m128i_t*)ctx->keyschdec; + u128_t *ekey = (u128_t *)ctx->keyschenc; + u128_t *dkey = (u128_t *)ctx->keyschdec; int rr; + aesni_prepare(); + +#define DO_AESNI_AESIMC() \ + asm volatile ("movdqa %[ekey], %%xmm1\n\t" \ + /*"aesimc %%xmm1, %%xmm1\n\t"*/ \ + ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" \ + "movdqa %%xmm1, %[dkey]" \ + : [dkey] "=m" (dkey[r]) \ + : [ekey] "m" (ekey[rr]) \ + : "memory") + dkey[0] = ekey[ctx->rounds]; - for (r=1, rr=ctx->rounds-1; r < ctx->rounds; r++, rr--) - { - asm volatile - ("movdqu %[ekey], %%xmm1\n\t" - /*"aesimc %%xmm1, %%xmm1\n\t"*/ - ".byte 0x66, 0x0f, 0x38, 0xdb, 0xc9\n\t" - "movdqu %%xmm1, %[dkey]" - : [dkey] "=m" (dkey[r]) - : [ekey] "m" (ekey[rr]) ); - } + r=1; + rr=ctx->rounds-1; + DO_AESNI_AESIMC(); r++; rr--; /* round 1 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 2 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 3 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 4 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 5 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 6 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 7 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 8 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 9 */ + if (ctx->rounds > 10) + { + DO_AESNI_AESIMC(); r++; rr--; /* round 10 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 11 */ + if (ctx->rounds > 12) + { + DO_AESNI_AESIMC(); r++; rr--; /* round 12 */ + DO_AESNI_AESIMC(); r++; rr--; /* round 13 */ + } + } + dkey[r] = ekey[0]; + +#undef DO_AESNI_AESIMC + + aesni_cleanup(); } else #endif /*USE_AESNI*/ @@ -556,6 +757,7 @@ prepare_decryption( RIJNDAEL_context *ctx ) } #undef W #undef w + wipememory(&w, sizeof(w)); } } @@ -745,7 +947,7 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, #ifdef USE_AESNI /* Encrypt one block using the Intel AES-NI instructions. A and B may - be the same; they need to be properly aligned to 16 bytes. + be the same. Our problem here is that gcc does not allow the "x" constraint for SSE registers in asm unless you compile with -msse. The common @@ -1809,7 +2011,6 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) if ( !ctx->decryption_prepared ) { prepare_decryption ( ctx ); - _gcry_burn_stack (64); ctx->decryption_prepared = 1; } From wk at gnupg.org Thu Nov 7 08:48:13 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 07 Nov 2013 08:48:13 +0100 Subject: cipher/gost28147: optimization: use precomputed S-box In-Reply-To: <5904457.oKotRVip6i@darkstar> (Sergey V.'s message of "Wed, 06 Nov 2013 23:45:26 +0400") References: <5904457.oKotRVip6i@darkstar> Message-ID: <87vc047iv6.fsf@vigenere.g10code.de> On Wed, 6 Nov 2013 20:45, sftp.mtuci at gmail.com said: > Some time ago I wrote gost28147-89 implementation [1]. Since I noteced > that libgcrypt now has own implementation I want to implement > optimization which I have in my code [2]. Thanks. Dmitry: Will you be so kind and have a look at the patch Sergey: I need a DCO before I can apply your patch. See doc/HACKING. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Nov 7 08:59:12 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 07 Nov 2013 08:59:12 +0100 Subject: [PATCH] Add CMAC mode (Cipher-based MAC) In-Reply-To: (Dmitry Eremin-Solenikov's message of "Fri, 1 Nov 2013 02:16:12 +0400") References: <20131031124141.22682.33976.stgit@localhost6.localdomain6> <871u31mqlv.fsf@vigenere.g10code.de> Message-ID: <87r4as7icv.fsf@vigenere.g10code.de> On Thu, 31 Oct 2013 23:16, dbaryshkov at gmail.com said: > Maybe we should just converge gcry_md_* and gcry_cipher_* spaces? I would propose to add gcry_mac_* instead. For a user of the library it is easier to use a dedicated set of functions for MACing than to figure out the right way to to this with gcry_cipher or gcry_md. When I added HMAC (for my ssh implementation), I considered this but given that back then there was only one MAC in practical use, I used the hack with the HMAC flag. Now with several MAC algorithms in practical use a dedicated set of MACing function might be useful. It still does not solve technical problems but it will be easy to explain and in the long run easier to maintain. Right, authenticated encryption is still separate and I can't see an easy way on how to merge that without giving up a clear separation between the functional blocks. Eventually we will add a buffering layer on top of the existing functions which could the be used to do MAC+encrypt or encrypt+MAC in the various protocol dependent forms (e.g. for OpenPGP CFB plus a SHA-1 MDC). But this is orthogonal to the existing building blocks. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Nov 7 09:02:04 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 07 Nov 2013 09:02:04 +0100 Subject: [PATCH] Add CMAC mode (Cipher-based MAC) In-Reply-To: <20131101133430.25415.20522.stgit@localhost6.localdomain6> (Jussi Kivilinna's message of "Fri, 01 Nov 2013 15:35:22 +0200") References: <871u31mqlv.fsf@vigenere.g10code.de> <20131101133430.25415.20522.stgit@localhost6.localdomain6> Message-ID: <87mwlg7i83.fsf@vigenere.g10code.de> On Fri, 1 Nov 2013 14:35, jussi.kivilinna at iki.fi said: > Since adding GCM mode kind of adds GHASH to gcry_cipher as side product > and CBC-MAC already is provided in gcry_cipher, adding CMAC to > gcry_cipher seems much cleaner option. If we decide for separate gcry_mac_ functions we could keep your gcry_cipher based approach internally but don't put it into the public API. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Thu Nov 7 09:11:09 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 07 Nov 2013 09:11:09 +0100 Subject: Tasks for 1.6 Message-ID: <87iow47hsy.fsf@vigenere.g10code.de> Hi, some notes on what I think should be done before a 1.6 release. - Decide what to do with MACing algorithms. - Check that the recent changes in gcry_pk_ don't break too much (this is mainly about GnuPG and something I will take care about). - Check that the new threading initialization scheme works on major platforms. - Look for rarely used function we may want to remove from the API (we have an ABI change anyway) - Fix side-channel weaknesses in the new ECC code. - Run test builds on all Debian supported platforms After that I think the release of 1.6 is justified. Experience has shown that we will need to release a couple of fixes soon after 1.6.0. The important thing is that we keep the ABI stable after 1.6.0. I would like to do a release within the next 4 weeks. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dbaryshkov at gmail.com Thu Nov 7 10:43:30 2013 From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov) Date: Thu, 7 Nov 2013 13:43:30 +0400 Subject: cipher/gost28147: optimization: use precomputed S-box In-Reply-To: <87vc047iv6.fsf@vigenere.g10code.de> References: <5904457.oKotRVip6i@darkstar> <87vc047iv6.fsf@vigenere.g10code.de> Message-ID: Hello, On Thu, Nov 7, 2013 at 11:48 AM, Werner Koch wrote: > On Wed, 6 Nov 2013 20:45, sftp.mtuci at gmail.com said: > >> Some time ago I wrote gost28147-89 implementation [1]. Since I noteced >> that libgcrypt now has own implementation I want to implement >> optimization which I have in my code [2]. > > Thanks. > > Dmitry: Will you be so kind and have a look at the patch Acked-by: Dmitry Eremin-Solenikov Sergey, thanks for this speedup. -- With best wishes Dmitry From cvs at cvs.gnupg.org Thu Nov 7 11:24:42 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Thu, 07 Nov 2013 11:24:42 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-367-g57b296e Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 57b296ea3a5204cd3711b7bf57c8fb14d8542402 (commit) from f702d62d888b30e24c19f203566a1473098b2b31 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 57b296ea3a5204cd3711b7bf57c8fb14d8542402 Author: Jussi Kivilinna Date: Thu Nov 7 12:24:04 2013 +0200 Change 64-bit shift to 32-bit in AES AMD64 assembly * cipher/rijndael-amd64.S (do16bit_shr): Change 'shrq' to 'shrl'. -- 64-bit shift is not needed here as registers are used for 32-bit values. Signed-off-by: Jussi Kivilinna diff --git a/cipher/rijndael-amd64.S b/cipher/rijndael-amd64.S index d360ea8..3b96889 100644 --- a/cipher/rijndael-amd64.S +++ b/cipher/rijndael-amd64.S @@ -101,7 +101,7 @@ #define do16bit_shr(shf, op, source, tablemul, table1, dest1, table2, dest2, t0, t1) \ movzbl source ## bl, t0 ## d; \ movzbl source ## bh, t1 ## d; \ - shrq $(shf), source; \ + shrl $(shf), source ## d; \ op ## l table1(RTAB,t0,tablemul), dest1 ## d; \ op ## l table2(RTAB,t1,tablemul), dest2 ## d; ----------------------------------------------------------------------- Summary of changes: cipher/rijndael-amd64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From cvs at cvs.gnupg.org Thu Nov 7 11:34:42 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Thu, 07 Nov 2013 11:34:42 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-368-gbfe4f65 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via bfe4f6523b80bae0040328ef324b9000ee5b38a4 (commit) from 57b296ea3a5204cd3711b7bf57c8fb14d8542402 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit bfe4f6523b80bae0040328ef324b9000ee5b38a4 Author: Jussi Kivilinna Date: Thu Nov 7 12:33:59 2013 +0200 Fix decryption function size in AES AMD64 assembly * cipher/rijndael-amd64.S (_gcry_aes_amd64_decrypt_block): Set '.size' for '_gcry_aes_amd64_decrypt_block', not '..._encrypt_block'. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/rijndael-amd64.S b/cipher/rijndael-amd64.S index 3b96889..35a9d26 100644 --- a/cipher/rijndael-amd64.S +++ b/cipher/rijndael-amd64.S @@ -355,7 +355,7 @@ _gcry_aes_amd64_decrypt_block: decround(9); jmp .Ldec_tail; -.size _gcry_aes_amd64_encrypt_block,.-_gcry_aes_amd64_encrypt_block; +.size _gcry_aes_amd64_decrypt_block,.-_gcry_aes_amd64_decrypt_block; .data .align 16 ----------------------------------------------------------------------- Summary of changes: cipher/rijndael-amd64.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From sftp.mtuci at gmail.com Thu Nov 7 17:17:58 2013 From: sftp.mtuci at gmail.com (Sergey V.) Date: Thu, 07 Nov 2013 20:17:58 +0400 Subject: cipher/gost28147: optimization: use precomputed S-box In-Reply-To: <87vc047iv6.fsf@vigenere.g10code.de> References: <5904457.oKotRVip6i@darkstar> <87vc047iv6.fsf@vigenere.g10code.de> Message-ID: <2066221.5IYa7Yq760@darkstar> On 2013-11-07 at 08:48:13, Werner Koch wrote: > On Wed, 6 Nov 2013 20:45, sftp.mtuci at gmail.com said: > > Some time ago I wrote gost28147-89 implementation [1]. Since I > > noteced that libgcrypt now has own implementation I want to > > implement optimization which I have in my code [2]. > > Thanks. > > Dmitry: Will you be so kind and have a look at the patch > Sergey: I need a DCO before I can apply your patch. See doc/HACKING. Libgcrypt Developer's Certificate of Origin. Version 1.0 ========================================================= By making a contribution to the Libgcrypt project, I certify that: (a) The contribution was created in whole or in part by me and I have the right to submit it under the free software license indicated in the file; or (b) The contribution is based upon previous work that, to the best of my knowledge, is covered under an appropriate free software license and I have the right under that license to submit that work with modifications, whether created in whole or in part by me, under the same free software license (unless I am permitted to submit under a different license), as indicated in the file; or (c) The contribution was provided directly to me by some other person who certified (a), (b) or (c) and I have not modified it. (d) I understand and agree that this project and the contribution are public and that a record of the contribution (including all personal information I submit with it, including my sign-off) is maintained indefinitely and may be redistributed consistent with this project or the free software license(s) involved. Signed-off-by: Sergey V -- Also for my patch istelf: Signed-off-by: Sergey V Or should I resend whole the patch? Thanks > Shalom-Salam, > > Werner -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: This is a digitally signed message part. URL: From jussi.kivilinna at iki.fi Fri Nov 8 09:34:50 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 08 Nov 2013 10:34:50 +0200 Subject: [PATCH] Add CMAC mode (Cipher-based MAC) In-Reply-To: <87r4as7icv.fsf@vigenere.g10code.de> References: <20131031124141.22682.33976.stgit@localhost6.localdomain6> <871u31mqlv.fsf@vigenere.g10code.de> <87r4as7icv.fsf@vigenere.g10code.de> Message-ID: <527CA22A.1040008@iki.fi> On 07.11.2013 09:59, Werner Koch wrote: > On Thu, 31 Oct 2013 23:16, dbaryshkov at gmail.com said: > >> Maybe we should just converge gcry_md_* and gcry_cipher_* spaces? > > I would propose to add gcry_mac_* instead. For a user of the library it > is easier to use a dedicated set of functions for MACing than to figure > out the right way to to this with gcry_cipher or gcry_md. When I added > HMAC (for my ssh implementation), I considered this but given that back > then there was only one MAC in practical use, I used the hack with the > HMAC flag. I'm fine with this. So we'd be looking at adding gcry_mac_* interface with CMAC, HMAC and GMAC modes. API might look something like this: /* mode = MAC mode, algo = depending on mode, either MD or cipher algo */ gcry_error_t gcry_mac_open (gcry_mac_hd_t *h, int mode, int algo, unsigned int flags); void gcry_mac_close (gcry_mac_hd_t h); gcry_error_t gcry_mac_setkey (gcry_mac_hd_t h, const void *key, unsigned int keylen); /* reset buffer state (keep currently setkey) */ gcry_error_t gcry_mac_reset (gcry_mac_hd_t h); /* GMAC needs IV */ void gcry_mac_setiv (gcry_mac_hd_t h, const void *iv, unsigned int ivlen); /* name? write, authenticate ... */ gcry_error_t gcry_mac_write(gcry_mac_hd_t h, const void *buf, size_t buflen); /* name? final, gettag (+checktag) ... */ gcry_error_t gcry_mac_final(gcry_mac_hd_t h, void *tag_out, size_t taglen); /* Get mode/algo of handle */ void gcry_mac_get_mode_algo(gcry_mac_hd_t h, int *mode_out, int *algo_out); /* Names for mac... CMAC_, HMAC_, etc? */ char *gcry_mac_algo_name (int mode, int algo, char *namebuf, int namebuflen); void gcry_mac_map_name (const char *name, int *mode_out, int *algo_out); Comments? -Jussi > > Now with several MAC algorithms in practical use a dedicated set of > MACing function might be useful. It still does not solve technical > problems but it will be easy to explain and in the long run easier to > maintain. > > Right, authenticated encryption is still separate and I can't see an > easy way on how to merge that without giving up a clear separation > between the functional blocks. Eventually we will add a buffering layer > on top of the existing functions which could the be used to do > MAC+encrypt or encrypt+MAC in the various protocol dependent forms > (e.g. for OpenPGP CFB plus a SHA-1 MDC). But this is orthogonal to the > existing building blocks. > > > Salam-Shalom, > > Werner > From cvs at cvs.gnupg.org Fri Nov 8 10:24:49 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 08 Nov 2013 10:24:49 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-370-g9f63c0f Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 9f63c0f7a3b2c15c7e258cd17395cabd0a8f00cc (commit) via ed45fd2e60c88e2f005282e6eadd018b59dcf65b (commit) from bfe4f6523b80bae0040328ef324b9000ee5b38a4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9f63c0f7a3b2c15c7e258cd17395cabd0a8f00cc Author: Werner Koch Date: Fri Nov 8 10:07:40 2013 +0100 ecc: Implement the "nocomp" flag for key generation. * cipher/ecc.c (ecc_generate): Support the "nocomp" flag. * tests/keygen.c (check_ecc_keys): Add a test for it. Signed-off-by: Werner Koch diff --git a/cipher/ecc.c b/cipher/ecc.c index f2a0e82..d62f555 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -483,7 +483,7 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) if (_gcry_mpi_ec_get_affine (x, y, &sk.E.G, ctx)) log_fatal ("ecgen: Failed to get affine coordinates for %s\n", "G"); base = _gcry_ecc_ec2os (x, y, sk.E.p); - if (sk.E.dialect == ECC_DIALECT_ED25519) + if (sk.E.dialect == ECC_DIALECT_ED25519 && !(flags & PUBKEY_FLAG_NOCOMP)) { unsigned char *encpk; unsigned int encpklen; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index dd65f9a..1619f0d 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2232,11 +2232,15 @@ are known: @table @code @item comp + at itemx nocomp @cindex comp -If supported and not yet the default return ECC points in compact -(compressed) representation. The compact representation requires a -small overhead before a point can be used but halves the size of a to -be conveyed public key. + at cindex nocomp +If supported by the algorithm and curve the @code{comp} flag requests +that points are returned in compact (compressed) representation. The + at code{nocomp} flag requests that points are returned with full +coordinates. The default depends on the the algorithm and curve. +The compact representation requires a small overhead before a point +can be used but halves the size of a to be conveyed public key. @item pkcs1 @cindex PKCS1 diff --git a/tests/keygen.c b/tests/keygen.c index 4796b5c..48663d4 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -416,15 +416,16 @@ check_ecc_keys (void) show_sexp ("ECC key:\n", key); if (verbose) - show ("creating ECC key using curve Ed25519 for ECDSA\n"); + show ("creating ECC key using curve Ed25519 for ECDSA (nocomp)\n"); rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve Ed25519)(flags)))"); + "(genkey(ecc(curve Ed25519)(flags nocomp)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); gcry_sexp_release (keyparm); if (rc) - die ("error generating ECC key using curve Ed25519 for ECDSA: %s\n", + die ("error generating ECC key using curve Ed25519 for ECDSA" + " (nocomp): %s\n", gpg_strerror (rc)); if (verbose > 1) commit ed45fd2e60c88e2f005282e6eadd018b59dcf65b Author: Werner Koch Date: Fri Nov 8 09:53:32 2013 +0100 ecc: Make "noparam" the default and replace by "param". * src/cipher.h (PUBKEY_FLAG_NOCOMP): New. (PUBKEY_FLAG_NOPARAM): Remove. (PUBKEY_FLAG_PARAM): New. * cipher/pubkey-util.c (_gcry_pk_util_parse_flaglist): Support the new flags and ignore the obsolete "noparam" flag. * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Return the curve name also for curves selected by NBITS. (_gcry_mpi_ec_new): Support the "param" flag. * cipher/ecc.c (ecc_generate, ecc_sign, ecc_verify): Ditto. * tests/keygen.c (check_ecc_keys): Remove the "noparam" flag. -- This is an API change but there are not many ECC users yet and adding the "param" flag for those who really need the parameters (e.g. if private keys have been stored without the curve name, it can easily be added. Note that no version of Libgcrypt with support for "noparam" has been released but for the sake of projects already working with the master version we don't bail out on "noparam". Signed-off-by: Werner Koch diff --git a/NEWS b/NEWS index 8010c37..d63ca96 100644 --- a/NEWS +++ b/NEWS @@ -43,6 +43,9 @@ Noteworthy changes in version 1.6.0 (unreleased) * The algorithm ids GCRY_PK_ECDSA and GCRY_PK_ECDH are now deprecated. Use GCRY_PK_ECC if you need an algorithm id. + * Changed gcry_pk_genkey for "ecc" to only include the curve name and + not the parameters. The flag "param" may be used to revert this. + * Interface changes relative to the 1.5.0 release: ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ gcry_ac_* REMOVED. @@ -63,6 +66,7 @@ Noteworthy changes in version 1.6.0 (unreleased) GCRYCTL_SET_IV REMOVED. GCRYCTL_SET_CTR REMOVED. GCRYCTL_DISABLE_ALGO CHANGED: Not anymore thread-safe. + gcry_pk_genkey CHANGED: ECC curve params not returned. gcry_md_hash_buffers NEW. gcry_buffer_t NEW. GCRYCTL_SET_ENFORCED_FIPS_FLAG NEW. diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 1bd3679..27d2d8e 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -380,7 +380,10 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, for (idx = 0; domain_parms[idx].desc; idx++) if (nbits == domain_parms[idx].nbits && domain_parms[idx].model == MPI_EC_WEIERSTRASS) - break; + { + resname = domain_parms[idx].desc; + break; + } } if (!domain_parms[idx].desc) return GPG_ERR_UNKNOWN_CURVE; @@ -671,7 +674,12 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, goto leave; } - if (!(flags & PUBKEY_FLAG_NOPARAM)) + /* Check whether a curve name was given. */ + l1 = gcry_sexp_find_token (keyparam, "curve", 5); + + /* If we don't have a curve name or if override parameters have + explicitly been requested, parse them. */ + if (!l1 || (flags & PUBKEY_FLAG_PARAM)) { errc = mpi_from_keyparam (&p, keyparam, "p"); if (errc) @@ -690,15 +698,13 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, goto leave; } } + else + l1 = NULL; /* No curvename. */ /* Check whether a curve parameter is available and use that to fill in missing values. If no curve parameter is available try an optional provided curvename. If only the curvename has been given use that one. */ - if (keyparam) - l1 = gcry_sexp_find_token (keyparam, "curve", 5); - else - l1 = NULL; if (l1 || curvename) { char *name; diff --git a/cipher/ecc.c b/cipher/ecc.c index 5578e05..f2a0e82 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -509,43 +509,43 @@ ecc_generate (const gcry_sexp_t genparms, gcry_sexp_t *r_skey) goto leave; } - if ((flags & PUBKEY_FLAG_NOPARAM) || (flags & PUBKEY_FLAG_EDDSA)) + if ((flags & PUBKEY_FLAG_PARAM) || (flags & PUBKEY_FLAG_EDDSA)) { rc = gcry_sexp_build (&curve_flags, NULL, - ((flags & PUBKEY_FLAG_NOPARAM) && (flags & PUBKEY_FLAG_EDDSA))? - "(flags noparam eddsa)" : - ((flags & PUBKEY_FLAG_NOPARAM))? - "(flags noparam)" : + ((flags & PUBKEY_FLAG_PARAM) && (flags & PUBKEY_FLAG_EDDSA))? + "(flags param eddsa)" : + ((flags & PUBKEY_FLAG_PARAM))? + "(flags param)" : "(flags eddsa)"); if (rc) goto leave; } - if ((flags & PUBKEY_FLAG_NOPARAM) && E.name) + if ((flags & PUBKEY_FLAG_PARAM) && E.name) rc = gcry_sexp_build (r_skey, NULL, "(key-data" " (public-key" - " (ecc%S%S(q%m)))" + " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" " (private-key" - " (ecc%S%S(q%m)(d%m)))" + " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" " )", curve_info, curve_flags, - public, + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, curve_info, curve_flags, - public, secret); + sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret); else rc = gcry_sexp_build (r_skey, NULL, "(key-data" " (public-key" - " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)))" + " (ecc%S%S(q%m)))" " (private-key" - " (ecc%S%S(p%m)(a%m)(b%m)(g%m)(n%m)(q%m)(d%m)))" + " (ecc%S%S(q%m)(d%m)))" " )", curve_info, curve_flags, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, + public, curve_info, curve_flags, - sk.E.p, sk.E.a, sk.E.b, base, sk.E.n, public, secret); + public, secret); if (rc) goto leave; @@ -713,13 +713,13 @@ ecc_sign (gcry_sexp_t *r_sig, gcry_sexp_t s_data, gcry_sexp_t keyparms) /* * Extract the key. */ - if ((ctx.flags & PUBKEY_FLAG_NOPARAM)) - rc = _gcry_sexp_extract_param (keyparms, NULL, "/q?+d", - &mpi_q, &sk.d, NULL); - else + if ((ctx.flags & PUBKEY_FLAG_PARAM)) rc = _gcry_sexp_extract_param (keyparms, NULL, "-p?a?b?g?n?/q?+d", &sk.E.p, &sk.E.a, &sk.E.b, &mpi_g, &sk.E.n, &mpi_q, &sk.d, NULL); + else + rc = _gcry_sexp_extract_param (keyparms, NULL, "/q?+d", + &mpi_q, &sk.d, NULL); if (rc) goto leave; if (mpi_g) @@ -878,13 +878,13 @@ ecc_verify (gcry_sexp_t s_sig, gcry_sexp_t s_data, gcry_sexp_t s_keyparms) /* * Extract the key. */ - if ((ctx.flags & PUBKEY_FLAG_NOPARAM)) - rc = _gcry_sexp_extract_param (s_keyparms, NULL, "/q", - &mpi_q, NULL); - else + if ((ctx.flags & PUBKEY_FLAG_PARAM)) rc = _gcry_sexp_extract_param (s_keyparms, NULL, "-p?a?b?g?n?/q", &pk.E.p, &pk.E.a, &pk.E.b, &mpi_g, &pk.E.n, &mpi_q, NULL); + else + rc = _gcry_sexp_extract_param (s_keyparms, NULL, "/q", + &mpi_q, NULL); if (rc) goto leave; if (mpi_g) diff --git a/cipher/pubkey-util.c b/cipher/pubkey-util.c index a591c0d..3e0b5ef 100644 --- a/cipher/pubkey-util.c +++ b/cipher/pubkey-util.c @@ -113,6 +113,15 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, encoding = PUBKEY_ENC_PKCS1; flags |= PUBKEY_FLAG_FIXEDLEN; } + else if (!memcmp (s, "param", 5)) + flags |= PUBKEY_FLAG_PARAM; + else if (!igninvflag) + rc = GPG_ERR_INV_FLAG; + break; + + case 6: + if (!memcmp (s, "nocomp", 6)) + flags |= PUBKEY_FLAG_NOCOMP; else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; @@ -121,7 +130,7 @@ _gcry_pk_util_parse_flaglist (gcry_sexp_t list, if (!memcmp (s, "rfc6979", 7)) flags |= PUBKEY_FLAG_RFC6979; else if (!memcmp (s, "noparam", 7)) - flags |= PUBKEY_FLAG_NOPARAM; + ; /* Ignore - it is the default. */ else if (!igninvflag) rc = GPG_ERR_INV_FLAG; break; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 03ace83..dd65f9a 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -2267,15 +2267,11 @@ order to prevent leaking of secret information. Blinding is only implemented by RSA, but it might be implemented by other algorithms in the future as well, when necessary. - at item noparam - at cindex noparam -For ECC key generation do not return the domain parameters but only -the name of the curve. For ECC signing and verification ignore any -provided domain parameters of the public or private key and use only -the curve name. It is more secure to rely on the curve name and thus -use the curve parameters as known by Libgcrypt. This option should -have been the default but for backward compatibility reasons this is -not possible. It is best to always use this flag with ECC keys. + at item param + at cindex param +For ECC key generation also return the domain parameters. For ECC +signing and verification override default parameters by provided +domain parameters of the public or private key. @item transient-key @cindex transient-key @@ -2849,7 +2845,7 @@ is in general not recommended. @example (genkey (ecc - (flags noparam transient-key))) + (flags transient-key))) @end example @item transient-key @@ -2894,12 +2890,12 @@ elliptic curve key generation: (public-key (ecc (curve Ed25519) - (flags noparam eddsa) + (flags eddsa) (q @var{q-value}))) (private-key (ecc (curve Ed25519) - (flags noparam eddsa) + (flags eddsa) (q @var{q-value}) (d @var{d-value})))) @end example diff --git a/src/cipher.h b/src/cipher.h index 5ac891e..d939ade 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -35,10 +35,11 @@ #define PUBKEY_FLAG_USE_X931 (1 << 6) #define PUBKEY_FLAG_USE_FIPS186 (1 << 7) #define PUBKEY_FLAG_USE_FIPS186_2 (1 << 8) -#define PUBKEY_FLAG_NOPARAM (1 << 9) +#define PUBKEY_FLAG_PARAM (1 << 9) #define PUBKEY_FLAG_COMP (1 << 10) -#define PUBKEY_FLAG_EDDSA (1 << 11) -#define PUBKEY_FLAG_GOST (1 << 12) +#define PUBKEY_FLAG_NOCOMP (1 << 11) +#define PUBKEY_FLAG_EDDSA (1 << 12) +#define PUBKEY_FLAG_GOST (1 << 13) enum pk_operation diff --git a/tests/keygen.c b/tests/keygen.c index 5879393..4796b5c 100644 --- a/tests/keygen.c +++ b/tests/keygen.c @@ -376,11 +376,11 @@ check_ecc_keys (void) show ("creating ECC key using curve %s\n", curves[testno]); if (!strcmp (curves[testno], "Ed25519")) rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve %s)(flags noparam eddsa)))", + "(genkey(ecc(curve %s)(flags eddsa)))", curves[testno]); else rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve %s)(flags noparam)))", + "(genkey(ecc(curve %s)(flags )))", curves[testno]); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); @@ -418,7 +418,7 @@ check_ecc_keys (void) if (verbose) show ("creating ECC key using curve Ed25519 for ECDSA\n"); rc = gcry_sexp_build (&keyparm, NULL, - "(genkey(ecc(curve Ed25519)(flags noparam)))"); + "(genkey(ecc(curve Ed25519)(flags)))"); if (rc) die ("error creating S-expression: %s\n", gpg_strerror (rc)); rc = gcry_pk_genkey (&key, keyparm); ----------------------------------------------------------------------- Summary of changes: NEWS | 4 ++++ cipher/ecc-curves.c | 18 ++++++++++++------ cipher/ecc.c | 46 +++++++++++++++++++++++----------------------- cipher/pubkey-util.c | 11 ++++++++++- doc/gcrypt.texi | 32 ++++++++++++++++---------------- src/cipher.h | 7 ++++--- tests/keygen.c | 11 ++++++----- 7 files changed, 75 insertions(+), 54 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Fri Nov 8 10:40:32 2013 From: wk at gnupg.org (Werner Koch) Date: Fri, 08 Nov 2013 10:40:32 +0100 Subject: [PATCH] Add CMAC mode (Cipher-based MAC) In-Reply-To: <527CA22A.1040008@iki.fi> (Jussi Kivilinna's message of "Fri, 08 Nov 2013 10:34:50 +0200") References: <20131031124141.22682.33976.stgit@localhost6.localdomain6> <871u31mqlv.fsf@vigenere.g10code.de> <87r4as7icv.fsf@vigenere.g10code.de> <527CA22A.1040008@iki.fi> Message-ID: <877gcj5izz.fsf@vigenere.g10code.de> On Fri, 8 Nov 2013 09:34, jussi.kivilinna at iki.fi said: > /* mode = MAC mode, algo = depending on mode, either MD or cipher algo */ > gcry_error_t gcry_mac_open (gcry_mac_hd_t *h, int mode, int algo, unsigned int flags); I would like to add gcry_ctx_t ctx For now NULL will be passed but in future it would allow to convey extra information or associate the mac with a cipher etc. I have no clear picture about this, but I believe this is a useful extension we will later be able to use. For example gcry_pk_* would benefit from such a new context parameter because that would allow to cache intermediate result (e.g. pre-computed values for faster signature verification). For backward compatibility we will need to introduce new functions instead of gcry_pk_ but for a new set of function we should be prepared. > /* name? write, authenticate ... */ > gcry_error_t gcry_mac_write(gcry_mac_hd_t h, const void *buf, size_t buflen); Write is fine because that is similar to gcry_md. > /* name? final, gettag (+checktag) ... */ > gcry_error_t gcry_mac_final(gcry_mac_hd_t h, void *tag_out, size_t taglen); Wouldn't gcry_mac_read and gcry_mac_verify be easier to understand? "tag" is quite specific. We could do without a gcry_mac_final I think. > /* Names for mac... CMAC_, HMAC_, etc? */ > char *gcry_mac_algo_name (int mode, int algo, char *namebuf, int namebuflen); > void gcry_mac_map_name (const char *name, int *mode_out, int *algo_out); That would be quite different from the other sub systems which return constant string. Application use of allocated names is much harder than a constant string. The question is whether we want o use combined algorithm names (GCRY_MAC_HMAC_SHA1, GCRY_MAC_CMAC_AES128, ...) like OpenSSL. In general I think these names are too complex (in particular, those used for TLS). However, the total number of MAC algorithms is and should be limited, so that to me this sounds reasonable. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Fri Nov 8 10:46:39 2013 From: wk at gnupg.org (Werner Koch) Date: Fri, 08 Nov 2013 10:46:39 +0100 Subject: cipher/gost28147: optimization: use precomputed S-box In-Reply-To: <2066221.5IYa7Yq760@darkstar> (Sergey V.'s message of "Thu, 07 Nov 2013 20:17:58 +0400") References: <5904457.oKotRVip6i@darkstar> <87vc047iv6.fsf@vigenere.g10code.de> <2066221.5IYa7Yq760@darkstar> Message-ID: <8738n75ips.fsf@vigenere.g10code.de> On Thu, 7 Nov 2013 17:17, sftp.mtuci at gmail.com said: > Also for my patch istelf: > Signed-off-by: Sergey V > > Or should I resend whole the patch? I would appreciate this. Please also change the commit message to include a ChangeLog style description followed by a "--" line and your comments. See Jussi's patches or HACKING on how to format them. In theory could do that but it takes too much time for me to fix up the commit logs. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From dbaryshkov at gmail.com Fri Nov 8 11:03:38 2013 From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov) Date: Fri, 8 Nov 2013 14:03:38 +0400 Subject: [RFC PATCH v2] Initial implementation of GCM Message-ID: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> Currently it is still quite slow. Still no support for generate_iv(). Is it really necessary? TODO: Merge/reuse cipher-internal state used by CCM. Changelog entry will be present in final patch submission. Changes since v1: - 6x-7x speedup. - added bench-slope support Signed-off-by: Dmitry Eremin-Solenikov --- cipher/Makefile.am | 2 +- cipher/cipher-ccm.c | 12 +- cipher/cipher-gcm.c | 476 +++++++++++++++++++++++++++++++++++++++++++++++ cipher/cipher-internal.h | 36 +++- cipher/cipher.c | 32 ++++ src/gcrypt.h.in | 6 +- tests/basic.c | 337 +++++++++++++++++++++++++++++++++ tests/bench-slope.c | 128 +++++++++++++ tests/benchmark.c | 2 + 9 files changed, 1023 insertions(+), 8 deletions(-) create mode 100644 cipher/cipher-gcm.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 95d484e..ed61eb2 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,7 +40,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ -cipher-ccm.c \ +cipher-ccm.c cipher-gcm.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index ebcbf1e..5d555fd 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -164,7 +164,7 @@ _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen, /* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */ if ((M_ * 2 + 2) != M || M < 4 || M > 16) return GPG_ERR_INV_LENGTH; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag) + if (!c->u_mode.ccm.nonce || c->marks.tag) return GPG_ERR_INV_STATE; if (c->u_mode.ccm.lengths) return GPG_ERR_INV_STATE; @@ -235,7 +235,7 @@ _gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, if (abuflen > 0 && !abuf) return GPG_ERR_INV_ARG; - if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->u_mode.ccm.tag) + if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->marks.tag) return GPG_ERR_INV_STATE; if (abuflen > c->u_mode.ccm.aadlen) return GPG_ERR_INV_LENGTH; @@ -267,7 +267,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, if (c->u_mode.ccm.encryptlen > 0) return GPG_ERR_UNFINISHED; - if (!c->u_mode.ccm.tag) + if (!c->marks.tag) { burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */ @@ -280,6 +280,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, if (burn) _gcry_burn_stack (burn + sizeof(void *) * 5); + + c->marks.tag = 1; } if (!check) @@ -325,7 +327,7 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths || + if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0) return GPG_ERR_INV_STATE; if (inbuflen > c->u_mode.ccm.encryptlen) @@ -350,7 +352,7 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths || + if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0) return GPG_ERR_INV_STATE; if (inbuflen > c->u_mode.ccm.encryptlen) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c new file mode 100644 index 0000000..8afd2d3 --- /dev/null +++ b/cipher/cipher-gcm.c @@ -0,0 +1,476 @@ +/* cipher-gcm.c - Generic Galois Counter Mode implementation + * Copyright (C) 2013 Dmitry Eremin-Solenikov + * + * 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 "ath.h" +#include "bufhelp.h" +#include "./cipher-internal.h" + +#ifdef GCM_USE_TABLES +static const byte gcmR[256][2] = +{ + { 0x00, 0x00, }, { 0x01, 0xc2, }, { 0x03, 0x84, }, { 0x02, 0x46, }, + { 0x07, 0x08, }, { 0x06, 0xca, }, { 0x04, 0x8c, }, { 0x05, 0x4e, }, + { 0x0e, 0x10, }, { 0x0f, 0xd2, }, { 0x0d, 0x94, }, { 0x0c, 0x56, }, + { 0x09, 0x18, }, { 0x08, 0xda, }, { 0x0a, 0x9c, }, { 0x0b, 0x5e, }, + { 0x1c, 0x20, }, { 0x1d, 0xe2, }, { 0x1f, 0xa4, }, { 0x1e, 0x66, }, + { 0x1b, 0x28, }, { 0x1a, 0xea, }, { 0x18, 0xac, }, { 0x19, 0x6e, }, + { 0x12, 0x30, }, { 0x13, 0xf2, }, { 0x11, 0xb4, }, { 0x10, 0x76, }, + { 0x15, 0x38, }, { 0x14, 0xfa, }, { 0x16, 0xbc, }, { 0x17, 0x7e, }, + { 0x38, 0x40, }, { 0x39, 0x82, }, { 0x3b, 0xc4, }, { 0x3a, 0x06, }, + { 0x3f, 0x48, }, { 0x3e, 0x8a, }, { 0x3c, 0xcc, }, { 0x3d, 0x0e, }, + { 0x36, 0x50, }, { 0x37, 0x92, }, { 0x35, 0xd4, }, { 0x34, 0x16, }, + { 0x31, 0x58, }, { 0x30, 0x9a, }, { 0x32, 0xdc, }, { 0x33, 0x1e, }, + { 0x24, 0x60, }, { 0x25, 0xa2, }, { 0x27, 0xe4, }, { 0x26, 0x26, }, + { 0x23, 0x68, }, { 0x22, 0xaa, }, { 0x20, 0xec, }, { 0x21, 0x2e, }, + { 0x2a, 0x70, }, { 0x2b, 0xb2, }, { 0x29, 0xf4, }, { 0x28, 0x36, }, + { 0x2d, 0x78, }, { 0x2c, 0xba, }, { 0x2e, 0xfc, }, { 0x2f, 0x3e, }, + { 0x70, 0x80, }, { 0x71, 0x42, }, { 0x73, 0x04, }, { 0x72, 0xc6, }, + { 0x77, 0x88, }, { 0x76, 0x4a, }, { 0x74, 0x0c, }, { 0x75, 0xce, }, + { 0x7e, 0x90, }, { 0x7f, 0x52, }, { 0x7d, 0x14, }, { 0x7c, 0xd6, }, + { 0x79, 0x98, }, { 0x78, 0x5a, }, { 0x7a, 0x1c, }, { 0x7b, 0xde, }, + { 0x6c, 0xa0, }, { 0x6d, 0x62, }, { 0x6f, 0x24, }, { 0x6e, 0xe6, }, + { 0x6b, 0xa8, }, { 0x6a, 0x6a, }, { 0x68, 0x2c, }, { 0x69, 0xee, }, + { 0x62, 0xb0, }, { 0x63, 0x72, }, { 0x61, 0x34, }, { 0x60, 0xf6, }, + { 0x65, 0xb8, }, { 0x64, 0x7a, }, { 0x66, 0x3c, }, { 0x67, 0xfe, }, + { 0x48, 0xc0, }, { 0x49, 0x02, }, { 0x4b, 0x44, }, { 0x4a, 0x86, }, + { 0x4f, 0xc8, }, { 0x4e, 0x0a, }, { 0x4c, 0x4c, }, { 0x4d, 0x8e, }, + { 0x46, 0xd0, }, { 0x47, 0x12, }, { 0x45, 0x54, }, { 0x44, 0x96, }, + { 0x41, 0xd8, }, { 0x40, 0x1a, }, { 0x42, 0x5c, }, { 0x43, 0x9e, }, + { 0x54, 0xe0, }, { 0x55, 0x22, }, { 0x57, 0x64, }, { 0x56, 0xa6, }, + { 0x53, 0xe8, }, { 0x52, 0x2a, }, { 0x50, 0x6c, }, { 0x51, 0xae, }, + { 0x5a, 0xf0, }, { 0x5b, 0x32, }, { 0x59, 0x74, }, { 0x58, 0xb6, }, + { 0x5d, 0xf8, }, { 0x5c, 0x3a, }, { 0x5e, 0x7c, }, { 0x5f, 0xbe, }, + { 0xe1, 0x00, }, { 0xe0, 0xc2, }, { 0xe2, 0x84, }, { 0xe3, 0x46, }, + { 0xe6, 0x08, }, { 0xe7, 0xca, }, { 0xe5, 0x8c, }, { 0xe4, 0x4e, }, + { 0xef, 0x10, }, { 0xee, 0xd2, }, { 0xec, 0x94, }, { 0xed, 0x56, }, + { 0xe8, 0x18, }, { 0xe9, 0xda, }, { 0xeb, 0x9c, }, { 0xea, 0x5e, }, + { 0xfd, 0x20, }, { 0xfc, 0xe2, }, { 0xfe, 0xa4, }, { 0xff, 0x66, }, + { 0xfa, 0x28, }, { 0xfb, 0xea, }, { 0xf9, 0xac, }, { 0xf8, 0x6e, }, + { 0xf3, 0x30, }, { 0xf2, 0xf2, }, { 0xf0, 0xb4, }, { 0xf1, 0x76, }, + { 0xf4, 0x38, }, { 0xf5, 0xfa, }, { 0xf7, 0xbc, }, { 0xf6, 0x7e, }, + { 0xd9, 0x40, }, { 0xd8, 0x82, }, { 0xda, 0xc4, }, { 0xdb, 0x06, }, + { 0xde, 0x48, }, { 0xdf, 0x8a, }, { 0xdd, 0xcc, }, { 0xdc, 0x0e, }, + { 0xd7, 0x50, }, { 0xd6, 0x92, }, { 0xd4, 0xd4, }, { 0xd5, 0x16, }, + { 0xd0, 0x58, }, { 0xd1, 0x9a, }, { 0xd3, 0xdc, }, { 0xd2, 0x1e, }, + { 0xc5, 0x60, }, { 0xc4, 0xa2, }, { 0xc6, 0xe4, }, { 0xc7, 0x26, }, + { 0xc2, 0x68, }, { 0xc3, 0xaa, }, { 0xc1, 0xec, }, { 0xc0, 0x2e, }, + { 0xcb, 0x70, }, { 0xca, 0xb2, }, { 0xc8, 0xf4, }, { 0xc9, 0x36, }, + { 0xcc, 0x78, }, { 0xcd, 0xba, }, { 0xcf, 0xfc, }, { 0xce, 0x3e, }, + { 0x91, 0x80, }, { 0x90, 0x42, }, { 0x92, 0x04, }, { 0x93, 0xc6, }, + { 0x96, 0x88, }, { 0x97, 0x4a, }, { 0x95, 0x0c, }, { 0x94, 0xce, }, + { 0x9f, 0x90, }, { 0x9e, 0x52, }, { 0x9c, 0x14, }, { 0x9d, 0xd6, }, + { 0x98, 0x98, }, { 0x99, 0x5a, }, { 0x9b, 0x1c, }, { 0x9a, 0xde, }, + { 0x8d, 0xa0, }, { 0x8c, 0x62, }, { 0x8e, 0x24, }, { 0x8f, 0xe6, }, + { 0x8a, 0xa8, }, { 0x8b, 0x6a, }, { 0x89, 0x2c, }, { 0x88, 0xee, }, + { 0x83, 0xb0, }, { 0x82, 0x72, }, { 0x80, 0x34, }, { 0x81, 0xf6, }, + { 0x84, 0xb8, }, { 0x85, 0x7a, }, { 0x87, 0x3c, }, { 0x86, 0xfe, }, + { 0xa9, 0xc0, }, { 0xa8, 0x02, }, { 0xaa, 0x44, }, { 0xab, 0x86, }, + { 0xae, 0xc8, }, { 0xaf, 0x0a, }, { 0xad, 0x4c, }, { 0xac, 0x8e, }, + { 0xa7, 0xd0, }, { 0xa6, 0x12, }, { 0xa4, 0x54, }, { 0xa5, 0x96, }, + { 0xa0, 0xd8, }, { 0xa1, 0x1a, }, { 0xa3, 0x5c, }, { 0xa2, 0x9e, }, + { 0xb5, 0xe0, }, { 0xb4, 0x22, }, { 0xb6, 0x64, }, { 0xb7, 0xa6, }, + { 0xb2, 0xe8, }, { 0xb3, 0x2a, }, { 0xb1, 0x6c, }, { 0xb0, 0xae, }, + { 0xbb, 0xf0, }, { 0xba, 0x32, }, { 0xb8, 0x74, }, { 0xb9, 0xb6, }, + { 0xbc, 0xf8, }, { 0xbd, 0x3a, }, { 0xbf, 0x7c, }, { 0xbe, 0xbe, }, +}; + +static unsigned bshift(unsigned char *b) +{ + unsigned char c; + int i; + c = b[15] & 1; + for (i = 15; i > 0; i--) + { + b[i] = (b[i] >> 1) | (b[i-1] << 7); + } + b[i] >>= 1; + return c; +} + +static void fillM(unsigned char *h, unsigned char *M) +{ + int i, j; + memset(&M[0 * 16], 0, 16); + memcpy(&M[8 * 16], h, 16); + for (i = 4; i > 0; i /= 2) + { + memcpy(&M[i * 16], &M[2*i * 16], 16); + if (bshift(&M[i * 16])) + M[i * 16 + 0] ^= 0xe1; + } + for (i = 2; i < 16; i *= 2) + for (j = 1; j < i; j++) + buf_xor(&M[(i+j) * 16], &M[i* 16], &M[j * 16], 16); +} + +static void ghash(unsigned char *result, const unsigned char *buf, const unsigned char *gcmM) +{ + unsigned char V[16]; + int i; + + buf_xor(V, result, buf, 16); + + memset(result, 0, 16); + + for (i = 15; i >= 0; i--) + { + byte A = result[15]; + byte T[16]; + int j; + const byte *M = &gcmM[(V[i] & 0xf) * 16]; + + memmove(result+1, result, 15); + result[0] = gcmR[A][0]; + result[1] ^= gcmR[A][1]; + + T[0] = M[0] >> 4; + for (j = 1; j < 16; j++) + T[j] = (M[j] >> 4) | (M[j-1] << 4); + T[0] ^= gcmR[(M[15] & 0xf) << 4][0]; + T[1] ^= gcmR[(M[15] & 0xf) << 4][1]; + buf_xor(T, T, &gcmM[(V[i] >> 4) * 16], 16); + buf_xor(result, result, T, 16); + } +} +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); + +#else + +static unsigned long bshift(unsigned long *b) +{ + unsigned long c; + int i; + c = b[3] & 1; + for (i = 3; i > 0; i--) + { + b[i] = (b[i] >> 1) | (b[i-1] << 31); + } + b[i] >>= 1; + return c; +} + +static void ghash(unsigned char *hsub, unsigned char *result, const unsigned char *buf) +{ + unsigned long V[4]; + int i, j; + byte *p; + +#ifdef WORDS_BIGENDIAN + p = result; +#else + unsigned long T[4]; + + buf_xor(V, result, buf, 16); + for (i = 0; i < 4; i++) + { + V[i] = (V[i] & 0x00ff00ff) << 8 | + (V[i] & 0xff00ff00) >> 8; + V[i] = (V[i] & 0x0000ffff) << 16 | + (V[i] & 0xffff0000) >> 16; + } + p = (byte *) T; +#endif + + memset(p, 0, 16); + + for (i = 0; i < 16; i++) + { + for (j = 0x80; j ; j >>= 1) + { + if (hsub[i] & j) + buf_xor(p, p, V, 16); + if (bshift(V)) + V[0] ^= 0xe1000000; + } + } +#ifndef WORDS_BIGENDIAN + for (i = 0, p = (byte *) T; i < 16; i += 4, p += 4) + { + result[i + 0] = p[3]; + result[i + 1] = p[2]; + result[i + 2] = p[1]; + result[i + 3] = p[0]; + } +#endif +} + +#define fillM(h, M) do { } while (0) + +#define GHASH(c, result, buf) ghash (c->u_iv.iv, result, buf); +#endif + + +gcry_err_code_t +_gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, + byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (blocksize >= 0x20) + return GPG_ERR_CIPHER_ALGO; + if (blocksize != 0x10) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.iv) + { + memset(tmp, 0, 16); + _gcry_cipher_gcm_setiv(c, tmp, 16); + } + + while (inbuflen) + { + for (i = blocksize; i > blocksize - 4; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + + n = blocksize < inbuflen ? blocksize : inbuflen; + + i = blocksize - 1; + c->length[i] += n * 8; + for ( ; c->length[i] == 0 && i > blocksize / 2; i --) + c->length[i - 1]++; + + c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + if (n < blocksize) + { + buf_xor_2dst (outbuf, tmp, inbuf, n); + memset(tmp + n, 0, blocksize - n); + GHASH (c, c->u_tag.tag, tmp); + } else { + buf_xor (outbuf, tmp, inbuf, n); + GHASH (c, c->u_tag.tag, outbuf); + } + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, + byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (blocksize >= 0x20) + return GPG_ERR_CIPHER_ALGO; + if (blocksize != 0x10) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.iv) + { + memset(tmp, 0, 16); + _gcry_cipher_gcm_setiv(c, tmp, 16); + } + + while (inbuflen) + { + for (i = blocksize; i > blocksize - 4; i--) + { + c->u_ctr.ctr[i-1]++; + if (c->u_ctr.ctr[i-1] != 0) + break; + } + + n = blocksize < inbuflen ? blocksize : inbuflen; + if (n < blocksize) + { + memcpy (tmp, inbuf, n); + memset(tmp + n, 0, blocksize - n); + GHASH (c, c->u_tag.tag, tmp); + } else { + GHASH (c, c->u_tag.tag, inbuf); + } + + i = blocksize - 1; + c->length[i] += n * 8; + for ( ; c->length[i] == 0 && i > blocksize / 2; i --) + c->length[i - 1]++; + + c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + + buf_xor (outbuf, inbuf, tmp, n); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, + const byte *aadbuf, unsigned int aadbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (!c->marks.iv) + { + memset(tmp, 0, 16); + _gcry_cipher_gcm_setiv(c, tmp, 16); + } + + n = aadbuflen; + i = blocksize / 2; + c->length[i-1] = (n % 0x20) * 8; + n /= 0x20; + for (; n && i > 0; i--, n >>= 8) + c->length[i-1] = n & 0xff; + + while (aadbuflen >= blocksize) + { + GHASH (c, c->u_tag.tag, aadbuf); + + aadbuflen -= blocksize; + aadbuf += blocksize; + } + + if (aadbuflen != 0) + { + memcpy(tmp, aadbuf, aadbuflen); + memset(tmp + aadbuflen, 0, blocksize - aadbuflen); + + GHASH (c, c->u_tag.tag, tmp); + } + + return 0; +} + +void +_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, + const byte *iv, unsigned int ivlen) +{ + memset (c->length, 0, 16); + memset (c->u_tag.tag, 0, 16); + c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_tag.tag ); + + fillM (c->u_iv.iv, c->gcm_table); + + if (ivlen != 16 - 4) + { + unsigned char tmp[MAX_BLOCKSIZE]; + unsigned n; + memset(c->u_ctr.ctr, 0, 16); + for (n = ivlen; n >= 16; n -= 16, iv += 16) + GHASH (c, c->u_ctr.ctr, iv); + if (n != 0) + { + memcpy(tmp, iv, n); + memset(tmp + n, 0, 16 - n); + GHASH (c, c->u_ctr.ctr, tmp); + } + memset(tmp, 0, 16); + n = 16; + tmp[n-1] = (ivlen % 0x20) * 8; + ivlen /= 0x20; + n--; + for (; n > 0; n--, ivlen >>= 8) + tmp[n-1] = ivlen & 0xff; + GHASH (c, c->u_ctr.ctr, tmp); + } else { + memcpy (c->u_ctr.ctr, iv, ivlen); + c->u_ctr.ctr[12] = c->u_ctr.ctr[13] = c->u_ctr.ctr[14] = 0; + c->u_ctr.ctr[15] = 1; + } + + c->spec->encrypt ( &c->context.c, c->lastiv, c->u_ctr.ctr ); + c->marks.iv = 1; + +} + +gcry_err_code_t +_gcry_cipher_gcm_tag (gcry_cipher_hd_t c, + byte *outbuf, unsigned int outbuflen, + int check) +{ + if (outbuflen < 16) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.tag) + { + GHASH (c, c->u_tag.tag, c->length); + buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16); + c->marks.tag = 1; + } + memcpy (outbuf, c->u_tag.tag, 16); + if (!check) + { + memcpy (outbuf, c->u_tag.tag, outbuflen); + return GPG_ERR_NO_ERROR; + } + else + { + int diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < outbuflen; i++) + diff -= !!(outbuf[i] - c->u_tag.tag[i]); + + return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, + size_t taglen) +{ + return _gcry_cipher_gcm_tag (c, outtag, taglen, 0); +} + + +gcry_err_code_t +_gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, + size_t taglen) +{ + return _gcry_cipher_gcm_tag (c, (unsigned char *)intag, taglen, 1); +} + + diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index f528c84..5d50e17 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -35,6 +35,9 @@ # define NEED_16BYTE_ALIGNED_CONTEXT 1 #endif +/* Undef this symbol to trade GCM speed for 256 bytes of memory per context */ +#define GCM_USE_TABLES 1 + /* A VIA processor with the Padlock engine as well as the Intel AES_NI instructions require an alignment of most data on a 16 byte @@ -96,6 +99,7 @@ struct gcry_cipher_handle struct { unsigned int key:1; /* Set to 1 if a key has been set. */ unsigned int iv:1; /* Set to 1 if a IV has been set. */ + unsigned int tag:1; /* Set to 1 if a tag is finalized. */ } marks; /* The initialization vector. For best performance we make sure @@ -114,9 +118,19 @@ struct gcry_cipher_handle unsigned char ctr[MAX_BLOCKSIZE]; } u_ctr; + /* The interim tag for GCM mode. */ + union { + cipher_context_alignment_t iv_align; + unsigned char tag[MAX_BLOCKSIZE]; + } u_tag; + /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; int unused; /* Number of unused bytes in LASTIV. */ + unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ +#ifdef GCM_USE_TABLES + unsigned char gcm_table[16 * 16]; /* pre-calculated table for GCM */ +#endif union { /* Mode specific storage for CCM mode. */ @@ -134,7 +148,6 @@ struct gcry_cipher_handle unsigned int nonce:1;/* Set to 1 if nonce has been set. */ unsigned int lengths:1; /* Set to 1 if CCM length parameters has been processed. */ - unsigned int tag:1; /* Set to 1 if tag has been finalized. */ } ccm; } u_mode; @@ -216,6 +229,27 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); +/*-- cipher-gcm.c --*/ +gcry_err_code_t _gcry_cipher_gcm_encrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen); +gcry_err_code_t _gcry_cipher_gcm_decrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen); +void _gcry_cipher_gcm_setiv +/* */ (gcry_cipher_hd_t c, + const unsigned char *iv, unsigned int ivlen); +gcry_err_code_t _gcry_cipher_gcm_authenticate +/* */ (gcry_cipher_hd_t c, + const unsigned char *aadbuf, unsigned int aadbuflen); +gcry_err_code_t _gcry_cipher_gcm_get_tag +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen); +gcry_err_code_t _gcry_cipher_gcm_check_tag +/* */ (gcry_cipher_hd_t c, + const unsigned char *outbuf, unsigned int outbuflen); #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index 705696c..90635b8 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -388,6 +388,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: + case GCRY_CIPHER_MODE_GCM: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; @@ -580,6 +581,13 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) static void cipher_setiv (gcry_cipher_hd_t c, const byte *iv, unsigned ivlen) { + /* GCM has its own IV handler */ + if (c->mode == GCRY_CIPHER_MODE_GCM) + { + _gcry_cipher_gcm_setiv (c, iv, ivlen); + return; + } + /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ if (c->spec->setiv) @@ -622,6 +630,8 @@ cipher_reset (gcry_cipher_hd_t c) memset (c->u_ctr.ctr, 0, c->spec->blocksize); memset (&c->u_mode, 0, sizeof c->u_mode); c->unused = 0; +/* memset (c->u_tag.tag, 0, c->spec->blocksize); + memset (c->length, 0, c->spec->blocksize); */ } @@ -717,6 +727,11 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, rc = _gcry_cipher_ccm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, + inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -817,6 +832,11 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, rc = _gcry_cipher_ccm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, + inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -942,6 +962,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, rc = _gcry_cipher_ccm_authenticate (hd, abuf, abuflen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen); + break; + default: log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -962,6 +986,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) rc = _gcry_cipher_ccm_get_tag (hd, outtag, taglen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen); + break; + default: log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -982,6 +1010,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) rc = _gcry_cipher_ccm_check_tag (hd, intag, taglen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen); + break; + default: log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 234e8a4..a60d8c9 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -894,9 +894,13 @@ enum gcry_cipher_modes GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */ GCRY_CIPHER_MODE_CTR = 6, /* Counter. */ GCRY_CIPHER_MODE_AESWRAP= 7, /* AES-WRAP algorithm. */ - GCRY_CIPHER_MODE_CCM = 8 /* Counter with CBC-MAC. */ + GCRY_CIPHER_MODE_CCM = 8, /* Counter with CBC-MAC. */ + GCRY_CIPHER_MODE_GCM = 9 /* Galois Counter Mode. */ }; +/* GCM works only with blocks of 128 bits */ +#define GCRY_GCM_BLOCK_LEN (128 / 8) + /* Flags used with the open function. */ enum gcry_cipher_flags { diff --git a/tests/basic.c b/tests/basic.c index 99d63ae..7f1536c 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1137,6 +1137,340 @@ check_ofb_cipher (void) fprintf (stderr, " Completed OFB checks.\n"); } +static void +check_gcm_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char iv[MAX_DATA_LEN]; + int ivlen; + unsigned char aad[MAX_DATA_LEN]; + int aadlen; + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + char tag[MAX_DATA_LEN]; + } tv[] = + { + /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */ + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45\x5a" }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 16, + "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", + "\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "", 0, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + 64, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", + "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad", 8, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x61\x35\x3b\x4c\x28\x06\x93\x4a\x77\x7f\xf5\x1f\xa2\x2a\x47\x55" + "\x69\x9b\x2a\x71\x4f\xcd\xc6\xf8\x37\x66\xe5\xf9\x7b\x6c\x74\x23" + "\x73\x80\x69\x00\xe4\x9f\x24\xb2\x2b\x09\x75\x44\xd4\x89\x6b\x42" + "\x49\x89\xb5\xe1\xeb\xac\x0f\x07\xc2\x3f\x45\x98", + "\x36\x12\xd2\xe7\x9e\x3b\x07\x85\x56\x1b\xe1\x4a\xac\xa2\xfc\xcb" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94" + "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7" + "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f" + "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", + "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50" }, + { GCRY_CIPHER_AES192, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\xd2\x7e\x88\x68\x1c\xe3\x24\x3c\x48\x30\x16\x5a\x8f\xdc\xf9\xff" + "\x1d\xe9\xa1\xd8\xe6\xb4\x47\xef\x6e\xf7\xb7\x98\x28\x66\x6e\x45" + "\x81\xe7\x90\x12\xaf\x34\xdd\xd9\xe2\xf0\x37\x58\x9b\x29\x2d\xb3" + "\xe6\x7c\x03\x67\x45\xfa\x22\xe7\xe9\xb7\x37\x3b", + "\xdc\xf5\x66\xff\x29\x1c\x25\xbb\xb8\x56\x8f\xc3\xd3\x76\xa6\xd9" }, + { GCRY_CIPHER_AES256, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x5a\x8d\xef\x2f\x0c\x9e\x53\xf1\xf7\x5d\x78\x53\x65\x9e\x2a\x20" + "\xee\xb2\xb2\x2a\xaf\xde\x64\x19\xa0\x58\xab\x4f\x6f\x74\x6b\xf4" + "\x0f\xc0\xc3\xb7\x80\xf2\x44\x45\x2d\xa3\xeb\xf1\xc5\xd8\x2c\xde" + "\xa2\x41\x89\x97\x20\x0e\xf8\x2e\x44\xae\x7e\x3f", + "\xa4\x4a\x82\x66\xee\x1c\x8e\xb0\xc8\xb5\xd4\xcf\x5a\xe9\xf1\x9a" } + }; + + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + int i, keylen; + gcry_error_t err = 0; + + if (verbose) + fprintf (stderr, " Starting GCM checks.\n"); + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + if (verbose) + fprintf (stderr, " checking GCM mode for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo); + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_GCM, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_GCM, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_open failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("aes-gcm, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_authenticate(hde, tv[i].aad, tv[i].aadlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_authenticate (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (!err) + err = gcry_cipher_authenticate(hdd, tv[i].aad, tv[i].aadlen); + if (err) + { + fail ("aes-gcm, de gcry_cipher_authenticate (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, + tv[i].plaintext, + tv[i].inlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_encrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("aes-gcm, encrypt mismatch entry %d\n", i); + + err = gcry_cipher_decrypt (hdd, out, tv[i].inlen, NULL, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_decrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("aes-gcm, decrypt mismatch entry %d\n", i); + +#define TAGLEN 16 + err = gcry_cipher_gettag (hde, out, TAGLEN); /* FIXME */ + if (err) + { + fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].tag, out, TAGLEN)) + fail ("aes-gcm, encrypt tag mismatch entry %d\n", i); + + + err = gcry_cipher_checktag (hdd, out, TAGLEN); + if (err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_reset(hde); + if (!err) + err = gcry_cipher_reset(hdd); + if (err) + { + fail ("aes-gcm, gcry_cipher_reset (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + +#if 0 + /* gcry_cipher_reset clears the IV */ + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* this time we encrypt and decrypt one byte at a time */ + int byteNum; + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_encrypt (hde, out+byteNum, 1, + (tv[i].plaintext) + byteNum, + 1); + if (err) + { + fail ("aes-gcm, gcry_cipher_encrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("aes-gcm, encrypt mismatch entry %d\n", i); + + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_decrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("aes-gcm, decrypt mismatch entry %d\n", i); +#endif + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } + if (verbose) + fprintf (stderr, " Completed GCM checks.\n"); +} + static void check_ccm_cipher (void) @@ -3188,6 +3522,8 @@ check_ciphers (void) check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0); + if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_GCM_BLOCK_LEN) + check_one_cipher (algos[i], GCRY_CIPHER_MODE_GCM, 0); } for (i = 0; algos2[i]; i++) @@ -3226,6 +3562,7 @@ check_cipher_modes(void) check_cfb_cipher (); check_ofb_cipher (); check_ccm_cipher (); + check_gcm_cipher (); check_stream_cipher (); check_stream_cipher_large_block (); diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 79b868c..fced8de 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -787,6 +787,127 @@ static struct bench_ops ccm_authenticate_ops = { &bench_ccm_authenticate_do_bench }; +static void +bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16]; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_gettag (hd, tag, sizeof (tag)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static void +bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16] = { 0, }; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_checktag (hd, tag, sizeof (tag)); + if (gpg_err_code (err) == GPG_ERR_CHECKSUM) + err = gpg_error (GPG_ERR_NO_ERROR); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static void +bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16] = { 0, }; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + char data = 0xff; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_authenticate (hd, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_gettag (hd, tag, sizeof (tag)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static struct bench_ops gcm_encrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_encrypt_do_bench +}; + +static struct bench_ops gcm_decrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_decrypt_do_bench +}; + +static struct bench_ops gcm_authenticate_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_authenticate_do_bench +}; + static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops}, @@ -802,6 +923,9 @@ static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops}, {0}, }; @@ -834,6 +958,10 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode) if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN) return; + /* CCM has restrictions for block-size */ + if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN) + return; + printf (" %14s | ", mode.name); fflush (stdout); diff --git a/tests/benchmark.c b/tests/benchmark.c index 93874fa..d70383e 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -497,6 +497,8 @@ cipher_bench ( const char *algoname ) { GCRY_CIPHER_MODE_CTR, " CTR", 0 }, { GCRY_CIPHER_MODE_CCM, " CCM", 0, ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 }, + { GCRY_CIPHER_MODE_GCM, " GCM", 0, + NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN }, { GCRY_CIPHER_MODE_STREAM, "", 0 }, {0} }; -- 1.8.4.rc3 From jussi.kivilinna at iki.fi Fri Nov 8 14:43:35 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 08 Nov 2013 15:43:35 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> Message-ID: <527CEA87.6060900@iki.fi> On 08.11.2013 12:03, Dmitry Eremin-Solenikov wrote: > Currently it is still quite slow. > > Still no support for generate_iv(). Is it really necessary? > > TODO: Merge/reuse cipher-internal state used by CCM. > > Changelog entry will be present in final patch submission. > > Changes since v1: > - 6x-7x speedup. > - added bench-slope support > > Signed-off-by: Dmitry Eremin-Solenikov > --- > cipher/Makefile.am | 2 +- > cipher/cipher-ccm.c | 12 +- > cipher/cipher-gcm.c | 476 +++++++++++++++++++++++++++++++++++++++++++++++ > cipher/cipher-internal.h | 36 +++- > cipher/cipher.c | 32 ++++ > src/gcrypt.h.in | 6 +- > tests/basic.c | 337 +++++++++++++++++++++++++++++++++ > tests/bench-slope.c | 128 +++++++++++++ > tests/benchmark.c | 2 + > 9 files changed, 1023 insertions(+), 8 deletions(-) > create mode 100644 cipher/cipher-gcm.c > [snip] > +static void ghash(unsigned char *result, const unsigned char *buf, const unsigned char *gcmM) > +{ > + unsigned char V[16]; > + int i; > + > + buf_xor(V, result, buf, 16); > + > + memset(result, 0, 16); > + > + for (i = 15; i >= 0; i--) > + { > + byte A = result[15]; > + byte T[16]; > + int j; > + const byte *M = &gcmM[(V[i] & 0xf) * 16]; > + > + memmove(result+1, result, 15); > + result[0] = gcmR[A][0]; > + result[1] ^= gcmR[A][1]; > + > + T[0] = M[0] >> 4; > + for (j = 1; j < 16; j++) > + T[j] = (M[j] >> 4) | (M[j-1] << 4); > + T[0] ^= gcmR[(M[15] & 0xf) << 4][0]; > + T[1] ^= gcmR[(M[15] & 0xf) << 4][1]; > + buf_xor(T, T, &gcmM[(V[i] >> 4) * 16], 16); > + buf_xor(result, result, T, 16); > + } > +} > +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); Following is faster: static void bshift (u64 *b) { u64 t[2], mask; t[0] = be_bswap64(b[0]); t[1] = be_bswap64(b[1]); mask = t[1] & 1 ? 0xe1: 0; t[1] = (t[1] >> 1) | (t[0] << 63); t[0] = (t[0] >> 1) ^ (mask << 56); b[0] = be_bswap64(t[0]); b[1] = be_bswap64(t[1]); } static void fillM (unsigned char *h, u64 *M) { int i, j; M[0 * 2 + 0] = 0; M[0 * 2 + 1] = 0; buf_cpy (&M[8 * 2], h, 16); for (i = 4; i > 0; i /= 2) { M[i * 2 + 0] = M[2 * i * 2 + 0]; M[i * 2 + 1] = M[2 * i * 2 + 1]; bshift (&M[i * 2]); } for (i = 2; i < 16; i *= 2) for (j = 1; j < i; j++) buf_xor (&M[(i + j) * 2], &M[i * 2], &M[j * 2], 16); } static void ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) { unsigned char V[16]; u64 tmp[2] = {0,}; int i; byte A, m15; u64 T[2]; u64 y; const u64 *M; buf_xor (V, result, buf, 16); /* First round can be manually tweaked based on fact that 'tmp' is zero. */ i = 15; M = &gcmM[(V[i] & 0xf) * 2]; m15 = M[1] >> 56; T[0] = (M[0] >> 4) & 0x0f0f0f0f0f0f0f0fULL; T[1] = (M[1] >> 4) & 0x0f0f0f0f0f0f0f0fULL; T[0] |= (M[0] & 0x0f0f0f0f0f0f0f0fULL) << 12; T[1] |= (M[1] & 0x0f0f0f0f0f0f0f0fULL) << 12; T[1] |= (M[0] & 0x0f0f0f0f0f0f0f0fULL) >> (64 - 12); T[0] ^= gcmR[(m15 & 0xf) << 4][0] | (gcmR[(m15 & 0xf) << 4][1] << 8); tmp[0] = T[0] ^ gcmM[(V[i] >> 4) * 2 + 0]; tmp[1] = T[1] ^ gcmM[(V[i] >> 4) * 2 + 1]; for (--i; i >= 0; i--) { M = &gcmM[(V[i] & 0xf) * 2]; A = tmp[1] >> 56; y = tmp[0]; tmp[0] = (y << 8); tmp[1] = (y >> 56) | (tmp[1] << 8); tmp[0] ^= gcmR[A][0] | (gcmR[A][1] << 8); m15 = M[1] >> 56; T[0] = (M[0] >> 4) & 0x0f0f0f0f0f0f0f0fULL; T[1] = (M[1] >> 4) & 0x0f0f0f0f0f0f0f0fULL; T[0] |= (M[0] & 0x0f0f0f0f0f0f0f0fULL) << 12; T[1] |= (M[1] & 0x0f0f0f0f0f0f0f0fULL) << 12; T[1] |= (M[0] & 0x0f0f0f0f0f0f0f0fULL) >> (64 - 12); T[0] ^= gcmR[(m15 & 0xf) << 4][0] | (gcmR[(m15 & 0xf) << 4][1] << 8); tmp[0] ^= T[0] ^ gcmM[(V[i] >> 4) * 2 + 0]; tmp[1] ^= T[1] ^ gcmM[(V[i] >> 4) * 2 + 1]; } buf_cpy (result, tmp, 16); } Note, the cipher_handle->gcm_table is also changed to: #ifdef GCM_USE_TABLES u64 gcm_table[2 * 16]; /* pre-calculated table for GCM */ #endif Cortex-A8: old GCM auth | 228.5 ns/B 4.17 MiB/s 230.3 c/B new GCM auth | 87.30 ns/B 10.92 MiB/s 88.00 c/B Core i5-4570: old GCM auth | 26.22 ns/B 36.37 MiB/s 83.91 c/B new GCM auth | 5.02 ns/B 190.0 MiB/s 16.06 c/B Intel can be improved further with use of ctr-bulk encryption functions and ghash with clmul instruction. > + > +#else > + [snip] > + > + > +gcry_err_code_t > +_gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, > + byte *outbuf, unsigned int outbuflen, > + const byte *inbuf, unsigned int inbuflen) > +{ > + unsigned int n; > + int i; > + unsigned int blocksize = c->spec->blocksize; > + unsigned char tmp[MAX_BLOCKSIZE]; > + > + if (blocksize >= 0x20) > + return GPG_ERR_CIPHER_ALGO; > + if (blocksize != 0x10) > + return GPG_ERR_CIPHER_ALGO; The '>= 0x20' can removed. > + if (outbuflen < inbuflen) > + return GPG_ERR_BUFFER_TOO_SHORT; > + [snip] > + > +gcry_err_code_t > +_gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, > + byte *outbuf, unsigned int outbuflen, > + const byte *inbuf, unsigned int inbuflen) > +{ > + unsigned int n; > + int i; > + unsigned int blocksize = c->spec->blocksize; > + unsigned char tmp[MAX_BLOCKSIZE]; > + > + if (blocksize >= 0x20) > + return GPG_ERR_CIPHER_ALGO; > + if (blocksize != 0x10) > + return GPG_ERR_CIPHER_ALGO; Unnecessary '>= 0x20'. > + if (outbuflen < inbuflen) > + return GPG_ERR_BUFFER_TOO_SHORT; > + [snip] > +gcry_err_code_t > +_gcry_cipher_gcm_tag (gcry_cipher_hd_t c, > + byte *outbuf, unsigned int outbuflen, > + int check) > +{ > + if (outbuflen < 16) > + return GPG_ERR_BUFFER_TOO_SHORT; > + > + if (!c->marks.tag) > + { > + GHASH (c, c->u_tag.tag, c->length); > + buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16); > + c->marks.tag = 1; > + } > + memcpy (outbuf, c->u_tag.tag, 16); When doing the above optimizations of ghash, tests/basic did not first report any errors.. because of this memcpy. Overwrites the outbuf when should be doing 'check'. > + if (!check) > + { > + memcpy (outbuf, c->u_tag.tag, outbuflen); > + return GPG_ERR_NO_ERROR; > + } > + else > + { > + int diff, i; > + > + /* Constant-time compare. */ > + for (i = 0, diff = 0; i < outbuflen; i++) > + diff -= !!(outbuf[i] - c->u_tag.tag[i]); > + > + return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; > + } > + [snip] > > + /* The interim tag for GCM mode. */ > + union { > + cipher_context_alignment_t iv_align; > + unsigned char tag[MAX_BLOCKSIZE]; > + } u_tag; > + Maybe this and gcm_table could be moved within u_mode union. > /* Space to save an IV or CTR for chaining operations. */ > unsigned char lastiv[MAX_BLOCKSIZE]; > int unused; /* Number of unused bytes in LASTIV. */ > + unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ > +#ifdef GCM_USE_TABLES > + unsigned char gcm_table[16 * 16]; /* pre-calculated table for GCM */ > +#endif > [snip] > +gcry_err_code_t _gcry_cipher_gcm_get_tag > +/* */ (gcry_cipher_hd_t c, > + unsigned char *outbuf, unsigned int outbuflen); > +gcry_err_code_t _gcry_cipher_gcm_check_tag > +/* */ (gcry_cipher_hd_t c, > + const unsigned char *outbuf, unsigned int outbuflen); > Building with './configure --enable-maintainer-mode' fails here. Prototypes do not match with functions in cipher-gcm.c (unsigned int <=> size_t). > > #endif /*G10_CIPHER_INTERNAL_H*/ > diff --git a/cipher/cipher.c b/cipher/cipher.c [snip] > @@ -622,6 +630,8 @@ cipher_reset (gcry_cipher_hd_t c) > memset (c->u_ctr.ctr, 0, c->spec->blocksize); > memset (&c->u_mode, 0, sizeof c->u_mode); > c->unused = 0; > +/* memset (c->u_tag.tag, 0, c->spec->blocksize); > + memset (c->length, 0, c->spec->blocksize); */ Maybe u_mode can be cleared depending on currently selected mode, full clear for CCM and less for GCM. -Jussi From jussi.kivilinna at iki.fi Fri Nov 8 15:08:05 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 08 Nov 2013 16:08:05 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <527CEA87.6060900@iki.fi> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <527CEA87.6060900@iki.fi> Message-ID: <527CF045.6010406@iki.fi> On 08.11.2013 15:43, Jussi Kivilinna wrote: > On 08.11.2013 12:03, Dmitry Eremin-Solenikov wrote: >> +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); > > Following is faster: > But does not work on big-endian :P -Jussi From phcoder at gmail.com Fri Nov 8 15:19:14 2013 From: phcoder at gmail.com (=?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?=) Date: Fri, 08 Nov 2013 15:19:14 +0100 Subject: Signed division in idea.c Message-ID: <527CF2E2.5050909@gmail.com> Hello, all. While compiling in an environment with only libgcc subset for ARM, I found out that idea.c uses signed divisions: Reading the code this seems to be unintended. Inlined patch replaces them with more appropriate unsigned division. diff --git a/grub-core/lib/libgcrypt/cipher/idea.c b/grub-core/lib/libgcrypt/cipher/idea.c index c025c95..3c5578f 100644 --- a/grub-core/lib/libgcrypt/cipher/idea.c +++ b/grub-core/lib/libgcrypt/cipher/idea.c @@ -72,8 +72,8 @@ mul_inv( u16 x ) if( x < 2 ) return x; - t1 = 0x10001L / x; - y = 0x10001L % x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; if( y == 1 ) return (1-t1) & 0xffff; -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 291 bytes Desc: OpenPGP digital signature URL: From phcoder at gmail.com Fri Nov 8 16:58:54 2013 From: phcoder at gmail.com (=?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?=) Date: Fri, 08 Nov 2013 16:58:54 +0100 Subject: [PATCH] Replace division by zero with assert failure Message-ID: <527D0A3E.7070401@gmail.com> C specification says that division by zero is undefined and may not provoke a signal. So it would be more appropriate to use gcry_assert diff --git a/grub-core/lib/libgcrypt/mpi/mpi-pow.c b/grub-core/lib/libgcrypt/mpi/mpi-pow.c index a63fc6d..f5d2116 100644 --- a/grub-core/lib/libgcrypt/mpi/mpi-pow.c +++ b/grub-core/lib/libgcrypt/mpi/mpi-pow.c @@ -76,8 +76,7 @@ gcry_mpi_powm (gcry_mpi_t res, rp = res->d; ep = expo->d; - if (!msize) - msize = 1 / msize; /* Provoke a signal. */ + gcry_assert (msize != 0); if (!esize) { diff --git a/grub-core/lib/libgcrypt/mpi/mpih-div.c b/grub-core/lib/libgcrypt/mpi/mpih-div.c index 224b810..07dcf54 100644 --- a/grub-core/lib/libgcrypt/mpi/mpih-div.c +++ b/grub-core/lib/libgcrypt/mpi/mpih-div.c @@ -212,9 +212,9 @@ _gcry_mpih_divrem( mpi_ptr_t qp, mpi_size_t qextra_limbs, switch(dsize) { case 0: - /* We are asked to divide by zero, so go ahead and do it! (To make - the compiler not remove this statement, return the value.) */ - return 1 / dsize; + /* We are asked to divide by zero. */ + gcry_assert (0); + return 0; case 1: { -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 291 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Fri Nov 8 17:12:43 2013 From: wk at gnupg.org (Werner Koch) Date: Fri, 08 Nov 2013 17:12:43 +0100 Subject: [PATCH] Replace division by zero with assert failure In-Reply-To: <527D0A3E.7070401@gmail.com> ("Vladimir =?utf-8?Q?'=CF=86-cod?= =?utf-8?Q?er=2Fphcoder'?= Serbinenko"'s message of "Fri, 08 Nov 2013 16:58:54 +0100") References: <527D0A3E.7070401@gmail.com> Message-ID: <87ppqa50uc.fsf@vigenere.g10code.de> On Fri, 8 Nov 2013 16:58, phcoder at gmail.com said: > C specification says that division by zero is undefined and may not > provoke a signal. So it would be more appropriate to use gcry_assert Actually this changed some time ago. What we now do is to call void _gcry_divide_by_zero (void) { gpg_err_set_errno (EDOM); _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero"); } I am not sure whether it has or should be backported to 1.5. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Fri Nov 8 17:22:52 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 08 Nov 2013 17:22:52 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-371-ge241dde Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via e241dde1420475459e32608137829e52748d0212 (commit) from 9f63c0f7a3b2c15c7e258cd17395cabd0a8f00cc (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit e241dde1420475459e32608137829e52748d0212 Author: Werner Koch Date: Fri Nov 8 17:21:02 2013 +0100 cipher: Avoid signed divisions in idea.c * cipher/idea.c (mul_inv): Use unsigned division. -- Reported-by: Vladimir '?-coder/phcoder' Serbinenko Hello, all. While compiling in an environment with only libgcc subset for ARM, I found out that idea.c uses signed divisions: Reading the code this seems to be unintended. Inlined patch replaces them with more appropriate unsigned division. Signed-off-by: Werner Koch diff --git a/cipher/idea.c b/cipher/idea.c index 7d91a9a..14234cf 100644 --- a/cipher/idea.c +++ b/cipher/idea.c @@ -72,8 +72,8 @@ mul_inv( u16 x ) if( x < 2 ) return x; - t1 = 0x10001L / x; - y = 0x10001L % x; + t1 = 0x10001UL / x; + y = 0x10001UL % x; if( y == 1 ) return (1-t1) & 0xffff; ----------------------------------------------------------------------- Summary of changes: cipher/idea.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Fri Nov 8 17:18:02 2013 From: wk at gnupg.org (Werner Koch) Date: Fri, 08 Nov 2013 17:18:02 +0100 Subject: Signed division in idea.c In-Reply-To: <527CF2E2.5050909@gmail.com> ("Vladimir =?utf-8?Q?'=CF=86-cod?= =?utf-8?Q?er=2Fphcoder'?= Serbinenko"'s message of "Fri, 08 Nov 2013 15:19:14 +0100") References: <527CF2E2.5050909@gmail.com> Message-ID: <87li0y50lh.fsf@vigenere.g10code.de> On Fri, 8 Nov 2013 15:19, phcoder at gmail.com said: > Hello, all. While compiling in an environment with only libgcc subset > for ARM, I found out that idea.c uses signed divisions: > Reading the code this seems to be unintended. Inlined patch replaces > them with more appropriate unsigned division. Thanks, pushed to master (e241dde) Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From cvs at cvs.gnupg.org Fri Nov 8 17:43:22 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Fri, 08 Nov 2013 17:43:22 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-372-g03aed1a Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 03aed1acec611362285db5156a6b92c91604fba4 (commit) from e241dde1420475459e32608137829e52748d0212 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 03aed1acec611362285db5156a6b92c91604fba4 Author: Werner Koch Date: Fri Nov 8 17:41:42 2013 +0100 ecc: Improve gcry_pk_get_curve. * cipher/ecc-curves.c (_gcry_ecc_fill_in_curve): Factor some code out to .. (find_domain_parms_idx): new. (_gcry_ecc_get_curve): Find by curve name on error. -- This change allows the use of an input with just the curve name which can be used to test whether a given curve has been implemented. Is is required because due to the "param" flag change the caller usually does not have the key parameters available. Signed-off-by: Werner Koch diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 27d2d8e..12f539a 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -333,6 +333,36 @@ scanval (const char *string) } +/* Return the index of the domain_parms table for a curve with NAME. + Return -1 if not found. */ +static int +find_domain_parms_idx (const char *name) +{ + int idx, aliasno; + + /* First check our native curves. */ + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (name, domain_parms[idx].desc)) + return idx; + + /* If not found consult the alias table. */ + if (!domain_parms[idx].desc) + { + for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) + if (!strcmp (name, curve_aliases[aliasno].other)) + break; + if (curve_aliases[aliasno].name) + { + for (idx = 0; domain_parms[idx].desc; idx++) + if (!strcmp (curve_aliases[aliasno].name, domain_parms[idx].desc)) + return idx; + } + } + + return -1; +} + + /* Generate the crypto system setup. This function takes the NAME of a curve or the desired number of bits and stores at R_CURVE the parameters of the named curve or those of a suitable curve. If @@ -345,49 +375,25 @@ gpg_err_code_t _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, elliptic_curve_t *curve, unsigned int *r_nbits) { - int idx, aliasno; + int idx; const char *resname = NULL; /* Set to a found curve name. */ if (name) - { - /* First check our native curves. */ - for (idx = 0; domain_parms[idx].desc; idx++) - if (!strcmp (name, domain_parms[idx].desc)) - { - resname = domain_parms[idx].desc; - break; - } - /* If not found consult the alias table. */ - if (!domain_parms[idx].desc) - { - for (aliasno = 0; curve_aliases[aliasno].name; aliasno++) - if (!strcmp (name, curve_aliases[aliasno].other)) - break; - if (curve_aliases[aliasno].name) - { - for (idx = 0; domain_parms[idx].desc; idx++) - if (!strcmp (curve_aliases[aliasno].name, - domain_parms[idx].desc)) - { - resname = domain_parms[idx].desc; - break; - } - } - } - } + idx = find_domain_parms_idx (name); else { for (idx = 0; domain_parms[idx].desc; idx++) if (nbits == domain_parms[idx].nbits && domain_parms[idx].model == MPI_EC_WEIERSTRASS) - { - resname = domain_parms[idx].desc; - break; - } + break; + if (!domain_parms[idx].desc) + idx = -1; } - if (!domain_parms[idx].desc) + if (idx < 0) return GPG_ERR_UNKNOWN_CURVE; + resname = domain_parms[idx].desc; + /* In fips mode we only support NIST curves. Note that it is possible to bypass this check by specifying the curve parameters directly. */ @@ -440,6 +446,7 @@ _gcry_ecc_fill_in_curve (unsigned int nbits, const char *name, const char * _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits) { + gpg_err_code_t rc; const char *result = NULL; elliptic_curve_t E; gcry_mpi_t mpi_g = NULL; @@ -467,10 +474,39 @@ _gcry_ecc_get_curve (gcry_sexp_t keyparms, int iterator, unsigned int *r_nbits) /* * Extract the curve parameters.. */ - if (_gcry_sexp_extract_param (keyparms, NULL, "-pabgn", - &E.p, &E.a, &E.b, &mpi_g, &E.n, - NULL)) + rc = gpg_err_code (_gcry_sexp_extract_param (keyparms, NULL, "-pabgn", + &E.p, &E.a, &E.b, &mpi_g, &E.n, + NULL)); + if (rc == GPG_ERR_NO_OBJ) + { + /* This might be the second use case of checking whether a + specific curve given by name is supported. */ + gcry_sexp_t l1; + char *name; + + l1 = gcry_sexp_find_token (keyparms, "curve", 5); + if (!l1) + goto leave; /* No curve name parameter. */ + + name = _gcry_sexp_nth_string (l1, 1); + gcry_sexp_release (l1); + if (!name) + goto leave; /* Name missing or out of core. */ + + idx = find_domain_parms_idx (name); + gcry_free (name); + if (idx >= 0) /* Curve found. */ + { + result = domain_parms[idx].desc; + if (r_nbits) + *r_nbits = domain_parms[idx].nbits; + } + return result; + } + + if (rc) goto leave; + if (mpi_g) { _gcry_mpi_point_init (&E.G); ----------------------------------------------------------------------- Summary of changes: cipher/ecc-curves.c | 106 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 71 insertions(+), 35 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From andre at amorim.me Fri Nov 8 17:27:10 2013 From: andre at amorim.me (Andre Amorim) Date: Fri, 8 Nov 2013 16:27:10 +0000 Subject: [PATCH] Replace division by zero with assert failure In-Reply-To: <87ppqa50uc.fsf@vigenere.g10code.de> References: <527D0A3E.7070401@gmail.com> <87ppqa50uc.fsf@vigenere.g10code.de> Message-ID: off: //Its always blows my mind since I think in terms of circuits, anyways let me back to my fpga board Gnupg key: 02375205 Fingerprint: F7CD D181 943B 0453 8668 AF16 84E9 7565 0237 5205 On 8 November 2013 16:12, Werner Koch wrote: > On Fri, 8 Nov 2013 16:58, phcoder at gmail.com said: > > C specification says that division by zero is undefined and may not > > provoke a signal. So it would be more appropriate to use gcry_assert > > Actually this changed some time ago. What we now do is to call > > void > _gcry_divide_by_zero (void) > { > gpg_err_set_errno (EDOM); > _gcry_fatal_error (gpg_err_code_from_errno (errno), "divide by zero"); > } > > I am not sure whether it has or should be backported to 1.5. > > > Salam-Shalom, > > Werner > > -- > Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > -------------- next part -------------- An HTML attachment was scrubbed... URL: From sftp.mtuci at gmail.com Sat Nov 9 17:10:10 2013 From: sftp.mtuci at gmail.com (Sergey V.) Date: Sat, 09 Nov 2013 20:10:10 +0400 Subject: [PATCH] cipher/gost28147: optimization: use precomputed S-box tables In-Reply-To: <8738n75ips.fsf@vigenere.g10code.de> References: <5904457.oKotRVip6i@darkstar> <2066221.5IYa7Yq760@darkstar> <8738n75ips.fsf@vigenere.g10code.de> Message-ID: <1510012.cTDcks2t53@darkstar> * cipher/gost.h (GOST28147_context): Remove unneeded subst and subst_set members. * cipher/gost28147.c (max): Remove unneeded macro. (test_sbox): Replace with new precomputed tables. (gost_set_subst): Remove function. (gost_val): Use new S-box tables. (gost_encrypt_block, gost_decrypt_block): Tweak to use new ctx and S-box tables. -- Use generated 8->8 S-boxes with precomputed bitwise shifts and bitwise rotations. So in the round function gost_val() we no need to do this operations. Before this patch: GOST28147 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 24.00 ns/B 39.74 MiB/s - c/B ECB dec | 26.41 ns/B 36.11 MiB/s - c/B CBC enc | 24.57 ns/B 38.81 MiB/s - c/B CBC dec | 26.58 ns/B 35.88 MiB/s - c/B CFB enc | 24.79 ns/B 38.46 MiB/s - c/B CFB dec | 24.72 ns/B 38.57 MiB/s - c/B OFB enc | 24.38 ns/B 39.12 MiB/s - c/B OFB dec | 24.35 ns/B 39.16 MiB/s - c/B CTR enc | 24.83 ns/B 38.41 MiB/s - c/B CTR dec | 25.27 ns/B 37.73 MiB/s - c/B After: GOST28147 | nanosecs/byte mebibytes/sec cycles/byte ECB enc | 16.29 ns/B 58.55 MiB/s - c/B ECB dec | 16.30 ns/B 58.50 MiB/s - c/B CBC enc | 16.94 ns/B 56.29 MiB/s - c/B CBC dec | 16.81 ns/B 56.72 MiB/s - c/B CFB enc | 17.13 ns/B 55.66 MiB/s - c/B CFB dec | 16.84 ns/B 56.63 MiB/s - c/B OFB enc | 16.69 ns/B 57.13 MiB/s - c/B OFB dec | 16.71 ns/B 57.08 MiB/s - c/B CTR enc | 17.01 ns/B 56.06 MiB/s - c/B CTR dec | 17.05 ns/B 55.93 MiB/s - c/B Signed-off-by: Sergey V --- cipher/gost.h | 2 - cipher/gost28147.c | 328 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 272 insertions(+), 58 deletions(-) diff --git a/cipher/gost.h b/cipher/gost.h index 42021aa..d058eb2 100644 --- a/cipher/gost.h +++ b/cipher/gost.h @@ -21,9 +21,7 @@ #define _GCRY_GOST_H typedef struct { - u32 subst[4][256]; u32 key[8]; - int subst_set; } GOST28147_context; /* This is a simple interface that will be used by GOST R 34.11-94 */ diff --git a/cipher/gost28147.c b/cipher/gost28147.c index 2bda868..c094209 100644 --- a/cipher/gost28147.c +++ b/cipher/gost28147.c @@ -35,32 +35,273 @@ #include "cipher.h" -#define max(a, b) (((a) > (b)) ? (a) : (b)) - - /* This is an s-box from RFC4357, named GostR3411-94-TestParamSet * For now it is the only s-box supported, as libgcrypt lacks mechanism - * for passing parameters to cipher in a usefull way. */ -unsigned char test_sbox[16 * 8] = { - 0x4, 0xE, 0x5, 0x7, 0x6, 0x4, 0xD, 0x1, - 0xA, 0xB, 0x8, 0xD, 0xC, 0xB, 0xB, 0xF, - 0x9, 0x4, 0x1, 0xA, 0x7, 0xA, 0x4, 0xD, - 0x2, 0xC, 0xD, 0x1, 0x1, 0x0, 0x1, 0x0, - - 0xD, 0x6, 0xA, 0x0, 0x5, 0x7, 0x3, 0x5, - 0x8, 0xD, 0x3, 0x8, 0xF, 0x2, 0xF, 0x7, - 0x0, 0xF, 0x4, 0x9, 0xD, 0x1, 0x5, 0xA, - 0xE, 0xA, 0x2, 0xF, 0x8, 0xD, 0x9, 0x4, - - 0x6, 0x2, 0xE, 0xE, 0x4, 0x3, 0x0, 0x9, - 0xB, 0x3, 0xF, 0x4, 0xA, 0x6, 0xA, 0x2, - 0x1, 0x8, 0xC, 0x6, 0x9, 0x8, 0xE, 0x3, - 0xC, 0x1, 0x7, 0xC, 0xE, 0x5, 0x7, 0xE, - - 0x7, 0x0, 0x6, 0xB, 0x0, 0x9, 0x6, 0x6, - 0xF, 0x7, 0x0, 0x2, 0x3, 0xC, 0x8, 0xB, - 0x5, 0x5, 0x9, 0x5, 0xB, 0xF, 0x2, 0x8, - 0x3, 0x9, 0xB, 0x3, 0x2, 0xE, 0xC, 0xC, + * for passing parameters to cipher in a usefull way. + * S-boxes was modified from 4->4 to 8->8 bits unit with precalculated + * shift and rotation by optimisation reasons. + */ +static const u32 test_sbox[4][256] = { + /* 0 */ + { 0x00072000, 0x00075000, 0x00074800, 0x00071000, + 0x00076800, 0x00074000, 0x00070000, 0x00077000, + 0x00073000, 0x00075800, 0x00070800, 0x00076000, + 0x00073800, 0x00077800, 0x00072800, 0x00071800, + 0x0005a000, 0x0005d000, 0x0005c800, 0x00059000, + 0x0005e800, 0x0005c000, 0x00058000, 0x0005f000, + 0x0005b000, 0x0005d800, 0x00058800, 0x0005e000, + 0x0005b800, 0X0005F800, 0x0005a800, 0x00059800, + 0x00022000, 0x00025000, 0x00024800, 0x00021000, + 0x00026800, 0x00024000, 0x00020000, 0x00027000, + 0X00023000, 0x00025800, 0x00020800, 0x00026000, + 0x00023800, 0x00027800, 0x00022800, 0x00021800, + 0x00062000, 0x00065000, 0x00064800, 0x00061000, + 0x00066800, 0x00064000, 0x00060000, 0x00067000, + 0x00063000, 0x00065800, 0x00060800, 0x00066000, + 0x00063800, 0x00067800, 0x00062800, 0x00061800, + 0x00032000, 0x00035000, 0x00034800, 0x00031000, + 0x00036800, 0x00034000, 0x00030000, 0x00037000, + 0x00033000, 0x00035800, 0x00030800, 0x00036000, + 0x00033800, 0x00037800, 0x00032800, 0x00031800, + 0x0006a000, 0x0006d000, 0x0006c800, 0x00069000, + 0x0006e800, 0x0006c000, 0x00068000, 0x0006f000, + 0x0006b000, 0x0006d800, 0x00068800, 0x0006e000, + 0x0006b800, 0x0006f800, 0x0006a800, 0x00069800, + 0x0007a000, 0x0007d000, 0x0007c800, 0x00079000, + 0x0007e800, 0x0007c000, 0x00078000, 0x0007f000, + 0x0007b000, 0x0007d800, 0x00078800, 0x0007e000, + 0x0007b800, 0x0007f800, 0x0007a800, 0x00079800, + 0x00052000, 0x00055000, 0x00054800, 0x00051000, + 0x00056800, 0x00054000, 0x00050000, 0x00057000, + 0x00053000, 0x00055800, 0x00050800, 0x00056000, + 0x00053800, 0x00057800, 0x00052800, 0x00051800, + 0x00012000, 0x00015000, 0x00014800, 0x00011000, + 0x00016800, 0x00014000, 0x00010000, 0x00017000, + 0x00013000, 0x00015800, 0x00010800, 0x00016000, + 0x00013800, 0x00017800, 0x00012800, 0x00011800, + 0x0001a000, 0x0001d000, 0x0001c800, 0x00019000, + 0x0001e800, 0x0001c000, 0x00018000, 0x0001f000, + 0x0001b000, 0x0001d800, 0x00018800, 0x0001e000, + 0x0001b800, 0x0001f800, 0x0001a800, 0x00019800, + 0x00042000, 0x00045000, 0x00044800, 0x00041000, + 0x00046800, 0x00044000, 0x00040000, 0x00047000, + 0x00043000, 0x00045800, 0x00040800, 0x00046000, + 0x00043800, 0x00047800, 0x00042800, 0x00041800, + 0x0000a000, 0x0000d000, 0x0000c800, 0x00009000, + 0x0000e800, 0x0000c000, 0x00008000, 0x0000f000, + 0x0000b000, 0x0000d800, 0x00008800, 0x0000e000, + 0x0000b800, 0x0000f800, 0x0000a800, 0x00009800, + 0x00002000, 0x00005000, 0x00004800, 0x00001000, + 0x00006800, 0x00004000, 0x00000000, 0x00007000, + 0x00003000, 0x00005800, 0x00000800, 0x00006000, + 0x00003800, 0x00007800, 0x00002800, 0x00001800, + 0x0003a000, 0x0003d000, 0x0003c800, 0x00039000, + 0x0003e800, 0x0003c000, 0x00038000, 0x0003f000, + 0x0003b000, 0x0003d800, 0x00038800, 0x0003e000, + 0x0003b800, 0x0003f800, 0x0003a800, 0x00039800, + 0x0002a000, 0x0002d000, 0x0002c800, 0x00029000, + 0x0002e800, 0x0002c000, 0x00028000, 0x0002f000, + 0x0002b000, 0x0002d800, 0x00028800, 0x0002e000, + 0x0002b800, 0x0002f800, 0x0002a800, 0x00029800, + 0x0004a000, 0x0004d000, 0x0004c800, 0x00049000, + 0x0004e800, 0x0004c000, 0x00048000, 0x0004f000, + 0x0004b000, 0x0004d800, 0x00048800, 0x0004e000, + 0x0004b800, 0x0004f800, 0x0004a800, 0x00049800 }, + /* 1 */ + { 0x03a80000, 0x03c00000, 0x03880000, 0x03e80000, + 0x03d00000, 0x03980000, 0x03a00000, 0x03900000, + 0x03f00000, 0x03f80000, 0x03e00000, 0x03b80000, + 0x03b00000, 0x03800000, 0x03c80000, 0x03d80000, + 0x06a80000, 0x06c00000, 0x06880000, 0x06e80000, + 0x06d00000, 0x06980000, 0x06a00000, 0x06900000, + 0x06f00000, 0x06f80000, 0x06e00000, 0x06b80000, + 0x06b00000, 0x06800000, 0x06c80000, 0x06d80000, + 0x05280000, 0x05400000, 0x05080000, 0x05680000, + 0x05500000, 0x05180000, 0x05200000, 0x05100000, + 0x05700000, 0x05780000, 0x05600000, 0x05380000, + 0x05300000, 0x05000000, 0x05480000, 0x05580000, + 0x00a80000, 0x00c00000, 0x00880000, 0x00e80000, + 0x00d00000, 0x00980000, 0x00a00000, 0x00900000, + 0x00f00000, 0x00f80000, 0x00e00000, 0x00b80000, + 0x00b00000, 0x00800000, 0x00c80000, 0x00d80000, + 0x00280000, 0x00400000, 0x00080000, 0x00680000, + 0x00500000, 0x00180000, 0x00200000, 0x00100000, + 0x00700000, 0x00780000, 0x00600000, 0x00380000, + 0x00300000, 0x00000000, 0x00480000, 0x00580000, + 0x04280000, 0x04400000, 0x04080000, 0x04680000, + 0x04500000, 0x04180000, 0x04200000, 0x04100000, + 0x04700000, 0x04780000, 0x04600000, 0x04380000, + 0x04300000, 0x04000000, 0x04480000, 0x04580000, + 0x04a80000, 0x04c00000, 0x04880000, 0x04e80000, + 0x04d00000, 0x04980000, 0x04a00000, 0x04900000, + 0x04f00000, 0x04f80000, 0x04e00000, 0x04b80000, + 0x04b00000, 0x04800000, 0x04c80000, 0x04d80000, + 0x07a80000, 0x07c00000, 0x07880000, 0x07e80000, + 0x07d00000, 0x07980000, 0x07a00000, 0x07900000, + 0x07f00000, 0x07f80000, 0x07e00000, 0x07b80000, + 0x07b00000, 0x07800000, 0x07c80000, 0x07d80000, + 0x07280000, 0x07400000, 0x07080000, 0x07680000, + 0x07500000, 0x07180000, 0x07200000, 0x07100000, + 0x07700000, 0x07780000, 0x07600000, 0x07380000, + 0x07300000, 0x07000000, 0x07480000, 0x07580000, + 0x02280000, 0x02400000, 0x02080000, 0x02680000, + 0x02500000, 0x02180000, 0x02200000, 0x02100000, + 0x02700000, 0x02780000, 0x02600000, 0x02380000, + 0x02300000, 0x02000000, 0x02480000, 0x02580000, + 0x03280000, 0x03400000, 0x03080000, 0x03680000, + 0x03500000, 0x03180000, 0x03200000, 0x03100000, + 0x03700000, 0x03780000, 0x03600000, 0x03380000, + 0x03300000, 0x03000000, 0x03480000, 0x03580000, + 0x06280000, 0x06400000, 0x06080000, 0x06680000, + 0x06500000, 0x06180000, 0x06200000, 0x06100000, + 0x06700000, 0x06780000, 0x06600000, 0x06380000, + 0x06300000, 0x06000000, 0x06480000, 0x06580000, + 0x05a80000, 0x05c00000, 0x05880000, 0x05e80000, + 0x05d00000, 0x05980000, 0x05a00000, 0x05900000, + 0x05f00000, 0x05f80000, 0x05e00000, 0x05b80000, + 0x05b00000, 0x05800000, 0x05c80000, 0x05d80000, + 0x01280000, 0x01400000, 0x01080000, 0x01680000, + 0x01500000, 0x01180000, 0x01200000, 0x01100000, + 0x01700000, 0x01780000, 0x01600000, 0x01380000, + 0x01300000, 0x01000000, 0x01480000, 0x01580000, + 0x02a80000, 0x02c00000, 0x02880000, 0x02e80000, + 0x02d00000, 0x02980000, 0x02a00000, 0x02900000, + 0x02f00000, 0x02f80000, 0x02e00000, 0x02b80000, + 0x02b00000, 0x02800000, 0x02c80000, 0x02d80000, + 0x01a80000, 0x01c00000, 0x01880000, 0x01e80000, + 0x01d00000, 0x01980000, 0x01a00000, 0x01900000, + 0x01f00000, 0x01f80000, 0x01e00000, 0x01b80000, + 0x01b00000, 0x01800000, 0x01c80000, 0x01d80000 }, + /* 2 */ + { 0x30000002, 0x60000002, 0x38000002, 0x08000002, + 0x28000002, 0x78000002, 0x68000002, 0x40000002, + 0x20000002, 0x50000002, 0x48000002, 0x70000002, + 0x00000002, 0x18000002, 0x58000002, 0x10000002, + 0xb0000005, 0xe0000005, 0xb8000005, 0x88000005, + 0xa8000005, 0xf8000005, 0xe8000005, 0xc0000005, + 0xa0000005, 0xd0000005, 0xc8000005, 0xf0000005, + 0x80000005, 0x98000005, 0xd8000005, 0x90000005, + 0x30000005, 0x60000005, 0x38000005, 0x08000005, + 0x28000005, 0x78000005, 0x68000005, 0x40000005, + 0x20000005, 0x50000005, 0x48000005, 0x70000005, + 0x00000005, 0x18000005, 0x58000005, 0x10000005, + 0x30000000, 0x60000000, 0x38000000, 0x08000000, + 0x28000000, 0x78000000, 0x68000000, 0x40000000, + 0x20000000, 0x50000000, 0x48000000, 0x70000000, + 0x00000000, 0x18000000, 0x58000000, 0x10000000, + 0xb0000003, 0xe0000003, 0xb8000003, 0x88000003, + 0xa8000003, 0xf8000003, 0xe8000003, 0xc0000003, + 0xa0000003, 0xd0000003, 0xc8000003, 0xf0000003, + 0x80000003, 0x98000003, 0xd8000003, 0x90000003, + 0x30000001, 0x60000001, 0x38000001, 0x08000001, + 0x28000001, 0x78000001, 0x68000001, 0x40000001, + 0x20000001, 0x50000001, 0x48000001, 0x70000001, + 0x00000001, 0x18000001, 0x58000001, 0x10000001, + 0xb0000000, 0xe0000000, 0xb8000000, 0x88000000, + 0xa8000000, 0xf8000000, 0xe8000000, 0xc0000000, + 0xa0000000, 0xd0000000, 0xc8000000, 0xf0000000, + 0x80000000, 0x98000000, 0xd8000000, 0x90000000, + 0xb0000006, 0xe0000006, 0xb8000006, 0x88000006, + 0xa8000006, 0xf8000006, 0xe8000006, 0xc0000006, + 0xa0000006, 0xd0000006, 0xc8000006, 0xf0000006, + 0x80000006, 0x98000006, 0xd8000006, 0x90000006, + 0xb0000001, 0xe0000001, 0xb8000001, 0x88000001, + 0xa8000001, 0xf8000001, 0xe8000001, 0xc0000001, + 0xa0000001, 0xd0000001, 0xc8000001, 0xf0000001, + 0x80000001, 0x98000001, 0xd8000001, 0x90000001, + 0x30000003, 0x60000003, 0x38000003, 0x08000003, + 0x28000003, 0x78000003, 0x68000003, 0x40000003, + 0x20000003, 0x50000003, 0x48000003, 0x70000003, + 0x00000003, 0x18000003, 0x58000003, 0x10000003, + 0x30000004, 0x60000004, 0x38000004, 0x08000004, + 0x28000004, 0x78000004, 0x68000004, 0x40000004, + 0x20000004, 0x50000004, 0x48000004, 0x70000004, + 0x00000004, 0x18000004, 0x58000004, 0x10000004, + 0xb0000002, 0xe0000002, 0xb8000002, 0x88000002, + 0xa8000002, 0xf8000002, 0xe8000002, 0xc0000002, + 0xa0000002, 0xd0000002, 0xc8000002, 0xf0000002, + 0x80000002, 0x98000002, 0xd8000002, 0x90000002, + 0xb0000004, 0xe0000004, 0xb8000004, 0x88000004, + 0xa8000004, 0xf8000004, 0xe8000004, 0xc0000004, + 0xa0000004, 0xd0000004, 0xc8000004, 0xf0000004, + 0x80000004, 0x98000004, 0xd8000004, 0x90000004, + 0x30000006, 0x60000006, 0x38000006, 0x08000006, + 0x28000006, 0x78000006, 0x68000006, 0x40000006, + 0x20000006, 0x50000006, 0x48000006, 0x70000006, + 0x00000006, 0x18000006, 0x58000006, 0x10000006, + 0xb0000007, 0xe0000007, 0xb8000007, 0x88000007, + 0xa8000007, 0xf8000007, 0xe8000007, 0xc0000007, + 0xa0000007, 0xd0000007, 0xc8000007, 0xf0000007, + 0x80000007, 0x98000007, 0xd8000007, 0x90000007, + 0x30000007, 0x60000007, 0x38000007, 0x08000007, + 0x28000007, 0x78000007, 0x68000007, 0x40000007, + 0x20000007, 0x50000007, 0x48000007, 0x70000007, + 0x00000007, 0x18000007, 0x58000007, 0x10000007 }, + /* 3 */ + { 0x000000e8, 0x000000d8, 0x000000a0, 0x00000088, + 0x00000098, 0x000000f8, 0x000000a8, 0x000000c8, + 0x00000080, 0x000000d0, 0x000000f0, 0x000000b8, + 0x000000b0, 0x000000c0, 0x00000090, 0x000000e0, + 0x000007e8, 0x000007d8, 0x000007a0, 0x00000788, + 0x00000798, 0x000007f8, 0x000007a8, 0x000007c8, + 0x00000780, 0x000007d0, 0x000007f0, 0x000007b8, + 0x000007b0, 0x000007c0, 0x00000790, 0x000007e0, + 0x000006e8, 0x000006d8, 0x000006a0, 0x00000688, + 0x00000698, 0x000006f8, 0x000006a8, 0x000006c8, + 0x00000680, 0x000006d0, 0x000006f0, 0x000006b8, + 0x000006b0, 0x000006c0, 0x00000690, 0x000006e0, + 0x00000068, 0x00000058, 0x00000020, 0x00000008, + 0x00000018, 0x00000078, 0x00000028, 0x00000048, + 0x00000000, 0x00000050, 0x00000070, 0x00000038, + 0x00000030, 0x00000040, 0x00000010, 0x00000060, + 0x000002e8, 0x000002d8, 0x000002a0, 0x00000288, + 0x00000298, 0x000002f8, 0x000002a8, 0x000002c8, + 0x00000280, 0x000002d0, 0x000002f0, 0x000002b8, + 0x000002b0, 0x000002c0, 0x00000290, 0x000002e0, + 0x000003e8, 0x000003d8, 0x000003a0, 0x00000388, + 0x00000398, 0x000003f8, 0x000003a8, 0x000003c8, + 0x00000380, 0x000003d0, 0x000003f0, 0x000003b8, + 0x000003b0, 0x000003c0, 0x00000390, 0x000003e0, + 0x00000568, 0x00000558, 0x00000520, 0x00000508, + 0x00000518, 0x00000578, 0x00000528, 0x00000548, + 0x00000500, 0x00000550, 0x00000570, 0x00000538, + 0x00000530, 0x00000540, 0x00000510, 0x00000560, + 0x00000268, 0x00000258, 0x00000220, 0x00000208, + 0x00000218, 0x00000278, 0x00000228, 0x00000248, + 0x00000200, 0x00000250, 0x00000270, 0x00000238, + 0x00000230, 0x00000240, 0x00000210, 0x00000260, + 0x000004e8, 0x000004d8, 0x000004a0, 0x00000488, + 0x00000498, 0x000004f8, 0x000004a8, 0x000004c8, + 0x00000480, 0x000004d0, 0x000004f0, 0x000004b8, + 0x000004b0, 0x000004c0, 0x00000490, 0x000004e0, + 0x00000168, 0x00000158, 0x00000120, 0x00000108, + 0x00000118, 0x00000178, 0x00000128, 0x00000148, + 0x00000100, 0x00000150, 0x00000170, 0x00000138, + 0x00000130, 0x00000140, 0x00000110, 0x00000160, + 0x000001e8, 0x000001d8, 0x000001a0, 0x00000188, + 0x00000198, 0x000001f8, 0x000001a8, 0x000001c8, + 0x00000180, 0x000001d0, 0x000001f0, 0x000001b8, + 0x000001b0, 0x000001c0, 0x00000190, 0x000001e0, + 0x00000768, 0x00000758, 0x00000720, 0x00000708, + 0x00000718, 0x00000778, 0x00000728, 0x00000748, + 0x00000700, 0x00000750, 0x00000770, 0x00000738, + 0x00000730, 0x00000740, 0x00000710, 0x00000760, + 0x00000368, 0x00000358, 0x00000320, 0x00000308, + 0x00000318, 0x00000378, 0x00000328, 0x00000348, + 0x00000300, 0x00000350, 0x00000370, 0x00000338, + 0x00000330, 0x00000340, 0x00000310, 0x00000360, + 0x000005e8, 0x000005d8, 0x000005a0, 0x00000588, + 0x00000598, 0x000005f8, 0x000005a8, 0x000005c8, + 0x00000580, 0x000005d0, 0x000005f0, 0x000005b8, + 0x000005b0, 0x000005c0, 0x00000590, 0x000005e0, + 0x00000468, 0x00000458, 0x00000420, 0x00000408, + 0x00000418, 0x00000478, 0x00000428, 0x00000448, + 0x00000400, 0x00000450, 0x00000470, 0x00000438, + 0x00000430, 0x00000440, 0x00000410, 0x00000460, + 0x00000668, 0x00000658, 0x00000620, 0x00000608, + 0x00000618, 0x00000678, 0x00000628, 0x00000648, + 0x00000600, 0x00000650, 0x00000670, 0x00000638, + 0x00000630, 0x00000640, 0x00000610, 0x00000660 } }; #include "gost.h" @@ -84,30 +325,15 @@ gost_setkey (void *c, const byte *key, unsigned keylen) return GPG_ERR_NO_ERROR; } -static void -gost_set_subst (GOST28147_context *ctx, unsigned char *sbox) -{ - unsigned i, j; - for (i = 0; i < 4; i++) - { - for (j = 0; j < 256; j++) - { - ctx->subst[i][j] = sbox[ (j & 0xf) * 8 + 2 * i + 0] | - (sbox[ (j >> 4) * 8 + 2 * i + 1] << 4); - } - } - ctx->subst_set = 1; -} - static u32 gost_val (GOST28147_context *ctx, u32 cm1, int subkey) { cm1 += ctx->key[subkey]; - cm1 = (ctx->subst[0][ (cm1 >> 0) & 0xff] << 0) | - (ctx->subst[1][ (cm1 >> 8) & 0xff] << 8) | - (ctx->subst[2][ (cm1 >> 16) & 0xff] << 16) | - (ctx->subst[3][ (cm1 >> 24) & 0xff] << 24); - return (cm1 << 11) | (cm1 >> 21); + cm1 = test_sbox[0][ (cm1 >> 0) & 0xff] | + test_sbox[1][ (cm1 >> 8) & 0xff] | + test_sbox[2][ (cm1 >> 16) & 0xff] | + test_sbox[3][ (cm1 >> 24) & 0xff]; + return cm1; } static unsigned int @@ -116,9 +342,6 @@ gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) GOST28147_context *ctx = c; u32 n1, n2; - if (!ctx->subst_set) - gost_set_subst (ctx, test_sbox); - n1 = (inbuf[0] << 0) | (inbuf[1] << 8) | (inbuf[2] << 16) | @@ -159,9 +382,7 @@ gost_encrypt_block (void *c, byte *outbuf, const byte *inbuf) return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + - max( 4*sizeof(void*) /* gost_val call */, - 3*sizeof(void*) /* gost_set_subst call */ + - 2*sizeof(void*) /* gost_set subst stack*/ ); + 4*sizeof(void*) /* gost_val call */; } unsigned int _gcry_gost_enc_one (GOST28147_context *c, const byte *key, @@ -177,9 +398,6 @@ gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) GOST28147_context *ctx = c; u32 n1, n2; - if (!ctx->subst_set) - gost_set_subst (ctx, test_sbox); - n1 = (inbuf[0] << 0) | (inbuf[1] << 8) | (inbuf[2] << 16) | @@ -220,9 +438,7 @@ gost_decrypt_block (void *c, byte *outbuf, const byte *inbuf) return /* burn_stack */ 4*sizeof(void*) /* func call */ + 3*sizeof(void*) /* stack */ + - max( 4*sizeof(void*) /* gost_val call */, - 3*sizeof(void*) /* gost_set_subst call */ + - 2*sizeof(void*) /* gost_set subst stack*/ ); + 4*sizeof(void*) /* gost_val call */; } gcry_cipher_spec_t _gcry_cipher_spec_gost28147 = -- 1.7.12.1 -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 836 bytes Desc: This is a digitally signed message part. URL: From cvs at cvs.gnupg.org Sat Nov 9 20:05:08 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 09 Nov 2013 20:05:08 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-373-g60ed0ab Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 60ed0abbbc7cb15812f1e713143c72555acea69e (commit) from 03aed1acec611362285db5156a6b92c91604fba4 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 60ed0abbbc7cb15812f1e713143c72555acea69e Author: Jussi Kivilinna Date: Sat Nov 9 21:04:14 2013 +0200 Fix tail handling for AES-NI counter mode * cipher/rijndael.c (do_aesni_ctr): Fix outputting of updated counter-IV. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/rijndael.c b/cipher/rijndael.c index cbdbbd8..b5a3d10 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1369,13 +1369,12 @@ do_aesni_ctr (const RIJNDAEL_context *ctx, #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" - asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0, xmm2 := CTR (xmm5) */ - "movdqa %%xmm0, %%xmm2\n\t" + asm volatile ("movdqa %%xmm5, %%xmm0\n\t" /* xmm0 := CTR (xmm5) */ "pcmpeqd %%xmm1, %%xmm1\n\t" "psrldq $8, %%xmm1\n\t" /* xmm1 = -1 */ - "pshufb %%xmm6, %%xmm2\n\t" - "psubq %%xmm1, %%xmm2\n\t" /* xmm2++ (big endian) */ + "pshufb %%xmm6, %%xmm5\n\t" + "psubq %%xmm1, %%xmm5\n\t" /* xmm5++ (big endian) */ /* detect if 64-bit carry handling is needed */ "cmpl $0xffffffff, 8(%[ctr])\n\t" @@ -1384,12 +1383,12 @@ do_aesni_ctr (const RIJNDAEL_context *ctx, "jne .Lno_carry%=\n\t" "pslldq $8, %%xmm1\n\t" /* move lower 64-bit to high */ - "psubq %%xmm1, %%xmm2\n\t" /* add carry to upper 64bits */ + "psubq %%xmm1, %%xmm5\n\t" /* add carry to upper 64bits */ ".Lno_carry%=:\n\t" - "pshufb %%xmm6, %%xmm2\n\t" - "movdqa %%xmm2, (%[ctr])\n\t" /* Update CTR (mem). */ + "pshufb %%xmm6, %%xmm5\n\t" + "movdqa %%xmm5, (%[ctr])\n\t" /* Update CTR (mem). */ "pxor (%[key]), %%xmm0\n\t" /* xmm1 ^= key[0] */ "movdqa 0x10(%[key]), %%xmm1\n\t" ----------------------------------------------------------------------- Summary of changes: cipher/rijndael.c | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From wk at gnupg.org Sat Nov 9 21:15:46 2013 From: wk at gnupg.org (Werner Koch) Date: Sat, 09 Nov 2013 21:15:46 +0100 Subject: [PATCH] cipher/gost28147: optimization: use precomputed S-box tables In-Reply-To: <1510012.cTDcks2t53@darkstar> (Sergey V.'s message of "Sat, 09 Nov 2013 20:10:10 +0400") References: <5904457.oKotRVip6i@darkstar> <2066221.5IYa7Yq760@darkstar> <8738n75ips.fsf@vigenere.g10code.de> <1510012.cTDcks2t53@darkstar> Message-ID: <874n7l49hp.fsf@vigenere.g10code.de> Pushed. Thanks. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Mon Nov 11 13:46:23 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 11 Nov 2013 14:46:23 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <527CF045.6010406@iki.fi> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <527CEA87.6060900@iki.fi> <527CF045.6010406@iki.fi> Message-ID: <5280D19F.2050305@iki.fi> On 08.11.2013 16:08, Jussi Kivilinna wrote: > On 08.11.2013 15:43, Jussi Kivilinna wrote: >> On 08.11.2013 12:03, Dmitry Eremin-Solenikov wrote: >>> +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); >> >> Following is faster: >> > > But does not work on big-endian :P > I ended up doing small patch-set on top of this patch, which adds more optimized versions of generic ghash for 32-bit (~33 cpb on Cortex-A8) and 64-bit machines (~11 cpb on Intel Haswell, ~16 on Intel Core2). I've also added Intel PCLMUL acceleration which gets GCM-auth to ~0.83 cpb on haswell. Patches are at https://github.com/jkivilin/libgcrypt/commits/gcm So, do we make v3 of this initial implementation and rebase these patches on it or do I push v2 and these patches to repo and we'll work on from there? -Jussi From dbaryshkov at gmail.com Mon Nov 11 14:02:30 2013 From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov) Date: Mon, 11 Nov 2013 17:02:30 +0400 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <5280D19F.2050305@iki.fi> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <527CEA87.6060900@iki.fi> <527CF045.6010406@iki.fi> <5280D19F.2050305@iki.fi> Message-ID: Hello, On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna wrote: > On 08.11.2013 16:08, Jussi Kivilinna wrote: >> On 08.11.2013 15:43, Jussi Kivilinna wrote: >>> On 08.11.2013 12:03, Dmitry Eremin-Solenikov wrote: >>>> +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); >>> >>> Following is faster: >>> >> >> But does not work on big-endian :P >> > > I ended up doing small patch-set on top of this patch, which adds more optimized > versions of generic ghash for 32-bit (~33 cpb on Cortex-A8) and 64-bit machines > (~11 cpb on Intel Haswell, ~16 on Intel Core2). I've also added Intel PCLMUL > acceleration which gets GCM-auth to ~0.83 cpb on haswell. > > Patches are at > https://github.com/jkivilin/libgcrypt/commits/gcm > > So, do we make v3 of this initial implementation and rebase these patches on it > or do I push v2 and these patches to repo and we'll work on from there? I'm unsure about generate_iv/set_iv argument. More on that here: http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/focus=2897 I'm fine with pushing this version of patches (I have to write proper changelog though) + your patches on top of that (have you tested big-endian? I can execute tests on G5 in a few hours). -- With best wishes Dmitry From jussi.kivilinna at iki.fi Mon Nov 11 15:09:32 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 11 Nov 2013 16:09:32 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <527CEA87.6060900@iki.fi> <527CF045.6010406@iki.fi> <5280D19F.2050305@iki.fi> Message-ID: <5280E51C.4040509@iki.fi> On 11.11.2013 15:02, Dmitry Eremin-Solenikov wrote: > Hello, > > On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna wrote: >> On 08.11.2013 16:08, Jussi Kivilinna wrote: >>> On 08.11.2013 15:43, Jussi Kivilinna wrote: >>>> On 08.11.2013 12:03, Dmitry Eremin-Solenikov wrote: >>>>> +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); >>>> >>>> Following is faster: >>>> >>> >>> But does not work on big-endian :P >>> >> >> I ended up doing small patch-set on top of this patch, which adds more optimized >> versions of generic ghash for 32-bit (~33 cpb on Cortex-A8) and 64-bit machines >> (~11 cpb on Intel Haswell, ~16 on Intel Core2). I've also added Intel PCLMUL >> acceleration which gets GCM-auth to ~0.83 cpb on haswell. >> >> Patches are at >> https://github.com/jkivilin/libgcrypt/commits/gcm >> >> So, do we make v3 of this initial implementation and rebase these patches on it >> or do I push v2 and these patches to repo and we'll work on from there? > > I'm unsure about generate_iv/set_iv argument. More on that here: > http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/focus=2897 > How is this handled in other libraries? > I'm fine with pushing this version of patches (I have to write proper > changelog though) > + your patches on top of that (have you tested big-endian? I can > execute tests on G5 > in a few hours). I've tested 32-bit and 64-bit binaries with qemu-powerpc. -Jussi From jussi.kivilinna at iki.fi Mon Nov 11 16:48:40 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 11 Nov 2013 17:48:40 +0200 Subject: [PATCH] Avoid unneeded stack burning with AES-NI and reduce number of 'decryption_prepared' checks Message-ID: <20131111154840.15120.79814.stgit@localhost6.localdomain6> * cipher/rijndael.c (RIJNDAEL_context): Make 'decryption_prepared', 'use_padlock' and 'use_aesni' 1-bit members in bitfield. (do_setkey): Move 'hwfeatures' inside [USE_AESNI ||?USE_PADLOCK]. (do_aesni_enc_aligned): Rename to... (do_aesni_enc): ...this, as function does not require aligned input. (do_aesni_dec_aligned): Rename to... (do_aesni_dec): ...this, as function does not require aligned input. (do_aesni): Remove. (rijndael_encrypt): Call 'do_aesni_enc' instead of 'do_aesni'. (rijndael_decrypt): Call 'do_aesni_dec' instead of 'do_aesni'. (check_decryption_preparation): New. (do_decrypt): Remove 'decryption_prepared' check. (rijndael_decrypt): Ditto and call 'check_decryption_preparation'. (_gcry_aes_cbc_dec): Ditto. (_gcry_aes_cfb_enc): Add 'burn_depth' and burn stack only when needed. (_gcry_aes_cbc_enc): Ditto. (_gcry_aes_ctr_enc): Ditto. (_gcry_aes_cfb_dec): Ditto. (_gcry_aes_cbc_dec): Ditto and correct clearing of 'savebuf'. -- Patch is mostly about reducing overhead for short buffers. Results on Intel i5-4570: After: $ tests/benchmark --cipher-repetitions 1000 --cipher-with-keysetup cipher aes Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 480ms 540ms 1750ms 300ms 1630ms 300ms 1640ms 1640ms 350ms 350ms 2130ms 2140ms Before: $ tests/benchmark --cipher-repetitions 1000 --cipher-with-keysetup cipher aes Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 520ms 590ms 1760ms 310ms 1640ms 310ms 1610ms 1600ms 360ms 360ms 2150ms 2160ms Signed-off-by: Jussi Kivilinna --- cipher/rijndael.c | 158 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 69 deletions(-) diff --git a/cipher/rijndael.c b/cipher/rijndael.c index b5a3d10..77c6b93 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -163,13 +163,13 @@ typedef struct PROPERLY_ALIGNED_TYPE dummy; byte keyschedule[MAXROUNDS+1][4][4]; } u2; - int rounds; /* Key-length-dependent number of rounds. */ - int decryption_prepared; /* The decryption key schedule is available. */ + int rounds; /* Key-length-dependent number of rounds. */ + int decryption_prepared:1; /* The decryption key schedule is available. */ #ifdef USE_PADLOCK - int use_padlock; /* Padlock shall be used. */ + int use_padlock:1; /* Padlock shall be used. */ #endif /*USE_PADLOCK*/ #ifdef USE_AESNI - int use_aesni; /* AES-NI shall be used. */ + int use_aesni:1; /* AES-NI shall be used. */ #endif /*USE_AESNI*/ } RIJNDAEL_context ATTR_ALIGNED_16; @@ -465,7 +465,9 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) int rounds; int i,j, r, t, rconpointer = 0; int KC; +#if defined(USE_AESNI) || defined(USE_PADLOCK) unsigned int hwfeatures; +#endif /* The on-the-fly self tests are only run in non-fips mode. In fips mode explicit self-tests are required. Actually the on-the-fly @@ -959,9 +961,9 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, back. If we decide to implement some block modes with parallelized AES instructions, it might indeed be better to use plain asm ala mpi/. */ -static void -do_aesni_enc_aligned (const RIJNDAEL_context *ctx, - unsigned char *b, const unsigned char *a) +static inline void +do_aesni_enc (const RIJNDAEL_context *ctx, unsigned char *b, + const unsigned char *a) { #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" @@ -1019,9 +1021,9 @@ do_aesni_enc_aligned (const RIJNDAEL_context *ctx, } -static void -do_aesni_dec_aligned (const RIJNDAEL_context *ctx, - unsigned char *b, const unsigned char *a) +static inline void +do_aesni_dec (const RIJNDAEL_context *ctx, unsigned char *b, + const unsigned char *a) { #define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t" #define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t" @@ -1626,24 +1628,6 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, #undef aesenclast_xmm1_xmm4 } - -static void -do_aesni (RIJNDAEL_context *ctx, int decrypt_flag, - unsigned char *bx, const unsigned char *ax) -{ - - if (decrypt_flag) - { - if (!ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - do_aesni_dec_aligned (ctx, bx, ax); - } - else - do_aesni_enc_aligned (ctx, bx, ax); -} #endif /*USE_AESNI*/ @@ -1666,7 +1650,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a) else if (ctx->use_aesni) { aesni_prepare (); - do_aesni (ctx, 0, b, a); + do_aesni_enc (ctx, b, a); aesni_cleanup (); burn_stack = 0; } @@ -1693,6 +1677,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); if (0) ; @@ -1722,6 +1707,8 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, inbuf += BLOCKSIZE; } aesni_cleanup (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -1737,7 +1724,8 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -1754,9 +1742,13 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char *last_iv; + unsigned int burn_depth = 48 + 2*sizeof(int); +#ifdef USE_AESNI + int use_aesni = ctx->use_aesni; +#endif #ifdef USE_AESNI - if (ctx->use_aesni) + if (use_aesni) aesni_prepare (); #endif /*USE_AESNI*/ @@ -1767,7 +1759,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, if (0) ; #ifdef USE_AESNI - else if (ctx->use_aesni) + else if (use_aesni) { /* ~35% speed up on Sandy-Bridge when doing xoring and copying with SSE registers. */ @@ -1781,7 +1773,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, [outbuf] "m" (*outbuf) : "memory" ); - do_aesni (ctx, 0, outbuf, outbuf); + do_aesni_enc (ctx, outbuf, outbuf); } #endif /*USE_AESNI*/ else @@ -1809,7 +1801,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, if (0) ; #ifdef USE_AESNI - else if (ctx->use_aesni) + else if (use_aesni) asm volatile ("movdqu %[last], %%xmm0\n\t" "movdqu %%xmm0, %[iv]\n\t" : /* No output */ @@ -1822,11 +1814,15 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, } #ifdef USE_AESNI - if (ctx->use_aesni) - aesni_cleanup (); + if (use_aesni) + { + aesni_cleanup (); + burn_depth = 0; /* No stack usage. */ + } #endif /*USE_AESNI*/ - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -1843,6 +1839,7 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); int i; if (0) @@ -1876,6 +1873,8 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, } aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -1900,7 +1899,8 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -2007,12 +2007,6 @@ do_decrypt_aligned (RIJNDAEL_context *ctx, static void do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) { - if ( !ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - #if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM) /* BX and AX are not necessary correctly aligned. Thus we might need to copy them here. We try to align to a 16 bytes. */ @@ -2041,6 +2035,21 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) } +static inline void +check_decryption_preparation (RIJNDAEL_context *ctx) +{ + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { /* Padlock does not need decryption subkeys. */ } +#endif /*USE_PADLOCK*/ + else if ( !ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + ctx->decryption_prepared = 1; + } +} static unsigned int @@ -2049,6 +2058,8 @@ rijndael_decrypt (void *context, byte *b, const byte *a) RIJNDAEL_context *ctx = context; unsigned int burn_stack; + check_decryption_preparation (ctx); + if (0) ; #ifdef USE_PADLOCK @@ -2062,7 +2073,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a) else if (ctx->use_aesni) { aesni_prepare (); - do_aesni (ctx, 1, b, a); + do_aesni_dec (ctx, b, a); aesni_cleanup (); burn_stack = 0; } @@ -2089,6 +2100,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); if (0) ; @@ -2161,6 +2173,8 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, } aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -2174,7 +2188,8 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -2190,7 +2205,9 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; - unsigned char savebuf[BLOCKSIZE]; + unsigned int burn_depth = 48 + 2*sizeof(int) + 4*sizeof (char*); + + check_decryption_preparation (ctx); if (0) ; @@ -2199,12 +2216,6 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, { aesni_prepare (); - if (!ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - asm volatile ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */ : /* No output */ @@ -2259,7 +2270,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, : "memory"); /* uses only xmm0 and xmm1 */ - do_aesni_dec_aligned (ctx, outbuf, inbuf); + do_aesni_dec (ctx, outbuf, inbuf); asm volatile ("movdqu %[outbuf], %%xmm0\n\t" @@ -2282,29 +2293,38 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else - for ( ;nblocks; nblocks-- ) - { - /* INBUF is needed later and it may be identical to OUTBUF, so store - the intermediate result to SAVEBUF. */ + { + unsigned char savebuf[BLOCKSIZE]; - if (0) - ; + for ( ;nblocks; nblocks-- ) + { + /* INBUF is needed later and it may be identical to OUTBUF, so store + the intermediate result to SAVEBUF. */ + + if (0) + ; #ifdef USE_PADLOCK - else if (ctx->use_padlock) - do_padlock (ctx, 1, savebuf, inbuf); + else if (ctx->use_padlock) + do_padlock (ctx, 1, savebuf, inbuf); #endif /*USE_PADLOCK*/ - else - do_decrypt (ctx, savebuf, inbuf); + else + do_decrypt (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); - inbuf += BLOCKSIZE; - outbuf += BLOCKSIZE; - } + buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); + inbuf += BLOCKSIZE; + outbuf += BLOCKSIZE; + } + + wipememory(savebuf, sizeof(savebuf)); + } - _gcry_burn_stack (48 + 2*sizeof(int) + BLOCKSIZE + 4*sizeof (char*)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } From smueller at chronox.de Wed Nov 13 04:42:57 2013 From: smueller at chronox.de (Stephan Mueller) Date: Wed, 13 Nov 2013 04:42:57 +0100 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <5280E51C.4040509@iki.fi> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <5280E51C.4040509@iki.fi> Message-ID: <2097574.VOKJ6vsnNC@myon.chronox.de> Am Montag, 11. November 2013, 16:09:32 schrieb Jussi Kivilinna: Hi Jussi, > On 11.11.2013 15:02, Dmitry Eremin-Solenikov wrote: > > Hello, > > > > On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna wrote: [..] > > I'm unsure about generate_iv/set_iv argument. More on that here: > > http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/foc > > us=2897 > How is this handled in other libraries? All libraries that undergo or underwent a FIPS 140-2 validation have appropriate handling here. As libgcrypt has a FIPS mode, it looks like FIPS is of importance. If so, either the handling is implemented or GCM cannot be allowed in FIPS mode. Ciao Stephan -- | Cui bono? | From cvs at cvs.gnupg.org Wed Nov 13 09:49:04 2013 From: cvs at cvs.gnupg.org (by Christian Grothoff) Date: Wed, 13 Nov 2013 09:49:04 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-379-gc4f9af4 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via c4f9af49f228df59c218381a25fa3c0f93ccbeae (commit) from 4fb3c8e5a7fc6a1568f54bcc0be17fecf75e0742 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c4f9af49f228df59c218381a25fa3c0f93ccbeae Author: Christian Grothoff Date: Mon Nov 11 16:04:30 2013 +0100 ecc: Fix some memory leaks * cipher/ecc-curves.c (_gcry_mpi_ec_new): Free ec->b before assigning. * cipher/ecc.c (nist_generate_key): Release Q. * cipher/ecc-eddsa.c (_gcry_ecc_eddsa_genkey): Ditto. -- _gcry_mpi_ec_new: Fixing memory leak detected with valgrind; if 'b' is non-NULL, the code in ec_p_init (ec.c:379) already makes a copy of 'b', so before we clobber ctx->b here, we need to at least release the old value (however, it would of course be nicer to not first make a copy of b in the first place, but this is the most localized change to get rid of the memory leak). nist_generate_key: Fixing rather obvious local leak; Q is first initialized, then used, copied into the result but never released. diff --git a/cipher/ecc-curves.c b/cipher/ecc-curves.c index 8c63f6c..5815e55 100644 --- a/cipher/ecc-curves.c +++ b/cipher/ecc-curves.c @@ -867,6 +867,7 @@ _gcry_mpi_ec_new (gcry_ctx_t *r_ctx, if (b) { + mpi_free (ec->b); ec->b = b; b = NULL; } diff --git a/cipher/ecc-eddsa.c b/cipher/ecc-eddsa.c index b9e866d..92c0713 100644 --- a/cipher/ecc-eddsa.c +++ b/cipher/ecc-eddsa.c @@ -432,6 +432,7 @@ _gcry_ecc_eddsa_genkey (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, point_set (&sk->Q, &Q); leave: + point_free (&Q); gcry_mpi_release (a); gcry_mpi_release (x); gcry_mpi_release (y); diff --git a/cipher/ecc.c b/cipher/ecc.c index b9af185..9135b68 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -217,6 +217,7 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, mpi_free (x); } + point_free (&Q); /* Now we can test our keys (this should never fail!). */ test_keys (sk, nbits - 64); ----------------------------------------------------------------------- Summary of changes: cipher/ecc-curves.c | 1 + cipher/ecc-eddsa.c | 1 + cipher/ecc.c | 1 + 3 files changed, 3 insertions(+) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Wed Nov 13 11:13:03 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 13 Nov 2013 12:13:03 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <2097574.VOKJ6vsnNC@myon.chronox.de> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <5280E51C.4040509@iki.fi> <2097574.VOKJ6vsnNC@myon.chronox.de> Message-ID: <528350AF.1080208@iki.fi> On 13.11.2013 05:42, Stephan Mueller wrote: > Am Montag, 11. November 2013, 16:09:32 schrieb Jussi Kivilinna: > > Hi Jussi, > >> On 11.11.2013 15:02, Dmitry Eremin-Solenikov wrote: >>> Hello, >>> >>> On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna > wrote: > > [..] > >>> I'm unsure about generate_iv/set_iv argument. More on that here: >>> http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/foc >>> us=2897 >> How is this handled in other libraries? > > All libraries that undergo or underwent a FIPS 140-2 validation have > appropriate handling here. > > As libgcrypt has a FIPS mode, it looks like FIPS is of importance. If so, > either the handling is implemented or GCM cannot be allowed in FIPS mode. > So if I read that previous mail thread correctly, disabling GCM encryption when setiv is invocate in FIPS mode should be enough. So with current implementation before adding generate_iv API, libgcrypt would in FIPS mode only provide decryption. Something like in the attached patch. -Jussi > Ciao > Stephan > -------------- next part -------------- A non-text attachment was scrubbed... Name: 10-gcm-add-fips-mode-restrictions.patch Type: text/x-patch Size: 3364 bytes Desc: not available URL: From cvs at cvs.gnupg.org Wed Nov 13 14:06:24 2013 From: cvs at cvs.gnupg.org (by Christian Grothoff) Date: Wed, 13 Nov 2013 14:06:24 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-380-g7d91e99 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 7d91e99bcd30a463dd4faed014b8521a663d8316 (commit) from c4f9af49f228df59c218381a25fa3c0f93ccbeae (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 7d91e99bcd30a463dd4faed014b8521a663d8316 Author: Christian Grothoff Date: Mon Nov 11 16:04:30 2013 +0100 ecc: Fix key generation for a plain Ed25519 key. * cipher/ecc.c (nist_generate_key): Use custom code for ED25519. -- I wish there would a an RFC for Curve25519 - the description in the paper is easy to misunderstand for a non-mathematician. Source code and a paper are nice but a proper description (like those in the HAC) would be better. Problem spotted by Florian Dold. Signed-off-by: Werner Koch diff --git a/cipher/ecc.c b/cipher/ecc.c index 9135b68..72ca726 100644 --- a/cipher/ecc.c +++ b/cipher/ecc.c @@ -145,7 +145,21 @@ nist_generate_key (ECC_secret_key *sk, elliptic_curve_t *E, mpi_ec_t ctx, point_init (&Q); /* Generate a secret. */ - sk->d = _gcry_dsa_gen_k (E->n, random_level); + if (ctx->dialect == ECC_DIALECT_ED25519) + { + char *rndbuf; + + sk->d = mpi_snew (256); + rndbuf = gcry_random_bytes_secure (32, random_level); + rndbuf[0] &= 0x7f; /* Clear bit 255. */ + rndbuf[0] |= 0x40; /* Set bit 254. */ + rndbuf[31] &= 0xf8; /* Clear bits 2..0 so that d mod 8 == 0 */ + _gcry_mpi_set_buffer (sk->d, rndbuf, 32, 0); + gcry_free (rndbuf); + } + else + sk->d = _gcry_dsa_gen_k (E->n, random_level); + /* Compute Q. */ _gcry_mpi_ec_mul_point (&Q, sk->d, &E->G, ctx); ----------------------------------------------------------------------- Summary of changes: cipher/ecc.c | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From dbaryshkov at gmail.com Wed Nov 13 21:22:49 2013 From: dbaryshkov at gmail.com (Dmitry Eremin-Solenikov) Date: Thu, 14 Nov 2013 00:22:49 +0400 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <528350AF.1080208@iki.fi> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <5280E51C.4040509@iki.fi> <2097574.VOKJ6vsnNC@myon.chronox.de> <528350AF.1080208@iki.fi> Message-ID: <5283DF99.7040101@gmail.com> On 13/11/13 14:13, Jussi Kivilinna wrote: > On 13.11.2013 05:42, Stephan Mueller wrote: >> Am Montag, 11. November 2013, 16:09:32 schrieb Jussi Kivilinna: >> >> Hi Jussi, >> >>> On 11.11.2013 15:02, Dmitry Eremin-Solenikov wrote: >>>> Hello, >>>> >>>> On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna >> wrote: >> >> [..] >> >>>> I'm unsure about generate_iv/set_iv argument. More on that here: >>>> http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/foc >>>> us=2897 >>> How is this handled in other libraries? >> >> All libraries that undergo or underwent a FIPS 140-2 validation have >> appropriate handling here. >> >> As libgcrypt has a FIPS mode, it looks like FIPS is of importance. If so, >> either the handling is implemented or GCM cannot be allowed in FIPS mode. >> > > So if I read that previous mail thread correctly, disabling GCM encryption > when setiv is invocate in FIPS mode should be enough. So with current > implementation before adding generate_iv API, libgcrypt would in FIPS mode > only provide decryption. Something like in the attached patch. I'm fine with your patch :) So if I send you (not to clobber an ML with another big message) the proper commit message (or a full patch), we can finally merge this? Werner, is that fine from your point of view? -- With best wishes Dmitry From wk at gnupg.org Thu Nov 14 09:05:10 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 14 Nov 2013 09:05:10 +0100 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <5283DF99.7040101@gmail.com> (Dmitry Eremin-Solenikov's message of "Thu, 14 Nov 2013 00:22:49 +0400") References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <5280E51C.4040509@iki.fi> <2097574.VOKJ6vsnNC@myon.chronox.de> <528350AF.1080208@iki.fi> <5283DF99.7040101@gmail.com> Message-ID: <87vbzvv26h.fsf@vigenere.g10code.de> On Wed, 13 Nov 2013 21:22, dbaryshkov at gmail.com said: > Werner, is that fine from your point of view? Sure. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Thu Nov 14 12:45:22 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 14 Nov 2013 13:45:22 +0200 Subject: [RFC PATCH v2] Initial implementation of GCM In-Reply-To: <5283DF99.7040101@gmail.com> References: <1383905018-29976-1-git-send-email-dbaryshkov@gmail.com> <5280E51C.4040509@iki.fi> <2097574.VOKJ6vsnNC@myon.chronox.de> <528350AF.1080208@iki.fi> <5283DF99.7040101@gmail.com> Message-ID: <5284B7D2.5050308@iki.fi> On 13.11.2013 22:22, Dmitry Eremin-Solenikov wrote: > On 13/11/13 14:13, Jussi Kivilinna wrote: >> On 13.11.2013 05:42, Stephan Mueller wrote: >>> Am Montag, 11. November 2013, 16:09:32 schrieb Jussi Kivilinna: >>> >>> Hi Jussi, >>> >>>> On 11.11.2013 15:02, Dmitry Eremin-Solenikov wrote: >>>>> Hello, >>>>> >>>>> On Mon, Nov 11, 2013 at 4:46 PM, Jussi Kivilinna >>> wrote: >>> >>> [..] >>> >>>>> I'm unsure about generate_iv/set_iv argument. More on that here: >>>>> http://thread.gmane.org/gmane.comp.encryption.gpg.libgcrypt.devel/2896/foc >>>>> us=2897 >>>> How is this handled in other libraries? >>> >>> All libraries that undergo or underwent a FIPS 140-2 validation have >>> appropriate handling here. >>> >>> As libgcrypt has a FIPS mode, it looks like FIPS is of importance. If so, >>> either the handling is implemented or GCM cannot be allowed in FIPS mode. >>> >> >> So if I read that previous mail thread correctly, disabling GCM encryption >> when setiv is invocate in FIPS mode should be enough. So with current >> implementation before adding generate_iv API, libgcrypt would in FIPS mode >> only provide decryption. Something like in the attached patch. > > I'm fine with your patch :) > So if I send you (not to clobber an ML with another big message) the > proper commit message (or a full patch), we can finally merge this? Sure. Also some documentation to doc/gcrypt.texi would be nice. -Jussi > > Werner, is that fine from your point of view? > From jussi.kivilinna at iki.fi Thu Nov 14 13:08:59 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 14 Nov 2013 14:08:59 +0200 Subject: Pushed 'gcm' branch to git.gnupg.org/libgcrypt by accident. Message-ID: <5284BD5B.6050302@iki.fi> Hello, I accidentally pushed 'gcm' work branch to git.gnupg.org, and could not remove it since removing branches is blocked at the server. -Jussi From wk at gnupg.org Thu Nov 14 13:24:43 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 14 Nov 2013 13:24:43 +0100 Subject: Pushed 'gcm' branch to git.gnupg.org/libgcrypt by accident. In-Reply-To: <5284BD5B.6050302@iki.fi> (Jussi Kivilinna's message of "Thu, 14 Nov 2013 14:08:59 +0200") References: <5284BD5B.6050302@iki.fi> Message-ID: <877gcbuq5w.fsf@vigenere.g10code.de> On Thu, 14 Nov 2013 13:08, jussi.kivilinna at iki.fi said: > I accidentally pushed 'gcm' work branch to git.gnupg.org, and could not remove it since removing branches is blocked at the server. I'll do it. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Thu Nov 14 13:57:35 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 14 Nov 2013 14:57:35 +0200 Subject: Pushed 'gcm' branch to git.gnupg.org/libgcrypt by accident. In-Reply-To: <877gcbuq5w.fsf@vigenere.g10code.de> References: <5284BD5B.6050302@iki.fi> <877gcbuq5w.fsf@vigenere.g10code.de> Message-ID: <5284C8BF.8040402@iki.fi> On 14.11.2013 14:24, Werner Koch wrote: > On Thu, 14 Nov 2013 13:08, jussi.kivilinna at iki.fi said: > >> I accidentally pushed 'gcm' work branch to git.gnupg.org, and could not remove it since removing branches is blocked at the server. > > I'll do it. > Thanks. -Jussi From jussi.kivilinna at iki.fi Thu Nov 14 16:02:58 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 14 Nov 2013 17:02:58 +0200 Subject: [PATCH] Camellia: Add AVX/AES-NI key setup Message-ID: <20131114150258.1259.83229.stgit@localhost6.localdomain6> * cipher/camellia-aesni-avx-amd64.S (key_bitlength, key_table): New order of fields in ctx. (camellia_f, vec_rol128, vec_ror128): New macros. (__camellia_avx_setup128, __camellia_avx_setup256) (_gcry_camellia_aesni_avx_keygen): New functions. * cipher/camellia-aesni-avx2-amd64.S (key_bitlength, key_table): New order of fields in ctx. * cipher/camellia-arm.S (CAMELLIA_TABLE_BYTE_LEN, key_length): Remove unused macros. * cipher/camellia-glue.c (CAMELLIA_context): Move keytable to head for better alignment; Make 'use_aesni_avx' and 'use_aesni_avx2' bitfield members. [USE_AESNI_AVX] (_gcry_camellia_aesni_avx_keygen): New prototype. (camellia_setkey) [USE_AESNI_AVX || USE_AESNI_AVX2]: Read hw features to variable 'hwf' and match features from it. (camellia_setkey) [USE_AESNI_AVX]: Use AES-NI/AVX key setup if available. -- Use AVX/AES-NI for key-setup for small speed-up. Signed-off-by: Jussi Kivilinna --- cipher/camellia-aesni-avx-amd64.S | 982 ++++++++++++++++++++++++++++++++++++ cipher/camellia-aesni-avx2-amd64.S | 4 cipher/camellia-arm.S | 3 cipher/camellia-glue.c | 54 +- 4 files changed, 1012 insertions(+), 31 deletions(-) diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index 9be5d14..b25a8c7 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -32,8 +32,8 @@ #define CAMELLIA_TABLE_BYTE_LEN 272 /* struct CAMELLIA_context: */ -#define key_bitlength 0 -#define key_table 4 +#define key_table 0 +#define key_bitlength CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %rdi @@ -1194,5 +1194,983 @@ _gcry_camellia_aesni_avx_cfb_dec: ret; .size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec; +/* + * IN: + * ab: 64-bit AB state + * cd: 64-bit CD state + */ +#define camellia_f(ab, x, t0, t1, t2, t3, t4, sbox2mask, sbox4mask, \ + _0f0f0f0fmask, pre_s1lo_mask, pre_s1hi_mask, key) \ + vmovq key, t0; \ + vpxor x, x, t3; \ + \ + vpxor ab, t0, x; \ + \ + /* \ + * S-function with AES subbytes \ + */ \ + \ + /* input rotation for sbox4 (<<< 1) */ \ + vpand x, sbox4mask, t0; \ + vpandn x, sbox4mask, x; \ + vpsllw $1, t0, t1; \ + vpsrlw $7, t0, t0; \ + vpor t0, t1, t0; \ + vpand sbox4mask, t0, t0; \ + vpor t0, x, x; \ + \ + vmovdqa .Lpost_tf_lo_s1 RIP, t0; \ + vmovdqa .Lpost_tf_hi_s1 RIP, t1; \ + vmovq .Lsbox3_output_mask RIP, t4; \ + \ + /* prefilter sboxes */ \ + filter_8bit(x, pre_s1lo_mask, pre_s1hi_mask, _0f0f0f0fmask, t2); \ + \ + /* AES subbytes + AES shift rows + AES inv shift rows */ \ + vaesenclast t3, x, x; \ + vpshufb .Linv_shift_row RIP, x, x; \ + \ + /* postfilter sboxes */ \ + filter_8bit(x, t0, t1, _0f0f0f0fmask, t2); \ + \ + /* output rotation for sbox2 (<<< 1) */ \ + /* output rotation for sbox3 (>>> 1) */ \ + vpor sbox2mask, t4, t2; \ + vpand x, sbox2mask, t0; \ + vpand x, t4, t1; \ + vpandn x, t2, x; \ + vpsllw $1, t0, t2; \ + vpsrlw $7, t0, t0; \ + vpor t0, t2, t0; \ + vpand sbox2mask, t0, t0; \ + vpsllw $7, t1, t2; \ + vpsrlw $1, t1, t1; \ + vpor t1, t2, t1; \ + vpand t4, t1, t1; \ + vpor x, t0, x; \ + vpor x, t1, x; \ + \ + vpshufb .Lsp11101110mask RIP, x, t4; \ + vpshufb .Lsp44044404mask RIP, x, t1; \ + vpshufb .Lsp30333033mask RIP, x, t2; \ + vpshufb .Lsp02220222mask RIP, x, t0; \ + vpxor t2, t1, t1; \ + \ + vpshufb .Lsp00444404mask RIP, x, t2; \ + vpxor t0, t1, t1; \ + vpshufb .Lsp03303033mask RIP, x, t0; \ + vpxor t2, t4, t4; \ + vpshufb .Lsp22000222mask RIP, x, t2; \ + vpxor t0, t1, t1; \ + vpxor t2, t4, t4; \ + vpshufb .Lsp10011110mask RIP, x, x; \ + vpxor t1, x, x; \ + vpxor t4, x, x; + +#define vec_rol128(in, out, nrol, t0) \ + vpshufd $0x4e, in, out; \ + vpsllq $(nrol), in, t0; \ + vpsrlq $(64-(nrol)), out, out; \ + vpaddd t0, out, out; + +#define vec_ror128(in, out, nror, t0) \ + vpshufd $0x4e, in, out; \ + vpsrlq $(nror), in, t0; \ + vpsllq $(64-(nror)), out, out; \ + vpaddd t0, out, out; + +.data + +.align 8 +.Lsbox2_output_mask: + .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; +.Lsbox3_output_mask: + .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; +.Lsbox4_input_mask: + .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; +.Lsp11101110mask: + .long 0x000000ff, 0x000000ff; +.Lsp44044404mask: + .long 0x0101ff01, 0x0101ff01; +.Lsp30333033mask: + .long 0x02ff0202, 0x02ff0202; +.Lsp02220222mask: + .long 0xff030303, 0xff030303; +.Lsp00444404mask: + .long 0xffff0404, 0x0404ff04; +.Lsp03303033mask: + .long 0xff0505ff, 0x05ff0505; +.Lsp22000222mask: + .long 0x0606ffff, 0xff060606; +.Lsp10011110mask: + .long 0x07ffff07, 0x070707ff; +.Lsigma1: + .long 0x3BCC908B, 0xA09E667F; +.Lsigma2: + .long 0x4CAA73B2, 0xB67AE858; +.Lsigma3: + .long 0xE94F82BE, 0xC6EF372F; +.Lsigma4: + .long 0xF1D36F1C, 0x54FF53A5; +.Lsigma5: + .long 0xDE682D1D, 0x10E527FA; +.Lsigma6: + .long 0xB3E6C1FD, 0xB05688C2; + +.text + +.align 8 +.type __camellia_avx_setup128, at function; +__camellia_avx_setup128: + /* input: + * %rdi: ctx, CTX; subkey storage at key_table(CTX) + * %xmm0: key + */ +#define cmll_sub(n, ctx) (key_table+((n)*8))(ctx) +#define KL128 %xmm0 +#define KA128 %xmm2 + + vpshufb .Lbswap128_mask RIP, KL128, KL128; + + vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovq .Lsbox4_input_mask RIP, %xmm12; + vbroadcastss .L0f0f0f0f RIP, %xmm13; + vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; + vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15; + + /* + * Generate KA + */ + vpsrldq $8, KL128, %xmm2; + vmovdqa KL128, %xmm3; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm2, %xmm4, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm2, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP); + camellia_f(%xmm2, %xmm3, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm4, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP); + + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm4, %xmm2, %xmm2; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm2, KA128; + vpor %xmm3, KA128, KA128; + + /* + * Generate subkeys + */ + vmovdqu KA128, cmll_sub(24, CTX); + vec_rol128(KL128, %xmm3, 15, %xmm15); + vec_rol128(KA128, %xmm4, 15, %xmm15); + vec_rol128(KA128, %xmm5, 30, %xmm15); + vec_rol128(KL128, %xmm6, 45, %xmm15); + vec_rol128(KA128, %xmm7, 45, %xmm15); + vec_rol128(KL128, %xmm8, 60, %xmm15); + vec_rol128(KA128, %xmm9, 60, %xmm15); + vec_ror128(KL128, %xmm10, 128-77, %xmm15); + + /* absorb kw2 to other subkeys */ + vpslldq $8, KL128, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, KA128, KA128; + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + + /* subl(1) ^= subr(1) & ~subr(9); */ + vpandn %xmm15, %xmm5, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm9, %xmm9; + + /* subl(1) ^= subr(1) & ~subr(17); */ + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, KL128, KL128; + vpshufd $0x1b, KA128, KA128; + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + vpshufd $0x1b, %xmm10, %xmm10; + + vmovdqu KL128, cmll_sub(0, CTX); + vpshufd $0x1b, KL128, KL128; + vmovdqu KA128, cmll_sub(2, CTX); + vmovdqu %xmm3, cmll_sub(4, CTX); + vmovdqu %xmm4, cmll_sub(6, CTX); + vmovdqu %xmm5, cmll_sub(8, CTX); + vmovdqu %xmm6, cmll_sub(10, CTX); + vpsrldq $8, %xmm8, %xmm8; + vmovq %xmm7, cmll_sub(12, CTX); + vmovq %xmm8, cmll_sub(13, CTX); + vmovdqu %xmm9, cmll_sub(14, CTX); + vmovdqu %xmm10, cmll_sub(16, CTX); + + vmovdqu cmll_sub(24, CTX), KA128; + + vec_ror128(KL128, %xmm3, 128 - 94, %xmm7); + vec_ror128(KA128, %xmm4, 128 - 94, %xmm7); + vec_ror128(KL128, %xmm5, 128 - 111, %xmm7); + vec_ror128(KA128, %xmm6, 128 - 111, %xmm7); + + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + vpslldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm6, %xmm6; + + /* absorb kw4 to other subkeys */ + vpslldq $8, %xmm6, %xmm15; + vpxor %xmm15, %xmm5, %xmm5; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm3, %xmm3; + + /* subl(25) ^= subr(25) & ~subr(16); */ + vpshufd $0x1b, cmll_sub(16, CTX), %xmm10; + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $4, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(25) & subl(16), subr(25) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + + vmovdqu %xmm3, cmll_sub(18, CTX); + vmovdqu %xmm4, cmll_sub(20, CTX); + vmovdqu %xmm5, cmll_sub(22, CTX); + vmovdqu %xmm6, cmll_sub(24, CTX); + + vpshufd $0x1b, cmll_sub(14, CTX), %xmm3; + vpshufd $0x1b, cmll_sub(12, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(10, CTX), %xmm5; + vpshufd $0x1b, cmll_sub(8, CTX), %xmm6; + + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + + /* subl(25) ^= subr(25) & ~subr(8); */ + vpandn %xmm15, %xmm6, %xmm13; + vpslldq $4, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(25) & subl(8), subr(25) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm6, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + + vmovdqu %xmm3, cmll_sub(14, CTX); + vmovdqu %xmm4, cmll_sub(12, CTX); + vmovdqu %xmm5, cmll_sub(10, CTX); + + vpshufd $0x1b, cmll_sub(6, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(4, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(2, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(0, CTX), %xmm0; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm2, %xmm2; + vpxor %xmm15, %xmm0, %xmm0; + + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm0, %xmm0; + + vpsrldq $8, %xmm2, %xmm3; + vpsrldq $8, %xmm4, %xmm5; + vpsrldq $8, %xmm6, %xmm7; + + /* + * key XOR is end of F-function. + */ + vpxor %xmm2, %xmm0, %xmm0; + vpxor %xmm4, %xmm2, %xmm2; + + vmovq %xmm0, cmll_sub(0, CTX); + vmovq %xmm3, cmll_sub(2, CTX); + vpxor %xmm5, %xmm3, %xmm3; + vpxor %xmm6, %xmm4, %xmm4; + vpxor %xmm7, %xmm5, %xmm5; + vmovq %xmm2, cmll_sub(3, CTX); + vmovq %xmm3, cmll_sub(4, CTX); + vmovq %xmm4, cmll_sub(5, CTX); + vmovq %xmm5, cmll_sub(6, CTX); + + vmovq cmll_sub(7, CTX), %xmm7; + vmovq cmll_sub(8, CTX), %xmm8; + vmovq cmll_sub(9, CTX), %xmm9; + vmovq cmll_sub(10, CTX), %xmm10; + /* tl = subl(10) ^ (subr(10) & ~subr(8)); */ + vpandn %xmm10, %xmm8, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm10, %xmm0; + /* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */ + vpand %xmm8, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm6, %xmm6; + vmovq %xmm6, cmll_sub(7, CTX); + + vmovq cmll_sub(11, CTX), %xmm11; + vmovq cmll_sub(12, CTX), %xmm12; + vmovq cmll_sub(13, CTX), %xmm13; + vmovq cmll_sub(14, CTX), %xmm14; + vmovq cmll_sub(15, CTX), %xmm15; + /* tl = subl(7) ^ (subr(7) & ~subr(9)); */ + vpandn %xmm7, %xmm9, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm7, %xmm0; + /* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */ + vpand %xmm9, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm11, %xmm0, %xmm0; + vpxor %xmm12, %xmm10, %xmm10; + vpxor %xmm13, %xmm11, %xmm11; + vpxor %xmm14, %xmm12, %xmm12; + vpxor %xmm15, %xmm13, %xmm13; + vmovq %xmm0, cmll_sub(10, CTX); + vmovq %xmm10, cmll_sub(11, CTX); + vmovq %xmm11, cmll_sub(12, CTX); + vmovq %xmm12, cmll_sub(13, CTX); + vmovq %xmm13, cmll_sub(14, CTX); + + vmovq cmll_sub(16, CTX), %xmm6; + vmovq cmll_sub(17, CTX), %xmm7; + vmovq cmll_sub(18, CTX), %xmm8; + vmovq cmll_sub(19, CTX), %xmm9; + vmovq cmll_sub(20, CTX), %xmm10; + /* tl = subl(18) ^ (subr(18) & ~subr(16)); */ + vpandn %xmm8, %xmm6, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm8, %xmm0; + /* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */ + vpand %xmm6, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm14, %xmm0, %xmm0; + vmovq %xmm0, cmll_sub(15, CTX); + + /* tl = subl(15) ^ (subr(15) & ~subr(17)); */ + vpandn %xmm15, %xmm7, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm15, %xmm0; + /* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */ + vpand %xmm7, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vmovq cmll_sub(21, CTX), %xmm1; + vmovq cmll_sub(22, CTX), %xmm2; + vmovq cmll_sub(23, CTX), %xmm3; + vmovq cmll_sub(24, CTX), %xmm4; + + vpxor %xmm9, %xmm0, %xmm0; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm1, %xmm9, %xmm9; + vpxor %xmm2, %xmm10, %xmm10; + vpxor %xmm3, %xmm1, %xmm1; + vpxor %xmm4, %xmm3, %xmm3; + + vmovq %xmm0, cmll_sub(18, CTX); + vmovq %xmm8, cmll_sub(19, CTX); + vmovq %xmm9, cmll_sub(20, CTX); + vmovq %xmm10, cmll_sub(21, CTX); + vmovq %xmm1, cmll_sub(22, CTX); + vmovq %xmm2, cmll_sub(23, CTX); + vmovq %xmm3, cmll_sub(24, CTX); + + /* kw2 and kw4 are unused now. */ + movq $0, cmll_sub(1, CTX); + movq $0, cmll_sub(25, CTX); + + vzeroall; + + ret; +.size __camellia_avx_setup128,.-__camellia_avx_setup128; + +.align 8 +.type __camellia_avx_setup256, at function; + +__camellia_avx_setup256: + /* input: + * %rdi: ctx, CTX; subkey storage at key_table(CTX) + * %xmm0 & %xmm1: key + */ +#define KL128 %xmm0 +#define KR128 %xmm1 +#define KA128 %xmm2 +#define KB128 %xmm3 + + vpshufb .Lbswap128_mask RIP, KL128, KL128; + vpshufb .Lbswap128_mask RIP, KR128, KR128; + + vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovq .Lsbox4_input_mask RIP, %xmm12; + vbroadcastss .L0f0f0f0f RIP, %xmm13; + vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; + vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15; + + /* + * Generate KA + */ + vpxor KL128, KR128, %xmm3; + vpsrldq $8, KR128, %xmm6; + vpsrldq $8, %xmm3, %xmm2; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm2, %xmm4, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm2, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP); + vpxor %xmm6, %xmm2, %xmm2; + camellia_f(%xmm2, %xmm3, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP); + vpxor %xmm4, %xmm3, %xmm3; + vpxor KR128, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm4, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP); + + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm4, %xmm2, %xmm2; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm2, KA128; + vpor %xmm3, KA128, KA128; + + /* + * Generate KB + */ + vpxor KA128, KR128, %xmm3; + vpsrldq $8, %xmm3, %xmm4; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm4, %xmm5, %xmm6, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma5 RIP); + vpxor %xmm5, %xmm3, %xmm3; + + camellia_f(%xmm3, %xmm5, %xmm6, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma6 RIP); + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm5, %xmm4, %xmm4; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm4, %xmm4; + vpor %xmm3, %xmm4, KB128; + + /* + * Generate subkeys + */ + vmovdqu KB128, cmll_sub(32, CTX); + vec_rol128(KR128, %xmm4, 15, %xmm15); + vec_rol128(KA128, %xmm5, 15, %xmm15); + vec_rol128(KR128, %xmm6, 30, %xmm15); + vec_rol128(KB128, %xmm7, 30, %xmm15); + vec_rol128(KL128, %xmm8, 45, %xmm15); + vec_rol128(KA128, %xmm9, 45, %xmm15); + vec_rol128(KL128, %xmm10, 60, %xmm15); + vec_rol128(KR128, %xmm11, 60, %xmm15); + vec_rol128(KB128, %xmm12, 60, %xmm15); + + /* absorb kw2 to other subkeys */ + vpslldq $8, KL128, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, KB128, KB128; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + + /* subl(1) ^= subr(1) & ~subr(9); */ + vpandn %xmm15, %xmm6, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm6, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm9, %xmm9; + + vpshufd $0x1b, KL128, KL128; + vpshufd $0x1b, KB128, KB128; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + + vmovdqu KL128, cmll_sub(0, CTX); + vpshufd $0x1b, KL128, KL128; + vmovdqu KB128, cmll_sub(2, CTX); + vmovdqu %xmm4, cmll_sub(4, CTX); + vmovdqu %xmm5, cmll_sub(6, CTX); + vmovdqu %xmm6, cmll_sub(8, CTX); + vmovdqu %xmm7, cmll_sub(10, CTX); + vmovdqu %xmm8, cmll_sub(12, CTX); + vmovdqu %xmm9, cmll_sub(14, CTX); + + vmovdqu cmll_sub(32, CTX), KB128; + + /* subl(1) ^= subr(1) & ~subr(17); */ + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm11, %xmm11; + vpxor %xmm15, %xmm12, %xmm12; + + vec_ror128(KL128, %xmm4, 128-77, %xmm14); + vec_ror128(KA128, %xmm5, 128-77, %xmm14); + vec_ror128(KR128, %xmm6, 128-94, %xmm14); + vec_ror128(KA128, %xmm7, 128-94, %xmm14); + vec_ror128(KL128, %xmm8, 128-111, %xmm14); + vec_ror128(KB128, %xmm9, 128-111, %xmm14); + + vpxor %xmm15, %xmm4, %xmm4; + + vpshufd $0x1b, %xmm10, %xmm10; + vpshufd $0x1b, %xmm11, %xmm11; + vpshufd $0x1b, %xmm12, %xmm12; + vpshufd $0x1b, %xmm4, %xmm4; + + vmovdqu %xmm10, cmll_sub(16, CTX); + vmovdqu %xmm11, cmll_sub(18, CTX); + vmovdqu %xmm12, cmll_sub(20, CTX); + vmovdqu %xmm4, cmll_sub(22, CTX); + + /* subl(1) ^= subr(1) & ~subr(25); */ + vpandn %xmm15, %xmm5, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm8, %xmm8; + vpslldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm9, %xmm9; + + /* absorb kw4 to other subkeys */ + vpslldq $8, %xmm9, %xmm15; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm6, %xmm6; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm5, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + + vmovdqu %xmm5, cmll_sub(24, CTX); + vmovdqu %xmm6, cmll_sub(26, CTX); + vmovdqu %xmm7, cmll_sub(28, CTX); + vmovdqu %xmm8, cmll_sub(30, CTX); + vmovdqu %xmm9, cmll_sub(32, CTX); + + vpshufd $0x1b, cmll_sub(22, CTX), %xmm0; + vpshufd $0x1b, cmll_sub(20, CTX), %xmm1; + vpshufd $0x1b, cmll_sub(18, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(16, CTX), %xmm3; + vpshufd $0x1b, cmll_sub(14, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(12, CTX), %xmm5; + vpshufd $0x1b, cmll_sub(10, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(8, CTX), %xmm7; + + vpxor %xmm15, %xmm0, %xmm0; + vpxor %xmm15, %xmm1, %xmm1; + vpxor %xmm15, %xmm2, %xmm2; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm3, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm3, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + vpxor %xmm15, %xmm6, %xmm6; + + vpshufd $0x1b, %xmm0, %xmm0; + vpshufd $0x1b, %xmm1, %xmm1; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + + vmovdqu %xmm0, cmll_sub(22, CTX); + vmovdqu %xmm1, cmll_sub(20, CTX); + vmovdqu %xmm2, cmll_sub(18, CTX); + vmovdqu %xmm4, cmll_sub(14, CTX); + vmovdqu %xmm5, cmll_sub(12, CTX); + vmovdqu %xmm6, cmll_sub(10, CTX); + + vpshufd $0x1b, cmll_sub(6, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(4, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(2, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(0, CTX), %xmm0; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm7, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm7, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm2, %xmm2; + vpxor %xmm15, %xmm0, %xmm0; + + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm0, %xmm0; + + vpsrldq $8, %xmm2, %xmm3; + vpsrldq $8, %xmm4, %xmm5; + vpsrldq $8, %xmm6, %xmm7; + + /* + * key XOR is end of F-function. + */ + vpxor %xmm2, %xmm0, %xmm0; + vpxor %xmm4, %xmm2, %xmm2; + + vmovq %xmm0, cmll_sub(0, CTX); + vmovq %xmm3, cmll_sub(2, CTX); + vpxor %xmm5, %xmm3, %xmm3; + vpxor %xmm6, %xmm4, %xmm4; + vpxor %xmm7, %xmm5, %xmm5; + vmovq %xmm2, cmll_sub(3, CTX); + vmovq %xmm3, cmll_sub(4, CTX); + vmovq %xmm4, cmll_sub(5, CTX); + vmovq %xmm5, cmll_sub(6, CTX); + + vmovq cmll_sub(7, CTX), %xmm7; + vmovq cmll_sub(8, CTX), %xmm8; + vmovq cmll_sub(9, CTX), %xmm9; + vmovq cmll_sub(10, CTX), %xmm10; + /* tl = subl(10) ^ (subr(10) & ~subr(8)); */ + vpandn %xmm10, %xmm8, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm10, %xmm0; + /* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */ + vpand %xmm8, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm6, %xmm6; + vmovq %xmm6, cmll_sub(7, CTX); + + vmovq cmll_sub(11, CTX), %xmm11; + vmovq cmll_sub(12, CTX), %xmm12; + vmovq cmll_sub(13, CTX), %xmm13; + vmovq cmll_sub(14, CTX), %xmm14; + vmovq cmll_sub(15, CTX), %xmm15; + /* tl = subl(7) ^ (subr(7) & ~subr(9)); */ + vpandn %xmm7, %xmm9, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm7, %xmm0; + /* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */ + vpand %xmm9, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm11, %xmm0, %xmm0; + vpxor %xmm12, %xmm10, %xmm10; + vpxor %xmm13, %xmm11, %xmm11; + vpxor %xmm14, %xmm12, %xmm12; + vpxor %xmm15, %xmm13, %xmm13; + vmovq %xmm0, cmll_sub(10, CTX); + vmovq %xmm10, cmll_sub(11, CTX); + vmovq %xmm11, cmll_sub(12, CTX); + vmovq %xmm12, cmll_sub(13, CTX); + vmovq %xmm13, cmll_sub(14, CTX); + + vmovq cmll_sub(16, CTX), %xmm6; + vmovq cmll_sub(17, CTX), %xmm7; + vmovq cmll_sub(18, CTX), %xmm8; + vmovq cmll_sub(19, CTX), %xmm9; + vmovq cmll_sub(20, CTX), %xmm10; + /* tl = subl(18) ^ (subr(18) & ~subr(16)); */ + vpandn %xmm8, %xmm6, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm8, %xmm0; + /* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */ + vpand %xmm6, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm14, %xmm0, %xmm0; + vmovq %xmm0, cmll_sub(15, CTX); + + /* tl = subl(15) ^ (subr(15) & ~subr(17)); */ + vpandn %xmm15, %xmm7, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm15, %xmm0; + /* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */ + vpand %xmm7, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vmovq cmll_sub(21, CTX), %xmm1; + vmovq cmll_sub(22, CTX), %xmm2; + vmovq cmll_sub(23, CTX), %xmm3; + vmovq cmll_sub(24, CTX), %xmm4; + + vpxor %xmm9, %xmm0, %xmm0; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm1, %xmm9, %xmm9; + vpxor %xmm2, %xmm10, %xmm10; + vpxor %xmm3, %xmm1, %xmm1; + + vmovq %xmm0, cmll_sub(18, CTX); + vmovq %xmm8, cmll_sub(19, CTX); + vmovq %xmm9, cmll_sub(20, CTX); + vmovq %xmm10, cmll_sub(21, CTX); + vmovq %xmm1, cmll_sub(22, CTX); + + vmovq cmll_sub(25, CTX), %xmm5; + vmovq cmll_sub(26, CTX), %xmm6; + vmovq cmll_sub(27, CTX), %xmm7; + vmovq cmll_sub(28, CTX), %xmm8; + vmovq cmll_sub(29, CTX), %xmm9; + vmovq cmll_sub(30, CTX), %xmm10; + vmovq cmll_sub(31, CTX), %xmm11; + vmovq cmll_sub(32, CTX), %xmm12; + + /* tl = subl(26) ^ (subr(26) & ~subr(24)); */ + vpandn %xmm6, %xmm4, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm6, %xmm0; + /* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */ + vpand %xmm4, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm2, %xmm2; + vmovq %xmm2, cmll_sub(23, CTX); + + /* tl = subl(23) ^ (subr(23) & ~subr(25)); */ + vpandn %xmm3, %xmm5, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm3, %xmm0; + /* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */ + vpand %xmm5, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm7, %xmm0, %xmm0; + vpxor %xmm8, %xmm6, %xmm6; + vpxor %xmm9, %xmm7, %xmm7; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm11, %xmm9, %xmm9; + vpxor %xmm12, %xmm11, %xmm11; + + vmovq %xmm0, cmll_sub(26, CTX); + vmovq %xmm6, cmll_sub(27, CTX); + vmovq %xmm7, cmll_sub(28, CTX); + vmovq %xmm8, cmll_sub(29, CTX); + vmovq %xmm9, cmll_sub(30, CTX); + vmovq %xmm10, cmll_sub(31, CTX); + vmovq %xmm11, cmll_sub(32, CTX); + + /* kw2 and kw4 are unused now. */ + movq $0, cmll_sub(1, CTX); + movq $0, cmll_sub(33, CTX); + + vzeroall; + + ret; +.size __camellia_avx_setup256,.-__camellia_avx_setup256; + +.align 8 +.globl _gcry_camellia_aesni_avx_keygen +.type _gcry_camellia_aesni_avx_keygen, at function; + +_gcry_camellia_aesni_avx_keygen: + /* input: + * %rdi: ctx, CTX + * %rsi: key + * %rdx: keylen + */ + + vzeroupper; + + vmovdqu (%rsi), %xmm0; + cmpl $24, %edx; + jb __camellia_avx_setup128; + je .Lprepare_key192; + + vmovdqu 16(%rsi), %xmm1; + jmp __camellia_avx_setup256; + +.Lprepare_key192: + vpcmpeqd %xmm2, %xmm2, %xmm2; + vmovq 16(%rsi), %xmm1; + + vpxor %xmm1, %xmm2, %xmm2; + vpslldq $8, %xmm2, %xmm2; + vpor %xmm2, %xmm1, %xmm1; + + jmp __camellia_avx_setup256; +.size _gcry_camellia_aesni_avx_keygen,.-_gcry_camellia_aesni_avx_keygen; + #endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)*/ #endif /*__x86_64*/ diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index 78ef2d6..65c923e 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -32,8 +32,8 @@ #define CAMELLIA_TABLE_BYTE_LEN 272 /* struct CAMELLIA_context: */ -#define key_bitlength 0 -#define key_table 4 +#define key_table 0 +#define key_bitlength CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %rdi diff --git a/cipher/camellia-arm.S b/cipher/camellia-arm.S index 302f436..c30d194 100644 --- a/cipher/camellia-arm.S +++ b/cipher/camellia-arm.S @@ -28,11 +28,8 @@ .syntax unified .arm -#define CAMELLIA_TABLE_BYTE_LEN 272 - /* struct camellia_ctx: */ #define key_table 0 -#define key_length CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %r0 diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index b7ae0fc..24936ce 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -90,13 +90,13 @@ typedef struct { - int keybitlength; KEY_TABLE_TYPE keytable; + int keybitlength; #ifdef USE_AESNI_AVX - int use_aesni_avx; /* AES-NI/AVX implementation shall be used. */ + unsigned int use_aesni_avx:1; /* AES-NI/AVX implementation shall be used. */ #endif /*USE_AESNI_AVX*/ #ifdef USE_AESNI_AVX2 - int use_aesni_avx2; /* AES-NI/AVX2 implementation shall be used. */ + unsigned int use_aesni_avx2:1;/* AES-NI/AVX2 implementation shall be used. */ #endif /*USE_AESNI_AVX2*/ } CAMELLIA_context; @@ -118,6 +118,10 @@ extern void _gcry_camellia_aesni_avx_cfb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); + +extern void _gcry_camellia_aesni_avx_keygen(CAMELLIA_context *ctx, + const unsigned char *key, + unsigned int keylen); #endif #ifdef USE_AESNI_AVX2 @@ -148,6 +152,9 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) CAMELLIA_context *ctx=c; static int initialized=0; static const char *selftest_failed=NULL; +#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) + unsigned int hwf = _gcry_get_hw_features (); +#endif if(keylen!=16 && keylen!=24 && keylen!=32) return GPG_ERR_INV_KEYLEN; @@ -163,39 +170,38 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) if(selftest_failed) return GPG_ERR_SELFTEST_FAILED; +#ifdef USE_AESNI_AVX + ctx->use_aesni_avx = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX); +#endif +#ifdef USE_AESNI_AVX2 + ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2); +#endif + ctx->keybitlength=keylen*8; - Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); - _gcry_burn_stack - ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ - +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ - +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ - +3*2*sizeof(void*) /* Function calls. */ - ); + if (0) + ; #ifdef USE_AESNI_AVX - ctx->use_aesni_avx = 0; - if ((_gcry_get_hw_features () & HWF_INTEL_AESNI) && - (_gcry_get_hw_features () & HWF_INTEL_AVX)) - { - ctx->use_aesni_avx = 1; - } + else if (ctx->use_aesni_avx) + _gcry_camellia_aesni_avx_keygen(ctx, key, keylen); + else #endif - -#ifdef USE_AESNI_AVX2 - ctx->use_aesni_avx2 = 0; - if ((_gcry_get_hw_features () & HWF_INTEL_AESNI) && - (_gcry_get_hw_features () & HWF_INTEL_AVX2)) { - ctx->use_aesni_avx2 = 1; + Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); + _gcry_burn_stack + ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ + +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ + +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ + +3*2*sizeof(void*) /* Function calls. */ + ); } -#endif return 0; } #ifdef USE_ARM_ASM -/* Assembly implementations of CAST5. */ +/* Assembly implementations of Camellia. */ extern void _gcry_camellia_arm_encrypt_block(const KEY_TABLE_TYPE keyTable, byte *outbuf, const byte *inbuf, const int keybits); From cvs at cvs.gnupg.org Thu Nov 14 23:51:21 2013 From: cvs at cvs.gnupg.org (by Werner Koch) Date: Thu, 14 Nov 2013 23:51:21 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-381-gc43a8c0 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via c43a8c0d81a711161f7a81b24ef7c33a1353eee0 (commit) from 7d91e99bcd30a463dd4faed014b8521a663d8316 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit c43a8c0d81a711161f7a81b24ef7c33a1353eee0 Author: Werner Koch Date: Thu Nov 14 23:40:41 2013 +0100 md: Fix hashing for data >= 256 GB * cipher/hash-common.h (gcry_md_block_ctx): Add "nblocks_high". * cipher/hash-common.c (_gcry_md_block_write): Bump NBLOCKS_HIGH. * cipher/md4.c (md4_init, md4_final): Take care of NBLOCKS_HIGH. * cipher/md5.c (md5_init, md5_final): Ditto. * cipher/rmd160.c (_gcry_rmd160_init, rmd160_final): Ditto. * cipher/sha1.c (sha1_init, sha1_final): Ditto. * cipher/sha256.c (sha256_init, sha224_init, sha256_final): Ditto. * cipher/sha512.c (sha512_init, sha384_init, sha512_final): Ditto. * cipher/tiger.c (do_init, tiger_final): Ditto. * cipher/whirlpool.c (whirlpool_final): Ditto. * cipher/md.c (gcry_md_algo_info): Add GCRYCTL_SELFTEST. (_gcry_md_selftest): Return "not implemented" as required. * tests/hashtest.c: New. * tests/genhashdata.c: New. * tests/Makefile.am (TESTS): Add hashtest. (noinst_PROGRAMS): Add genhashdata -- Problem found by Denis Corbin and analyzed by Yuriy Kaminskiy. sha512 and whirlpool should not have this problem because they use 64 bit types for counting the blocks. However, a similar fix has been employed to allow for really huge sizes - despite that it will be very hard to test them. The test vectors have been produced by sha{1,224,256}sum and the genhashdata tool. A sequence of 'a' is used for them because a test using one million 'a' is commonly used for test vectors. More test vectors are required. Running the large tests needs to be done manual for now: ./hashtest --gigs 256 tests all algorithms, ./hashtest --gigs 256 sha1 sha224 sha256 only the given ones. A configure option to include these test in the standard regression suite will be useful. The tests will take looong. Signed-off-by: Werner Koch diff --git a/cipher/hash-common.c b/cipher/hash-common.c index e318e7e..ffbc39e 100644 --- a/cipher/hash-common.c +++ b/cipher/hash-common.c @@ -115,7 +115,8 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) _gcry_burn_stack (stack_burn); stack_burn = 0; hd->count = 0; - hd->nblocks++; + if (!++hd->nblocks) + hd->nblocks_high++; } if (!inbuf) return; @@ -133,7 +134,8 @@ _gcry_md_block_write (void *context, const void *inbuf_arg, size_t inlen) { stack_burn = hd->bwrite (hd, inbuf); hd->count = 0; - hd->nblocks++; + if (!++hd->nblocks) + hd->nblocks_high++; inlen -= hd->blocksize; inbuf += hd->blocksize; } diff --git a/cipher/hash-common.h b/cipher/hash-common.h index ce91da5..aa95365 100644 --- a/cipher/hash-common.h +++ b/cipher/hash-common.h @@ -45,6 +45,7 @@ typedef struct gcry_md_block_ctx { byte buf[MD_BLOCK_MAX_BLOCKSIZE]; MD_NBLOCKS_TYPE nblocks; + MD_NBLOCKS_TYPE nblocks_high; int count; size_t blocksize; _gcry_md_block_write_t bwrite; diff --git a/cipher/md.c b/cipher/md.c index 5c66397..3bfa3bd 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -1028,6 +1028,8 @@ md_asn_oid (int algorithm, size_t *asnlen, size_t *mdlen) * GCRYCTL_GET_ASNOID: * Return the ASNOID of the algorithm in buffer. if buffer is NULL, only * the required length is returned. + * GCRYCTL_SELFTEST + * Helper for the regression tests - shall not be used by applications. * * 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 @@ -1076,6 +1078,12 @@ gcry_md_algo_info (int algo, int what, void *buffer, size_t *nbytes) } break; + case GCRYCTL_SELFTEST: + /* Helper function for the regression tests. */ + err = gpg_err_code (_gcry_md_selftest (algo, nbytes? (int)*nbytes : 0, + NULL)); + break; + default: err = GPG_ERR_INV_OP; break; @@ -1227,7 +1235,7 @@ _gcry_md_selftest (int algo, int extended, selftest_report_func_t report) ec = spec->selftest (algo, extended, report); else { - ec = GPG_ERR_DIGEST_ALGO; + ec = spec->selftest? GPG_ERR_DIGEST_ALGO : GPG_ERR_NOT_IMPLEMENTED; if (report) report ("digest", algo, "module", (spec && !spec->flags.disabled)? diff --git a/cipher/md4.c b/cipher/md4.c index ab32b14..b9a1a95 100644 --- a/cipher/md4.c +++ b/cipher/md4.c @@ -79,6 +79,7 @@ md4_init( void *context ) ctx->D = 0x10325476; ctx->bctx.nblocks = 0; + ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; ctx->bctx.bwrite = transform; @@ -191,16 +192,21 @@ static void md4_final( void *context ) { MD4_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) diff --git a/cipher/md5.c b/cipher/md5.c index 1b6ad48..79b6e87 100644 --- a/cipher/md5.c +++ b/cipher/md5.c @@ -63,6 +63,7 @@ md5_init( void *context ) ctx->D = 0x10325476; ctx->bctx.nblocks = 0; + ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 64; ctx->bctx.bwrite = transform; @@ -215,16 +216,21 @@ static void md5_final( void *context) { MD5_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) diff --git a/cipher/rmd160.c b/cipher/rmd160.c index f7430ea..a6d9a80 100644 --- a/cipher/rmd160.c +++ b/cipher/rmd160.c @@ -155,6 +155,7 @@ _gcry_rmd160_init (void *context) hd->h4 = 0xC3D2E1F0; hd->bctx.nblocks = 0; + hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; @@ -414,16 +415,21 @@ static void rmd160_final( void *context ) { RMD160_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) diff --git a/cipher/sha1.c b/cipher/sha1.c index 95591eb..025b3ab 100644 --- a/cipher/sha1.c +++ b/cipher/sha1.c @@ -74,6 +74,7 @@ sha1_init (void *context) hd->h4 = 0xc3d2e1f0; hd->bctx.nblocks = 0; + hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; @@ -227,16 +228,21 @@ static void sha1_final(void *context) { SHA1_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; unsigned char *p; unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) diff --git a/cipher/sha256.c b/cipher/sha256.c index d3917e4..bd5a412 100644 --- a/cipher/sha256.c +++ b/cipher/sha256.c @@ -70,6 +70,7 @@ sha256_init (void *context) hd->h7 = 0x5be0cd19; hd->bctx.nblocks = 0; + hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; @@ -91,6 +92,7 @@ sha224_init (void *context) hd->h7 = 0xbefa4fa4; hd->bctx.nblocks = 0; + hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; @@ -261,16 +263,21 @@ static void sha256_final(void *context) { SHA256_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; byte *p; unsigned int burn; _gcry_md_block_write (hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) diff --git a/cipher/sha512.c b/cipher/sha512.c index 97fb203..14608dc 100644 --- a/cipher/sha512.c +++ b/cipher/sha512.c @@ -97,6 +97,7 @@ sha512_init (void *context) hd->h7 = U64_C(0x5be0cd19137e2179); ctx->bctx.nblocks = 0; + ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; @@ -122,6 +123,7 @@ sha384_init (void *context) hd->h7 = U64_C(0x47b5481dbefa4fa4); ctx->bctx.nblocks = 0; + ctx->bctx.nblocks_high = 0; ctx->bctx.count = 0; ctx->bctx.blocksize = 128; ctx->bctx.bwrite = transform; @@ -515,15 +517,20 @@ sha512_final (void *context) { SHA512_CONTEXT *hd = context; unsigned int stack_burn_depth; - u64 t, msb, lsb; + u64 t, th, msb, lsb; byte *p; _gcry_md_block_write (context, NULL, 0); /* flush */ ; t = hd->bctx.nblocks; + /* if (sizeof t == sizeof hd->bctx.nblocks) */ + th = hd->bctx.nblocks_high; + /* else */ + /* th = hd->bctx.nblocks >> 64; In case we ever use u128 */ + /* multiply by 128 to make a byte count */ lsb = t << 7; - msb = t >> 57; + msb = (th << 7) | (t >> 57); /* add the count */ t = lsb; if ((lsb += hd->bctx.count) < t) diff --git a/cipher/tiger.c b/cipher/tiger.c index a70a3f2..9b8d0ef 100644 --- a/cipher/tiger.c +++ b/cipher/tiger.c @@ -602,6 +602,7 @@ do_init (void *context, int variant) hd->c = 0xf096a5b4c3b2e187LL; hd->bctx.nblocks = 0; + hd->bctx.nblocks_high = 0; hd->bctx.count = 0; hd->bctx.blocksize = 64; hd->bctx.bwrite = transform; @@ -735,7 +736,7 @@ static void tiger_final( void *context ) { TIGER_CONTEXT *hd = context; - u32 t, msb, lsb; + u32 t, th, msb, lsb; byte *p; unsigned int burn; byte pad = hd->variant == 2? 0x80 : 0x01; @@ -743,9 +744,14 @@ tiger_final( void *context ) _gcry_md_block_write(hd, NULL, 0); /* flush */; t = hd->bctx.nblocks; + if (sizeof t == sizeof hd->bctx.nblocks) + th = hd->bctx.nblocks_high; + else + th = hd->bctx.nblocks >> 32; + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 26; + msb = (th << 6) | (t >> 26); /* add the count */ t = lsb; if( (lsb += hd->bctx.count) < t ) diff --git a/cipher/whirlpool.c b/cipher/whirlpool.c index 168c38f..e562781 100644 --- a/cipher/whirlpool.c +++ b/cipher/whirlpool.c @@ -1296,13 +1296,18 @@ whirlpool_final (void *ctx) { whirlpool_context_t *context = ctx; unsigned int i; - u64 t, lsb, msb; + u64 t, th, lsb, msb; unsigned char *length; t = context->bctx.nblocks; + /* if (sizeof t == sizeof context->bctx.nblocks) */ + th = context->bctx.nblocks_high; + /* else */ + /* th = context->bctx.nblocks >> 64; In case we ever use u128 */ + /* multiply by 64 to make a byte count */ lsb = t << 6; - msb = t >> 58; + msb = (th << 6) | (t >> 58); /* add the count */ t = lsb; if ((lsb += context->bctx.count) < t) diff --git a/tests/Makefile.am b/tests/Makefile.am index c9ba5f4..87283f9 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -20,7 +20,7 @@ TESTS = version mpitests tsexp t-convert \ t-mpi-bit t-mpi-point curves \ - prime basic keygen pubkey hmac t-kdf keygrip \ + prime basic keygen pubkey hmac hashtest t-kdf keygrip \ fips186-dsa aeswrap pkcs1v2 random dsa-rfc6979 t-ed25519 @@ -36,7 +36,7 @@ AM_CFLAGS = $(GPG_ERROR_CFLAGS) LDADD = ../src/libgcrypt.la $(DL_LIBS) ../compat/libcompat.la $(GPG_ERROR_LIBS) EXTRA_PROGRAMS = testapi pkbench -noinst_PROGRAMS = $(TESTS) fipsdrv rsacvt +noinst_PROGRAMS = $(TESTS) fipsdrv rsacvt genhashdata EXTRA_DIST = README rsa-16k.key cavs_tests.sh cavs_driver.pl \ pkcs1v2-oaep.h pkcs1v2-pss.h pkcs1v2-v15c.h pkcs1v2-v15s.h \ diff --git a/tests/genhashdata.c b/tests/genhashdata.c new file mode 100644 index 0000000..8777f9c --- /dev/null +++ b/tests/genhashdata.c @@ -0,0 +1,158 @@ +/* genhashdata.c - Create data for hash tests + * 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 . + */ + +/* Results: + +$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha1sum;done +92fc51850c7b750e6e774b75f294f6979d4059f0 - +4bddeeb4c08683f02d4944d93dbcb02ebab50134 - +71b923afde1c8c040884c723a2e3335b333e64c6 - +2d99f9b5b86e9c9c937104f4242bd6b8bc0927ef - +a60dabe8d749f798b7ec3a684cc3eab487451482 - + +$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha224sum;done +b5672b54d2480a5688a2dc727a1ad4db7a81ef31ce8999e0bbaeffdc - +814ea7159473e6ffc1c64b90026a542e13ac6980f7f3ca3c4582a9b8 - +9ec0e1829455db8650ec7a8b06912196f97a7358bc3a73c79911cd4e - +e578d5d523320876565bbbc892511a485427caee6dd754d57e3e58c2 - +ff0464df248cd298b63765bc4f87f21e25c93c657fdf3656d3c878e5 - + +$ for i in -64 -1 0 1 64; do ./genhashdata --gigs 256 --bytes $i|sha256sum;done +87a9828d3de78d55d252341db2a622908c4e0ceaee9961ecf9768700fc799ec8 - +823bf95f64ef04a4a77579c38760b1d401b56bf3a8e664bdf56ca15afb468a03 - +2d0723878cb2c3d5c59dfad910cdb857f4430a6ba2a7d687938d7a20e63dde47 - +5a2e21b1e79cd866acf53a2a18ca76bd4e02c4b01bf4627354171824c812d95f - +34444808af8e9d995e67f9e155ed94bf55f195a51dc1d8a989e6bcf95511c8a2 - + +*/ + +#include +#include +#include +#include +#include + +#define PGM "genhashdata" + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + exit (1); +} + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int gigs = 0; + int bytes = 0; + char pattern[1024]; + int i, g; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: " PGM " [options]\n" + "Options:\n" + " --gigs N Emit N GiB of test bytes\n" + " --bytes DIFF Stop DIFF bytes earlier or later\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--gigs")) + { + argc--; argv++; + if (argc) + { + gigs = atoi (*argv); + argc--; argv++; + } + } + else if (!strcmp (*argv, "--bytes")) + { + argc--; argv++; + if (argc) + { + bytes = atoi (*argv); + argc--; argv++; + } + } + else if (!strncmp (*argv, "--", 2)) + die ("unknown option '%s'", *argv); + } + + if (gigs < 0 || gigs > 1024*1024) + die ("value for --gigs must be in the range 0 to %d", 1024*1024); + if (bytes < -1024 || bytes > 1024) + die ("value for --bytes must be in the range -1024 to 1024"); + if (sizeof pattern != 1024) + die ("internal error"); + + if (argc > 1) + die ("arguments are not expected"); + + memset (pattern, 'a', sizeof pattern); + + for (g=0; g < gigs; g++) + { + if (g + 1 == gigs && bytes < 0) + { + for (i = 0; i < 1024*1023; i++) + if (fwrite (pattern, sizeof pattern, 1, stdout) != 1) + die ("writing to stdout failed: %s", strerror (errno)); + for (i = 0; i < 1023; i++) + if (fwrite (pattern, sizeof pattern, 1, stdout) != 1) + die ("writing to stdout failed: %s", strerror (errno)); + if (fwrite (pattern, sizeof pattern + bytes, 1, stdout) != 1) + die ("writing to stdout failed: %s", strerror (errno)); + } + else + { + for (i = 0; i < 1024*1024; i++) + if (fwrite (pattern, sizeof pattern, 1, stdout) != 1) + die ("writing to stdout failed: %s", strerror (errno)); + } + } + if (bytes > 0) + if (fwrite (pattern, bytes, 1, stdout) != 1) + die ("writing to stdout failed: %s", strerror (errno)); + if (fflush (stdout)) + die ("writing to stdout failed: %s", strerror (errno)); + + return 0; +} diff --git a/tests/hashtest.c b/tests/hashtest.c new file mode 100644 index 0000000..15310d0 --- /dev/null +++ b/tests/hashtest.c @@ -0,0 +1,472 @@ +/* hashtest.c - Check the hash fucntions + * 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 . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#include "../src/gcrypt-int.h" + +#include "stopwatch.h" + +#define PGM "hashtest" + +#define my_isascii(c) (!((c) & 0x80)) +#define digitp(p) (*(p) >= '0' && *(p) <= '9') +#define hexdigitp(a) (digitp (a) \ + || (*(a) >= 'A' && *(a) <= 'F') \ + || (*(a) >= 'a' && *(a) <= 'f')) +#define xtoi_1(p) (*(p) <= '9'? (*(p)- '0'): \ + *(p) <= 'F'? (*(p)-'A'+10):(*(p)-'a'+10)) +#define xtoi_2(p) ((xtoi_1(p) * 16) + xtoi_1((p)+1)) +#define xmalloc(a) gcry_xmalloc ((a)) +#define xcalloc(a,b) gcry_xcalloc ((a),(b)) +#define xstrdup(a) gcry_xstrdup ((a)) +#define xfree(a) gcry_free ((a)) +#define pass() do { ; } while (0) + +static int verbose; +static int debug; +static int error_count; +static int missing_test_vectors; + +static struct { + int algo; + int gigs; + int bytes; + const char *hex; +} testvectors[] = { + { GCRY_MD_SHA1, 256, -64, "92fc51850c7b750e6e774b75f294f6979d4059f0" }, + { GCRY_MD_SHA1, 256, -1, "4bddeeb4c08683f02d4944d93dbcb02ebab50134" }, + { GCRY_MD_SHA1, 256, -0, "71b923afde1c8c040884c723a2e3335b333e64c6" }, + { GCRY_MD_SHA1, 256, 1, "2d99f9b5b86e9c9c937104f4242bd6b8bc0927ef" }, + { GCRY_MD_SHA1, 256, 64, "a60dabe8d749f798b7ec3a684cc3eab487451482" }, + { GCRY_MD_SHA224, 256, -64, + "b5672b54d2480a5688a2dc727a1ad4db7a81ef31ce8999e0bbaeffdc" }, + { GCRY_MD_SHA224, 256, -1, + "814ea7159473e6ffc1c64b90026a542e13ac6980f7f3ca3c4582a9b8" }, + { GCRY_MD_SHA224, 256, 0, + "9ec0e1829455db8650ec7a8b06912196f97a7358bc3a73c79911cd4e" }, + { GCRY_MD_SHA224, 256, 1, + "e578d5d523320876565bbbc892511a485427caee6dd754d57e3e58c2" }, + { GCRY_MD_SHA224, 256, 64, + "ff0464df248cd298b63765bc4f87f21e25c93c657fdf3656d3c878e5" }, + { GCRY_MD_SHA256, 256, -64, + "87a9828d3de78d55d252341db2a622908c4e0ceaee9961ecf9768700fc799ec8" }, + { GCRY_MD_SHA256, 256, -1, + "823bf95f64ef04a4a77579c38760b1d401b56bf3a8e664bdf56ca15afb468a03" }, + { GCRY_MD_SHA256, 256, 0, + "2d0723878cb2c3d5c59dfad910cdb857f4430a6ba2a7d687938d7a20e63dde47" }, + { GCRY_MD_SHA256, 256, 1, + "5a2e21b1e79cd866acf53a2a18ca76bd4e02c4b01bf4627354171824c812d95f" }, + { GCRY_MD_SHA256, 256, 64, + "34444808af8e9d995e67f9e155ed94bf55f195a51dc1d8a989e6bcf95511c8a2" }, + { 0 } +}; + + + + + +static void +die (const char *format, ...) +{ + va_list arg_ptr ; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + va_start( arg_ptr, format ) ; + vfprintf (stderr, format, arg_ptr ); + va_end(arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + exit (1); +} + +static void +fail (const char *format, ...) +{ + va_list arg_ptr; + + fflush (stdout); + fprintf (stderr, "%s: ", PGM); + /* if (wherestr) */ + /* fprintf (stderr, "%s: ", wherestr); */ + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + error_count++; + if (error_count >= 50) + die ("stopped after 50 errors."); +} + +static void +show (const char *format, ...) +{ + va_list arg_ptr; + + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + va_end (arg_ptr); +} + + +static void +showhex (const void *buffer, size_t buflen, const char *format, ...) +{ + va_list arg_ptr; + const unsigned char *s; + + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + va_end (arg_ptr); + + for (s=buffer; buflen; buflen--, s++) + fprintf (stderr, "%02x", *s); + putc ('\n', stderr); +} + + +static void +show_note (const char *format, ...) +{ + va_list arg_ptr; + + if (!verbose && getenv ("srcdir")) + fputs (" ", stderr); /* To align above "PASS: ". */ + else + fprintf (stderr, "%s: ", PGM); + va_start (arg_ptr, format); + vfprintf (stderr, format, arg_ptr); + if (*format && format[strlen(format)-1] != '\n') + putc ('\n', stderr); + va_end (arg_ptr); +} + +/* Convert STRING consisting of hex characters into its binary + representation and return it as an allocated buffer. The valid + length of the buffer is returned at R_LENGTH. The string is + delimited by end of string. The function returns NULL on + error. */ +static void * +hex2buffer (const char *string, size_t *r_length) +{ + const char *s; + unsigned char *buffer; + size_t length; + + buffer = xmalloc (strlen(string)/2+1); + length = 0; + for (s=string; *s; s +=2 ) + { + if (!hexdigitp (s) || !hexdigitp (s+1)) + return NULL; /* Invalid hex digits. */ + ((unsigned char*)buffer)[length++] = xtoi_2 (s); + } + *r_length = length; + return buffer; +} + + +static void +run_selftest (int algo) +{ + gpg_error_t err; + size_t n; + + n = 1; + err = gcry_md_algo_info (algo, GCRYCTL_SELFTEST, NULL, &n); + if (err && gpg_err_code (err) != GPG_ERR_NOT_IMPLEMENTED) + fail ("extended selftest for %s (%d) failed: %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + else if (err && verbose) + show ("extended selftest for %s (%d) not implemented", + gcry_md_algo_name (algo), algo); + else if (verbose) + show ("extended selftest for %s (%d) passed", + gcry_md_algo_name (algo), algo); +} + +/* Compare DIGEST of length DIGESTLEN generated using ALGO and GIGS + plus BYTES with the test vector and print an error message if the + don't match. Return 0 on match. */ +static int +cmp_digest (const unsigned char *digest, size_t digestlen, + int algo, int gigs, int bytes) +{ + int idx; + unsigned char *tv_digest; + size_t tv_digestlen = 0; + + for (idx=0; testvectors[idx].algo; idx++) + { + if (testvectors[idx].algo == algo + && testvectors[idx].gigs == gigs + && testvectors[idx].bytes == bytes) + break; + } + if (!testvectors[idx].algo) + { + show ("%d GiB %+3d %-10s warning: %s", + gigs, bytes, gcry_md_algo_name (algo), "no test vector"); + missing_test_vectors++; + return 1; + } + + tv_digest = hex2buffer (testvectors[idx].hex, &tv_digestlen); + if (tv_digestlen != digestlen) /* Ooops. */ + { + fail ("%d GiB %+3d %-10s error: %s", + gigs, bytes, gcry_md_algo_name (algo), "digest length mismatch"); + xfree (tv_digest); + return 1; + } + if (memcmp (tv_digest, digest, tv_digestlen)) + { + fail ("%d GiB %+3d %-10s error: %s", + gigs, bytes, gcry_md_algo_name (algo), "mismatch"); + xfree (tv_digest); + return 1; + } + xfree (tv_digest); + + return 0; +} + + +static void +run_longtest (int algo, int gigs) +{ + gpg_error_t err; + gcry_md_hd_t hd; + gcry_md_hd_t hd_pre = NULL; + gcry_md_hd_t hd_pre2 = NULL; + gcry_md_hd_t hd_post = NULL; + gcry_md_hd_t hd_post2 = NULL; + char pattern[1024]; + int i, g; + const unsigned char *digest; + unsigned int digestlen; + + memset (pattern, 'a', sizeof pattern); + + err = gcry_md_open (&hd, algo, 0); + if (err) + { + fail ("gcry_md_open failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + return; + } + + digestlen = gcry_md_get_algo_dlen (algo); + + + for (g=0; g < gigs; g++) + { + if (g == gigs - 1) + { + for (i = 0; i < 1024*1023; i++) + gcry_md_write (hd, pattern, sizeof pattern); + for (i = 0; i < 1023; i++) + gcry_md_write (hd, pattern, sizeof pattern); + err = gcry_md_copy (&hd_pre, hd); + if (!err) + err = gcry_md_copy (&hd_pre2, hd); + if (err) + die ("gcry_md_copy failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + gcry_md_write (hd, pattern, sizeof pattern); + } + else + { + for (i = 0; i < 1024*1024; i++) + gcry_md_write (hd, pattern, sizeof pattern); + } + if (g && !(g % 16)) + show_note ("%d GiB so far hashed with %s", g, gcry_md_algo_name (algo)); + } + if (g >= 16) + show_note ("%d GiB hashed with %s", g, gcry_md_algo_name (algo)); + + err = gcry_md_copy (&hd_post, hd); + if (err) + die ("gcry_md_copy failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + err = gcry_md_copy (&hd_post2, hd); + if (err) + die ("gcry_md_copy failed for %s (%d): %s", + gcry_md_algo_name (algo), algo, gpg_strerror (err)); + + gcry_md_write (hd_pre2, pattern, sizeof pattern - 64); + gcry_md_write (hd_pre, pattern, sizeof pattern - 1); + gcry_md_write (hd_post, pattern, 1); + gcry_md_write (hd_post2, pattern, 64); + + digest = gcry_md_read (hd_pre2, algo); + if (cmp_digest (digest, digestlen, algo, gigs, -64) || verbose) + showhex (digest, digestlen, "%d GiB %+3d %-10s ", + gigs, -64, gcry_md_algo_name (algo)); + digest = gcry_md_read (hd_pre, algo); + if (cmp_digest (digest, digestlen, algo, gigs, -1) || verbose) + showhex (digest, digestlen, "%d GiB %+3d %-10s ", + gigs, -1, gcry_md_algo_name (algo)); + digest = gcry_md_read (hd, algo); + if (cmp_digest (digest, digestlen, algo, gigs, 0) || verbose) + showhex (digest, digestlen, "%d GiB %+3d %-10s ", + gigs, 0, gcry_md_algo_name (algo)); + digest = gcry_md_read (hd_post, algo); + if (cmp_digest (digest, digestlen, algo, gigs, 1) || verbose) + showhex (digest, digestlen, "%d GiB %+3d %-10s ", + gigs, 1, gcry_md_algo_name (algo)); + digest = gcry_md_read (hd_post2, algo); + if (cmp_digest (digest, digestlen, algo, gigs, 64) || verbose) + showhex (digest, digestlen, "%d GiB %+3d %-10s ", + gigs, 64, gcry_md_algo_name (algo)); + + gcry_md_close (hd); + gcry_md_close (hd_pre); + gcry_md_close (hd_pre2); + gcry_md_close (hd_post); + gcry_md_close (hd_post2); +} + + +int +main (int argc, char **argv) +{ + int last_argc = -1; + int gigs = 0; + int algo = 0; + int idx; + + if (argc) + { argc--; argv++; } + + while (argc && last_argc != argc ) + { + last_argc = argc; + if (!strcmp (*argv, "--")) + { + argc--; argv++; + break; + } + else if (!strcmp (*argv, "--help")) + { + fputs ("usage: " PGM " [options] [algos]\n" + "Options:\n" + " --verbose print timings etc.\n" + " --debug flyswatter\n" + " --gigs N Run a test on N GiB\n", + stdout); + exit (0); + } + else if (!strcmp (*argv, "--verbose")) + { + verbose++; + argc--; argv++; + } + else if (!strcmp (*argv, "--debug")) + { + verbose += 2; + debug++; + argc--; argv++; + } + else if (!strcmp (*argv, "--gigs")) + { + argc--; argv++; + if (argc) + { + gigs = atoi (*argv); + argc--; argv++; + } + } + else if (!strncmp (*argv, "--", 2)) + die ("unknown option '%s'", *argv); + } + + if (gigs < 0 || gigs > 1024*1024) + die ("value for --gigs must be in the range 0 to %d", 1024*1024); + + gcry_control (GCRYCTL_DISABLE_SECMEM, 0); + if (!gcry_check_version (GCRYPT_VERSION)) + die ("version mismatch\n"); + if (debug) + gcry_control (GCRYCTL_SET_DEBUG_FLAGS, 1u , 0); + gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); + gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0); + + /* A quick check that all given algorithms are valid. */ + for (idx=0; idx < argc; idx++) + { + algo = gcry_md_map_name (argv[idx]); + if (!algo) + fail ("invalid algorithm '%s'", argv[idx]); + } + if (error_count) + exit (1); + + /* Start checking. */ + start_timer (); + if (!argc) + { + for (algo=1; algo < 400; algo++) + if (!gcry_md_test_algo (algo)) + { + if (!gigs) + run_selftest (algo); + else + run_longtest (algo, gigs); + } + } + else + { + for (idx=0; idx < argc; idx++) + { + algo = gcry_md_map_name (argv[idx]); + if (!algo) + die ("invalid algorithm '%s'", argv[idx]); + + if (!gigs) + run_selftest (algo); + else + run_longtest (algo, gigs); + } + } + stop_timer (); + + if (missing_test_vectors) + fail ("Some test vectors are missing"); + + if (verbose) + show ("All tests completed in %s. Errors: %d\n", + elapsed_time (), error_count); + return !!error_count; +} ----------------------------------------------------------------------- Summary of changes: cipher/hash-common.c | 6 +- cipher/hash-common.h | 1 + cipher/md.c | 10 +- cipher/md4.c | 10 +- cipher/md5.c | 10 +- cipher/rmd160.c | 10 +- cipher/sha1.c | 10 +- cipher/sha256.c | 11 +- cipher/sha512.c | 11 +- cipher/tiger.c | 10 +- cipher/whirlpool.c | 9 +- tests/Makefile.am | 4 +- tests/genhashdata.c | 158 +++++++++++++++++ tests/hashtest.c | 472 ++++++++++++++++++++++++++++++++++++++++++++++++++ 14 files changed, 711 insertions(+), 21 deletions(-) create mode 100644 tests/genhashdata.c create mode 100644 tests/hashtest.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Fri Nov 15 15:52:25 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 15 Nov 2013 16:52:25 +0200 Subject: [PATCH] cipher: use size_t for internal buffer lengths Message-ID: <20131115145225.28932.22153.stgit@localhost6.localdomain6> * cipher/arcfour.c (do_encrypt_stream, encrypt_stream): Use 'size_t' for buffer lengths. * cipher/blowfish.c (_gcry_blowfish_ctr_enc, _gcry_blowfish_cbc_dec) (_gcry_blowfish_cfb_dec): Ditto. * cipher/camellia-glue.c (_gcry_camellia_ctr_enc) (_gcry_camellia_cbc_dec, _gcry_blowfish_cfb_dec): Ditto. * cipher/cast5.c (_gcry_cast5_ctr_enc, _gcry_cast5_cbc_dec) (_gcry_cast5_cfb_dec): Ditto. * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt) (_gcry_cipher_aeswrap_decrypt): Ditto. * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt) (_gcry_cipher_cbc_decrypt): Ditto. * cipher/cipher-ccm.c (_gcry_cipher_ccm_encrypt) (_gcry_cipher_ccm_decrypt): Ditto. * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt) (_gcry_cipher_cfb_decrypt): Ditto. * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Ditto. * cipher/cipher-internal.h (gcry_cipher_handle->bulk) (_gcry_cipher_cbc_encrypt, _gcry_cipher_cbc_decrypt) (_gcry_cipher_cfb_encrypt, _gcry_cipher_cfb_decrypt) (_gcry_cipher_ofb_encrypt, _gcry_cipher_ctr_encrypt) (_gcry_cipher_aeswrap_encrypt, _gcry_cipher_aeswrap_decrypt) (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Ditto. * cipher/cipher-ofb.c (_gcry_cipher_cbc_encrypt): Ditto. * cipher/cipher-selftest.h (gcry_cipher_bulk_cbc_dec_t) (gcry_cipher_bulk_cfb_dec_t, gcry_cipher_bulk_ctr_enc_t): Ditto. * cipher/cipher.c (cipher_setkey, cipher_setiv, do_ecb_crypt) (do_ecb_encrypt, do_ecb_decrypt, cipher_encrypt) (cipher_decrypt): Ditto. * cipher/rijndael.c (_gcry_aes_ctr_enc, _gcry_aes_cbc_dec) (_gcry_aes_cfb_dec, _gcry_aes_cbc_enc, _gcry_aes_cfb_enc): Ditto. * cipher/salsa20.c (salsa20_setiv, salsa20_do_encrypt_stream) (salsa20_encrypt_stream, salsa20r12_encrypt_stream): Ditto. * cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec) (_gcry_serpent_cfb_dec): Ditto. * cipher/twofish.c (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec) (_gcry_twofish_cfb_dec): Ditto. * src/cipher-proto.h (gcry_cipher_stencrypt_t) (gcry_cipher_stdecrypt_t, cipher_setiv_fuct_t): Ditto. * src/cipher.h (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec) (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec, _gcry_aes_ctr_enc) (_gcry_blowfish_cfb_dec, _gcry_blowfish_cbc_dec) (_gcry_blowfish_ctr_enc, _gcry_cast5_cfb_dec, _gcry_cast5_cbc_dec) (_gcry_cast5_ctr_enc, _gcry_camellia_cfb_dec, _gcry_camellia_cbc_dec) (_gcry_camellia_ctr_enc, _gcry_serpent_cfb_dec, _gcry_serpent_cbc_dec) (_gcry_serpent_ctr_enc, _gcry_twofish_cfb_dec, _gcry_twofish_cbc_dec) (_gcry_twofish_ctr_enc): Ditto. -- On 64-bit platforms, cipher module internally converts 64-bit size_t values to 32-bit unsigned integers. Signed-off-by: Jussi Kivilinna --- cipher/arcfour.c | 4 ++-- cipher/blowfish.c | 6 +++--- cipher/camellia-glue.c | 6 +++--- cipher/cast5.c | 6 +++--- cipher/cipher-aeswrap.c | 12 ++++++----- cipher/cipher-cbc.c | 20 +++++++++--------- cipher/cipher-ccm.c | 8 ++++--- cipher/cipher-cfb.c | 12 ++++++----- cipher/cipher-ctr.c | 8 ++++--- cipher/cipher-internal.h | 50 +++++++++++++++++++++++----------------------- cipher/cipher-ofb.c | 4 ++-- cipher/cipher-selftest.h | 6 +++--- cipher/cipher.c | 28 +++++++++++++------------- cipher/rijndael.c | 10 +++++---- cipher/salsa20.c | 16 +++++++-------- cipher/serpent.c | 8 ++++--- cipher/twofish.c | 6 +++--- src/cipher-proto.h | 7 +++--- src/cipher.h | 40 ++++++++++++++++++------------------- 19 files changed, 128 insertions(+), 129 deletions(-) diff --git a/cipher/arcfour.c b/cipher/arcfour.c index 64f7204..d692c84 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -40,7 +40,7 @@ typedef struct { static void do_encrypt_stream( ARCFOUR_context *ctx, - byte *outbuf, const byte *inbuf, unsigned int length ) + byte *outbuf, const byte *inbuf, size_t length ) { #ifndef __i386__ register unsigned int i = ctx->idx_i; @@ -89,7 +89,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, static void encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { ARCFOUR_context *ctx = (ARCFOUR_context *) context; do_encrypt_stream (ctx, outbuf, inbuf, length ); diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 4665a1d..ae470d8 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -588,7 +588,7 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf) of size BLOWFISH_BLOCKSIZE. */ void _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -658,7 +658,7 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -719,7 +719,7 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 24936ce..575bb04 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -290,7 +290,7 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) void _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -382,7 +382,7 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, void _gcry_camellia_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -465,7 +465,7 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, void _gcry_camellia_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/cast5.c b/cipher/cast5.c index 09c9691..115e1e6 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -564,7 +564,7 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf) of size CAST5_BLOCKSIZE. */ void _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -635,7 +635,7 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -695,7 +695,7 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index 03b0ea7..50ac107 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -35,11 +35,11 @@ blocksize 128. */ gcry_err_code_t _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen ) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen ) { int j, x; - unsigned int n, i; + size_t n, i; unsigned char *r, *a, *b; unsigned char t[8]; unsigned int burn, nburn; @@ -117,11 +117,11 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, blocksize 128. */ gcry_err_code_t _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { int j, x; - unsigned int n, i; + size_t n, i; unsigned char *r, *a, *b; unsigned char t[8]; unsigned int burn, nburn; diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c index 4ad2ebd..4b929da 100644 --- a/cipher/cipher-cbc.c +++ b/cipher/cipher-cbc.c @@ -34,15 +34,15 @@ gcry_err_code_t _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; unsigned char *ivp; int i; size_t blocksize = c->spec->blocksize; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; - unsigned nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; unsigned int burn, nburn; if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) @@ -92,7 +92,7 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, { /* We have to be careful here, since outbuf might be equal to inbuf. */ - int restbytes; + size_t restbytes; unsigned char b; if ((inbuflen % blocksize) == 0) @@ -124,14 +124,14 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; int i; size_t blocksize = c->spec->blocksize; gcry_cipher_decrypt_t dec_fn = c->spec->decrypt; - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; unsigned int burn, nburn; if (outbuflen < inbuflen) @@ -175,7 +175,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { - int restbytes; + size_t restbytes; if ((inbuflen % blocksize) == 0) restbytes = blocksize; diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index ebcbf1e..2a1fc74 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -318,8 +318,8 @@ _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, gcry_err_code_t _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - unsigned int outbuflen, const unsigned char *inbuf, - unsigned int inbuflen) + size_t outbuflen, const unsigned char *inbuf, + size_t inbuflen) { unsigned int burn; @@ -342,8 +342,8 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, gcry_err_code_t _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - unsigned int outbuflen, const unsigned char *inbuf, - unsigned int inbuflen) + size_t outbuflen, const unsigned char *inbuf, + size_t inbuflen) { gcry_err_code_t err; unsigned int burn; diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index 610d006..8539f54 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -33,8 +33,8 @@ gcry_err_code_t _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; @@ -73,7 +73,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, also allows to use a bulk encryption function if available. */ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) { - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; @@ -130,8 +130,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; @@ -170,7 +170,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, also allows to use a bulk encryption function if available. */ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) { - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c index 37a6a79..1e7133c 100644 --- a/cipher/cipher-ctr.c +++ b/cipher/cipher-ctr.c @@ -33,14 +33,14 @@ gcry_err_code_t _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; int i; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; unsigned int blocksize = c->spec->blocksize; - unsigned int nblocks; + size_t nblocks; unsigned int burn, nburn; if (outbuflen < inbuflen) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index f528c84..db06823 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -74,19 +74,19 @@ struct gcry_cipher_handle struct { void (*cfb_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*cfb_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*cbc_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac); + size_t nblocks, int cbc_mac); void (*cbc_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*ctr_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); } bulk; @@ -150,57 +150,57 @@ struct gcry_cipher_handle /*-- cipher-cbc.c --*/ gcry_err_code_t _gcry_cipher_cbc_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_cbc_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-cfb.c --*/ gcry_err_code_t _gcry_cipher_cfb_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_cfb_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-ofb.c --*/ gcry_err_code_t _gcry_cipher_ofb_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-ctr.c --*/ gcry_err_code_t _gcry_cipher_ctr_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-aeswrap.c --*/ gcry_err_code_t _gcry_cipher_aeswrap_encrypt /* */ (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen); + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_aeswrap_decrypt /* */ (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen); + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen); /*-- cipher-ccm.c --*/ gcry_err_code_t _gcry_cipher_ccm_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_ccm_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_ccm_set_nonce /* */ (gcry_cipher_hd_t c, const unsigned char *nonce, size_t noncelen); diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c index c6d84dd..3842774 100644 --- a/cipher/cipher-ofb.c +++ b/cipher/cipher-ofb.c @@ -33,8 +33,8 @@ gcry_err_code_t _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; diff --git a/cipher/cipher-selftest.h b/cipher/cipher-selftest.h index 41d77af..3a0fe98 100644 --- a/cipher/cipher-selftest.h +++ b/cipher/cipher-selftest.h @@ -28,17 +28,17 @@ typedef void (*gcry_cipher_bulk_cbc_dec_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); typedef void (*gcry_cipher_bulk_cfb_dec_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); typedef void (*gcry_cipher_bulk_ctr_enc_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /* Helper function for bulk CBC decryption selftest */ const char * diff --git a/cipher/cipher.c b/cipher/cipher.c index 705696c..80aa7a7 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -555,7 +555,7 @@ gcry_cipher_close (gcry_cipher_hd_t h) /* Set the key to be used for the encryption context C to KEY with length KEYLEN. The length should match the required length. */ static gcry_error_t -cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) +cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) { gcry_err_code_t ret; @@ -578,7 +578,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) /* Set the IV to be used for the encryption context C to IV with length IVLEN. The length should match the required length. */ static void -cipher_setiv (gcry_cipher_hd_t c, const byte *iv, unsigned ivlen) +cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ @@ -594,7 +594,7 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, unsigned ivlen) if (ivlen != c->spec->blocksize) { log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", - ivlen, (unsigned int)c->spec->blocksize); + (unsigned int)ivlen, (unsigned int)c->spec->blocksize); fips_signal_error ("IV length does not match blocklength"); } if (ivlen > c->spec->blocksize) @@ -628,12 +628,12 @@ cipher_reset (gcry_cipher_hd_t c) static gcry_err_code_t do_ecb_crypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen, gcry_cipher_encrypt_t crypt_fn) { unsigned int blocksize = c->spec->blocksize; - unsigned int n, nblocks; + size_t n, nblocks; unsigned int burn, nburn; if (outbuflen < inbuflen) @@ -660,16 +660,16 @@ do_ecb_crypt (gcry_cipher_hd_t c, static gcry_err_code_t do_ecb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->encrypt); } static gcry_err_code_t do_ecb_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->decrypt); } @@ -681,8 +681,8 @@ do_ecb_decrypt (gcry_cipher_hd_t c, * Depending on the mode some constraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; @@ -781,8 +781,8 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, * Depending on the mode some some contraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 47b2559..257a162 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1672,7 +1672,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a) void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1736,7 +1736,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac) + size_t nblocks, int cbc_mac) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1834,7 +1834,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -2095,7 +2095,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a) void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -2200,7 +2200,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/salsa20.c b/cipher/salsa20.c index f708b18..72b28b0 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -112,7 +112,7 @@ typedef struct SALSA20_context_s #define LE_READ_UINT32(p) buf_get_le32(p) -static void salsa20_setiv (void *context, const byte *iv, unsigned int ivlen); +static void salsa20_setiv (void *context, const byte *iv, size_t ivlen); static const char *selftest (void); @@ -360,13 +360,13 @@ salsa20_setkey (void *context, const byte *key, unsigned int keylen) static void -salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) +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", ivlen); + log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen); if (!iv || ivlen != SALSA20_IV_SIZE) memset (tmp, 0, sizeof(tmp)); @@ -387,14 +387,14 @@ salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) static void salsa20_do_encrypt_stream (SALSA20_context_t *ctx, byte *outbuf, const byte *inbuf, - unsigned int length, unsigned rounds) + size_t length, unsigned rounds) { unsigned int nburn, burn = 0; if (ctx->unused) { unsigned char *p = (void*)ctx->pad; - unsigned int n; + size_t n; gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE); @@ -414,7 +414,7 @@ salsa20_do_encrypt_stream (SALSA20_context_t *ctx, #ifdef USE_AMD64 if (length >= SALSA20_BLOCK_SIZE) { - unsigned int nblocks = length / SALSA20_BLOCK_SIZE; + size_t nblocks = length / SALSA20_BLOCK_SIZE; burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf, nblocks, rounds); length -= SALSA20_BLOCK_SIZE * nblocks; @@ -461,7 +461,7 @@ salsa20_do_encrypt_stream (SALSA20_context_t *ctx, static void salsa20_encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; @@ -472,7 +472,7 @@ salsa20_encrypt_stream (void *context, static void salsa20r12_encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; diff --git a/cipher/serpent.c b/cipher/serpent.c index 915cc95..8e647d4 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -827,7 +827,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) void _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -944,8 +944,8 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, intended for the bulk encryption feature of cipher.c. */ void _gcry_serpent_cbc_dec(void *context, unsigned char *iv, - void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + void *outbuf_arg, const void *inbuf_arg, + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1053,7 +1053,7 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv, void _gcry_serpent_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/twofish.c b/cipher/twofish.c index 04081db..ecd76e3 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -966,7 +966,7 @@ twofish_decrypt (void *context, byte *out, const byte *in) of size TWOFISH_BLOCKSIZE. */ void _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1025,7 +1025,7 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1075,7 +1075,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index c7ce906..c82012c 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -153,21 +153,20 @@ typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, typedef void (*gcry_cipher_stencrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + size_t n); /* Type for the cipher_stdecrypt function. */ typedef void (*gcry_cipher_stdecrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + 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, unsigned int ivlen); +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 diff --git a/src/cipher.h b/src/cipher.h index d939ade..38d2a97 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -97,78 +97,78 @@ void _gcry_sha1_hash_buffers (void *outbuf, /*-- rijndael.c --*/ void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf, const void *inbuf, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac); + size_t nblocks, int cbc_mac); void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- blowfish.c --*/ void _gcry_blowfish_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_blowfish_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_blowfish_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- cast5.c --*/ void _gcry_cast5_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_cast5_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_cast5_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- camellia-glue.c --*/ void _gcry_camellia_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_camellia_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_camellia_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- serpent.c --*/ void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_serpent_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_serpent_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- twofish.c --*/ void _gcry_twofish_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_twofish_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_twofish_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- dsa.c --*/ void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data); From cvs at cvs.gnupg.org Fri Nov 15 16:02:05 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Fri, 15 Nov 2013 16:02:05 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-383-gef9f52c Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via ef9f52cbb39e46918c96200b09c21e931eff174f (commit) via c8ad83fb605fdbf6dc0b0dbcc8aedfbd477640da (commit) from c43a8c0d81a711161f7a81b24ef7c33a1353eee0 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit ef9f52cbb39e46918c96200b09c21e931eff174f Author: Jussi Kivilinna Date: Fri Nov 15 16:23:00 2013 +0200 Camellia: Add AVX/AES-NI key setup * cipher/camellia-aesni-avx-amd64.S (key_bitlength, key_table): New order of fields in ctx. (camellia_f, vec_rol128, vec_ror128): New macros. (__camellia_avx_setup128, __camellia_avx_setup256) (_gcry_camellia_aesni_avx_keygen): New functions. * cipher/camellia-aesni-avx2-amd64.S (key_bitlength, key_table): New order of fields in ctx. * cipher/camellia-arm.S (CAMELLIA_TABLE_BYTE_LEN, key_length): Remove unused macros. * cipher/camellia-glue.c (CAMELLIA_context): Move keytable to head for better alignment; Make 'use_aesni_avx' and 'use_aesni_avx2' bitfield members. [USE_AESNI_AVX] (_gcry_camellia_aesni_avx_keygen): New prototype. (camellia_setkey) [USE_AESNI_AVX || USE_AESNI_AVX2]: Read hw features to variable 'hwf' and match features from it. (camellia_setkey) [USE_AESNI_AVX]: Use AES-NI/AVX key setup if available. -- Use AVX/AES-NI for key-setup for small speed-up. Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index 9be5d14..b25a8c7 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -32,8 +32,8 @@ #define CAMELLIA_TABLE_BYTE_LEN 272 /* struct CAMELLIA_context: */ -#define key_bitlength 0 -#define key_table 4 +#define key_table 0 +#define key_bitlength CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %rdi @@ -1194,5 +1194,983 @@ _gcry_camellia_aesni_avx_cfb_dec: ret; .size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec; +/* + * IN: + * ab: 64-bit AB state + * cd: 64-bit CD state + */ +#define camellia_f(ab, x, t0, t1, t2, t3, t4, sbox2mask, sbox4mask, \ + _0f0f0f0fmask, pre_s1lo_mask, pre_s1hi_mask, key) \ + vmovq key, t0; \ + vpxor x, x, t3; \ + \ + vpxor ab, t0, x; \ + \ + /* \ + * S-function with AES subbytes \ + */ \ + \ + /* input rotation for sbox4 (<<< 1) */ \ + vpand x, sbox4mask, t0; \ + vpandn x, sbox4mask, x; \ + vpsllw $1, t0, t1; \ + vpsrlw $7, t0, t0; \ + vpor t0, t1, t0; \ + vpand sbox4mask, t0, t0; \ + vpor t0, x, x; \ + \ + vmovdqa .Lpost_tf_lo_s1 RIP, t0; \ + vmovdqa .Lpost_tf_hi_s1 RIP, t1; \ + vmovq .Lsbox3_output_mask RIP, t4; \ + \ + /* prefilter sboxes */ \ + filter_8bit(x, pre_s1lo_mask, pre_s1hi_mask, _0f0f0f0fmask, t2); \ + \ + /* AES subbytes + AES shift rows + AES inv shift rows */ \ + vaesenclast t3, x, x; \ + vpshufb .Linv_shift_row RIP, x, x; \ + \ + /* postfilter sboxes */ \ + filter_8bit(x, t0, t1, _0f0f0f0fmask, t2); \ + \ + /* output rotation for sbox2 (<<< 1) */ \ + /* output rotation for sbox3 (>>> 1) */ \ + vpor sbox2mask, t4, t2; \ + vpand x, sbox2mask, t0; \ + vpand x, t4, t1; \ + vpandn x, t2, x; \ + vpsllw $1, t0, t2; \ + vpsrlw $7, t0, t0; \ + vpor t0, t2, t0; \ + vpand sbox2mask, t0, t0; \ + vpsllw $7, t1, t2; \ + vpsrlw $1, t1, t1; \ + vpor t1, t2, t1; \ + vpand t4, t1, t1; \ + vpor x, t0, x; \ + vpor x, t1, x; \ + \ + vpshufb .Lsp11101110mask RIP, x, t4; \ + vpshufb .Lsp44044404mask RIP, x, t1; \ + vpshufb .Lsp30333033mask RIP, x, t2; \ + vpshufb .Lsp02220222mask RIP, x, t0; \ + vpxor t2, t1, t1; \ + \ + vpshufb .Lsp00444404mask RIP, x, t2; \ + vpxor t0, t1, t1; \ + vpshufb .Lsp03303033mask RIP, x, t0; \ + vpxor t2, t4, t4; \ + vpshufb .Lsp22000222mask RIP, x, t2; \ + vpxor t0, t1, t1; \ + vpxor t2, t4, t4; \ + vpshufb .Lsp10011110mask RIP, x, x; \ + vpxor t1, x, x; \ + vpxor t4, x, x; + +#define vec_rol128(in, out, nrol, t0) \ + vpshufd $0x4e, in, out; \ + vpsllq $(nrol), in, t0; \ + vpsrlq $(64-(nrol)), out, out; \ + vpaddd t0, out, out; + +#define vec_ror128(in, out, nror, t0) \ + vpshufd $0x4e, in, out; \ + vpsrlq $(nror), in, t0; \ + vpsllq $(64-(nror)), out, out; \ + vpaddd t0, out, out; + +.data + +.align 8 +.Lsbox2_output_mask: + .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; +.Lsbox3_output_mask: + .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; +.Lsbox4_input_mask: + .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; +.Lsp11101110mask: + .long 0x000000ff, 0x000000ff; +.Lsp44044404mask: + .long 0x0101ff01, 0x0101ff01; +.Lsp30333033mask: + .long 0x02ff0202, 0x02ff0202; +.Lsp02220222mask: + .long 0xff030303, 0xff030303; +.Lsp00444404mask: + .long 0xffff0404, 0x0404ff04; +.Lsp03303033mask: + .long 0xff0505ff, 0x05ff0505; +.Lsp22000222mask: + .long 0x0606ffff, 0xff060606; +.Lsp10011110mask: + .long 0x07ffff07, 0x070707ff; +.Lsigma1: + .long 0x3BCC908B, 0xA09E667F; +.Lsigma2: + .long 0x4CAA73B2, 0xB67AE858; +.Lsigma3: + .long 0xE94F82BE, 0xC6EF372F; +.Lsigma4: + .long 0xF1D36F1C, 0x54FF53A5; +.Lsigma5: + .long 0xDE682D1D, 0x10E527FA; +.Lsigma6: + .long 0xB3E6C1FD, 0xB05688C2; + +.text + +.align 8 +.type __camellia_avx_setup128, at function; +__camellia_avx_setup128: + /* input: + * %rdi: ctx, CTX; subkey storage at key_table(CTX) + * %xmm0: key + */ +#define cmll_sub(n, ctx) (key_table+((n)*8))(ctx) +#define KL128 %xmm0 +#define KA128 %xmm2 + + vpshufb .Lbswap128_mask RIP, KL128, KL128; + + vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovq .Lsbox4_input_mask RIP, %xmm12; + vbroadcastss .L0f0f0f0f RIP, %xmm13; + vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; + vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15; + + /* + * Generate KA + */ + vpsrldq $8, KL128, %xmm2; + vmovdqa KL128, %xmm3; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm2, %xmm4, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm2, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP); + camellia_f(%xmm2, %xmm3, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm4, %xmm1, + %xmm5, %xmm6, %xmm7, %xmm8, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP); + + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm4, %xmm2, %xmm2; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm2, KA128; + vpor %xmm3, KA128, KA128; + + /* + * Generate subkeys + */ + vmovdqu KA128, cmll_sub(24, CTX); + vec_rol128(KL128, %xmm3, 15, %xmm15); + vec_rol128(KA128, %xmm4, 15, %xmm15); + vec_rol128(KA128, %xmm5, 30, %xmm15); + vec_rol128(KL128, %xmm6, 45, %xmm15); + vec_rol128(KA128, %xmm7, 45, %xmm15); + vec_rol128(KL128, %xmm8, 60, %xmm15); + vec_rol128(KA128, %xmm9, 60, %xmm15); + vec_ror128(KL128, %xmm10, 128-77, %xmm15); + + /* absorb kw2 to other subkeys */ + vpslldq $8, KL128, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, KA128, KA128; + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + + /* subl(1) ^= subr(1) & ~subr(9); */ + vpandn %xmm15, %xmm5, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm9, %xmm9; + + /* subl(1) ^= subr(1) & ~subr(17); */ + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, KL128, KL128; + vpshufd $0x1b, KA128, KA128; + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + vpshufd $0x1b, %xmm10, %xmm10; + + vmovdqu KL128, cmll_sub(0, CTX); + vpshufd $0x1b, KL128, KL128; + vmovdqu KA128, cmll_sub(2, CTX); + vmovdqu %xmm3, cmll_sub(4, CTX); + vmovdqu %xmm4, cmll_sub(6, CTX); + vmovdqu %xmm5, cmll_sub(8, CTX); + vmovdqu %xmm6, cmll_sub(10, CTX); + vpsrldq $8, %xmm8, %xmm8; + vmovq %xmm7, cmll_sub(12, CTX); + vmovq %xmm8, cmll_sub(13, CTX); + vmovdqu %xmm9, cmll_sub(14, CTX); + vmovdqu %xmm10, cmll_sub(16, CTX); + + vmovdqu cmll_sub(24, CTX), KA128; + + vec_ror128(KL128, %xmm3, 128 - 94, %xmm7); + vec_ror128(KA128, %xmm4, 128 - 94, %xmm7); + vec_ror128(KL128, %xmm5, 128 - 111, %xmm7); + vec_ror128(KA128, %xmm6, 128 - 111, %xmm7); + + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + vpslldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm6, %xmm6; + + /* absorb kw4 to other subkeys */ + vpslldq $8, %xmm6, %xmm15; + vpxor %xmm15, %xmm5, %xmm5; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm3, %xmm3; + + /* subl(25) ^= subr(25) & ~subr(16); */ + vpshufd $0x1b, cmll_sub(16, CTX), %xmm10; + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $4, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(25) & subl(16), subr(25) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + + vmovdqu %xmm3, cmll_sub(18, CTX); + vmovdqu %xmm4, cmll_sub(20, CTX); + vmovdqu %xmm5, cmll_sub(22, CTX); + vmovdqu %xmm6, cmll_sub(24, CTX); + + vpshufd $0x1b, cmll_sub(14, CTX), %xmm3; + vpshufd $0x1b, cmll_sub(12, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(10, CTX), %xmm5; + vpshufd $0x1b, cmll_sub(8, CTX), %xmm6; + + vpxor %xmm15, %xmm3, %xmm3; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + + /* subl(25) ^= subr(25) & ~subr(8); */ + vpandn %xmm15, %xmm6, %xmm13; + vpslldq $4, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(25) & subl(8), subr(25) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm6, %xmm14; + vpslld $1, %xmm14, %xmm11; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm11, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm3, %xmm3; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + + vmovdqu %xmm3, cmll_sub(14, CTX); + vmovdqu %xmm4, cmll_sub(12, CTX); + vmovdqu %xmm5, cmll_sub(10, CTX); + + vpshufd $0x1b, cmll_sub(6, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(4, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(2, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(0, CTX), %xmm0; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm2, %xmm2; + vpxor %xmm15, %xmm0, %xmm0; + + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm0, %xmm0; + + vpsrldq $8, %xmm2, %xmm3; + vpsrldq $8, %xmm4, %xmm5; + vpsrldq $8, %xmm6, %xmm7; + + /* + * key XOR is end of F-function. + */ + vpxor %xmm2, %xmm0, %xmm0; + vpxor %xmm4, %xmm2, %xmm2; + + vmovq %xmm0, cmll_sub(0, CTX); + vmovq %xmm3, cmll_sub(2, CTX); + vpxor %xmm5, %xmm3, %xmm3; + vpxor %xmm6, %xmm4, %xmm4; + vpxor %xmm7, %xmm5, %xmm5; + vmovq %xmm2, cmll_sub(3, CTX); + vmovq %xmm3, cmll_sub(4, CTX); + vmovq %xmm4, cmll_sub(5, CTX); + vmovq %xmm5, cmll_sub(6, CTX); + + vmovq cmll_sub(7, CTX), %xmm7; + vmovq cmll_sub(8, CTX), %xmm8; + vmovq cmll_sub(9, CTX), %xmm9; + vmovq cmll_sub(10, CTX), %xmm10; + /* tl = subl(10) ^ (subr(10) & ~subr(8)); */ + vpandn %xmm10, %xmm8, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm10, %xmm0; + /* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */ + vpand %xmm8, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm6, %xmm6; + vmovq %xmm6, cmll_sub(7, CTX); + + vmovq cmll_sub(11, CTX), %xmm11; + vmovq cmll_sub(12, CTX), %xmm12; + vmovq cmll_sub(13, CTX), %xmm13; + vmovq cmll_sub(14, CTX), %xmm14; + vmovq cmll_sub(15, CTX), %xmm15; + /* tl = subl(7) ^ (subr(7) & ~subr(9)); */ + vpandn %xmm7, %xmm9, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm7, %xmm0; + /* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */ + vpand %xmm9, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm11, %xmm0, %xmm0; + vpxor %xmm12, %xmm10, %xmm10; + vpxor %xmm13, %xmm11, %xmm11; + vpxor %xmm14, %xmm12, %xmm12; + vpxor %xmm15, %xmm13, %xmm13; + vmovq %xmm0, cmll_sub(10, CTX); + vmovq %xmm10, cmll_sub(11, CTX); + vmovq %xmm11, cmll_sub(12, CTX); + vmovq %xmm12, cmll_sub(13, CTX); + vmovq %xmm13, cmll_sub(14, CTX); + + vmovq cmll_sub(16, CTX), %xmm6; + vmovq cmll_sub(17, CTX), %xmm7; + vmovq cmll_sub(18, CTX), %xmm8; + vmovq cmll_sub(19, CTX), %xmm9; + vmovq cmll_sub(20, CTX), %xmm10; + /* tl = subl(18) ^ (subr(18) & ~subr(16)); */ + vpandn %xmm8, %xmm6, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm8, %xmm0; + /* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */ + vpand %xmm6, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm14, %xmm0, %xmm0; + vmovq %xmm0, cmll_sub(15, CTX); + + /* tl = subl(15) ^ (subr(15) & ~subr(17)); */ + vpandn %xmm15, %xmm7, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm15, %xmm0; + /* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */ + vpand %xmm7, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vmovq cmll_sub(21, CTX), %xmm1; + vmovq cmll_sub(22, CTX), %xmm2; + vmovq cmll_sub(23, CTX), %xmm3; + vmovq cmll_sub(24, CTX), %xmm4; + + vpxor %xmm9, %xmm0, %xmm0; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm1, %xmm9, %xmm9; + vpxor %xmm2, %xmm10, %xmm10; + vpxor %xmm3, %xmm1, %xmm1; + vpxor %xmm4, %xmm3, %xmm3; + + vmovq %xmm0, cmll_sub(18, CTX); + vmovq %xmm8, cmll_sub(19, CTX); + vmovq %xmm9, cmll_sub(20, CTX); + vmovq %xmm10, cmll_sub(21, CTX); + vmovq %xmm1, cmll_sub(22, CTX); + vmovq %xmm2, cmll_sub(23, CTX); + vmovq %xmm3, cmll_sub(24, CTX); + + /* kw2 and kw4 are unused now. */ + movq $0, cmll_sub(1, CTX); + movq $0, cmll_sub(25, CTX); + + vzeroall; + + ret; +.size __camellia_avx_setup128,.-__camellia_avx_setup128; + +.align 8 +.type __camellia_avx_setup256, at function; + +__camellia_avx_setup256: + /* input: + * %rdi: ctx, CTX; subkey storage at key_table(CTX) + * %xmm0 & %xmm1: key + */ +#define KL128 %xmm0 +#define KR128 %xmm1 +#define KA128 %xmm2 +#define KB128 %xmm3 + + vpshufb .Lbswap128_mask RIP, KL128, KL128; + vpshufb .Lbswap128_mask RIP, KR128, KR128; + + vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovq .Lsbox4_input_mask RIP, %xmm12; + vbroadcastss .L0f0f0f0f RIP, %xmm13; + vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; + vmovdqa .Lpre_tf_hi_s1 RIP, %xmm15; + + /* + * Generate KA + */ + vpxor KL128, KR128, %xmm3; + vpsrldq $8, KR128, %xmm6; + vpsrldq $8, %xmm3, %xmm2; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm2, %xmm4, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma1 RIP); + vpxor %xmm4, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm2, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma2 RIP); + vpxor %xmm6, %xmm2, %xmm2; + camellia_f(%xmm2, %xmm3, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma3 RIP); + vpxor %xmm4, %xmm3, %xmm3; + vpxor KR128, %xmm3, %xmm3; + camellia_f(%xmm3, %xmm4, %xmm5, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma4 RIP); + + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm4, %xmm2, %xmm2; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm2, KA128; + vpor %xmm3, KA128, KA128; + + /* + * Generate KB + */ + vpxor KA128, KR128, %xmm3; + vpsrldq $8, %xmm3, %xmm4; + vpslldq $8, %xmm3, %xmm3; + vpsrldq $8, %xmm3, %xmm3; + + camellia_f(%xmm4, %xmm5, %xmm6, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma5 RIP); + vpxor %xmm5, %xmm3, %xmm3; + + camellia_f(%xmm3, %xmm5, %xmm6, + %xmm7, %xmm8, %xmm9, %xmm10, + %xmm11, %xmm12, %xmm13, %xmm14, %xmm15, .Lsigma6 RIP); + vpslldq $8, %xmm3, %xmm3; + vpxor %xmm5, %xmm4, %xmm4; + vpsrldq $8, %xmm3, %xmm3; + vpslldq $8, %xmm4, %xmm4; + vpor %xmm3, %xmm4, KB128; + + /* + * Generate subkeys + */ + vmovdqu KB128, cmll_sub(32, CTX); + vec_rol128(KR128, %xmm4, 15, %xmm15); + vec_rol128(KA128, %xmm5, 15, %xmm15); + vec_rol128(KR128, %xmm6, 30, %xmm15); + vec_rol128(KB128, %xmm7, 30, %xmm15); + vec_rol128(KL128, %xmm8, 45, %xmm15); + vec_rol128(KA128, %xmm9, 45, %xmm15); + vec_rol128(KL128, %xmm10, 60, %xmm15); + vec_rol128(KR128, %xmm11, 60, %xmm15); + vec_rol128(KB128, %xmm12, 60, %xmm15); + + /* absorb kw2 to other subkeys */ + vpslldq $8, KL128, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, KB128, KB128; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + + /* subl(1) ^= subr(1) & ~subr(9); */ + vpandn %xmm15, %xmm6, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(9), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm6, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm9, %xmm9; + + vpshufd $0x1b, KL128, KL128; + vpshufd $0x1b, KB128, KB128; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + + vmovdqu KL128, cmll_sub(0, CTX); + vpshufd $0x1b, KL128, KL128; + vmovdqu KB128, cmll_sub(2, CTX); + vmovdqu %xmm4, cmll_sub(4, CTX); + vmovdqu %xmm5, cmll_sub(6, CTX); + vmovdqu %xmm6, cmll_sub(8, CTX); + vmovdqu %xmm7, cmll_sub(10, CTX); + vmovdqu %xmm8, cmll_sub(12, CTX); + vmovdqu %xmm9, cmll_sub(14, CTX); + + vmovdqu cmll_sub(32, CTX), KB128; + + /* subl(1) ^= subr(1) & ~subr(17); */ + vpandn %xmm15, %xmm10, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(17), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm10, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm11, %xmm11; + vpxor %xmm15, %xmm12, %xmm12; + + vec_ror128(KL128, %xmm4, 128-77, %xmm14); + vec_ror128(KA128, %xmm5, 128-77, %xmm14); + vec_ror128(KR128, %xmm6, 128-94, %xmm14); + vec_ror128(KA128, %xmm7, 128-94, %xmm14); + vec_ror128(KL128, %xmm8, 128-111, %xmm14); + vec_ror128(KB128, %xmm9, 128-111, %xmm14); + + vpxor %xmm15, %xmm4, %xmm4; + + vpshufd $0x1b, %xmm10, %xmm10; + vpshufd $0x1b, %xmm11, %xmm11; + vpshufd $0x1b, %xmm12, %xmm12; + vpshufd $0x1b, %xmm4, %xmm4; + + vmovdqu %xmm10, cmll_sub(16, CTX); + vmovdqu %xmm11, cmll_sub(18, CTX); + vmovdqu %xmm12, cmll_sub(20, CTX); + vmovdqu %xmm4, cmll_sub(22, CTX); + + /* subl(1) ^= subr(1) & ~subr(25); */ + vpandn %xmm15, %xmm5, %xmm13; + vpslldq $12, %xmm13, %xmm13; + vpsrldq $8, %xmm13, %xmm13; + vpxor %xmm13, %xmm15, %xmm15; + /* dw = subl(1) & subl(25), subr(1) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm8, %xmm8; + vpslldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm9, %xmm9; + + /* absorb kw4 to other subkeys */ + vpslldq $8, %xmm9, %xmm15; + vpxor %xmm15, %xmm8, %xmm8; + vpxor %xmm15, %xmm7, %xmm7; + vpxor %xmm15, %xmm6, %xmm6; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm5, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm5, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm7, %xmm7; + vpshufd $0x1b, %xmm8, %xmm8; + vpshufd $0x1b, %xmm9, %xmm9; + + vmovdqu %xmm5, cmll_sub(24, CTX); + vmovdqu %xmm6, cmll_sub(26, CTX); + vmovdqu %xmm7, cmll_sub(28, CTX); + vmovdqu %xmm8, cmll_sub(30, CTX); + vmovdqu %xmm9, cmll_sub(32, CTX); + + vpshufd $0x1b, cmll_sub(22, CTX), %xmm0; + vpshufd $0x1b, cmll_sub(20, CTX), %xmm1; + vpshufd $0x1b, cmll_sub(18, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(16, CTX), %xmm3; + vpshufd $0x1b, cmll_sub(14, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(12, CTX), %xmm5; + vpshufd $0x1b, cmll_sub(10, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(8, CTX), %xmm7; + + vpxor %xmm15, %xmm0, %xmm0; + vpxor %xmm15, %xmm1, %xmm1; + vpxor %xmm15, %xmm2, %xmm2; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm3, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm3, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm5, %xmm5; + vpxor %xmm15, %xmm6, %xmm6; + + vpshufd $0x1b, %xmm0, %xmm0; + vpshufd $0x1b, %xmm1, %xmm1; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm5, %xmm5; + vpshufd $0x1b, %xmm6, %xmm6; + + vmovdqu %xmm0, cmll_sub(22, CTX); + vmovdqu %xmm1, cmll_sub(20, CTX); + vmovdqu %xmm2, cmll_sub(18, CTX); + vmovdqu %xmm4, cmll_sub(14, CTX); + vmovdqu %xmm5, cmll_sub(12, CTX); + vmovdqu %xmm6, cmll_sub(10, CTX); + + vpshufd $0x1b, cmll_sub(6, CTX), %xmm6; + vpshufd $0x1b, cmll_sub(4, CTX), %xmm4; + vpshufd $0x1b, cmll_sub(2, CTX), %xmm2; + vpshufd $0x1b, cmll_sub(0, CTX), %xmm0; + + /* subl(33) ^= subr(33) & ~subr(24); */ + vpandn %xmm15, %xmm7, %xmm14; + vpslldq $4, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + /* dw = subl(33) & subl(24), subr(33) ^= CAMELLIA_RL1(dw); */ + vpand %xmm15, %xmm7, %xmm14; + vpslld $1, %xmm14, %xmm13; + vpsrld $31, %xmm14, %xmm14; + vpaddd %xmm13, %xmm14, %xmm14; + vpsrldq $12, %xmm14, %xmm14; + vpslldq $8, %xmm14, %xmm14; + vpxor %xmm14, %xmm15, %xmm15; + + vpxor %xmm15, %xmm6, %xmm6; + vpxor %xmm15, %xmm4, %xmm4; + vpxor %xmm15, %xmm2, %xmm2; + vpxor %xmm15, %xmm0, %xmm0; + + vpshufd $0x1b, %xmm6, %xmm6; + vpshufd $0x1b, %xmm4, %xmm4; + vpshufd $0x1b, %xmm2, %xmm2; + vpshufd $0x1b, %xmm0, %xmm0; + + vpsrldq $8, %xmm2, %xmm3; + vpsrldq $8, %xmm4, %xmm5; + vpsrldq $8, %xmm6, %xmm7; + + /* + * key XOR is end of F-function. + */ + vpxor %xmm2, %xmm0, %xmm0; + vpxor %xmm4, %xmm2, %xmm2; + + vmovq %xmm0, cmll_sub(0, CTX); + vmovq %xmm3, cmll_sub(2, CTX); + vpxor %xmm5, %xmm3, %xmm3; + vpxor %xmm6, %xmm4, %xmm4; + vpxor %xmm7, %xmm5, %xmm5; + vmovq %xmm2, cmll_sub(3, CTX); + vmovq %xmm3, cmll_sub(4, CTX); + vmovq %xmm4, cmll_sub(5, CTX); + vmovq %xmm5, cmll_sub(6, CTX); + + vmovq cmll_sub(7, CTX), %xmm7; + vmovq cmll_sub(8, CTX), %xmm8; + vmovq cmll_sub(9, CTX), %xmm9; + vmovq cmll_sub(10, CTX), %xmm10; + /* tl = subl(10) ^ (subr(10) & ~subr(8)); */ + vpandn %xmm10, %xmm8, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm10, %xmm0; + /* dw = tl & subl(8), tr = subr(10) ^ CAMELLIA_RL1(dw); */ + vpand %xmm8, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm6, %xmm6; + vmovq %xmm6, cmll_sub(7, CTX); + + vmovq cmll_sub(11, CTX), %xmm11; + vmovq cmll_sub(12, CTX), %xmm12; + vmovq cmll_sub(13, CTX), %xmm13; + vmovq cmll_sub(14, CTX), %xmm14; + vmovq cmll_sub(15, CTX), %xmm15; + /* tl = subl(7) ^ (subr(7) & ~subr(9)); */ + vpandn %xmm7, %xmm9, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm7, %xmm0; + /* dw = tl & subl(9), tr = subr(7) ^ CAMELLIA_RL1(dw); */ + vpand %xmm9, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm11, %xmm0, %xmm0; + vpxor %xmm12, %xmm10, %xmm10; + vpxor %xmm13, %xmm11, %xmm11; + vpxor %xmm14, %xmm12, %xmm12; + vpxor %xmm15, %xmm13, %xmm13; + vmovq %xmm0, cmll_sub(10, CTX); + vmovq %xmm10, cmll_sub(11, CTX); + vmovq %xmm11, cmll_sub(12, CTX); + vmovq %xmm12, cmll_sub(13, CTX); + vmovq %xmm13, cmll_sub(14, CTX); + + vmovq cmll_sub(16, CTX), %xmm6; + vmovq cmll_sub(17, CTX), %xmm7; + vmovq cmll_sub(18, CTX), %xmm8; + vmovq cmll_sub(19, CTX), %xmm9; + vmovq cmll_sub(20, CTX), %xmm10; + /* tl = subl(18) ^ (subr(18) & ~subr(16)); */ + vpandn %xmm8, %xmm6, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm8, %xmm0; + /* dw = tl & subl(16), tr = subr(18) ^ CAMELLIA_RL1(dw); */ + vpand %xmm6, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vpxor %xmm14, %xmm0, %xmm0; + vmovq %xmm0, cmll_sub(15, CTX); + + /* tl = subl(15) ^ (subr(15) & ~subr(17)); */ + vpandn %xmm15, %xmm7, %xmm1; + vpsrldq $4, %xmm1, %xmm1; + vpxor %xmm1, %xmm15, %xmm0; + /* dw = tl & subl(17), tr = subr(15) ^ CAMELLIA_RL1(dw); */ + vpand %xmm7, %xmm0, %xmm1; + vpslld $1, %xmm1, %xmm2; + vpsrld $31, %xmm1, %xmm1; + vpaddd %xmm2, %xmm1, %xmm1; + vpslldq $12, %xmm1, %xmm1; + vpsrldq $8, %xmm1, %xmm1; + vpxor %xmm1, %xmm0, %xmm0; + + vmovq cmll_sub(21, CTX), %xmm1; + vmovq cmll_sub(22, CTX), %xmm2; + vmovq cmll_sub(23, CTX), %xmm3; + vmovq cmll_sub(24, CTX), %xmm4; + + vpxor %xmm9, %xmm0, %xmm0; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm1, %xmm9, %xmm9; + vpxor %xmm2, %xmm10, %xmm10; + vpxor %xmm3, %xmm1, %xmm1; + + vmovq %xmm0, cmll_sub(18, CTX); + vmovq %xmm8, cmll_sub(19, CTX); + vmovq %xmm9, cmll_sub(20, CTX); + vmovq %xmm10, cmll_sub(21, CTX); + vmovq %xmm1, cmll_sub(22, CTX); + + vmovq cmll_sub(25, CTX), %xmm5; + vmovq cmll_sub(26, CTX), %xmm6; + vmovq cmll_sub(27, CTX), %xmm7; + vmovq cmll_sub(28, CTX), %xmm8; + vmovq cmll_sub(29, CTX), %xmm9; + vmovq cmll_sub(30, CTX), %xmm10; + vmovq cmll_sub(31, CTX), %xmm11; + vmovq cmll_sub(32, CTX), %xmm12; + + /* tl = subl(26) ^ (subr(26) & ~subr(24)); */ + vpandn %xmm6, %xmm4, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm6, %xmm0; + /* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */ + vpand %xmm4, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm0, %xmm2, %xmm2; + vmovq %xmm2, cmll_sub(23, CTX); + + /* tl = subl(23) ^ (subr(23) & ~subr(25)); */ + vpandn %xmm3, %xmm5, %xmm15; + vpsrldq $4, %xmm15, %xmm15; + vpxor %xmm15, %xmm3, %xmm0; + /* dw = tl & subl(26), tr = subr(24) ^ CAMELLIA_RL1(dw); */ + vpand %xmm5, %xmm0, %xmm15; + vpslld $1, %xmm15, %xmm14; + vpsrld $31, %xmm15, %xmm15; + vpaddd %xmm14, %xmm15, %xmm15; + vpslldq $12, %xmm15, %xmm15; + vpsrldq $8, %xmm15, %xmm15; + vpxor %xmm15, %xmm0, %xmm0; + + vpxor %xmm7, %xmm0, %xmm0; + vpxor %xmm8, %xmm6, %xmm6; + vpxor %xmm9, %xmm7, %xmm7; + vpxor %xmm10, %xmm8, %xmm8; + vpxor %xmm11, %xmm9, %xmm9; + vpxor %xmm12, %xmm11, %xmm11; + + vmovq %xmm0, cmll_sub(26, CTX); + vmovq %xmm6, cmll_sub(27, CTX); + vmovq %xmm7, cmll_sub(28, CTX); + vmovq %xmm8, cmll_sub(29, CTX); + vmovq %xmm9, cmll_sub(30, CTX); + vmovq %xmm10, cmll_sub(31, CTX); + vmovq %xmm11, cmll_sub(32, CTX); + + /* kw2 and kw4 are unused now. */ + movq $0, cmll_sub(1, CTX); + movq $0, cmll_sub(33, CTX); + + vzeroall; + + ret; +.size __camellia_avx_setup256,.-__camellia_avx_setup256; + +.align 8 +.globl _gcry_camellia_aesni_avx_keygen +.type _gcry_camellia_aesni_avx_keygen, at function; + +_gcry_camellia_aesni_avx_keygen: + /* input: + * %rdi: ctx, CTX + * %rsi: key + * %rdx: keylen + */ + + vzeroupper; + + vmovdqu (%rsi), %xmm0; + cmpl $24, %edx; + jb __camellia_avx_setup128; + je .Lprepare_key192; + + vmovdqu 16(%rsi), %xmm1; + jmp __camellia_avx_setup256; + +.Lprepare_key192: + vpcmpeqd %xmm2, %xmm2, %xmm2; + vmovq 16(%rsi), %xmm1; + + vpxor %xmm1, %xmm2, %xmm2; + vpslldq $8, %xmm2, %xmm2; + vpor %xmm2, %xmm1, %xmm1; + + jmp __camellia_avx_setup256; +.size _gcry_camellia_aesni_avx_keygen,.-_gcry_camellia_aesni_avx_keygen; + #endif /*defined(ENABLE_AESNI_SUPPORT) && defined(ENABLE_AVX_SUPPORT)*/ #endif /*__x86_64*/ diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index 78ef2d6..65c923e 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -32,8 +32,8 @@ #define CAMELLIA_TABLE_BYTE_LEN 272 /* struct CAMELLIA_context: */ -#define key_bitlength 0 -#define key_table 4 +#define key_table 0 +#define key_bitlength CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %rdi diff --git a/cipher/camellia-arm.S b/cipher/camellia-arm.S index 302f436..c30d194 100644 --- a/cipher/camellia-arm.S +++ b/cipher/camellia-arm.S @@ -28,11 +28,8 @@ .syntax unified .arm -#define CAMELLIA_TABLE_BYTE_LEN 272 - /* struct camellia_ctx: */ #define key_table 0 -#define key_length CAMELLIA_TABLE_BYTE_LEN /* register macros */ #define CTX %r0 diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index b7ae0fc..24936ce 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -90,13 +90,13 @@ typedef struct { - int keybitlength; KEY_TABLE_TYPE keytable; + int keybitlength; #ifdef USE_AESNI_AVX - int use_aesni_avx; /* AES-NI/AVX implementation shall be used. */ + unsigned int use_aesni_avx:1; /* AES-NI/AVX implementation shall be used. */ #endif /*USE_AESNI_AVX*/ #ifdef USE_AESNI_AVX2 - int use_aesni_avx2; /* AES-NI/AVX2 implementation shall be used. */ + unsigned int use_aesni_avx2:1;/* AES-NI/AVX2 implementation shall be used. */ #endif /*USE_AESNI_AVX2*/ } CAMELLIA_context; @@ -118,6 +118,10 @@ extern void _gcry_camellia_aesni_avx_cfb_dec(CAMELLIA_context *ctx, unsigned char *out, const unsigned char *in, unsigned char *iv); + +extern void _gcry_camellia_aesni_avx_keygen(CAMELLIA_context *ctx, + const unsigned char *key, + unsigned int keylen); #endif #ifdef USE_AESNI_AVX2 @@ -148,6 +152,9 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) CAMELLIA_context *ctx=c; static int initialized=0; static const char *selftest_failed=NULL; +#if defined(USE_AESNI_AVX) || defined(USE_AESNI_AVX2) + unsigned int hwf = _gcry_get_hw_features (); +#endif if(keylen!=16 && keylen!=24 && keylen!=32) return GPG_ERR_INV_KEYLEN; @@ -163,39 +170,38 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) if(selftest_failed) return GPG_ERR_SELFTEST_FAILED; +#ifdef USE_AESNI_AVX + ctx->use_aesni_avx = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX); +#endif +#ifdef USE_AESNI_AVX2 + ctx->use_aesni_avx2 = (hwf & HWF_INTEL_AESNI) && (hwf & HWF_INTEL_AVX2); +#endif + ctx->keybitlength=keylen*8; - Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); - _gcry_burn_stack - ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ - +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ - +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ - +3*2*sizeof(void*) /* Function calls. */ - ); + if (0) + ; #ifdef USE_AESNI_AVX - ctx->use_aesni_avx = 0; - if ((_gcry_get_hw_features () & HWF_INTEL_AESNI) && - (_gcry_get_hw_features () & HWF_INTEL_AVX)) - { - ctx->use_aesni_avx = 1; - } + else if (ctx->use_aesni_avx) + _gcry_camellia_aesni_avx_keygen(ctx, key, keylen); + else #endif - -#ifdef USE_AESNI_AVX2 - ctx->use_aesni_avx2 = 0; - if ((_gcry_get_hw_features () & HWF_INTEL_AESNI) && - (_gcry_get_hw_features () & HWF_INTEL_AVX2)) { - ctx->use_aesni_avx2 = 1; + Camellia_Ekeygen(ctx->keybitlength,key,ctx->keytable); + _gcry_burn_stack + ((19+34+34)*sizeof(u32)+2*sizeof(void*) /* camellia_setup256 */ + +(4+32)*sizeof(u32)+2*sizeof(void*) /* camellia_setup192 */ + +0+sizeof(int)+2*sizeof(void*) /* Camellia_Ekeygen */ + +3*2*sizeof(void*) /* Function calls. */ + ); } -#endif return 0; } #ifdef USE_ARM_ASM -/* Assembly implementations of CAST5. */ +/* Assembly implementations of Camellia. */ extern void _gcry_camellia_arm_encrypt_block(const KEY_TABLE_TYPE keyTable, byte *outbuf, const byte *inbuf, const int keybits); commit c8ad83fb605fdbf6dc0b0dbcc8aedfbd477640da Author: Jussi Kivilinna Date: Fri Nov 15 16:23:00 2013 +0200 Avoid unneeded stack burning with AES-NI and reduce number of 'decryption_prepared' checks * cipher/rijndael.c (RIJNDAEL_context): Make 'decryption_prepared', 'use_padlock' and 'use_aesni' 1-bit members in bitfield. (do_setkey): Move 'hwfeatures' inside [USE_AESNI ||?USE_PADLOCK]. (do_aesni_enc_aligned): Rename to... (do_aesni_enc): ...this, as function does not require aligned input. (do_aesni_dec_aligned): Rename to... (do_aesni_dec): ...this, as function does not require aligned input. (do_aesni): Remove. (rijndael_encrypt): Call 'do_aesni_enc' instead of 'do_aesni'. (rijndael_decrypt): Call 'do_aesni_dec' instead of 'do_aesni'. (check_decryption_preparation): New. (do_decrypt): Remove 'decryption_prepared' check. (rijndael_decrypt): Ditto and call 'check_decryption_preparation'. (_gcry_aes_cbc_dec): Ditto. (_gcry_aes_cfb_enc): Add 'burn_depth' and burn stack only when needed. (_gcry_aes_cbc_enc): Ditto. (_gcry_aes_ctr_enc): Ditto. (_gcry_aes_cfb_dec): Ditto. (_gcry_aes_cbc_dec): Ditto and correct clearing of 'savebuf'. -- Patch is mostly about reducing overhead for short buffers. Results on Intel i5-4570: After: $ tests/benchmark --cipher-repetitions 1000 --cipher-with-keysetup cipher aes Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 480ms 540ms 1750ms 300ms 1630ms 300ms 1640ms 1640ms 350ms 350ms 2130ms 2140ms Before: $ tests/benchmark --cipher-repetitions 1000 --cipher-with-keysetup cipher aes Running each test 1000 times. ECB/Stream CBC CFB OFB CTR CCM --------------- --------------- --------------- --------------- --------------- --------------- AES 520ms 590ms 1760ms 310ms 1640ms 310ms 1610ms 1600ms 360ms 360ms 2150ms 2160ms Signed-off-by: Jussi Kivilinna diff --git a/cipher/rijndael.c b/cipher/rijndael.c index b5a3d10..47b2559 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -163,13 +163,13 @@ typedef struct PROPERLY_ALIGNED_TYPE dummy; byte keyschedule[MAXROUNDS+1][4][4]; } u2; - int rounds; /* Key-length-dependent number of rounds. */ - int decryption_prepared; /* The decryption key schedule is available. */ + int rounds; /* Key-length-dependent number of rounds. */ + unsigned int decryption_prepared:1; /* The decryption key schedule is available. */ #ifdef USE_PADLOCK - int use_padlock; /* Padlock shall be used. */ + unsigned int use_padlock:1; /* Padlock shall be used. */ #endif /*USE_PADLOCK*/ #ifdef USE_AESNI - int use_aesni; /* AES-NI shall be used. */ + unsigned int use_aesni:1; /* AES-NI shall be used. */ #endif /*USE_AESNI*/ } RIJNDAEL_context ATTR_ALIGNED_16; @@ -465,7 +465,9 @@ do_setkey (RIJNDAEL_context *ctx, const byte *key, const unsigned keylen) int rounds; int i,j, r, t, rconpointer = 0; int KC; +#if defined(USE_AESNI) || defined(USE_PADLOCK) unsigned int hwfeatures; +#endif /* The on-the-fly self tests are only run in non-fips mode. In fips mode explicit self-tests are required. Actually the on-the-fly @@ -959,9 +961,9 @@ do_padlock (const RIJNDAEL_context *ctx, int decrypt_flag, back. If we decide to implement some block modes with parallelized AES instructions, it might indeed be better to use plain asm ala mpi/. */ -static void -do_aesni_enc_aligned (const RIJNDAEL_context *ctx, - unsigned char *b, const unsigned char *a) +static inline void +do_aesni_enc (const RIJNDAEL_context *ctx, unsigned char *b, + const unsigned char *a) { #define aesenc_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdc, 0xc1\n\t" #define aesenclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdd, 0xc1\n\t" @@ -1019,9 +1021,9 @@ do_aesni_enc_aligned (const RIJNDAEL_context *ctx, } -static void -do_aesni_dec_aligned (const RIJNDAEL_context *ctx, - unsigned char *b, const unsigned char *a) +static inline void +do_aesni_dec (const RIJNDAEL_context *ctx, unsigned char *b, + const unsigned char *a) { #define aesdec_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xde, 0xc1\n\t" #define aesdeclast_xmm1_xmm0 ".byte 0x66, 0x0f, 0x38, 0xdf, 0xc1\n\t" @@ -1626,24 +1628,6 @@ do_aesni_ctr_4 (const RIJNDAEL_context *ctx, #undef aesenclast_xmm1_xmm4 } - -static void -do_aesni (RIJNDAEL_context *ctx, int decrypt_flag, - unsigned char *bx, const unsigned char *ax) -{ - - if (decrypt_flag) - { - if (!ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - do_aesni_dec_aligned (ctx, bx, ax); - } - else - do_aesni_enc_aligned (ctx, bx, ax); -} #endif /*USE_AESNI*/ @@ -1666,7 +1650,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a) else if (ctx->use_aesni) { aesni_prepare (); - do_aesni (ctx, 0, b, a); + do_aesni_enc (ctx, b, a); aesni_cleanup (); burn_stack = 0; } @@ -1693,6 +1677,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); if (0) ; @@ -1722,6 +1707,8 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, inbuf += BLOCKSIZE; } aesni_cleanup (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -1737,7 +1724,8 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -1754,9 +1742,13 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; unsigned char *last_iv; + unsigned int burn_depth = 48 + 2*sizeof(int); +#ifdef USE_AESNI + int use_aesni = ctx->use_aesni; +#endif #ifdef USE_AESNI - if (ctx->use_aesni) + if (use_aesni) aesni_prepare (); #endif /*USE_AESNI*/ @@ -1767,7 +1759,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, if (0) ; #ifdef USE_AESNI - else if (ctx->use_aesni) + else if (use_aesni) { /* ~35% speed up on Sandy-Bridge when doing xoring and copying with SSE registers. */ @@ -1781,7 +1773,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, [outbuf] "m" (*outbuf) : "memory" ); - do_aesni (ctx, 0, outbuf, outbuf); + do_aesni_enc (ctx, outbuf, outbuf); } #endif /*USE_AESNI*/ else @@ -1809,7 +1801,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, if (0) ; #ifdef USE_AESNI - else if (ctx->use_aesni) + else if (use_aesni) asm volatile ("movdqu %[last], %%xmm0\n\t" "movdqu %%xmm0, %[iv]\n\t" : /* No output */ @@ -1822,11 +1814,15 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, } #ifdef USE_AESNI - if (ctx->use_aesni) - aesni_cleanup (); + if (use_aesni) + { + aesni_cleanup (); + burn_depth = 0; /* No stack usage. */ + } #endif /*USE_AESNI*/ - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -1843,6 +1839,7 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); int i; if (0) @@ -1876,6 +1873,8 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, } aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -1900,7 +1899,8 @@ _gcry_aes_ctr_enc (void *context, unsigned char *ctr, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -2007,12 +2007,6 @@ do_decrypt_aligned (RIJNDAEL_context *ctx, static void do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) { - if ( !ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - #if !defined(USE_AMD64_ASM) && !defined(USE_ARM_ASM) /* BX and AX are not necessary correctly aligned. Thus we might need to copy them here. We try to align to a 16 bytes. */ @@ -2041,6 +2035,21 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax) } +static inline void +check_decryption_preparation (RIJNDAEL_context *ctx) +{ + if (0) + ; +#ifdef USE_PADLOCK + else if (ctx->use_padlock) + { /* Padlock does not need decryption subkeys. */ } +#endif /*USE_PADLOCK*/ + else if ( !ctx->decryption_prepared ) + { + prepare_decryption ( ctx ); + ctx->decryption_prepared = 1; + } +} static unsigned int @@ -2049,6 +2058,8 @@ rijndael_decrypt (void *context, byte *b, const byte *a) RIJNDAEL_context *ctx = context; unsigned int burn_stack; + check_decryption_preparation (ctx); + if (0) ; #ifdef USE_PADLOCK @@ -2062,7 +2073,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a) else if (ctx->use_aesni) { aesni_prepare (); - do_aesni (ctx, 1, b, a); + do_aesni_dec (ctx, b, a); aesni_cleanup (); burn_stack = 0; } @@ -2089,6 +2100,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; + unsigned int burn_depth = 48 + 2*sizeof(int); if (0) ; @@ -2161,6 +2173,8 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, } aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else @@ -2174,7 +2188,8 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, } } - _gcry_burn_stack (48 + 2*sizeof(int)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } @@ -2190,7 +2205,9 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; const unsigned char *inbuf = inbuf_arg; - unsigned char savebuf[BLOCKSIZE]; + unsigned int burn_depth = 48 + 2*sizeof(int) + 4*sizeof (char*); + + check_decryption_preparation (ctx); if (0) ; @@ -2199,12 +2216,6 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, { aesni_prepare (); - if (!ctx->decryption_prepared ) - { - prepare_decryption ( ctx ); - ctx->decryption_prepared = 1; - } - asm volatile ("movdqu %[iv], %%xmm5\n\t" /* use xmm5 as fast IV storage */ : /* No output */ @@ -2259,7 +2270,7 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, : "memory"); /* uses only xmm0 and xmm1 */ - do_aesni_dec_aligned (ctx, outbuf, inbuf); + do_aesni_dec (ctx, outbuf, inbuf); asm volatile ("movdqu %[outbuf], %%xmm0\n\t" @@ -2282,29 +2293,38 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv, aesni_cleanup (); aesni_cleanup_2_6 (); + + burn_depth = 0; /* No stack usage. */ } #endif /*USE_AESNI*/ else - for ( ;nblocks; nblocks-- ) - { - /* INBUF is needed later and it may be identical to OUTBUF, so store - the intermediate result to SAVEBUF. */ + { + unsigned char savebuf[BLOCKSIZE]; - if (0) - ; + for ( ;nblocks; nblocks-- ) + { + /* INBUF is needed later and it may be identical to OUTBUF, so store + the intermediate result to SAVEBUF. */ + + if (0) + ; #ifdef USE_PADLOCK - else if (ctx->use_padlock) - do_padlock (ctx, 1, savebuf, inbuf); + else if (ctx->use_padlock) + do_padlock (ctx, 1, savebuf, inbuf); #endif /*USE_PADLOCK*/ - else - do_decrypt (ctx, savebuf, inbuf); + else + do_decrypt (ctx, savebuf, inbuf); - buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); - inbuf += BLOCKSIZE; - outbuf += BLOCKSIZE; - } + buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE); + inbuf += BLOCKSIZE; + outbuf += BLOCKSIZE; + } + + wipememory(savebuf, sizeof(savebuf)); + } - _gcry_burn_stack (48 + 2*sizeof(int) + BLOCKSIZE + 4*sizeof (char*)); + if (burn_depth) + _gcry_burn_stack (burn_depth); } ----------------------------------------------------------------------- Summary of changes: cipher/camellia-aesni-avx-amd64.S | 982 +++++++++++++++++++++++++++++++++++- cipher/camellia-aesni-avx2-amd64.S | 4 +- cipher/camellia-arm.S | 3 - cipher/camellia-glue.c | 54 +- cipher/rijndael.c | 158 +++--- 5 files changed, 1101 insertions(+), 100 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Sat Nov 16 13:15:46 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 16 Nov 2013 14:15:46 +0200 Subject: [PATCH 1/3] Use correct blocksize of 32 bytes for GOSTR3411-94 HMAC Message-ID: <20131116121546.8367.83081.stgit@localhost6.localdomain6> * cipher/md.c (md_open): Set macpads_Bsize to 32 for GCRY_MD_GOST24311_94. -- Signed-off-by: Jussi Kivilinna --- cipher/md.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cipher/md.c b/cipher/md.c index 3bfa3bd..65dadd1 100644 --- a/cipher/md.c +++ b/cipher/md.c @@ -326,6 +326,9 @@ md_open (gcry_md_hd_t *h, int algo, int secure, int hmac) case GCRY_MD_SHA512: ctx->macpads_Bsize = 128; break; + case GCRY_MD_GOSTR3411_94: + ctx->macpads_Bsize = 32; + break; default: ctx->macpads_Bsize = 64; break; From jussi.kivilinna at iki.fi Sat Nov 16 13:15:56 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 16 Nov 2013 14:15:56 +0200 Subject: [PATCH 3/3] Add CMAC (Cipher-based MAC) to MAC API In-Reply-To: <20131116121546.8367.83081.stgit@localhost6.localdomain6> References: <20131116121546.8367.83081.stgit@localhost6.localdomain6> Message-ID: <20131116121556.8367.33147.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'cipher-cmac.c' and 'mac-cmac.c'. * cipher/cipher-cmac.c: New. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_keys'. (gcry_cipher_handle.u_mode): Add 'cmac'. * cipher/cipher.c (gcry_cipher_open): Rename to... (_gcry_cipher_open_internal): ...this and add CMAC. (gcry_cipher_open): New wrapper that disallows use of internal modes (CMAC) from outside. (cipher_setkey, cipher_encrypt, cipher_decrypt) (_gcry_cipher_authenticate, _gcry_cipher_gettag) (_gcry_cipher_checktag): Add handling for CMAC mode. (cipher_reset): Do not reset 'marks.key'. * cipher/mac-cmac.c: New. * cipher/mac-internal.h: Add CMAC support and algorithms. * cipher/mac.c: Add CMAC algorithms. * src/cipher.h (gcry_cipher_internal_modes): New. (_gcry_cipher_open_internal, _gcry_cipher_cmac_authenticate) (_gcry_cipher_cmac_get_tag, _gcry_cipher_cmac_check_tag) (_gcry_cipher_cmac_set_subkeys): New prototypes. * src/gcrypt.h.in (gcry_mac_algos): Add CMAC algorithms. * tests/basic.c (check_mac): Add CMAC test vectors. -- Patch adds CMAC (Cipher-based MAC) as defined in RFC 4493 and NIST Special Publication 800-38B. Internally CMAC is added to cipher module, but is available to outside only through MAC API. TODO: - Documentation. Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 4 - cipher/cipher-cmac.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ cipher/cipher-internal.h | 13 ++- cipher/cipher.c | 55 +++++++++++ cipher/mac-cmac.c | 230 +++++++++++++++++++++++++++++++++++++++++++++ cipher/mac-internal.h | 41 ++++++++ cipher/mac.c | 33 ++++++ src/cipher.h | 24 +++++ src/gcrypt.h.in | 14 +++ tests/basic.c | 141 +++++++++++++++++++++++++++ 10 files changed, 788 insertions(+), 4 deletions(-) create mode 100644 cipher/cipher-cmac.c create mode 100644 cipher/mac-cmac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 1d54b07..2fd9822 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,12 +40,12 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ -cipher-ccm.c \ +cipher-ccm.c cipher-cmac.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ -mac-hmac.c \ +mac-hmac.c mac-cmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c new file mode 100644 index 0000000..6bab1b3 --- /dev/null +++ b/cipher/cipher-cmac.c @@ -0,0 +1,237 @@ +/* cmac.c - CMAC, Cipher-based MAC. + * Copyright ? 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 "g10lib.h" +#include "cipher.h" +#include "cipher-internal.h" +#include "bufhelp.h" + + +#define set_burn(burn, nburn) do { \ + unsigned int __nburn = (nburn); \ + (burn) = (burn) > __nburn ? (burn) : __nburn; } while (0) + + +static void +cmac_write (gcry_cipher_hd_t c, const byte * inbuf, size_t inlen) +{ + gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; + const unsigned int blocksize = c->spec->blocksize; + byte outbuf[MAX_BLOCKSIZE]; + unsigned int burn = 0; + unsigned int nblocks; + + if (!inlen || !inbuf) + return; + + /* Last block is needed for cmac_final. */ + if (c->unused + inlen <= blocksize) + { + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + return; + } + + if (c->unused) + { + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + + buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize); + set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv)); + + c->unused = 0; + } + + if (c->bulk.cbc_enc && inlen > blocksize) + { + nblocks = inlen / blocksize; + nblocks -= (nblocks * blocksize == inlen); + + c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, 1); + inbuf += nblocks * blocksize; + inlen -= nblocks * blocksize; + + wipememory (outbuf, sizeof (outbuf)); + } + else + while (inlen > blocksize) + { + buf_xor (c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); + set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv)); + inlen -= blocksize; + inbuf += blocksize; + } + + /* Make sure that last block is passed to cmac_final. */ + if (inlen == 0) + BUG (); + + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); +} + + +static void cmac_generate_subkeys (gcry_cipher_hd_t c) +{ + const unsigned int blocksize = c->spec->blocksize; + byte rb, carry, t, bi; + unsigned int burn; + int i, j; + union + { + size_t _aligned; + byte buf[MAX_BLOCKSIZE]; + } u; + + if (MAX_BLOCKSIZE < blocksize) + BUG(); + + /* encrypt zero block */ + memset (u.buf, 0, blocksize); + burn = c->spec->encrypt (&c->context.c, u.buf, u.buf); + + /* Currently supported blocksizes are 16 and 8. */ + rb = blocksize == 16 ? 0x87 : 0x1B /*blocksize == 8 */ ; + + for (j = 0; j < 2; j++) + { + /* Generate subkeys K1 and K2 */ + carry = 0; + for (i = blocksize - 1; i >= 0; i--) + { + bi = u.buf[i]; + t = carry | (bi << 1); + carry = bi >> 7; + u.buf[i] = t & 0xff; + c->u_keys.cmac.subkeys[j][i] = u.buf[i]; + } + u.buf[blocksize - 1] ^= carry ? rb : 0; + c->u_keys.cmac.subkeys[j][blocksize - 1] = u.buf[blocksize - 1]; + } + + wipememory (&u, sizeof (u)); + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); +} + + +static void +cmac_final (gcry_cipher_hd_t c) +{ + const unsigned int blocksize = c->spec->blocksize; + unsigned int count = c->unused; + unsigned int burn; + byte *subkey; + + if (count == blocksize) + subkey = c->u_keys.cmac.subkeys[0]; /* K1 */ + else + { + subkey = c->u_keys.cmac.subkeys[1]; /* K2 */ + c->lastiv[count++] = 0x80; + while (count < blocksize) + c->lastiv[count++] = 0; + } + + buf_xor (c->lastiv, c->lastiv, subkey, blocksize); + + buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize); + burn = c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_iv.iv); + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); + + c->unused = 0; +} + + +static gcry_err_code_t +cmac_tag (gcry_cipher_hd_t c, unsigned char *tag, size_t taglen, int check) +{ + if (!tag || taglen == 0 || taglen > c->spec->blocksize) + return GPG_ERR_INV_ARG; + + if (!c->u_mode.cmac.tag) + { + cmac_final (c); + c->u_mode.cmac.tag = 1; + } + + if (!check) + { + memcpy (tag, c->u_iv.iv, taglen); + return GPG_ERR_NO_ERROR; + } + else + { + return buf_eq_const(tag, c->u_iv.iv, taglen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + } +} + + +gcry_err_code_t +_gcry_cipher_cmac_authenticate (gcry_cipher_hd_t c, + const unsigned char *abuf, size_t abuflen) +{ + if (abuflen > 0 && !abuf) + return GPG_ERR_INV_ARG; + if (c->u_mode.cmac.tag) + return GPG_ERR_INV_STATE; + /* To support new blocksize, update cmac_generate_subkeys() then add new + blocksize here. */ + if (c->spec->blocksize != 16 && c->spec->blocksize != 8) + return GPG_ERR_INV_CIPHER_MODE; + + cmac_write (c, abuf, abuflen); + + return GPG_ERR_NO_ERROR; +} + + +gcry_err_code_t +_gcry_cipher_cmac_get_tag (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen) +{ + return cmac_tag (c, outtag, taglen, 0); +} + + +gcry_err_code_t +_gcry_cipher_cmac_check_tag (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen) +{ + return cmac_tag (c, (unsigned char *) intag, taglen, 1); +} + +gcry_err_code_t +_gcry_cipher_cmac_set_subkeys (gcry_cipher_hd_t c) +{ + cmac_generate_subkeys (c); + + return GPG_ERR_NO_ERROR; +} diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index db06823..70351b1 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -136,8 +136,20 @@ struct gcry_cipher_handle processed. */ unsigned int tag:1; /* Set to 1 if tag has been finalized. */ } ccm; + /* Mode specific storage for CMAC mode. */ + struct { + unsigned int tag:1; /* Set to 1 if tag has been finalized. */ + } cmac; } u_mode; + /* Mode specific storage for subkeys. _Not_ cleared by gcry_cipher_reset. */ + union { + /* Mode specific storage for CMAC mode. */ + struct { + unsigned char subkeys[2][MAX_BLOCKSIZE]; + } cmac; + } u_keys; + /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation whereas the second one is a copy created by cipher_setkey and @@ -217,5 +229,4 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag const unsigned char *intag, size_t taglen); - #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index 80aa7a7..1e54a9e 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -344,6 +344,24 @@ gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags) { + gcry_err_code_t err; + gcry_cipher_hd_t h = NULL; + + if (mode >= GCRY_CIPHER_MODE_INTERNAL) + err = GPG_ERR_INV_CIPHER_MODE; + else + err = _gcry_cipher_open_internal (&h, algo, mode, flags); + + *handle = err ? NULL : h; + + return gcry_error (err); +} + + +gcry_err_code_t +_gcry_cipher_open_internal (gcry_cipher_hd_t *handle, + int algo, int mode, unsigned int flags) +{ int secure = (flags & GCRY_CIPHER_SECURE); gcry_cipher_spec_t *spec; gcry_cipher_hd_t h = NULL; @@ -388,6 +406,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: + case GCRY_CIPHER_MODE_CMAC: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; @@ -567,10 +586,20 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) (void *) &c->context.c, c->spec->contextsize); c->marks.key = 1; + + switch (c->mode) + { + case GCRY_CIPHER_MODE_CMAC: + _gcry_cipher_cmac_set_subkeys (c); + break; + default: + break; + }; } else c->marks.key = 0; + return gcry_error (ret); } @@ -613,6 +642,10 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) static void cipher_reset (gcry_cipher_hd_t c) { + unsigned int marks_key; + + marks_key = c->marks.key; + memcpy (&c->context.c, (char *) &c->context.c + c->spec->contextsize, c->spec->contextsize); @@ -622,6 +655,8 @@ cipher_reset (gcry_cipher_hd_t c) memset (c->u_ctr.ctr, 0, c->spec->blocksize); memset (&c->u_mode, 0, sizeof c->u_mode); c->unused = 0; + + c->marks.key = marks_key; } @@ -717,6 +752,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ccm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -817,6 +856,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ccm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -942,6 +985,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, rc = _gcry_cipher_ccm_authenticate (hd, abuf, abuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_authenticate (hd, abuf, abuflen); + break; + default: log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -962,6 +1009,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) rc = _gcry_cipher_ccm_get_tag (hd, outtag, taglen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_get_tag (hd, outtag, taglen); + break; + default: log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -982,6 +1033,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) rc = _gcry_cipher_ccm_check_tag (hd, intag, taglen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_check_tag (hd, intag, taglen); + break; + default: log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c new file mode 100644 index 0000000..b35b6cd --- /dev/null +++ b/cipher/mac-cmac.c @@ -0,0 +1,230 @@ +/* mac-cmac.c - CMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "./mac-internal.h" + + +static int map_mac_algo_to_cipher (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_CIPHER_NONE; + case GCRY_MAC_CMAC_AES: + return GCRY_CIPHER_AES; + case GCRY_MAC_CMAC_3DES: + return GCRY_CIPHER_3DES; + case GCRY_MAC_CMAC_CAMELLIA: + return GCRY_CIPHER_CAMELLIA128; + case GCRY_MAC_CMAC_IDEA: + return GCRY_CIPHER_IDEA; + case GCRY_MAC_CMAC_CAST5: + return GCRY_CIPHER_CAST5; + case GCRY_MAC_CMAC_BLOWFISH: + return GCRY_CIPHER_BLOWFISH; + case GCRY_MAC_CMAC_TWOFISH: + return GCRY_CIPHER_TWOFISH; + case GCRY_MAC_CMAC_SERPENT: + return GCRY_CIPHER_SERPENT128; + case GCRY_MAC_CMAC_SEED: + return GCRY_CIPHER_SEED; + case GCRY_MAC_CMAC_RFC2268: + return GCRY_CIPHER_RFC2268_128; + case GCRY_MAC_CMAC_GOST28147: + return GCRY_CIPHER_GOST28147; + } +} + + +static gcry_err_code_t cmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_cipher_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + int cipher_algo; + unsigned int flags; + + cipher_algo = map_mac_algo_to_cipher(h->spec->algo); + flags = (secure ? GCRY_CIPHER_SECURE : 0); + + err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC, + flags); + if (err) + return err; + + h->u.cmac.cipher_algo = cipher_algo; + h->u.cmac.ctx = hd; + 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) +{ + return _gcry_cipher_cmac_get_tag (h->u.cmac.ctx, outbuf, outlen); +} + + +static gcry_err_code_t +cmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + return _gcry_cipher_cmac_check_tag (h->u.cmac.ctx, buf, buflen); +} + + +static unsigned int cmac_get_maclen (int algo) +{ + return _gcry_cipher_get_algo_blklen (map_mac_algo_to_cipher (algo)); +} + + +static unsigned int cmac_get_keylen (int algo) +{ + return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); +} + + +static gcry_mac_spec_ops_t cmac_ops = + { + cmac_open, + cmac_close, + cmac_setkey, + NULL, + cmac_reset, + cmac_write, + cmac_read, + cmac_verify, + cmac_get_maclen, + cmac_get_keylen + }; + + +#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 diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 3da40f7..aeffb19 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -98,6 +98,10 @@ struct gcry_mac_handle gcry_md_hd_t md_ctx; int md_algo; } hmac; + struct { + gcry_cipher_hd_t ctx; + int cipher_algo; + } cmac; } u; }; @@ -138,3 +142,40 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; #if USE_MD4 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; #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 diff --git a/cipher/mac.c b/cipher/mac.c index 2a4bce8..dca4af3 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -64,6 +64,39 @@ static gcry_mac_spec_t *mac_list[] = #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #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, +#endif +#if USE_TWOFISH + &_gcry_mac_type_spec_cmac_twofish, +#endif +#if USE_SERPENT + &_gcry_mac_type_spec_cmac_serpent, +#endif +#if USE_RFC2268 + &_gcry_mac_type_spec_cmac_rfc2268, +#endif +#if USE_SEED + &_gcry_mac_type_spec_cmac_seed, +#endif +#if USE_CAMELLIA + &_gcry_mac_type_spec_cmac_camellia, +#endif +#ifdef USE_IDEA + &_gcry_mac_type_spec_cmac_idea, +#endif +#if USE_GOST28147 + &_gcry_mac_type_spec_cmac_gost28147, +#endif NULL, }; diff --git a/src/cipher.h b/src/cipher.h index 38d2a97..10bfe0c 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -84,6 +84,30 @@ struct pk_encoding_ctx #include "cipher-proto.h" +/* The internal encryption modes. */ +enum gcry_cipher_internal_modes + { + GCRY_CIPHER_MODE_INTERNAL = 0x10000, + GCRY_CIPHER_MODE_CMAC = 0x10000 + 1 /* Cipher-based MAC. */ + }; + + +/*-- cipher.c --*/ +gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, + int algo, int mode, + unsigned int flags); + +/*-- cipher-cmac.c --*/ +gcry_err_code_t _gcry_cipher_cmac_authenticate +/* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen); +gcry_err_code_t _gcry_cipher_cmac_get_tag +/* */ (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen); +gcry_err_code_t _gcry_cipher_cmac_check_tag +/* */ (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen); +gcry_err_code_t _gcry_cipher_cmac_set_subkeys +/* */ (gcry_cipher_hd_t c); /*-- rmd160.c --*/ void _gcry_rmd160_hash_buffer (void *outbuf, diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index b0bece1..dd2318c 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1309,7 +1309,19 @@ enum gcry_mac_algos GCRY_MAC_HMAC_WHIRLPOOL = 10, GCRY_MAC_HMAC_GOSTR3411_94 = 11, GCRY_MAC_HMAC_STRIBOG256 = 12, - GCRY_MAC_HMAC_STRIBOG512 = 13 + GCRY_MAC_HMAC_STRIBOG512 = 13, + + GCRY_MAC_CMAC_AES = 100, + GCRY_MAC_CMAC_3DES = 101, + GCRY_MAC_CMAC_CAMELLIA = 102, + GCRY_MAC_CMAC_CAST5 = 103, + GCRY_MAC_CMAC_BLOWFISH = 104, + GCRY_MAC_CMAC_TWOFISH = 105, + GCRY_MAC_CMAC_SERPENT = 106, + GCRY_MAC_CMAC_SEED = 107, + GCRY_MAC_CMAC_RFC2268 = 108, + GCRY_MAC_CMAC_IDEA = 109, + GCRY_MAC_CMAC_GOST28147 = 110 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index 6ca1803..d04a78e 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4398,6 +4398,147 @@ check_mac (void) "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + /* CMAC AES and DES test vectors from + http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica\ + tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "", + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "", + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + /* CMAC Camellia test vectors from + http://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */ + { GCRY_MAC_CMAC_CAMELLIA, + "", + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\xba\x92\x57\x82\xaa\xa1\xf5\xd9\xa0\x0f\x89\x64\x80\x94\xfc\x71" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\x6d\x96\x28\x54\xa3\xb9\xfd\xa5\x6d\x7d\x45\xa9\x5e\xe1\x79\x93" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\x5c\x18\xd1\x19\xcc\xd6\x76\x61\x44\xac\x18\x66\x13\x1d\x9f\x22" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" }, { 0 }, }; int i; From jussi.kivilinna at iki.fi Sat Nov 16 13:15:51 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 16 Nov 2013 14:15:51 +0200 Subject: [PATCH 2/3] Add new MAC API, initially with HMAC In-Reply-To: <20131116121546.8367.83081.stgit@localhost6.localdomain6> References: <20131116121546.8367.83081.stgit@localhost6.localdomain6> Message-ID: <20131116121551.8367.70686.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'mac.c', 'mac-internal.h' and 'mac-hmac.c'. * cipher/bufhelp.h (buf_eq_const): New. * cipher/cipher-ccm.c (_gcry_cipher_ccm_tag): Use 'buf_eq_const' for constant-time compare. * cipher/mac-hmac.c: New. * cipher/mac-internal.h: New. * cipher/mac.c: New. * src/gcrypt-int.h [GPG_ERROR_VERSION_NUMBER < 1.13] (GPG_ERR_MAC_ALGO): New. * src/gcrypt.h.in (gcry_mac_handle, gcry_mac_hd_t, gcry_mac_algos) (gcry_mac_flags, gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name) (gcry_mac_reset, gcry_mac_test_algo): New. * src/libgcrypt.def (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/libgcrypt.vers (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/visibility.c (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/visibility.h (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * tests/basic.c (check_one_mac, check_mac): New. (main): Call 'check_mac'. * tests/bench-slope.c (bench_print_header, bench_print_footer): Allow variable algorithm name width. (_cipher_bench, hash_bench): Update to above change. (bench_hash_do_bench): Add 'gcry_md_reset'. (bench_mac_mode, bench_mac_init, bench_mac_free, bench_mac_do_bench) (mac_ops, mac_modes, mac_bench_one, _mac_bench, mac_bench): New. (main): Add 'mac' benchmark options. * tests/benchmark.c (mac_repetitions, mac_bench): New. (main): Add 'mac' benchmark options. -- TODO: - Documentation. - GPG_ERR_MAC_ALGO to libgpg-error. Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 2 cipher/bufhelp.h | 17 ++ cipher/cipher-ccm.c | 13 - cipher/mac-hmac.c | 278 ++++++++++++++++++++++++++++++ cipher/mac-internal.h | 140 +++++++++++++++ cipher/mac.c | 449 +++++++++++++++++++++++++++++++++++++++++++++++++ src/gcrypt-int.h | 4 src/gcrypt.h.in | 97 +++++++++++ src/libgcrypt.def | 14 ++ src/libgcrypt.vers | 5 + src/visibility.c | 106 ++++++++++++ src/visibility.h | 42 +++++ tests/basic.c | 394 +++++++++++++++++++++++++++++++++++++++++++ tests/bench-slope.c | 180 +++++++++++++++++++- tests/benchmark.c | 142 +++++++++++++++ 15 files changed, 1863 insertions(+), 20 deletions(-) create mode 100644 cipher/mac-hmac.c create mode 100644 cipher/mac-internal.h create mode 100644 cipher/mac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 95d484e..1d54b07 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -44,6 +44,8 @@ cipher-ccm.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ +mac.c mac-internal.h \ +mac-hmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index dc39b46..45a7209 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -220,6 +220,23 @@ buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) } +/* Constant-time compare of two buffers. Returns 1 if buffers are equal, + and 0 if buffers differ. */ +static inline int +buf_eq_const(const void *_a, const void *_b, size_t len) +{ + const byte *a = _a; + const byte *b = _b; + size_t diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < len; i++) + diff -= !!(a[i] - b[i]); + + return !diff; +} + + #ifndef BUFHELP_FAST_UNALIGNED_ACCESS /* Functions for loading and storing unaligned u32 values of different diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index 2a1fc74..1eba7f0 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -289,13 +289,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, } else { - int diff, i; - - /* Constant-time compare. */ - for (i = 0, diff = 0; i < outbuflen; i++) - diff -= !!(outbuf[i] - c->u_iv.iv[i]); - - return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } } @@ -304,7 +299,7 @@ gcry_err_code_t _gcry_cipher_ccm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen) { - return _gcry_cipher_ccm_tag (c, outtag, taglen, 0); + return _gcry_cipher_ccm_tag (c, outtag, taglen, 0); } @@ -312,7 +307,7 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen) { - return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1); + return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1); } diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c new file mode 100644 index 0000000..591a837 --- /dev/null +++ b/cipher/mac-hmac.c @@ -0,0 +1,278 @@ +/* mac-hmac.c - HMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "./mac-internal.h" +#include "bufhelp.h" + + +static int map_mac_algo_to_md (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_MD_NONE; + case GCRY_MAC_HMAC_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_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_STRIBOG256: + return GCRY_MD_STRIBOG256; + case GCRY_MAC_HMAC_STRIBOG512: + return GCRY_MD_STRIBOG512; + } +} + + +static gcry_err_code_t hmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_md_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + unsigned int flags; + int md_algo; + + md_algo = map_mac_algo_to_md(h->spec->algo); + + flags = GCRY_MD_FLAG_HMAC; + flags |= (secure ? GCRY_MD_FLAG_SECURE : 0); + + err = gcry_md_open (&hd, md_algo, flags); + if (err) + return err; + + h->u.hmac.md_algo = md_algo; + h->u.hmac.md_ctx = hd; + return 0; +} + + +static void hmac_close (gcry_mac_hd_t h) +{ + gcry_md_close (h->u.hmac.md_ctx); + h->u.hmac.md_ctx = NULL; +} + + +static gcry_err_code_t +hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + return gcry_md_setkey (h->u.hmac.md_ctx, key, keylen); +} + + +static gcry_err_code_t +hmac_reset (gcry_mac_hd_t h) +{ + gcry_md_reset (h->u.hmac.md_ctx); + return 0; +} + + +static gcry_err_code_t +hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + gcry_md_write (h->u.hmac.md_ctx, buf, buflen); + return 0; +} + + +static gcry_err_code_t +hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t outlen) +{ + unsigned int dlen; + const unsigned char *digest; + + dlen = gcry_md_get_algo_dlen (h->u.hmac.md_algo); + digest = gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); + + if (outlen <= dlen) + buf_cpy (outbuf, digest, outlen); + else + { + buf_cpy (outbuf, digest, dlen); + memset (outbuf + dlen, 0, 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_MAC_HMAC_SHA384: + case GCRY_MAC_HMAC_SHA512: + return 128; + case GCRY_MAC_HMAC_GOSTR3411_94: + return 32; + default: + return 64; + } +} + + +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 + }; + + +#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 + }; +#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 + }; +#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 diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h new file mode 100644 index 0000000..3da40f7 --- /dev/null +++ b/cipher/mac-internal.h @@ -0,0 +1,140 @@ +/* mac-internal.h - Internal defs for mac.c + * Copyright ? 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 . + */ + +/* The data object used to hold a handle to an encryption object. */ +struct gcry_mac_handle; +typedef struct gcry_mac_handle *gcry_mac_hd_t; + + +/* + * + * Message authentication code related definitions. + * + */ + + +/* Magic values for the context structure. */ +#define CTX_MAGIC_NORMAL 0x59d9b8af +#define CTX_MAGIC_SECURE 0x12c27cd0 + + +/* MAC module functions. */ +typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h); +typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h); +typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h, + const unsigned char *key, + size_t keylen); +typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h, + const unsigned char *iv, + size_t ivlen); +typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h); +typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h, + const unsigned char *inbuf, + size_t inlen); +typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h, + unsigned char *outbuf, + size_t outlen); +typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h, + const unsigned char *inbuf, + size_t inlen); +typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo); +typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo); + + +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_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; + } 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; +#endif +#ifdef USE_GOST_R_3411_94 +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; +#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 diff --git a/cipher/mac.c b/cipher/mac.c new file mode 100644 index 0000000..2a4bce8 --- /dev/null +++ b/cipher/mac.c @@ -0,0 +1,449 @@ +/* mac.c - message authentication code dispatcher + * Copyright ? 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 *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, +#endif +#ifdef USE_GOST_R_3411_94 + &_gcry_mac_type_spec_hmac_gost3411_94, +#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 + NULL, + }; + + + + +/* 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; + int idx; + + for (idx = 0; (spec = mac_list[idx]); idx++) + if (algo == spec->algo) + return spec; + return NULL; +} + + +/* 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 = gcry_calloc_secure (1, sizeof(*h)); + else + h = gcry_calloc (1, sizeof(*h)); + + if (!h) + return gpg_err_code_from_syserror (); + + h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; + h->spec = spec; + h->algo = algo; + h->gcry_ctx = ctx; + + err = h->spec->ops->open (h); + if (err) + gcry_free (h); + else + *hd = h; + + return err; +} + + +static gcry_error_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->reset) + hd->spec->ops->close(hd); + + wipememory (hd, sizeof(*hd)); + + gcry_free (hd); +} + + +static gcry_error_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_error_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_error_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_error_t +mac_read (gcry_mac_hd_t hd, void *outbuf, size_t outlen) +{ + if (!outbuf || outlen == 0 || !hd->spec->ops->read) + return GPG_ERR_INV_ARG; + + return hd->spec->ops->read(hd, outbuf, outlen); +} + + +static gcry_error_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. */ +gcry_error_t +gcry_mac_open (gcry_mac_hd_t *h, int algo, unsigned int flags, gcry_ctx_t ctx) +{ + gcry_err_code_t err; + gcry_mac_hd_t hd = NULL; + + if ((flags & ~GCRY_MAC_FLAG_SECURE)) + err = GPG_ERR_INV_ARG; + else + err = mac_open(&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx); + + *h = err ? NULL : hd; + return gpg_error (err); +} + + +void +gcry_mac_close (gcry_mac_hd_t hd) +{ + mac_close(hd); +} + + +gcry_error_t +gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) +{ + gcry_error_t err; + + err = mac_setkey(hd, key, keylen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) +{ + gcry_error_t err; + + err = mac_setiv(hd, iv, ivlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t outlen) +{ + gcry_error_t err; + + err = mac_read(hd, outbuf, outlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) +{ + gcry_err_code_t err; + + err = mac_write(hd, inbuf, inlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + gcry_err_code_t err; + + err = mac_verify(hd, buf, buflen); + + return gpg_error (err); +} + + +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_error_t +gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t rc = GPG_ERR_NO_ERROR; + + /* Currently not used. */ + (void)hd; + (void)buffer; + (void)buflen; + + switch (cmd) + { + case GCRYCTL_RESET: + rc = mac_reset (hd); + break; + default: + rc = GPG_ERR_INV_OP; + } + return gcry_error (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_error_t +gcry_mac_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + unsigned int ui; + + switch (what) + { + case GCRYCTL_GET_KEYLEN: + if (buffer || (!nbytes)) + err = 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. */ + err = GPG_ERR_MAC_ALGO; + } + break; + case GCRYCTL_TEST_ALGO: + if (buffer || nbytes) + err = GPG_ERR_INV_ARG; + else + err = check_mac_algo (algo); + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index 295328b..974fef9 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -37,4 +37,8 @@ # define GPG_ERR_BROKEN_SECKEY 196 #endif +#if GPG_ERROR_VERSION_NUMBER < 0x010d00 /* 1.13 */ +# define GPG_ERR_MAC_ALGO 197 +#endif + #endif /*GCRY_GCRYPT_INT_H*/ diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index fffc15c..b0bece1 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1279,6 +1279,103 @@ void gcry_md_debug (gcry_md_hd_t hd, const char *suffix); #define gcry_md_get_asnoid(a,b,n) \ gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n)) + + +/********************************************** + * * + * Message Authentication Code Functions * + * * + **********************************************/ + +/* The data object used to hold a handle to an encryption object. */ +struct gcry_mac_handle; +typedef struct gcry_mac_handle *gcry_mac_hd_t; + +/* Algorithm IDs for the hash functions we know about. Not all of them + are implemented. */ +enum gcry_mac_algos + { + GCRY_MAC_NONE = 0, + + GCRY_MAC_HMAC_SHA256 = 1, + GCRY_MAC_HMAC_SHA224 = 2, + GCRY_MAC_HMAC_SHA512 = 3, + GCRY_MAC_HMAC_SHA384 = 4, + GCRY_MAC_HMAC_SHA1 = 5, + GCRY_MAC_HMAC_MD5 = 6, + GCRY_MAC_HMAC_MD4 = 7, + GCRY_MAC_HMAC_RMD160 = 8, + GCRY_MAC_HMAC_TIGER1 = 9, /* The fixed TIGER variant */ + GCRY_MAC_HMAC_WHIRLPOOL = 10, + GCRY_MAC_HMAC_GOSTR3411_94 = 11, + GCRY_MAC_HMAC_STRIBOG256 = 12, + GCRY_MAC_HMAC_STRIBOG512 = 13 + }; + +/* Flags used with the open function. */ +enum gcry_mac_flags + { + GCRY_MAC_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */ + }; + +/* Create a MAC handle for algorithm ALGO. FLAGS may be given as an bitwise OR + of the gcry_mac_flags values. CTX maybe NULL or gcry_ctx_t object to be + associated with HANDLE. */ +gcry_error_t gcry_mac_open (gcry_mac_hd_t *handle, int algo, + unsigned int flags, gcry_ctx_t ctx); + +/* Close the MAC handle H and release all resource. */ +void gcry_mac_close (gcry_mac_hd_t h); + +/* Perform various operations on the MAC object H. */ +gcry_error_t gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer, + size_t buflen); + +/* Retrieve various information about the MAC algorithm ALGO. */ +gcry_error_t gcry_mac_algo_info (int algo, int what, void *buffer, + size_t *nbytes); + +/* Set KEY of length KEYLEN bytes for the MAC handle HD. */ +gcry_error_t gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, + size_t keylen); + +/* Set initialization vector IV of length IVLEN for the MAC handle HD. */ +gcry_error_t gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, + size_t ivlen); + +/* Pass LENGTH bytes of data in BUFFER to the MAC object HD so that + it can update the MAC values. */ +gcry_error_t gcry_mac_write (gcry_mac_hd_t hd, const void *buffer, + size_t length); + +/* Read out the final authentication code from the MAC object HD to BUFFER. */ +gcry_error_t gcry_mac_read (gcry_mac_hd_t hd, void *buffer, size_t buflen); + +/* Verify the final authentication code from the MAC object HD with BUFFER. */ +gcry_error_t gcry_mac_verify (gcry_mac_hd_t hd, const void *buffer, + size_t buflen); + +/* Retrieve the length in bytes of the MAC yielded by algorithm ALGO. */ +unsigned int gcry_mac_get_algo_maclen (int algo); + +/* Retrieve the default key length in bytes used with algorithm A. */ +unsigned int gcry_mac_get_algo_keylen (int algo); + +/* Map the MAC algorithm whose ID is contained in ALGORITHM to a + string representation of the algorithm name. For unknown algorithm + IDs this function returns "?". */ +const char *gcry_mac_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE; + +/* Map the algorithm name NAME to an MAC algorithm ID. Return 0 if + the algorithm name is not known. */ +int gcry_mac_map_name (const char *name) _GCRY_GCC_ATTR_PURE; + +/* Reset the handle to the state after open/setkey. */ +#define gcry_mac_reset(h) gcry_mac_ctl ((h), GCRYCTL_RESET, NULL, 0) + +/* Return 0 if the algorithm A is available for use. */ +#define gcry_mac_test_algo(a) \ + gcry_mac_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) /****************************** diff --git a/src/libgcrypt.def b/src/libgcrypt.def index e2aba2b..a90efce 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -261,5 +261,19 @@ EXPORTS gcry_mpi_set_opaque_copy @229 + gcry_mac_algo_info @230 + gcry_mac_algo_name @231 + gcry_mac_map_name @232 + gcry_mac_get_algo_maclen @233 + gcry_mac_get_algo_keylen @234 + gcry_mac_open @235 + gcry_mac_close @236 + gcry_mac_setkey @237 + gcry_mac_setiv @238 + gcry_mac_write @239 + gcry_mac_read @240 + gcry_mac_verify @241 + gcry_mac_ctl @242 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index c3a09b8..5118c81 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -53,6 +53,11 @@ GCRYPT_1.6 { gcry_cipher_setkey; gcry_cipher_setiv; gcry_cipher_setctr; gcry_cipher_authenticate; gcry_cipher_gettag; gcry_cipher_checktag; + gcry_mac_algo_info; gcry_mac_algo_name; gcry_mac_map_name; + gcry_mac_get_algo_maclen; gcry_mac_get_algo_keylen; + gcry_mac_open; gcry_mac_close; gcry_mac_setkey; gcry_mac_setiv; + gcry_mac_write; gcry_mac_read; gcry_mac_verify; gcry_mac_ctl; + gcry_pk_algo_info; gcry_pk_algo_name; gcry_pk_ctl; gcry_pk_decrypt; gcry_pk_encrypt; gcry_pk_genkey; gcry_pk_get_keygrip; gcry_pk_get_nbits; diff --git a/src/visibility.c b/src/visibility.c index 852bdf9..88152e8 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -829,6 +829,112 @@ gcry_cipher_get_algo_blklen (int algo) } gcry_error_t +gcry_mac_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_algo_info (algo, what, buffer, nbytes); +} + +const char * +gcry_mac_algo_name (int algorithm) +{ + return _gcry_mac_algo_name (algorithm); +} + +int +gcry_mac_map_name (const char *string) +{ + return _gcry_mac_map_name (string); +} + +unsigned int +gcry_mac_get_algo_maclen (int algo) +{ + return _gcry_mac_get_algo_maclen (algo); +} + +unsigned int +gcry_mac_get_algo_keylen (int algo) +{ + return _gcry_mac_get_algo_keylen (algo); +} + +gcry_error_t +gcry_mac_open (gcry_mac_hd_t *handle, int algo, unsigned int flags, + gcry_ctx_t ctx) +{ + if (!fips_is_operational ()) + { + *handle = NULL; + return gpg_error (fips_not_operational ()); + } + + return _gcry_mac_open (handle, algo, flags, ctx); +} + +void +gcry_mac_close (gcry_mac_hd_t hd) +{ + _gcry_mac_close (hd); +} + +gcry_error_t +gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_setkey (hd, key, keylen); +} + +gcry_error_t +gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_setiv (hd, iv, ivlen); +} + +gcry_error_t +gcry_mac_write (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_write (hd, buf, buflen); +} + +gcry_error_t +gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t outlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_read (hd, outbuf, outlen); +} + +gcry_error_t +gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_verify (hd, buf, buflen); +} + +gcry_error_t +gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_ctl (h, cmd, buffer, buflen); +} + +gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t pkey) { if (!fips_is_operational ()) diff --git a/src/visibility.h b/src/visibility.h index 438db5b..318ff44 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -94,6 +94,20 @@ #define gcry_cipher_mode_from_oid _gcry_cipher_mode_from_oid #define gcry_cipher_open _gcry_cipher_open +#define gcry_mac_algo_info _gcry_mac_algo_info +#define gcry_mac_algo_name _gcry_mac_algo_name +#define gcry_mac_map_name _gcry_mac_map_name +#define gcry_mac_get_algo_maclen _gcry_mac_get_algo_maclen +#define gcry_mac_get_algo_keylen _gcry_mac_get_algo_keylen +#define gcry_mac_open _gcry_mac_open +#define gcry_mac_close _gcry_mac_close +#define gcry_mac_setkey _gcry_mac_setkey +#define gcry_mac_setiv _gcry_mac_setiv +#define gcry_mac_write _gcry_mac_write +#define gcry_mac_read _gcry_mac_read +#define gcry_mac_verify _gcry_mac_verify +#define gcry_mac_ctl _gcry_mac_ctl + #define gcry_pk_algo_info _gcry_pk_algo_info #define gcry_pk_algo_name _gcry_pk_algo_name #define gcry_pk_ctl _gcry_pk_ctl @@ -313,6 +327,20 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo, #undef gcry_cipher_mode_from_oid #undef gcry_cipher_open +#undef gcry_mac_algo_info +#undef gcry_mac_algo_name +#undef gcry_mac_map_name +#undef gcry_mac_get_algo_maclen +#undef gcry_mac_get_algo_keylen +#undef gcry_mac_open +#undef gcry_mac_close +#undef gcry_mac_setkey +#undef gcry_mac_setiv +#undef gcry_mac_write +#undef gcry_mac_read +#undef gcry_mac_verify +#undef gcry_mac_ctl + #undef gcry_pk_algo_info #undef gcry_pk_algo_name #undef gcry_pk_ctl @@ -493,6 +521,20 @@ MARK_VISIBLE (gcry_cipher_map_name) MARK_VISIBLE (gcry_cipher_mode_from_oid) MARK_VISIBLE (gcry_cipher_open) +MARK_VISIBLE (gcry_mac_algo_info) +MARK_VISIBLE (gcry_mac_algo_name) +MARK_VISIBLE (gcry_mac_map_name) +MARK_VISIBLE (gcry_mac_get_algo_maclen) +MARK_VISIBLE (gcry_mac_get_algo_keylen) +MARK_VISIBLE (gcry_mac_open) +MARK_VISIBLE (gcry_mac_close) +MARK_VISIBLE (gcry_mac_setkey) +MARK_VISIBLE (gcry_mac_setiv) +MARK_VISIBLE (gcry_mac_write) +MARK_VISIBLE (gcry_mac_read) +MARK_VISIBLE (gcry_mac_verify) +MARK_VISIBLE (gcry_mac_ctl) + MARK_VISIBLE (gcry_pk_algo_info) MARK_VISIBLE (gcry_pk_algo_name) MARK_VISIBLE (gcry_pk_ctl) diff --git a/tests/basic.c b/tests/basic.c index 99d63ae..6ca1803 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4038,7 +4038,398 @@ check_hmac (void) if (verbose) fprintf (stderr, "Completed hashed MAC checks.\n"); - } +} + + +static void +check_one_mac (int algo, const char *data, int datalen, + const char *key, int keylen, const char *expect) +{ + gcry_mac_hd_t hd; + unsigned char *p; + unsigned int maclen; + int i; + gcry_error_t err = 0; + + err = gcry_mac_open (&hd, algo, 0, NULL); + if (err) + { + fail ("algo %d, gcry_mac_open failed: %s\n", algo, gpg_strerror (err)); + return; + } + + maclen = gcry_mac_get_algo_maclen (algo); + if (maclen < 1 || maclen > 500) + { + fail ("algo %d, gcry_mac_get_algo_maclen failed: %d\n", algo, maclen); + return; + } + + p = malloc(maclen); + if (!p) + { + fail ("algo %d, could not malloc %d bytes\n", algo, maclen); + return; + } + + err = gcry_mac_setkey (hd, key, keylen); + if (err) + fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + err = gcry_mac_write (hd, data, datalen); + if (err) + fail("algo %d, mac gcry_mac_write failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + err = gcry_mac_verify (hd, expect, maclen); + if (err) + fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + err = gcry_mac_read (hd, p, maclen); + if (err) + fail("algo %d, mac gcry_mac_read failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + if (memcmp (p, expect, maclen)) + { + printf ("computed: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", p[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("algo %d, digest mismatch\n", algo); + } + if (err) + goto out; + +out: + free (p); + gcry_mac_close (hd); +} + +static void +check_mac (void) +{ + static const struct algos + { + int algo; + const char *data; + const char *key; + const char *expect; + } algos[] = + { + { GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe", + "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" }, + { GCRY_MAC_HMAC_MD5, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" }, + { GCRY_MAC_HMAC_MD5, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" }, + { GCRY_MAC_HMAC_MD5, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" }, + { GCRY_MAC_HMAC_MD5, "Test With Truncation", + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" }, + { GCRY_MAC_HMAC_MD5, "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", + "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" }, + { GCRY_MAC_HMAC_MD5, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa", + "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", }, + { GCRY_MAC_HMAC_SHA256, "what do ya want for nothing?", "Jefe", + "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a" + "\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" }, + { GCRY_MAC_HMAC_SHA256, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88" + "\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" }, + { GCRY_MAC_HMAC_SHA256, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7" + "\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" }, + { GCRY_MAC_HMAC_SHA256, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08" + "\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" }, + { GCRY_MAC_HMAC_SHA256, + "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", + "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f" + "\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" }, + { GCRY_MAC_HMAC_SHA256, + "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", + "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44" + "\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" }, + { GCRY_MAC_HMAC_SHA224, "what do ya want for nothing?", "Jefe", + "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" }, + { GCRY_MAC_HMAC_SHA224, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47" + "\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" }, + { GCRY_MAC_HMAC_SHA224, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64" + "\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" }, + { GCRY_MAC_HMAC_SHA224, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62" + "\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" }, + { GCRY_MAC_HMAC_SHA224, + "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", + "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" + "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" }, + { GCRY_MAC_HMAC_SHA224, + "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", + "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" + "\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" }, + { GCRY_MAC_HMAC_SHA384, "what do ya want for nothing?", "Jefe", + "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" }, + { GCRY_MAC_HMAC_SHA384, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15" + "\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea" + "\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" }, + { GCRY_MAC_HMAC_SHA384, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f" + "\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b" + "\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" }, + { GCRY_MAC_HMAC_SHA384, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7" + "\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e" + "\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" }, + { GCRY_MAC_HMAC_SHA384, + "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", + "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" + "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" + "\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" }, + { GCRY_MAC_HMAC_SHA384, + "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", + "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" + "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5" + "\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" }, + { GCRY_MAC_HMAC_SHA512, "what do ya want for nothing?", "Jefe", + "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" }, + { GCRY_MAC_HMAC_SHA512, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0" + "\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" + "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" + "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" }, + { GCRY_MAC_HMAC_SHA512, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9" + "\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39" + "\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07" + "\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" }, + { GCRY_MAC_HMAC_SHA512, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7" + "\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb" + "\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63" + "\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" }, + { GCRY_MAC_HMAC_SHA512, + "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", + "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4" + "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52" + "\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" + "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" }, + { GCRY_MAC_HMAC_SHA512, + "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", + "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd" + "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" + "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" + "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + { 0 }, + }; + int i; + + if (verbose) + fprintf (stderr, "Starting MAC checks.\n"); + + for (i = 0; algos[i].algo; i++) + { + if ((gcry_mac_test_algo (algos[i].algo) + || algos[i].algo == GCRY_MAC_HMAC_MD5) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i].algo); + continue; + } + if (verbose) + fprintf (stderr, + " checking %s [%i] for %zi byte key and %zi byte data\n", + gcry_mac_algo_name (algos[i].algo), + algos[i].algo, + strlen(algos[i].key), strlen(algos[i].data)); + + check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), + algos[i].key, strlen(algos[i].key), + algos[i].expect); + } + + if (verbose) + fprintf (stderr, "Completed MAC checks.\n"); +} /* Check that the signature SIG matches the hash HASH. PKEY is the public key used for the verification. BADHASH is a hash value which @@ -4996,6 +5387,7 @@ main (int argc, char **argv) check_bulk_cipher_modes (); check_digests (); check_hmac (); + check_mac (); check_pubkey (); } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 79b868c..877597e 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -493,17 +493,17 @@ bench_print_result (double nsecs_per_byte) } static void -bench_print_header (const char *algo_name) +bench_print_header (int algo_width, const char *algo_name) { - printf (" %-14s | ", algo_name); + printf (" %-*s | ", algo_width, algo_name); printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec", "cycles/byte"); } static void -bench_print_footer (void) +bench_print_footer (int algo_width) { - printf (" %-14s =\n", ""); + printf (" %-*s =\n", algo_width, ""); } @@ -854,12 +854,12 @@ _cipher_bench (int algo) algoname = gcry_cipher_algo_name (algo); - bench_print_header (algoname); + bench_print_header (14, algoname); for (i = 0; cipher_modes[i].mode; i++) cipher_bench_one (algo, &cipher_modes[i]); - bench_print_footer (); + bench_print_footer (14); } @@ -937,6 +937,7 @@ bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_md_hd_t hd = obj->priv; + gcry_md_reset (hd); gcry_md_write (hd, buf, buflen); gcry_md_final (hd); } @@ -993,7 +994,7 @@ hash_bench (char **argv, int argc) printf ("Hash:\n"); - bench_print_header (""); + bench_print_header (14, ""); if (argv && argc) { @@ -1011,7 +1012,159 @@ hash_bench (char **argv, int argc) _hash_bench (i); } - bench_print_footer (); + bench_print_footer (14); +} + + +/************************************************************ MAC benchmarks. */ + +struct bench_mac_mode +{ + const char *name; + struct bench_ops *ops; + + int algo; +}; + + +static int +bench_mac_init (struct bench_obj *obj) +{ + struct bench_mac_mode *mode = obj->priv; + gcry_mac_hd_t hd; + int err; + unsigned int keylen; + void *key; + + obj->min_bufsize = BUF_START_SIZE; + obj->max_bufsize = BUF_END_SIZE; + obj->step_size = BUF_STEP_SIZE; + obj->num_measure_repetitions = NUM_MEASUREMENT_REPETITIONS; + + keylen = gcry_mac_get_algo_keylen (mode->algo); + if (keylen == 0) + keylen = 32; + key = malloc (keylen); + if (!key) + { + fprintf (stderr, PGM ": couldn't allocate %d bytes\n", keylen); + exit (1); + } + memset(key, 42, keylen); + + err = gcry_mac_open (&hd, mode->algo, 0, NULL); + if (err) + { + fprintf (stderr, PGM ": error opening mac `%s'\n", + gcry_mac_algo_name (mode->algo)); + free (key); + exit (1); + } + + err = gcry_mac_setkey (hd, key, keylen); + free (key); + if (err) + { + fprintf (stderr, PGM ": error setting key for mac `%s'\n", + gcry_mac_algo_name (mode->algo)); + exit (1); + } + + obj->priv = hd; + + return 0; +} + +static void +bench_mac_free (struct bench_obj *obj) +{ + gcry_mac_hd_t hd = obj->priv; + + gcry_mac_close (hd); +} + +static void +bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_mac_hd_t hd = obj->priv; + char b; + + gcry_mac_reset (hd); + gcry_mac_write (hd, buf, buflen); + gcry_mac_read (hd, &b, sizeof(b)); +} + +static struct bench_ops mac_ops = { + &bench_mac_init, + &bench_mac_free, + &bench_mac_do_bench +}; + + +static struct bench_mac_mode mac_modes[] = { + {"", &mac_ops}, + {0}, +}; + + +static void +mac_bench_one (int algo, struct bench_mac_mode *pmode) +{ + struct bench_mac_mode mode = *pmode; + struct bench_obj obj = { 0 }; + double result; + + mode.algo = algo; + + if (mode.name[0] == '\0') + printf (" %-18s | ", gcry_mac_algo_name (algo)); + else + printf (" %18s | ", mode.name); + fflush (stdout); + + obj.ops = mode.ops; + obj.priv = &mode; + + result = do_slope_benchmark (&obj); + + bench_print_result (result); +} + +static void +_mac_bench (int algo) +{ + int i; + + for (i = 0; mac_modes[i].name; i++) + mac_bench_one (algo, &mac_modes[i]); +} + +void +mac_bench (char **argv, int argc) +{ + int i, algo; + + printf ("MAC:\n"); + + bench_print_header (18, ""); + + if (argv && argc) + { + for (i = 0; i < argc; i++) + { + algo = gcry_mac_map_name (argv[i]); + if (algo) + _mac_bench (algo); + } + } + else + { + for (i = 1; i < 400; i++) + if (!gcry_mac_test_algo (i)) + _mac_bench (i); + } + + bench_print_footer (18); } @@ -1021,7 +1174,7 @@ void print_help (void) { static const char *help_lines[] = { - "usage: bench-slope [options] [hash|cipher [algonames]]", + "usage: bench-slope [options] [hash|mac|cipher [algonames]]", "", " options:", " --cpu-mhz Set CPU speed for calculating cycles per bytes", @@ -1147,6 +1300,7 @@ main (int argc, char **argv) { warm_up_cpu (); hash_bench (NULL, 0); + mac_bench (NULL, 0); cipher_bench (NULL, 0); } else if (!strcmp (*argv, "hash")) @@ -1157,6 +1311,14 @@ main (int argc, char **argv) warm_up_cpu (); hash_bench ((argc == 0) ? NULL : argv, argc); } + else if (!strcmp (*argv, "mac")) + { + argc--; + argv++; + + warm_up_cpu (); + mac_bench ((argc == 0) ? NULL : argv, argc); + } else if (!strcmp (*argv, "cipher")) { argc--; diff --git a/tests/benchmark.c b/tests/benchmark.c index 93874fa..e2c2ce0 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -47,6 +47,9 @@ static int cipher_repetitions; /* Number of hash repetitions. */ static int hash_repetitions; +/* Number of hash repetitions. */ +static int mac_repetitions; + /* Alignment of the buffers. */ static int buffer_alignment; @@ -436,6 +439,122 @@ md_bench ( const char *algoname ) } + +static void +mac_bench ( const char *algoname ) +{ + int algo; + gcry_mac_hd_t hd; + int step, pos, j, i, repcount; + char buf_base[1000+15]; + size_t bufsize = 1000; + char *buf; + char mac[3][512]; + char key[512]; + unsigned int maclen, keylen; + gcry_error_t err = GPG_ERR_NO_ERROR; + + if (!algoname) + { + for (i=1; i < 400; i++) + if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) + ; /* Don't use MD5 in fips mode. */ + else if ( !gcry_mac_test_algo (i) ) + mac_bench (gcry_mac_algo_name (i)); + return; + } + + buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); + + algo = gcry_mac_map_name (algoname); + if (!algo) + { + fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); + exit (1); + } + + maclen = gcry_mac_get_algo_maclen (algo); + if (maclen > sizeof(mac)) + maclen = sizeof(mac); + + keylen = gcry_mac_get_algo_keylen (algo); + if (keylen == 0) + keylen = 32; + if (keylen > sizeof(key)) + keylen = sizeof(key); + for (i=0; i < keylen; i++) + key[i] = (keylen - i) ^ 0x54; + + err = gcry_mac_open (&hd, algo, 0, NULL); + if (err) + { + fprintf (stderr, PGM ": error opening mac algorithm `%s': %s\n", algoname, + gpg_strerror (err)); + exit (1); + } + + err = gcry_mac_setkey (hd, key, keylen); + if (err) + { + fprintf (stderr, PGM ": error setting key for mac algorithm `%s': %s\n", + algoname, gpg_strerror (err)); + exit (1); + } + + for (i=0; i < bufsize; i++) + buf[i] = i; + + printf ("%-20s", gcry_mac_algo_name (algo)); + + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + gcry_mac_write (hd, buf, bufsize); + gcry_mac_read (hd, mac[0], maclen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_reset (hd); + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + for (step=bufsize/10, pos=0, j=0; j < 10; j++, pos+=step) + gcry_mac_write (hd, &buf[pos], step); + gcry_mac_read (hd, mac[1], maclen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_reset (hd); + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + for (step=bufsize/100, pos=0, j=0; j < 100; j++, pos+=step) + gcry_mac_write (hd, &buf[pos], step); + gcry_mac_read (hd, mac[2], maclen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_close (hd); + + for (i=1; i < 3; i++) + { + if (memcmp(mac[i-1], mac[i], maclen)) + { + fprintf (stderr, PGM ": mac mismatch with algorithm `%s'\n", + algoname); + exit(1); + } + } + + putchar ('\n'); + fflush (stdout); +} + + + static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen) { const int _L = 4; @@ -1186,7 +1305,7 @@ main( int argc, char **argv ) else if (!strcmp (*argv, "--help")) { fputs ("usage: benchmark " - "[md|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n", + "[md|mac|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n", stdout); exit (0); } @@ -1256,6 +1375,15 @@ main( int argc, char **argv ) argc--; argv++; } } + else if (!strcmp (*argv, "--mac-repetitions")) + { + argc--; argv++; + if (argc) + { + mac_repetitions = atoi(*argv); + argc--; argv++; + } + } else if (!strcmp (*argv, "--pk-count")) { argc--; argv++; @@ -1330,12 +1458,16 @@ main( int argc, char **argv ) cipher_repetitions = 1; if (hash_repetitions < 1) hash_repetitions = 1; + if (mac_repetitions < 1) + mac_repetitions = 1; if ( !argc ) { gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); md_bench (NULL); putchar ('\n'); + mac_bench (NULL); + putchar ('\n'); cipher_bench (NULL); putchar ('\n'); rsa_bench (pk_count, 1, no_blinding); @@ -1367,6 +1499,14 @@ main( int argc, char **argv ) for (argc--, argv++; argc; argc--, argv++) md_bench ( *argv ); } + else if ( !strcmp (*argv, "mac")) + { + if (argc == 1) + mac_bench (NULL); + else + for (argc--, argv++; argc; argc--, argv++) + mac_bench ( *argv ); + } else if ( !strcmp (*argv, "cipher")) { if (argc == 1) From cvs at cvs.gnupg.org Mon Nov 18 14:40:14 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Mon, 18 Nov 2013 14:40:14 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-384-gb787657 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via b787657a9d2c1d8e19f9fcb0b21e31cb062630cf (commit) from ef9f52cbb39e46918c96200b09c21e931eff174f (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit b787657a9d2c1d8e19f9fcb0b21e31cb062630cf Author: Jussi Kivilinna Date: Fri Nov 15 16:23:00 2013 +0200 cipher: use size_t for internal buffer lengths * cipher/arcfour.c (do_encrypt_stream, encrypt_stream): Use 'size_t' for buffer lengths. * cipher/blowfish.c (_gcry_blowfish_ctr_enc, _gcry_blowfish_cbc_dec) (_gcry_blowfish_cfb_dec): Ditto. * cipher/camellia-glue.c (_gcry_camellia_ctr_enc) (_gcry_camellia_cbc_dec, _gcry_blowfish_cfb_dec): Ditto. * cipher/cast5.c (_gcry_cast5_ctr_enc, _gcry_cast5_cbc_dec) (_gcry_cast5_cfb_dec): Ditto. * cipher/cipher-aeswrap.c (_gcry_cipher_aeswrap_encrypt) (_gcry_cipher_aeswrap_decrypt): Ditto. * cipher/cipher-cbc.c (_gcry_cipher_cbc_encrypt) (_gcry_cipher_cbc_decrypt): Ditto. * cipher/cipher-ccm.c (_gcry_cipher_ccm_encrypt) (_gcry_cipher_ccm_decrypt): Ditto. * cipher/cipher-cfb.c (_gcry_cipher_cfb_encrypt) (_gcry_cipher_cfb_decrypt): Ditto. * cipher/cipher-ctr.c (_gcry_cipher_ctr_encrypt): Ditto. * cipher/cipher-internal.h (gcry_cipher_handle->bulk) (_gcry_cipher_cbc_encrypt, _gcry_cipher_cbc_decrypt) (_gcry_cipher_cfb_encrypt, _gcry_cipher_cfb_decrypt) (_gcry_cipher_ofb_encrypt, _gcry_cipher_ctr_encrypt) (_gcry_cipher_aeswrap_encrypt, _gcry_cipher_aeswrap_decrypt) (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Ditto. * cipher/cipher-ofb.c (_gcry_cipher_cbc_encrypt): Ditto. * cipher/cipher-selftest.h (gcry_cipher_bulk_cbc_dec_t) (gcry_cipher_bulk_cfb_dec_t, gcry_cipher_bulk_ctr_enc_t): Ditto. * cipher/cipher.c (cipher_setkey, cipher_setiv, do_ecb_crypt) (do_ecb_encrypt, do_ecb_decrypt, cipher_encrypt) (cipher_decrypt): Ditto. * cipher/rijndael.c (_gcry_aes_ctr_enc, _gcry_aes_cbc_dec) (_gcry_aes_cfb_dec, _gcry_aes_cbc_enc, _gcry_aes_cfb_enc): Ditto. * cipher/salsa20.c (salsa20_setiv, salsa20_do_encrypt_stream) (salsa20_encrypt_stream, salsa20r12_encrypt_stream): Ditto. * cipher/serpent.c (_gcry_serpent_ctr_enc, _gcry_serpent_cbc_dec) (_gcry_serpent_cfb_dec): Ditto. * cipher/twofish.c (_gcry_twofish_ctr_enc, _gcry_twofish_cbc_dec) (_gcry_twofish_cfb_dec): Ditto. * src/cipher-proto.h (gcry_cipher_stencrypt_t) (gcry_cipher_stdecrypt_t, cipher_setiv_fuct_t): Ditto. * src/cipher.h (_gcry_aes_cfb_enc, _gcry_aes_cfb_dec) (_gcry_aes_cbc_enc, _gcry_aes_cbc_dec, _gcry_aes_ctr_enc) (_gcry_blowfish_cfb_dec, _gcry_blowfish_cbc_dec) (_gcry_blowfish_ctr_enc, _gcry_cast5_cfb_dec, _gcry_cast5_cbc_dec) (_gcry_cast5_ctr_enc, _gcry_camellia_cfb_dec, _gcry_camellia_cbc_dec) (_gcry_camellia_ctr_enc, _gcry_serpent_cfb_dec, _gcry_serpent_cbc_dec) (_gcry_serpent_ctr_enc, _gcry_twofish_cfb_dec, _gcry_twofish_cbc_dec) (_gcry_twofish_ctr_enc): Ditto. -- On 64-bit platforms, cipher module internally converts 64-bit size_t values to 32-bit unsigned integers. Signed-off-by: Jussi Kivilinna diff --git a/cipher/arcfour.c b/cipher/arcfour.c index 64f7204..d692c84 100644 --- a/cipher/arcfour.c +++ b/cipher/arcfour.c @@ -40,7 +40,7 @@ typedef struct { static void do_encrypt_stream( ARCFOUR_context *ctx, - byte *outbuf, const byte *inbuf, unsigned int length ) + byte *outbuf, const byte *inbuf, size_t length ) { #ifndef __i386__ register unsigned int i = ctx->idx_i; @@ -89,7 +89,7 @@ do_encrypt_stream( ARCFOUR_context *ctx, static void encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { ARCFOUR_context *ctx = (ARCFOUR_context *) context; do_encrypt_stream (ctx, outbuf, inbuf, length ); diff --git a/cipher/blowfish.c b/cipher/blowfish.c index 4665a1d..ae470d8 100644 --- a/cipher/blowfish.c +++ b/cipher/blowfish.c @@ -588,7 +588,7 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf) of size BLOWFISH_BLOCKSIZE. */ void _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -658,7 +658,7 @@ _gcry_blowfish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -719,7 +719,7 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_blowfish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { BLOWFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 24936ce..575bb04 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -290,7 +290,7 @@ camellia_decrypt(void *c, byte *outbuf, const byte *inbuf) void _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -382,7 +382,7 @@ _gcry_camellia_ctr_enc(void *context, unsigned char *ctr, void _gcry_camellia_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -465,7 +465,7 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv, void _gcry_camellia_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { CAMELLIA_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/cast5.c b/cipher/cast5.c index 09c9691..115e1e6 100644 --- a/cipher/cast5.c +++ b/cipher/cast5.c @@ -564,7 +564,7 @@ decrypt_block (void *context, byte *outbuf, const byte *inbuf) of size CAST5_BLOCKSIZE. */ void _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -635,7 +635,7 @@ _gcry_cast5_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -695,7 +695,7 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_cast5_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { CAST5_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/cipher-aeswrap.c b/cipher/cipher-aeswrap.c index 03b0ea7..50ac107 100644 --- a/cipher/cipher-aeswrap.c +++ b/cipher/cipher-aeswrap.c @@ -35,11 +35,11 @@ blocksize 128. */ gcry_err_code_t _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen ) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen ) { int j, x; - unsigned int n, i; + size_t n, i; unsigned char *r, *a, *b; unsigned char t[8]; unsigned int burn, nburn; @@ -117,11 +117,11 @@ _gcry_cipher_aeswrap_encrypt (gcry_cipher_hd_t c, blocksize 128. */ gcry_err_code_t _gcry_cipher_aeswrap_decrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { int j, x; - unsigned int n, i; + size_t n, i; unsigned char *r, *a, *b; unsigned char t[8]; unsigned int burn, nburn; diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c index 4ad2ebd..4b929da 100644 --- a/cipher/cipher-cbc.c +++ b/cipher/cipher-cbc.c @@ -34,15 +34,15 @@ gcry_err_code_t _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; unsigned char *ivp; int i; size_t blocksize = c->spec->blocksize; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; - unsigned nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; unsigned int burn, nburn; if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen)) @@ -92,7 +92,7 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, { /* We have to be careful here, since outbuf might be equal to inbuf. */ - int restbytes; + size_t restbytes; unsigned char b; if ((inbuflen % blocksize) == 0) @@ -124,14 +124,14 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; int i; size_t blocksize = c->spec->blocksize; gcry_cipher_decrypt_t dec_fn = c->spec->decrypt; - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; unsigned int burn, nburn; if (outbuflen < inbuflen) @@ -175,7 +175,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c, if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize) { - int restbytes; + size_t restbytes; if ((inbuflen % blocksize) == 0) restbytes = blocksize; diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index ebcbf1e..2a1fc74 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -318,8 +318,8 @@ _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, gcry_err_code_t _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - unsigned int outbuflen, const unsigned char *inbuf, - unsigned int inbuflen) + size_t outbuflen, const unsigned char *inbuf, + size_t inbuflen) { unsigned int burn; @@ -342,8 +342,8 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, gcry_err_code_t _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, - unsigned int outbuflen, const unsigned char *inbuf, - unsigned int inbuflen) + size_t outbuflen, const unsigned char *inbuf, + size_t inbuflen) { gcry_err_code_t err; unsigned int burn; diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c index 610d006..8539f54 100644 --- a/cipher/cipher-cfb.c +++ b/cipher/cipher-cfb.c @@ -33,8 +33,8 @@ gcry_err_code_t _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; @@ -73,7 +73,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, also allows to use a bulk encryption function if available. */ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_enc) { - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; c->bulk.cfb_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; @@ -130,8 +130,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; @@ -170,7 +170,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c, also allows to use a bulk encryption function if available. */ if (inbuflen >= blocksize_x_2 && c->bulk.cfb_dec) { - unsigned int nblocks = inbuflen / blocksize; + size_t nblocks = inbuflen / blocksize; c->bulk.cfb_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks); outbuf += nblocks * blocksize; inbuf += nblocks * blocksize; diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c index 37a6a79..1e7133c 100644 --- a/cipher/cipher-ctr.c +++ b/cipher/cipher-ctr.c @@ -33,14 +33,14 @@ gcry_err_code_t _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { - unsigned int n; + size_t n; int i; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; unsigned int blocksize = c->spec->blocksize; - unsigned int nblocks; + size_t nblocks; unsigned int burn, nburn; if (outbuflen < inbuflen) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index f528c84..db06823 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -74,19 +74,19 @@ struct gcry_cipher_handle struct { void (*cfb_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*cfb_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*cbc_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac); + size_t nblocks, int cbc_mac); void (*cbc_dec)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void (*ctr_enc)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); } bulk; @@ -150,57 +150,57 @@ struct gcry_cipher_handle /*-- cipher-cbc.c --*/ gcry_err_code_t _gcry_cipher_cbc_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_cbc_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-cfb.c --*/ gcry_err_code_t _gcry_cipher_cfb_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_cfb_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-ofb.c --*/ gcry_err_code_t _gcry_cipher_ofb_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-ctr.c --*/ gcry_err_code_t _gcry_cipher_ctr_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); /*-- cipher-aeswrap.c --*/ gcry_err_code_t _gcry_cipher_aeswrap_encrypt /* */ (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen); + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_aeswrap_decrypt /* */ (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen); + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen); /*-- cipher-ccm.c --*/ gcry_err_code_t _gcry_cipher_ccm_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_ccm_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_ccm_set_nonce /* */ (gcry_cipher_hd_t c, const unsigned char *nonce, size_t noncelen); diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c index c6d84dd..3842774 100644 --- a/cipher/cipher-ofb.c +++ b/cipher/cipher-ofb.c @@ -33,8 +33,8 @@ gcry_err_code_t _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { unsigned char *ivp; gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; diff --git a/cipher/cipher-selftest.h b/cipher/cipher-selftest.h index 41d77af..3a0fe98 100644 --- a/cipher/cipher-selftest.h +++ b/cipher/cipher-selftest.h @@ -28,17 +28,17 @@ typedef void (*gcry_cipher_bulk_cbc_dec_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); typedef void (*gcry_cipher_bulk_cfb_dec_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); typedef void (*gcry_cipher_bulk_ctr_enc_t)(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /* Helper function for bulk CBC decryption selftest */ const char * diff --git a/cipher/cipher.c b/cipher/cipher.c index 705696c..80aa7a7 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -555,7 +555,7 @@ gcry_cipher_close (gcry_cipher_hd_t h) /* Set the key to be used for the encryption context C to KEY with length KEYLEN. The length should match the required length. */ static gcry_error_t -cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) +cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) { gcry_err_code_t ret; @@ -578,7 +578,7 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, unsigned int keylen) /* Set the IV to be used for the encryption context C to IV with length IVLEN. The length should match the required length. */ static void -cipher_setiv (gcry_cipher_hd_t c, const byte *iv, unsigned ivlen) +cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ @@ -594,7 +594,7 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, unsigned ivlen) if (ivlen != c->spec->blocksize) { log_info ("WARNING: cipher_setiv: ivlen=%u blklen=%u\n", - ivlen, (unsigned int)c->spec->blocksize); + (unsigned int)ivlen, (unsigned int)c->spec->blocksize); fips_signal_error ("IV length does not match blocklength"); } if (ivlen > c->spec->blocksize) @@ -628,12 +628,12 @@ cipher_reset (gcry_cipher_hd_t c) static gcry_err_code_t do_ecb_crypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen, + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen, gcry_cipher_encrypt_t crypt_fn) { unsigned int blocksize = c->spec->blocksize; - unsigned int n, nblocks; + size_t n, nblocks; unsigned int burn, nburn; if (outbuflen < inbuflen) @@ -660,16 +660,16 @@ do_ecb_crypt (gcry_cipher_hd_t c, static gcry_err_code_t do_ecb_encrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->encrypt); } static gcry_err_code_t do_ecb_decrypt (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen) + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen) { return do_ecb_crypt (c, outbuf, outbuflen, inbuf, inbuflen, c->spec->decrypt); } @@ -681,8 +681,8 @@ do_ecb_decrypt (gcry_cipher_hd_t c, * Depending on the mode some constraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; @@ -781,8 +781,8 @@ gcry_cipher_encrypt (gcry_cipher_hd_t h, void *out, size_t outsize, * Depending on the mode some some contraints apply to INBUFLEN. */ static gcry_err_code_t -cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) +cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { gcry_err_code_t rc; diff --git a/cipher/rijndael.c b/cipher/rijndael.c index 47b2559..257a162 100644 --- a/cipher/rijndael.c +++ b/cipher/rijndael.c @@ -1672,7 +1672,7 @@ rijndael_encrypt (void *context, byte *b, const byte *a) void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1736,7 +1736,7 @@ _gcry_aes_cfb_enc (void *context, unsigned char *iv, void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac) + size_t nblocks, int cbc_mac) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1834,7 +1834,7 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv, void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -2095,7 +2095,7 @@ rijndael_decrypt (void *context, byte *b, const byte *a) void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -2200,7 +2200,7 @@ _gcry_aes_cfb_dec (void *context, unsigned char *iv, void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { RIJNDAEL_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/salsa20.c b/cipher/salsa20.c index f708b18..72b28b0 100644 --- a/cipher/salsa20.c +++ b/cipher/salsa20.c @@ -112,7 +112,7 @@ typedef struct SALSA20_context_s #define LE_READ_UINT32(p) buf_get_le32(p) -static void salsa20_setiv (void *context, const byte *iv, unsigned int ivlen); +static void salsa20_setiv (void *context, const byte *iv, size_t ivlen); static const char *selftest (void); @@ -360,13 +360,13 @@ salsa20_setkey (void *context, const byte *key, unsigned int keylen) static void -salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) +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", ivlen); + log_info ("WARNING: salsa20_setiv: bad ivlen=%u\n", (u32)ivlen); if (!iv || ivlen != SALSA20_IV_SIZE) memset (tmp, 0, sizeof(tmp)); @@ -387,14 +387,14 @@ salsa20_setiv (void *context, const byte *iv, unsigned int ivlen) static void salsa20_do_encrypt_stream (SALSA20_context_t *ctx, byte *outbuf, const byte *inbuf, - unsigned int length, unsigned rounds) + size_t length, unsigned rounds) { unsigned int nburn, burn = 0; if (ctx->unused) { unsigned char *p = (void*)ctx->pad; - unsigned int n; + size_t n; gcry_assert (ctx->unused < SALSA20_BLOCK_SIZE); @@ -414,7 +414,7 @@ salsa20_do_encrypt_stream (SALSA20_context_t *ctx, #ifdef USE_AMD64 if (length >= SALSA20_BLOCK_SIZE) { - unsigned int nblocks = length / SALSA20_BLOCK_SIZE; + size_t nblocks = length / SALSA20_BLOCK_SIZE; burn = _gcry_salsa20_amd64_encrypt_blocks(ctx->input, inbuf, outbuf, nblocks, rounds); length -= SALSA20_BLOCK_SIZE * nblocks; @@ -461,7 +461,7 @@ salsa20_do_encrypt_stream (SALSA20_context_t *ctx, static void salsa20_encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; @@ -472,7 +472,7 @@ salsa20_encrypt_stream (void *context, static void salsa20r12_encrypt_stream (void *context, - byte *outbuf, const byte *inbuf, unsigned int length) + byte *outbuf, const byte *inbuf, size_t length) { SALSA20_context_t *ctx = (SALSA20_context_t *)context; diff --git a/cipher/serpent.c b/cipher/serpent.c index 915cc95..8e647d4 100644 --- a/cipher/serpent.c +++ b/cipher/serpent.c @@ -827,7 +827,7 @@ serpent_decrypt (void *ctx, byte *buffer_out, const byte *buffer_in) void _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -944,8 +944,8 @@ _gcry_serpent_ctr_enc(void *context, unsigned char *ctr, intended for the bulk encryption feature of cipher.c. */ void _gcry_serpent_cbc_dec(void *context, unsigned char *iv, - void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + void *outbuf_arg, const void *inbuf_arg, + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1053,7 +1053,7 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv, void _gcry_serpent_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks) + size_t nblocks) { serpent_context_t *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/cipher/twofish.c b/cipher/twofish.c index 04081db..ecd76e3 100644 --- a/cipher/twofish.c +++ b/cipher/twofish.c @@ -966,7 +966,7 @@ twofish_decrypt (void *context, byte *out, const byte *in) of size TWOFISH_BLOCKSIZE. */ void _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1025,7 +1025,7 @@ _gcry_twofish_ctr_enc(void *context, unsigned char *ctr, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; @@ -1075,7 +1075,7 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg, intended for the bulk encryption feature of cipher.c. */ void _gcry_twofish_cfb_dec(void *context, unsigned char *iv, void *outbuf_arg, - const void *inbuf_arg, unsigned int nblocks) + const void *inbuf_arg, size_t nblocks) { TWOFISH_context *ctx = context; unsigned char *outbuf = outbuf_arg; diff --git a/src/cipher-proto.h b/src/cipher-proto.h index c7ce906..c82012c 100644 --- a/src/cipher-proto.h +++ b/src/cipher-proto.h @@ -153,21 +153,20 @@ typedef unsigned int (*gcry_cipher_decrypt_t) (void *c, typedef void (*gcry_cipher_stencrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + size_t n); /* Type for the cipher_stdecrypt function. */ typedef void (*gcry_cipher_stdecrypt_t) (void *c, unsigned char *outbuf, const unsigned char *inbuf, - unsigned int n); + 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, unsigned int ivlen); +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 diff --git a/src/cipher.h b/src/cipher.h index d939ade..38d2a97 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -97,78 +97,78 @@ void _gcry_sha1_hash_buffers (void *outbuf, /*-- rijndael.c --*/ void _gcry_aes_cfb_enc (void *context, unsigned char *iv, void *outbuf, const void *inbuf, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_cbc_enc (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks, int cbc_mac); + size_t nblocks, int cbc_mac); void _gcry_aes_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_aes_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- blowfish.c --*/ void _gcry_blowfish_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_blowfish_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_blowfish_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- cast5.c --*/ void _gcry_cast5_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_cast5_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_cast5_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- camellia-glue.c --*/ void _gcry_camellia_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_camellia_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_camellia_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- serpent.c --*/ void _gcry_serpent_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_serpent_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_serpent_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- twofish.c --*/ void _gcry_twofish_ctr_enc (void *context, unsigned char *ctr, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_twofish_cbc_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); void _gcry_twofish_cfb_dec (void *context, unsigned char *iv, void *outbuf_arg, const void *inbuf_arg, - unsigned int nblocks); + size_t nblocks); /*-- dsa.c --*/ void _gcry_register_pk_dsa_progress (gcry_handler_progress_t cbc, void *cb_data); ----------------------------------------------------------------------- Summary of changes: cipher/arcfour.c | 4 ++-- cipher/blowfish.c | 6 +++--- cipher/camellia-glue.c | 6 +++--- cipher/cast5.c | 6 +++--- cipher/cipher-aeswrap.c | 12 +++++------ cipher/cipher-cbc.c | 20 +++++++++---------- cipher/cipher-ccm.c | 8 ++++---- cipher/cipher-cfb.c | 12 +++++------ cipher/cipher-ctr.c | 8 ++++---- cipher/cipher-internal.h | 50 +++++++++++++++++++++++----------------------- cipher/cipher-ofb.c | 4 ++-- cipher/cipher-selftest.h | 6 +++--- cipher/cipher.c | 28 +++++++++++++------------- cipher/rijndael.c | 10 +++++----- cipher/salsa20.c | 16 +++++++-------- cipher/serpent.c | 8 ++++---- cipher/twofish.c | 6 +++--- src/cipher-proto.h | 7 +++---- src/cipher.h | 40 ++++++++++++++++++------------------- 19 files changed, 128 insertions(+), 129 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Mon Nov 18 17:32:43 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 18 Nov 2013 18:32:43 +0200 Subject: [PATCH 2/2] [v2] Add CMAC (Cipher-based MAC) to MAC API In-Reply-To: <20131118163238.17898.85919.stgit@localhost6.localdomain6> References: <20131118163238.17898.85919.stgit@localhost6.localdomain6> Message-ID: <20131118163243.17898.97652.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'cipher-cmac.c' and 'mac-cmac.c'. * cipher/cipher-cmac.c: New. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_keys'. (gcry_cipher_handle.u_mode): Add 'cmac'. * cipher/cipher.c (gcry_cipher_open): Rename to... (_gcry_cipher_open_internal): ...this and add CMAC. (gcry_cipher_open): New wrapper that disallows use of internal modes (CMAC) from outside. (cipher_setkey, cipher_encrypt, cipher_decrypt) (_gcry_cipher_authenticate, _gcry_cipher_gettag) (_gcry_cipher_checktag): Add handling for CMAC mode. (cipher_reset): Do not reset 'marks.key'. * cipher/mac-cmac.c: New. * cipher/mac-internal.h: Add CMAC support and algorithms. * cipher/mac.c: Add CMAC algorithms. * src/cipher.h (gcry_cipher_internal_modes): New. (_gcry_cipher_open_internal, _gcry_cipher_cmac_authenticate) (_gcry_cipher_cmac_get_tag, _gcry_cipher_cmac_check_tag) (_gcry_cipher_cmac_set_subkeys): New prototypes. * src/gcrypt.h.in (gcry_mac_algos): Add CMAC algorithms. * tests/basic.c (check_mac): Add CMAC test vectors. -- Patch adds CMAC (Cipher-based MAC) as defined in RFC 4493 and NIST Special Publication 800-38B. Internally CMAC is added to cipher module, but is available to outside only through MAC API. [v2]: - Add documentation Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 4 - cipher/cipher-cmac.c | 237 ++++++++++++++++++++++++++++++++++++++++++++++ cipher/cipher-internal.h | 9 ++ cipher/cipher.c | 68 +++++++++++++ cipher/mac-cmac.c | 233 +++++++++++++++++++++++++++++++++++++++++++++ cipher/mac-internal.h | 42 ++++++++ cipher/mac.c | 33 ++++++ doc/gcrypt.texi | 48 +++++++++ src/cipher.h | 24 +++++ src/gcrypt.h.in | 14 +++ tests/basic.c | 141 +++++++++++++++++++++++++++ 11 files changed, 847 insertions(+), 6 deletions(-) create mode 100644 cipher/cipher-cmac.c create mode 100644 cipher/mac-cmac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 1d54b07..2fd9822 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,12 +40,12 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ -cipher-ccm.c \ +cipher-ccm.c cipher-cmac.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ -mac-hmac.c \ +mac-hmac.c mac-cmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/cipher-cmac.c b/cipher/cipher-cmac.c new file mode 100644 index 0000000..0b228db --- /dev/null +++ b/cipher/cipher-cmac.c @@ -0,0 +1,237 @@ +/* cmac.c - CMAC, Cipher-based MAC. + * Copyright ? 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 "g10lib.h" +#include "cipher.h" +#include "cipher-internal.h" +#include "bufhelp.h" + + +#define set_burn(burn, nburn) do { \ + unsigned int __nburn = (nburn); \ + (burn) = (burn) > __nburn ? (burn) : __nburn; } while (0) + + +static void +cmac_write (gcry_cipher_hd_t c, const byte * inbuf, size_t inlen) +{ + gcry_cipher_encrypt_t enc_fn = c->spec->encrypt; + const unsigned int blocksize = c->spec->blocksize; + byte outbuf[MAX_BLOCKSIZE]; + unsigned int burn = 0; + unsigned int nblocks; + + if (!inlen || !inbuf) + return; + + /* Last block is needed for cmac_final. */ + if (c->unused + inlen <= blocksize) + { + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + return; + } + + if (c->unused) + { + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + + buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize); + set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv)); + + c->unused = 0; + } + + if (c->bulk.cbc_enc && inlen > blocksize) + { + nblocks = inlen / blocksize; + nblocks -= (nblocks * blocksize == inlen); + + c->bulk.cbc_enc (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks, 1); + inbuf += nblocks * blocksize; + inlen -= nblocks * blocksize; + + wipememory (outbuf, sizeof (outbuf)); + } + else + while (inlen > blocksize) + { + buf_xor (c->u_iv.iv, c->u_iv.iv, inbuf, blocksize); + set_burn (burn, enc_fn (&c->context.c, c->u_iv.iv, c->u_iv.iv)); + inlen -= blocksize; + inbuf += blocksize; + } + + /* Make sure that last block is passed to cmac_final. */ + if (inlen == 0) + BUG (); + + for (; inlen && c->unused < blocksize; inlen--) + c->lastiv[c->unused++] = *inbuf++; + + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); +} + + +static void cmac_generate_subkeys (gcry_cipher_hd_t c) +{ + const unsigned int blocksize = c->spec->blocksize; + byte rb, carry, t, bi; + unsigned int burn; + int i, j; + union + { + size_t _aligned; + byte buf[MAX_BLOCKSIZE]; + } u; + + if (MAX_BLOCKSIZE < blocksize) + BUG(); + + /* encrypt zero block */ + memset (u.buf, 0, blocksize); + burn = c->spec->encrypt (&c->context.c, u.buf, u.buf); + + /* Currently supported blocksizes are 16 and 8. */ + rb = blocksize == 16 ? 0x87 : 0x1B /*blocksize == 8 */ ; + + for (j = 0; j < 2; j++) + { + /* Generate subkeys K1 and K2 */ + carry = 0; + for (i = blocksize - 1; i >= 0; i--) + { + bi = u.buf[i]; + t = carry | (bi << 1); + carry = bi >> 7; + u.buf[i] = t & 0xff; + c->u_mode.cmac.subkeys[j][i] = u.buf[i]; + } + u.buf[blocksize - 1] ^= carry ? rb : 0; + c->u_mode.cmac.subkeys[j][blocksize - 1] = u.buf[blocksize - 1]; + } + + wipememory (&u, sizeof (u)); + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); +} + + +static void +cmac_final (gcry_cipher_hd_t c) +{ + const unsigned int blocksize = c->spec->blocksize; + unsigned int count = c->unused; + unsigned int burn; + byte *subkey; + + if (count == blocksize) + subkey = c->u_mode.cmac.subkeys[0]; /* K1 */ + else + { + subkey = c->u_mode.cmac.subkeys[1]; /* K2 */ + c->lastiv[count++] = 0x80; + while (count < blocksize) + c->lastiv[count++] = 0; + } + + buf_xor (c->lastiv, c->lastiv, subkey, blocksize); + + buf_xor (c->u_iv.iv, c->u_iv.iv, c->lastiv, blocksize); + burn = c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_iv.iv); + if (burn) + _gcry_burn_stack (burn + 4 * sizeof (void *)); + + c->unused = 0; +} + + +static gcry_err_code_t +cmac_tag (gcry_cipher_hd_t c, unsigned char *tag, size_t taglen, int check) +{ + if (!tag || taglen == 0 || taglen > c->spec->blocksize) + return GPG_ERR_INV_ARG; + + if (!c->u_mode.cmac.tag) + { + cmac_final (c); + c->u_mode.cmac.tag = 1; + } + + if (!check) + { + memcpy (tag, c->u_iv.iv, taglen); + return GPG_ERR_NO_ERROR; + } + else + { + return buf_eq_const(tag, c->u_iv.iv, taglen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + } +} + + +gcry_err_code_t +_gcry_cipher_cmac_authenticate (gcry_cipher_hd_t c, + const unsigned char *abuf, size_t abuflen) +{ + if (abuflen > 0 && !abuf) + return GPG_ERR_INV_ARG; + if (c->u_mode.cmac.tag) + return GPG_ERR_INV_STATE; + /* To support new blocksize, update cmac_generate_subkeys() then add new + blocksize here. */ + if (c->spec->blocksize != 16 && c->spec->blocksize != 8) + return GPG_ERR_INV_CIPHER_MODE; + + cmac_write (c, abuf, abuflen); + + return GPG_ERR_NO_ERROR; +} + + +gcry_err_code_t +_gcry_cipher_cmac_get_tag (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen) +{ + return cmac_tag (c, outtag, taglen, 0); +} + + +gcry_err_code_t +_gcry_cipher_cmac_check_tag (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen) +{ + return cmac_tag (c, (unsigned char *) intag, taglen, 1); +} + +gcry_err_code_t +_gcry_cipher_cmac_set_subkeys (gcry_cipher_hd_t c) +{ + cmac_generate_subkeys (c); + + return GPG_ERR_NO_ERROR; +} diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index db06823..44f43a4 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -136,8 +136,16 @@ struct gcry_cipher_handle processed. */ unsigned int tag:1; /* Set to 1 if tag has been finalized. */ } ccm; + /* Mode specific storage for CMAC mode. */ + struct { + unsigned int tag:1; /* Set to 1 if tag has been finalized. */ + + /* Subkeys for tag creation, not cleared by gcry_cipher_reset. */ + unsigned char subkeys[2][MAX_BLOCKSIZE]; + } cmac; } u_mode; + /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation whereas the second one is a copy created by cipher_setkey and @@ -217,5 +225,4 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag const unsigned char *intag, size_t taglen); - #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index 80aa7a7..b68703e 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -344,6 +344,24 @@ gcry_error_t gcry_cipher_open (gcry_cipher_hd_t *handle, int algo, int mode, unsigned int flags) { + gcry_err_code_t err; + gcry_cipher_hd_t h = NULL; + + if (mode >= GCRY_CIPHER_MODE_INTERNAL) + err = GPG_ERR_INV_CIPHER_MODE; + else + err = _gcry_cipher_open_internal (&h, algo, mode, flags); + + *handle = err ? NULL : h; + + return gcry_error (err); +} + + +gcry_err_code_t +_gcry_cipher_open_internal (gcry_cipher_hd_t *handle, + int algo, int mode, unsigned int flags) +{ int secure = (flags & GCRY_CIPHER_SECURE); gcry_cipher_spec_t *spec; gcry_cipher_hd_t h = NULL; @@ -388,6 +406,7 @@ gcry_cipher_open (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_OFB: case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: + case GCRY_CIPHER_MODE_CMAC: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; @@ -567,10 +586,20 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) (void *) &c->context.c, c->spec->contextsize); c->marks.key = 1; + + switch (c->mode) + { + case GCRY_CIPHER_MODE_CMAC: + _gcry_cipher_cmac_set_subkeys (c); + break; + default: + break; + }; } else c->marks.key = 0; + return gcry_error (ret); } @@ -613,6 +642,10 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) static void cipher_reset (gcry_cipher_hd_t c) { + unsigned int marks_key; + + marks_key = c->marks.key; + memcpy (&c->context.c, (char *) &c->context.c + c->spec->contextsize, c->spec->contextsize); @@ -620,8 +653,21 @@ cipher_reset (gcry_cipher_hd_t c) memset (c->u_iv.iv, 0, c->spec->blocksize); memset (c->lastiv, 0, c->spec->blocksize); memset (c->u_ctr.ctr, 0, c->spec->blocksize); - memset (&c->u_mode, 0, sizeof c->u_mode); c->unused = 0; + + c->marks.key = marks_key; + + switch (c->mode) + { + case GCRY_CIPHER_MODE_CMAC: + /* Only clear 'tag' for cmac, keep subkeys. */ + c->u_mode.cmac.tag = 0; + break; + + default: + memset (&c->u_mode, 0, sizeof c->u_mode); + break; + } } @@ -717,6 +763,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ccm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -817,6 +867,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = _gcry_cipher_ccm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = GPG_ERR_INV_CIPHER_MODE; + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -942,6 +996,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, rc = _gcry_cipher_ccm_authenticate (hd, abuf, abuflen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_authenticate (hd, abuf, abuflen); + break; + default: log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -962,6 +1020,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) rc = _gcry_cipher_ccm_get_tag (hd, outtag, taglen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_get_tag (hd, outtag, taglen); + break; + default: log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -982,6 +1044,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) rc = _gcry_cipher_ccm_check_tag (hd, intag, taglen); break; + case GCRY_CIPHER_MODE_CMAC: + rc = _gcry_cipher_cmac_check_tag (hd, intag, taglen); + break; + default: log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c new file mode 100644 index 0000000..7cdb397 --- /dev/null +++ b/cipher/mac-cmac.c @@ -0,0 +1,233 @@ +/* mac-cmac.c - CMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "./mac-internal.h" + + +static int map_mac_algo_to_cipher (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_CIPHER_NONE; + case GCRY_MAC_CMAC_AES: + return GCRY_CIPHER_AES; + case GCRY_MAC_CMAC_3DES: + return GCRY_CIPHER_3DES; + case GCRY_MAC_CMAC_CAMELLIA: + return GCRY_CIPHER_CAMELLIA128; + case GCRY_MAC_CMAC_IDEA: + return GCRY_CIPHER_IDEA; + case GCRY_MAC_CMAC_CAST5: + return GCRY_CIPHER_CAST5; + case GCRY_MAC_CMAC_BLOWFISH: + return GCRY_CIPHER_BLOWFISH; + case GCRY_MAC_CMAC_TWOFISH: + return GCRY_CIPHER_TWOFISH; + case GCRY_MAC_CMAC_SERPENT: + return GCRY_CIPHER_SERPENT128; + case GCRY_MAC_CMAC_SEED: + return GCRY_CIPHER_SEED; + case GCRY_MAC_CMAC_RFC2268: + return GCRY_CIPHER_RFC2268_128; + case GCRY_MAC_CMAC_GOST28147: + return GCRY_CIPHER_GOST28147; + } +} + + +static gcry_err_code_t cmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_cipher_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + int cipher_algo; + unsigned int flags; + + cipher_algo = map_mac_algo_to_cipher(h->spec->algo); + flags = (secure ? GCRY_CIPHER_SECURE : 0); + + err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_CMAC, + flags); + if (err) + return err; + + h->u.cmac.cipher_algo = cipher_algo; + h->u.cmac.ctx = hd; + h->u.cmac.blklen = _gcry_cipher_get_algo_blklen (cipher_algo); + return 0; +} + + +static void cmac_close (gcry_mac_hd_t h) +{ + _gcry_cipher_close (h->u.cmac.ctx); + h->u.cmac.ctx = NULL; +} + + +static gcry_err_code_t +cmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + return _gcry_cipher_setkey (h->u.cmac.ctx, key, keylen); +} + + +static gcry_err_code_t +cmac_reset (gcry_mac_hd_t h) +{ + return gcry_cipher_reset (h->u.cmac.ctx); +} + + +static gcry_err_code_t +cmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + return _gcry_cipher_cmac_authenticate (h->u.cmac.ctx, buf, buflen); +} + + +static gcry_err_code_t +cmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) +{ + if (*outlen > h->u.cmac.blklen) + *outlen = h->u.cmac.blklen; + return _gcry_cipher_cmac_get_tag (h->u.cmac.ctx, outbuf, *outlen); +} + + +static gcry_err_code_t +cmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + return _gcry_cipher_cmac_check_tag (h->u.cmac.ctx, buf, buflen); +} + + +static unsigned int cmac_get_maclen (int algo) +{ + return _gcry_cipher_get_algo_blklen (map_mac_algo_to_cipher (algo)); +} + + +static unsigned int cmac_get_keylen (int algo) +{ + return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); +} + + +static gcry_mac_spec_ops_t cmac_ops = + { + cmac_open, + cmac_close, + cmac_setkey, + NULL, + cmac_reset, + cmac_write, + cmac_read, + cmac_verify, + cmac_get_maclen, + cmac_get_keylen + }; + + +#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 diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 9ebc035..146b218 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -98,6 +98,11 @@ struct gcry_mac_handle gcry_md_hd_t md_ctx; int md_algo; } hmac; + struct { + gcry_cipher_hd_t ctx; + int cipher_algo; + unsigned int blklen; + } cmac; } u; }; @@ -138,3 +143,40 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; #if USE_MD4 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; #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 diff --git a/cipher/mac.c b/cipher/mac.c index 54757bb..d9b2ed6 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -64,6 +64,39 @@ static gcry_mac_spec_t *mac_list[] = #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #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, +#endif +#if USE_TWOFISH + &_gcry_mac_type_spec_cmac_twofish, +#endif +#if USE_SERPENT + &_gcry_mac_type_spec_cmac_serpent, +#endif +#if USE_RFC2268 + &_gcry_mac_type_spec_cmac_rfc2268, +#endif +#if USE_SEED + &_gcry_mac_type_spec_cmac_seed, +#endif +#if USE_CAMELLIA + &_gcry_mac_type_spec_cmac_camellia, +#endif +#ifdef USE_IDEA + &_gcry_mac_type_spec_cmac_idea, +#endif +#if USE_GOST28147 + &_gcry_mac_type_spec_cmac_gost28147, +#endif NULL, }; diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 0baafde..edd91f3 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3479,6 +3479,50 @@ algorithm described in GOST R 34.11-2012. This is HMAC message authentication algorithm based on the 512-bit hash algorithm described in GOST R 34.11-2012. + at item GCRY_MAC_CMAC_AES +This is CMAC (Cipher-based MAC) message authentication algorithm based on +the AES block cipher algorithm. + + at item GCRY_MAC_CMAC_3DES +This is CMAC message authentication algorithm based on the three-key EDE +Triple-DES block cipher algorithm. + + at item GCRY_MAC_CMAC_CAMELLIA +This is CMAC message authentication algorithm based on the Camellia block cipher +algorithm. + + at item GCRY_MAC_CMAC_CAST5 +This is CMAC message authentication algorithm based on the CAST128-5 +block cipher algorithm. + + at item GCRY_MAC_CMAC_BLOWFISH +This is CMAC message authentication algorithm based on the Blowfish +block cipher algorithm. + + at item GCRY_MAC_CMAC_TWOFISH +This is CMAC message authentication algorithm based on the Twofish +block cipher algorithm. + + at item GCRY_MAC_CMAC_SERPENT +This is CMAC message authentication algorithm based on the Serpent +block cipher algorithm. + + at item GCRY_MAC_CMAC_SEED +This is CMAC message authentication algorithm based on the SEED +block cipher algorithm. + + at item GCRY_MAC_CMAC_RFC2268 +This is CMAC message authentication algorithm based on the Ron's Cipher 2 +block cipher algorithm. + + at item GCRY_MAC_CMAC_IDEA +This is CMAC message authentication algorithm based on the IDEA +block cipher algorithm. + + at item GCRY_MAC_CMAC_GOST28147 +This is CMAC message authentication algorithm based on the GOST 28147-89 +block cipher algorithm. + @end table @c end table of MAC algorithms @@ -3518,7 +3562,9 @@ In order to use a handle for performing MAC algorithm operations, a @deftypefun gcry_error_t gcry_mac_setkey (gcry_mac_hd_t @var{h}, const void *@var{key}, size_t @var{keylen}) Set the MAC key to the value of @var{key} of length @var{keylen} bytes. With -HMAC algorithms, there is no restriction on the length of the key. +HMAC algorithms, there is no restriction on the length of the key. With CMAC +algorithms, the length of the key is restricted to those supported by the +underlying block cipher. @end deftypefun diff --git a/src/cipher.h b/src/cipher.h index 38d2a97..10bfe0c 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -84,6 +84,30 @@ struct pk_encoding_ctx #include "cipher-proto.h" +/* The internal encryption modes. */ +enum gcry_cipher_internal_modes + { + GCRY_CIPHER_MODE_INTERNAL = 0x10000, + GCRY_CIPHER_MODE_CMAC = 0x10000 + 1 /* Cipher-based MAC. */ + }; + + +/*-- cipher.c --*/ +gcry_err_code_t _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, + int algo, int mode, + unsigned int flags); + +/*-- cipher-cmac.c --*/ +gcry_err_code_t _gcry_cipher_cmac_authenticate +/* */ (gcry_cipher_hd_t c, const unsigned char *abuf, size_t abuflen); +gcry_err_code_t _gcry_cipher_cmac_get_tag +/* */ (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen); +gcry_err_code_t _gcry_cipher_cmac_check_tag +/* */ (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen); +gcry_err_code_t _gcry_cipher_cmac_set_subkeys +/* */ (gcry_cipher_hd_t c); /*-- rmd160.c --*/ void _gcry_rmd160_hash_buffer (void *outbuf, diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index b352f56..e22e1c8 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1309,7 +1309,19 @@ enum gcry_mac_algos GCRY_MAC_HMAC_WHIRLPOOL = 10, GCRY_MAC_HMAC_GOSTR3411_94 = 11, GCRY_MAC_HMAC_STRIBOG256 = 12, - GCRY_MAC_HMAC_STRIBOG512 = 13 + GCRY_MAC_HMAC_STRIBOG512 = 13, + + GCRY_MAC_CMAC_AES = 100, + GCRY_MAC_CMAC_3DES = 101, + GCRY_MAC_CMAC_CAMELLIA = 102, + GCRY_MAC_CMAC_CAST5 = 103, + GCRY_MAC_CMAC_BLOWFISH = 104, + GCRY_MAC_CMAC_TWOFISH = 105, + GCRY_MAC_CMAC_SERPENT = 106, + GCRY_MAC_CMAC_SEED = 107, + GCRY_MAC_CMAC_RFC2268 = 108, + GCRY_MAC_CMAC_IDEA = 109, + GCRY_MAC_CMAC_GOST28147 = 110 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index e7569d8..c6d03dc 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4400,6 +4400,147 @@ check_mac (void) "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + /* CMAC AES and DES test vectors from + http://web.archive.org/web/20130930212819/http://csrc.nist.gov/publica\ + tions/nistpubs/800-38B/Updated_CMAC_Examples.pdf */ + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "", + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_AES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "", + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "", + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + { GCRY_MAC_CMAC_3DES, + "\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" }, + /* CMAC Camellia test vectors from + http://tools.ietf.org/html/draft-kato-ipsec-camellia-cmac96and128-05 */ + { GCRY_MAC_CMAC_CAMELLIA, + "", + "\x2b\x7e\x15\x16\x28\xae\xd2\xa6\xab\xf7\x15\x88\x09\xcf\x4f\x3c", + "\xba\x92\x57\x82\xaa\xa1\xf5\xd9\xa0\x0f\x89\x64\x80\x94\xfc\x71" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\x6d\x96\x28\x54\xa3\xb9\xfd\xa5\x6d\x7d\x45\xa9\x5e\xe1\x79\x93" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\x5c\x18\xd1\x19\xcc\xd6\x76\x61\x44\xac\x18\x66\x13\x1d\x9f\x22" }, + { GCRY_MAC_CMAC_CAMELLIA, + "\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", + "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" }, { 0 }, }; int i; From jussi.kivilinna at iki.fi Mon Nov 18 17:32:38 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 18 Nov 2013 18:32:38 +0200 Subject: [PATCH 1/2] [v2] Add new MAC API, initially with HMAC Message-ID: <20131118163238.17898.85919.stgit@localhost6.localdomain6> Does these look ok for pushing? -- * cipher/Makefile.am: Add 'mac.c', 'mac-internal.h' and 'mac-hmac.c'. * cipher/bufhelp.h (buf_eq_const): New. * cipher/cipher-ccm.c (_gcry_cipher_ccm_tag): Use 'buf_eq_const' for constant-time compare. * cipher/mac-hmac.c: New. * cipher/mac-internal.h: New. * cipher/mac.c: New. * src/gcrypt-int.h [GPG_ERROR_VERSION_NUMBER < 1.13] (GPG_ERR_MAC_ALGO): New. * src/gcrypt.h.in (gcry_mac_handle, gcry_mac_hd_t, gcry_mac_algos) (gcry_mac_flags, gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name) (gcry_mac_reset, gcry_mac_test_algo): New. * src/libgcrypt.def (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/libgcrypt.vers (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/visibility.c (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * src/visibility.h (gcry_mac_open, gcry_mac_close, gcry_mac_ctl) (gcry_mac_algo_info, gcry_mac_setkey, gcry_mac_setiv, gcry_mac_write) (gcry_mac_read, gcry_mac_verify, gcry_mac_get_algo_maclen) (gcry_mac_get_algo_keylen, gcry_mac_algo_name, gcry_mac_map_name): New. * tests/basic.c (check_one_mac, check_mac): New. (main): Call 'check_mac'. * tests/bench-slope.c (bench_print_header, bench_print_footer): Allow variable algorithm name width. (_cipher_bench, hash_bench): Update to above change. (bench_hash_do_bench): Add 'gcry_md_reset'. (bench_mac_mode, bench_mac_init, bench_mac_free, bench_mac_do_bench) (mac_ops, mac_modes, mac_bench_one, _mac_bench, mac_bench): New. (main): Add 'mac' benchmark options. * tests/benchmark.c (mac_repetitions, mac_bench): New. (main): Add 'mac' benchmark options. -- Add MAC API, with HMAC algorithms. Internally uses HMAC functionality of the MD module. [v2]: - Add documentation for MAC API. - Change length argument for gcry_mac_read from size_t to size_t* for returning number of written bytes. Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 2 cipher/bufhelp.h | 17 ++ cipher/cipher-ccm.c | 13 - cipher/mac-hmac.c | 278 ++++++++++++++++++++++++++++++ cipher/mac-internal.h | 140 +++++++++++++++ cipher/mac.c | 449 +++++++++++++++++++++++++++++++++++++++++++++++++ doc/gcrypt.texi | 254 +++++++++++++++++++++++++++- src/gcrypt-int.h | 4 src/gcrypt.h.in | 97 +++++++++++ src/libgcrypt.def | 14 ++ src/libgcrypt.vers | 5 + src/visibility.c | 106 ++++++++++++ src/visibility.h | 42 +++++ tests/basic.c | 396 +++++++++++++++++++++++++++++++++++++++++++ tests/bench-slope.c | 182 +++++++++++++++++++- tests/benchmark.c | 146 ++++++++++++++++ 16 files changed, 2122 insertions(+), 23 deletions(-) create mode 100644 cipher/mac-hmac.c create mode 100644 cipher/mac-internal.h create mode 100644 cipher/mac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 95d484e..1d54b07 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -44,6 +44,8 @@ cipher-ccm.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ +mac.c mac-internal.h \ +mac-hmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index dc39b46..45a7209 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -220,6 +220,23 @@ buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len) } +/* Constant-time compare of two buffers. Returns 1 if buffers are equal, + and 0 if buffers differ. */ +static inline int +buf_eq_const(const void *_a, const void *_b, size_t len) +{ + const byte *a = _a; + const byte *b = _b; + size_t diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < len; i++) + diff -= !!(a[i] - b[i]); + + return !diff; +} + + #ifndef BUFHELP_FAST_UNALIGNED_ACCESS /* Functions for loading and storing unaligned u32 values of different diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index 2a1fc74..1eba7f0 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -289,13 +289,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, } else { - int diff, i; - - /* Constant-time compare. */ - for (i = 0, diff = 0; i < outbuflen; i++) - diff -= !!(outbuf[i] - c->u_iv.iv[i]); - - return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + return buf_eq_const(outbuf, c->u_iv.iv, outbuflen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } } @@ -304,7 +299,7 @@ gcry_err_code_t _gcry_cipher_ccm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen) { - return _gcry_cipher_ccm_tag (c, outtag, taglen, 0); + return _gcry_cipher_ccm_tag (c, outtag, taglen, 0); } @@ -312,7 +307,7 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen) { - return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1); + return _gcry_cipher_ccm_tag (c, (unsigned char *)intag, taglen, 1); } diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c new file mode 100644 index 0000000..b4cd380 --- /dev/null +++ b/cipher/mac-hmac.c @@ -0,0 +1,278 @@ +/* mac-hmac.c - HMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "./mac-internal.h" +#include "bufhelp.h" + + +static int map_mac_algo_to_md (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_MD_NONE; + case GCRY_MAC_HMAC_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_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_STRIBOG256: + return GCRY_MD_STRIBOG256; + case GCRY_MAC_HMAC_STRIBOG512: + return GCRY_MD_STRIBOG512; + } +} + + +static gcry_err_code_t hmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_md_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + unsigned int flags; + int md_algo; + + md_algo = map_mac_algo_to_md(h->spec->algo); + + flags = GCRY_MD_FLAG_HMAC; + flags |= (secure ? GCRY_MD_FLAG_SECURE : 0); + + err = gcry_md_open (&hd, md_algo, flags); + if (err) + return err; + + h->u.hmac.md_algo = md_algo; + h->u.hmac.md_ctx = hd; + return 0; +} + + +static void hmac_close (gcry_mac_hd_t h) +{ + gcry_md_close (h->u.hmac.md_ctx); + h->u.hmac.md_ctx = NULL; +} + + +static gcry_err_code_t +hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + return gcry_md_setkey (h->u.hmac.md_ctx, key, keylen); +} + + +static gcry_err_code_t +hmac_reset (gcry_mac_hd_t h) +{ + gcry_md_reset (h->u.hmac.md_ctx); + return 0; +} + + +static gcry_err_code_t +hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + gcry_md_write (h->u.hmac.md_ctx, buf, buflen); + return 0; +} + + +static gcry_err_code_t +hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) +{ + unsigned int dlen; + const unsigned char *digest; + + dlen = gcry_md_get_algo_dlen (h->u.hmac.md_algo); + digest = gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); + + if (*outlen <= dlen) + buf_cpy (outbuf, digest, *outlen); + else + { + buf_cpy (outbuf, digest, dlen); + *outlen = dlen; + } + + return 0; +} + + +static gcry_err_code_t +hmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + unsigned int dlen; + const unsigned char *digest; + + dlen = gcry_md_get_algo_dlen (h->u.hmac.md_algo); + digest = gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); + + if (buflen > dlen) + return GPG_ERR_INV_LENGTH; + + return buf_eq_const (buf, digest, buflen) ? 0 : GPG_ERR_CHECKSUM; +} + + +static unsigned int hmac_get_maclen(int algo) +{ + return gcry_md_get_algo_dlen (map_mac_algo_to_md (algo)); +} + + +static unsigned int hmac_get_keylen(int algo) +{ + /* Return blocksize for default key length. */ + switch (algo) + { + case GCRY_MAC_HMAC_SHA384: + case GCRY_MAC_HMAC_SHA512: + return 128; + case GCRY_MAC_HMAC_GOSTR3411_94: + return 32; + default: + return 64; + } +} + + +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 + }; + + +#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 + }; +#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 + }; +#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 diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h new file mode 100644 index 0000000..9ebc035 --- /dev/null +++ b/cipher/mac-internal.h @@ -0,0 +1,140 @@ +/* mac-internal.h - Internal defs for mac.c + * Copyright ? 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 . + */ + +/* The data object used to hold a handle to an encryption object. */ +struct gcry_mac_handle; +typedef struct gcry_mac_handle *gcry_mac_hd_t; + + +/* + * + * Message authentication code related definitions. + * + */ + + +/* Magic values for the context structure. */ +#define CTX_MAGIC_NORMAL 0x59d9b8af +#define CTX_MAGIC_SECURE 0x12c27cd0 + + +/* MAC module functions. */ +typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h); +typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h); +typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h, + const unsigned char *key, + size_t keylen); +typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h, + const unsigned char *iv, + size_t ivlen); +typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h); +typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h, + const unsigned char *inbuf, + size_t inlen); +typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h, + unsigned char *outbuf, + size_t *outlen); +typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h, + const unsigned char *inbuf, + size_t inlen); +typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo); +typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo); + + +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_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; + } 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; +#endif +#ifdef USE_GOST_R_3411_94 +extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; +#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 diff --git a/cipher/mac.c b/cipher/mac.c new file mode 100644 index 0000000..54757bb --- /dev/null +++ b/cipher/mac.c @@ -0,0 +1,449 @@ +/* mac.c - message authentication code dispatcher + * Copyright ? 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 *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, +#endif +#ifdef USE_GOST_R_3411_94 + &_gcry_mac_type_spec_hmac_gost3411_94, +#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 + NULL, + }; + + + + +/* 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; + int idx; + + for (idx = 0; (spec = mac_list[idx]); idx++) + if (algo == spec->algo) + return spec; + return NULL; +} + + +/* 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 = gcry_calloc_secure (1, sizeof(*h)); + else + h = gcry_calloc (1, sizeof(*h)); + + if (!h) + return gpg_err_code_from_syserror (); + + h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; + h->spec = spec; + h->algo = algo; + h->gcry_ctx = ctx; + + err = h->spec->ops->open (h); + if (err) + gcry_free (h); + else + *hd = h; + + return err; +} + + +static gcry_error_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->reset) + hd->spec->ops->close(hd); + + wipememory (hd, sizeof(*hd)); + + gcry_free (hd); +} + + +static gcry_error_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_error_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_error_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_error_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_error_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. */ +gcry_error_t +gcry_mac_open (gcry_mac_hd_t *h, int algo, unsigned int flags, gcry_ctx_t ctx) +{ + gcry_err_code_t err; + gcry_mac_hd_t hd = NULL; + + if ((flags & ~GCRY_MAC_FLAG_SECURE)) + err = GPG_ERR_INV_ARG; + else + err = mac_open(&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx); + + *h = err ? NULL : hd; + return gpg_error (err); +} + + +void +gcry_mac_close (gcry_mac_hd_t hd) +{ + mac_close(hd); +} + + +gcry_error_t +gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) +{ + gcry_error_t err; + + err = mac_setkey(hd, key, keylen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) +{ + gcry_error_t err; + + err = mac_setiv(hd, iv, ivlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) +{ + gcry_err_code_t err; + + err = mac_write(hd, inbuf, inlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t *outlen) +{ + gcry_error_t err; + + err = mac_read(hd, outbuf, outlen); + + return gpg_error (err); +} + + +gcry_error_t +gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + gcry_err_code_t err; + + err = mac_verify(hd, buf, buflen); + + return gpg_error (err); +} + + +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_error_t +gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen) +{ + gcry_err_code_t rc = GPG_ERR_NO_ERROR; + + /* Currently not used. */ + (void)hd; + (void)buffer; + (void)buflen; + + switch (cmd) + { + case GCRYCTL_RESET: + rc = mac_reset (hd); + break; + default: + rc = GPG_ERR_INV_OP; + } + return gcry_error (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_error_t +gcry_mac_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + gcry_err_code_t err = GPG_ERR_NO_ERROR; + unsigned int ui; + + switch (what) + { + case GCRYCTL_GET_KEYLEN: + if (buffer || (!nbytes)) + err = 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. */ + err = GPG_ERR_MAC_ALGO; + } + break; + case GCRYCTL_TEST_ALGO: + if (buffer || nbytes) + err = GPG_ERR_INV_ARG; + else + err = check_mac_algo (algo); + break; + + default: + err = GPG_ERR_INV_OP; + } + + return gcry_error (err); +} + diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 1619f0d..0baafde 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -86,13 +86,14 @@ section entitled ``GNU General Public License''. * Handler Functions:: Working with handler functions. * Symmetric cryptography:: How to use symmetric cryptography. * Public Key cryptography:: How to use public key cryptography. -* Hashing:: How to use hash and MAC algorithms. +* Hashing:: How to use hash algorithms. +* Message Authentication Codes:: How to use MAC algorithms. * Key Derivation:: How to derive keys from strings * Random Numbers:: How to work with random numbers. * S-expressions:: How to manage S-expressions. * MPI library:: How to work with multi-precision-integers. * Prime numbers:: How to use the Prime number related functions. -* Utilities:: Utility functions. +* Utilities:: Utility functions. * Tools:: Utility tools * Architecture:: How Libgcrypt works internally. @@ -2967,7 +2968,7 @@ function will be extended to cover more algorithms. Libgcrypt provides an easy and consistent to use interface for hashing. Hashing is buffered and several hash algorithms can be updated at once. -It is possible to compute a MAC using the same routines. The +It is possible to compute a HMAC using the same routines. The programming model follows an open/process/close paradigm and is in that similar to other building blocks provided by Libgcrypt. @@ -3395,6 +3396,253 @@ because @code{gcry_md_close} implicitly stops debugging. @end deftypefun + + at c ********************************************************** + at c ******************* MAC Functions ********************** + at c ********************************************************** + at node Message Authentication Codes + at chapter Message Authentication Codes + +Libgcrypt provides an easy and consistent to use interface for generating +Message Authentication Codes (MAC). MAC generation is buffered and interface +similar to the one used with hash algorithms. The programming model follows +an open/process/close paradigm and is in that similar to other building blocks +provided by Libgcrypt. + + at menu +* Available MAC algorithms:: List of MAC algorithms supported by the library. +* Working with MAC algorithms:: List of functions related to MAC algorithms. + at end menu + + at node Available MAC algorithms + at section Available MAC algorithms + + at c begin table of MAC algorithms + at cindex HMAC-SHA-1 + at cindex HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384, HMAC-SHA-512 + at cindex HMAC-RIPE-MD-160 + at cindex HMAC-MD2, HMAC-MD4, HMAC-MD5 + at cindex HMAC-TIGER1 + at cindex HMAC-Whirlpool + at cindex HMAC-Stribog-256, HMAC-Stribog-512 + at cindex HMAC-GOSTR-3411-94 + at table @code + at item GCRY_MAC_NONE +This is not a real algorithm but used by some functions as an error +return value. This constant is guaranteed to have the value @code{0}. + + at item GCRY_MAC_HMAC_SHA256 +This is keyed-hash message authentication code (HMAC) message authentication +algorithm based on the SHA-256 hash algorithm. + + at item GCRY_MAC_HMAC_SHA224 +This is HMAC message authentication algorithm based on the SHA-224 hash +algorithm. + + at item GCRY_MAC_HMAC_SHA512 +This is HMAC message authentication algorithm based on the SHA-512 hash +algorithm. + + at item GCRY_MAC_HMAC_SHA384 +This is HMAC message authentication algorithm based on the SHA-384 hash +algorithm. + + at item GCRY_MAC_HMAC_SHA1 +This is HMAC message authentication algorithm based on the SHA-1 hash +algorithm. + + at item GCRY_MAC_HMAC_MD5 +This is HMAC message authentication algorithm based on the MD5 hash +algorithm. + + at item GCRY_MAC_HMAC_MD4 +This is HMAC message authentication algorithm based on the MD4 hash +algorithm. + + at item GCRY_MAC_HMAC_RMD160 +This is HMAC message authentication algorithm based on the RIPE-MD-160 hash +algorithm. + + at item GCRY_MAC_HMAC_WHIRLPOOL +This is HMAC message authentication algorithm based on the WHIRLPOOL hash +algorithm. + + at item GCRY_MAC_HMAC_GOSTR3411_94 +This is HMAC message authentication algorithm based on the GOST R 34.11-94 hash +algorithm. + + at item GCRY_MAC_HMAC_STRIBOG256 +This is HMAC message authentication algorithm based on the 256-bit hash +algorithm described in GOST R 34.11-2012. + + at item GCRY_MAC_HMAC_STRIBOG512 +This is HMAC message authentication algorithm based on the 512-bit hash +algorithm described in GOST R 34.11-2012. + + at end table + at c end table of MAC algorithms + + at node Working with MAC algorithms + at section Working with MAC algorithms + +To use most of these function it is necessary to create a context; +this is done using: + + at deftypefun gcry_error_t gcry_mac_open (gcry_mac_hd_t *@var{hd}, int @var{algo}, unsigned int @var{flags}, gcry_ctx_t @var{ctx}) + +Create a MAC object for algorithm @var{algo}. @var{flags} may be given as an +bitwise OR of constants described below. @var{hd} is guaranteed to either +receive a valid handle or NULL. @var{ctx} is context object to associate MAC +object with. @var{ctx} maybe set to NULL. + +For a list of supported algorithms, see @xref{Available MAC algorithms}. + +The flags allowed for @var{mode} are: + + at c begin table of MAC flags + at table @code + at item GCRY_MAC_FLAG_SECURE +Allocate all buffers and the resulting MAC in "secure memory". Use this if the +MAC data is highly confidential. + + at end table + at c begin table of MAC flags + + at end deftypefun + at c end function gcry_mac_open + + +In order to use a handle for performing MAC algorithm operations, a +`key' has to be set first: + + at deftypefun gcry_error_t gcry_mac_setkey (gcry_mac_hd_t @var{h}, const void *@var{key}, size_t @var{keylen}) + +Set the MAC key to the value of @var{key} of length @var{keylen} bytes. With +HMAC algorithms, there is no restriction on the length of the key. + at end deftypefun + + + at c Some MAC algorithms need initialization vector to be set, which can be + at c performed with function: + at c + at c @deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) + at c + at c Set the IV to the value of @var{iv} of length @var{ivlen} bytes. + at c @end deftypefun + + +After you are done with the MAC calculation, you should release the resources +by using: + + at deftypefun void gcry_mac_close (gcry_mac_hd_t @var{h}) + +Release all resources of MAC context @var{h}. @var{h} should not be +used after a call to this function. A @code{NULL} passed as @var{h} is +ignored. The function also clears all sensitive information associated +with this handle. + at end deftypefun + + +Often you have to do several MAC operations using the same algorithm. +To avoid the overhead of creating and releasing context, a reset function +is provided: + + at deftypefun gcry_error_t gcry_mac_reset (gcry_mac_hd_t @var{h}) + +Reset the current context to its initial state. This is effectively identical +to a close followed by an open and setting same key. + +Note that gcry_mac_reset is implemented as a macro. + at end deftypefun + + +Now that we have prepared everything to calculate MAC, it is time to +see how it is actually done. + + at deftypefun gcry_error_t gcry_mac_write (gcry_mac_hd_t @var{h}, const void *@var{buffer}, size_t @var{length}) + +Pass @var{length} bytes of the data in @var{buffer} to the MAC object +with handle @var{h} to update the MAC values. + at end deftypefun + + +The way to read out the calculated MAC is by using the function: + + at deftypefun gcry_error_t gcry_mac_read (gcry_mac_hd_t @var{h}, void *@var{buffer}, size_t *@var{length}) + + at code{gcry_mac_read} returns the MAC after finalizing the calculation. +Function copies the resulting MAC value to @var{buffer} of the length + at var{length}. If @var{length} is larger than length of resulting MAC value, +then length of MAC is returned through @var{length}. + at end deftypefun + + +To compare existing MAC value with recalculated MAC, one is to use the function: + + at deftypefun gcry_error_t gcry_mac_verify (gcry_mac_hd_t @var{h}, void *@var{buffer}, size_t @var{length}) + + at code{gcry_mac_verify} finalizes MAC calculation and compares result with + at var{length} bytes of data in @var{buffer}. Error code @code{GPG_ERR_CHECKSUM} +is returned if the MAC value in the buffer @var{buffer} does not match +the MAC calculated in object @var{h}. + at end deftypefun + + + at c *********************************** + at c ***** MAC info functions ********** + at c *********************************** + +MAC algorithms are identified by internal algorithm numbers (see + at code{gcry_mac_open} for a list). However, in most applications they are +used by names, so two functions are available to map between string +representations and MAC algorithm identifiers. + + at deftypefun {const char *} gcry_mac_algo_name (int @var{algo}) + +Map the MAC algorithm id @var{algo} to a string representation of the +algorithm name. For unknown algorithms this function returns the +string @code{"?"}. This function should not be used to test for the +availability of an algorithm. + at end deftypefun + + at deftypefun int gcry_mac_map_name (const char *@var{name}) + +Map the algorithm with @var{name} to a MAC algorithm identifier. +Returns 0 if the algorithm name is not known. This function should not +be used to test for the availability of an algorithm. + at end deftypefun + + +To test whether an algorithm is actually available for use, the +following macro should be used: + + at deftypefun gcry_error_t gcry_mac_test_algo (int @var{algo}) + +The macro returns 0 if the MAC algorithm @var{algo} is available for use. + at end deftypefun + + +If the length of a message digest is not known, it can be retrieved +using the following function: + + at deftypefun {unsigned int} gcry_mac_get_algo_maclen (int @var{algo}) + +Retrieve the length in bytes of the MAC yielded by algorithm @var{algo}. +This is often used prior to @code{gcry_mac_read} to allocate sufficient memory +for the MAC value. On error @code{0} is returned. + at end deftypefun + + + at deftypefun unsigned int gcry_mac_get_algo_keylen (@var{algo}) + +This function returns length of the key for MAC algorithm @var{algo}. If +the algorithm supports multiple key lengths, the default supported key +length is returned. On error @code{0} is returned. The key length is +returned as number of octets. + at end deftypefun + + + @c ******************************************************* @c ******************* KDF ***************************** @c ******************************************************* diff --git a/src/gcrypt-int.h b/src/gcrypt-int.h index 295328b..974fef9 100644 --- a/src/gcrypt-int.h +++ b/src/gcrypt-int.h @@ -37,4 +37,8 @@ # define GPG_ERR_BROKEN_SECKEY 196 #endif +#if GPG_ERROR_VERSION_NUMBER < 0x010d00 /* 1.13 */ +# define GPG_ERR_MAC_ALGO 197 +#endif + #endif /*GCRY_GCRYPT_INT_H*/ diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index fffc15c..b352f56 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1279,6 +1279,103 @@ void gcry_md_debug (gcry_md_hd_t hd, const char *suffix); #define gcry_md_get_asnoid(a,b,n) \ gcry_md_algo_info((a), GCRYCTL_GET_ASNOID, (b), (n)) + + +/********************************************** + * * + * Message Authentication Code Functions * + * * + **********************************************/ + +/* The data object used to hold a handle to an encryption object. */ +struct gcry_mac_handle; +typedef struct gcry_mac_handle *gcry_mac_hd_t; + +/* Algorithm IDs for the hash functions we know about. Not all of them + are implemented. */ +enum gcry_mac_algos + { + GCRY_MAC_NONE = 0, + + GCRY_MAC_HMAC_SHA256 = 1, + GCRY_MAC_HMAC_SHA224 = 2, + GCRY_MAC_HMAC_SHA512 = 3, + GCRY_MAC_HMAC_SHA384 = 4, + GCRY_MAC_HMAC_SHA1 = 5, + GCRY_MAC_HMAC_MD5 = 6, + GCRY_MAC_HMAC_MD4 = 7, + GCRY_MAC_HMAC_RMD160 = 8, + GCRY_MAC_HMAC_TIGER1 = 9, /* The fixed TIGER variant */ + GCRY_MAC_HMAC_WHIRLPOOL = 10, + GCRY_MAC_HMAC_GOSTR3411_94 = 11, + GCRY_MAC_HMAC_STRIBOG256 = 12, + GCRY_MAC_HMAC_STRIBOG512 = 13 + }; + +/* Flags used with the open function. */ +enum gcry_mac_flags + { + GCRY_MAC_FLAG_SECURE = 1, /* Allocate all buffers in "secure" memory. */ + }; + +/* Create a MAC handle for algorithm ALGO. FLAGS may be given as an bitwise OR + of the gcry_mac_flags values. CTX maybe NULL or gcry_ctx_t object to be + associated with HANDLE. */ +gcry_error_t gcry_mac_open (gcry_mac_hd_t *handle, int algo, + unsigned int flags, gcry_ctx_t ctx); + +/* Close the MAC handle H and release all resource. */ +void gcry_mac_close (gcry_mac_hd_t h); + +/* Perform various operations on the MAC object H. */ +gcry_error_t gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer, + size_t buflen); + +/* Retrieve various information about the MAC algorithm ALGO. */ +gcry_error_t gcry_mac_algo_info (int algo, int what, void *buffer, + size_t *nbytes); + +/* Set KEY of length KEYLEN bytes for the MAC handle HD. */ +gcry_error_t gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, + size_t keylen); + +/* Set initialization vector IV of length IVLEN for the MAC handle HD. */ +gcry_error_t gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, + size_t ivlen); + +/* Pass LENGTH bytes of data in BUFFER to the MAC object HD so that + it can update the MAC values. */ +gcry_error_t gcry_mac_write (gcry_mac_hd_t hd, const void *buffer, + size_t length); + +/* Read out the final authentication code from the MAC object HD to BUFFER. */ +gcry_error_t gcry_mac_read (gcry_mac_hd_t hd, void *buffer, size_t *buflen); + +/* Verify the final authentication code from the MAC object HD with BUFFER. */ +gcry_error_t gcry_mac_verify (gcry_mac_hd_t hd, const void *buffer, + size_t buflen); + +/* Retrieve the length in bytes of the MAC yielded by algorithm ALGO. */ +unsigned int gcry_mac_get_algo_maclen (int algo); + +/* Retrieve the default key length in bytes used with algorithm A. */ +unsigned int gcry_mac_get_algo_keylen (int algo); + +/* Map the MAC algorithm whose ID is contained in ALGORITHM to a + string representation of the algorithm name. For unknown algorithm + IDs this function returns "?". */ +const char *gcry_mac_algo_name (int algorithm) _GCRY_GCC_ATTR_PURE; + +/* Map the algorithm name NAME to an MAC algorithm ID. Return 0 if + the algorithm name is not known. */ +int gcry_mac_map_name (const char *name) _GCRY_GCC_ATTR_PURE; + +/* Reset the handle to the state after open/setkey. */ +#define gcry_mac_reset(h) gcry_mac_ctl ((h), GCRYCTL_RESET, NULL, 0) + +/* Return 0 if the algorithm A is available for use. */ +#define gcry_mac_test_algo(a) \ + gcry_mac_algo_info( (a), GCRYCTL_TEST_ALGO, NULL, NULL ) /****************************** diff --git a/src/libgcrypt.def b/src/libgcrypt.def index e2aba2b..a90efce 100644 --- a/src/libgcrypt.def +++ b/src/libgcrypt.def @@ -261,5 +261,19 @@ EXPORTS gcry_mpi_set_opaque_copy @229 + gcry_mac_algo_info @230 + gcry_mac_algo_name @231 + gcry_mac_map_name @232 + gcry_mac_get_algo_maclen @233 + gcry_mac_get_algo_keylen @234 + gcry_mac_open @235 + gcry_mac_close @236 + gcry_mac_setkey @237 + gcry_mac_setiv @238 + gcry_mac_write @239 + gcry_mac_read @240 + gcry_mac_verify @241 + gcry_mac_ctl @242 + ;; end of file with public symbols for Windows. diff --git a/src/libgcrypt.vers b/src/libgcrypt.vers index c3a09b8..5118c81 100644 --- a/src/libgcrypt.vers +++ b/src/libgcrypt.vers @@ -53,6 +53,11 @@ GCRYPT_1.6 { gcry_cipher_setkey; gcry_cipher_setiv; gcry_cipher_setctr; gcry_cipher_authenticate; gcry_cipher_gettag; gcry_cipher_checktag; + gcry_mac_algo_info; gcry_mac_algo_name; gcry_mac_map_name; + gcry_mac_get_algo_maclen; gcry_mac_get_algo_keylen; + gcry_mac_open; gcry_mac_close; gcry_mac_setkey; gcry_mac_setiv; + gcry_mac_write; gcry_mac_read; gcry_mac_verify; gcry_mac_ctl; + gcry_pk_algo_info; gcry_pk_algo_name; gcry_pk_ctl; gcry_pk_decrypt; gcry_pk_encrypt; gcry_pk_genkey; gcry_pk_get_keygrip; gcry_pk_get_nbits; diff --git a/src/visibility.c b/src/visibility.c index 852bdf9..3235746 100644 --- a/src/visibility.c +++ b/src/visibility.c @@ -829,6 +829,112 @@ gcry_cipher_get_algo_blklen (int algo) } gcry_error_t +gcry_mac_algo_info (int algo, int what, void *buffer, size_t *nbytes) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_algo_info (algo, what, buffer, nbytes); +} + +const char * +gcry_mac_algo_name (int algorithm) +{ + return _gcry_mac_algo_name (algorithm); +} + +int +gcry_mac_map_name (const char *string) +{ + return _gcry_mac_map_name (string); +} + +unsigned int +gcry_mac_get_algo_maclen (int algo) +{ + return _gcry_mac_get_algo_maclen (algo); +} + +unsigned int +gcry_mac_get_algo_keylen (int algo) +{ + return _gcry_mac_get_algo_keylen (algo); +} + +gcry_error_t +gcry_mac_open (gcry_mac_hd_t *handle, int algo, unsigned int flags, + gcry_ctx_t ctx) +{ + if (!fips_is_operational ()) + { + *handle = NULL; + return gpg_error (fips_not_operational ()); + } + + return _gcry_mac_open (handle, algo, flags, ctx); +} + +void +gcry_mac_close (gcry_mac_hd_t hd) +{ + _gcry_mac_close (hd); +} + +gcry_error_t +gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_setkey (hd, key, keylen); +} + +gcry_error_t +gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_setiv (hd, iv, ivlen); +} + +gcry_error_t +gcry_mac_write (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_write (hd, buf, buflen); +} + +gcry_error_t +gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t *outlen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_read (hd, outbuf, outlen); +} + +gcry_error_t +gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_verify (hd, buf, buflen); +} + +gcry_error_t +gcry_mac_ctl (gcry_mac_hd_t h, int cmd, void *buffer, size_t buflen) +{ + if (!fips_is_operational ()) + return gpg_error (fips_not_operational ()); + + return _gcry_mac_ctl (h, cmd, buffer, buflen); +} + +gcry_error_t gcry_pk_encrypt (gcry_sexp_t *result, gcry_sexp_t data, gcry_sexp_t pkey) { if (!fips_is_operational ()) diff --git a/src/visibility.h b/src/visibility.h index 438db5b..318ff44 100644 --- a/src/visibility.h +++ b/src/visibility.h @@ -94,6 +94,20 @@ #define gcry_cipher_mode_from_oid _gcry_cipher_mode_from_oid #define gcry_cipher_open _gcry_cipher_open +#define gcry_mac_algo_info _gcry_mac_algo_info +#define gcry_mac_algo_name _gcry_mac_algo_name +#define gcry_mac_map_name _gcry_mac_map_name +#define gcry_mac_get_algo_maclen _gcry_mac_get_algo_maclen +#define gcry_mac_get_algo_keylen _gcry_mac_get_algo_keylen +#define gcry_mac_open _gcry_mac_open +#define gcry_mac_close _gcry_mac_close +#define gcry_mac_setkey _gcry_mac_setkey +#define gcry_mac_setiv _gcry_mac_setiv +#define gcry_mac_write _gcry_mac_write +#define gcry_mac_read _gcry_mac_read +#define gcry_mac_verify _gcry_mac_verify +#define gcry_mac_ctl _gcry_mac_ctl + #define gcry_pk_algo_info _gcry_pk_algo_info #define gcry_pk_algo_name _gcry_pk_algo_name #define gcry_pk_ctl _gcry_pk_ctl @@ -313,6 +327,20 @@ gcry_err_code_t gcry_md_get (gcry_md_hd_t hd, int algo, #undef gcry_cipher_mode_from_oid #undef gcry_cipher_open +#undef gcry_mac_algo_info +#undef gcry_mac_algo_name +#undef gcry_mac_map_name +#undef gcry_mac_get_algo_maclen +#undef gcry_mac_get_algo_keylen +#undef gcry_mac_open +#undef gcry_mac_close +#undef gcry_mac_setkey +#undef gcry_mac_setiv +#undef gcry_mac_write +#undef gcry_mac_read +#undef gcry_mac_verify +#undef gcry_mac_ctl + #undef gcry_pk_algo_info #undef gcry_pk_algo_name #undef gcry_pk_ctl @@ -493,6 +521,20 @@ MARK_VISIBLE (gcry_cipher_map_name) MARK_VISIBLE (gcry_cipher_mode_from_oid) MARK_VISIBLE (gcry_cipher_open) +MARK_VISIBLE (gcry_mac_algo_info) +MARK_VISIBLE (gcry_mac_algo_name) +MARK_VISIBLE (gcry_mac_map_name) +MARK_VISIBLE (gcry_mac_get_algo_maclen) +MARK_VISIBLE (gcry_mac_get_algo_keylen) +MARK_VISIBLE (gcry_mac_open) +MARK_VISIBLE (gcry_mac_close) +MARK_VISIBLE (gcry_mac_setkey) +MARK_VISIBLE (gcry_mac_setiv) +MARK_VISIBLE (gcry_mac_write) +MARK_VISIBLE (gcry_mac_read) +MARK_VISIBLE (gcry_mac_verify) +MARK_VISIBLE (gcry_mac_ctl) + MARK_VISIBLE (gcry_pk_algo_info) MARK_VISIBLE (gcry_pk_algo_name) MARK_VISIBLE (gcry_pk_ctl) diff --git a/tests/basic.c b/tests/basic.c index 99d63ae..e7569d8 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4038,7 +4038,400 @@ check_hmac (void) if (verbose) fprintf (stderr, "Completed hashed MAC checks.\n"); - } +} + + +static void +check_one_mac (int algo, const char *data, int datalen, + const char *key, int keylen, const char *expect) +{ + gcry_mac_hd_t hd; + unsigned char *p; + unsigned int maclen; + size_t macoutlen; + int i; + gcry_error_t err = 0; + + err = gcry_mac_open (&hd, algo, 0, NULL); + if (err) + { + fail ("algo %d, gcry_mac_open failed: %s\n", algo, gpg_strerror (err)); + return; + } + + maclen = gcry_mac_get_algo_maclen (algo); + if (maclen < 1 || maclen > 500) + { + fail ("algo %d, gcry_mac_get_algo_maclen failed: %d\n", algo, maclen); + return; + } + + p = malloc(maclen); + if (!p) + { + fail ("algo %d, could not malloc %d bytes\n", algo, maclen); + return; + } + + err = gcry_mac_setkey (hd, key, keylen); + if (err) + fail("algo %d, mac gcry_mac_setkey failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + err = gcry_mac_write (hd, data, datalen); + if (err) + fail("algo %d, mac gcry_mac_write failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + err = gcry_mac_verify (hd, expect, maclen); + if (err) + fail("algo %d, mac gcry_mac_verify failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + macoutlen = maclen; + err = gcry_mac_read (hd, p, &macoutlen); + if (err) + fail("algo %d, mac gcry_mac_read failed: %s\n", algo, gpg_strerror (err)); + if (err) + goto out; + + if (memcmp (p, expect, maclen)) + { + printf ("computed: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", p[i] & 0xFF); + printf ("\nexpected: "); + for (i = 0; i < maclen; i++) + printf ("%02x ", expect[i] & 0xFF); + printf ("\n"); + + fail ("algo %d, digest mismatch\n", algo); + } + if (err) + goto out; + +out: + free (p); + gcry_mac_close (hd); +} + +static void +check_mac (void) +{ + static const struct algos + { + int algo; + const char *data; + const char *key; + const char *expect; + } algos[] = + { + { GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe", + "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38" }, + { GCRY_MAC_HMAC_MD5, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", + "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d" }, + { GCRY_MAC_HMAC_MD5, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6" }, + { GCRY_MAC_HMAC_MD5, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x69\x7e\xaf\x0a\xca\x3a\x3a\xea\x3a\x75\x16\x47\x46\xff\xaa\x79" }, + { GCRY_MAC_HMAC_MD5, "Test With Truncation", + "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", + "\x56\x46\x1e\xf2\x34\x2e\xdc\x00\xf9\xba\xb9\x95\x69\x0e\xfd\x4c" }, + { GCRY_MAC_HMAC_MD5, "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", + "\x6b\x1a\xb7\xfe\x4b\xd7\xbf\x8f\x0b\x62\xe6\xce\x61\xb9\xd0\xcd" }, + { GCRY_MAC_HMAC_MD5, + "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" + "\xaa\xaa\xaa\xaa\xaa", + "\x6f\x63\x0f\xad\x67\xcd\xa0\xee\x1f\xb1\xf5\x62\xdb\x3a\xa5\x3e", }, + { GCRY_MAC_HMAC_SHA256, "what do ya want for nothing?", "Jefe", + "\x5b\xdc\xc1\x46\xbf\x60\x75\x4e\x6a\x04\x24\x26\x08\x95\x75\xc7\x5a" + "\x00\x3f\x08\x9d\x27\x39\x83\x9d\xec\x58\xb9\x64\xec\x38\x43" }, + { GCRY_MAC_HMAC_SHA256, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xb0\x34\x4c\x61\xd8\xdb\x38\x53\x5c\xa8\xaf\xce\xaf\x0b\xf1\x2b\x88" + "\x1d\xc2\x00\xc9\x83\x3d\xa7\x26\xe9\x37\x6c\x2e\x32\xcf\xf7" }, + { GCRY_MAC_HMAC_SHA256, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x77\x3e\xa9\x1e\x36\x80\x0e\x46\x85\x4d\xb8\xeb\xd0\x91\x81\xa7" + "\x29\x59\x09\x8b\x3e\xf8\xc1\x22\xd9\x63\x55\x14\xce\xd5\x65\xfe" }, + { GCRY_MAC_HMAC_SHA256, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x82\x55\x8a\x38\x9a\x44\x3c\x0e\xa4\xcc\x81\x98\x99\xf2\x08" + "\x3a\x85\xf0\xfa\xa3\xe5\x78\xf8\x07\x7a\x2e\x3f\xf4\x67\x29\x66\x5b" }, + { GCRY_MAC_HMAC_SHA256, + "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", + "\x60\xe4\x31\x59\x1e\xe0\xb6\x7f\x0d\x8a\x26\xaa\xcb\xf5\xb7\x7f" + "\x8e\x0b\xc6\x21\x37\x28\xc5\x14\x05\x46\x04\x0f\x0e\xe3\x7f\x54" }, + { GCRY_MAC_HMAC_SHA256, + "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", + "\x9b\x09\xff\xa7\x1b\x94\x2f\xcb\x27\x63\x5f\xbc\xd5\xb0\xe9\x44" + "\xbf\xdc\x63\x64\x4f\x07\x13\x93\x8a\x7f\x51\x53\x5c\x3a\x35\xe2" }, + { GCRY_MAC_HMAC_SHA224, "what do ya want for nothing?", "Jefe", + "\xa3\x0e\x01\x09\x8b\xc6\xdb\xbf\x45\x69\x0f\x3a\x7e\x9e\x6d\x0f" + "\x8b\xbe\xa2\xa3\x9e\x61\x48\x00\x8f\xd0\x5e\x44" }, + { GCRY_MAC_HMAC_SHA224, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x89\x6f\xb1\x12\x8a\xbb\xdf\x19\x68\x32\x10\x7c\xd4\x9d\xf3\x3f\x47" + "\xb4\xb1\x16\x99\x12\xba\x4f\x53\x68\x4b\x22" }, + { GCRY_MAC_HMAC_SHA224, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x7f\xb3\xcb\x35\x88\xc6\xc1\xf6\xff\xa9\x69\x4d\x7d\x6a\xd2\x64" + "\x93\x65\xb0\xc1\xf6\x5d\x69\xd1\xec\x83\x33\xea" }, + { GCRY_MAC_HMAC_SHA224, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x6c\x11\x50\x68\x74\x01\x3c\xac\x6a\x2a\xbc\x1b\xb3\x82\x62" + "\x7c\xec\x6a\x90\xd8\x6e\xfc\x01\x2d\xe7\xaf\xec\x5a" }, + { GCRY_MAC_HMAC_SHA224, + "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", + "\x95\xe9\xa0\xdb\x96\x20\x95\xad\xae\xbe\x9b\x2d\x6f\x0d\xbc\xe2" + "\xd4\x99\xf1\x12\xf2\xd2\xb7\x27\x3f\xa6\x87\x0e" }, + { GCRY_MAC_HMAC_SHA224, + "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", + "\x3a\x85\x41\x66\xac\x5d\x9f\x02\x3f\x54\xd5\x17\xd0\xb3\x9d\xbd" + "\x94\x67\x70\xdb\x9c\x2b\x95\xc9\xf6\xf5\x65\xd1" }, + { GCRY_MAC_HMAC_SHA384, "what do ya want for nothing?", "Jefe", + "\xaf\x45\xd2\xe3\x76\x48\x40\x31\x61\x7f\x78\xd2\xb5\x8a\x6b\x1b" + "\x9c\x7e\xf4\x64\xf5\xa0\x1b\x47\xe4\x2e\xc3\x73\x63\x22\x44\x5e" + "\x8e\x22\x40\xca\x5e\x69\xe2\xc7\x8b\x32\x39\xec\xfa\xb2\x16\x49" }, + { GCRY_MAC_HMAC_SHA384, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\xaf\xd0\x39\x44\xd8\x48\x95\x62\x6b\x08\x25\xf4\xab\x46\x90\x7f\x15" + "\xf9\xda\xdb\xe4\x10\x1e\xc6\x82\xaa\x03\x4c\x7c\xeb\xc5\x9c\xfa\xea" + "\x9e\xa9\x07\x6e\xde\x7f\x4a\xf1\x52\xe8\xb2\xfa\x9c\xb6" }, + { GCRY_MAC_HMAC_SHA384, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\x88\x06\x26\x08\xd3\xe6\xad\x8a\x0a\xa2\xac\xe0\x14\xc8\xa8\x6f" + "\x0a\xa6\x35\xd9\x47\xac\x9f\xeb\xe8\x3e\xf4\xe5\x59\x66\x14\x4b" + "\x2a\x5a\xb3\x9d\xc1\x38\x14\xb9\x4e\x3a\xb6\xe1\x01\xa3\x4f\x27" }, + { GCRY_MAC_HMAC_SHA384, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\x3e\x8a\x69\xb7\x78\x3c\x25\x85\x19\x33\xab\x62\x90\xaf\x6c\xa7" + "\x7a\x99\x81\x48\x08\x50\x00\x9c\xc5\x57\x7c\x6e\x1f\x57\x3b\x4e" + "\x68\x01\xdd\x23\xc4\xa7\xd6\x79\xcc\xf8\xa3\x86\xc6\x74\xcf\xfb" }, + { GCRY_MAC_HMAC_SHA384, + "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", + "\x4e\xce\x08\x44\x85\x81\x3e\x90\x88\xd2\xc6\x3a\x04\x1b\xc5\xb4" + "\x4f\x9e\xf1\x01\x2a\x2b\x58\x8f\x3c\xd1\x1f\x05\x03\x3a\xc4\xc6" + "\x0c\x2e\xf6\xab\x40\x30\xfe\x82\x96\x24\x8d\xf1\x63\xf4\x49\x52" }, + { GCRY_MAC_HMAC_SHA384, + "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", + "\x66\x17\x17\x8e\x94\x1f\x02\x0d\x35\x1e\x2f\x25\x4e\x8f\xd3\x2c" + "\x60\x24\x20\xfe\xb0\xb8\xfb\x9a\xdc\xce\xbb\x82\x46\x1e\x99\xc5" + "\xa6\x78\xcc\x31\xe7\x99\x17\x6d\x38\x60\xe6\x11\x0c\x46\x52\x3e" }, + { GCRY_MAC_HMAC_SHA512, "what do ya want for nothing?", "Jefe", + "\x16\x4b\x7a\x7b\xfc\xf8\x19\xe2\xe3\x95\xfb\xe7\x3b\x56\xe0\xa3" + "\x87\xbd\x64\x22\x2e\x83\x1f\xd6\x10\x27\x0c\xd7\xea\x25\x05\x54" + "\x97\x58\xbf\x75\xc0\x5a\x99\x4a\x6d\x03\x4f\x65\xf8\xf0\xe6\xfd" + "\xca\xea\xb1\xa3\x4d\x4a\x6b\x4b\x63\x6e\x07\x0a\x38\xbc\xe7\x37" }, + { GCRY_MAC_HMAC_SHA512, + "Hi There", + "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" + "\x0b\x0b\x0b", + "\x87\xaa\x7c\xde\xa5\xef\x61\x9d\x4f\xf0\xb4\x24\x1a\x1d\x6c\xb0" + "\x23\x79\xf4\xe2\xce\x4e\xc2\x78\x7a\xd0\xb3\x05\x45\xe1\x7c\xde" + "\xda\xa8\x33\xb7\xd6\xb8\xa7\x02\x03\x8b\x27\x4e\xae\xa3\xf4\xe4" + "\xbe\x9d\x91\x4e\xeb\x61\xf1\x70\x2e\x69\x6c\x20\x3a\x12\x68\x54" }, + { GCRY_MAC_HMAC_SHA512, + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" + "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\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", + "\xfa\x73\xb0\x08\x9d\x56\xa2\x84\xef\xb0\xf0\x75\x6c\x89\x0b\xe9" + "\xb1\xb5\xdb\xdd\x8e\xe8\x1a\x36\x55\xf8\x3e\x33\xb2\x27\x9d\x39" + "\xbf\x3e\x84\x82\x79\xa7\x22\xc8\x06\xb4\x85\xa4\x7e\x67\xc8\x07" + "\xb9\x46\xa3\x37\xbe\xe8\x94\x26\x74\x27\x88\x59\xe1\x32\x92\xfb" }, + { GCRY_MAC_HMAC_SHA512, + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" + "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\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", + "\xb0\xba\x46\x56\x37\x45\x8c\x69\x90\xe5\xa8\xc5\xf6\x1d\x4a\xf7" + "\xe5\x76\xd9\x7f\xf9\x4b\x87\x2d\xe7\x6f\x80\x50\x36\x1e\xe3\xdb" + "\xa9\x1c\xa5\xc1\x1a\xa2\x5e\xb4\xd6\x79\x27\x5c\xc5\x78\x80\x63" + "\xa5\xf1\x97\x41\x12\x0c\x4f\x2d\xe2\xad\xeb\xeb\x10\xa2\x98\xdd" }, + { GCRY_MAC_HMAC_SHA512, + "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", + "\x80\xb2\x42\x63\xc7\xc1\xa3\xeb\xb7\x14\x93\xc1\xdd\x7b\xe8\xb4" + "\x9b\x46\xd1\xf4\x1b\x4a\xee\xc1\x12\x1b\x01\x37\x83\xf8\xf3\x52" + "\x6b\x56\xd0\x37\xe0\x5f\x25\x98\xbd\x0f\xd2\x21\x5d\x6a\x1e\x52" + "\x95\xe6\x4f\x73\xf6\x3f\x0a\xec\x8b\x91\x5a\x98\x5d\x78\x65\x98" }, + { GCRY_MAC_HMAC_SHA512, + "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", + "\xe3\x7b\x6a\x77\x5d\xc8\x7d\xba\xa4\xdf\xa9\xf9\x6e\x5e\x3f\xfd" + "\xde\xbd\x71\xf8\x86\x72\x89\x86\x5d\xf5\xa3\x2d\x20\xcd\xc9\x44" + "\xb6\x02\x2c\xac\x3c\x49\x82\xb1\x0d\x5e\xeb\x55\xc3\xe4\xde\x15" + "\x13\x46\x76\xfb\x6d\xe0\x44\x60\x65\xc9\x74\x40\xfa\x8c\x6a\x58" }, + { 0 }, + }; + int i; + + if (verbose) + fprintf (stderr, "Starting MAC checks.\n"); + + for (i = 0; algos[i].algo; i++) + { + if ((gcry_mac_test_algo (algos[i].algo) + || algos[i].algo == GCRY_MAC_HMAC_MD5) && in_fips_mode) + { + if (verbose) + fprintf (stderr, " algorithm %d not available in fips mode\n", + algos[i].algo); + continue; + } + if (verbose) + fprintf (stderr, + " checking %s [%i] for %zi byte key and %zi byte data\n", + gcry_mac_algo_name (algos[i].algo), + algos[i].algo, + strlen(algos[i].key), strlen(algos[i].data)); + + check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), + algos[i].key, strlen(algos[i].key), + algos[i].expect); + } + + if (verbose) + fprintf (stderr, "Completed MAC checks.\n"); +} /* Check that the signature SIG matches the hash HASH. PKEY is the public key used for the verification. BADHASH is a hash value which @@ -4996,6 +5389,7 @@ main (int argc, char **argv) check_bulk_cipher_modes (); check_digests (); check_hmac (); + check_mac (); check_pubkey (); } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index 79b868c..f9d3c46 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -493,17 +493,17 @@ bench_print_result (double nsecs_per_byte) } static void -bench_print_header (const char *algo_name) +bench_print_header (int algo_width, const char *algo_name) { - printf (" %-14s | ", algo_name); + printf (" %-*s | ", algo_width, algo_name); printf ("%14s %15s %13s\n", "nanosecs/byte", "mebibytes/sec", "cycles/byte"); } static void -bench_print_footer (void) +bench_print_footer (int algo_width) { - printf (" %-14s =\n", ""); + printf (" %-*s =\n", algo_width, ""); } @@ -854,12 +854,12 @@ _cipher_bench (int algo) algoname = gcry_cipher_algo_name (algo); - bench_print_header (algoname); + bench_print_header (14, algoname); for (i = 0; cipher_modes[i].mode; i++) cipher_bench_one (algo, &cipher_modes[i]); - bench_print_footer (); + bench_print_footer (14); } @@ -937,6 +937,7 @@ bench_hash_do_bench (struct bench_obj *obj, void *buf, size_t buflen) { gcry_md_hd_t hd = obj->priv; + gcry_md_reset (hd); gcry_md_write (hd, buf, buflen); gcry_md_final (hd); } @@ -993,7 +994,7 @@ hash_bench (char **argv, int argc) printf ("Hash:\n"); - bench_print_header (""); + bench_print_header (14, ""); if (argv && argc) { @@ -1011,7 +1012,161 @@ hash_bench (char **argv, int argc) _hash_bench (i); } - bench_print_footer (); + bench_print_footer (14); +} + + +/************************************************************ MAC benchmarks. */ + +struct bench_mac_mode +{ + const char *name; + struct bench_ops *ops; + + int algo; +}; + + +static int +bench_mac_init (struct bench_obj *obj) +{ + struct bench_mac_mode *mode = obj->priv; + gcry_mac_hd_t hd; + int err; + unsigned int keylen; + void *key; + + obj->min_bufsize = BUF_START_SIZE; + obj->max_bufsize = BUF_END_SIZE; + obj->step_size = BUF_STEP_SIZE; + obj->num_measure_repetitions = NUM_MEASUREMENT_REPETITIONS; + + keylen = gcry_mac_get_algo_keylen (mode->algo); + if (keylen == 0) + keylen = 32; + key = malloc (keylen); + if (!key) + { + fprintf (stderr, PGM ": couldn't allocate %d bytes\n", keylen); + exit (1); + } + memset(key, 42, keylen); + + err = gcry_mac_open (&hd, mode->algo, 0, NULL); + if (err) + { + fprintf (stderr, PGM ": error opening mac `%s'\n", + gcry_mac_algo_name (mode->algo)); + free (key); + exit (1); + } + + err = gcry_mac_setkey (hd, key, keylen); + free (key); + if (err) + { + fprintf (stderr, PGM ": error setting key for mac `%s'\n", + gcry_mac_algo_name (mode->algo)); + exit (1); + } + + obj->priv = hd; + + return 0; +} + +static void +bench_mac_free (struct bench_obj *obj) +{ + gcry_mac_hd_t hd = obj->priv; + + gcry_mac_close (hd); +} + +static void +bench_mac_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_mac_hd_t hd = obj->priv; + size_t bs; + char b; + + gcry_mac_reset (hd); + gcry_mac_write (hd, buf, buflen); + bs = sizeof(b); + gcry_mac_read (hd, &b, &bs); +} + +static struct bench_ops mac_ops = { + &bench_mac_init, + &bench_mac_free, + &bench_mac_do_bench +}; + + +static struct bench_mac_mode mac_modes[] = { + {"", &mac_ops}, + {0}, +}; + + +static void +mac_bench_one (int algo, struct bench_mac_mode *pmode) +{ + struct bench_mac_mode mode = *pmode; + struct bench_obj obj = { 0 }; + double result; + + mode.algo = algo; + + if (mode.name[0] == '\0') + printf (" %-18s | ", gcry_mac_algo_name (algo)); + else + printf (" %18s | ", mode.name); + fflush (stdout); + + obj.ops = mode.ops; + obj.priv = &mode; + + result = do_slope_benchmark (&obj); + + bench_print_result (result); +} + +static void +_mac_bench (int algo) +{ + int i; + + for (i = 0; mac_modes[i].name; i++) + mac_bench_one (algo, &mac_modes[i]); +} + +void +mac_bench (char **argv, int argc) +{ + int i, algo; + + printf ("MAC:\n"); + + bench_print_header (18, ""); + + if (argv && argc) + { + for (i = 0; i < argc; i++) + { + algo = gcry_mac_map_name (argv[i]); + if (algo) + _mac_bench (algo); + } + } + else + { + for (i = 1; i < 400; i++) + if (!gcry_mac_test_algo (i)) + _mac_bench (i); + } + + bench_print_footer (18); } @@ -1021,7 +1176,7 @@ void print_help (void) { static const char *help_lines[] = { - "usage: bench-slope [options] [hash|cipher [algonames]]", + "usage: bench-slope [options] [hash|mac|cipher [algonames]]", "", " options:", " --cpu-mhz Set CPU speed for calculating cycles per bytes", @@ -1147,6 +1302,7 @@ main (int argc, char **argv) { warm_up_cpu (); hash_bench (NULL, 0); + mac_bench (NULL, 0); cipher_bench (NULL, 0); } else if (!strcmp (*argv, "hash")) @@ -1157,6 +1313,14 @@ main (int argc, char **argv) warm_up_cpu (); hash_bench ((argc == 0) ? NULL : argv, argc); } + else if (!strcmp (*argv, "mac")) + { + argc--; + argv++; + + warm_up_cpu (); + mac_bench ((argc == 0) ? NULL : argv, argc); + } else if (!strcmp (*argv, "cipher")) { argc--; diff --git a/tests/benchmark.c b/tests/benchmark.c index 93874fa..c4accd3 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -47,6 +47,9 @@ static int cipher_repetitions; /* Number of hash repetitions. */ static int hash_repetitions; +/* Number of hash repetitions. */ +static int mac_repetitions; + /* Alignment of the buffers. */ static int buffer_alignment; @@ -436,6 +439,126 @@ md_bench ( const char *algoname ) } + +static void +mac_bench ( const char *algoname ) +{ + int algo; + gcry_mac_hd_t hd; + int step, pos, j, i, repcount; + char buf_base[1000+15]; + size_t bufsize = 1000; + char *buf; + char mac[3][512]; + char key[512]; + unsigned int maclen, keylen; + size_t macoutlen; + gcry_error_t err = GPG_ERR_NO_ERROR; + + if (!algoname) + { + for (i=1; i < 400; i++) + if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) + ; /* Don't use MD5 in fips mode. */ + else if ( !gcry_mac_test_algo (i) ) + mac_bench (gcry_mac_algo_name (i)); + return; + } + + buf = buf_base + ((16 - ((size_t)buf_base & 0x0f)) % buffer_alignment); + + algo = gcry_mac_map_name (algoname); + if (!algo) + { + fprintf (stderr, PGM ": invalid hash algorithm `%s'\n", algoname); + exit (1); + } + + maclen = gcry_mac_get_algo_maclen (algo); + if (maclen > sizeof(mac)) + maclen = sizeof(mac); + + keylen = gcry_mac_get_algo_keylen (algo); + if (keylen == 0) + keylen = 32; + if (keylen > sizeof(key)) + keylen = sizeof(key); + for (i=0; i < keylen; i++) + key[i] = (keylen - i) ^ 0x54; + + err = gcry_mac_open (&hd, algo, 0, NULL); + if (err) + { + fprintf (stderr, PGM ": error opening mac algorithm `%s': %s\n", algoname, + gpg_strerror (err)); + exit (1); + } + + err = gcry_mac_setkey (hd, key, keylen); + if (err) + { + fprintf (stderr, PGM ": error setting key for mac algorithm `%s': %s\n", + algoname, gpg_strerror (err)); + exit (1); + } + + for (i=0; i < bufsize; i++) + buf[i] = i; + + printf ("%-20s", gcry_mac_algo_name (algo)); + + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + gcry_mac_write (hd, buf, bufsize); + macoutlen = maclen; + gcry_mac_read (hd, mac[0], &macoutlen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_reset (hd); + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + for (step=bufsize/10, pos=0, j=0; j < 10; j++, pos+=step) + gcry_mac_write (hd, &buf[pos], step); + macoutlen = maclen; + gcry_mac_read (hd, mac[1], &macoutlen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_reset (hd); + start_timer (); + for (repcount=0; repcount < mac_repetitions; repcount++) + for (i=0; i < 1000; i++) + for (step=bufsize/100, pos=0, j=0; j < 100; j++, pos+=step) + gcry_mac_write (hd, &buf[pos], step); + macoutlen = maclen; + gcry_mac_read (hd, mac[2], &macoutlen); + stop_timer (); + printf (" %s", elapsed_time ()); + fflush (stdout); + + gcry_mac_close (hd); + + for (i=1; i < 3; i++) + { + if (memcmp(mac[i-1], mac[i], maclen)) + { + fprintf (stderr, PGM ": mac mismatch with algorithm `%s'\n", + algoname); + exit(1); + } + } + + putchar ('\n'); + fflush (stdout); +} + + + static void ccm_aead_init(gcry_cipher_hd_t hd, size_t buflen, int authlen) { const int _L = 4; @@ -1186,7 +1309,7 @@ main( int argc, char **argv ) else if (!strcmp (*argv, "--help")) { fputs ("usage: benchmark " - "[md|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n", + "[md|mac|cipher|random|mpi|rsa|dsa|ecc [algonames]]\n", stdout); exit (0); } @@ -1256,6 +1379,15 @@ main( int argc, char **argv ) argc--; argv++; } } + else if (!strcmp (*argv, "--mac-repetitions")) + { + argc--; argv++; + if (argc) + { + mac_repetitions = atoi(*argv); + argc--; argv++; + } + } else if (!strcmp (*argv, "--pk-count")) { argc--; argv++; @@ -1330,12 +1462,16 @@ main( int argc, char **argv ) cipher_repetitions = 1; if (hash_repetitions < 1) hash_repetitions = 1; + if (mac_repetitions < 1) + mac_repetitions = 1; if ( !argc ) { gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0); md_bench (NULL); putchar ('\n'); + mac_bench (NULL); + putchar ('\n'); cipher_bench (NULL); putchar ('\n'); rsa_bench (pk_count, 1, no_blinding); @@ -1367,6 +1503,14 @@ main( int argc, char **argv ) for (argc--, argv++; argc; argc--, argv++) md_bench ( *argv ); } + else if ( !strcmp (*argv, "mac")) + { + if (argc == 1) + mac_bench (NULL); + else + for (argc--, argv++; argc; argc--, argv++) + mac_bench ( *argv ); + } else if ( !strcmp (*argv, "cipher")) { if (argc == 1) From wk at gnupg.org Tue Nov 19 11:32:46 2013 From: wk at gnupg.org (Werner Koch) Date: Tue, 19 Nov 2013 11:32:46 +0100 Subject: [PATCH 2/2] [v2] Add CMAC (Cipher-based MAC) to MAC API In-Reply-To: <20131118163243.17898.97652.stgit@localhost6.localdomain6> (Jussi Kivilinna's message of "Mon, 18 Nov 2013 18:32:43 +0200") References: <20131118163238.17898.85919.stgit@localhost6.localdomain6> <20131118163243.17898.97652.stgit@localhost6.localdomain6> Message-ID: <87a9h0r8a9.fsf@vigenere.g10code.de> On Mon, 18 Nov 2013 17:32, jussi.kivilinna at iki.fi said: > +++ b/src/gcrypt.h.in > @@ -1309,7 +1309,19 @@ enum gcry_mac_algos > GCRY_MAC_HMAC_WHIRLPOOL = 10, > GCRY_MAC_HMAC_GOSTR3411_94 = 11, > GCRY_MAC_HMAC_STRIBOG256 = 12, > - GCRY_MAC_HMAC_STRIBOG512 = 13 > + GCRY_MAC_HMAC_STRIBOG512 = 13, > + > + GCRY_MAC_CMAC_AES = 100, > + GCRY_MAC_CMAC_3DES = 101, What do you think about using 101 for the first HMAC algo and start CMAC at 201 ? This might be helpful to detect the use of a cipher/hash algorithm in place of a MAC algorithm id. Shalom-Salam, Werner p.s. Please put the name of a function in its definition at pos 0. -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Tue Nov 19 12:53:15 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 19 Nov 2013 13:53:15 +0200 Subject: [PATCH 2/2] [v2] Add CMAC (Cipher-based MAC) to MAC API In-Reply-To: <87a9h0r8a9.fsf@vigenere.g10code.de> References: <20131118163238.17898.85919.stgit@localhost6.localdomain6> <20131118163243.17898.97652.stgit@localhost6.localdomain6> <87a9h0r8a9.fsf@vigenere.g10code.de> Message-ID: <528B512B.1090308@iki.fi> On 19.11.2013 12:32, Werner Koch wrote: > On Mon, 18 Nov 2013 17:32, jussi.kivilinna at iki.fi said: > >> +++ b/src/gcrypt.h.in >> @@ -1309,7 +1309,19 @@ enum gcry_mac_algos >> GCRY_MAC_HMAC_WHIRLPOOL = 10, >> GCRY_MAC_HMAC_GOSTR3411_94 = 11, >> GCRY_MAC_HMAC_STRIBOG256 = 12, >> - GCRY_MAC_HMAC_STRIBOG512 = 13 >> + GCRY_MAC_HMAC_STRIBOG512 = 13, >> + >> + GCRY_MAC_CMAC_AES = 100, >> + GCRY_MAC_CMAC_3DES = 101, > > What do you think about using 101 for the first HMAC algo and start CMAC > at 201 ? This might be helpful to detect the use of a cipher/hash > algorithm in place of a MAC algorithm id. Sure, that makes sense and later GMAC can be added starting at 401. > > > Shalom-Salam, > > Werner > > > p.s. > Please put the name of a function in its definition at pos 0. Ok. -Jussi From jussi.kivilinna at iki.fi Tue Nov 19 18:30:00 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 19 Nov 2013 19:30:00 +0200 Subject: [PATCH 1/2] Tweak Camellia-AVX key-setup for small speed-up Message-ID: <20131119173000.544.99271.stgit@localhost6.localdomain6> * cipher/camellia-aesni-avx-amd64.S (camellia_f): Merge S-function output rotation with P-function. -- Signed-off-by: Jussi Kivilinna --- cipher/camellia-aesni-avx-amd64.S | 72 ++++++++++++++----------------------- 1 file changed, 28 insertions(+), 44 deletions(-) diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index b25a8c7..ffb1aed 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -1213,7 +1213,7 @@ _gcry_camellia_aesni_avx_cfb_dec: /* input rotation for sbox4 (<<< 1) */ \ vpand x, sbox4mask, t0; \ vpandn x, sbox4mask, x; \ - vpsllw $1, t0, t1; \ + vpaddw t0, t0, t1; \ vpsrlw $7, t0, t0; \ vpor t0, t1, t0; \ vpand sbox4mask, t0, t0; \ @@ -1238,34 +1238,22 @@ _gcry_camellia_aesni_avx_cfb_dec: vpor sbox2mask, t4, t2; \ vpand x, sbox2mask, t0; \ vpand x, t4, t1; \ - vpandn x, t2, x; \ - vpsllw $1, t0, t2; \ + vpaddb x, x, t2; \ + vpshufb .Lsp1110111044044404mask RIP, x, t4; \ + vpshufb .Lsp0044440410011110mask RIP, x, x; \ vpsrlw $7, t0, t0; \ - vpor t0, t2, t0; \ - vpand sbox2mask, t0, t0; \ - vpsllw $7, t1, t2; \ + vpsllw $7, t1, t3; \ vpsrlw $1, t1, t1; \ - vpor t1, t2, t1; \ - vpand t4, t1, t1; \ - vpor x, t0, x; \ - vpor x, t1, x; \ - \ - vpshufb .Lsp11101110mask RIP, x, t4; \ - vpshufb .Lsp44044404mask RIP, x, t1; \ - vpshufb .Lsp30333033mask RIP, x, t2; \ - vpshufb .Lsp02220222mask RIP, x, t0; \ - vpxor t2, t1, t1; \ - \ - vpshufb .Lsp00444404mask RIP, x, t2; \ - vpxor t0, t1, t1; \ - vpshufb .Lsp03303033mask RIP, x, t0; \ - vpxor t2, t4, t4; \ - vpshufb .Lsp22000222mask RIP, x, t2; \ - vpxor t0, t1, t1; \ - vpxor t2, t4, t4; \ - vpshufb .Lsp10011110mask RIP, x, x; \ - vpxor t1, x, x; \ - vpxor t4, x, x; + vpor t0, t2, t0; \ + vpshufb .Lsp0222022222000222mask RIP, t0, t0; \ + vpor t1, t3, t1; \ + vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ + \ + vpxor x, t4, t4; \ + vpxor t1, t0, t0; \ + vpxor t4, t0, t0; \ + vpsrldq $8, t0, x; \ + vpxor t0, x, x; #define vec_rol128(in, out, nrol, t0) \ vpshufd $0x4e, in, out; \ @@ -1281,29 +1269,25 @@ _gcry_camellia_aesni_avx_cfb_dec: .data -.align 8 +.align 16 +.Lsp1110111044044404mask: + .long 0x000000ff, 0x000000ff; + .long 0x0101ff01, 0x0101ff01; +.Lsp0044440410011110mask: + .long 0xffff0404, 0x0404ff04; + .long 0x07ffff07, 0x070707ff; +.Lsp0222022222000222mask: + .long 0xff030303, 0xff030303; + .long 0x0606ffff, 0xff060606; +.Lsp3033303303303033mask: + .long 0x02ff0202, 0x02ff0202; + .long 0xff0505ff, 0x05ff0505; .Lsbox2_output_mask: .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; .Lsbox3_output_mask: .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; .Lsbox4_input_mask: .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; -.Lsp11101110mask: - .long 0x000000ff, 0x000000ff; -.Lsp44044404mask: - .long 0x0101ff01, 0x0101ff01; -.Lsp30333033mask: - .long 0x02ff0202, 0x02ff0202; -.Lsp02220222mask: - .long 0xff030303, 0xff030303; -.Lsp00444404mask: - .long 0xffff0404, 0x0404ff04; -.Lsp03303033mask: - .long 0xff0505ff, 0x05ff0505; -.Lsp22000222mask: - .long 0x0606ffff, 0xff060606; -.Lsp10011110mask: - .long 0x07ffff07, 0x070707ff; .Lsigma1: .long 0x3BCC908B, 0xA09E667F; .Lsigma2: From jussi.kivilinna at iki.fi Tue Nov 19 18:30:05 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 19 Nov 2013 19:30:05 +0200 Subject: [PATCH 2/2] Camellia: fix compiler warning In-Reply-To: <20131119173000.544.99271.stgit@localhost6.localdomain6> References: <20131119173000.544.99271.stgit@localhost6.localdomain6> Message-ID: <20131119173005.544.76161.stgit@localhost6.localdomain6> * cipher/camellia-glue.c (camellia_setkey): Use braces around empty if statement. -- Patch silences following warning: camellia-glue.c: In function 'camellia_setkey': camellia-glue.c:183:5: warning: suggest braces around empty body in an 'if' statement [-Wempty-body] Signed-off-by: Jussi Kivilinna --- cipher/camellia-glue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 575bb04..f18d135 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -180,7 +180,7 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) ctx->keybitlength=keylen*8; if (0) - ; + { } #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) _gcry_camellia_aesni_avx_keygen(ctx, key, keylen); From cvs at cvs.gnupg.org Tue Nov 19 22:25:56 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Tue, 19 Nov 2013 22:25:56 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-389-g9816ae9 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 9816ae9d9931b75e4fdc9a5be10e6af447132313 (commit) via 77922a82c3f2e30eca04511fa5a355208349c657 (commit) from b49cd64aaaff2e5488a84665362ef7150683226c (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 9816ae9d9931b75e4fdc9a5be10e6af447132313 Author: Jussi Kivilinna Date: Mon Nov 18 20:27:35 2013 +0200 Camellia: fix compiler warning * cipher/camellia-glue.c (camellia_setkey): Use braces around empty if statement. -- Patch silences following warning: camellia-glue.c: In function 'camellia_setkey': camellia-glue.c:183:5: warning: suggest braces around empty body in an 'if' statement [-Wempty-body] Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c index 575bb04..f18d135 100644 --- a/cipher/camellia-glue.c +++ b/cipher/camellia-glue.c @@ -180,7 +180,7 @@ camellia_setkey(void *c, const byte *key, unsigned keylen) ctx->keybitlength=keylen*8; if (0) - ; + { } #ifdef USE_AESNI_AVX else if (ctx->use_aesni_avx) _gcry_camellia_aesni_avx_keygen(ctx, key, keylen); commit 77922a82c3f2e30eca04511fa5a355208349c657 Author: Jussi Kivilinna Date: Tue Nov 19 15:48:32 2013 +0200 Tweak Camellia-AVX key-setup for small speed-up * cipher/camellia-aesni-avx-amd64.S (camellia_f): Merge S-function output rotation with P-function. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index b25a8c7..ffb1aed 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -1213,7 +1213,7 @@ _gcry_camellia_aesni_avx_cfb_dec: /* input rotation for sbox4 (<<< 1) */ \ vpand x, sbox4mask, t0; \ vpandn x, sbox4mask, x; \ - vpsllw $1, t0, t1; \ + vpaddw t0, t0, t1; \ vpsrlw $7, t0, t0; \ vpor t0, t1, t0; \ vpand sbox4mask, t0, t0; \ @@ -1238,34 +1238,22 @@ _gcry_camellia_aesni_avx_cfb_dec: vpor sbox2mask, t4, t2; \ vpand x, sbox2mask, t0; \ vpand x, t4, t1; \ - vpandn x, t2, x; \ - vpsllw $1, t0, t2; \ + vpaddb x, x, t2; \ + vpshufb .Lsp1110111044044404mask RIP, x, t4; \ + vpshufb .Lsp0044440410011110mask RIP, x, x; \ vpsrlw $7, t0, t0; \ - vpor t0, t2, t0; \ - vpand sbox2mask, t0, t0; \ - vpsllw $7, t1, t2; \ + vpsllw $7, t1, t3; \ vpsrlw $1, t1, t1; \ - vpor t1, t2, t1; \ - vpand t4, t1, t1; \ - vpor x, t0, x; \ - vpor x, t1, x; \ - \ - vpshufb .Lsp11101110mask RIP, x, t4; \ - vpshufb .Lsp44044404mask RIP, x, t1; \ - vpshufb .Lsp30333033mask RIP, x, t2; \ - vpshufb .Lsp02220222mask RIP, x, t0; \ - vpxor t2, t1, t1; \ - \ - vpshufb .Lsp00444404mask RIP, x, t2; \ - vpxor t0, t1, t1; \ - vpshufb .Lsp03303033mask RIP, x, t0; \ - vpxor t2, t4, t4; \ - vpshufb .Lsp22000222mask RIP, x, t2; \ - vpxor t0, t1, t1; \ - vpxor t2, t4, t4; \ - vpshufb .Lsp10011110mask RIP, x, x; \ - vpxor t1, x, x; \ - vpxor t4, x, x; + vpor t0, t2, t0; \ + vpshufb .Lsp0222022222000222mask RIP, t0, t0; \ + vpor t1, t3, t1; \ + vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ + \ + vpxor x, t4, t4; \ + vpxor t1, t0, t0; \ + vpxor t4, t0, t0; \ + vpsrldq $8, t0, x; \ + vpxor t0, x, x; #define vec_rol128(in, out, nrol, t0) \ vpshufd $0x4e, in, out; \ @@ -1281,29 +1269,25 @@ _gcry_camellia_aesni_avx_cfb_dec: .data -.align 8 +.align 16 +.Lsp1110111044044404mask: + .long 0x000000ff, 0x000000ff; + .long 0x0101ff01, 0x0101ff01; +.Lsp0044440410011110mask: + .long 0xffff0404, 0x0404ff04; + .long 0x07ffff07, 0x070707ff; +.Lsp0222022222000222mask: + .long 0xff030303, 0xff030303; + .long 0x0606ffff, 0xff060606; +.Lsp3033303303303033mask: + .long 0x02ff0202, 0x02ff0202; + .long 0xff0505ff, 0x05ff0505; .Lsbox2_output_mask: .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; .Lsbox3_output_mask: .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; .Lsbox4_input_mask: .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; -.Lsp11101110mask: - .long 0x000000ff, 0x000000ff; -.Lsp44044404mask: - .long 0x0101ff01, 0x0101ff01; -.Lsp30333033mask: - .long 0x02ff0202, 0x02ff0202; -.Lsp02220222mask: - .long 0xff030303, 0xff030303; -.Lsp00444404mask: - .long 0xffff0404, 0x0404ff04; -.Lsp03303033mask: - .long 0xff0505ff, 0x05ff0505; -.Lsp22000222mask: - .long 0x0606ffff, 0xff060606; -.Lsp10011110mask: - .long 0x07ffff07, 0x070707ff; .Lsigma1: .long 0x3BCC908B, 0xA09E667F; .Lsigma2: ----------------------------------------------------------------------- Summary of changes: cipher/camellia-aesni-avx-amd64.S | 72 +++++++++++++++---------------------- cipher/camellia-glue.c | 2 +- 2 files changed, 29 insertions(+), 45 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Wed Nov 20 18:00:07 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:07 +0200 Subject: [PATCH 02/13] Add some documentation for GCM mode In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170007.11305.17762.stgit@localhost6.localdomain6> * doc/gcrypt.texi: Add mention of GCM mode. -- Signed-off-by: Jussi Kivilinna --- doc/gcrypt.texi | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index b8ee494..1f6ceec 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -1642,6 +1642,12 @@ Counter with CBC-MAC mode is an Authenticated Encryption with Associated Data (AEAD) block cipher mode, which is specified in 'NIST Special Publication 800-38C' and RFC 3610. + at item GCRY_CIPHER_MODE_GCM + at cindex GCM, Galois/Counter Mode +Galois/Counter Mode (GCM) is an Authenticated Encryption with +Associated Data (AEAD) block cipher mode, which is specified in +'NIST Special Publication 800-38D'. + @end table @node Working with cipher handles @@ -1672,9 +1678,9 @@ with some algorithms - in particular, stream mode block cipher modes (@code{GCRY_CIPHER_MODE_ECB}, @code{GCRY_CIPHER_MODE_CBC}, @code{GCRY_CIPHER_MODE_CFB}, @code{GCRY_CIPHER_MODE_OFB} and @code{GCRY_CIPHER_MODE_CTR}) will work -with any block cipher algorithm. The @code{GCRY_CIPHER_MODE_CCM} will -only work with block cipher algorithms which have the block size of -16 bytes. +with any block cipher algorithm. @code{GCRY_CIPHER_MODE_CCM} and + at code{GCRY_CIPHER_MODE_GCM} modes will only work with block cipher algorithms +which have the block size of 16 bytes. The third argument @var{flags} can either be passed as @code{0} or as the bit-wise OR of the following constants. From jussi.kivilinna at iki.fi Wed Nov 20 18:00:22 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:22 +0200 Subject: [PATCH 05/13] GCM: Use counter mode code for speed-up In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170022.11305.81005.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (ghash): Add process for multiple blocks. (gcm_bytecounter_add, gcm_add32_be128, gcm_check_datalen) (gcm_check_aadlen_or_ivlen, do_ghash_buf): New functions. (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt) (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_set_iv) (_gcry_cipher_gcm_tag): Adjust to use above new functions and counter mode functions for encryption/decryption. * cipher/cipher-internal.h (gcry_cipher_handle): Remove 'length'; Add 'u_mode.gcm.(addlen|datalen|tagiv|datalen_over_limits)'. (_gcry_cipher_gcm_setiv): Return gcry_err_code_t. * cipher/cipher.c (cipher_setiv): Return error code. (_gcry_cipher_setiv): Handle error code from 'cipher_setiv'. -- Patch changes GCM to use counter mode code for bulk speed up and also adds data length checks as given in NIST SP-800-38D section 5.2.1.1. Bit length requirements from section 5.2.1.1: len(plaintext) <= 2^39-256 bits == 2^36-32 bytes == 2^32-2 blocks len(aad) <= 2^64-1 bits ~= 2^61-1 bytes len(iv) <= 2^64-1 bit ~= 2^61-1 bytes Intel Haswell: Old: AES GCM enc | 3.00 ns/B 317.4 MiB/s 9.61 c/B GCM dec | 1.96 ns/B 486.9 MiB/s 6.27 c/B GCM auth | 0.848 ns/B 1124.7 MiB/s 2.71 c/B New: AES GCM enc | 1.12 ns/B 851.8 MiB/s 3.58 c/B GCM dec | 1.12 ns/B 853.7 MiB/s 3.57 c/B GCM auth | 0.843 ns/B 1131.4 MiB/s 2.70 c/B Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 362 +++++++++++++++++++++++++++------------------- cipher/cipher-internal.h | 14 +- cipher/cipher.c | 14 +- 3 files changed, 232 insertions(+), 158 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index b93f0fa..cdd946e 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -442,8 +442,11 @@ do_ghash_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf) static void -ghash (gcry_cipher_hd_t c, unsigned char *result, const unsigned char *buf) +ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, + unsigned int nblocks) { + const unsigned int blocksize = GCRY_GCM_BLOCK_LEN; + if (0) ; #ifdef GCM_USE_INTEL_PCLMUL @@ -451,7 +454,12 @@ ghash (gcry_cipher_hd_t c, unsigned char *result, const unsigned char *buf) { /* TODO: Loop structure, use bit-reflection and add faster bulk processing (parallel four blocks). */ - do_ghash_pclmul (c, result, buf); + while (nblocks) + { + do_ghash_pclmul (c, result, buf); + buf += blocksize; + nblocks--; + } /* Clear used registers. */ asm volatile( "pxor %%xmm0, %%xmm0\n\t" @@ -466,9 +474,17 @@ ghash (gcry_cipher_hd_t c, unsigned char *result, const unsigned char *buf) } #endif else - GHASH (c, result, buf); + { + while (nblocks) + { + GHASH (c, result, buf); + buf += blocksize; + nblocks--; + } + } } + static void setupM (gcry_cipher_hd_t c, byte *h) { @@ -484,7 +500,7 @@ setupM (gcry_cipher_hd_t c, byte *h) /* Swap endianness of hsub. */ tmp[0] = buf_get_be64(c->u_iv.iv + 8); tmp[1] = buf_get_be64(c->u_iv.iv + 0); - buf_cpy (c->u_iv.iv, tmp, 16); + buf_cpy (c->u_iv.iv, tmp, GCRY_GCM_BLOCK_LEN); } #endif else @@ -492,224 +508,275 @@ setupM (gcry_cipher_hd_t c, byte *h) } -gcry_err_code_t -_gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, - byte * outbuf, unsigned int outbuflen, - const byte * inbuf, unsigned int inbuflen) +static inline void +gcm_bytecounter_add (u32 ctr[2], u32 add) { - unsigned int n; - int i; - unsigned int blocksize = c->spec->blocksize; - unsigned char tmp[MAX_BLOCKSIZE]; + ctr[0] += add; + if (ctr[0] >= add) + return; + ++ctr[1]; +} - if (blocksize >= 0x20) - return GPG_ERR_CIPHER_ALGO; - if (blocksize != 0x10) - return GPG_ERR_CIPHER_ALGO; - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; - if (!c->marks.iv) - { - memset (tmp, 0, 16); - _gcry_cipher_gcm_setiv (c, tmp, 16); - } +static inline u32 +gcm_add32_be128 (byte *ctr, unsigned int add) +{ + /* 'ctr' must be aligned to four bytes. */ + const unsigned int blocksize = GCRY_GCM_BLOCK_LEN; + u32 *pval = (u32 *)(void *)(ctr + blocksize - sizeof(u32)); + u32 val; - while (inbuflen) - { - for (i = blocksize; i > blocksize - 4; i--) - { - c->u_ctr.ctr[i - 1]++; - if (c->u_ctr.ctr[i - 1] != 0) - break; - } + val = be_bswap32(*pval) + add; + *pval = be_bswap32(val); - n = blocksize < inbuflen ? blocksize : inbuflen; + return val; /* return result as host-endian value */ +} - i = blocksize - 1; - c->length[i] += n * 8; - for (; c->length[i] == 0 && i > blocksize / 2; i--) - c->length[i - 1]++; - c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); - if (n < blocksize) - { - buf_xor_2dst (outbuf, tmp, inbuf, n); - memset (tmp + n, 0, blocksize - n); - ghash (c, c->u_mode.gcm.u_tag.tag, tmp); - } - else - { - buf_xor (outbuf, tmp, inbuf, n); - ghash (c, c->u_mode.gcm.u_tag.tag, outbuf); - } +static inline int +gcm_check_datalen (u32 ctr[2]) +{ + /* len(plaintext) <= 2^39-256 bits == 2^36-32 bytes == 2^32-2 blocks */ + if (ctr[1] > 0xfU) + return 0; + if (ctr[1] < 0xfU) + return 1; - inbuflen -= n; - outbuf += n; - inbuf += n; - } + if (ctr[0] <= 0xffffffe0U) + return 1; return 0; } -gcry_err_code_t -_gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, - byte * outbuf, unsigned int outbuflen, - const byte * inbuf, unsigned int inbuflen) + +static inline int +gcm_check_aadlen_or_ivlen (u32 ctr[2]) +{ + /* len(aad/iv) <= 2^64-1 bits ~= 2^61-1 bytes */ + if (ctr[1] > 0x1fffffffU) + return 0; + if (ctr[1] < 0x1fffffffU) + return 1; + + if (ctr[0] <= 0xffffffffU) + return 1; + + return 0; +} + + +static void +do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, + unsigned int buflen) { - unsigned int n; - int i; - unsigned int blocksize = c->spec->blocksize; unsigned char tmp[MAX_BLOCKSIZE]; + unsigned int blocksize = GCRY_GCM_BLOCK_LEN; + unsigned int nblocks; - if (blocksize >= 0x20) - return GPG_ERR_CIPHER_ALGO; - if (blocksize != 0x10) - return GPG_ERR_CIPHER_ALGO; - if (outbuflen < inbuflen) - return GPG_ERR_BUFFER_TOO_SHORT; + nblocks = buflen / blocksize; - if (!c->marks.iv) + if (nblocks) { - memset (tmp, 0, 16); - _gcry_cipher_gcm_setiv (c, tmp, 16); + ghash (c, hash, buf, nblocks); + buf += blocksize * nblocks; + buflen -= blocksize * nblocks; } - while (inbuflen) + if (buflen) { - for (i = blocksize; i > blocksize - 4; i--) - { - c->u_ctr.ctr[i - 1]++; - if (c->u_ctr.ctr[i - 1] != 0) - break; - } + buf_cpy (tmp, buf, buflen); + memset (tmp + buflen, 0, blocksize - buflen); + ghash (c, hash, tmp, 1); + } + + /* TODO: burn stack */ +} - n = blocksize < inbuflen ? blocksize : inbuflen; - if (n < blocksize) - { - memcpy (tmp, inbuf, n); - memset (tmp + n, 0, blocksize - n); - ghash (c, c->u_mode.gcm.u_tag.tag, tmp); - } - else - { - ghash (c, c->u_mode.gcm.u_tag.tag, inbuf); - } - i = blocksize - 1; - c->length[i] += n * 8; - for (; c->length[i] == 0 && i > blocksize / 2; i--) - c->length[i - 1]++; +gcry_err_code_t +_gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, + byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) +{ + static const unsigned char zerobuf[MAX_BLOCKSIZE]; + gcry_err_code_t err; - c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if (c->u_mode.gcm.datalen_over_limits) + return GPG_ERR_INV_LENGTH; - buf_xor (outbuf, inbuf, tmp, n); + if (!c->marks.iv) + _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); - inbuflen -= n; - outbuf += n; - inbuf += n; + gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen); + if (!gcm_check_datalen(c->u_mode.gcm.datalen)) + { + c->u_mode.gcm.datalen_over_limits = 1; + return GPG_ERR_INV_LENGTH; } + err = _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen); + if (err != 0) + return err; + + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen); + return 0; } + gcry_err_code_t -_gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, - const byte * aadbuf, unsigned int aadbuflen) +_gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, + byte *outbuf, unsigned int outbuflen, + const byte *inbuf, unsigned int inbuflen) { - unsigned int n; - int i; - unsigned int blocksize = c->spec->blocksize; - unsigned char tmp[MAX_BLOCKSIZE]; + static const unsigned char zerobuf[MAX_BLOCKSIZE]; + + if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + if (c->u_mode.gcm.datalen_over_limits) + return GPG_ERR_INV_LENGTH; if (!c->marks.iv) + _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); + + gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen); + if (!gcm_check_datalen(c->u_mode.gcm.datalen)) { - memset (tmp, 0, 16); - _gcry_cipher_gcm_setiv (c, tmp, 16); + c->u_mode.gcm.datalen_over_limits = 1; + return GPG_ERR_INV_LENGTH; } - n = aadbuflen; - i = blocksize / 2; - c->length[i - 1] = (n % 0x20) * 8; - n /= 0x20; - for (; n && i > 0; i--, n >>= 8) - c->length[i - 1] = n & 0xff; + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen); - while (aadbuflen >= blocksize) - { - ghash (c, c->u_mode.gcm.u_tag.tag, aadbuf); + return _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen); +} - aadbuflen -= blocksize; - aadbuf += blocksize; - } - if (aadbuflen != 0) - { - memcpy (tmp, aadbuf, aadbuflen); - memset (tmp + aadbuflen, 0, blocksize - aadbuflen); +gcry_err_code_t +_gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, + const byte * aadbuf, unsigned int aadbuflen) +{ + static const unsigned char zerobuf[MAX_BLOCKSIZE]; + + if (c->spec->blocksize != GCRY_GCM_BLOCK_LEN) + return GPG_ERR_CIPHER_ALGO; + if (c->u_mode.gcm.datalen_over_limits) + return GPG_ERR_INV_LENGTH; - ghash (c, c->u_mode.gcm.u_tag.tag, tmp); + if (!c->marks.iv) + _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); + + gcm_bytecounter_add(c->u_mode.gcm.aadlen, aadbuflen); + if (!gcm_check_aadlen_or_ivlen(c->u_mode.gcm.aadlen)) + { + c->u_mode.gcm.datalen_over_limits = 1; + return GPG_ERR_INV_LENGTH; } + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen); + return 0; } -void -_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, - const byte * iv, unsigned int ivlen) + +gcry_err_code_t +_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { - memset (c->length, 0, 16); - memset (c->u_mode.gcm.u_tag.tag, 0, 16); + memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen)); + memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen)); + memset (c->u_mode.gcm.u_tag.tag, 0, GCRY_GCM_BLOCK_LEN); + c->u_mode.gcm.datalen_over_limits = 0; + + if (ivlen == 0) + return GPG_ERR_INV_LENGTH; + c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_mode.gcm.u_tag.tag); setupM (c, c->u_iv.iv); - if (ivlen != 16 - 4) + if (ivlen != GCRY_GCM_BLOCK_LEN - 4) { - unsigned char tmp[MAX_BLOCKSIZE]; - unsigned n; - memset (c->u_ctr.ctr, 0, 16); - for (n = ivlen; n >= 16; n -= 16, iv += 16) - ghash (c, c->u_ctr.ctr, iv); - if (n != 0) + u32 iv_bytes[2] = {0, 0}; + u32 bitlengths[2][2]; + + memset(c->u_ctr.ctr, 0, GCRY_GCM_BLOCK_LEN); + + gcm_bytecounter_add(iv_bytes, ivlen); + if (!gcm_check_aadlen_or_ivlen(iv_bytes)) { - memcpy (tmp, iv, n); - memset (tmp + n, 0, 16 - n); - ghash (c, c->u_ctr.ctr, tmp); + c->u_mode.gcm.datalen_over_limits = 1; + return GPG_ERR_INV_LENGTH; } - memset (tmp, 0, 16); - n = 16; - tmp[n - 1] = (ivlen % 0x20) * 8; - ivlen /= 0x20; - n--; - for (; n > 0; n--, ivlen >>= 8) - tmp[n - 1] = ivlen & 0xff; - ghash (c, c->u_ctr.ctr, tmp); + + do_ghash_buf(c, c->u_ctr.ctr, iv, ivlen); + + /* iv length, 64-bit */ + bitlengths[1][1] = be_bswap32(iv_bytes[0] << 3); + bitlengths[1][0] = be_bswap32((iv_bytes[0] >> 29) | + (iv_bytes[1] << 3)); + /* zeros, 64-bit */ + bitlengths[0][1] = 0; + bitlengths[0][0] = 0; + + do_ghash_buf(c, c->u_ctr.ctr, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN); + + wipememory(iv_bytes, sizeof iv_bytes); + wipememory(bitlengths, sizeof bitlengths); } else { + /* 96-bit IV is handled differently. */ memcpy (c->u_ctr.ctr, iv, ivlen); c->u_ctr.ctr[12] = c->u_ctr.ctr[13] = c->u_ctr.ctr[14] = 0; c->u_ctr.ctr[15] = 1; } - c->spec->encrypt (&c->context.c, c->lastiv, c->u_ctr.ctr); + c->spec->encrypt (&c->context.c, c->u_mode.gcm.tagiv, c->u_ctr.ctr); + + gcm_add32_be128 (c->u_ctr.ctr, 1); + + c->unused = 0; c->marks.iv = 1; + return 0; } + static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, byte * outbuf, unsigned int outbuflen, int check) { - if (outbuflen < 16) + if (outbuflen < GCRY_GCM_BLOCK_LEN) return GPG_ERR_BUFFER_TOO_SHORT; + if (c->u_mode.gcm.datalen_over_limits) + return GPG_ERR_INV_LENGTH; if (!c->marks.tag) { - ghash (c, c->u_mode.gcm.u_tag.tag, c->length); - buf_xor (c->u_mode.gcm.u_tag.tag, c->lastiv, c->u_mode.gcm.u_tag.tag, 16); + u32 bitlengths[2][2]; + + /* aad length */ + bitlengths[0][1] = be_bswap32(c->u_mode.gcm.aadlen[0] << 3); + bitlengths[0][0] = be_bswap32((c->u_mode.gcm.aadlen[0] >> 29) | + (c->u_mode.gcm.aadlen[1] << 3)); + /* data length */ + bitlengths[1][1] = be_bswap32(c->u_mode.gcm.datalen[0] << 3); + bitlengths[1][0] = be_bswap32((c->u_mode.gcm.datalen[0] >> 29) | + (c->u_mode.gcm.datalen[1] << 3)); + + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths, + GCRY_GCM_BLOCK_LEN); + buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, + c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); c->marks.tag = 1; + + wipememory(bitlengths, sizeof bitlengths); } if (!check) @@ -726,6 +793,7 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, return 0; } + gcry_err_code_t _gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index a6e6271..9287ef5 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -133,7 +133,6 @@ struct gcry_cipher_handle /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; int unused; /* Number of unused bytes in LASTIV. */ - unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ union { /* Mode specific storage for CCM mode. */ @@ -169,6 +168,13 @@ struct gcry_cipher_handle unsigned char tag[MAX_BLOCKSIZE]; } u_tag; + /* byte counters for GCM */ + u32 aadlen[2]; + u32 datalen[2]; + + /* encrypted tag counter */ + unsigned char tagiv[MAX_BLOCKSIZE]; + /* Pre-calculated table for GCM. */ #ifdef GCM_USE_TABLES #if defined(HAVE_U64_TYPEDEF) && (SIZEOF_UNSIGNED_LONG == 8 \ @@ -181,6 +187,7 @@ struct gcry_cipher_handle #endif #endif + unsigned int datalen_over_limits:1; #ifdef GCM_USE_INTEL_PCLMUL unsigned int use_intel_pclmul:1; #endif @@ -274,9 +281,9 @@ gcry_err_code_t _gcry_cipher_gcm_decrypt /* */ (gcry_cipher_hd_t c, unsigned char *outbuf, unsigned int outbuflen, const unsigned char *inbuf, unsigned int inbuflen); -void _gcry_cipher_gcm_setiv +gcry_err_code_t _gcry_cipher_gcm_setiv /* */ (gcry_cipher_hd_t c, - const unsigned char *iv, unsigned int ivlen); + const unsigned char *iv, size_t ivlen); gcry_err_code_t _gcry_cipher_gcm_authenticate /* */ (gcry_cipher_hd_t c, const unsigned char *aadbuf, unsigned int aadbuflen); @@ -287,4 +294,5 @@ gcry_err_code_t _gcry_cipher_gcm_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); + #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index bba6abb..a3c2c6f 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -600,29 +600,25 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) else c->marks.key = 0; - return gcry_error (ret); } /* Set the IV to be used for the encryption context C to IV with length IVLEN. The length should match the required length. */ -static void +static gcry_err_code_t cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { /* GCM has its own IV handler */ if (c->mode == GCRY_CIPHER_MODE_GCM) - { - _gcry_cipher_gcm_setiv (c, iv, ivlen); - return; - } + return _gcry_cipher_gcm_setiv (c, iv, ivlen); /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ if (c->spec->setiv) { c->spec->setiv (&c->context.c, iv, ivlen); - return; + return 0; } memset (c->u_iv.iv, 0, c->spec->blocksize); @@ -642,6 +638,8 @@ cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) else c->marks.iv = 0; c->unused = 0; + + return 0; } @@ -973,7 +971,7 @@ _gcry_cipher_setiv (gcry_cipher_hd_t hd, const void *iv, size_t ivlen) break; default: - cipher_setiv (hd, iv, ivlen); + rc = cipher_setiv (hd, iv, ivlen); break; } return gpg_error (rc); From jussi.kivilinna at iki.fi Wed Nov 20 18:00:32 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:32 +0200 Subject: [PATCH 07/13] Add aggregated bulk processing for GCM on x86-64 In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170032.11305.70927.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c [__x86_64__] (gfmul_pclmul_aggr4): New. (ghash) [GCM_USE_INTEL_PCLMUL]: Add aggregated bulk processing for __x86_64__. (setupM) [__x86_64__]: Add initialization for aggregated bulk processing. -- Intel Haswell (x86-64): Old: AES GCM enc | 0.990 ns/B 963.3 MiB/s 3.17 c/B GCM dec | 0.982 ns/B 970.9 MiB/s 3.14 c/B GCM auth | 0.711 ns/B 1340.8 MiB/s 2.28 c/B New: AES GCM enc | 0.535 ns/B 1783.8 MiB/s 1.71 c/B GCM dec | 0.531 ns/B 1796.2 MiB/s 1.70 c/B GCM auth | 0.255 ns/B 3736.4 MiB/s 0.817 c/B Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 228 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 219 insertions(+), 9 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index baedc04..fcfa357 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -421,6 +421,131 @@ static inline void gfmul_pclmul(void) ::: "cc" ); } +#ifdef __x86_64__ +static inline void gfmul_pclmul_aggr4(void) +{ + /* Input: + H?: XMM0 X_i : XMM6 + H?: XMM8 X_(i-1) : XMM3 + H?: XMM9 X_(i-2) : XMM2 + H?: XMM10 X_(i-3)?Y_(i-4): XMM1 + Output: + Y_i: XMM1 + Inputs XMM0 stays unmodified. + Input must be converted to little-endian. + */ + asm volatile (/* perform clmul and merge results... */ + "pshufd $78, %%xmm10, %%xmm11\n\t" + "pshufd $78, %%xmm1, %%xmm12\n\t" + "pxor %%xmm10, %%xmm11\n\t" /* xmm11 holds 4:a0+a1 */ + "pxor %%xmm1, %%xmm12\n\t" /* xmm12 holds 4:b0+b1 */ + + "pshufd $78, %%xmm9, %%xmm13\n\t" + "pshufd $78, %%xmm2, %%xmm14\n\t" + "pxor %%xmm9, %%xmm13\n\t" /* xmm13 holds 3:a0+a1 */ + "pxor %%xmm2, %%xmm14\n\t" /* xmm14 holds 3:b0+b1 */ + + "pshufd $78, %%xmm8, %%xmm5\n\t" + "pshufd $78, %%xmm3, %%xmm15\n\t" + "pxor %%xmm8, %%xmm5\n\t" /* xmm1 holds 2:a0+a1 */ + "pxor %%xmm3, %%xmm15\n\t" /* xmm2 holds 2:b0+b1 */ + + "movdqa %%xmm10, %%xmm4\n\t" + "movdqa %%xmm9, %%xmm7\n\t" + "pclmulqdq $0, %%xmm1, %%xmm4\n\t" /* xmm4 holds 4:a0*b0 */ + "pclmulqdq $0, %%xmm2, %%xmm7\n\t" /* xmm7 holds 3:a0*b0 */ + "pclmulqdq $17, %%xmm10, %%xmm1\n\t" /* xmm1 holds 4:a1*b1 */ + "pclmulqdq $17, %%xmm9, %%xmm2\n\t" /* xmm9 holds 3:a1*b1 */ + "pclmulqdq $0, %%xmm11, %%xmm12\n\t" /* xmm12 holds 4:(a0+a1)*(b0+b1) */ + "pclmulqdq $0, %%xmm13, %%xmm14\n\t" /* xmm14 holds 3:(a0+a1)*(b0+b1) */ + + "pshufd $78, %%xmm0, %%xmm10\n\t" + "pshufd $78, %%xmm6, %%xmm11\n\t" + "pxor %%xmm0, %%xmm10\n\t" /* xmm10 holds 1:a0+a1 */ + "pxor %%xmm6, %%xmm11\n\t" /* xmm11 holds 1:b0+b1 */ + + "pxor %%xmm4, %%xmm7\n\t" /* xmm7 holds 3+4:a0*b0 */ + "pxor %%xmm2, %%xmm1\n\t" /* xmm1 holds 3+4:a1*b1 */ + "pxor %%xmm14, %%xmm12\n\t" /* xmm12 holds 3+4:(a0+a1)*(b0+b1) */ + + "movdqa %%xmm8, %%xmm13\n\t" + "pclmulqdq $0, %%xmm3, %%xmm13\n\t" /* xmm13 holds 2:a0*b0 */ + "pclmulqdq $17, %%xmm8, %%xmm3\n\t" /* xmm3 holds 2:a1*b1 */ + "pclmulqdq $0, %%xmm5, %%xmm15\n\t" /* xmm15 holds 2:(a0+a1)*(b0+b1) */ + + "pxor %%xmm13, %%xmm7\n\t" /* xmm7 holds 2+3+4:a0*b0 */ + "pxor %%xmm3, %%xmm1\n\t" /* xmm1 holds 2+3+4:a1*b1 */ + "pxor %%xmm15, %%xmm12\n\t" /* xmm12 holds 2+3+4:(a0+a1)*(b0+b1) */ + + "movdqa %%xmm0, %%xmm3\n\t" + "pclmulqdq $0, %%xmm6, %%xmm3\n\t" /* xmm3 holds 1:a0*b0 */ + "pclmulqdq $17, %%xmm0, %%xmm6\n\t" /* xmm6 holds 1:a1*b1 */ + "movdqa %%xmm11, %%xmm4\n\t" + "pclmulqdq $0, %%xmm10, %%xmm4\n\t" /* xmm4 holds 1:(a0+a1)*(b0+b1) */ + + "pxor %%xmm7, %%xmm3\n\t" /* xmm3 holds 1+2+3+4:a0*b0 */ + "pxor %%xmm1, %%xmm6\n\t" /* xmm6 holds 1+2+3+4:a1*b1 */ + "pxor %%xmm12, %%xmm4\n\t" /* xmm4 holds 1+2+3+4:(a0+a1)*(b0+b1) */ + + /* aggregated reduction... */ + "movdqa %%xmm3, %%xmm5\n\t" + "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */ + "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */ + "movdqa %%xmm4, %%xmm5\n\t" + "psrldq $8, %%xmm4\n\t" + "pslldq $8, %%xmm5\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm4, %%xmm6\n\t" /* holds the result of the + carry-less multiplication of xmm0 + by xmm1 */ + + /* shift the result by one bit position to the left cope for + the fact that bits are reversed */ + "movdqa %%xmm3, %%xmm4\n\t" + "movdqa %%xmm6, %%xmm5\n\t" + "pslld $1, %%xmm3\n\t" + "pslld $1, %%xmm6\n\t" + "psrld $31, %%xmm4\n\t" + "psrld $31, %%xmm5\n\t" + "movdqa %%xmm4, %%xmm1\n\t" + "pslldq $4, %%xmm5\n\t" + "pslldq $4, %%xmm4\n\t" + "psrldq $12, %%xmm1\n\t" + "por %%xmm4, %%xmm3\n\t" + "por %%xmm5, %%xmm6\n\t" + "por %%xmm6, %%xmm1\n\t" + + /* first phase of the reduction */ + "movdqa %%xmm3, %%xmm6\n\t" + "movdqa %%xmm3, %%xmm7\n\t" + "pslld $31, %%xmm6\n\t" /* packed right shifting << 31 */ + "movdqa %%xmm3, %%xmm5\n\t" + "pslld $30, %%xmm7\n\t" /* packed right shifting shift << 30 */ + "pslld $25, %%xmm5\n\t" /* packed right shifting shift << 25 */ + "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */ + "pxor %%xmm5, %%xmm6\n\t" + "movdqa %%xmm6, %%xmm7\n\t" + "pslldq $12, %%xmm6\n\t" + "psrldq $4, %%xmm7\n\t" + "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction + complete */ + + /* second phase of the reduction */ + "movdqa %%xmm3, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm4\n\t" + "psrld $1, %%xmm2\n\t" /* packed left shifting >> 1 */ + "movdqa %%xmm3, %%xmm5\n\t" + "psrld $2, %%xmm4\n\t" /* packed left shifting >> 2 */ + "psrld $7, %%xmm5\n\t" /* packed left shifting >> 7 */ + "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */ + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm7, %%xmm2\n\t" + "pxor %%xmm2, %%xmm3\n\t" + "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */ + :::"cc"); +} +#endif + #endif /*GCM_USE_INTEL_PCLMUL*/ @@ -438,32 +563,74 @@ ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, #ifdef GCM_USE_INTEL_PCLMUL else if (c->u_mode.gcm.use_intel_pclmul) { - /* TODO: Add faster bulk processing (parallel four blocks) for x86-64. */ - static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - /* Preload hash. */ + /* Preload hash and H1. */ asm volatile ("movdqu %[hash], %%xmm1\n\t" + "movdqa %[hsub], %%xmm0\n\t" "pshufb %[be_mask], %%xmm1\n\t" /* be => le */ : - : [hash] "m" (*result), [be_mask] "m" (*be_mask)); + : [hash] "m" (*result), [be_mask] "m" (*be_mask), + [hsub] "m" (*c->u_iv.iv)); + +#ifdef __x86_64__ + if (nblocks >= 4) + { + do + { + asm volatile ("movdqa %[be_mask], %%xmm4\n\t" + "movdqu 0*16(%[buf]), %%xmm5\n\t" + "movdqu 1*16(%[buf]), %%xmm2\n\t" + "movdqu 2*16(%[buf]), %%xmm3\n\t" + "movdqu 3*16(%[buf]), %%xmm6\n\t" + "pshufb %%xmm4, %%xmm5\n\t" /* be => le */ + + /* Load H2, H3, H4. */ + "movdqu 2*16(%[h_234]), %%xmm10\n\t" + "movdqu 1*16(%[h_234]), %%xmm9\n\t" + "movdqu 0*16(%[h_234]), %%xmm8\n\t" + + "pxor %%xmm5, %%xmm1\n\t" + "pshufb %%xmm4, %%xmm2\n\t" /* be => le */ + "pshufb %%xmm4, %%xmm3\n\t" /* be => le */ + "pshufb %%xmm4, %%xmm6\n\t" /* be => le */ + : + : [buf] "r" (buf), [be_mask] "m" (*be_mask), + [h_234] "r" (c->u_mode.gcm.gcm_table)); + + gfmul_pclmul_aggr4 (); + + buf += 4 * blocksize; + nblocks -= 4; + } + while (nblocks >= 4); + + /* Clear used x86-64/XMM registers. */ + asm volatile( "pxor %%xmm8, %%xmm8\n\t" + "pxor %%xmm9, %%xmm9\n\t" + "pxor %%xmm10, %%xmm10\n\t" + "pxor %%xmm11, %%xmm11\n\t" + "pxor %%xmm12, %%xmm12\n\t" + "pxor %%xmm13, %%xmm13\n\t" + "pxor %%xmm14, %%xmm14\n\t" + "pxor %%xmm15, %%xmm15\n\t" + ::: "cc" ); + } +#endif - do + while (nblocks--) { asm volatile ("movdqu %[buf], %%xmm2\n\t" - "movdqa %[hsub], %%xmm0\n\t" "pshufb %[be_mask], %%xmm2\n\t" /* be => le */ "pxor %%xmm2, %%xmm1\n\t" : - : [buf] "m" (*buf), [be_mask] "m" (*be_mask), - [hsub] "m" (*c->u_iv.iv)); + : [buf] "m" (*buf), [be_mask] "m" (*be_mask)); gfmul_pclmul (); buf += blocksize; } - while (--nblocks); /* Store hash. */ asm volatile ("pshufb %[be_mask], %%xmm1\n\t" /* be => le */ @@ -511,6 +678,49 @@ setupM (gcry_cipher_hd_t c, byte *h) tmp[0] = buf_get_be64(c->u_iv.iv + 8); tmp[1] = buf_get_be64(c->u_iv.iv + 0); buf_cpy (c->u_iv.iv, tmp, GCRY_GCM_BLOCK_LEN); + +#ifdef __x86_64__ + asm volatile ("movdqu %[h_1], %%xmm0\n\t" + "movdqa %%xmm0, %%xmm1\n\t" + : + : [h_1] "m" (*tmp)); + + gfmul_pclmul (); /* H?H => H? */ + + asm volatile ("movdqu %%xmm1, 0*16(%[h_234])\n\t" + "movdqa %%xmm1, %%xmm8\n\t" + : + : [h_234] "r" (c->u_mode.gcm.gcm_table) + : "memory"); + + gfmul_pclmul (); /* H?H? => H? */ + + asm volatile ("movdqa %%xmm8, %%xmm0\n\t" + "movdqu %%xmm1, 1*16(%[h_234])\n\t" + "movdqa %%xmm8, %%xmm1\n\t" + : + : [h_234] "r" (c->u_mode.gcm.gcm_table) + : "memory"); + + gfmul_pclmul (); /* H??H? => H? */ + + asm volatile ("movdqu %%xmm1, 2*16(%[h_234])\n\t" + : + : [h_234] "r" (c->u_mode.gcm.gcm_table) + : "memory"); + + /* Clear used registers. */ + asm volatile( "pxor %%xmm0, %%xmm0\n\t" + "pxor %%xmm1, %%xmm1\n\t" + "pxor %%xmm2, %%xmm2\n\t" + "pxor %%xmm3, %%xmm3\n\t" + "pxor %%xmm4, %%xmm4\n\t" + "pxor %%xmm5, %%xmm5\n\t" + "pxor %%xmm6, %%xmm6\n\t" + "pxor %%xmm7, %%xmm7\n\t" + "pxor %%xmm8, %%xmm8\n\t" + ::: "cc" ); +#endif } #endif else From jussi.kivilinna at iki.fi Wed Nov 20 18:00:52 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:52 +0200 Subject: [PATCH 11/13] GCM: Use size_t for buffer sizes In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170052.11305.7701.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (ghash, gcm_bytecounter_add, do_ghash_buf) (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt) (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_geniv) (_gcry_cipher_gcm_tag): Use size_t for buffer lengths. * cipher/cipher-internal.h (_gcry_cipher_gcm_encrypt) (_gcry_cipher_gcm_decrypt, _gcry_cipher_gcm_authenticate): Use size_t for buffer lengths. -- Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 30 ++++++++++++++++++------------ cipher/cipher-internal.h | 11 ++++++----- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 0e97c67..62855b1 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -559,7 +559,7 @@ static inline void gfmul_pclmul_aggr4(void) static unsigned int ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, - unsigned int nblocks) + size_t nblocks) { const unsigned int blocksize = GCRY_GCM_BLOCK_LEN; unsigned int burn; @@ -743,8 +743,14 @@ setupM (gcry_cipher_hd_t c, byte *h) static inline void -gcm_bytecounter_add (u32 ctr[2], u32 add) +gcm_bytecounter_add (u32 ctr[2], size_t add) { + if (sizeof(add) > sizeof(u32)) + { + u32 high_add = ((add >> 31) >> 1) & 0xffffffff; + ctr[1] += high_add; + } + ctr[0] += add; if (ctr[0] >= add) return; @@ -801,11 +807,11 @@ gcm_check_aadlen_or_ivlen (u32 ctr[2]) static void do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, - unsigned int buflen) + size_t buflen) { unsigned char tmp[MAX_BLOCKSIZE]; unsigned int blocksize = GCRY_GCM_BLOCK_LEN; - unsigned int nblocks; + size_t nblocks; unsigned int burn = 0; nblocks = buflen / blocksize; @@ -832,8 +838,8 @@ do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, gcry_err_code_t _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { static const unsigned char zerobuf[MAX_BLOCKSIZE]; gcry_err_code_t err; @@ -872,8 +878,8 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, - byte *outbuf, unsigned int outbuflen, - const byte *inbuf, unsigned int inbuflen) + byte *outbuf, size_t outbuflen, + const byte *inbuf, size_t inbuflen) { static const unsigned char zerobuf[MAX_BLOCKSIZE]; @@ -904,7 +910,7 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, gcry_err_code_t _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, - const byte * aadbuf, unsigned int aadbuflen) + const byte * aadbuf, size_t aadbuflen) { static const unsigned char zerobuf[MAX_BLOCKSIZE]; @@ -1015,8 +1021,8 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) #if 0 && TODO void _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, - byte *ivout, unsigned int ivoutlen, const byte *nonce, - unsigned int noncelen) + byte *ivout, size_t ivoutlen, const byte *nonce, + size_t noncelen) { /* nonce: user provided part (might be null) */ /* noncelen: check if proper length (if nonce not null) */ @@ -1047,7 +1053,7 @@ _gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, - byte * outbuf, unsigned int outbuflen, int check) + byte * outbuf, size_t outbuflen, int check) { if (outbuflen < GCRY_GCM_BLOCK_LEN) return GPG_ERR_BUFFER_TOO_SHORT; diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index fced20c..225f699 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -273,21 +273,22 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); + /*-- cipher-gcm.c --*/ gcry_err_code_t _gcry_cipher_gcm_encrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_gcm_decrypt /* */ (gcry_cipher_hd_t c, - unsigned char *outbuf, unsigned int outbuflen, - const unsigned char *inbuf, unsigned int inbuflen); + unsigned char *outbuf, size_t outbuflen, + const unsigned char *inbuf, size_t inbuflen); gcry_err_code_t _gcry_cipher_gcm_setiv /* */ (gcry_cipher_hd_t c, const unsigned char *iv, size_t ivlen); gcry_err_code_t _gcry_cipher_gcm_authenticate /* */ (gcry_cipher_hd_t c, - const unsigned char *aadbuf, unsigned int aadbuflen); + const unsigned char *aadbuf, size_t aadbuflen); gcry_err_code_t _gcry_cipher_gcm_get_tag /* */ (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen); From jussi.kivilinna at iki.fi Wed Nov 20 18:00:12 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:12 +0200 Subject: [PATCH 03/13] GCM: GHASH optimizations In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170012.11305.11188.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c [GCM_USE_TABLES] (gcmR, ghash): Replace with new. [GCM_USE_TABLES] [GCM_TABLES_USE_U64] (bshift, fillM, do_ghash): New. [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (bshift, fillM): Replace with new. [GCM_USE_TABLES] [!GCM_TABLES_USE_U64] (do_ghash): New. (_gcry_cipher_gcm_tag): Remove extra memcpy to outbuf and use buf_eq_const for comparing authentication tag. * cipher/cipher-internal.h (gcry_cipher_handle): Different 'gcm_table' for 32-bit and 64-bit platforms. -- Patch improves GHASH speed. Intel Haswell (x86-64): Old: GCM auth | 26.22 ns/B 36.38 MiB/s 83.89 c/B New: GCM auth | 3.18 ns/B 300.0 MiB/s 10.17 c/B Intel Haswell (mingw32): Old: GCM auth | 27.27 ns/B 34.97 MiB/s 87.27 c/B New: GCM auth | 7.58 ns/B 125.7 MiB/s 24.27 c/B Cortex-A8: Old: GCM auth | 231.4 ns/B 4.12 MiB/s 233.3 c/B New: GCM auth | 30.82 ns/B 30.94 MiB/s 31.07 c/B Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 333 +++++++++++++++++++++++++++++++--------------- cipher/cipher-internal.h | 9 + 2 files changed, 230 insertions(+), 112 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index b6c50bf..d7fc0d8 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -30,134 +30,251 @@ #include "./cipher-internal.h" #ifdef GCM_USE_TABLES -static const byte gcmR[256][2] = { - {0x00, 0x00,}, {0x01, 0xc2,}, {0x03, 0x84,}, {0x02, 0x46,}, - {0x07, 0x08,}, {0x06, 0xca,}, {0x04, 0x8c,}, {0x05, 0x4e,}, - {0x0e, 0x10,}, {0x0f, 0xd2,}, {0x0d, 0x94,}, {0x0c, 0x56,}, - {0x09, 0x18,}, {0x08, 0xda,}, {0x0a, 0x9c,}, {0x0b, 0x5e,}, - {0x1c, 0x20,}, {0x1d, 0xe2,}, {0x1f, 0xa4,}, {0x1e, 0x66,}, - {0x1b, 0x28,}, {0x1a, 0xea,}, {0x18, 0xac,}, {0x19, 0x6e,}, - {0x12, 0x30,}, {0x13, 0xf2,}, {0x11, 0xb4,}, {0x10, 0x76,}, - {0x15, 0x38,}, {0x14, 0xfa,}, {0x16, 0xbc,}, {0x17, 0x7e,}, - {0x38, 0x40,}, {0x39, 0x82,}, {0x3b, 0xc4,}, {0x3a, 0x06,}, - {0x3f, 0x48,}, {0x3e, 0x8a,}, {0x3c, 0xcc,}, {0x3d, 0x0e,}, - {0x36, 0x50,}, {0x37, 0x92,}, {0x35, 0xd4,}, {0x34, 0x16,}, - {0x31, 0x58,}, {0x30, 0x9a,}, {0x32, 0xdc,}, {0x33, 0x1e,}, - {0x24, 0x60,}, {0x25, 0xa2,}, {0x27, 0xe4,}, {0x26, 0x26,}, - {0x23, 0x68,}, {0x22, 0xaa,}, {0x20, 0xec,}, {0x21, 0x2e,}, - {0x2a, 0x70,}, {0x2b, 0xb2,}, {0x29, 0xf4,}, {0x28, 0x36,}, - {0x2d, 0x78,}, {0x2c, 0xba,}, {0x2e, 0xfc,}, {0x2f, 0x3e,}, - {0x70, 0x80,}, {0x71, 0x42,}, {0x73, 0x04,}, {0x72, 0xc6,}, - {0x77, 0x88,}, {0x76, 0x4a,}, {0x74, 0x0c,}, {0x75, 0xce,}, - {0x7e, 0x90,}, {0x7f, 0x52,}, {0x7d, 0x14,}, {0x7c, 0xd6,}, - {0x79, 0x98,}, {0x78, 0x5a,}, {0x7a, 0x1c,}, {0x7b, 0xde,}, - {0x6c, 0xa0,}, {0x6d, 0x62,}, {0x6f, 0x24,}, {0x6e, 0xe6,}, - {0x6b, 0xa8,}, {0x6a, 0x6a,}, {0x68, 0x2c,}, {0x69, 0xee,}, - {0x62, 0xb0,}, {0x63, 0x72,}, {0x61, 0x34,}, {0x60, 0xf6,}, - {0x65, 0xb8,}, {0x64, 0x7a,}, {0x66, 0x3c,}, {0x67, 0xfe,}, - {0x48, 0xc0,}, {0x49, 0x02,}, {0x4b, 0x44,}, {0x4a, 0x86,}, - {0x4f, 0xc8,}, {0x4e, 0x0a,}, {0x4c, 0x4c,}, {0x4d, 0x8e,}, - {0x46, 0xd0,}, {0x47, 0x12,}, {0x45, 0x54,}, {0x44, 0x96,}, - {0x41, 0xd8,}, {0x40, 0x1a,}, {0x42, 0x5c,}, {0x43, 0x9e,}, - {0x54, 0xe0,}, {0x55, 0x22,}, {0x57, 0x64,}, {0x56, 0xa6,}, - {0x53, 0xe8,}, {0x52, 0x2a,}, {0x50, 0x6c,}, {0x51, 0xae,}, - {0x5a, 0xf0,}, {0x5b, 0x32,}, {0x59, 0x74,}, {0x58, 0xb6,}, - {0x5d, 0xf8,}, {0x5c, 0x3a,}, {0x5e, 0x7c,}, {0x5f, 0xbe,}, - {0xe1, 0x00,}, {0xe0, 0xc2,}, {0xe2, 0x84,}, {0xe3, 0x46,}, - {0xe6, 0x08,}, {0xe7, 0xca,}, {0xe5, 0x8c,}, {0xe4, 0x4e,}, - {0xef, 0x10,}, {0xee, 0xd2,}, {0xec, 0x94,}, {0xed, 0x56,}, - {0xe8, 0x18,}, {0xe9, 0xda,}, {0xeb, 0x9c,}, {0xea, 0x5e,}, - {0xfd, 0x20,}, {0xfc, 0xe2,}, {0xfe, 0xa4,}, {0xff, 0x66,}, - {0xfa, 0x28,}, {0xfb, 0xea,}, {0xf9, 0xac,}, {0xf8, 0x6e,}, - {0xf3, 0x30,}, {0xf2, 0xf2,}, {0xf0, 0xb4,}, {0xf1, 0x76,}, - {0xf4, 0x38,}, {0xf5, 0xfa,}, {0xf7, 0xbc,}, {0xf6, 0x7e,}, - {0xd9, 0x40,}, {0xd8, 0x82,}, {0xda, 0xc4,}, {0xdb, 0x06,}, - {0xde, 0x48,}, {0xdf, 0x8a,}, {0xdd, 0xcc,}, {0xdc, 0x0e,}, - {0xd7, 0x50,}, {0xd6, 0x92,}, {0xd4, 0xd4,}, {0xd5, 0x16,}, - {0xd0, 0x58,}, {0xd1, 0x9a,}, {0xd3, 0xdc,}, {0xd2, 0x1e,}, - {0xc5, 0x60,}, {0xc4, 0xa2,}, {0xc6, 0xe4,}, {0xc7, 0x26,}, - {0xc2, 0x68,}, {0xc3, 0xaa,}, {0xc1, 0xec,}, {0xc0, 0x2e,}, - {0xcb, 0x70,}, {0xca, 0xb2,}, {0xc8, 0xf4,}, {0xc9, 0x36,}, - {0xcc, 0x78,}, {0xcd, 0xba,}, {0xcf, 0xfc,}, {0xce, 0x3e,}, - {0x91, 0x80,}, {0x90, 0x42,}, {0x92, 0x04,}, {0x93, 0xc6,}, - {0x96, 0x88,}, {0x97, 0x4a,}, {0x95, 0x0c,}, {0x94, 0xce,}, - {0x9f, 0x90,}, {0x9e, 0x52,}, {0x9c, 0x14,}, {0x9d, 0xd6,}, - {0x98, 0x98,}, {0x99, 0x5a,}, {0x9b, 0x1c,}, {0x9a, 0xde,}, - {0x8d, 0xa0,}, {0x8c, 0x62,}, {0x8e, 0x24,}, {0x8f, 0xe6,}, - {0x8a, 0xa8,}, {0x8b, 0x6a,}, {0x89, 0x2c,}, {0x88, 0xee,}, - {0x83, 0xb0,}, {0x82, 0x72,}, {0x80, 0x34,}, {0x81, 0xf6,}, - {0x84, 0xb8,}, {0x85, 0x7a,}, {0x87, 0x3c,}, {0x86, 0xfe,}, - {0xa9, 0xc0,}, {0xa8, 0x02,}, {0xaa, 0x44,}, {0xab, 0x86,}, - {0xae, 0xc8,}, {0xaf, 0x0a,}, {0xad, 0x4c,}, {0xac, 0x8e,}, - {0xa7, 0xd0,}, {0xa6, 0x12,}, {0xa4, 0x54,}, {0xa5, 0x96,}, - {0xa0, 0xd8,}, {0xa1, 0x1a,}, {0xa3, 0x5c,}, {0xa2, 0x9e,}, - {0xb5, 0xe0,}, {0xb4, 0x22,}, {0xb6, 0x64,}, {0xb7, 0xa6,}, - {0xb2, 0xe8,}, {0xb3, 0x2a,}, {0xb1, 0x6c,}, {0xb0, 0xae,}, - {0xbb, 0xf0,}, {0xba, 0x32,}, {0xb8, 0x74,}, {0xb9, 0xb6,}, - {0xbc, 0xf8,}, {0xbd, 0x3a,}, {0xbf, 0x7c,}, {0xbe, 0xbe,}, +static const u16 gcmR[256] = { + 0x0000, 0x01c2, 0x0384, 0x0246, 0x0708, 0x06ca, 0x048c, 0x054e, + 0x0e10, 0x0fd2, 0x0d94, 0x0c56, 0x0918, 0x08da, 0x0a9c, 0x0b5e, + 0x1c20, 0x1de2, 0x1fa4, 0x1e66, 0x1b28, 0x1aea, 0x18ac, 0x196e, + 0x1230, 0x13f2, 0x11b4, 0x1076, 0x1538, 0x14fa, 0x16bc, 0x177e, + 0x3840, 0x3982, 0x3bc4, 0x3a06, 0x3f48, 0x3e8a, 0x3ccc, 0x3d0e, + 0x3650, 0x3792, 0x35d4, 0x3416, 0x3158, 0x309a, 0x32dc, 0x331e, + 0x2460, 0x25a2, 0x27e4, 0x2626, 0x2368, 0x22aa, 0x20ec, 0x212e, + 0x2a70, 0x2bb2, 0x29f4, 0x2836, 0x2d78, 0x2cba, 0x2efc, 0x2f3e, + 0x7080, 0x7142, 0x7304, 0x72c6, 0x7788, 0x764a, 0x740c, 0x75ce, + 0x7e90, 0x7f52, 0x7d14, 0x7cd6, 0x7998, 0x785a, 0x7a1c, 0x7bde, + 0x6ca0, 0x6d62, 0x6f24, 0x6ee6, 0x6ba8, 0x6a6a, 0x682c, 0x69ee, + 0x62b0, 0x6372, 0x6134, 0x60f6, 0x65b8, 0x647a, 0x663c, 0x67fe, + 0x48c0, 0x4902, 0x4b44, 0x4a86, 0x4fc8, 0x4e0a, 0x4c4c, 0x4d8e, + 0x46d0, 0x4712, 0x4554, 0x4496, 0x41d8, 0x401a, 0x425c, 0x439e, + 0x54e0, 0x5522, 0x5764, 0x56a6, 0x53e8, 0x522a, 0x506c, 0x51ae, + 0x5af0, 0x5b32, 0x5974, 0x58b6, 0x5df8, 0x5c3a, 0x5e7c, 0x5fbe, + 0xe100, 0xe0c2, 0xe284, 0xe346, 0xe608, 0xe7ca, 0xe58c, 0xe44e, + 0xef10, 0xeed2, 0xec94, 0xed56, 0xe818, 0xe9da, 0xeb9c, 0xea5e, + 0xfd20, 0xfce2, 0xfea4, 0xff66, 0xfa28, 0xfbea, 0xf9ac, 0xf86e, + 0xf330, 0xf2f2, 0xf0b4, 0xf176, 0xf438, 0xf5fa, 0xf7bc, 0xf67e, + 0xd940, 0xd882, 0xdac4, 0xdb06, 0xde48, 0xdf8a, 0xddcc, 0xdc0e, + 0xd750, 0xd692, 0xd4d4, 0xd516, 0xd058, 0xd19a, 0xd3dc, 0xd21e, + 0xc560, 0xc4a2, 0xc6e4, 0xc726, 0xc268, 0xc3aa, 0xc1ec, 0xc02e, + 0xcb70, 0xcab2, 0xc8f4, 0xc936, 0xcc78, 0xcdba, 0xcffc, 0xce3e, + 0x9180, 0x9042, 0x9204, 0x93c6, 0x9688, 0x974a, 0x950c, 0x94ce, + 0x9f90, 0x9e52, 0x9c14, 0x9dd6, 0x9898, 0x995a, 0x9b1c, 0x9ade, + 0x8da0, 0x8c62, 0x8e24, 0x8fe6, 0x8aa8, 0x8b6a, 0x892c, 0x88ee, + 0x83b0, 0x8272, 0x8034, 0x81f6, 0x84b8, 0x857a, 0x873c, 0x86fe, + 0xa9c0, 0xa802, 0xaa44, 0xab86, 0xaec8, 0xaf0a, 0xad4c, 0xac8e, + 0xa7d0, 0xa612, 0xa454, 0xa596, 0xa0d8, 0xa11a, 0xa35c, 0xa29e, + 0xb5e0, 0xb422, 0xb664, 0xb7a6, 0xb2e8, 0xb32a, 0xb16c, 0xb0ae, + 0xbbf0, 0xba32, 0xb874, 0xb9b6, 0xbcf8, 0xbd3a, 0xbf7c, 0xbebe, }; -static unsigned -bshift (unsigned char *b) +#ifdef GCM_TABLES_USE_U64 +static void +bshift (u64 * b0, u64 * b1) +{ + u64 t[2], mask; + + t[0] = *b0; + t[1] = *b1; + mask = t[1] & 1 ? 0xe1 : 0; + mask <<= 56; + + *b1 = (t[1] >> 1) ^ (t[0] << 63); + *b0 = (t[0] >> 1) ^ mask; +} + +static void +fillM (unsigned char *h, u64 * M) +{ + int i, j; + + M[0 + 0] = 0; + M[0 + 16] = 0; + + M[8 + 0] = buf_get_be64 (h + 0); + M[8 + 16] = buf_get_be64 (h + 8); + + for (i = 4; i > 0; i /= 2) + { + M[i + 0] = M[2 * i + 0]; + M[i + 16] = M[2 * i + 16]; + + bshift (&M[i], &M[i + 16]); + } + + for (i = 2; i < 16; i *= 2) + for (j = 1; j < i; j++) + { + M[(i + j) + 0] = M[i + 0] ^ M[j + 0]; + M[(i + j) + 16] = M[i + 16] ^ M[j + 16]; + } +} + +static void +do_ghash (unsigned char *result, const unsigned char *buf, const u64 * gcmM) { - unsigned char c; + u64 V[2]; + u64 tmp[2]; + const u64 *M; + u64 T; + u32 A; int i; - c = b[15] & 1; - for (i = 15; i > 0; i--) + + buf_xor (V, result, buf, 16); + V[0] = be_bswap64 (V[0]); + V[1] = be_bswap64 (V[1]); + + /* First round can be manually tweaked based on fact that 'tmp' is zero. */ + i = 15; + + M = &gcmM[(V[1] & 0xf)]; + V[1] >>= 4; + tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48); + tmp[1] = (M[16] >> 4) ^ (M[0] << 60); + tmp[0] ^= gcmM[(V[1] & 0xf) + 0]; + tmp[1] ^= gcmM[(V[1] & 0xf) + 16]; + V[1] >>= 4; + + --i; + while (1) { - b[i] = (b[i] >> 1) | (b[i - 1] << 7); + M = &gcmM[(V[1] & 0xf)]; + V[1] >>= 4; + + A = tmp[1] & 0xff; + T = tmp[0]; + tmp[0] = (T >> 8) ^ ((u64) gcmR[A] << 48) ^ gcmM[(V[1] & 0xf) + 0]; + tmp[1] = (T << 56) ^ (tmp[1] >> 8) ^ gcmM[(V[1] & 0xf) + 16]; + + tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[16] & 0xf) << 4] << 48); + tmp[1] ^= (M[16] >> 4) ^ (M[0] << 60); + + if (i == 0) + break; + else if (i == 8) + V[1] = V[0]; + else + V[1] >>= 4; + --i; } - b[i] >>= 1; - return c; + + buf_put_be64 (result + 0, tmp[0]); + buf_put_be64 (result + 8, tmp[1]); +} + +#else + +static void +bshift (u32 * M, int i) +{ + u32 t[4], mask; + + t[0] = M[i * 4 + 0]; + t[1] = M[i * 4 + 1]; + t[2] = M[i * 4 + 2]; + t[3] = M[i * 4 + 3]; + mask = t[3] & 1 ? 0xe1 : 0; + + M[i * 4 + 3] = (t[3] >> 1) ^ (t[2] << 31); + M[i * 4 + 2] = (t[2] >> 1) ^ (t[1] << 31); + M[i * 4 + 1] = (t[1] >> 1) ^ (t[0] << 31); + M[i * 4 + 0] = (t[0] >> 1) ^ (mask << 24); } static void -fillM (unsigned char *h, unsigned char *M) +fillM (unsigned char *h, u32 * M) { int i, j; - memset (&M[0 * 16], 0, 16); - memcpy (&M[8 * 16], h, 16); + + M[0 * 4 + 0] = 0; + M[0 * 4 + 1] = 0; + M[0 * 4 + 2] = 0; + M[0 * 4 + 3] = 0; + + M[8 * 4 + 0] = buf_get_be32 (h + 0); + M[8 * 4 + 1] = buf_get_be32 (h + 4); + M[8 * 4 + 2] = buf_get_be32 (h + 8); + M[8 * 4 + 3] = buf_get_be32 (h + 12); + for (i = 4; i > 0; i /= 2) { - memcpy (&M[i * 16], &M[2 * i * 16], 16); - if (bshift (&M[i * 16])) - M[i * 16 + 0] ^= 0xe1; + M[i * 4 + 0] = M[2 * i * 4 + 0]; + M[i * 4 + 1] = M[2 * i * 4 + 1]; + M[i * 4 + 2] = M[2 * i * 4 + 2]; + M[i * 4 + 3] = M[2 * i * 4 + 3]; + + bshift (M, i); } + for (i = 2; i < 16; i *= 2) for (j = 1; j < i; j++) - buf_xor (&M[(i + j) * 16], &M[i * 16], &M[j * 16], 16); + { + M[(i + j) * 4 + 0] = M[i * 4 + 0] ^ M[j * 4 + 0]; + M[(i + j) * 4 + 1] = M[i * 4 + 1] ^ M[j * 4 + 1]; + M[(i + j) * 4 + 2] = M[i * 4 + 2] ^ M[j * 4 + 2]; + M[(i + j) * 4 + 3] = M[i * 4 + 3] ^ M[j * 4 + 3]; + } } static void -ghash (unsigned char *result, const unsigned char *buf, - const unsigned char *gcmM) +do_ghash (unsigned char *result, const unsigned char *buf, const u32 * gcmM) { - unsigned char V[16]; + byte V[16]; + u32 tmp[4]; + u32 v; + const u32 *M, *m; + u32 T[3]; int i; - buf_xor (V, result, buf, 16); + buf_xor (V, result, buf, 16); /* V is big-endian */ + + /* First round can be manually tweaked based on fact that 'tmp' is zero. */ + i = 15; - memset (result, 0, 16); + v = V[i]; + M = &gcmM[(v & 0xf) * 4]; + v = (v & 0xf0) >> 4; + m = &gcmM[v * 4]; + v = V[--i]; - for (i = 15; i >= 0; i--) + tmp[0] = (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16) ^ m[0]; + tmp[1] = (M[1] >> 4) ^ (M[0] << 28) ^ m[1]; + tmp[2] = (M[2] >> 4) ^ (M[1] << 28) ^ m[2]; + tmp[3] = (M[3] >> 4) ^ (M[2] << 28) ^ m[3]; + + while (1) { - byte A = result[15]; - byte T[16]; - int j; - const byte *M = &gcmM[(V[i] & 0xf) * 16]; - - memmove (result + 1, result, 15); - result[0] = gcmR[A][0]; - result[1] ^= gcmR[A][1]; - - T[0] = M[0] >> 4; - for (j = 1; j < 16; j++) - T[j] = (M[j] >> 4) | (M[j - 1] << 4); - T[0] ^= gcmR[(M[15] & 0xf) << 4][0]; - T[1] ^= gcmR[(M[15] & 0xf) << 4][1]; - buf_xor (T, T, &gcmM[(V[i] >> 4) * 16], 16); - buf_xor (result, result, T, 16); + M = &gcmM[(v & 0xf) * 4]; + v = (v & 0xf0) >> 4; + m = &gcmM[v * 4]; + + T[0] = tmp[0]; + T[1] = tmp[1]; + T[2] = tmp[2]; + tmp[0] = (T[0] >> 8) ^ ((u32) gcmR[tmp[3] & 0xff] << 16) ^ m[0]; + tmp[1] = (T[0] << 24) ^ (tmp[1] >> 8) ^ m[1]; + tmp[2] = (T[1] << 24) ^ (tmp[2] >> 8) ^ m[2]; + tmp[3] = (T[2] << 24) ^ (tmp[3] >> 8) ^ m[3]; + + tmp[0] ^= (M[0] >> 4) ^ ((u64) gcmR[(M[3] << 4) & 0xf0] << 16); + tmp[1] ^= (M[1] >> 4) ^ (M[0] << 28); + tmp[2] ^= (M[2] >> 4) ^ (M[1] << 28); + tmp[3] ^= (M[3] >> 4) ^ (M[2] << 28); + + if (i == 0) + break; + + v = V[--i]; } + + buf_put_be32 (result + 0, tmp[0]); + buf_put_be32 (result + 4, tmp[1]); + buf_put_be32 (result + 8, tmp[2]); + buf_put_be32 (result + 12, tmp[3]); +} +#endif + +static void +ghash (unsigned char *result, const unsigned char *buf, const void *gcmM) +{ + do_ghash (result, buf, gcmM); } #define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); @@ -447,7 +564,7 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16); c->marks.tag = 1; } - memcpy (outbuf, c->u_tag.tag, 16); + if (!check) { memcpy (outbuf, c->u_tag.tag, outbuflen); @@ -455,13 +572,8 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, } else { - int diff, i; - - /* Constant-time compare. */ - for (i = 0, diff = 0; i < outbuflen; i++) - diff -= ! !(outbuf[i] - c->u_tag.tag[i]); - - return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + return buf_eq_const(outbuf, c->u_tag.tag, outbuflen) ? + GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } return 0; @@ -474,7 +586,6 @@ _gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, return _gcry_cipher_gcm_tag (c, outtag, taglen, 0); } - gcry_err_code_t _gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 7da9c68..b4d0ff9 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -129,7 +129,14 @@ struct gcry_cipher_handle int unused; /* Number of unused bytes in LASTIV. */ unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ #ifdef GCM_USE_TABLES - unsigned char gcm_table[16 * 16]; /* pre-calculated table for GCM */ + #if defined(HAVE_U64_TYPEDEF) && \ + (SIZEOF_UNSIGNED_LONG == 8 || defined(__x86_64__)) + #define GCM_TABLES_USE_U64 1 + u64 gcm_table[2 * 16]; /* pre-calculated table for GCM */ + #else + #undef GCM_TABLES_USE_U64 + u32 gcm_table[4 * 16]; /* pre-calculated table for GCM */ + #endif #endif union { From jussi.kivilinna at iki.fi Wed Nov 20 18:00:37 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:37 +0200 Subject: [PATCH 08/13] GCM: Add stack burning In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170037.11305.3085.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (do_ghash, ghash): Return stack burn depth. (setupM): Wipe 'tmp' buffer. (do_ghash_buf): Wipe 'tmp' buffer and add stack burning. -- Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index fcfa357..cf666ab 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -108,7 +108,7 @@ do_fillM (unsigned char *h, u64 *M) } } -static inline void +static inline unsigned int do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) { u64 V[2]; @@ -158,6 +158,9 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) buf_put_be64 (result + 0, tmp[0]); buf_put_be64 (result + 8, tmp[1]); + + return (sizeof(V) + sizeof(T) + sizeof(tmp) + + sizeof(int)*2 + sizeof(void*)*5); } #else @@ -214,7 +217,7 @@ do_fillM (unsigned char *h, u32 *M) } } -static inline void +static inline unsigned int do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) { byte V[16]; @@ -269,6 +272,9 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) buf_put_be32 (result + 4, tmp[1]); buf_put_be32 (result + 8, tmp[2]); buf_put_be32 (result + 12, tmp[3]); + + return (sizeof(V) + sizeof(T) + sizeof(tmp) + + sizeof(int)*2 + sizeof(void*)*6); } #endif /* !HAVE_U64_TYPEDEF || SIZEOF_UNSIGNED_LONG != 8 */ @@ -291,7 +297,7 @@ bshift (unsigned long *b) return c; } -static void +static unsigned int do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) { unsigned long V[4]; @@ -333,6 +339,8 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) result[i + 3] = p[0]; } #endif + + return (sizeof(V) + sizeof(T) + sizeof(int)*2 + sizeof(void*)*5); } #define fillM(c, h) do { } while (0) @@ -549,14 +557,15 @@ static inline void gfmul_pclmul_aggr4(void) #endif /*GCM_USE_INTEL_PCLMUL*/ -static void +static unsigned int ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, unsigned int nblocks) { const unsigned int blocksize = GCRY_GCM_BLOCK_LEN; + unsigned int burn; if (nblocks == 0) - return; + return 0; if (0) ; @@ -648,17 +657,20 @@ ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, "pxor %%xmm6, %%xmm6\n\t" "pxor %%xmm7, %%xmm7\n\t" ::: "cc" ); + burn = 0; } #endif else { while (nblocks) { - GHASH (c, result, buf); + burn = GHASH (c, result, buf); buf += blocksize; nblocks--; } } + + return burn + (burn ? 5*sizeof(void*) : 0); } @@ -721,6 +733,8 @@ setupM (gcry_cipher_hd_t c, byte *h) "pxor %%xmm8, %%xmm8\n\t" ::: "cc" ); #endif + + wipememory (tmp, sizeof(tmp)); } #endif else @@ -792,12 +806,13 @@ do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, unsigned char tmp[MAX_BLOCKSIZE]; unsigned int blocksize = GCRY_GCM_BLOCK_LEN; unsigned int nblocks; + unsigned int burn = 0; nblocks = buflen / blocksize; if (nblocks) { - ghash (c, hash, buf, nblocks); + burn = ghash (c, hash, buf, nblocks); buf += blocksize * nblocks; buflen -= blocksize * nblocks; } @@ -806,10 +821,12 @@ do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, { buf_cpy (tmp, buf, buflen); memset (tmp + buflen, 0, blocksize - buflen); - ghash (c, hash, tmp, 1); + burn = ghash (c, hash, tmp, 1); + wipememory (tmp, sizeof(tmp)); } - /* TODO: burn stack */ + if (burn) + _gcry_burn_stack (burn); } From jussi.kivilinna at iki.fi Wed Nov 20 18:01:02 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:01:02 +0200 Subject: [PATCH 13/13] GCM: Move gcm_table initialization to setkey In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170102.11305.5288.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c: Change all 'c->u_iv.iv' to 'c->u_mode.gcm.u_ghash_key.key'. (_gcry_cipher_gcm_setkey): New. (_gcry_cipher_gcm_initiv): Move ghash initialization to function above. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.gcm.u_ghash_key'; Reorder 'u_mode.gcm' members for partial clearing in gcry_cipher_reset. (_gcry_cipher_gcm_setkey): New prototype. * cipher/cipher.c (cipher_setkey): Add GCM setkey. (cipher_reset): Clear 'u_mode' only partially for GCM. -- GHASH tables can be generated at setkey time. No need to regenerate for every new IV. Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 25 ++++++++++++++++--------- cipher/cipher-internal.h | 30 +++++++++++++++++++++--------- cipher/cipher.c | 23 +++++++++++++++++++++-- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 42cfc1e..457e337 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -344,7 +344,7 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) } #define fillM(c, h) do { } while (0) -#define GHASH(c, result, buf) do_ghash (c->u_iv.iv, result, buf) +#define GHASH(c, result, buf) do_ghash (c->u_mode.gcm.u_ghash_key.key, result, buf) #endif /* !GCM_USE_TABLES */ @@ -581,7 +581,7 @@ ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, "pshufb %[be_mask], %%xmm1\n\t" /* be => le */ : : [hash] "m" (*result), [be_mask] "m" (*be_mask), - [hsub] "m" (*c->u_iv.iv)); + [hsub] "m" (*c->u_mode.gcm.u_ghash_key.key)); #ifdef __x86_64__ if (nblocks >= 4) @@ -687,9 +687,9 @@ setupM (gcry_cipher_hd_t c, byte *h) c->u_mode.gcm.use_intel_pclmul = 1; /* Swap endianness of hsub. */ - tmp[0] = buf_get_be64(c->u_iv.iv + 8); - tmp[1] = buf_get_be64(c->u_iv.iv + 0); - buf_cpy (c->u_iv.iv, tmp, GCRY_GCM_BLOCK_LEN); + tmp[0] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 8); + tmp[1] = buf_get_be64(c->u_mode.gcm.u_ghash_key.key + 0); + buf_cpy (c->u_mode.gcm.u_ghash_key.key, tmp, GCRY_GCM_BLOCK_LEN); #ifdef __x86_64__ asm volatile ("movdqu %[h_1], %%xmm0\n\t" @@ -982,6 +982,17 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, } +void +_gcry_cipher_gcm_setkey (gcry_cipher_hd_t c) +{ + memset (c->u_mode.gcm.u_ghash_key.key, 0, GCRY_GCM_BLOCK_LEN); + + c->spec->encrypt (&c->context.c, c->u_mode.gcm.u_ghash_key.key, + c->u_mode.gcm.u_ghash_key.key); + setupM (c, c->u_mode.gcm.u_ghash_key.key); +} + + static gcry_err_code_t _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { @@ -995,10 +1006,6 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) if (ivlen == 0) return GPG_ERR_INV_LENGTH; - c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_mode.gcm.u_tag.tag); - - setupM (c, c->u_iv.iv); - if (ivlen != GCRY_GCM_BLOCK_LEN - 4) { u32 iv_bytes[2] = {0, 0}; diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index ede6f75..6fb3bac 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -179,6 +179,25 @@ struct gcry_cipher_handle /* encrypted tag counter */ unsigned char tagiv[MAX_BLOCKSIZE]; + unsigned int ghash_data_finalized:1; + unsigned int ghash_aad_finalized:1; + + unsigned int datalen_over_limits:1; + unsigned int disallow_encryption_because_of_setiv_in_fips_mode:1; + + /* --- Following members are not cleared in gcry_cipher_reset --- */ + + /* GHASH multiplier from key. */ + union { + cipher_context_alignment_t iv_align; + unsigned char key[MAX_BLOCKSIZE]; + } u_ghash_key; + +#ifdef GCM_USE_INTEL_PCLMUL + /* Use Intel PCLMUL instructions for accelerated GHASH. */ + unsigned int use_intel_pclmul:1; +#endif + /* Pre-calculated table for GCM. */ #ifdef GCM_USE_TABLES #if defined(HAVE_U64_TYPEDEF) && (SIZEOF_UNSIGNED_LONG == 8 \ @@ -190,15 +209,6 @@ struct gcry_cipher_handle u32 gcm_table[4 * 16]; #endif #endif - - unsigned int ghash_data_finalized:1; - unsigned int ghash_aad_finalized:1; - - unsigned int datalen_over_limits:1; - unsigned int disallow_encryption_because_of_setiv_in_fips_mode:1; -#ifdef GCM_USE_INTEL_PCLMUL - unsigned int use_intel_pclmul:1; -#endif } gcm; } u_mode; @@ -302,6 +312,8 @@ gcry_err_code_t _gcry_cipher_gcm_get_tag gcry_err_code_t _gcry_cipher_gcm_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); +void _gcry_cipher_gcm_setkey +/* */ (gcry_cipher_hd_t c); #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index a3c2c6f..516f44b 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -593,6 +593,11 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) case GCRY_CIPHER_MODE_CMAC: _gcry_cipher_cmac_set_subkeys (c); break; + + case GCRY_CIPHER_MODE_GCM: + _gcry_cipher_gcm_setkey (c); + break; + default: break; }; @@ -670,9 +675,23 @@ cipher_reset (gcry_cipher_hd_t c) c->u_mode.cmac.tag = 0; break; - default: - memset (&c->u_mode, 0, sizeof c->u_mode); + case GCRY_CIPHER_MODE_GCM: + /* Only clear head of u_mode, keep ghash_key and gcm_table. */ + { + byte *u_mode_pos = (void *)&c->u_mode; + byte *ghash_key_pos = c->u_mode.gcm.u_ghash_key.key; + size_t u_mode_head_length = ghash_key_pos - u_mode_pos; + + memset (&c->u_mode, 0, u_mode_head_length); + } + break; + + case GCRY_CIPHER_MODE_CCM: + memset (&c->u_mode.ccm, 0, sizeof c->u_mode.ccm); break; + + default: + break; /* u_mode unused by other modes. */ } } From jussi.kivilinna at iki.fi Wed Nov 20 18:00:47 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:47 +0200 Subject: [PATCH 10/13] GCM: add FIPS mode restrictions In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170047.11305.51263.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt) (_gcry_cipher_gcm_get_tag): Do not allow using in FIPS mode is setiv was invocated directly. (_gcry_cipher_gcm_setiv): Rename to... (_gcry_cipher_gcm_initiv): ...this. (_gcry_cipher_gcm_setiv): New setiv function with check for FIPS mode. [TODO] (_gcry_cipher_gcm_getiv): New. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode'. -- Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 61 ++++++++++++++++++++++++++++++++++++++++++++-- cipher/cipher-internal.h | 1 + 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 124fe3e..0e97c67 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -850,6 +850,9 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, if (!c->marks.iv) _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); + if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode) + return GPG_ERR_INV_STATE; + gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen); if (!gcm_check_datalen(c->u_mode.gcm.datalen)) { @@ -928,8 +931,8 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, } -gcry_err_code_t -_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) +static gcry_err_code_t +_gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { memset (c->u_mode.gcm.aadlen, 0, sizeof(c->u_mode.gcm.aadlen)); memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen)); @@ -992,6 +995,56 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) } +gcry_err_code_t +_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) +{ + c->marks.iv = 0; + c->marks.tag = 0; + c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0; + + if (fips_mode ()) + { + /* Direct invocation of GCM setiv in FIPS mode disables encryption. */ + c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 1; + } + + return _gcry_cipher_gcm_initiv (c, iv, ivlen); +} + + +#if 0 && TODO +void +_gcry_cipher_gcm_geniv (gcry_cipher_hd_t c, + byte *ivout, unsigned int ivoutlen, const byte *nonce, + unsigned int noncelen) +{ + /* nonce: user provided part (might be null) */ + /* noncelen: check if proper length (if nonce not null) */ + /* ivout: iv used to initialize gcm, output to user */ + /* ivoutlen: check correct size */ + byte iv[IVLEN]; + + if (!ivout) + return GPG_ERR_INV_ARG; + if (ivoutlen != IVLEN) + return GPG_ERR_INV_LENGTH; + if (nonce != NULL && !is_nonce_ok_len(noncelen)) + return GPG_ERR_INV_ARG; + + gcm_generate_iv(iv, nonce, noncelen); + + c->marks.iv = 0; + c->marks.tag = 0; + c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode = 0; + + _gcry_cipher_gcm_initiv (c, iv, IVLEN); + + buf_cpy(ivout, iv, IVLEN); + wipememory(iv, sizeof(iv)); +} +#endif + + static gcry_err_code_t _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, byte * outbuf, unsigned int outbuflen, int check) @@ -1042,6 +1095,10 @@ gcry_err_code_t _gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, size_t taglen) { + /* Outputting authentication tag is part of encryption. */ + if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode) + return GPG_ERR_INV_STATE; + return _gcry_cipher_gcm_tag (c, outtag, taglen, 0); } diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 9287ef5..fced20c 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -188,6 +188,7 @@ struct gcry_cipher_handle #endif unsigned int datalen_over_limits:1; + unsigned int disallow_encryption_because_of_setiv_in_fips_mode:1; #ifdef GCM_USE_INTEL_PCLMUL unsigned int use_intel_pclmul:1; #endif From jussi.kivilinna at iki.fi Wed Nov 20 18:00:57 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:57 +0200 Subject: [PATCH 12/13] GCM: Add support for split data buffers and online operation In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170057.11305.33015.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (do_ghash_buf): Add buffering for less than blocksize length input and padding handling. (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt): Add handling for AAD padding and check if data has already being padded. (_gcry_cipher_gcm_authenticate): Check that AAD or data has not being padded yet. (_gcry_cipher_gcm_initiv): Clear padding marks. (_gcry_cipher_gcm_tag): Add finalization and padding; Clear sensitive data from cipher handle, since they are not used after generating tag. * cipher/cipher-internal.h (gcry_cipher_handle): Add 'u_mode.gcm.macbuf', 'u_mode.gcm.mac_unused', 'u_mode.gcm.ghash_data_finalized' and 'u_mode.gcm.ghash_aad_finalized'. -- Until now, GCM was expecting full data to be input in one go. This patch adds support for feeding data continuously (for encryption/decryption/aad). Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 113 +++++++++++++++++++++++++++++++++++----------- cipher/cipher-internal.h | 7 +++ 2 files changed, 92 insertions(+), 28 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index 62855b1..42cfc1e 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -806,30 +806,60 @@ gcm_check_aadlen_or_ivlen (u32 ctr[2]) static void -do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte * buf, - size_t buflen) +do_ghash_buf(gcry_cipher_hd_t c, byte *hash, const byte *buf, + size_t buflen, int do_padding) { - unsigned char tmp[MAX_BLOCKSIZE]; unsigned int blocksize = GCRY_GCM_BLOCK_LEN; - size_t nblocks; + unsigned int unused = c->u_mode.gcm.mac_unused; + size_t nblocks, n; unsigned int burn = 0; - nblocks = buflen / blocksize; + if (buflen == 0 && (unused == 0 || !do_padding)) + return; - if (nblocks) + do { - burn = ghash (c, hash, buf, nblocks); - buf += blocksize * nblocks; - buflen -= blocksize * nblocks; - } + if (buflen + unused < blocksize || unused > 0) + { + n = blocksize - unused; + n = n < buflen ? n : buflen; - if (buflen) - { - buf_cpy (tmp, buf, buflen); - memset (tmp + buflen, 0, blocksize - buflen); - burn = ghash (c, hash, tmp, 1); - wipememory (tmp, sizeof(tmp)); + buf_cpy (&c->u_mode.gcm.macbuf[unused], buf, n); + + unused += n; + buf += n; + buflen -= n; + } + if (!buflen) + { + if (!do_padding) + break; + + while (unused < blocksize) + c->u_mode.gcm.macbuf[unused++] = 0; + } + + if (unused > 0) + { + gcry_assert (unused == blocksize); + + /* Process one block from macbuf. */ + burn = ghash (c, hash, c->u_mode.gcm.macbuf, 1); + unused = 0; + } + + nblocks = buflen / blocksize; + + if (nblocks) + { + burn = ghash (c, hash, buf, nblocks); + buf += blocksize * nblocks; + buflen -= blocksize * nblocks; + } } + while (buflen > 0); + + c->u_mode.gcm.mac_unused = unused; if (burn) _gcry_burn_stack (burn); @@ -850,7 +880,7 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag) + if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized) return GPG_ERR_INV_STATE; if (!c->marks.iv) @@ -859,6 +889,13 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, if (c->u_mode.gcm.disallow_encryption_because_of_setiv_in_fips_mode) return GPG_ERR_INV_STATE; + if (!c->u_mode.gcm.ghash_aad_finalized) + { + /* Start of encryption marks end of AAD stream. */ + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1); + c->u_mode.gcm.ghash_aad_finalized = 1; + } + gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen); if (!gcm_check_datalen(c->u_mode.gcm.datalen)) { @@ -870,7 +907,7 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, if (err != 0) return err; - do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen); + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, outbuf, inbuflen, 0); return 0; } @@ -889,12 +926,19 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag) + if (c->marks.tag || c->u_mode.gcm.ghash_data_finalized) return GPG_ERR_INV_STATE; if (!c->marks.iv) _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); + if (!c->u_mode.gcm.ghash_aad_finalized) + { + /* Start of decryption marks end of AAD stream. */ + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1); + c->u_mode.gcm.ghash_aad_finalized = 1; + } + gcm_bytecounter_add(c->u_mode.gcm.datalen, inbuflen); if (!gcm_check_datalen(c->u_mode.gcm.datalen)) { @@ -902,7 +946,7 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, return GPG_ERR_INV_LENGTH; } - do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen); + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, inbuf, inbuflen, 0); return _gcry_cipher_ctr_encrypt(c, outbuf, outbuflen, inbuf, inbuflen); } @@ -918,7 +962,8 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, return GPG_ERR_CIPHER_ALGO; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; - if (c->marks.tag) + if (c->marks.tag || c->u_mode.gcm.ghash_aad_finalized || + c->u_mode.gcm.ghash_data_finalized) return GPG_ERR_INV_STATE; if (!c->marks.iv) @@ -931,7 +976,7 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, return GPG_ERR_INV_LENGTH; } - do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen); + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, aadbuf, aadbuflen, 0); return 0; } @@ -944,6 +989,8 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) memset (c->u_mode.gcm.datalen, 0, sizeof(c->u_mode.gcm.datalen)); memset (c->u_mode.gcm.u_tag.tag, 0, GCRY_GCM_BLOCK_LEN); c->u_mode.gcm.datalen_over_limits = 0; + c->u_mode.gcm.ghash_data_finalized = 0; + c->u_mode.gcm.ghash_aad_finalized = 0; if (ivlen == 0) return GPG_ERR_INV_LENGTH; @@ -966,7 +1013,7 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) return GPG_ERR_INV_LENGTH; } - do_ghash_buf(c, c->u_ctr.ctr, iv, ivlen); + do_ghash_buf(c, c->u_ctr.ctr, iv, ivlen, 1); /* iv length, 64-bit */ bitlengths[1][1] = be_bswap32(iv_bytes[0] << 3); @@ -976,10 +1023,10 @@ _gcry_cipher_gcm_initiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) bitlengths[0][1] = 0; bitlengths[0][0] = 0; - do_ghash_buf(c, c->u_ctr.ctr, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN); + do_ghash_buf(c, c->u_ctr.ctr, (byte*)bitlengths, GCRY_GCM_BLOCK_LEN, 1); - wipememory(iv_bytes, sizeof iv_bytes); - wipememory(bitlengths, sizeof bitlengths); + wipememory (iv_bytes, sizeof iv_bytes); + wipememory (bitlengths, sizeof bitlengths); } else { @@ -1073,13 +1120,23 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, bitlengths[1][0] = be_bswap32((c->u_mode.gcm.datalen[0] >> 29) | (c->u_mode.gcm.datalen[1] << 3)); + /* Finalize data-stream. */ + do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, NULL, 0, 1); + c->u_mode.gcm.ghash_aad_finalized = 1; + c->u_mode.gcm.ghash_data_finalized = 1; + + /* Add bitlengths to tag. */ do_ghash_buf(c, c->u_mode.gcm.u_tag.tag, (byte*)bitlengths, - GCRY_GCM_BLOCK_LEN); + GCRY_GCM_BLOCK_LEN, 1); buf_xor (c->u_mode.gcm.u_tag.tag, c->u_mode.gcm.tagiv, c->u_mode.gcm.u_tag.tag, GCRY_GCM_BLOCK_LEN); c->marks.tag = 1; - wipememory(bitlengths, sizeof bitlengths); + wipememory (bitlengths, sizeof (bitlengths)); + wipememory (c->u_mode.gcm.macbuf, GCRY_GCM_BLOCK_LEN); + wipememory (c->u_mode.gcm.tagiv, GCRY_GCM_BLOCK_LEN); + wipememory (c->u_mode.gcm.aadlen, sizeof (c->u_mode.gcm.aadlen)); + wipememory (c->u_mode.gcm.datalen, sizeof (c->u_mode.gcm.datalen)); } if (!check) diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 225f699..ede6f75 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -168,6 +168,10 @@ struct gcry_cipher_handle unsigned char tag[MAX_BLOCKSIZE]; } u_tag; + /* Space to save partial input lengths for MAC. */ + unsigned char macbuf[GCRY_CCM_BLOCK_LEN]; + int mac_unused; /* Number of unprocessed bytes in MACBUF. */ + /* byte counters for GCM */ u32 aadlen[2]; u32 datalen[2]; @@ -187,6 +191,9 @@ struct gcry_cipher_handle #endif #endif + unsigned int ghash_data_finalized:1; + unsigned int ghash_aad_finalized:1; + unsigned int datalen_over_limits:1; unsigned int disallow_encryption_because_of_setiv_in_fips_mode:1; #ifdef GCM_USE_INTEL_PCLMUL From jussi.kivilinna at iki.fi Wed Nov 20 18:00:42 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:42 +0200 Subject: [PATCH 09/13] GCM: Add clearing and checking of marks.tag In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170042.11305.19153.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (_gcry_cipher_gcm_encrypt) (_gcry_cipher_gcm_decrypt, _gcry_cipher_gcm_authenticate): Make sure that tag has not been finalized yet. (_gcry_cipher_gcm_setiv): Clear 'marks.tag'. -- Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index cf666ab..124fe3e 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -844,6 +844,8 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; + if (c->marks.tag) + return GPG_ERR_INV_STATE; if (!c->marks.iv) _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); @@ -878,6 +880,8 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, return GPG_ERR_BUFFER_TOO_SHORT; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; + if (c->marks.tag) + return GPG_ERR_INV_STATE; if (!c->marks.iv) _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); @@ -905,6 +909,8 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, return GPG_ERR_CIPHER_ALGO; if (c->u_mode.gcm.datalen_over_limits) return GPG_ERR_INV_LENGTH; + if (c->marks.tag) + return GPG_ERR_INV_STATE; if (!c->marks.iv) _gcry_cipher_gcm_setiv (c, zerobuf, GCRY_GCM_BLOCK_LEN); @@ -980,6 +986,7 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) c->unused = 0; c->marks.iv = 1; + c->marks.tag = 0; return 0; } From jussi.kivilinna at iki.fi Wed Nov 20 18:00:17 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:17 +0200 Subject: [PATCH 04/13] Add Intel PCLMUL acceleration for GCM In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170017.11305.78120.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (fillM): Rename... (do_fillM): ...to this. (ghash): Remove. (fillM): New macro. (GHASH): Use 'do_ghash' instead of 'ghash'. [GCM_USE_INTEL_PCLMUL] (do_ghash_pclmul): New. (ghash): New. (setupM): New. (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt) (_gcry_cipher_gcm_authenticate, _gcry_cipher_gcm_setiv) (_gcry_cipher_gcm_tag): Use 'ghash' instead of 'GHASH' and 'c->u_mode.gcm.u_tag.tag' instead of 'c->u_tag.tag'. * cipher/cipher-internal.h (GCM_USE_INTEL_PCLMUL): New. (gcry_cipher_handle): Move 'u_tag' and 'gcm_table' under 'u_mode.gcm'. * configure.ac (pclmulsupport, gcry_cv_gcc_inline_asm_pclmul): New. * src/g10lib.h (HWF_INTEL_PCLMUL): New. * src/global.c: Add "intel-pclmul". * src/hwf-x86.c (detect_x86_gnuc): Add check for Intel PCLMUL. -- Speed-up GCM for Intel CPUs. Intel Haswell (x86-64): Old: AES GCM enc | 5.17 ns/B 184.4 MiB/s 16.55 c/B GCM dec | 4.38 ns/B 218.0 MiB/s 14.00 c/B GCM auth | 3.17 ns/B 300.4 MiB/s 10.16 c/B New: AES GCM enc | 3.01 ns/B 317.2 MiB/s 9.62 c/B GCM dec | 1.96 ns/B 486.9 MiB/s 6.27 c/B GCM auth | 0.848 ns/B 1124.8 MiB/s 2.71 c/B Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 205 +++++++++++++++++++++++++++++++++++++++------- cipher/cipher-internal.h | 55 +++++++++--- configure.ac | 35 ++++++++ src/g10lib.h | 1 src/global.c | 1 src/hwf-x86.c | 5 + 6 files changed, 256 insertions(+), 46 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index d7fc0d8..b93f0fa 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -1,5 +1,6 @@ /* cipher-gcm.c - Generic Galois Counter Mode implementation * Copyright (C) 2013 Dmitry Eremin-Solenikov + * Copyright ? 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * @@ -81,7 +82,7 @@ bshift (u64 * b0, u64 * b1) } static void -fillM (unsigned char *h, u64 * M) +do_fillM (unsigned char *h, u64 *M) { int i, j; @@ -179,7 +180,7 @@ bshift (u32 * M, int i) } static void -fillM (unsigned char *h, u32 * M) +do_fillM (unsigned char *h, u32 *M) { int i, j; @@ -269,15 +270,10 @@ do_ghash (unsigned char *result, const unsigned char *buf, const u32 * gcmM) buf_put_be32 (result + 8, tmp[2]); buf_put_be32 (result + 12, tmp[3]); } -#endif - -static void -ghash (unsigned char *result, const unsigned char *buf, const void *gcmM) -{ - do_ghash (result, buf, gcmM); -} +#endif /* !HAVE_U64_TYPEDEF || SIZEOF_UNSIGNED_LONG != 8 */ -#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); +#define fillM(c, h) do_fillM (h, c->u_mode.gcm.gcm_table) +#define GHASH(c, result, buf) do_ghash (result, buf, c->u_mode.gcm.gcm_table) #else @@ -296,7 +292,7 @@ bshift (unsigned long *b) } static void -ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) +do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) { unsigned long V[4]; int i, j; @@ -339,10 +335,161 @@ ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) #endif } -#define fillM(h, M) do { } while (0) +#define fillM(c, h) do { } while (0) +#define GHASH(c, result, buf) do_ghash (c->u_iv.iv, result, buf) + +#endif /* !GCM_USE_TABLES */ + + +#ifdef GCM_USE_INTEL_PCLMUL +/* + Intel PCLMUL ghash based on white paper: + "Intel? Carry-Less Multiplication Instruction and its Usage for Computing the + GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis. + */ +static void +do_ghash_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf) +{ + static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + asm volatile ("movdqu (%[result]), %%xmm1\n\t" + "movdqu %[buf], %%xmm2\n\t" + "movdqa %[hsub], %%xmm0\n\t" + "pxor %%xmm2, %%xmm1\n\t" /* big endian */ + + /* be => le */ + "pshufb %[be_mask], %%xmm1\n\t" + + /* gfmul, xmm0 has operator a and xmm1 has operator b. */ + "pshufd $78, %%xmm0, %%xmm2\n\t" + "pshufd $78, %%xmm1, %%xmm4\n\t" + "pxor %%xmm0, %%xmm2\n\t" /* xmm2 holds a0+a1 */ + "pxor %%xmm1, %%xmm4\n\t" /* xmm4 holds b0+b1 */ + + "movdqa %%xmm0, %%xmm3\n\t" + "pclmulqdq $0, %%xmm1, %%xmm3\n\t" /* xmm3 holds a0*b0 */ + "movdqa %%xmm0, %%xmm6\n\t" + "pclmulqdq $17, %%xmm1, %%xmm6\n\t" /* xmm6 holds a1*b1 */ + "movdqa %%xmm3, %%xmm5\n\t" + "pclmulqdq $0, %%xmm2, %%xmm4\n\t" /* xmm4 holds (a0+a1)*(b0+b1) */ + + "pxor %%xmm6, %%xmm5\n\t" /* xmm5 holds a0*b0+a1*b1 */ + "pxor %%xmm5, %%xmm4\n\t" /* xmm4 holds a0*b0+a1*b1+(a0+a1)*(b0+b1) */ + "movdqa %%xmm4, %%xmm5\n\t" + "psrldq $8, %%xmm4\n\t" + "pslldq $8, %%xmm5\n\t" + "pxor %%xmm5, %%xmm3\n\t" + "pxor %%xmm4, %%xmm6\n\t" /* holds the result of the + carry-less multiplication of xmm0 + by xmm1 */ + + /* shift the result by one bit position to the left cope for + the fact that bits are reversed */ + "movdqa %%xmm3, %%xmm7\n\t" + "movdqa %%xmm6, %%xmm0\n\t" + "pslld $1, %%xmm3\n\t" + "pslld $1, %%xmm6\n\t" + "psrld $31, %%xmm7\n\t" + "psrld $31, %%xmm0\n\t" + "movdqa %%xmm7, %%xmm1\n\t" + "pslldq $4, %%xmm0\n\t" + "pslldq $4, %%xmm7\n\t" + "psrldq $12, %%xmm1\n\t" + "por %%xmm7, %%xmm3\n\t" + "por %%xmm0, %%xmm6\n\t" + "por %%xmm1, %%xmm6\n\t" + + /* first phase of the reduction */ + "movdqa %%xmm3, %%xmm7\n\t" + "movdqa %%xmm3, %%xmm0\n\t" + "pslld $31, %%xmm7\n\t" /* packed right shifting << 31 */ + "movdqa %%xmm3, %%xmm1\n\t" + "pslld $30, %%xmm0\n\t" /* packed right shifting shift << 30 */ + "pslld $25, %%xmm1\n\t" /* packed right shifting shift << 25 */ + "pxor %%xmm0, %%xmm7\n\t" /* xor the shifted versions */ + "pxor %%xmm1, %%xmm7\n\t" + "movdqa %%xmm7, %%xmm0\n\t" + "pslldq $12, %%xmm7\n\t" + "psrldq $4, %%xmm0\n\t" + "pxor %%xmm7, %%xmm3\n\t" /* first phase of the reduction + complete */ + + /* second phase of the reduction */ + "movdqa %%xmm3, %%xmm2\n\t" + "movdqa %%xmm3, %%xmm4\n\t" + "psrld $1, %%xmm2\n\t" /* packed left shifting >> 1 */ + "movdqa %%xmm3, %%xmm5\n\t" + "psrld $2, %%xmm4\n\t" /* packed left shifting >> 2 */ + "psrld $7, %%xmm5\n\t" /* packed left shifting >> 7 */ + "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */ + "pxor %%xmm5, %%xmm2\n\t" + "pxor %%xmm0, %%xmm2\n\t" + "pxor %%xmm2, %%xmm3\n\t" + "pxor %%xmm3, %%xmm6\n\t" /* the result is in xmm6 */ + + /* le => be */ + "pshufb %[be_mask], %%xmm6\n\t" + + "movdqu %%xmm6, (%[result])\n\t" /* store the result */ + : + : [result] "r" (result), [buf] "m" (*buf), + [hsub] "m" (*c->u_iv.iv), [be_mask] "m" (*be_mask) + : "memory" ); +} + +#endif /*GCM_USE_INTEL_PCLMUL*/ + + +static void +ghash (gcry_cipher_hd_t c, unsigned char *result, const unsigned char *buf) +{ + if (0) + ; +#ifdef GCM_USE_INTEL_PCLMUL + else if (c->u_mode.gcm.use_intel_pclmul) + { + /* TODO: Loop structure, use bit-reflection and add faster bulk + processing (parallel four blocks). */ + do_ghash_pclmul (c, result, buf); + + /* Clear used registers. */ + asm volatile( "pxor %%xmm0, %%xmm0\n\t" + "pxor %%xmm1, %%xmm1\n\t" + "pxor %%xmm2, %%xmm2\n\t" + "pxor %%xmm3, %%xmm3\n\t" + "pxor %%xmm4, %%xmm4\n\t" + "pxor %%xmm5, %%xmm5\n\t" + "pxor %%xmm6, %%xmm6\n\t" + "pxor %%xmm7, %%xmm7\n\t" + ::: "cc" ); + } +#endif + else + GHASH (c, result, buf); +} + +static void +setupM (gcry_cipher_hd_t c, byte *h) +{ + if (0) + ; +#ifdef GCM_USE_INTEL_PCLMUL + else if (_gcry_get_hw_features () & HWF_INTEL_PCLMUL) + { + u64 tmp[2]; + + c->u_mode.gcm.use_intel_pclmul = 1; -#define GHASH(c, result, buf) ghash (c->u_iv.iv, result, buf); + /* Swap endianness of hsub. */ + tmp[0] = buf_get_be64(c->u_iv.iv + 8); + tmp[1] = buf_get_be64(c->u_iv.iv + 0); + buf_cpy (c->u_iv.iv, tmp, 16); + } #endif + else + fillM (c, h); +} gcry_err_code_t @@ -389,12 +536,12 @@ _gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, { buf_xor_2dst (outbuf, tmp, inbuf, n); memset (tmp + n, 0, blocksize - n); - GHASH (c, c->u_tag.tag, tmp); + ghash (c, c->u_mode.gcm.u_tag.tag, tmp); } else { buf_xor (outbuf, tmp, inbuf, n); - GHASH (c, c->u_tag.tag, outbuf); + ghash (c, c->u_mode.gcm.u_tag.tag, outbuf); } inbuflen -= n; @@ -442,11 +589,11 @@ _gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, { memcpy (tmp, inbuf, n); memset (tmp + n, 0, blocksize - n); - GHASH (c, c->u_tag.tag, tmp); + ghash (c, c->u_mode.gcm.u_tag.tag, tmp); } else { - GHASH (c, c->u_tag.tag, inbuf); + ghash (c, c->u_mode.gcm.u_tag.tag, inbuf); } i = blocksize - 1; @@ -490,7 +637,7 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, while (aadbuflen >= blocksize) { - GHASH (c, c->u_tag.tag, aadbuf); + ghash (c, c->u_mode.gcm.u_tag.tag, aadbuf); aadbuflen -= blocksize; aadbuf += blocksize; @@ -501,7 +648,7 @@ _gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, memcpy (tmp, aadbuf, aadbuflen); memset (tmp + aadbuflen, 0, blocksize - aadbuflen); - GHASH (c, c->u_tag.tag, tmp); + ghash (c, c->u_mode.gcm.u_tag.tag, tmp); } return 0; @@ -512,10 +659,10 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, const byte * iv, unsigned int ivlen) { memset (c->length, 0, 16); - memset (c->u_tag.tag, 0, 16); - c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_tag.tag); + memset (c->u_mode.gcm.u_tag.tag, 0, 16); + c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_mode.gcm.u_tag.tag); - fillM (c->u_iv.iv, c->gcm_table); + setupM (c, c->u_iv.iv); if (ivlen != 16 - 4) { @@ -523,12 +670,12 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, unsigned n; memset (c->u_ctr.ctr, 0, 16); for (n = ivlen; n >= 16; n -= 16, iv += 16) - GHASH (c, c->u_ctr.ctr, iv); + ghash (c, c->u_ctr.ctr, iv); if (n != 0) { memcpy (tmp, iv, n); memset (tmp + n, 0, 16 - n); - GHASH (c, c->u_ctr.ctr, tmp); + ghash (c, c->u_ctr.ctr, tmp); } memset (tmp, 0, 16); n = 16; @@ -537,7 +684,7 @@ _gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, n--; for (; n > 0; n--, ivlen >>= 8) tmp[n - 1] = ivlen & 0xff; - GHASH (c, c->u_ctr.ctr, tmp); + ghash (c, c->u_ctr.ctr, tmp); } else { @@ -560,19 +707,19 @@ _gcry_cipher_gcm_tag (gcry_cipher_hd_t c, if (!c->marks.tag) { - GHASH (c, c->u_tag.tag, c->length); - buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16); + ghash (c, c->u_mode.gcm.u_tag.tag, c->length); + buf_xor (c->u_mode.gcm.u_tag.tag, c->lastiv, c->u_mode.gcm.u_tag.tag, 16); c->marks.tag = 1; } if (!check) { - memcpy (outbuf, c->u_tag.tag, outbuflen); + memcpy (outbuf, c->u_mode.gcm.u_tag.tag, outbuflen); return GPG_ERR_NO_ERROR; } else { - return buf_eq_const(outbuf, c->u_tag.tag, outbuflen) ? + return buf_eq_const(outbuf, c->u_mode.gcm.u_tag.tag, outbuflen) ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; } diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index b4d0ff9..a6e6271 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -39,6 +39,18 @@ #define GCM_USE_TABLES 1 +/* GCM_USE_INTEL_PCLMUL inidicates whether to compile GCM with Intel PCLMUL + code. */ +#undef GCM_USE_INTEL_PCLMUL +#if defined(ENABLE_PCLMUL_SUPPORT) && defined(GCM_USE_TABLES) +# if ((defined(__i386__) && SIZEOF_UNSIGNED_LONG == 4) || defined(__x86_64__)) +# if __GNUC__ >= 4 +# define GCM_USE_INTEL_PCLMUL 1 +# endif +# endif +#endif /* GCM_USE_INTEL_PCLMUL */ + + /* A VIA processor with the Padlock engine as well as the Intel AES_NI instructions require an alignment of most data on a 16 byte boundary. Because we trick out the compiler while allocating the @@ -118,26 +130,10 @@ struct gcry_cipher_handle unsigned char ctr[MAX_BLOCKSIZE]; } u_ctr; - /* The interim tag for GCM mode. */ - union { - cipher_context_alignment_t iv_align; - unsigned char tag[MAX_BLOCKSIZE]; - } u_tag; - /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; int unused; /* Number of unused bytes in LASTIV. */ unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ -#ifdef GCM_USE_TABLES - #if defined(HAVE_U64_TYPEDEF) && \ - (SIZEOF_UNSIGNED_LONG == 8 || defined(__x86_64__)) - #define GCM_TABLES_USE_U64 1 - u64 gcm_table[2 * 16]; /* pre-calculated table for GCM */ - #else - #undef GCM_TABLES_USE_U64 - u32 gcm_table[4 * 16]; /* pre-calculated table for GCM */ - #endif -#endif union { /* Mode specific storage for CCM mode. */ @@ -156,6 +152,7 @@ struct gcry_cipher_handle unsigned int lengths:1; /* Set to 1 if CCM length parameters has been processed. */ } ccm; + /* Mode specific storage for CMAC mode. */ struct { unsigned int tag:1; /* Set to 1 if tag has been finalized. */ @@ -163,8 +160,32 @@ struct gcry_cipher_handle /* Subkeys for tag creation, not cleared by gcry_cipher_reset. */ unsigned char subkeys[2][MAX_BLOCKSIZE]; } cmac; - } u_mode; + /* Mode specific storage for GCM mode. */ + struct { + /* The interim tag for GCM mode. */ + union { + cipher_context_alignment_t iv_align; + unsigned char tag[MAX_BLOCKSIZE]; + } u_tag; + + /* Pre-calculated table for GCM. */ +#ifdef GCM_USE_TABLES + #if defined(HAVE_U64_TYPEDEF) && (SIZEOF_UNSIGNED_LONG == 8 \ + || defined(__x86_64__)) + #define GCM_TABLES_USE_U64 1 + u64 gcm_table[2 * 16]; + #else + #undef GCM_TABLES_USE_U64 + u32 gcm_table[4 * 16]; + #endif +#endif + +#ifdef GCM_USE_INTEL_PCLMUL + unsigned int use_intel_pclmul:1; +#endif + } gcm; + } u_mode; /* What follows are two contexts of the cipher in use. The first one needs to be aligned well enough for the cipher operation diff --git a/configure.ac b/configure.ac index c4f8776..6d40343 100644 --- a/configure.ac +++ b/configure.ac @@ -567,6 +567,14 @@ AC_ARG_ENABLE(aesni-support, aesnisupport=$enableval,aesnisupport=yes) AC_MSG_RESULT($aesnisupport) +# Implementation of the --disable-pclmul-support switch. +AC_MSG_CHECKING([whether PCLMUL support is requested]) +AC_ARG_ENABLE(pclmul-support, + AC_HELP_STRING([--disable-pclmul-support], + [Disable support for the Intel PCLMUL instructions]), + pclmulsupport=$enableval,pclmulsupport=yes) +AC_MSG_RESULT($pclmulsupport) + # Implementation of the --disable-drng-support switch. AC_MSG_CHECKING([whether DRNG support is requested]) AC_ARG_ENABLE(drng-support, @@ -991,6 +999,23 @@ fi # +# Check whether GCC inline assembler supports PCLMUL instructions. +# +AC_CACHE_CHECK([whether GCC inline assembler supports PCLMUL instructions], + [gcry_cv_gcc_inline_asm_pclmul], + [gcry_cv_gcc_inline_asm_pclmul=no + AC_COMPILE_IFELSE([AC_LANG_SOURCE( + [[void a(void) { + __asm__("pclmulqdq \$0, %%xmm1, %%xmm3\n\t":::"cc"); + }]])], + [gcry_cv_gcc_inline_asm_pclmul=yes])]) +if test "$gcry_cv_gcc_inline_asm_pclmul" = "yes" ; then + AC_DEFINE(HAVE_GCC_INLINE_ASM_PCLMUL,1, + [Defined if inline assembler supports PCLMUL instructions]) +fi + + +# # Check whether GCC inline assembler supports AVX instructions # AC_CACHE_CHECK([whether GCC inline assembler supports AVX instructions], @@ -1369,6 +1394,11 @@ if test x"$aesnisupport" = xyes ; then aesnisupport="no (unsupported by compiler)" fi fi +if test x"$pclmulsupport" = xyes ; then + if test "$gcry_cv_gcc_inline_asm_pclmul" != "yes" ; then + pclmulsupport="no (unsupported by compiler)" + fi +fi if test x"$avxsupport" = xyes ; then if test "$gcry_cv_gcc_inline_asm_avx" != "yes" ; then avxsupport="no (unsupported by compiler)" @@ -1389,6 +1419,10 @@ if test x"$aesnisupport" = xyes ; then AC_DEFINE(ENABLE_AESNI_SUPPORT, 1, [Enable support for Intel AES-NI instructions.]) fi +if test x"$pclmulsupport" = xyes ; then + AC_DEFINE(ENABLE_PCLMUL_SUPPORT, 1, + [Enable support for Intel PCLMUL instructions.]) +fi if test x"$avxsupport" = xyes ; then AC_DEFINE(ENABLE_AVX_SUPPORT,1, [Enable support for Intel AVX instructions.]) @@ -1826,6 +1860,7 @@ GCRY_MSG_SHOW([Random number generator: ],[$random]) GCRY_MSG_SHOW([Using linux capabilities: ],[$use_capabilities]) GCRY_MSG_SHOW([Try using Padlock crypto: ],[$padlocksupport]) GCRY_MSG_SHOW([Try using AES-NI crypto: ],[$aesnisupport]) +GCRY_MSG_SHOW([Try using Intel PCLMUL: ],[$pclmulsupport]) GCRY_MSG_SHOW([Try using DRNG (RDRAND): ],[$drngsupport]) GCRY_MSG_SHOW([Try using Intel AVX: ],[$avxsupport]) GCRY_MSG_SHOW([Try using Intel AVX2: ],[$avx2support]) diff --git a/src/g10lib.h b/src/g10lib.h index ae4502c..0612cbc 100644 --- a/src/g10lib.h +++ b/src/g10lib.h @@ -167,6 +167,7 @@ int _gcry_log_verbosity( int level ); #define HWF_PADLOCK_SHA 4 #define HWF_PADLOCK_MMUL 8 +#define HWF_INTEL_PCLMUL 128 #define HWF_INTEL_AESNI 256 #define HWF_INTEL_RDRAND 512 #define HWF_INTEL_AVX 1024 diff --git a/src/global.c b/src/global.c index 44667cf..841f188 100644 --- a/src/global.c +++ b/src/global.c @@ -66,6 +66,7 @@ static struct { HWF_PADLOCK_AES, "padlock-aes" }, { HWF_PADLOCK_SHA, "padlock-sha" }, { HWF_PADLOCK_MMUL,"padlock-mmul"}, + { HWF_INTEL_PCLMUL,"intel-pclmul" }, { HWF_INTEL_AESNI, "intel-aesni" }, { HWF_INTEL_RDRAND,"intel-rdrand" }, { HWF_INTEL_AVX, "intel-avx" }, diff --git a/src/hwf-x86.c b/src/hwf-x86.c index 2ceb04c..784fe2a 100644 --- a/src/hwf-x86.c +++ b/src/hwf-x86.c @@ -201,6 +201,11 @@ detect_x86_gnuc (void) /* Get CPU info and Intel feature flags (ECX). */ get_cpuid(1, NULL, NULL, &features, NULL); +#ifdef ENABLE_PCLMUL_SUPPORT + /* Test bit 1 for PCLMUL. */ + if (features & 0x00000002) + result |= HWF_INTEL_PCLMUL; +#endif #ifdef ENABLE_AESNI_SUPPORT /* Test bit 25 for AES-NI. */ if (features & 0x02000000) From jussi.kivilinna at iki.fi Wed Nov 20 18:00:27 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:27 +0200 Subject: [PATCH 06/13] GCM: Tweak Intel PCLMUL ghash loop for small speed-up In-Reply-To: <20131120170002.11305.34379.stgit@localhost6.localdomain6> References: <20131120170002.11305.34379.stgit@localhost6.localdomain6> Message-ID: <20131120170027.11305.14550.stgit@localhost6.localdomain6> * cipher/cipher-gcm.c (do_ghash): Mark 'inline'. [GCM_USE_INTEL_PCLMUL] (do_ghash_pclmul): Rename to... [GCM_USE_INTEL_PCLMUL] (gfmul_pclmul): ..this and make inline function. (ghash) [GCM_USE_INTEL_PCLMUL]: Preload data before ghash-pclmul loop. -- Intel Haswell: Old: AES GCM enc | 1.12 ns/B 853.5 MiB/s 3.58 c/B GCM dec | 1.12 ns/B 853.4 MiB/s 3.58 c/B GCM auth | 0.843 ns/B 1131.5 MiB/s 2.70 c/B New: AES GCM enc | 0.990 ns/B 963.3 MiB/s 3.17 c/B GCM dec | 0.982 ns/B 970.9 MiB/s 3.14 c/B GCM auth | 0.711 ns/B 1340.8 MiB/s 2.28 c/B Signed-off-by: Jussi Kivilinna --- cipher/cipher-gcm.c | 120 ++++++++++++++++++++++++++++----------------------- 1 file changed, 65 insertions(+), 55 deletions(-) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c index cdd946e..baedc04 100644 --- a/cipher/cipher-gcm.c +++ b/cipher/cipher-gcm.c @@ -108,8 +108,8 @@ do_fillM (unsigned char *h, u64 *M) } } -static void -do_ghash (unsigned char *result, const unsigned char *buf, const u64 * gcmM) +static inline void +do_ghash (unsigned char *result, const unsigned char *buf, const u64 *gcmM) { u64 V[2]; u64 tmp[2]; @@ -214,8 +214,8 @@ do_fillM (unsigned char *h, u32 *M) } } -static void -do_ghash (unsigned char *result, const unsigned char *buf, const u32 * gcmM) +static inline void +do_ghash (unsigned char *result, const unsigned char *buf, const u32 *gcmM) { byte V[16]; u32 tmp[4]; @@ -347,21 +347,12 @@ do_ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) "Intel? Carry-Less Multiplication Instruction and its Usage for Computing the GCM Mode - Rev 2.01"; Shay Gueron, Michael E. Kounavis. */ -static void -do_ghash_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf) +static inline void gfmul_pclmul(void) { - static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = - { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; - - asm volatile ("movdqu (%[result]), %%xmm1\n\t" - "movdqu %[buf], %%xmm2\n\t" - "movdqa %[hsub], %%xmm0\n\t" - "pxor %%xmm2, %%xmm1\n\t" /* big endian */ - - /* be => le */ - "pshufb %[be_mask], %%xmm1\n\t" - - /* gfmul, xmm0 has operator a and xmm1 has operator b. */ + /* Input: XMM0 and XMM1, Output: XMM1. Input XMM0 stays unmodified. + Input must be converted to little-endian. + */ + asm volatile (/* gfmul, xmm0 has operator a and xmm1 has operator b. */ "pshufd $78, %%xmm0, %%xmm2\n\t" "pshufd $78, %%xmm1, %%xmm4\n\t" "pxor %%xmm0, %%xmm2\n\t" /* xmm2 holds a0+a1 */ @@ -386,33 +377,33 @@ do_ghash_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf) /* shift the result by one bit position to the left cope for the fact that bits are reversed */ - "movdqa %%xmm3, %%xmm7\n\t" - "movdqa %%xmm6, %%xmm0\n\t" + "movdqa %%xmm3, %%xmm4\n\t" + "movdqa %%xmm6, %%xmm5\n\t" "pslld $1, %%xmm3\n\t" "pslld $1, %%xmm6\n\t" - "psrld $31, %%xmm7\n\t" - "psrld $31, %%xmm0\n\t" - "movdqa %%xmm7, %%xmm1\n\t" - "pslldq $4, %%xmm0\n\t" - "pslldq $4, %%xmm7\n\t" + "psrld $31, %%xmm4\n\t" + "psrld $31, %%xmm5\n\t" + "movdqa %%xmm4, %%xmm1\n\t" + "pslldq $4, %%xmm5\n\t" + "pslldq $4, %%xmm4\n\t" "psrldq $12, %%xmm1\n\t" - "por %%xmm7, %%xmm3\n\t" - "por %%xmm0, %%xmm6\n\t" - "por %%xmm1, %%xmm6\n\t" + "por %%xmm4, %%xmm3\n\t" + "por %%xmm5, %%xmm6\n\t" + "por %%xmm6, %%xmm1\n\t" /* first phase of the reduction */ + "movdqa %%xmm3, %%xmm6\n\t" "movdqa %%xmm3, %%xmm7\n\t" - "movdqa %%xmm3, %%xmm0\n\t" - "pslld $31, %%xmm7\n\t" /* packed right shifting << 31 */ - "movdqa %%xmm3, %%xmm1\n\t" - "pslld $30, %%xmm0\n\t" /* packed right shifting shift << 30 */ - "pslld $25, %%xmm1\n\t" /* packed right shifting shift << 25 */ - "pxor %%xmm0, %%xmm7\n\t" /* xor the shifted versions */ - "pxor %%xmm1, %%xmm7\n\t" - "movdqa %%xmm7, %%xmm0\n\t" - "pslldq $12, %%xmm7\n\t" - "psrldq $4, %%xmm0\n\t" - "pxor %%xmm7, %%xmm3\n\t" /* first phase of the reduction + "pslld $31, %%xmm6\n\t" /* packed right shifting << 31 */ + "movdqa %%xmm3, %%xmm5\n\t" + "pslld $30, %%xmm7\n\t" /* packed right shifting shift << 30 */ + "pslld $25, %%xmm5\n\t" /* packed right shifting shift << 25 */ + "pxor %%xmm7, %%xmm6\n\t" /* xor the shifted versions */ + "pxor %%xmm5, %%xmm6\n\t" + "movdqa %%xmm6, %%xmm7\n\t" + "pslldq $12, %%xmm6\n\t" + "psrldq $4, %%xmm7\n\t" + "pxor %%xmm6, %%xmm3\n\t" /* first phase of the reduction complete */ /* second phase of the reduction */ @@ -424,18 +415,10 @@ do_ghash_pclmul (gcry_cipher_hd_t c, byte *result, const byte *buf) "psrld $7, %%xmm5\n\t" /* packed left shifting >> 7 */ "pxor %%xmm4, %%xmm2\n\t" /* xor the shifted versions */ "pxor %%xmm5, %%xmm2\n\t" - "pxor %%xmm0, %%xmm2\n\t" + "pxor %%xmm7, %%xmm2\n\t" "pxor %%xmm2, %%xmm3\n\t" - "pxor %%xmm3, %%xmm6\n\t" /* the result is in xmm6 */ - - /* le => be */ - "pshufb %[be_mask], %%xmm6\n\t" - - "movdqu %%xmm6, (%[result])\n\t" /* store the result */ - : - : [result] "r" (result), [buf] "m" (*buf), - [hsub] "m" (*c->u_iv.iv), [be_mask] "m" (*be_mask) - : "memory" ); + "pxor %%xmm3, %%xmm1\n\t" /* the result is in xmm1 */ + ::: "cc" ); } #endif /*GCM_USE_INTEL_PCLMUL*/ @@ -447,19 +430,46 @@ ghash (gcry_cipher_hd_t c, byte *result, const byte *buf, { const unsigned int blocksize = GCRY_GCM_BLOCK_LEN; + if (nblocks == 0) + return; + if (0) ; #ifdef GCM_USE_INTEL_PCLMUL else if (c->u_mode.gcm.use_intel_pclmul) { - /* TODO: Loop structure, use bit-reflection and add faster bulk - processing (parallel four blocks). */ - while (nblocks) + /* TODO: Add faster bulk processing (parallel four blocks) for x86-64. */ + + static const unsigned char be_mask[16] __attribute__ ((aligned (16))) = + { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 }; + + /* Preload hash. */ + asm volatile ("movdqu %[hash], %%xmm1\n\t" + "pshufb %[be_mask], %%xmm1\n\t" /* be => le */ + : + : [hash] "m" (*result), [be_mask] "m" (*be_mask)); + + do { - do_ghash_pclmul (c, result, buf); + asm volatile ("movdqu %[buf], %%xmm2\n\t" + "movdqa %[hsub], %%xmm0\n\t" + "pshufb %[be_mask], %%xmm2\n\t" /* be => le */ + "pxor %%xmm2, %%xmm1\n\t" + : + : [buf] "m" (*buf), [be_mask] "m" (*be_mask), + [hsub] "m" (*c->u_iv.iv)); + + gfmul_pclmul (); + buf += blocksize; - nblocks--; } + while (--nblocks); + + /* Store hash. */ + asm volatile ("pshufb %[be_mask], %%xmm1\n\t" /* be => le */ + "movdqu %%xmm1, %[hash]\n\t" + : [hash] "=m" (*result) + : [be_mask] "m" (*be_mask)); /* Clear used registers. */ asm volatile( "pxor %%xmm0, %%xmm0\n\t" From jussi.kivilinna at iki.fi Wed Nov 20 18:00:02 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Wed, 20 Nov 2013 19:00:02 +0200 Subject: [PATCH 01/13] Initial implementation of GCM Message-ID: <20131120170002.11305.34379.stgit@localhost6.localdomain6> From: Dmitry Eremin-Solenikov * cipher/Makefile.am: Add 'cipher-gcm.c'. * cipher/cipher-ccm.c (_gcry_ciphert_ccm_set_lengths) (_gcry_cipher_ccm_authenticate, _gcry_cipher_ccm_tag) (_gcry_cipher_ccm_encrypt, _gcry_cipher_ccm_decrypt): Change 'c->u_mode.ccm.tag' to 'c->marks.tag'. * cipher/cipher-gcm.c: New. * cipher/cipher-internal.h (GCM_USE_TABLES): New. (gcry_cipher_handle): Add 'marks.tag', 'u_tag', 'length' and 'gcm_table'; Remove 'u_mode.ccm.tag'. (_gcry_cipher_gcm_encrypt, _gcry_cipher_gcm_decrypt) (_gcry_cipher_gcm_setiv, _gcry_cipher_gcm_authenticate) (_gcry_cipher_gcm_get_tag, _gcry_cipher_gcm_check_tag): New. * cipher/cipher.c (_gcry_cipher_open_internal, cipher_setkey) (cipher_encrypt, cipher_decrypt, _gcry_cipher_authenticate) (_gcry_cipher_gettag, _gcry_cipher_checktag): Add GCM mode handling. * src/gcrypt.h.in (gcry_cipher_modes): Add GCRY_CIPHER_MODE_GCM. (GCRY_GCM_BLOCK_LEN): New. * tests/basic.c (check_gcm_cipher): New. (check_ciphers): Add GCM check. (check_cipher_modes): Call 'check_gcm_cipher'. * tests/bench-slope.c (bench_gcm_encrypt_do_bench) (bench_gcm_decrypt_do_bench, bench_gcm_authenticate_do_bench) (gcm_encrypt_ops, gcm_decrypt_ops, gcm_authenticate_ops): New. (cipher_modes): Add GCM enc/dec/auth. (cipher_bench_one): Limit GCM to block ciphers with 16 byte block-size. * tests/benchmark.c (cipher_bench): Add GCM. -- Currently it is still quite slow. Still no support for generate_iv(). Is it really necessary? TODO: Merge/reuse cipher-internal state used by CCM. Changelog entry will be present in final patch submission. Changes since v1: - 6x-7x speedup. - added bench-slope support Signed-off-by: Dmitry Eremin-Solenikov [jk: mangle new file throught 'indent -nut'] [jk: few fixes] [jk: changelog] --- cipher/Makefile.am | 2 cipher/cipher-ccm.c | 12 + cipher/cipher-gcm.c | 483 ++++++++++++++++++++++++++++++++++++++++++++++ cipher/cipher-internal.h | 36 +++ cipher/cipher.c | 28 +++ src/gcrypt.h.in | 6 - tests/basic.c | 337 ++++++++++++++++++++++++++++++++ tests/bench-slope.c | 128 ++++++++++++ tests/benchmark.c | 2 9 files changed, 1026 insertions(+), 8 deletions(-) create mode 100644 cipher/cipher-gcm.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index 2fd9822..e29b28d 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -40,7 +40,7 @@ libcipher_la_LIBADD = $(GCRYPT_MODULES) libcipher_la_SOURCES = \ cipher.c cipher-internal.h \ cipher-cbc.c cipher-cfb.c cipher-ofb.c cipher-ctr.c cipher-aeswrap.c \ -cipher-ccm.c cipher-cmac.c \ +cipher-ccm.c cipher-cmac.c cipher-gcm.c \ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c index 1eba7f0..d2b8841 100644 --- a/cipher/cipher-ccm.c +++ b/cipher/cipher-ccm.c @@ -164,7 +164,7 @@ _gcry_cipher_ccm_set_lengths (gcry_cipher_hd_t c, size_t encryptlen, /* Authentication field must be 4, 6, 8, 10, 12, 14 or 16. */ if ((M_ * 2 + 2) != M || M < 4 || M > 16) return GPG_ERR_INV_LENGTH; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag) + if (!c->u_mode.ccm.nonce || c->marks.tag) return GPG_ERR_INV_STATE; if (c->u_mode.ccm.lengths) return GPG_ERR_INV_STATE; @@ -235,7 +235,7 @@ _gcry_cipher_ccm_authenticate (gcry_cipher_hd_t c, const unsigned char *abuf, if (abuflen > 0 && !abuf) return GPG_ERR_INV_ARG; - if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->u_mode.ccm.tag) + if (!c->u_mode.ccm.nonce || !c->u_mode.ccm.lengths || c->marks.tag) return GPG_ERR_INV_STATE; if (abuflen > c->u_mode.ccm.aadlen) return GPG_ERR_INV_LENGTH; @@ -267,7 +267,7 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, if (c->u_mode.ccm.encryptlen > 0) return GPG_ERR_UNFINISHED; - if (!c->u_mode.ccm.tag) + if (!c->marks.tag) { burn = do_cbc_mac (c, NULL, 0, 1); /* Perform final padding. */ @@ -280,6 +280,8 @@ _gcry_cipher_ccm_tag (gcry_cipher_hd_t c, unsigned char *outbuf, if (burn) _gcry_burn_stack (burn + sizeof(void *) * 5); + + c->marks.tag = 1; } if (!check) @@ -320,7 +322,7 @@ _gcry_cipher_ccm_encrypt (gcry_cipher_hd_t c, unsigned char *outbuf, if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths || + if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0) return GPG_ERR_INV_STATE; if (inbuflen > c->u_mode.ccm.encryptlen) @@ -345,7 +347,7 @@ _gcry_cipher_ccm_decrypt (gcry_cipher_hd_t c, unsigned char *outbuf, if (outbuflen < inbuflen) return GPG_ERR_BUFFER_TOO_SHORT; - if (!c->u_mode.ccm.nonce || c->u_mode.ccm.tag || !c->u_mode.ccm.lengths || + if (!c->u_mode.ccm.nonce || c->marks.tag || !c->u_mode.ccm.lengths || c->u_mode.ccm.aadlen > 0) return GPG_ERR_INV_STATE; if (inbuflen > c->u_mode.ccm.encryptlen) diff --git a/cipher/cipher-gcm.c b/cipher/cipher-gcm.c new file mode 100644 index 0000000..b6c50bf --- /dev/null +++ b/cipher/cipher-gcm.c @@ -0,0 +1,483 @@ +/* cipher-gcm.c - Generic Galois Counter Mode implementation + * Copyright (C) 2013 Dmitry Eremin-Solenikov + * + * 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 "ath.h" +#include "bufhelp.h" +#include "./cipher-internal.h" + +#ifdef GCM_USE_TABLES +static const byte gcmR[256][2] = { + {0x00, 0x00,}, {0x01, 0xc2,}, {0x03, 0x84,}, {0x02, 0x46,}, + {0x07, 0x08,}, {0x06, 0xca,}, {0x04, 0x8c,}, {0x05, 0x4e,}, + {0x0e, 0x10,}, {0x0f, 0xd2,}, {0x0d, 0x94,}, {0x0c, 0x56,}, + {0x09, 0x18,}, {0x08, 0xda,}, {0x0a, 0x9c,}, {0x0b, 0x5e,}, + {0x1c, 0x20,}, {0x1d, 0xe2,}, {0x1f, 0xa4,}, {0x1e, 0x66,}, + {0x1b, 0x28,}, {0x1a, 0xea,}, {0x18, 0xac,}, {0x19, 0x6e,}, + {0x12, 0x30,}, {0x13, 0xf2,}, {0x11, 0xb4,}, {0x10, 0x76,}, + {0x15, 0x38,}, {0x14, 0xfa,}, {0x16, 0xbc,}, {0x17, 0x7e,}, + {0x38, 0x40,}, {0x39, 0x82,}, {0x3b, 0xc4,}, {0x3a, 0x06,}, + {0x3f, 0x48,}, {0x3e, 0x8a,}, {0x3c, 0xcc,}, {0x3d, 0x0e,}, + {0x36, 0x50,}, {0x37, 0x92,}, {0x35, 0xd4,}, {0x34, 0x16,}, + {0x31, 0x58,}, {0x30, 0x9a,}, {0x32, 0xdc,}, {0x33, 0x1e,}, + {0x24, 0x60,}, {0x25, 0xa2,}, {0x27, 0xe4,}, {0x26, 0x26,}, + {0x23, 0x68,}, {0x22, 0xaa,}, {0x20, 0xec,}, {0x21, 0x2e,}, + {0x2a, 0x70,}, {0x2b, 0xb2,}, {0x29, 0xf4,}, {0x28, 0x36,}, + {0x2d, 0x78,}, {0x2c, 0xba,}, {0x2e, 0xfc,}, {0x2f, 0x3e,}, + {0x70, 0x80,}, {0x71, 0x42,}, {0x73, 0x04,}, {0x72, 0xc6,}, + {0x77, 0x88,}, {0x76, 0x4a,}, {0x74, 0x0c,}, {0x75, 0xce,}, + {0x7e, 0x90,}, {0x7f, 0x52,}, {0x7d, 0x14,}, {0x7c, 0xd6,}, + {0x79, 0x98,}, {0x78, 0x5a,}, {0x7a, 0x1c,}, {0x7b, 0xde,}, + {0x6c, 0xa0,}, {0x6d, 0x62,}, {0x6f, 0x24,}, {0x6e, 0xe6,}, + {0x6b, 0xa8,}, {0x6a, 0x6a,}, {0x68, 0x2c,}, {0x69, 0xee,}, + {0x62, 0xb0,}, {0x63, 0x72,}, {0x61, 0x34,}, {0x60, 0xf6,}, + {0x65, 0xb8,}, {0x64, 0x7a,}, {0x66, 0x3c,}, {0x67, 0xfe,}, + {0x48, 0xc0,}, {0x49, 0x02,}, {0x4b, 0x44,}, {0x4a, 0x86,}, + {0x4f, 0xc8,}, {0x4e, 0x0a,}, {0x4c, 0x4c,}, {0x4d, 0x8e,}, + {0x46, 0xd0,}, {0x47, 0x12,}, {0x45, 0x54,}, {0x44, 0x96,}, + {0x41, 0xd8,}, {0x40, 0x1a,}, {0x42, 0x5c,}, {0x43, 0x9e,}, + {0x54, 0xe0,}, {0x55, 0x22,}, {0x57, 0x64,}, {0x56, 0xa6,}, + {0x53, 0xe8,}, {0x52, 0x2a,}, {0x50, 0x6c,}, {0x51, 0xae,}, + {0x5a, 0xf0,}, {0x5b, 0x32,}, {0x59, 0x74,}, {0x58, 0xb6,}, + {0x5d, 0xf8,}, {0x5c, 0x3a,}, {0x5e, 0x7c,}, {0x5f, 0xbe,}, + {0xe1, 0x00,}, {0xe0, 0xc2,}, {0xe2, 0x84,}, {0xe3, 0x46,}, + {0xe6, 0x08,}, {0xe7, 0xca,}, {0xe5, 0x8c,}, {0xe4, 0x4e,}, + {0xef, 0x10,}, {0xee, 0xd2,}, {0xec, 0x94,}, {0xed, 0x56,}, + {0xe8, 0x18,}, {0xe9, 0xda,}, {0xeb, 0x9c,}, {0xea, 0x5e,}, + {0xfd, 0x20,}, {0xfc, 0xe2,}, {0xfe, 0xa4,}, {0xff, 0x66,}, + {0xfa, 0x28,}, {0xfb, 0xea,}, {0xf9, 0xac,}, {0xf8, 0x6e,}, + {0xf3, 0x30,}, {0xf2, 0xf2,}, {0xf0, 0xb4,}, {0xf1, 0x76,}, + {0xf4, 0x38,}, {0xf5, 0xfa,}, {0xf7, 0xbc,}, {0xf6, 0x7e,}, + {0xd9, 0x40,}, {0xd8, 0x82,}, {0xda, 0xc4,}, {0xdb, 0x06,}, + {0xde, 0x48,}, {0xdf, 0x8a,}, {0xdd, 0xcc,}, {0xdc, 0x0e,}, + {0xd7, 0x50,}, {0xd6, 0x92,}, {0xd4, 0xd4,}, {0xd5, 0x16,}, + {0xd0, 0x58,}, {0xd1, 0x9a,}, {0xd3, 0xdc,}, {0xd2, 0x1e,}, + {0xc5, 0x60,}, {0xc4, 0xa2,}, {0xc6, 0xe4,}, {0xc7, 0x26,}, + {0xc2, 0x68,}, {0xc3, 0xaa,}, {0xc1, 0xec,}, {0xc0, 0x2e,}, + {0xcb, 0x70,}, {0xca, 0xb2,}, {0xc8, 0xf4,}, {0xc9, 0x36,}, + {0xcc, 0x78,}, {0xcd, 0xba,}, {0xcf, 0xfc,}, {0xce, 0x3e,}, + {0x91, 0x80,}, {0x90, 0x42,}, {0x92, 0x04,}, {0x93, 0xc6,}, + {0x96, 0x88,}, {0x97, 0x4a,}, {0x95, 0x0c,}, {0x94, 0xce,}, + {0x9f, 0x90,}, {0x9e, 0x52,}, {0x9c, 0x14,}, {0x9d, 0xd6,}, + {0x98, 0x98,}, {0x99, 0x5a,}, {0x9b, 0x1c,}, {0x9a, 0xde,}, + {0x8d, 0xa0,}, {0x8c, 0x62,}, {0x8e, 0x24,}, {0x8f, 0xe6,}, + {0x8a, 0xa8,}, {0x8b, 0x6a,}, {0x89, 0x2c,}, {0x88, 0xee,}, + {0x83, 0xb0,}, {0x82, 0x72,}, {0x80, 0x34,}, {0x81, 0xf6,}, + {0x84, 0xb8,}, {0x85, 0x7a,}, {0x87, 0x3c,}, {0x86, 0xfe,}, + {0xa9, 0xc0,}, {0xa8, 0x02,}, {0xaa, 0x44,}, {0xab, 0x86,}, + {0xae, 0xc8,}, {0xaf, 0x0a,}, {0xad, 0x4c,}, {0xac, 0x8e,}, + {0xa7, 0xd0,}, {0xa6, 0x12,}, {0xa4, 0x54,}, {0xa5, 0x96,}, + {0xa0, 0xd8,}, {0xa1, 0x1a,}, {0xa3, 0x5c,}, {0xa2, 0x9e,}, + {0xb5, 0xe0,}, {0xb4, 0x22,}, {0xb6, 0x64,}, {0xb7, 0xa6,}, + {0xb2, 0xe8,}, {0xb3, 0x2a,}, {0xb1, 0x6c,}, {0xb0, 0xae,}, + {0xbb, 0xf0,}, {0xba, 0x32,}, {0xb8, 0x74,}, {0xb9, 0xb6,}, + {0xbc, 0xf8,}, {0xbd, 0x3a,}, {0xbf, 0x7c,}, {0xbe, 0xbe,}, +}; + +static unsigned +bshift (unsigned char *b) +{ + unsigned char c; + int i; + c = b[15] & 1; + for (i = 15; i > 0; i--) + { + b[i] = (b[i] >> 1) | (b[i - 1] << 7); + } + b[i] >>= 1; + return c; +} + +static void +fillM (unsigned char *h, unsigned char *M) +{ + int i, j; + memset (&M[0 * 16], 0, 16); + memcpy (&M[8 * 16], h, 16); + for (i = 4; i > 0; i /= 2) + { + memcpy (&M[i * 16], &M[2 * i * 16], 16); + if (bshift (&M[i * 16])) + M[i * 16 + 0] ^= 0xe1; + } + for (i = 2; i < 16; i *= 2) + for (j = 1; j < i; j++) + buf_xor (&M[(i + j) * 16], &M[i * 16], &M[j * 16], 16); +} + +static void +ghash (unsigned char *result, const unsigned char *buf, + const unsigned char *gcmM) +{ + unsigned char V[16]; + int i; + + buf_xor (V, result, buf, 16); + + memset (result, 0, 16); + + for (i = 15; i >= 0; i--) + { + byte A = result[15]; + byte T[16]; + int j; + const byte *M = &gcmM[(V[i] & 0xf) * 16]; + + memmove (result + 1, result, 15); + result[0] = gcmR[A][0]; + result[1] ^= gcmR[A][1]; + + T[0] = M[0] >> 4; + for (j = 1; j < 16; j++) + T[j] = (M[j] >> 4) | (M[j - 1] << 4); + T[0] ^= gcmR[(M[15] & 0xf) << 4][0]; + T[1] ^= gcmR[(M[15] & 0xf) << 4][1]; + buf_xor (T, T, &gcmM[(V[i] >> 4) * 16], 16); + buf_xor (result, result, T, 16); + } +} + +#define GHASH(c, result, buf) ghash (result, buf, c->gcm_table); + +#else + +static unsigned long +bshift (unsigned long *b) +{ + unsigned long c; + int i; + c = b[3] & 1; + for (i = 3; i > 0; i--) + { + b[i] = (b[i] >> 1) | (b[i - 1] << 31); + } + b[i] >>= 1; + return c; +} + +static void +ghash (unsigned char *hsub, unsigned char *result, const unsigned char *buf) +{ + unsigned long V[4]; + int i, j; + byte *p; + +#ifdef WORDS_BIGENDIAN + p = result; +#else + unsigned long T[4]; + + buf_xor (V, result, buf, 16); + for (i = 0; i < 4; i++) + { + V[i] = (V[i] & 0x00ff00ff) << 8 | (V[i] & 0xff00ff00) >> 8; + V[i] = (V[i] & 0x0000ffff) << 16 | (V[i] & 0xffff0000) >> 16; + } + p = (byte *) T; +#endif + + memset (p, 0, 16); + + for (i = 0; i < 16; i++) + { + for (j = 0x80; j; j >>= 1) + { + if (hsub[i] & j) + buf_xor (p, p, V, 16); + if (bshift (V)) + V[0] ^= 0xe1000000; + } + } +#ifndef WORDS_BIGENDIAN + for (i = 0, p = (byte *) T; i < 16; i += 4, p += 4) + { + result[i + 0] = p[3]; + result[i + 1] = p[2]; + result[i + 2] = p[1]; + result[i + 3] = p[0]; + } +#endif +} + +#define fillM(h, M) do { } while (0) + +#define GHASH(c, result, buf) ghash (c->u_iv.iv, result, buf); +#endif + + +gcry_err_code_t +_gcry_cipher_gcm_encrypt (gcry_cipher_hd_t c, + byte * outbuf, unsigned int outbuflen, + const byte * inbuf, unsigned int inbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (blocksize >= 0x20) + return GPG_ERR_CIPHER_ALGO; + if (blocksize != 0x10) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.iv) + { + memset (tmp, 0, 16); + _gcry_cipher_gcm_setiv (c, tmp, 16); + } + + while (inbuflen) + { + for (i = blocksize; i > blocksize - 4; i--) + { + c->u_ctr.ctr[i - 1]++; + if (c->u_ctr.ctr[i - 1] != 0) + break; + } + + n = blocksize < inbuflen ? blocksize : inbuflen; + + i = blocksize - 1; + c->length[i] += n * 8; + for (; c->length[i] == 0 && i > blocksize / 2; i--) + c->length[i - 1]++; + + c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + if (n < blocksize) + { + buf_xor_2dst (outbuf, tmp, inbuf, n); + memset (tmp + n, 0, blocksize - n); + GHASH (c, c->u_tag.tag, tmp); + } + else + { + buf_xor (outbuf, tmp, inbuf, n); + GHASH (c, c->u_tag.tag, outbuf); + } + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_decrypt (gcry_cipher_hd_t c, + byte * outbuf, unsigned int outbuflen, + const byte * inbuf, unsigned int inbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (blocksize >= 0x20) + return GPG_ERR_CIPHER_ALGO; + if (blocksize != 0x10) + return GPG_ERR_CIPHER_ALGO; + if (outbuflen < inbuflen) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.iv) + { + memset (tmp, 0, 16); + _gcry_cipher_gcm_setiv (c, tmp, 16); + } + + while (inbuflen) + { + for (i = blocksize; i > blocksize - 4; i--) + { + c->u_ctr.ctr[i - 1]++; + if (c->u_ctr.ctr[i - 1] != 0) + break; + } + + n = blocksize < inbuflen ? blocksize : inbuflen; + if (n < blocksize) + { + memcpy (tmp, inbuf, n); + memset (tmp + n, 0, blocksize - n); + GHASH (c, c->u_tag.tag, tmp); + } + else + { + GHASH (c, c->u_tag.tag, inbuf); + } + + i = blocksize - 1; + c->length[i] += n * 8; + for (; c->length[i] == 0 && i > blocksize / 2; i--) + c->length[i - 1]++; + + c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr); + + buf_xor (outbuf, inbuf, tmp, n); + + inbuflen -= n; + outbuf += n; + inbuf += n; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_authenticate (gcry_cipher_hd_t c, + const byte * aadbuf, unsigned int aadbuflen) +{ + unsigned int n; + int i; + unsigned int blocksize = c->spec->blocksize; + unsigned char tmp[MAX_BLOCKSIZE]; + + if (!c->marks.iv) + { + memset (tmp, 0, 16); + _gcry_cipher_gcm_setiv (c, tmp, 16); + } + + n = aadbuflen; + i = blocksize / 2; + c->length[i - 1] = (n % 0x20) * 8; + n /= 0x20; + for (; n && i > 0; i--, n >>= 8) + c->length[i - 1] = n & 0xff; + + while (aadbuflen >= blocksize) + { + GHASH (c, c->u_tag.tag, aadbuf); + + aadbuflen -= blocksize; + aadbuf += blocksize; + } + + if (aadbuflen != 0) + { + memcpy (tmp, aadbuf, aadbuflen); + memset (tmp + aadbuflen, 0, blocksize - aadbuflen); + + GHASH (c, c->u_tag.tag, tmp); + } + + return 0; +} + +void +_gcry_cipher_gcm_setiv (gcry_cipher_hd_t c, + const byte * iv, unsigned int ivlen) +{ + memset (c->length, 0, 16); + memset (c->u_tag.tag, 0, 16); + c->spec->encrypt (&c->context.c, c->u_iv.iv, c->u_tag.tag); + + fillM (c->u_iv.iv, c->gcm_table); + + if (ivlen != 16 - 4) + { + unsigned char tmp[MAX_BLOCKSIZE]; + unsigned n; + memset (c->u_ctr.ctr, 0, 16); + for (n = ivlen; n >= 16; n -= 16, iv += 16) + GHASH (c, c->u_ctr.ctr, iv); + if (n != 0) + { + memcpy (tmp, iv, n); + memset (tmp + n, 0, 16 - n); + GHASH (c, c->u_ctr.ctr, tmp); + } + memset (tmp, 0, 16); + n = 16; + tmp[n - 1] = (ivlen % 0x20) * 8; + ivlen /= 0x20; + n--; + for (; n > 0; n--, ivlen >>= 8) + tmp[n - 1] = ivlen & 0xff; + GHASH (c, c->u_ctr.ctr, tmp); + } + else + { + memcpy (c->u_ctr.ctr, iv, ivlen); + c->u_ctr.ctr[12] = c->u_ctr.ctr[13] = c->u_ctr.ctr[14] = 0; + c->u_ctr.ctr[15] = 1; + } + + c->spec->encrypt (&c->context.c, c->lastiv, c->u_ctr.ctr); + c->marks.iv = 1; + +} + +static gcry_err_code_t +_gcry_cipher_gcm_tag (gcry_cipher_hd_t c, + byte * outbuf, unsigned int outbuflen, int check) +{ + if (outbuflen < 16) + return GPG_ERR_BUFFER_TOO_SHORT; + + if (!c->marks.tag) + { + GHASH (c, c->u_tag.tag, c->length); + buf_xor (c->u_tag.tag, c->lastiv, c->u_tag.tag, 16); + c->marks.tag = 1; + } + memcpy (outbuf, c->u_tag.tag, 16); + if (!check) + { + memcpy (outbuf, c->u_tag.tag, outbuflen); + return GPG_ERR_NO_ERROR; + } + else + { + int diff, i; + + /* Constant-time compare. */ + for (i = 0, diff = 0; i < outbuflen; i++) + diff -= ! !(outbuf[i] - c->u_tag.tag[i]); + + return !diff ? GPG_ERR_NO_ERROR : GPG_ERR_CHECKSUM; + } + + return 0; +} + +gcry_err_code_t +_gcry_cipher_gcm_get_tag (gcry_cipher_hd_t c, unsigned char *outtag, + size_t taglen) +{ + return _gcry_cipher_gcm_tag (c, outtag, taglen, 0); +} + + +gcry_err_code_t +_gcry_cipher_gcm_check_tag (gcry_cipher_hd_t c, const unsigned char *intag, + size_t taglen) +{ + return _gcry_cipher_gcm_tag (c, (unsigned char *) intag, taglen, 1); +} diff --git a/cipher/cipher-internal.h b/cipher/cipher-internal.h index 44f43a4..7da9c68 100644 --- a/cipher/cipher-internal.h +++ b/cipher/cipher-internal.h @@ -35,6 +35,9 @@ # define NEED_16BYTE_ALIGNED_CONTEXT 1 #endif +/* Undef this symbol to trade GCM speed for 256 bytes of memory per context */ +#define GCM_USE_TABLES 1 + /* A VIA processor with the Padlock engine as well as the Intel AES_NI instructions require an alignment of most data on a 16 byte @@ -96,6 +99,7 @@ struct gcry_cipher_handle struct { unsigned int key:1; /* Set to 1 if a key has been set. */ unsigned int iv:1; /* Set to 1 if a IV has been set. */ + unsigned int tag:1; /* Set to 1 if a tag is finalized. */ } marks; /* The initialization vector. For best performance we make sure @@ -114,9 +118,19 @@ struct gcry_cipher_handle unsigned char ctr[MAX_BLOCKSIZE]; } u_ctr; + /* The interim tag for GCM mode. */ + union { + cipher_context_alignment_t iv_align; + unsigned char tag[MAX_BLOCKSIZE]; + } u_tag; + /* Space to save an IV or CTR for chaining operations. */ unsigned char lastiv[MAX_BLOCKSIZE]; int unused; /* Number of unused bytes in LASTIV. */ + unsigned char length[MAX_BLOCKSIZE]; /* bit counters for GCM */ +#ifdef GCM_USE_TABLES + unsigned char gcm_table[16 * 16]; /* pre-calculated table for GCM */ +#endif union { /* Mode specific storage for CCM mode. */ @@ -134,7 +148,6 @@ struct gcry_cipher_handle unsigned int nonce:1;/* Set to 1 if nonce has been set. */ unsigned int lengths:1; /* Set to 1 if CCM length parameters has been processed. */ - unsigned int tag:1; /* Set to 1 if tag has been finalized. */ } ccm; /* Mode specific storage for CMAC mode. */ struct { @@ -224,5 +237,26 @@ gcry_err_code_t _gcry_cipher_ccm_check_tag /* */ (gcry_cipher_hd_t c, const unsigned char *intag, size_t taglen); +/*-- cipher-gcm.c --*/ +gcry_err_code_t _gcry_cipher_gcm_encrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen); +gcry_err_code_t _gcry_cipher_gcm_decrypt +/* */ (gcry_cipher_hd_t c, + unsigned char *outbuf, unsigned int outbuflen, + const unsigned char *inbuf, unsigned int inbuflen); +void _gcry_cipher_gcm_setiv +/* */ (gcry_cipher_hd_t c, + const unsigned char *iv, unsigned int ivlen); +gcry_err_code_t _gcry_cipher_gcm_authenticate +/* */ (gcry_cipher_hd_t c, + const unsigned char *aadbuf, unsigned int aadbuflen); +gcry_err_code_t _gcry_cipher_gcm_get_tag +/* */ (gcry_cipher_hd_t c, + unsigned char *outtag, size_t taglen); +gcry_err_code_t _gcry_cipher_gcm_check_tag +/* */ (gcry_cipher_hd_t c, + const unsigned char *intag, size_t taglen); #endif /*G10_CIPHER_INTERNAL_H*/ diff --git a/cipher/cipher.c b/cipher/cipher.c index b68703e..bba6abb 100644 --- a/cipher/cipher.c +++ b/cipher/cipher.c @@ -407,6 +407,7 @@ _gcry_cipher_open_internal (gcry_cipher_hd_t *handle, case GCRY_CIPHER_MODE_CTR: case GCRY_CIPHER_MODE_AESWRAP: case GCRY_CIPHER_MODE_CMAC: + case GCRY_CIPHER_MODE_GCM: if (!spec->encrypt || !spec->decrypt) err = GPG_ERR_INV_CIPHER_MODE; break; @@ -609,6 +610,13 @@ cipher_setkey (gcry_cipher_hd_t c, byte *key, size_t keylen) static void cipher_setiv (gcry_cipher_hd_t c, const byte *iv, size_t ivlen) { + /* GCM has its own IV handler */ + if (c->mode == GCRY_CIPHER_MODE_GCM) + { + _gcry_cipher_gcm_setiv (c, iv, ivlen); + return; + } + /* If the cipher has its own IV handler, we use only this one. This is currently used for stream ciphers requiring a nonce. */ if (c->spec->setiv) @@ -767,6 +775,10 @@ cipher_encrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = GPG_ERR_INV_CIPHER_MODE; break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_encrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stencrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -871,6 +883,10 @@ cipher_decrypt (gcry_cipher_hd_t c, byte *outbuf, size_t outbuflen, rc = GPG_ERR_INV_CIPHER_MODE; break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_decrypt (c, outbuf, outbuflen, inbuf, inbuflen); + break; + case GCRY_CIPHER_MODE_STREAM: c->spec->stdecrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf, inbuflen); @@ -1000,6 +1016,10 @@ _gcry_cipher_authenticate (gcry_cipher_hd_t hd, const void *abuf, rc = _gcry_cipher_cmac_authenticate (hd, abuf, abuflen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_authenticate (hd, abuf, abuflen); + break; + default: log_error ("gcry_cipher_authenticate: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -1024,6 +1044,10 @@ _gcry_cipher_gettag (gcry_cipher_hd_t hd, void *outtag, size_t taglen) rc = _gcry_cipher_cmac_get_tag (hd, outtag, taglen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_get_tag (hd, outtag, taglen); + break; + default: log_error ("gcry_cipher_gettag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; @@ -1048,6 +1072,10 @@ _gcry_cipher_checktag (gcry_cipher_hd_t hd, const void *intag, size_t taglen) rc = _gcry_cipher_cmac_check_tag (hd, intag, taglen); break; + case GCRY_CIPHER_MODE_GCM: + rc = _gcry_cipher_gcm_check_tag (hd, intag, taglen); + break; + default: log_error ("gcry_cipher_checktag: invalid mode %d\n", hd->mode); rc = GPG_ERR_INV_CIPHER_MODE; diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 3e8e72c..24f7af6 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -895,7 +895,8 @@ enum gcry_cipher_modes GCRY_CIPHER_MODE_OFB = 5, /* Outer feedback. */ GCRY_CIPHER_MODE_CTR = 6, /* Counter. */ GCRY_CIPHER_MODE_AESWRAP= 7, /* AES-WRAP algorithm. */ - GCRY_CIPHER_MODE_CCM = 8 /* Counter with CBC-MAC. */ + GCRY_CIPHER_MODE_CCM = 8, /* Counter with CBC-MAC. */ + GCRY_CIPHER_MODE_GCM = 9 /* Galois Counter Mode. */ }; /* Flags used with the open function. */ @@ -907,6 +908,9 @@ enum gcry_cipher_flags GCRY_CIPHER_CBC_MAC = 8 /* Enable CBC message auth. code (MAC). */ }; +/* GCM works only with blocks of 128 bits */ +#define GCRY_GCM_BLOCK_LEN (128 / 8) + /* CCM works only with blocks of 128 bits. */ #define GCRY_CCM_BLOCK_LEN (128 / 8) diff --git a/tests/basic.c b/tests/basic.c index f9c6497..b4541a0 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -1137,6 +1137,340 @@ check_ofb_cipher (void) fprintf (stderr, " Completed OFB checks.\n"); } +static void +check_gcm_cipher (void) +{ + struct tv + { + int algo; + char key[MAX_DATA_LEN]; + char iv[MAX_DATA_LEN]; + int ivlen; + unsigned char aad[MAX_DATA_LEN]; + int aadlen; + unsigned char plaintext[MAX_DATA_LEN]; + int inlen; + char out[MAX_DATA_LEN]; + char tag[MAX_DATA_LEN]; + } tv[] = + { + /* http://csrc.nist.gov/groups/ST/toolkit/BCM/documents/proposedmodes/gcm/gcm-revised-spec.pdf */ + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "", + 0, + "", + "\x58\xe2\xfc\xce\xfa\x7e\x30\x61\x36\x7f\x1d\x57\xa4\xe7\x45\x5a" }, + { GCRY_CIPHER_AES, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 12, + "", 0, + "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", + 16, + "\x03\x88\xda\xce\x60\xb6\xa3\x92\xf3\x28\xc2\xb9\x71\xb2\xfe\x78", + "\xab\x6e\x47\xd4\x2c\xec\x13\xbd\xf5\x3a\x67\xb2\x12\x57\xbd\xdf" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "", 0, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39\x1a\xaf\xd2\x55", + 64, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", + "\x4d\x5c\x2a\xf3\x27\xcd\x64\xa6\x2c\xf3\x5a\xbd\x2b\xa6\xfa\xb4" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad\xde\xca\xf8\x88", 12, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x42\x83\x1e\xc2\x21\x77\x74\x24\x4b\x72\x21\xb7\x84\xd0\xd4\x9c" + "\xe3\xaa\x21\x2f\x2c\x02\xa4\xe0\x35\xc1\x7e\x23\x29\xac\xa1\x2e" + "\x21\xd5\x14\xb2\x54\x66\x93\x1c\x7d\x8f\x6a\x5a\xac\x84\xaa\x05" + "\x1b\xa3\x0b\x39\x6a\x0a\xac\x97\x3d\x58\xe0\x91\x47\x3f\x59\x85", + "\x5b\xc9\x4f\xbc\x32\x21\xa5\xdb\x94\xfa\xe9\x5a\xe7\x12\x1a\x47" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\xca\xfe\xba\xbe\xfa\xce\xdb\xad", 8, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x61\x35\x3b\x4c\x28\x06\x93\x4a\x77\x7f\xf5\x1f\xa2\x2a\x47\x55" + "\x69\x9b\x2a\x71\x4f\xcd\xc6\xf8\x37\x66\xe5\xf9\x7b\x6c\x74\x23" + "\x73\x80\x69\x00\xe4\x9f\x24\xb2\x2b\x09\x75\x44\xd4\x89\x6b\x42" + "\x49\x89\xb5\xe1\xeb\xac\x0f\x07\xc2\x3f\x45\x98", + "\x36\x12\xd2\xe7\x9e\x3b\x07\x85\x56\x1b\xe1\x4a\xac\xa2\xfc\xcb" }, + { GCRY_CIPHER_AES, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x8c\xe2\x49\x98\x62\x56\x15\xb6\x03\xa0\x33\xac\xa1\x3f\xb8\x94" + "\xbe\x91\x12\xa5\xc3\xa2\x11\xa8\xba\x26\x2a\x3c\xca\x7e\x2c\xa7" + "\x01\xe4\xa9\xa4\xfb\xa4\x3c\x90\xcc\xdc\xb2\x81\xd4\x8c\x7c\x6f" + "\xd6\x28\x75\xd2\xac\xa4\x17\x03\x4c\x34\xae\xe5", + "\x61\x9c\xc5\xae\xff\xfe\x0b\xfa\x46\x2a\xf4\x3c\x16\x99\xd0\x50" }, + { GCRY_CIPHER_AES192, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\xd2\x7e\x88\x68\x1c\xe3\x24\x3c\x48\x30\x16\x5a\x8f\xdc\xf9\xff" + "\x1d\xe9\xa1\xd8\xe6\xb4\x47\xef\x6e\xf7\xb7\x98\x28\x66\x6e\x45" + "\x81\xe7\x90\x12\xaf\x34\xdd\xd9\xe2\xf0\x37\x58\x9b\x29\x2d\xb3" + "\xe6\x7c\x03\x67\x45\xfa\x22\xe7\xe9\xb7\x37\x3b", + "\xdc\xf5\x66\xff\x29\x1c\x25\xbb\xb8\x56\x8f\xc3\xd3\x76\xa6\xd9" }, + { GCRY_CIPHER_AES256, + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08" + "\xfe\xff\xe9\x92\x86\x65\x73\x1c\x6d\x6a\x8f\x94\x67\x30\x83\x08", + "\x93\x13\x22\x5d\xf8\x84\x06\xe5\x55\x90\x9c\x5a\xff\x52\x69\xaa" + "\x6a\x7a\x95\x38\x53\x4f\x7d\xa1\xe4\xc3\x03\xd2\xa3\x18\xa7\x28" + "\xc3\xc0\xc9\x51\x56\x80\x95\x39\xfc\xf0\xe2\x42\x9a\x6b\x52\x54" + "\x16\xae\xdb\xf5\xa0\xde\x6a\x57\xa6\x37\xb3\x9b", 60, + "\xfe\xed\xfa\xce\xde\xad\xbe\xef\xfe\xed\xfa\xce\xde\xad\xbe\xef" + "\xab\xad\xda\xd2", 20, + "\xd9\x31\x32\x25\xf8\x84\x06\xe5\xa5\x59\x09\xc5\xaf\xf5\x26\x9a" + "\x86\xa7\xa9\x53\x15\x34\xf7\xda\x2e\x4c\x30\x3d\x8a\x31\x8a\x72" + "\x1c\x3c\x0c\x95\x95\x68\x09\x53\x2f\xcf\x0e\x24\x49\xa6\xb5\x25" + "\xb1\x6a\xed\xf5\xaa\x0d\xe6\x57\xba\x63\x7b\x39", + 60, + "\x5a\x8d\xef\x2f\x0c\x9e\x53\xf1\xf7\x5d\x78\x53\x65\x9e\x2a\x20" + "\xee\xb2\xb2\x2a\xaf\xde\x64\x19\xa0\x58\xab\x4f\x6f\x74\x6b\xf4" + "\x0f\xc0\xc3\xb7\x80\xf2\x44\x45\x2d\xa3\xeb\xf1\xc5\xd8\x2c\xde" + "\xa2\x41\x89\x97\x20\x0e\xf8\x2e\x44\xae\x7e\x3f", + "\xa4\x4a\x82\x66\xee\x1c\x8e\xb0\xc8\xb5\xd4\xcf\x5a\xe9\xf1\x9a" } + }; + + gcry_cipher_hd_t hde, hdd; + unsigned char out[MAX_DATA_LEN]; + int i, keylen; + gcry_error_t err = 0; + + if (verbose) + fprintf (stderr, " Starting GCM checks.\n"); + + for (i = 0; i < sizeof (tv) / sizeof (tv[0]); i++) + { + if (verbose) + fprintf (stderr, " checking GCM mode for %s [%i]\n", + gcry_cipher_algo_name (tv[i].algo), + tv[i].algo); + err = gcry_cipher_open (&hde, tv[i].algo, GCRY_CIPHER_MODE_GCM, 0); + if (!err) + err = gcry_cipher_open (&hdd, tv[i].algo, GCRY_CIPHER_MODE_GCM, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_open failed: %s\n", gpg_strerror (err)); + return; + } + + keylen = gcry_cipher_get_algo_keylen(tv[i].algo); + if (!keylen) + { + fail ("aes-gcm, gcry_cipher_get_algo_keylen failed\n"); + return; + } + + err = gcry_cipher_setkey (hde, tv[i].key, keylen); + if (!err) + err = gcry_cipher_setkey (hdd, tv[i].key, keylen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setkey failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_authenticate(hde, tv[i].aad, tv[i].aadlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_authenticate (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + if (!err) + err = gcry_cipher_authenticate(hdd, tv[i].aad, tv[i].aadlen); + if (err) + { + fail ("aes-gcm, de gcry_cipher_authenticate (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_encrypt (hde, out, MAX_DATA_LEN, + tv[i].plaintext, + tv[i].inlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_encrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("aes-gcm, encrypt mismatch entry %d\n", i); + + err = gcry_cipher_decrypt (hdd, out, tv[i].inlen, NULL, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_decrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("aes-gcm, decrypt mismatch entry %d\n", i); + +#define TAGLEN 16 + err = gcry_cipher_gettag (hde, out, TAGLEN); /* FIXME */ + if (err) + { + fail ("aes-gcm, gcry_cipher_gettag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + if (memcmp (tv[i].tag, out, TAGLEN)) + fail ("aes-gcm, encrypt tag mismatch entry %d\n", i); + + + err = gcry_cipher_checktag (hdd, out, TAGLEN); + if (err) + { + fail ("aes-gcm, gcry_cipher_checktag(%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + err = gcry_cipher_reset(hde); + if (!err) + err = gcry_cipher_reset(hdd); + if (err) + { + fail ("aes-gcm, gcry_cipher_reset (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + +#if 0 + /* gcry_cipher_reset clears the IV */ + err = gcry_cipher_setiv (hde, tv[i].iv, tv[i].ivlen); + if (!err) + err = gcry_cipher_setiv (hdd, tv[i].iv, tv[i].ivlen); + if (err) + { + fail ("aes-gcm, gcry_cipher_setiv failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + + /* this time we encrypt and decrypt one byte at a time */ + int byteNum; + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_encrypt (hde, out+byteNum, 1, + (tv[i].plaintext) + byteNum, + 1); + if (err) + { + fail ("aes-gcm, gcry_cipher_encrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].out, out, tv[i].inlen)) + fail ("aes-gcm, encrypt mismatch entry %d\n", i); + + for (byteNum = 0; byteNum < tv[i].inlen; ++byteNum) + { + err = gcry_cipher_decrypt (hdd, out+byteNum, 1, NULL, 0); + if (err) + { + fail ("aes-gcm, gcry_cipher_decrypt (%d) failed: %s\n", + i, gpg_strerror (err)); + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + return; + } + } + + if (memcmp (tv[i].plaintext, out, tv[i].inlen)) + fail ("aes-gcm, decrypt mismatch entry %d\n", i); +#endif + + gcry_cipher_close (hde); + gcry_cipher_close (hdd); + } + if (verbose) + fprintf (stderr, " Completed GCM checks.\n"); +} + static void check_ccm_cipher (void) @@ -3188,6 +3522,8 @@ check_ciphers (void) check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, 0); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CBC, GCRY_CIPHER_CBC_CTS); check_one_cipher (algos[i], GCRY_CIPHER_MODE_CTR, 0); + if (gcry_cipher_get_algo_blklen (algos[i]) == GCRY_GCM_BLOCK_LEN) + check_one_cipher (algos[i], GCRY_CIPHER_MODE_GCM, 0); } for (i = 0; algos2[i]; i++) @@ -3226,6 +3562,7 @@ check_cipher_modes(void) check_cfb_cipher (); check_ofb_cipher (); check_ccm_cipher (); + check_gcm_cipher (); check_stream_cipher (); check_stream_cipher_large_block (); diff --git a/tests/bench-slope.c b/tests/bench-slope.c index f9d3c46..d29a4ad 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -787,6 +787,127 @@ static struct bench_ops ccm_authenticate_ops = { &bench_ccm_authenticate_do_bench }; +static void +bench_gcm_encrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16]; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_encrypt (hd, buf, buflen, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_gettag (hd, tag, sizeof (tag)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static void +bench_gcm_decrypt_do_bench (struct bench_obj *obj, void *buf, size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16] = { 0, }; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_decrypt (hd, buf, buflen, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_checktag (hd, tag, sizeof (tag)); + if (gpg_err_code (err) == GPG_ERR_CHECKSUM) + err = gpg_error (GPG_ERR_NO_ERROR); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static void +bench_gcm_authenticate_do_bench (struct bench_obj *obj, void *buf, + size_t buflen) +{ + gcry_cipher_hd_t hd = obj->priv; + int err; + char tag[16] = { 0, }; + char nonce[12] = { 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, + 0xdb, 0xad, 0xde, 0xca, 0xf8, 0x88, }; + char data = 0xff; + + gcry_cipher_setiv (hd, nonce, sizeof (nonce)); + + err = gcry_cipher_authenticate (hd, buf, buflen); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_authenticate failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_encrypt (hd, &data, sizeof (data), &data, sizeof (data)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_encrypt failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } + + err = gcry_cipher_gettag (hd, tag, sizeof (tag)); + if (err) + { + fprintf (stderr, PGM ": gcry_cipher_gettag failed: %s\n", + gpg_strerror (err)); + gcry_cipher_close (hd); + exit (1); + } +} + +static struct bench_ops gcm_encrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_encrypt_do_bench +}; + +static struct bench_ops gcm_decrypt_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_decrypt_do_bench +}; + +static struct bench_ops gcm_authenticate_ops = { + &bench_encrypt_init, + &bench_encrypt_free, + &bench_gcm_authenticate_do_bench +}; + static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_ECB, "ECB enc", &encrypt_ops}, @@ -802,6 +923,9 @@ static struct bench_cipher_mode cipher_modes[] = { {GCRY_CIPHER_MODE_CCM, "CCM enc", &ccm_encrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM dec", &ccm_decrypt_ops}, {GCRY_CIPHER_MODE_CCM, "CCM auth", &ccm_authenticate_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM enc", &gcm_encrypt_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM dec", &gcm_decrypt_ops}, + {GCRY_CIPHER_MODE_GCM, "GCM auth", &gcm_authenticate_ops}, {0}, }; @@ -834,6 +958,10 @@ cipher_bench_one (int algo, struct bench_cipher_mode *pmode) if (mode.mode == GCRY_CIPHER_MODE_CCM && blklen != GCRY_CCM_BLOCK_LEN) return; + /* CCM has restrictions for block-size */ + if (mode.mode == GCRY_CIPHER_MODE_GCM && blklen != GCRY_GCM_BLOCK_LEN) + return; + printf (" %14s | ", mode.name); fflush (stdout); diff --git a/tests/benchmark.c b/tests/benchmark.c index c4accd3..3058bd5 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -620,6 +620,8 @@ cipher_bench ( const char *algoname ) { GCRY_CIPHER_MODE_CTR, " CTR", 0 }, { GCRY_CIPHER_MODE_CCM, " CCM", 0, ccm_aead_init, GCRY_CCM_BLOCK_LEN, 8 }, + { GCRY_CIPHER_MODE_GCM, " GCM", 0, + NULL, GCRY_GCM_BLOCK_LEN, GCRY_GCM_BLOCK_LEN }, { GCRY_CIPHER_MODE_STREAM, "", 0 }, {0} }; From phcoder at gmail.com Fri Nov 22 05:24:44 2013 From: phcoder at gmail.com (=?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?=) Date: Fri, 22 Nov 2013 05:24:44 +0100 Subject: [PATCH] longlong.h on mips with clang Message-ID: <528EDC8C.7080808@gmail.com> clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. Hence following patch: diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h index 8c8260e..6f8dda7 100644 --- a/grub-core/lib/libgcrypt/mpi/longlong.h +++ b/grub-core/lib/libgcrypt/mpi/longlong.h @@ -749,7 +749,7 @@ extern USItype __udiv_qrnnd (); ************** MIPS ***************** ***************************************/ #if defined (__mips__) && W_TYPE_SIZE == 32 -#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#if defined (__clang__) || (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) #define umul_ppmm(w1, w0, u, v) \ do { \ UDItype _r; Resulting assembly is afc: 01a20019 multu t5,v0 b00: 00006012 mflo t4 b04: 00000810 mfhi at which matches the intent. -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 291 bytes Desc: OpenPGP digital signature URL: From jussi.kivilinna at iki.fi Fri Nov 22 13:20:13 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 22 Nov 2013 14:20:13 +0200 Subject: [PATCH] Add GMAC to MAC API Message-ID: <20131122122013.17443.91601.stgit@localhost6.localdomain6> * cipher/Makefile.am: Add 'mac-gmac.c'. * cipher/mac-gmac.c: New. * cipher/mac-internal.h (gcry_mac_handle): Add 'u.gcm'. (_gcry_mac_type_spec_gmac_aes, _gcry_mac_type_spec_gmac_twofish) (_gcry_mac_type_spec_gmac_serpent, _gcry_mac_type_spec_gmac_seed) (_gcry_mac_type_spec_gmac_camellia): New externs. * cipher/mac.c (mac_list): Add GMAC specifications. * doc/gcrypt.texi: Add mention of GMAC. * src/gcrypt.h.in (gcry_mac_algos): Add GCM algorithms. * tests/basic.c (check_one_mac): Add support for MAC IVs. (check_mac): Add support for MAC IVs and add GMAC test vectors. * tests/bench-slope.c (mac_bench): Iterate algorithm numbers to 499. * tests/benchmark.c (mac_bench): Iterate algorithm numbers to 499. -- Signed-off-by: Jussi Kivilinna --- cipher/Makefile.am | 2 - cipher/mac-gmac.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ cipher/mac-internal.h | 23 ++++++ cipher/mac.c | 5 + doc/gcrypt.texi | 34 +++++++-- src/gcrypt.h.in | 8 ++ tests/basic.c | 57 ++++++++++++++- tests/bench-slope.c | 2 - tests/benchmark.c | 2 - 9 files changed, 302 insertions(+), 15 deletions(-) create mode 100644 cipher/mac-gmac.c diff --git a/cipher/Makefile.am b/cipher/Makefile.am index e29b28d..ff9deca 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -45,7 +45,7 @@ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ -mac-hmac.c mac-cmac.c \ +mac-hmac.c mac-cmac.c mac-gmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c new file mode 100644 index 0000000..5b7313f --- /dev/null +++ b/cipher/mac-gmac.c @@ -0,0 +1,184 @@ +/* mac-gmac.c - GMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "./mac-internal.h" + + +static int +map_mac_algo_to_cipher (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_CIPHER_NONE; + case GCRY_MAC_GMAC_AES: + return GCRY_CIPHER_AES; + case GCRY_MAC_GMAC_CAMELLIA: + return GCRY_CIPHER_CAMELLIA128; + case GCRY_MAC_GMAC_TWOFISH: + return GCRY_CIPHER_TWOFISH; + case GCRY_MAC_GMAC_SERPENT: + return GCRY_CIPHER_SERPENT128; + case GCRY_MAC_GMAC_SEED: + return GCRY_CIPHER_SEED; + } +} + + +static gcry_err_code_t +gmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_cipher_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + int cipher_algo; + unsigned int flags; + + cipher_algo = map_mac_algo_to_cipher (h->spec->algo); + flags = (secure ? GCRY_CIPHER_SECURE : 0); + + err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM, + flags); + if (err) + return err; + + h->u.gmac.cipher_algo = cipher_algo; + h->u.gmac.ctx = hd; + return 0; +} + + +static void +gmac_close (gcry_mac_hd_t h) +{ + _gcry_cipher_close (h->u.gmac.ctx); + h->u.gmac.ctx = NULL; +} + + +static gcry_err_code_t +gmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + return _gcry_cipher_setkey (h->u.gmac.ctx, key, keylen); +} + + +static gcry_err_code_t +gmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) +{ + return _gcry_cipher_gcm_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_gcm_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_gcm_get_tag (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_gcm_check_tag (h->u.gmac.ctx, buf, buflen); +} + + +static unsigned int +gmac_get_maclen (int 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 +}; + + +#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-internal.h b/cipher/mac-internal.h index 146b218..2a5e7c6 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -103,6 +103,10 @@ struct gcry_mac_handle int cipher_algo; unsigned int blklen; } cmac; + struct { + gcry_cipher_hd_t ctx; + int cipher_algo; + } gmac; } u; }; @@ -180,3 +184,22 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; #if USE_GOST28147 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; #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 diff --git a/cipher/mac.c b/cipher/mac.c index 8d1dec0..5ac8729 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -74,21 +74,26 @@ static gcry_mac_spec_t *mac_list[] = { #endif #if USE_AES &_gcry_mac_type_spec_cmac_aes, + &_gcry_mac_type_spec_gmac_aes, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, + &_gcry_mac_type_spec_gmac_twofish, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, + &_gcry_mac_type_spec_gmac_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, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, + &_gcry_mac_type_spec_gmac_camellia, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 1f6ceec..4870a1c 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3529,6 +3529,26 @@ block cipher algorithm. This is CMAC message authentication algorithm based on the GOST 28147-89 block cipher algorithm. + at item GCRY_MAC_GMAC_AES +This is GMAC (GCM mode based MAC) message authentication algorithm based on +the AES block cipher algorithm. + + at item GCRY_MAC_GMAC_CAMELLIA +This is GMAC message authentication algorithm based on the Camellia +block cipher algorithm. + + at item GCRY_MAC_GMAC_TWOFISH +This is GMAC message authentication algorithm based on the Twofish +block cipher algorithm. + + at item GCRY_MAC_GMAC_SERPENT +This is GMAC message authentication algorithm based on the Serpent +block cipher algorithm. + + at item GCRY_MAC_GMAC_SEED +This is GMAC message authentication algorithm based on the SEED +block cipher algorithm. + @end table @c end table of MAC algorithms @@ -3574,13 +3594,13 @@ underlying block cipher. @end deftypefun - at c Some MAC algorithms need initialization vector to be set, which can be - at c performed with function: - at c @c - at c @deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) - at c @c - at c Set the IV to the value of @var{iv} of length @var{ivlen} bytes. - at c @end deftypefun +GMAC algorithms need initialization vector to be set, which can be +performed with function: + + at deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) + +Set the IV to the value of @var{iv} of length @var{ivlen} bytes. + at end deftypefun After you are done with the MAC calculation, you should release the resources diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 24f7af6..625fa9f 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1325,7 +1325,13 @@ enum gcry_mac_algos GCRY_MAC_CMAC_SEED = 208, GCRY_MAC_CMAC_RFC2268 = 209, GCRY_MAC_CMAC_IDEA = 210, - GCRY_MAC_CMAC_GOST28147 = 211 + GCRY_MAC_CMAC_GOST28147 = 211, + + GCRY_MAC_GMAC_AES = 401, + GCRY_MAC_GMAC_CAMELLIA = 402, + GCRY_MAC_GMAC_TWOFISH = 403, + GCRY_MAC_GMAC_SERPENT = 404, + GCRY_MAC_GMAC_SEED = 405 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index a205f48..789297f 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4450,8 +4450,8 @@ check_hmac (void) static void check_one_mac (int algo, const char *data, int datalen, - const char *key, int keylen, const char *expect, - int test_buffering) + const char *key, int keylen, const char *iv, int ivlen, + const char *expect, int test_buffering) { gcry_mac_hd_t hd; unsigned char *p; @@ -4487,6 +4487,16 @@ check_one_mac (int algo, const char *data, int datalen, if (err) goto out; + if (ivlen && iv) + { + err = gcry_mac_setiv (hd, iv, ivlen); + if (err) + fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo, + gpg_strerror (err)); + if (err) + goto out; + } + if (test_buffering) { for (i = 0; i < datalen; i++) @@ -4550,6 +4560,7 @@ check_mac (void) const char *data; const char *key; const char *expect; + const char *iv; } algos[] = { { GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe", @@ -4964,6 +4975,42 @@ check_mac (void) "\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", "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" }, + /* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */ + { GCRY_MAC_GMAC_AES, + "", + "\x11\x75\x4c\xd7\x2a\xec\x30\x9b\xf5\x2f\x76\x87\x21\x2e\x89\x57", + "\x25\x03\x27\xc6\x74\xaa\xf4\x77\xae\xf2\x67\x57\x48\xcf\x69\x71", + "\x3c\x81\x9d\x9a\x9b\xed\x08\x76\x15\x03\x0b\x65" }, + { GCRY_MAC_GMAC_AES, + "\x2b\x63\x26\x64\x29\x67\x4a\xb5\xe2\xea\xff\x63\x9c\x23\x14\x66" + "\x2f\x92\x57\x4b\x29\x8f\x57\x7a\xcf\x7d\x6f\x99\x1a\x87\x92\x1f" + "\xc2\x32\xea\xfc\xc7\xb1\x46\x48\x96\x63\x2d\x6c\x8a\xbe\x88\xc2" + "\xcc\xa4\x04\xdb\xf8\x7c\x20\x6a\x19\xd3\x73\xed\x99\x50\x17\x34" + "\x69\x13\x4d\x7c\x14\xc2\x84\x7d\xf2\x4a\x88\xc1\xc5\x3b\x4d\xe4" + "\x9d\xb3\x66\x39\x2b\x6d\xc6\x51\x27\x6e", + "\x0f\x3b\x17\xde\xae\x62\x13\x64\x55\x4a\xe5\x39\xdb\x09\xde\x11", + "\xff\xb0\xbb\x6d\xfc\x23\x58\x75\x4f\x17\x78\x48\x5b\x59\x65\x7f", + "\xa7\xf6\x07\x4c\xda\x56\x1c\xd2\xaa\x15\xba\x8c\x2f\xa6\x39\x42" + "\x59\x3e\x7c\xcf\x45\xc2\x9a\x57\xda\xd8\xa6\xe2\xea\x63\x54\xce" + "\x8a\xde\x39\xdd\xde\x4a\xc4\x5b\xbd\xc6\x63\xf0\xa5\x37\xc9\x48" + "\x18\x23\x5a\x73\xd8\xa0\x8b\xd8\x98\xab\xd0\x99\xe1\x5c\x08\x8c" + "\x6e\x21\x17\x5a\xf4\xe9\xa4\x99\x70\x12\x82\xed\x32\x81\x50\xa6" + "\xd9\x90\xe8\xec\x87\x85\xce\x26\x1b\xe1\xb8\x3f\xd8\x59\x1e\x57" + "\x76\x5f\x3d\xc1\x11\x3f\xd0\x2a\x40\xf5\x01\x6a\xd0\xd0\xed\xc4" + "\x92\x9a\x02\xe0\x17\xb2\xc5\xf4\x18\xd2\x96\xab\xd6\xc2\xea\x2e" }, + { GCRY_MAC_GMAC_AES, + "\x61\x14\x60\x11\x90\xf6\xef\x5e\x59\x23\x5d\xc0\x42\x8c\x09\xe3" + "\x27\x0b\x19\xea", + "\x15\xa4\x14\x46\x6a\x7f\x90\xea\x32\xbf\xd7\xf6\xe5\x8b\xfa\x06" + "\xe9\x07\xfc\x41\x66\x89\xd9\x60\x39\x45\xd7\x94\x54\xd4\x23\x17", + "\x19\x6e\x0e\x01\x0f\x08\x56\xf9\x82\xb4\x08\x92\x41\xd6\x24\x84", + "\xab" }, + { GCRY_MAC_GMAC_AES, + "\x8b\x5c\x12\x4b\xef\x6e\x2f\x0f\xe4\xd8\xc9\x5c\xd5\xfa\x4c\xf1", + "\x41\xc5\xda\x86\x67\xef\x72\x52\x20\xff\xe3\x9a\xe0\xac\x59\x0a" + "\xc9\xfc\xa7\x29\xab\x60\xad\xa0", + "\x20\x4b\xdb\x1b\xd6\x21\x54\xbf\x08\x92\x2a\xaa\x54\xee\xd7\x05", + "\x05\xad\x13\xa5\xe2\xc2\xab\x66\x7e\x1a\x6f\xbc" }, { 0 }, }; int i; @@ -4989,10 +5036,12 @@ check_mac (void) strlen(algos[i].key), strlen(algos[i].data)); check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), + algos[i].key, strlen(algos[i].key), algos[i].iv, + algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 0); check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), + algos[i].key, strlen(algos[i].key), algos[i].iv, + algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 1); } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index d29a4ad..fd9f64b 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -1289,7 +1289,7 @@ mac_bench (char **argv, int argc) } else { - for (i = 1; i < 400; i++) + for (i = 1; i < 500; i++) if (!gcry_mac_test_algo (i)) _mac_bench (i); } diff --git a/tests/benchmark.c b/tests/benchmark.c index 3058bd5..8bb8584 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -457,7 +457,7 @@ mac_bench ( const char *algoname ) if (!algoname) { - for (i=1; i < 400; i++) + for (i=1; i < 500; i++) if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_mac_test_algo (i) ) From mac at mcrowe.com Fri Nov 22 13:31:06 2013 From: mac at mcrowe.com (Mike Crowe) Date: Fri, 22 Nov 2013 12:31:06 +0000 Subject: [PATCH] Avoid secmem leaking capability state Message-ID: <1385123466-30446-1-git-send-email-mac@mcrowe.com> The capability state returned by cap_from_text needs to be freed after it has been used. Valgrind reports this as: 36 bytes in 1 blocks are definitely lost in loss record 132 of 242 at 0x4027938: malloc (vg_replace_malloc.c:270) by 0x4C0B2CF: cap_init (cap_alloc.c:19) by 0x4C0BE0F: cap_from_text (cap_text.c:122) by 0x4573413: secmem_init (secmem.c:243) by 0x4573691: _gcry_secmem_malloc_internal (secmem.c:517) by 0x4573869: _gcry_secmem_malloc (secmem.c:554) by 0x4573007: _gcry_private_malloc_secure (stdmem.c:147) by 0x456F0F4: do_malloc.constprop.4 (global.c:774) by 0x456FAEF: _gcry_malloc_secure (global.c:813) by 0x45841AB: md_open (md.c:491) by 0x4584861: _gcry_md_open (md.c:534) by 0x456D1D8: gcry_md_open (visibility.c:777) 36 bytes in 1 blocks are definitely lost in loss record 133 of 242 at 0x4027938: malloc (vg_replace_malloc.c:270) by 0x4C0B2CF: cap_init (cap_alloc.c:19) by 0x4C0BE0F: cap_from_text (cap_text.c:122) by 0x4573505: secmem_init (secmem.c:247) by 0x4573691: _gcry_secmem_malloc_internal (secmem.c:517) by 0x4573869: _gcry_secmem_malloc (secmem.c:554) by 0x4573007: _gcry_private_malloc_secure (stdmem.c:147) by 0x456F0F4: do_malloc.constprop.4 (global.c:774) by 0x456FAEF: _gcry_malloc_secure (global.c:813) by 0x45841AB: md_open (md.c:491) by 0x4584861: _gcry_md_open (md.c:534) by 0x456D1D8: gcry_md_open (visibility.c:777) Signed-off-by: Mike Crowe --- src/secmem.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/secmem.c b/src/secmem.c index c350bc9..2d76858 100644 --- a/src/secmem.c +++ b/src/secmem.c @@ -242,12 +242,17 @@ lock_pool (void *p, size_t n) { #if defined(USE_CAPABILITIES) && defined(HAVE_MLOCK) int err; + cap_t cap; - cap_set_proc (cap_from_text ("cap_ipc_lock+ep")); + cap = cap_from_text ("cap_ipc_lock+ep"); + cap_set_proc (cap); + cap_free(cap); err = no_mlock? 0 : mlock (p, n); if (err && errno) err = errno; - cap_set_proc (cap_from_text ("cap_ipc_lock+p")); + cap = cap_from_text ("cap_ipc_lock+p"); + cap_set_proc (cap); + cap_free(cap); if (err) { -- 1.7.10.4 From cvs at cvs.gnupg.org Sat Nov 23 11:51:58 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Sat, 23 Nov 2013 11:51:58 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-403-ga34448c Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via a34448c929b13bfb7b66d69169c89e7319a18b31 (commit) from dbfa651618693da7ea73b4d2d00d4efd411bfb46 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit a34448c929b13bfb7b66d69169c89e7319a18b31 Author: Jussi Kivilinna Date: Thu Nov 21 21:34:21 2013 +0200 Add GMAC to MAC API * cipher/Makefile.am: Add 'mac-gmac.c'. * cipher/mac-gmac.c: New. * cipher/mac-internal.h (gcry_mac_handle): Add 'u.gcm'. (_gcry_mac_type_spec_gmac_aes, _gcry_mac_type_spec_gmac_twofish) (_gcry_mac_type_spec_gmac_serpent, _gcry_mac_type_spec_gmac_seed) (_gcry_mac_type_spec_gmac_camellia): New externs. * cipher/mac.c (mac_list): Add GMAC specifications. * doc/gcrypt.texi: Add mention of GMAC. * src/gcrypt.h.in (gcry_mac_algos): Add GCM algorithms. * tests/basic.c (check_one_mac): Add support for MAC IVs. (check_mac): Add support for MAC IVs and add GMAC test vectors. * tests/bench-slope.c (mac_bench): Iterate algorithm numbers to 499. * tests/benchmark.c (mac_bench): Iterate algorithm numbers to 499. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/Makefile.am b/cipher/Makefile.am index e29b28d..ff9deca 100644 --- a/cipher/Makefile.am +++ b/cipher/Makefile.am @@ -45,7 +45,7 @@ cipher-selftest.c cipher-selftest.h \ pubkey.c pubkey-internal.h pubkey-util.c \ md.c \ mac.c mac-internal.h \ -mac-hmac.c mac-cmac.c \ +mac-hmac.c mac-cmac.c mac-gmac.c \ kdf.c kdf-internal.h \ hmac-tests.c \ bithelp.h \ diff --git a/cipher/mac-gmac.c b/cipher/mac-gmac.c new file mode 100644 index 0000000..e040bfe --- /dev/null +++ b/cipher/mac-gmac.c @@ -0,0 +1,185 @@ +/* mac-gmac.c - GMAC glue for MAC API + * Copyright ? 2013 Jussi Kivilinna + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see . + */ + +#include +#include +#include +#include +#include + +#include "g10lib.h" +#include "cipher.h" +#include "./mac-internal.h" + + +static int +map_mac_algo_to_cipher (int mac_algo) +{ + switch (mac_algo) + { + default: + return GCRY_CIPHER_NONE; + case GCRY_MAC_GMAC_AES: + return GCRY_CIPHER_AES; + case GCRY_MAC_GMAC_CAMELLIA: + return GCRY_CIPHER_CAMELLIA128; + case GCRY_MAC_GMAC_TWOFISH: + return GCRY_CIPHER_TWOFISH; + case GCRY_MAC_GMAC_SERPENT: + return GCRY_CIPHER_SERPENT128; + case GCRY_MAC_GMAC_SEED: + return GCRY_CIPHER_SEED; + } +} + + +static gcry_err_code_t +gmac_open (gcry_mac_hd_t h) +{ + gcry_err_code_t err; + gcry_cipher_hd_t hd; + int secure = (h->magic == CTX_MAGIC_SECURE); + int cipher_algo; + unsigned int flags; + + cipher_algo = map_mac_algo_to_cipher (h->spec->algo); + flags = (secure ? GCRY_CIPHER_SECURE : 0); + + err = _gcry_cipher_open_internal (&hd, cipher_algo, GCRY_CIPHER_MODE_GCM, + flags); + if (err) + return err; + + h->u.gmac.cipher_algo = cipher_algo; + h->u.gmac.ctx = hd; + return 0; +} + + +static void +gmac_close (gcry_mac_hd_t h) +{ + _gcry_cipher_close (h->u.gmac.ctx); + h->u.gmac.ctx = NULL; +} + + +static gcry_err_code_t +gmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) +{ + return _gcry_cipher_setkey (h->u.gmac.ctx, key, keylen); +} + + +static gcry_err_code_t +gmac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) +{ + return _gcry_cipher_setiv (h->u.gmac.ctx, iv, ivlen); +} + + +static gcry_err_code_t +gmac_reset (gcry_mac_hd_t h) +{ + return gcry_cipher_reset (h->u.gmac.ctx); +} + + +static gcry_err_code_t +gmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + return _gcry_cipher_authenticate (h->u.gmac.ctx, buf, buflen); +} + + +static gcry_err_code_t +gmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) +{ + if (*outlen > GCRY_GCM_BLOCK_LEN) + *outlen = GCRY_GCM_BLOCK_LEN; + return _gcry_cipher_gettag (h->u.gmac.ctx, outbuf, *outlen); +} + + +static gcry_err_code_t +gmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) +{ + return _gcry_cipher_checktag (h->u.gmac.ctx, buf, buflen); +} + + +static unsigned int +gmac_get_maclen (int algo) +{ + (void)algo; + return GCRY_GCM_BLOCK_LEN; +} + + +static unsigned int +gmac_get_keylen (int algo) +{ + return _gcry_cipher_get_algo_keylen (map_mac_algo_to_cipher (algo)); +} + + +static gcry_mac_spec_ops_t gmac_ops = { + gmac_open, + gmac_close, + gmac_setkey, + gmac_setiv, + gmac_reset, + gmac_write, + gmac_read, + gmac_verify, + gmac_get_maclen, + gmac_get_keylen +}; + + +#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-internal.h b/cipher/mac-internal.h index 146b218..2a5e7c6 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -103,6 +103,10 @@ struct gcry_mac_handle int cipher_algo; unsigned int blklen; } cmac; + struct { + gcry_cipher_hd_t ctx; + int cipher_algo; + } gmac; } u; }; @@ -180,3 +184,22 @@ extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; #if USE_GOST28147 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; #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 diff --git a/cipher/mac.c b/cipher/mac.c index 8d1dec0..5ac8729 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -74,21 +74,26 @@ static gcry_mac_spec_t *mac_list[] = { #endif #if USE_AES &_gcry_mac_type_spec_cmac_aes, + &_gcry_mac_type_spec_gmac_aes, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, + &_gcry_mac_type_spec_gmac_twofish, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, + &_gcry_mac_type_spec_gmac_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, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, + &_gcry_mac_type_spec_gmac_camellia, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, diff --git a/doc/gcrypt.texi b/doc/gcrypt.texi index 1f6ceec..4870a1c 100644 --- a/doc/gcrypt.texi +++ b/doc/gcrypt.texi @@ -3529,6 +3529,26 @@ block cipher algorithm. This is CMAC message authentication algorithm based on the GOST 28147-89 block cipher algorithm. + at item GCRY_MAC_GMAC_AES +This is GMAC (GCM mode based MAC) message authentication algorithm based on +the AES block cipher algorithm. + + at item GCRY_MAC_GMAC_CAMELLIA +This is GMAC message authentication algorithm based on the Camellia +block cipher algorithm. + + at item GCRY_MAC_GMAC_TWOFISH +This is GMAC message authentication algorithm based on the Twofish +block cipher algorithm. + + at item GCRY_MAC_GMAC_SERPENT +This is GMAC message authentication algorithm based on the Serpent +block cipher algorithm. + + at item GCRY_MAC_GMAC_SEED +This is GMAC message authentication algorithm based on the SEED +block cipher algorithm. + @end table @c end table of MAC algorithms @@ -3574,13 +3594,13 @@ underlying block cipher. @end deftypefun - at c Some MAC algorithms need initialization vector to be set, which can be - at c performed with function: - at c @c - at c @deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) - at c @c - at c Set the IV to the value of @var{iv} of length @var{ivlen} bytes. - at c @end deftypefun +GMAC algorithms need initialization vector to be set, which can be +performed with function: + + at deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) + +Set the IV to the value of @var{iv} of length @var{ivlen} bytes. + at end deftypefun After you are done with the MAC calculation, you should release the resources diff --git a/src/gcrypt.h.in b/src/gcrypt.h.in index 24f7af6..625fa9f 100644 --- a/src/gcrypt.h.in +++ b/src/gcrypt.h.in @@ -1325,7 +1325,13 @@ enum gcry_mac_algos GCRY_MAC_CMAC_SEED = 208, GCRY_MAC_CMAC_RFC2268 = 209, GCRY_MAC_CMAC_IDEA = 210, - GCRY_MAC_CMAC_GOST28147 = 211 + GCRY_MAC_CMAC_GOST28147 = 211, + + GCRY_MAC_GMAC_AES = 401, + GCRY_MAC_GMAC_CAMELLIA = 402, + GCRY_MAC_GMAC_TWOFISH = 403, + GCRY_MAC_GMAC_SERPENT = 404, + GCRY_MAC_GMAC_SEED = 405 }; /* Flags used with the open function. */ diff --git a/tests/basic.c b/tests/basic.c index a205f48..789297f 100644 --- a/tests/basic.c +++ b/tests/basic.c @@ -4450,8 +4450,8 @@ check_hmac (void) static void check_one_mac (int algo, const char *data, int datalen, - const char *key, int keylen, const char *expect, - int test_buffering) + const char *key, int keylen, const char *iv, int ivlen, + const char *expect, int test_buffering) { gcry_mac_hd_t hd; unsigned char *p; @@ -4487,6 +4487,16 @@ check_one_mac (int algo, const char *data, int datalen, if (err) goto out; + if (ivlen && iv) + { + err = gcry_mac_setiv (hd, iv, ivlen); + if (err) + fail("algo %d, mac gcry_mac_ivkey failed: %s\n", algo, + gpg_strerror (err)); + if (err) + goto out; + } + if (test_buffering) { for (i = 0; i < datalen; i++) @@ -4550,6 +4560,7 @@ check_mac (void) const char *data; const char *key; const char *expect; + const char *iv; } algos[] = { { GCRY_MAC_HMAC_MD5, "what do ya want for nothing?", "Jefe", @@ -4964,6 +4975,42 @@ check_mac (void) "\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", "\xc2\x69\x9a\x6e\xba\x55\xce\x9d\x93\x9a\x8a\x4e\x19\x46\x6e\xe9" }, + /* http://csrc.nist.gov/groups/STM/cavp/documents/mac/gcmtestvectors.zip */ + { GCRY_MAC_GMAC_AES, + "", + "\x11\x75\x4c\xd7\x2a\xec\x30\x9b\xf5\x2f\x76\x87\x21\x2e\x89\x57", + "\x25\x03\x27\xc6\x74\xaa\xf4\x77\xae\xf2\x67\x57\x48\xcf\x69\x71", + "\x3c\x81\x9d\x9a\x9b\xed\x08\x76\x15\x03\x0b\x65" }, + { GCRY_MAC_GMAC_AES, + "\x2b\x63\x26\x64\x29\x67\x4a\xb5\xe2\xea\xff\x63\x9c\x23\x14\x66" + "\x2f\x92\x57\x4b\x29\x8f\x57\x7a\xcf\x7d\x6f\x99\x1a\x87\x92\x1f" + "\xc2\x32\xea\xfc\xc7\xb1\x46\x48\x96\x63\x2d\x6c\x8a\xbe\x88\xc2" + "\xcc\xa4\x04\xdb\xf8\x7c\x20\x6a\x19\xd3\x73\xed\x99\x50\x17\x34" + "\x69\x13\x4d\x7c\x14\xc2\x84\x7d\xf2\x4a\x88\xc1\xc5\x3b\x4d\xe4" + "\x9d\xb3\x66\x39\x2b\x6d\xc6\x51\x27\x6e", + "\x0f\x3b\x17\xde\xae\x62\x13\x64\x55\x4a\xe5\x39\xdb\x09\xde\x11", + "\xff\xb0\xbb\x6d\xfc\x23\x58\x75\x4f\x17\x78\x48\x5b\x59\x65\x7f", + "\xa7\xf6\x07\x4c\xda\x56\x1c\xd2\xaa\x15\xba\x8c\x2f\xa6\x39\x42" + "\x59\x3e\x7c\xcf\x45\xc2\x9a\x57\xda\xd8\xa6\xe2\xea\x63\x54\xce" + "\x8a\xde\x39\xdd\xde\x4a\xc4\x5b\xbd\xc6\x63\xf0\xa5\x37\xc9\x48" + "\x18\x23\x5a\x73\xd8\xa0\x8b\xd8\x98\xab\xd0\x99\xe1\x5c\x08\x8c" + "\x6e\x21\x17\x5a\xf4\xe9\xa4\x99\x70\x12\x82\xed\x32\x81\x50\xa6" + "\xd9\x90\xe8\xec\x87\x85\xce\x26\x1b\xe1\xb8\x3f\xd8\x59\x1e\x57" + "\x76\x5f\x3d\xc1\x11\x3f\xd0\x2a\x40\xf5\x01\x6a\xd0\xd0\xed\xc4" + "\x92\x9a\x02\xe0\x17\xb2\xc5\xf4\x18\xd2\x96\xab\xd6\xc2\xea\x2e" }, + { GCRY_MAC_GMAC_AES, + "\x61\x14\x60\x11\x90\xf6\xef\x5e\x59\x23\x5d\xc0\x42\x8c\x09\xe3" + "\x27\x0b\x19\xea", + "\x15\xa4\x14\x46\x6a\x7f\x90\xea\x32\xbf\xd7\xf6\xe5\x8b\xfa\x06" + "\xe9\x07\xfc\x41\x66\x89\xd9\x60\x39\x45\xd7\x94\x54\xd4\x23\x17", + "\x19\x6e\x0e\x01\x0f\x08\x56\xf9\x82\xb4\x08\x92\x41\xd6\x24\x84", + "\xab" }, + { GCRY_MAC_GMAC_AES, + "\x8b\x5c\x12\x4b\xef\x6e\x2f\x0f\xe4\xd8\xc9\x5c\xd5\xfa\x4c\xf1", + "\x41\xc5\xda\x86\x67\xef\x72\x52\x20\xff\xe3\x9a\xe0\xac\x59\x0a" + "\xc9\xfc\xa7\x29\xab\x60\xad\xa0", + "\x20\x4b\xdb\x1b\xd6\x21\x54\xbf\x08\x92\x2a\xaa\x54\xee\xd7\x05", + "\x05\xad\x13\xa5\xe2\xc2\xab\x66\x7e\x1a\x6f\xbc" }, { 0 }, }; int i; @@ -4989,10 +5036,12 @@ check_mac (void) strlen(algos[i].key), strlen(algos[i].data)); check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), + algos[i].key, strlen(algos[i].key), algos[i].iv, + algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 0); check_one_mac (algos[i].algo, algos[i].data, strlen (algos[i].data), - algos[i].key, strlen(algos[i].key), + algos[i].key, strlen(algos[i].key), algos[i].iv, + algos[i].iv ? strlen(algos[i].iv) : 0, algos[i].expect, 1); } diff --git a/tests/bench-slope.c b/tests/bench-slope.c index d29a4ad..fd9f64b 100644 --- a/tests/bench-slope.c +++ b/tests/bench-slope.c @@ -1289,7 +1289,7 @@ mac_bench (char **argv, int argc) } else { - for (i = 1; i < 400; i++) + for (i = 1; i < 500; i++) if (!gcry_mac_test_algo (i)) _mac_bench (i); } diff --git a/tests/benchmark.c b/tests/benchmark.c index 3058bd5..8bb8584 100644 --- a/tests/benchmark.c +++ b/tests/benchmark.c @@ -457,7 +457,7 @@ mac_bench ( const char *algoname ) if (!algoname) { - for (i=1; i < 400; i++) + for (i=1; i < 500; i++) if (in_fips_mode && i == GCRY_MAC_HMAC_MD5) ; /* Don't use MD5 in fips mode. */ else if ( !gcry_mac_test_algo (i) ) ----------------------------------------------------------------------- Summary of changes: cipher/Makefile.am | 2 +- cipher/mac-gmac.c | 185 +++++++++++++++++++++++++++++++++++++++++++++++++ cipher/mac-internal.h | 23 ++++++ cipher/mac.c | 5 ++ doc/gcrypt.texi | 34 +++++++-- src/gcrypt.h.in | 8 ++- tests/basic.c | 57 +++++++++++++-- tests/bench-slope.c | 2 +- tests/benchmark.c | 2 +- 9 files changed, 303 insertions(+), 15 deletions(-) create mode 100644 cipher/mac-gmac.c hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Mon Nov 25 16:35:11 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Mon, 25 Nov 2013 17:35:11 +0200 Subject: [PATCH] Camellia: Tweaks for AES-NI implementations Message-ID: <20131125153511.15266.10974.stgit@localhost6.localdomain6> * cipher/camellia-aesni-avx-amd64.S: Align stack to 16 bytes; tweak key-setup for small speed up. * cipher/camellia-aesni-avx2-amd64.S: Use vmovdqu even with aligned stack; reorder vinsert128 instructions; use rbp for stack frame. -- Use of vmovdqa with ymm registers produces quite interesting scattering in cycles measurement. By vmovdqu instead makes results more stable. Signed-off-by: Jussi Kivilinna --- cipher/camellia-aesni-avx-amd64.S | 73 +++++++----- cipher/camellia-aesni-avx2-amd64.S | 215 ++++++++++++++++++------------------ 2 files changed, 148 insertions(+), 140 deletions(-) diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index ffb1aed..38ec7a3 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -958,9 +958,13 @@ _gcry_camellia_aesni_avx_ctr_enc: * %rcx: iv (big endian, 128bit) */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; vmovdqa .Lbswap128_mask RIP, %xmm14; @@ -1033,8 +1037,6 @@ _gcry_camellia_aesni_avx_ctr_enc: call __camellia_enc_blk16; - addq $(16 * 16), %rsp; - vpxor 0 * 16(%rdx), %xmm7, %xmm7; vpxor 1 * 16(%rdx), %xmm6, %xmm6; vpxor 2 * 16(%rdx), %xmm5, %xmm5; @@ -1058,6 +1060,7 @@ _gcry_camellia_aesni_avx_ctr_enc: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_ctr_enc,.-_gcry_camellia_aesni_avx_ctr_enc; @@ -1073,6 +1076,9 @@ _gcry_camellia_aesni_avx_cbc_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; movq %rcx, %r9; @@ -1087,12 +1093,11 @@ _gcry_camellia_aesni_avx_cbc_dec: %xmm15, %rdx, (key_table)(CTX, %r8, 8)); subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; call __camellia_dec_blk16; - addq $(16 * 16), %rsp; - /* XOR output with IV */ vpxor (%r9), %xmm7, %xmm7; vpxor (0 * 16)(%rdx), %xmm6, %xmm6; @@ -1112,6 +1117,7 @@ _gcry_camellia_aesni_avx_cbc_dec: vpxor (14 * 16)(%rdx), %xmm8, %xmm8; movq (15 * 16 + 0)(%rdx), %r10; movq (15 * 16 + 8)(%rdx), %r11; + write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0, %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); @@ -1122,6 +1128,7 @@ _gcry_camellia_aesni_avx_cbc_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_cbc_dec,.-_gcry_camellia_aesni_avx_cbc_dec; @@ -1137,9 +1144,13 @@ _gcry_camellia_aesni_avx_cfb_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; /* inpack16_pre: */ @@ -1166,8 +1177,6 @@ _gcry_camellia_aesni_avx_cfb_dec: call __camellia_enc_blk16; - addq $(16 * 16), %rsp; - vpxor 0 * 16(%rdx), %xmm7, %xmm7; vpxor 1 * 16(%rdx), %xmm6, %xmm6; vpxor 2 * 16(%rdx), %xmm5, %xmm5; @@ -1191,6 +1200,7 @@ _gcry_camellia_aesni_avx_cfb_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec; @@ -1199,7 +1209,7 @@ _gcry_camellia_aesni_avx_cfb_dec: * ab: 64-bit AB state * cd: 64-bit CD state */ -#define camellia_f(ab, x, t0, t1, t2, t3, t4, sbox2mask, sbox4mask, \ +#define camellia_f(ab, x, t0, t1, t2, t3, t4, inv_shift_row, sbox4mask, \ _0f0f0f0fmask, pre_s1lo_mask, pre_s1hi_mask, key) \ vmovq key, t0; \ vpxor x, x, t3; \ @@ -1221,37 +1231,33 @@ _gcry_camellia_aesni_avx_cfb_dec: \ vmovdqa .Lpost_tf_lo_s1 RIP, t0; \ vmovdqa .Lpost_tf_hi_s1 RIP, t1; \ - vmovq .Lsbox3_output_mask RIP, t4; \ \ /* prefilter sboxes */ \ filter_8bit(x, pre_s1lo_mask, pre_s1hi_mask, _0f0f0f0fmask, t2); \ \ /* AES subbytes + AES shift rows + AES inv shift rows */ \ vaesenclast t3, x, x; \ - vpshufb .Linv_shift_row RIP, x, x; \ \ /* postfilter sboxes */ \ filter_8bit(x, t0, t1, _0f0f0f0fmask, t2); \ \ /* output rotation for sbox2 (<<< 1) */ \ /* output rotation for sbox3 (>>> 1) */ \ - vpor sbox2mask, t4, t2; \ - vpand x, sbox2mask, t0; \ - vpand x, t4, t1; \ - vpaddb x, x, t2; \ - vpshufb .Lsp1110111044044404mask RIP, x, t4; \ - vpshufb .Lsp0044440410011110mask RIP, x, x; \ - vpsrlw $7, t0, t0; \ + vpshufb inv_shift_row, x, t1; \ + vpshufb .Lsp0044440444044404mask RIP, x, t4; \ + vpshufb .Lsp1110111010011110mask RIP, x, x; \ + vpaddb t1, t1, t2; \ + vpsrlw $7, t1, t0; \ vpsllw $7, t1, t3; \ - vpsrlw $1, t1, t1; \ vpor t0, t2, t0; \ + vpsrlw $1, t1, t1; \ vpshufb .Lsp0222022222000222mask RIP, t0, t0; \ vpor t1, t3, t1; \ - vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ \ vpxor x, t4, t4; \ - vpxor t1, t0, t0; \ + vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ vpxor t4, t0, t0; \ + vpxor t1, t0, t0; \ vpsrldq $8, t0, x; \ vpxor t0, x, x; @@ -1270,22 +1276,21 @@ _gcry_camellia_aesni_avx_cfb_dec: .data .align 16 -.Lsp1110111044044404mask: - .long 0x000000ff, 0x000000ff; - .long 0x0101ff01, 0x0101ff01; -.Lsp0044440410011110mask: +.Linv_shift_row_and_unpcklbw: + .byte 0x00, 0xff, 0x0d, 0xff, 0x0a, 0xff, 0x07, 0xff + .byte 0x04, 0xff, 0x01, 0xff, 0x0e, 0xff, 0x0b, 0xff +.Lsp0044440444044404mask: .long 0xffff0404, 0x0404ff04; - .long 0x07ffff07, 0x070707ff; + .long 0x0d0dff0d, 0x0d0dff0d; +.Lsp1110111010011110mask: + .long 0x000000ff, 0x000000ff; + .long 0x0bffff0b, 0x0b0b0bff; .Lsp0222022222000222mask: - .long 0xff030303, 0xff030303; - .long 0x0606ffff, 0xff060606; + .long 0xff060606, 0xff060606; + .long 0x0c0cffff, 0xff0c0c0c; .Lsp3033303303303033mask: - .long 0x02ff0202, 0x02ff0202; - .long 0xff0505ff, 0x05ff0505; -.Lsbox2_output_mask: - .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; -.Lsbox3_output_mask: - .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; + .long 0x04ff0404, 0x04ff0404; + .long 0xff0a0aff, 0x0aff0a0a; .Lsbox4_input_mask: .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; .Lsigma1: @@ -1316,7 +1321,7 @@ __camellia_avx_setup128: vpshufb .Lbswap128_mask RIP, KL128, KL128; - vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11; vmovq .Lsbox4_input_mask RIP, %xmm12; vbroadcastss .L0f0f0f0f RIP, %xmm13; vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; @@ -1663,7 +1668,7 @@ __camellia_avx_setup256: vpshufb .Lbswap128_mask RIP, KL128, KL128; vpshufb .Lbswap128_mask RIP, KR128, KR128; - vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11; vmovq .Lsbox4_input_mask RIP, %xmm12; vbroadcastss .L0f0f0f0f RIP, %xmm13; vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index 65c923e..1a89ff4 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -124,15 +124,15 @@ vextracti128 $1, x5, t5##_x; \ vaesenclast t4##_x, x0##_x, x0##_x; \ vaesenclast t4##_x, t0##_x, t0##_x; \ - vinserti128 $1, t0##_x, x0, x0; \ vaesenclast t4##_x, x7##_x, x7##_x; \ vaesenclast t4##_x, t1##_x, t1##_x; \ - vinserti128 $1, t1##_x, x7, x7; \ vaesenclast t4##_x, x3##_x, x3##_x; \ vaesenclast t4##_x, t3##_x, t3##_x; \ - vinserti128 $1, t3##_x, x3, x3; \ vaesenclast t4##_x, x6##_x, x6##_x; \ vaesenclast t4##_x, t2##_x, t2##_x; \ + vinserti128 $1, t0##_x, x0, x0; \ + vinserti128 $1, t1##_x, x7, x7; \ + vinserti128 $1, t3##_x, x3, x3; \ vinserti128 $1, t2##_x, x6, x6; \ vextracti128 $1, x1, t3##_x; \ vextracti128 $1, x4, t2##_x; \ @@ -140,15 +140,15 @@ vbroadcasti128 .Lpost_tf_hi_s1 RIP, t1; \ vaesenclast t4##_x, x2##_x, x2##_x; \ vaesenclast t4##_x, t6##_x, t6##_x; \ - vinserti128 $1, t6##_x, x2, x2; \ vaesenclast t4##_x, x5##_x, x5##_x; \ vaesenclast t4##_x, t5##_x, t5##_x; \ - vinserti128 $1, t5##_x, x5, x5; \ vaesenclast t4##_x, x1##_x, x1##_x; \ vaesenclast t4##_x, t3##_x, t3##_x; \ - vinserti128 $1, t3##_x, x1, x1; \ vaesenclast t4##_x, x4##_x, x4##_x; \ vaesenclast t4##_x, t2##_x, t2##_x; \ + vinserti128 $1, t6##_x, x2, x2; \ + vinserti128 $1, t5##_x, x5, x5; \ + vinserti128 $1, t3##_x, x1, x1; \ vinserti128 $1, t2##_x, x4, x4; \ \ /* postfilter sboxes 1 and 4 */ \ @@ -249,14 +249,14 @@ roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_cd, (key_table + (i) * 8)(CTX)); \ \ - vmovdqa x0, 4 * 32(mem_cd); \ - vmovdqa x1, 5 * 32(mem_cd); \ - vmovdqa x2, 6 * 32(mem_cd); \ - vmovdqa x3, 7 * 32(mem_cd); \ - vmovdqa x4, 0 * 32(mem_cd); \ - vmovdqa x5, 1 * 32(mem_cd); \ - vmovdqa x6, 2 * 32(mem_cd); \ - vmovdqa x7, 3 * 32(mem_cd); \ + vmovdqu x0, 4 * 32(mem_cd); \ + vmovdqu x1, 5 * 32(mem_cd); \ + vmovdqu x2, 6 * 32(mem_cd); \ + vmovdqu x3, 7 * 32(mem_cd); \ + vmovdqu x4, 0 * 32(mem_cd); \ + vmovdqu x5, 1 * 32(mem_cd); \ + vmovdqu x6, 2 * 32(mem_cd); \ + vmovdqu x7, 3 * 32(mem_cd); \ \ roundsm32(x4, x5, x6, x7, x0, x1, x2, x3, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_ab, (key_table + ((i) + (dir)) * 8)(CTX)); \ @@ -267,14 +267,14 @@ #define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \ /* Store new AB state */ \ - vmovdqa x4, 4 * 32(mem_ab); \ - vmovdqa x5, 5 * 32(mem_ab); \ - vmovdqa x6, 6 * 32(mem_ab); \ - vmovdqa x7, 7 * 32(mem_ab); \ - vmovdqa x0, 0 * 32(mem_ab); \ - vmovdqa x1, 1 * 32(mem_ab); \ - vmovdqa x2, 2 * 32(mem_ab); \ - vmovdqa x3, 3 * 32(mem_ab); + vmovdqu x4, 4 * 32(mem_ab); \ + vmovdqu x5, 5 * 32(mem_ab); \ + vmovdqu x6, 6 * 32(mem_ab); \ + vmovdqu x7, 7 * 32(mem_ab); \ + vmovdqu x0, 0 * 32(mem_ab); \ + vmovdqu x1, 1 * 32(mem_ab); \ + vmovdqu x2, 2 * 32(mem_ab); \ + vmovdqu x3, 3 * 32(mem_ab); #define enc_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_ab, mem_cd, i) \ @@ -356,13 +356,13 @@ \ vpxor l4, t0, l4; \ vpbroadcastd krr, t0; /* only lowest 32-bit used */ \ - vmovdqa l4, 4 * 32(l); \ + vmovdqu l4, 4 * 32(l); \ vpxor l5, t1, l5; \ - vmovdqa l5, 5 * 32(l); \ + vmovdqu l5, 5 * 32(l); \ vpxor l6, t2, l6; \ - vmovdqa l6, 6 * 32(l); \ + vmovdqu l6, 6 * 32(l); \ vpxor l7, t3, l7; \ - vmovdqa l7, 7 * 32(l); \ + vmovdqu l7, 7 * 32(l); \ \ /* \ * t2 = krr; \ @@ -387,11 +387,11 @@ vpxor 1 * 32(r), t1, t1; \ vpxor 2 * 32(r), t2, t2; \ vpxor 3 * 32(r), t3, t3; \ - vmovdqa t0, 0 * 32(r); \ + vmovdqu t0, 0 * 32(r); \ vpbroadcastd krl, t0; /* only lowest 32-bit used */ \ - vmovdqa t1, 1 * 32(r); \ - vmovdqa t2, 2 * 32(r); \ - vmovdqa t3, 3 * 32(r); \ + vmovdqu t1, 1 * 32(r); \ + vmovdqu t2, 2 * 32(r); \ + vmovdqu t3, 3 * 32(r); \ \ /* \ * t2 = krl; \ @@ -417,11 +417,11 @@ vpxor 5 * 32(r), t1, t1; \ vpxor 6 * 32(r), t2, t2; \ vpxor 7 * 32(r), t3, t3; \ - vmovdqa t0, 4 * 32(r); \ + vmovdqu t0, 4 * 32(r); \ vpbroadcastd klr, t0; /* only lowest 32-bit used */ \ - vmovdqa t1, 5 * 32(r); \ - vmovdqa t2, 6 * 32(r); \ - vmovdqa t3, 7 * 32(r); \ + vmovdqu t1, 5 * 32(r); \ + vmovdqu t2, 6 * 32(r); \ + vmovdqu t3, 7 * 32(r); \ \ /* \ * t0 = klr; \ @@ -443,13 +443,13 @@ vpor l7, t3, t3; \ \ vpxor l0, t0, l0; \ - vmovdqa l0, 0 * 32(l); \ + vmovdqu l0, 0 * 32(l); \ vpxor l1, t1, l1; \ - vmovdqa l1, 1 * 32(l); \ + vmovdqu l1, 1 * 32(l); \ vpxor l2, t2, l2; \ - vmovdqa l2, 2 * 32(l); \ + vmovdqu l2, 2 * 32(l); \ vpxor l3, t3, l3; \ - vmovdqa l3, 3 * 32(l); + vmovdqu l3, 3 * 32(l); #define transpose_4x4(x0, x1, x2, x3, t1, t2) \ vpunpckhdq x1, x0, t2; \ @@ -466,20 +466,20 @@ #define byteslice_16x16b_fast(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, \ a3, b3, c3, d3, st0, st1) \ - vmovdqa d2, st0; \ - vmovdqa d3, st1; \ + vmovdqu d2, st0; \ + vmovdqu d3, st1; \ transpose_4x4(a0, a1, a2, a3, d2, d3); \ transpose_4x4(b0, b1, b2, b3, d2, d3); \ - vmovdqa st0, d2; \ - vmovdqa st1, d3; \ + vmovdqu st0, d2; \ + vmovdqu st1, d3; \ \ - vmovdqa a0, st0; \ - vmovdqa a1, st1; \ + vmovdqu a0, st0; \ + vmovdqu a1, st1; \ transpose_4x4(c0, c1, c2, c3, a0, a1); \ transpose_4x4(d0, d1, d2, d3, a0, a1); \ \ vbroadcasti128 .Lshufb_16x16b RIP, a0; \ - vmovdqa st1, a1; \ + vmovdqu st1, a1; \ vpshufb a0, a2, a2; \ vpshufb a0, a3, a3; \ vpshufb a0, b0, b0; \ @@ -495,22 +495,22 @@ vpshufb a0, d1, d1; \ vpshufb a0, d2, d2; \ vpshufb a0, d3, d3; \ - vmovdqa d3, st1; \ - vmovdqa st0, d3; \ + vmovdqu d3, st1; \ + vmovdqu st0, d3; \ vpshufb a0, d3, a0; \ - vmovdqa d2, st0; \ + vmovdqu d2, st0; \ \ transpose_4x4(a0, b0, c0, d0, d2, d3); \ transpose_4x4(a1, b1, c1, d1, d2, d3); \ - vmovdqa st0, d2; \ - vmovdqa st1, d3; \ + vmovdqu st0, d2; \ + vmovdqu st1, d3; \ \ - vmovdqa b0, st0; \ - vmovdqa b1, st1; \ + vmovdqu b0, st0; \ + vmovdqu b1, st1; \ transpose_4x4(a2, b2, c2, d2, b0, b1); \ transpose_4x4(a3, b3, c3, d3, b0, b1); \ - vmovdqa st0, b0; \ - vmovdqa st1, b1; \ + vmovdqu st0, b0; \ + vmovdqu st1, b1; \ /* does not adjust output bytes inside vectors */ /* load blocks to registers and apply pre-whitening */ @@ -542,22 +542,22 @@ byteslice_16x16b_fast(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, \ y4, y5, y6, y7, (mem_ab), (mem_cd)); \ \ - vmovdqa x0, 0 * 32(mem_ab); \ - vmovdqa x1, 1 * 32(mem_ab); \ - vmovdqa x2, 2 * 32(mem_ab); \ - vmovdqa x3, 3 * 32(mem_ab); \ - vmovdqa x4, 4 * 32(mem_ab); \ - vmovdqa x5, 5 * 32(mem_ab); \ - vmovdqa x6, 6 * 32(mem_ab); \ - vmovdqa x7, 7 * 32(mem_ab); \ - vmovdqa y0, 0 * 32(mem_cd); \ - vmovdqa y1, 1 * 32(mem_cd); \ - vmovdqa y2, 2 * 32(mem_cd); \ - vmovdqa y3, 3 * 32(mem_cd); \ - vmovdqa y4, 4 * 32(mem_cd); \ - vmovdqa y5, 5 * 32(mem_cd); \ - vmovdqa y6, 6 * 32(mem_cd); \ - vmovdqa y7, 7 * 32(mem_cd); + vmovdqu x0, 0 * 32(mem_ab); \ + vmovdqu x1, 1 * 32(mem_ab); \ + vmovdqu x2, 2 * 32(mem_ab); \ + vmovdqu x3, 3 * 32(mem_ab); \ + vmovdqu x4, 4 * 32(mem_ab); \ + vmovdqu x5, 5 * 32(mem_ab); \ + vmovdqu x6, 6 * 32(mem_ab); \ + vmovdqu x7, 7 * 32(mem_ab); \ + vmovdqu y0, 0 * 32(mem_cd); \ + vmovdqu y1, 1 * 32(mem_cd); \ + vmovdqu y2, 2 * 32(mem_cd); \ + vmovdqu y3, 3 * 32(mem_cd); \ + vmovdqu y4, 4 * 32(mem_cd); \ + vmovdqu y5, 5 * 32(mem_cd); \ + vmovdqu y6, 6 * 32(mem_cd); \ + vmovdqu y7, 7 * 32(mem_cd); /* de-byteslice, apply post-whitening and store blocks */ #define outunpack32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \ @@ -565,7 +565,7 @@ byteslice_16x16b_fast(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, \ y3, y7, x3, x7, stack_tmp0, stack_tmp1); \ \ - vmovdqa x0, stack_tmp0; \ + vmovdqu x0, stack_tmp0; \ \ vpbroadcastq key, x0; \ vpshufb .Lpack_bswap RIP, x0, x0; \ @@ -800,14 +800,14 @@ __camellia_enc_blk32: .Lenc_done: /* load CD for output */ - vmovdqa 0 * 32(%rcx), %ymm8; - vmovdqa 1 * 32(%rcx), %ymm9; - vmovdqa 2 * 32(%rcx), %ymm10; - vmovdqa 3 * 32(%rcx), %ymm11; - vmovdqa 4 * 32(%rcx), %ymm12; - vmovdqa 5 * 32(%rcx), %ymm13; - vmovdqa 6 * 32(%rcx), %ymm14; - vmovdqa 7 * 32(%rcx), %ymm15; + vmovdqu 0 * 32(%rcx), %ymm8; + vmovdqu 1 * 32(%rcx), %ymm9; + vmovdqu 2 * 32(%rcx), %ymm10; + vmovdqu 3 * 32(%rcx), %ymm11; + vmovdqu 4 * 32(%rcx), %ymm12; + vmovdqu 5 * 32(%rcx), %ymm13; + vmovdqu 6 * 32(%rcx), %ymm14; + vmovdqu 7 * 32(%rcx), %ymm15; outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, @@ -887,14 +887,14 @@ __camellia_dec_blk32: %ymm15, %rax, %rcx, 0); /* load CD for output */ - vmovdqa 0 * 32(%rcx), %ymm8; - vmovdqa 1 * 32(%rcx), %ymm9; - vmovdqa 2 * 32(%rcx), %ymm10; - vmovdqa 3 * 32(%rcx), %ymm11; - vmovdqa 4 * 32(%rcx), %ymm12; - vmovdqa 5 * 32(%rcx), %ymm13; - vmovdqa 6 * 32(%rcx), %ymm14; - vmovdqa 7 * 32(%rcx), %ymm15; + vmovdqu 0 * 32(%rcx), %ymm8; + vmovdqu 1 * 32(%rcx), %ymm9; + vmovdqu 2 * 32(%rcx), %ymm10; + vmovdqu 3 * 32(%rcx), %ymm11; + vmovdqu 4 * 32(%rcx), %ymm12; + vmovdqu 5 * 32(%rcx), %ymm13; + vmovdqu 6 * 32(%rcx), %ymm14; + vmovdqu 7 * 32(%rcx), %ymm15; outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, @@ -937,14 +937,16 @@ _gcry_camellia_aesni_avx2_ctr_enc: * %rcx: iv (big endian, 128bit) */ + pushq %rbp; + movq %rsp, %rbp; + movq 8(%rcx), %r11; bswapq %r11; vzeroupper; - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; vpcmpeqd %ymm15, %ymm15, %ymm15; @@ -958,7 +960,7 @@ _gcry_camellia_aesni_avx2_ctr_enc: vbroadcasti128 .Lbswap128_mask RIP, %ymm14; vinserti128 $1, %xmm0, %ymm1, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 15 * 32(%rax); + vmovdqu %ymm13, 15 * 32(%rax); /* check need for handling 64-bit overflow and carry */ cmpq $(0xffffffffffffffff - 32), %r11; @@ -968,10 +970,10 @@ _gcry_camellia_aesni_avx2_ctr_enc: vpaddq %ymm15, %ymm15, %ymm15; /* ab: -2:0 ; cd: -2:0 */ vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 14 * 32(%rax); + vmovdqu %ymm13, 14 * 32(%rax); vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 13 * 32(%rax); + vmovdqu %ymm13, 13 * 32(%rax); vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm12; vpsubq %ymm15, %ymm0, %ymm0; @@ -1010,11 +1012,11 @@ _gcry_camellia_aesni_avx2_ctr_enc: inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le1 ; cd: le2 */ inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le2 ; cd: le3 */ vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 14 * 32(%rax); + vmovdqu %ymm13, 14 * 32(%rax); inc_le128(%ymm0, %ymm15, %ymm13); inc_le128(%ymm0, %ymm15, %ymm13); vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 13 * 32(%rax); + vmovdqu %ymm13, 13 * 32(%rax); inc_le128(%ymm0, %ymm15, %ymm13); inc_le128(%ymm0, %ymm15, %ymm13); vpshufb %ymm14, %ymm0, %ymm12; @@ -1083,8 +1085,6 @@ _gcry_camellia_aesni_avx2_ctr_enc: call __camellia_enc_blk32; - movq %r10, %rsp; - vpxor 0 * 32(%rdx), %ymm7, %ymm7; vpxor 1 * 32(%rdx), %ymm6, %ymm6; vpxor 2 * 32(%rdx), %ymm5, %ymm5; @@ -1109,6 +1109,7 @@ _gcry_camellia_aesni_avx2_ctr_enc: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_ctr_enc,.-_gcry_camellia_aesni_avx2_ctr_enc; @@ -1124,6 +1125,9 @@ _gcry_camellia_aesni_avx2_cbc_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; movq %rcx, %r9; @@ -1133,9 +1137,8 @@ _gcry_camellia_aesni_avx2_cbc_dec: movl $24, %eax; cmovel %eax, %r8d; /* max */ - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; inpack32_pre(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, @@ -1145,11 +1148,11 @@ _gcry_camellia_aesni_avx2_cbc_dec: call __camellia_dec_blk32; /* XOR output with IV */ - vmovdqa %ymm8, (%rax); + vmovdqu %ymm8, (%rax); vmovdqu (%r9), %xmm8; vinserti128 $1, (%rdx), %ymm8, %ymm8; vpxor %ymm8, %ymm7, %ymm7; - vmovdqa (%rax), %ymm8; + vmovdqu (%rax), %ymm8; vpxor (0 * 32 + 16)(%rdx), %ymm6, %ymm6; vpxor (1 * 32 + 16)(%rdx), %ymm5, %ymm5; vpxor (2 * 32 + 16)(%rdx), %ymm4, %ymm4; @@ -1168,8 +1171,6 @@ _gcry_camellia_aesni_avx2_cbc_dec: movq (15 * 32 + 16 + 0)(%rdx), %rax; movq (15 * 32 + 16 + 8)(%rdx), %rcx; - movq %r10, %rsp; - write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0, %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9, %ymm8, %rsi); @@ -1180,6 +1181,7 @@ _gcry_camellia_aesni_avx2_cbc_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_cbc_dec,.-_gcry_camellia_aesni_avx2_cbc_dec; @@ -1195,11 +1197,13 @@ _gcry_camellia_aesni_avx2_cfb_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; /* inpack16_pre: */ @@ -1228,8 +1232,6 @@ _gcry_camellia_aesni_avx2_cfb_dec: call __camellia_enc_blk32; - movq %r10, %rsp; - vpxor 0 * 32(%rdx), %ymm7, %ymm7; vpxor 1 * 32(%rdx), %ymm6, %ymm6; vpxor 2 * 32(%rdx), %ymm5, %ymm5; @@ -1253,6 +1255,7 @@ _gcry_camellia_aesni_avx2_cfb_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_cfb_dec,.-_gcry_camellia_aesni_avx2_cfb_dec; From cvs at cvs.gnupg.org Tue Nov 26 11:25:45 2013 From: cvs at cvs.gnupg.org (by Jussi Kivilinna) Date: Tue, 26 Nov 2013 11:25:45 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-404-g3ef21e7 Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 3ef21e7e1b8003db9792155044db95f9d9ced184 (commit) from a34448c929b13bfb7b66d69169c89e7319a18b31 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3ef21e7e1b8003db9792155044db95f9d9ced184 Author: Jussi Kivilinna Date: Sun Nov 24 17:54:15 2013 +0200 Camellia: Tweaks for AES-NI implementations * cipher/camellia-aesni-avx-amd64.S: Align stack to 16 bytes; tweak key-setup for small speed up. * cipher/camellia-aesni-avx2-amd64.S: Use vmovdqu even with aligned stack; reorder vinsert128 instructions; use rbp for stack frame. -- Use of 'vmovdqa' with ymm registers produces quite interesting scattering in measurement timings. By using 'vmovdqu' instead, repeated measuments produce more stable results. Signed-off-by: Jussi Kivilinna diff --git a/cipher/camellia-aesni-avx-amd64.S b/cipher/camellia-aesni-avx-amd64.S index ffb1aed..38ec7a3 100644 --- a/cipher/camellia-aesni-avx-amd64.S +++ b/cipher/camellia-aesni-avx-amd64.S @@ -958,9 +958,13 @@ _gcry_camellia_aesni_avx_ctr_enc: * %rcx: iv (big endian, 128bit) */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; vmovdqa .Lbswap128_mask RIP, %xmm14; @@ -1033,8 +1037,6 @@ _gcry_camellia_aesni_avx_ctr_enc: call __camellia_enc_blk16; - addq $(16 * 16), %rsp; - vpxor 0 * 16(%rdx), %xmm7, %xmm7; vpxor 1 * 16(%rdx), %xmm6, %xmm6; vpxor 2 * 16(%rdx), %xmm5, %xmm5; @@ -1058,6 +1060,7 @@ _gcry_camellia_aesni_avx_ctr_enc: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_ctr_enc,.-_gcry_camellia_aesni_avx_ctr_enc; @@ -1073,6 +1076,9 @@ _gcry_camellia_aesni_avx_cbc_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; movq %rcx, %r9; @@ -1087,12 +1093,11 @@ _gcry_camellia_aesni_avx_cbc_dec: %xmm15, %rdx, (key_table)(CTX, %r8, 8)); subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; call __camellia_dec_blk16; - addq $(16 * 16), %rsp; - /* XOR output with IV */ vpxor (%r9), %xmm7, %xmm7; vpxor (0 * 16)(%rdx), %xmm6, %xmm6; @@ -1112,6 +1117,7 @@ _gcry_camellia_aesni_avx_cbc_dec: vpxor (14 * 16)(%rdx), %xmm8, %xmm8; movq (15 * 16 + 0)(%rdx), %r10; movq (15 * 16 + 8)(%rdx), %r11; + write_output(%xmm7, %xmm6, %xmm5, %xmm4, %xmm3, %xmm2, %xmm1, %xmm0, %xmm15, %xmm14, %xmm13, %xmm12, %xmm11, %xmm10, %xmm9, %xmm8, %rsi); @@ -1122,6 +1128,7 @@ _gcry_camellia_aesni_avx_cbc_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_cbc_dec,.-_gcry_camellia_aesni_avx_cbc_dec; @@ -1137,9 +1144,13 @@ _gcry_camellia_aesni_avx_cfb_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; subq $(16 * 16), %rsp; + andq $~31, %rsp; movq %rsp, %rax; /* inpack16_pre: */ @@ -1166,8 +1177,6 @@ _gcry_camellia_aesni_avx_cfb_dec: call __camellia_enc_blk16; - addq $(16 * 16), %rsp; - vpxor 0 * 16(%rdx), %xmm7, %xmm7; vpxor 1 * 16(%rdx), %xmm6, %xmm6; vpxor 2 * 16(%rdx), %xmm5, %xmm5; @@ -1191,6 +1200,7 @@ _gcry_camellia_aesni_avx_cfb_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx_cfb_dec,.-_gcry_camellia_aesni_avx_cfb_dec; @@ -1199,7 +1209,7 @@ _gcry_camellia_aesni_avx_cfb_dec: * ab: 64-bit AB state * cd: 64-bit CD state */ -#define camellia_f(ab, x, t0, t1, t2, t3, t4, sbox2mask, sbox4mask, \ +#define camellia_f(ab, x, t0, t1, t2, t3, t4, inv_shift_row, sbox4mask, \ _0f0f0f0fmask, pre_s1lo_mask, pre_s1hi_mask, key) \ vmovq key, t0; \ vpxor x, x, t3; \ @@ -1221,37 +1231,33 @@ _gcry_camellia_aesni_avx_cfb_dec: \ vmovdqa .Lpost_tf_lo_s1 RIP, t0; \ vmovdqa .Lpost_tf_hi_s1 RIP, t1; \ - vmovq .Lsbox3_output_mask RIP, t4; \ \ /* prefilter sboxes */ \ filter_8bit(x, pre_s1lo_mask, pre_s1hi_mask, _0f0f0f0fmask, t2); \ \ /* AES subbytes + AES shift rows + AES inv shift rows */ \ vaesenclast t3, x, x; \ - vpshufb .Linv_shift_row RIP, x, x; \ \ /* postfilter sboxes */ \ filter_8bit(x, t0, t1, _0f0f0f0fmask, t2); \ \ /* output rotation for sbox2 (<<< 1) */ \ /* output rotation for sbox3 (>>> 1) */ \ - vpor sbox2mask, t4, t2; \ - vpand x, sbox2mask, t0; \ - vpand x, t4, t1; \ - vpaddb x, x, t2; \ - vpshufb .Lsp1110111044044404mask RIP, x, t4; \ - vpshufb .Lsp0044440410011110mask RIP, x, x; \ - vpsrlw $7, t0, t0; \ + vpshufb inv_shift_row, x, t1; \ + vpshufb .Lsp0044440444044404mask RIP, x, t4; \ + vpshufb .Lsp1110111010011110mask RIP, x, x; \ + vpaddb t1, t1, t2; \ + vpsrlw $7, t1, t0; \ vpsllw $7, t1, t3; \ - vpsrlw $1, t1, t1; \ vpor t0, t2, t0; \ + vpsrlw $1, t1, t1; \ vpshufb .Lsp0222022222000222mask RIP, t0, t0; \ vpor t1, t3, t1; \ - vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ \ vpxor x, t4, t4; \ - vpxor t1, t0, t0; \ + vpshufb .Lsp3033303303303033mask RIP, t1, t1; \ vpxor t4, t0, t0; \ + vpxor t1, t0, t0; \ vpsrldq $8, t0, x; \ vpxor t0, x, x; @@ -1270,22 +1276,21 @@ _gcry_camellia_aesni_avx_cfb_dec: .data .align 16 -.Lsp1110111044044404mask: - .long 0x000000ff, 0x000000ff; - .long 0x0101ff01, 0x0101ff01; -.Lsp0044440410011110mask: +.Linv_shift_row_and_unpcklbw: + .byte 0x00, 0xff, 0x0d, 0xff, 0x0a, 0xff, 0x07, 0xff + .byte 0x04, 0xff, 0x01, 0xff, 0x0e, 0xff, 0x0b, 0xff +.Lsp0044440444044404mask: .long 0xffff0404, 0x0404ff04; - .long 0x07ffff07, 0x070707ff; + .long 0x0d0dff0d, 0x0d0dff0d; +.Lsp1110111010011110mask: + .long 0x000000ff, 0x000000ff; + .long 0x0bffff0b, 0x0b0b0bff; .Lsp0222022222000222mask: - .long 0xff030303, 0xff030303; - .long 0x0606ffff, 0xff060606; + .long 0xff060606, 0xff060606; + .long 0x0c0cffff, 0xff0c0c0c; .Lsp3033303303303033mask: - .long 0x02ff0202, 0x02ff0202; - .long 0xff0505ff, 0x05ff0505; -.Lsbox2_output_mask: - .byte 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00; -.Lsbox3_output_mask: - .byte 0x00, 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00; + .long 0x04ff0404, 0x04ff0404; + .long 0xff0a0aff, 0x0aff0a0a; .Lsbox4_input_mask: .byte 0x00, 0xff, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00; .Lsigma1: @@ -1316,7 +1321,7 @@ __camellia_avx_setup128: vpshufb .Lbswap128_mask RIP, KL128, KL128; - vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11; vmovq .Lsbox4_input_mask RIP, %xmm12; vbroadcastss .L0f0f0f0f RIP, %xmm13; vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; @@ -1663,7 +1668,7 @@ __camellia_avx_setup256: vpshufb .Lbswap128_mask RIP, KL128, KL128; vpshufb .Lbswap128_mask RIP, KR128, KR128; - vmovq .Lsbox2_output_mask RIP, %xmm11; + vmovdqa .Linv_shift_row_and_unpcklbw RIP, %xmm11; vmovq .Lsbox4_input_mask RIP, %xmm12; vbroadcastss .L0f0f0f0f RIP, %xmm13; vmovdqa .Lpre_tf_lo_s1 RIP, %xmm14; diff --git a/cipher/camellia-aesni-avx2-amd64.S b/cipher/camellia-aesni-avx2-amd64.S index 65c923e..1a89ff4 100644 --- a/cipher/camellia-aesni-avx2-amd64.S +++ b/cipher/camellia-aesni-avx2-amd64.S @@ -124,15 +124,15 @@ vextracti128 $1, x5, t5##_x; \ vaesenclast t4##_x, x0##_x, x0##_x; \ vaesenclast t4##_x, t0##_x, t0##_x; \ - vinserti128 $1, t0##_x, x0, x0; \ vaesenclast t4##_x, x7##_x, x7##_x; \ vaesenclast t4##_x, t1##_x, t1##_x; \ - vinserti128 $1, t1##_x, x7, x7; \ vaesenclast t4##_x, x3##_x, x3##_x; \ vaesenclast t4##_x, t3##_x, t3##_x; \ - vinserti128 $1, t3##_x, x3, x3; \ vaesenclast t4##_x, x6##_x, x6##_x; \ vaesenclast t4##_x, t2##_x, t2##_x; \ + vinserti128 $1, t0##_x, x0, x0; \ + vinserti128 $1, t1##_x, x7, x7; \ + vinserti128 $1, t3##_x, x3, x3; \ vinserti128 $1, t2##_x, x6, x6; \ vextracti128 $1, x1, t3##_x; \ vextracti128 $1, x4, t2##_x; \ @@ -140,15 +140,15 @@ vbroadcasti128 .Lpost_tf_hi_s1 RIP, t1; \ vaesenclast t4##_x, x2##_x, x2##_x; \ vaesenclast t4##_x, t6##_x, t6##_x; \ - vinserti128 $1, t6##_x, x2, x2; \ vaesenclast t4##_x, x5##_x, x5##_x; \ vaesenclast t4##_x, t5##_x, t5##_x; \ - vinserti128 $1, t5##_x, x5, x5; \ vaesenclast t4##_x, x1##_x, x1##_x; \ vaesenclast t4##_x, t3##_x, t3##_x; \ - vinserti128 $1, t3##_x, x1, x1; \ vaesenclast t4##_x, x4##_x, x4##_x; \ vaesenclast t4##_x, t2##_x, t2##_x; \ + vinserti128 $1, t6##_x, x2, x2; \ + vinserti128 $1, t5##_x, x5, x5; \ + vinserti128 $1, t3##_x, x1, x1; \ vinserti128 $1, t2##_x, x4, x4; \ \ /* postfilter sboxes 1 and 4 */ \ @@ -249,14 +249,14 @@ roundsm32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_cd, (key_table + (i) * 8)(CTX)); \ \ - vmovdqa x0, 4 * 32(mem_cd); \ - vmovdqa x1, 5 * 32(mem_cd); \ - vmovdqa x2, 6 * 32(mem_cd); \ - vmovdqa x3, 7 * 32(mem_cd); \ - vmovdqa x4, 0 * 32(mem_cd); \ - vmovdqa x5, 1 * 32(mem_cd); \ - vmovdqa x6, 2 * 32(mem_cd); \ - vmovdqa x7, 3 * 32(mem_cd); \ + vmovdqu x0, 4 * 32(mem_cd); \ + vmovdqu x1, 5 * 32(mem_cd); \ + vmovdqu x2, 6 * 32(mem_cd); \ + vmovdqu x3, 7 * 32(mem_cd); \ + vmovdqu x4, 0 * 32(mem_cd); \ + vmovdqu x5, 1 * 32(mem_cd); \ + vmovdqu x6, 2 * 32(mem_cd); \ + vmovdqu x7, 3 * 32(mem_cd); \ \ roundsm32(x4, x5, x6, x7, x0, x1, x2, x3, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_ab, (key_table + ((i) + (dir)) * 8)(CTX)); \ @@ -267,14 +267,14 @@ #define store_ab_state(x0, x1, x2, x3, x4, x5, x6, x7, mem_ab) \ /* Store new AB state */ \ - vmovdqa x4, 4 * 32(mem_ab); \ - vmovdqa x5, 5 * 32(mem_ab); \ - vmovdqa x6, 6 * 32(mem_ab); \ - vmovdqa x7, 7 * 32(mem_ab); \ - vmovdqa x0, 0 * 32(mem_ab); \ - vmovdqa x1, 1 * 32(mem_ab); \ - vmovdqa x2, 2 * 32(mem_ab); \ - vmovdqa x3, 3 * 32(mem_ab); + vmovdqu x4, 4 * 32(mem_ab); \ + vmovdqu x5, 5 * 32(mem_ab); \ + vmovdqu x6, 6 * 32(mem_ab); \ + vmovdqu x7, 7 * 32(mem_ab); \ + vmovdqu x0, 0 * 32(mem_ab); \ + vmovdqu x1, 1 * 32(mem_ab); \ + vmovdqu x2, 2 * 32(mem_ab); \ + vmovdqu x3, 3 * 32(mem_ab); #define enc_rounds32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, y5, \ y6, y7, mem_ab, mem_cd, i) \ @@ -356,13 +356,13 @@ \ vpxor l4, t0, l4; \ vpbroadcastd krr, t0; /* only lowest 32-bit used */ \ - vmovdqa l4, 4 * 32(l); \ + vmovdqu l4, 4 * 32(l); \ vpxor l5, t1, l5; \ - vmovdqa l5, 5 * 32(l); \ + vmovdqu l5, 5 * 32(l); \ vpxor l6, t2, l6; \ - vmovdqa l6, 6 * 32(l); \ + vmovdqu l6, 6 * 32(l); \ vpxor l7, t3, l7; \ - vmovdqa l7, 7 * 32(l); \ + vmovdqu l7, 7 * 32(l); \ \ /* \ * t2 = krr; \ @@ -387,11 +387,11 @@ vpxor 1 * 32(r), t1, t1; \ vpxor 2 * 32(r), t2, t2; \ vpxor 3 * 32(r), t3, t3; \ - vmovdqa t0, 0 * 32(r); \ + vmovdqu t0, 0 * 32(r); \ vpbroadcastd krl, t0; /* only lowest 32-bit used */ \ - vmovdqa t1, 1 * 32(r); \ - vmovdqa t2, 2 * 32(r); \ - vmovdqa t3, 3 * 32(r); \ + vmovdqu t1, 1 * 32(r); \ + vmovdqu t2, 2 * 32(r); \ + vmovdqu t3, 3 * 32(r); \ \ /* \ * t2 = krl; \ @@ -417,11 +417,11 @@ vpxor 5 * 32(r), t1, t1; \ vpxor 6 * 32(r), t2, t2; \ vpxor 7 * 32(r), t3, t3; \ - vmovdqa t0, 4 * 32(r); \ + vmovdqu t0, 4 * 32(r); \ vpbroadcastd klr, t0; /* only lowest 32-bit used */ \ - vmovdqa t1, 5 * 32(r); \ - vmovdqa t2, 6 * 32(r); \ - vmovdqa t3, 7 * 32(r); \ + vmovdqu t1, 5 * 32(r); \ + vmovdqu t2, 6 * 32(r); \ + vmovdqu t3, 7 * 32(r); \ \ /* \ * t0 = klr; \ @@ -443,13 +443,13 @@ vpor l7, t3, t3; \ \ vpxor l0, t0, l0; \ - vmovdqa l0, 0 * 32(l); \ + vmovdqu l0, 0 * 32(l); \ vpxor l1, t1, l1; \ - vmovdqa l1, 1 * 32(l); \ + vmovdqu l1, 1 * 32(l); \ vpxor l2, t2, l2; \ - vmovdqa l2, 2 * 32(l); \ + vmovdqu l2, 2 * 32(l); \ vpxor l3, t3, l3; \ - vmovdqa l3, 3 * 32(l); + vmovdqu l3, 3 * 32(l); #define transpose_4x4(x0, x1, x2, x3, t1, t2) \ vpunpckhdq x1, x0, t2; \ @@ -466,20 +466,20 @@ #define byteslice_16x16b_fast(a0, b0, c0, d0, a1, b1, c1, d1, a2, b2, c2, d2, \ a3, b3, c3, d3, st0, st1) \ - vmovdqa d2, st0; \ - vmovdqa d3, st1; \ + vmovdqu d2, st0; \ + vmovdqu d3, st1; \ transpose_4x4(a0, a1, a2, a3, d2, d3); \ transpose_4x4(b0, b1, b2, b3, d2, d3); \ - vmovdqa st0, d2; \ - vmovdqa st1, d3; \ + vmovdqu st0, d2; \ + vmovdqu st1, d3; \ \ - vmovdqa a0, st0; \ - vmovdqa a1, st1; \ + vmovdqu a0, st0; \ + vmovdqu a1, st1; \ transpose_4x4(c0, c1, c2, c3, a0, a1); \ transpose_4x4(d0, d1, d2, d3, a0, a1); \ \ vbroadcasti128 .Lshufb_16x16b RIP, a0; \ - vmovdqa st1, a1; \ + vmovdqu st1, a1; \ vpshufb a0, a2, a2; \ vpshufb a0, a3, a3; \ vpshufb a0, b0, b0; \ @@ -495,22 +495,22 @@ vpshufb a0, d1, d1; \ vpshufb a0, d2, d2; \ vpshufb a0, d3, d3; \ - vmovdqa d3, st1; \ - vmovdqa st0, d3; \ + vmovdqu d3, st1; \ + vmovdqu st0, d3; \ vpshufb a0, d3, a0; \ - vmovdqa d2, st0; \ + vmovdqu d2, st0; \ \ transpose_4x4(a0, b0, c0, d0, d2, d3); \ transpose_4x4(a1, b1, c1, d1, d2, d3); \ - vmovdqa st0, d2; \ - vmovdqa st1, d3; \ + vmovdqu st0, d2; \ + vmovdqu st1, d3; \ \ - vmovdqa b0, st0; \ - vmovdqa b1, st1; \ + vmovdqu b0, st0; \ + vmovdqu b1, st1; \ transpose_4x4(a2, b2, c2, d2, b0, b1); \ transpose_4x4(a3, b3, c3, d3, b0, b1); \ - vmovdqa st0, b0; \ - vmovdqa st1, b1; \ + vmovdqu st0, b0; \ + vmovdqu st1, b1; \ /* does not adjust output bytes inside vectors */ /* load blocks to registers and apply pre-whitening */ @@ -542,22 +542,22 @@ byteslice_16x16b_fast(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, \ y4, y5, y6, y7, (mem_ab), (mem_cd)); \ \ - vmovdqa x0, 0 * 32(mem_ab); \ - vmovdqa x1, 1 * 32(mem_ab); \ - vmovdqa x2, 2 * 32(mem_ab); \ - vmovdqa x3, 3 * 32(mem_ab); \ - vmovdqa x4, 4 * 32(mem_ab); \ - vmovdqa x5, 5 * 32(mem_ab); \ - vmovdqa x6, 6 * 32(mem_ab); \ - vmovdqa x7, 7 * 32(mem_ab); \ - vmovdqa y0, 0 * 32(mem_cd); \ - vmovdqa y1, 1 * 32(mem_cd); \ - vmovdqa y2, 2 * 32(mem_cd); \ - vmovdqa y3, 3 * 32(mem_cd); \ - vmovdqa y4, 4 * 32(mem_cd); \ - vmovdqa y5, 5 * 32(mem_cd); \ - vmovdqa y6, 6 * 32(mem_cd); \ - vmovdqa y7, 7 * 32(mem_cd); + vmovdqu x0, 0 * 32(mem_ab); \ + vmovdqu x1, 1 * 32(mem_ab); \ + vmovdqu x2, 2 * 32(mem_ab); \ + vmovdqu x3, 3 * 32(mem_ab); \ + vmovdqu x4, 4 * 32(mem_ab); \ + vmovdqu x5, 5 * 32(mem_ab); \ + vmovdqu x6, 6 * 32(mem_ab); \ + vmovdqu x7, 7 * 32(mem_ab); \ + vmovdqu y0, 0 * 32(mem_cd); \ + vmovdqu y1, 1 * 32(mem_cd); \ + vmovdqu y2, 2 * 32(mem_cd); \ + vmovdqu y3, 3 * 32(mem_cd); \ + vmovdqu y4, 4 * 32(mem_cd); \ + vmovdqu y5, 5 * 32(mem_cd); \ + vmovdqu y6, 6 * 32(mem_cd); \ + vmovdqu y7, 7 * 32(mem_cd); /* de-byteslice, apply post-whitening and store blocks */ #define outunpack32(x0, x1, x2, x3, x4, x5, x6, x7, y0, y1, y2, y3, y4, \ @@ -565,7 +565,7 @@ byteslice_16x16b_fast(y0, y4, x0, x4, y1, y5, x1, x5, y2, y6, x2, x6, \ y3, y7, x3, x7, stack_tmp0, stack_tmp1); \ \ - vmovdqa x0, stack_tmp0; \ + vmovdqu x0, stack_tmp0; \ \ vpbroadcastq key, x0; \ vpshufb .Lpack_bswap RIP, x0, x0; \ @@ -800,14 +800,14 @@ __camellia_enc_blk32: .Lenc_done: /* load CD for output */ - vmovdqa 0 * 32(%rcx), %ymm8; - vmovdqa 1 * 32(%rcx), %ymm9; - vmovdqa 2 * 32(%rcx), %ymm10; - vmovdqa 3 * 32(%rcx), %ymm11; - vmovdqa 4 * 32(%rcx), %ymm12; - vmovdqa 5 * 32(%rcx), %ymm13; - vmovdqa 6 * 32(%rcx), %ymm14; - vmovdqa 7 * 32(%rcx), %ymm15; + vmovdqu 0 * 32(%rcx), %ymm8; + vmovdqu 1 * 32(%rcx), %ymm9; + vmovdqu 2 * 32(%rcx), %ymm10; + vmovdqu 3 * 32(%rcx), %ymm11; + vmovdqu 4 * 32(%rcx), %ymm12; + vmovdqu 5 * 32(%rcx), %ymm13; + vmovdqu 6 * 32(%rcx), %ymm14; + vmovdqu 7 * 32(%rcx), %ymm15; outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, @@ -887,14 +887,14 @@ __camellia_dec_blk32: %ymm15, %rax, %rcx, 0); /* load CD for output */ - vmovdqa 0 * 32(%rcx), %ymm8; - vmovdqa 1 * 32(%rcx), %ymm9; - vmovdqa 2 * 32(%rcx), %ymm10; - vmovdqa 3 * 32(%rcx), %ymm11; - vmovdqa 4 * 32(%rcx), %ymm12; - vmovdqa 5 * 32(%rcx), %ymm13; - vmovdqa 6 * 32(%rcx), %ymm14; - vmovdqa 7 * 32(%rcx), %ymm15; + vmovdqu 0 * 32(%rcx), %ymm8; + vmovdqu 1 * 32(%rcx), %ymm9; + vmovdqu 2 * 32(%rcx), %ymm10; + vmovdqu 3 * 32(%rcx), %ymm11; + vmovdqu 4 * 32(%rcx), %ymm12; + vmovdqu 5 * 32(%rcx), %ymm13; + vmovdqu 6 * 32(%rcx), %ymm14; + vmovdqu 7 * 32(%rcx), %ymm15; outunpack32(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, %ymm8, %ymm9, %ymm10, %ymm11, %ymm12, %ymm13, %ymm14, @@ -937,14 +937,16 @@ _gcry_camellia_aesni_avx2_ctr_enc: * %rcx: iv (big endian, 128bit) */ + pushq %rbp; + movq %rsp, %rbp; + movq 8(%rcx), %r11; bswapq %r11; vzeroupper; - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; vpcmpeqd %ymm15, %ymm15, %ymm15; @@ -958,7 +960,7 @@ _gcry_camellia_aesni_avx2_ctr_enc: vbroadcasti128 .Lbswap128_mask RIP, %ymm14; vinserti128 $1, %xmm0, %ymm1, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 15 * 32(%rax); + vmovdqu %ymm13, 15 * 32(%rax); /* check need for handling 64-bit overflow and carry */ cmpq $(0xffffffffffffffff - 32), %r11; @@ -968,10 +970,10 @@ _gcry_camellia_aesni_avx2_ctr_enc: vpaddq %ymm15, %ymm15, %ymm15; /* ab: -2:0 ; cd: -2:0 */ vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 14 * 32(%rax); + vmovdqu %ymm13, 14 * 32(%rax); vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 13 * 32(%rax); + vmovdqu %ymm13, 13 * 32(%rax); vpsubq %ymm15, %ymm0, %ymm0; vpshufb %ymm14, %ymm0, %ymm12; vpsubq %ymm15, %ymm0, %ymm0; @@ -1010,11 +1012,11 @@ _gcry_camellia_aesni_avx2_ctr_enc: inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le1 ; cd: le2 */ inc_le128(%ymm0, %ymm15, %ymm13); /* ab: le2 ; cd: le3 */ vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 14 * 32(%rax); + vmovdqu %ymm13, 14 * 32(%rax); inc_le128(%ymm0, %ymm15, %ymm13); inc_le128(%ymm0, %ymm15, %ymm13); vpshufb %ymm14, %ymm0, %ymm13; - vmovdqa %ymm13, 13 * 32(%rax); + vmovdqu %ymm13, 13 * 32(%rax); inc_le128(%ymm0, %ymm15, %ymm13); inc_le128(%ymm0, %ymm15, %ymm13); vpshufb %ymm14, %ymm0, %ymm12; @@ -1083,8 +1085,6 @@ _gcry_camellia_aesni_avx2_ctr_enc: call __camellia_enc_blk32; - movq %r10, %rsp; - vpxor 0 * 32(%rdx), %ymm7, %ymm7; vpxor 1 * 32(%rdx), %ymm6, %ymm6; vpxor 2 * 32(%rdx), %ymm5, %ymm5; @@ -1109,6 +1109,7 @@ _gcry_camellia_aesni_avx2_ctr_enc: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_ctr_enc,.-_gcry_camellia_aesni_avx2_ctr_enc; @@ -1124,6 +1125,9 @@ _gcry_camellia_aesni_avx2_cbc_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; movq %rcx, %r9; @@ -1133,9 +1137,8 @@ _gcry_camellia_aesni_avx2_cbc_dec: movl $24, %eax; cmovel %eax, %r8d; /* max */ - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; inpack32_pre(%ymm0, %ymm1, %ymm2, %ymm3, %ymm4, %ymm5, %ymm6, %ymm7, @@ -1145,11 +1148,11 @@ _gcry_camellia_aesni_avx2_cbc_dec: call __camellia_dec_blk32; /* XOR output with IV */ - vmovdqa %ymm8, (%rax); + vmovdqu %ymm8, (%rax); vmovdqu (%r9), %xmm8; vinserti128 $1, (%rdx), %ymm8, %ymm8; vpxor %ymm8, %ymm7, %ymm7; - vmovdqa (%rax), %ymm8; + vmovdqu (%rax), %ymm8; vpxor (0 * 32 + 16)(%rdx), %ymm6, %ymm6; vpxor (1 * 32 + 16)(%rdx), %ymm5, %ymm5; vpxor (2 * 32 + 16)(%rdx), %ymm4, %ymm4; @@ -1168,8 +1171,6 @@ _gcry_camellia_aesni_avx2_cbc_dec: movq (15 * 32 + 16 + 0)(%rdx), %rax; movq (15 * 32 + 16 + 8)(%rdx), %rcx; - movq %r10, %rsp; - write_output(%ymm7, %ymm6, %ymm5, %ymm4, %ymm3, %ymm2, %ymm1, %ymm0, %ymm15, %ymm14, %ymm13, %ymm12, %ymm11, %ymm10, %ymm9, %ymm8, %rsi); @@ -1180,6 +1181,7 @@ _gcry_camellia_aesni_avx2_cbc_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_cbc_dec,.-_gcry_camellia_aesni_avx2_cbc_dec; @@ -1195,11 +1197,13 @@ _gcry_camellia_aesni_avx2_cfb_dec: * %rcx: iv */ + pushq %rbp; + movq %rsp, %rbp; + vzeroupper; - movq %rsp, %r10; subq $(16 * 32), %rsp; - andq $~31, %rsp; + andq $~63, %rsp; movq %rsp, %rax; /* inpack16_pre: */ @@ -1228,8 +1232,6 @@ _gcry_camellia_aesni_avx2_cfb_dec: call __camellia_enc_blk32; - movq %r10, %rsp; - vpxor 0 * 32(%rdx), %ymm7, %ymm7; vpxor 1 * 32(%rdx), %ymm6, %ymm6; vpxor 2 * 32(%rdx), %ymm5, %ymm5; @@ -1253,6 +1255,7 @@ _gcry_camellia_aesni_avx2_cfb_dec: vzeroall; + leave; ret; .size _gcry_camellia_aesni_avx2_cfb_dec,.-_gcry_camellia_aesni_avx2_cfb_dec; ----------------------------------------------------------------------- Summary of changes: cipher/camellia-aesni-avx-amd64.S | 73 ++++++------ cipher/camellia-aesni-avx2-amd64.S | 215 ++++++++++++++++++------------------ 2 files changed, 148 insertions(+), 140 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Tue Nov 26 13:31:39 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Tue, 26 Nov 2013 14:31:39 +0200 Subject: Tasks for 1.6 In-Reply-To: <87iow47hsy.fsf@vigenere.g10code.de> References: <87iow47hsy.fsf@vigenere.g10code.de> Message-ID: <529494AB.10105@iki.fi> On 07.11.2013 10:11, Werner Koch wrote: > Hi, > > some notes on what I think should be done before a 1.6 release. > > - Decide what to do with MACing algorithms. > > - Check that the recent changes in gcry_pk_ don't break too much (this > is mainly about GnuPG and something I will take care about). > > - Check that the new threading initialization scheme works on major > platforms. > > - Look for rarely used function we may want to remove from the API (we > have an ABI change anyway) > > - Fix side-channel weaknesses in the new ECC code. > > - Run test builds on all Debian supported platforms I've only have access to x86 and ARM, but I've tested libgcrypt on other archs with help of cross-compilers and qemu userspace emulation. List of tested builds: - i386-linux-gnu (native) - x86_64-linux-gnu (native) - x86_64-linux-gnux32 (native) - arm-linux-gnueabihf (native) - mingw32 (wine) - powerpc-linux-gnu (qemu) - aarch64-linux-gnu (qemu) - mips-linux-gnu (qemu) - mipsel-linux-gnu (qemu) - sparc-linux-gnu (qemu) -Jussi > > After that I think the release of 1.6 is justified. Experience has > shown that we will need to release a couple of fixes soon after 1.6.0. > The important thing is that we keep the ABI stable after 1.6.0. > > I would like to do a release within the next 4 weeks. > > > Salam-Shalom, > > Werner > > From patrick at enigmail.net Tue Nov 26 17:50:34 2013 From: patrick at enigmail.net (Patrick Brunschwig) Date: Tue, 26 Nov 2013 17:50:34 +0100 Subject: Using --enable-special-filenames on Windows Message-ID: <5294D15A.4070109@enigmail.net> I'm trying to figure out how to use --enable-special-filenames on Windows. While the use of e.g. "-&9" is straight forward on Unix, I wonder how I have to implement a Windows application to use the same functionality (if at all)? Any hints welcome Thanks, Patrick From wk at gnupg.org Tue Nov 26 20:47:03 2013 From: wk at gnupg.org (Werner Koch) Date: Tue, 26 Nov 2013 20:47:03 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <5294D15A.4070109@enigmail.net> (Patrick Brunschwig's message of "Tue, 26 Nov 2013 17:50:34 +0100") References: <5294D15A.4070109@enigmail.net> Message-ID: <87wqjvgd3c.fsf@vigenere.g10code.de> On Tue, 26 Nov 2013 17:50, patrick at enigmail.net said: > I'm trying to figure out how to use --enable-special-filenames on > Windows. While the use of e.g. "-&9" is straight forward on Unix, I > wonder how I have to implement a Windows application to use the same GPGME is your friend ;-). You need to create a pipe with an inheritable file handle and pass that to gpg. The problem is that you need to use CreateProcess without the inherit flag (otherwise all handles would be inherited). The solution used by GPGME (and later done in the same way by GTK+) is to spawn a temporary process, duplicate the handles into that process along with a dup-to translation table and have that helper process then spawn gpg - now with the inherit flag set. It was quite some work to get that beast working reliable. Mozilla might have a similar mechanism somewhere. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From patrick at enigmail.net Wed Nov 27 08:25:06 2013 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 27 Nov 2013 08:25:06 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <87wqjvgd3c.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> Message-ID: <52959E52.2000208@enigmail.net> On 26.11.13 20:47, Werner Koch wrote: > On Tue, 26 Nov 2013 17:50, patrick at enigmail.net said: >> I'm trying to figure out how to use --enable-special-filenames >> on Windows. While the use of e.g. "-&9" is straight forward on >> Unix, I wonder how I have to implement a Windows application to >> use the same > > GPGME is your friend ;-). Not really when integrating with Thunderbird... > You need to create a pipe with an inheritable file handle and pass > that to gpg. The problem is that you need to use CreateProcess > without the inherit flag (otherwise all handles would be > inherited). The solution used by GPGME (and later done in the same > way by GTK+) is to spawn a temporary process, duplicate the handles > into that process along with a dup-to translation table and have > that helper process then spawn gpg - now with the inherit flag set. > It was quite some work to get that beast working reliable. I see, this is really tricky. > Mozilla might have a similar mechanism somewhere. Well yes, I'll have to dig into the Mozilla code once more... Thanks! -Patrick From lrn1986 at gmail.com Wed Nov 27 09:45:33 2013 From: lrn1986 at gmail.com (LRN) Date: Wed, 27 Nov 2013 12:45:33 +0400 Subject: Using --enable-special-filenames on Windows In-Reply-To: <87wqjvgd3c.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> Message-ID: <5295B12D.9080207@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 26.11.2013 23:47, Werner Koch wrote: > On Tue, 26 Nov 2013 17:50, patrick at enigmail.net said: >> I'm trying to figure out how to use --enable-special-filenames >> on Windows. While the use of e.g. "-&9" is straight forward on >> Unix, I wonder how I have to implement a Windows application to >> use the same > > GPGME is your friend ;-). > > You need to create a pipe with an inheritable file handle and pass > that to gpg. The problem is that you need to use CreateProcess > without the inherit flag (otherwise all handles would be > inherited). Isn't it easier to create all handles as non-inheritable (or make them non-inheritable immediately after creation), and then just make specific handles inheritable when you spawn a child process? - -- O< ascii ribbon - stop html email! - www.asciiribbon.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (MingW32) iQEcBAEBAgAGBQJSlbEtAAoJEOs4Jb6SI2CwWvMIAIY4T1HBgUxI37zo/8Eg3pmK ikpPG5jlQPYAltHyl8jcrS0u5+gGim5NJd4V3DfX0a6x+1jbxvrEvUvdB+BDsrlK 9wYLWtVVt9csROJ3uGed18OgjQbdsd8ixEqafWju7Vb7cG9RNtc93HJG+DWFqaYR 5BgoiC4PSGB2itAsj2VstZhYc0Yp5UXOIFLU/04Ik6BnDtOXoKz+5WVDvlVPC25P giEs5qT6aVCvqsdzcy9l3ZZ7r7c56n5MsRGaHlvHtFoCljoCxcPAGE9QhRkdoHR1 hgcbti3URFOzZW/9onSjr7EN5w2OtOSfNApOrWn6zEDo+PysTylYdmqTUSb3jXY= =Mp6N -----END PGP SIGNATURE----- From wk at gnupg.org Wed Nov 27 11:04:22 2013 From: wk at gnupg.org (Werner Koch) Date: Wed, 27 Nov 2013 11:04:22 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <52959E52.2000208@enigmail.net> (Patrick Brunschwig's message of "Wed, 27 Nov 2013 08:25:06 +0100") References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <52959E52.2000208@enigmail.net> Message-ID: <878uwagnyx.fsf@vigenere.g10code.de> On Wed, 27 Nov 2013 08:25, patrick at enigmail.net said: > > Not really when integrating with Thunderbird... Where is the problem? Should we try to get into into Moziall proper? Is the LGPL a problem? Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From wk at gnupg.org Wed Nov 27 11:29:12 2013 From: wk at gnupg.org (Werner Koch) Date: Wed, 27 Nov 2013 11:29:12 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <5295B12D.9080207@gmail.com> (LRN's message of "Wed, 27 Nov 2013 12:45:33 +0400") References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <5295B12D.9080207@gmail.com> Message-ID: <8738migmtj.fsf@vigenere.g10code.de> On Wed, 27 Nov 2013 09:45, lrn1986 at gmail.com said: > Isn't it easier to create all handles as non-inheritable (or make them > non-inheritable immediately after creation), and then just make > specific handles inheritable when you spawn a child process? You can't do that in a library because you can't enforce such a policy on the actual application and other used libraries. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From lrn1986 at gmail.com Wed Nov 27 11:42:08 2013 From: lrn1986 at gmail.com (LRN) Date: Wed, 27 Nov 2013 14:42:08 +0400 Subject: Using --enable-special-filenames on Windows In-Reply-To: <8738migmtj.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <5295B12D.9080207@gmail.com> <8738migmtj.fsf@vigenere.g10code.de> Message-ID: <5295CC80.80005@gmail.com> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On 27.11.2013 14:29, Werner Koch wrote: > On Wed, 27 Nov 2013 09:45 LRN said: > >> Isn't it easier to create all handles as non-inheritable (or make >> them non-inheritable immediately after creation), and then just >> make specific handles inheritable when you spawn a child >> process? > > You can't do that in a library because you can't enforce such a > policy on the actual application and other used libraries. You can make it part of the API: "All objects are uninheritable by default (non-inheritable on W32, close-on-fork on other platforms)" and provide platform-abstracted API to override that rule (depends on how the objects are used, and by whom). Just a thought. - -- O< ascii ribbon - stop html email! - www.asciiribbon.org -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (MingW32) iQEcBAEBAgAGBQJSlcyAAAoJEOs4Jb6SI2CwYJ8IAJInLtqeHc8NUL7qr9PR91bI yOwsOUChbymrP1A4f7nm0JCKjtPfKWxQ5YC0dNJTTJa330ILMp3AYy0nH8jlmb9I JFDeP0yXfTUfnSzpEgTd3btSGdZ1MurfzEiTvfsK25gHrNPErleMITIEvv7ctys9 leCcuCaEtSM/s1PMp9F75kBBDOZMfcLlFEmzbk0yLtgVsxgC6Fpwa4FgJvTvrm3k lm4z8olwyp5be2xeuHeaqxeqCgD+5Dm1DrakknXp52JlVVlbB47HhvHvpqCc435j zjWVwKG7hMDmFVUMBFiZREM/8gzM0g7qGA6H9HD0TnKWzgST/eS+X6/8Pz1jBro= =+/EU -----END PGP SIGNATURE----- From patrick at enigmail.net Wed Nov 27 12:56:57 2013 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 27 Nov 2013 12:56:57 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <878uwagnyx.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <52959E52.2000208@enigmail.net> <878uwagnyx.fsf@vigenere.g10code.de> Message-ID: <5295DE09.1070908@enigmail.net> On 27.11.13 11:04, Werner Koch wrote: > On Wed, 27 Nov 2013 08:25, patrick at enigmail.net said: >> >> Not really when integrating with Thunderbird... > > Where is the problem? Should we try to get into into Moziall proper? > Is the LGPL a problem? The main "problem" is that I don't want any binary components in Enigmail anymore. I worked for the last two years on replacing all binary components with JavaScript, and where this wasn't possible, I either moved C++ code to Thunderbird (very little), or I'm using the JavaScript-to-C bridge to use libc / Windows-core APIs. I reached this goal almost entirely - the only remaining binary component is a tiny wrapper library to do the fork()-ing on Unix (to avoid issues with garbage collection in JavaScript), and no binary code on Windows at all. Integrating gpgme in the Mozilla product could be a solution, but I'm not sure if this would be accepted by Mozilla. And it would need to be part of standard Thunderbird builds (which I think is quite unlikely). But I'll certainly look into gpgme to see how it's done there. -Patrick From grothoff at gnunet.org Wed Nov 27 12:45:15 2013 From: grothoff at gnunet.org (Christian Grothoff) Date: Wed, 27 Nov 2013 12:45:15 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <8738migmtj.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <5295B12D.9080207@gmail.com> <8738migmtj.fsf@vigenere.g10code.de> Message-ID: <5295DB4B.6030107@gnunet.org> True, but it does make sense to ensure that all sockets opened by a library are non-inheritable by default. My 2 cents Christian On 11/27/13 11:29, Werner Koch wrote: > On Wed, 27 Nov 2013 09:45, lrn1986 at gmail.com said: > >> Isn't it easier to create all handles as non-inheritable (or make them >> non-inheritable immediately after creation), and then just make >> specific handles inheritable when you spawn a child process? > > You can't do that in a library because you can't enforce such a policy > on the actual application and other used libraries. > > > Shalom-Salam, > > Werner > > From wk at gnupg.org Wed Nov 27 13:59:18 2013 From: wk at gnupg.org (Werner Koch) Date: Wed, 27 Nov 2013 13:59:18 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <5295CC80.80005@gmail.com> (LRN's message of "Wed, 27 Nov 2013 14:42:08 +0400") References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> <5295B12D.9080207@gmail.com> <8738migmtj.fsf@vigenere.g10code.de> <5295CC80.80005@gmail.com> Message-ID: <87y54af1ax.fsf@vigenere.g10code.de> On Wed, 27 Nov 2013 11:42, lrn1986 at gmail.com said: > You can make it part of the API: "All objects are uninheritable by > default (non-inheritable on W32, close-on-fork on other platforms)" > and provide platform-abstracted API to override that rule (depends on We have to live with the existing operating systems and can't change their behaviour anymore. One library can't force the author of a large application not to use other libraries which will have side effects on the used file descriptors. Application writers are often not aware of what libraries they are actually using (cf. inter library dependencies and all the mess with linking to to several ABIs of the same library) Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From patrick at enigmail.net Wed Nov 27 18:28:39 2013 From: patrick at enigmail.net (Patrick Brunschwig) Date: Wed, 27 Nov 2013 18:28:39 +0100 Subject: Using --enable-special-filenames on Windows In-Reply-To: <87wqjvgd3c.fsf@vigenere.g10code.de> References: <5294D15A.4070109@enigmail.net> <87wqjvgd3c.fsf@vigenere.g10code.de> Message-ID: <52962BC7.90905@enigmail.net> On 26.11.13 20:47, Werner Koch wrote: > On Tue, 26 Nov 2013 17:50, patrick at enigmail.net said: >> I'm trying to figure out how to use --enable-special-filenames on >> Windows. While the use of e.g. "-&9" is straight forward on Unix, I >> wonder how I have to implement a Windows application to use the same > > GPGME is your friend ;-). > > You need to create a pipe with an inheritable file handle and pass that > to gpg. The problem is that you need to use CreateProcess without the > inherit flag (otherwise all handles would be inherited). The solution > used by GPGME (and later done in the same way by GTK+) is to spawn a > temporary process, duplicate the handles into that process along with a > dup-to translation table and have that helper process then spawn gpg - > now with the inherit flag set. It was quite some work to get that beast > working reliable. If I get it right, then gpgme-w32spawn does this translation. Now, I'd assume that the easiest for my case would be to just use this bit of gpgme and keep the rest as it is. I tried to figure out how gpgme-w32spawn works. My understanding is that you create a temporary file containing the translation table(?) and otherwise you pass the arguments for gpg to the command line. However, it's not straight forward by reading the code. Could you enlighten me? Thanks, Patrick From wk at gnupg.org Wed Nov 27 19:17:08 2013 From: wk at gnupg.org (Werner Koch) Date: Wed, 27 Nov 2013 19:17:08 +0100 Subject: Tasks for 1.6 In-Reply-To: <87iow47hsy.fsf@vigenere.g10code.de> (Werner Koch's message of "Thu, 07 Nov 2013 09:11:09 +0100") References: <87iow47hsy.fsf@vigenere.g10code.de> Message-ID: <878uw9g15n.fsf@vigenere.g10code.de> On Thu, 7 Nov 2013 09:11, wk at gnupg.org said: > - Decide what to do with MACing algorithms. Done. We have a new API. > - Check that the recent changes in gcry_pk_ don't break too much (this > is mainly about GnuPG and something I will take care about). Done. I can build gnupg 2.0 with Libgcrypt 1.5 as well as with 1.6. GnuPG 2.1 meanwhile requires 1.6 and work. Thus this should be fine as well. > - Check that the new threading initialization scheme works on major > platforms. Done. I have not seen any problems but I have no non-ELF platforms for tests. > - Look for rarely used function we may want to remove from the API (we > have an ABI change anyway) Any suggestions? > - Fix side-channel weaknesses in the new ECC code. TBD > - Run test builds on all Debian supported platforms Done. Shalom-Salam, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From anil.singhar at linaro.org Thu Nov 28 06:24:07 2013 From: anil.singhar at linaro.org (Anil Singhar) Date: Thu, 28 Nov 2013 10:54:07 +0530 Subject: Fwd: Regarding porting libgcrypt11 to arm64 In-Reply-To: References: Message-ID: Hi, Could someone from the gcrypt developer community please let me know if the package "libgcrypt11" has been already been completely ported to arm64. I saw the following commit related to aarch64 by Jussi Kivilinna in the development branch: commit 2901a10dbf1264707debc8402546c07eeac60932 Author: Jussi Kivilinna Date: Wed Oct 23 18:36:18 2013 +0300 bufhelp: enable unaligned memory accesses for AArch64 (64-bit ARM) * cipher/bufhelp.h [__aarch64__] (BUFHELP_FAST_UNALIGNED_ACCESS): Set macro on AArch64. -- Signed-off-by: Jussi Kivilinna diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h index 21fac07..198d286 100644 --- a/cipher/bufhelp.h +++ b/cipher/bufhelp.h @@ -35,7 +35,8 @@ #if defined(__i386__) || defined(__x86_64__) || \ defined(__powerpc__) || defined(__powerpc64__) || \ - (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) + (defined(__arm__) && defined(__ARM_FEATURE_UNALIGNED)) || \ + defined(__aarch64__) Beyond this I could not find any other arm64 related commits. But looks like there are other functions such as those under the mpi folder, which has been traditionally written in assembly and possibly can be optimized using SIMD instructions available on aarch64/arm64. Could someone please let me know if anyone is already working on it and if not, may I work on it. Thanks and Regards, Anil -------------- next part -------------- An HTML attachment was scrubbed... URL: From wk at gnupg.org Thu Nov 28 08:49:05 2013 From: wk at gnupg.org (Werner Koch) Date: Thu, 28 Nov 2013 08:49:05 +0100 Subject: Fwd: Regarding porting libgcrypt11 to arm64 In-Reply-To: (Anil Singhar's message of "Thu, 28 Nov 2013 10:54:07 +0530") References: Message-ID: <8738mhezke.fsf@vigenere.g10code.de> On Thu, 28 Nov 2013 06:24, anil.singhar at linaro.org said: > Could someone from the gcrypt developer community please let me know if the > package "libgcrypt11" has been already been completely ported to arm64. I > saw the following commit related to aarch64 by Jussi Kivilinna in the AFAIK, the current libtool and the config.{guess,sub} files do not yet support arm64. I am in contact with another development team to work on that. Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Thu Nov 28 15:56:04 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Thu, 28 Nov 2013 16:56:04 +0200 Subject: Fwd: Regarding porting libgcrypt11 to arm64 In-Reply-To: <8738mhezke.fsf@vigenere.g10code.de> References: <8738mhezke.fsf@vigenere.g10code.de> Message-ID: <52975984.6040703@iki.fi> On 28.11.2013 09:49, Werner Koch wrote: > On Thu, 28 Nov 2013 06:24, anil.singhar at linaro.org said: > >> Could someone from the gcrypt developer community please let me know if the >> package "libgcrypt11" has been already been completely ported to arm64. I >> saw the following commit related to aarch64 by Jussi Kivilinna in the > > AFAIK, the current libtool and the config.{guess,sub} files do not yet > support arm64. I am in contact with another development team to work on > that. With config.{guess,sub} from development branch, libgcrypt11 can compiled on arm64 and passes tests. -Jussi > > > Salam-Shalom, > > Werner > From phcoder at gmail.com Fri Nov 29 08:55:32 2013 From: phcoder at gmail.com (=?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?=) Date: Fri, 29 Nov 2013 08:55:32 +0100 Subject: [PATCH] longlong.h on mips with clang In-Reply-To: <528EDC8C.7080808@gmail.com> References: <528EDC8C.7080808@gmail.com> Message-ID: <52984874.7020808@gmail.com> On 22.11.2013 05:24, Vladimir '?-coder/phcoder' Serbinenko wrote: > clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. Hence following patch: > > diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h > index 8c8260e..6f8dda7 100644 > --- a/grub-core/lib/libgcrypt/mpi/longlong.h > +++ b/grub-core/lib/libgcrypt/mpi/longlong.h > @@ -749,7 +749,7 @@ extern USItype __udiv_qrnnd (); > ************** MIPS ***************** > ***************************************/ > #if defined (__mips__) && W_TYPE_SIZE == 32 > -#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) > +#if defined (__clang__) || (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) > #define umul_ppmm(w1, w0, u, v) \ > do { \ > UDItype _r; > > Resulting assembly is > afc: 01a20019 multu t5,v0 > b00: 00006012 mflo t4 > b04: 00000810 mfhi at > which matches the intent. > ping? -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 291 bytes Desc: OpenPGP digital signature URL: From phcoder at gmail.com Fri Nov 29 08:56:43 2013 From: phcoder at gmail.com (=?UTF-8?B?VmxhZGltaXIgJ8+GLWNvZGVyL3BoY29kZXInIFNlcmJpbmVua28=?=) Date: Fri, 29 Nov 2013 08:56:43 +0100 Subject: [PATCH] Fix armv3 compile error Message-ID: <529848BB.3060903@gmail.com> ARMv3 code uses __CLOBBER_CC at the end of clobber list while it should have been __AND_CLOBBER_CC diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h index 6f8dda7..cd3ea20 100644 --- a/grub-core/lib/libgcrypt/mpi/longlong.h +++ b/grub-core/lib/libgcrypt/mpi/longlong.h @@ -247,7 +247,7 @@ extern UDItype __udiv_qrnnd (); "=r" ((xl)) \ : "r" ((USItype)(a)), \ "r" ((USItype)(b)) \ - : "r0", "r1", "r2" __CLOBBER_CC) + : "r0", "r1", "r2" __AND_CLOBBER_CC) #else /* __ARM_ARCH >= 4 */ #define umul_ppmm(xh, xl, a, b) \ __asm__ ("@ Inlined umul_ppmm\n" \ -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 291 bytes Desc: OpenPGP digital signature URL: From wk at gnupg.org Fri Nov 29 10:11:04 2013 From: wk at gnupg.org (Werner Koch) Date: Fri, 29 Nov 2013 10:11:04 +0100 Subject: [PATCH] longlong.h on mips with clang In-Reply-To: <52984874.7020808@gmail.com> ("Vladimir =?utf-8?Q?'=CF=86-cod?= =?utf-8?Q?er=2Fphcoder'?= Serbinenko"'s message of "Fri, 29 Nov 2013 08:55:32 +0100") References: <528EDC8C.7080808@gmail.com> <52984874.7020808@gmail.com> Message-ID: <87wqjrd13r.fsf@vigenere.g10code.de> Hi, On Fri, 29 Nov 2013 08:55, phcoder at gmail.com said: > On 22.11.2013 05:24, Vladimir '?-coder/phcoder' Serbinenko wrote: >> clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. Hence following patch: On Fri, 29 Nov 2013 08:56, phcoder at gmail.com said: > ARMv3 code uses __CLOBBER_CC at the end of clobber list while it should have been __AND_CLOBBER_CC Jussi: any reason not to apply them? Salam-Shalom, Werner -- Die Gedanken sind frei. Ausnahmen regelt ein Bundesgesetz. From jussi.kivilinna at iki.fi Fri Nov 29 10:59:07 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 29 Nov 2013 11:59:07 +0200 Subject: [PATCH] longlong.h on mips with clang In-Reply-To: <87wqjrd13r.fsf@vigenere.g10code.de> References: <528EDC8C.7080808@gmail.com> <52984874.7020808@gmail.com> <87wqjrd13r.fsf@vigenere.g10code.de> Message-ID: <5298656B.7000703@iki.fi> On 29.11.2013 11:11, Werner Koch wrote: > Hi, > > On Fri, 29 Nov 2013 08:55, phcoder at gmail.com said: >> On 22.11.2013 05:24, Vladimir '?-coder/phcoder' Serbinenko wrote: >>> clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. Hence following patch: > > On Fri, 29 Nov 2013 08:56, phcoder at gmail.com said: >> ARMv3 code uses __CLOBBER_CC at the end of clobber list while it should have been __AND_CLOBBER_CC > > Jussi: any reason not to apply them? Otherwise they look good, but these are not against libgcrypt repository: diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h And don't have changelog. -Jussi > > > Salam-Shalom, > > Werner > From jussi.kivilinna at iki.fi Fri Nov 29 12:00:46 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Fri, 29 Nov 2013 13:00:46 +0200 Subject: [PATCH] longlong.h on mips with clang In-Reply-To: <5298656B.7000703@iki.fi> References: <528EDC8C.7080808@gmail.com> <52984874.7020808@gmail.com> <87wqjrd13r.fsf@vigenere.g10code.de> <5298656B.7000703@iki.fi> Message-ID: <529873DE.8010909@iki.fi> On 29.11.2013 11:59, Jussi Kivilinna wrote: > On 29.11.2013 11:11, Werner Koch wrote: >> Hi, >> >> On Fri, 29 Nov 2013 08:55, phcoder at gmail.com said: >>> On 22.11.2013 05:24, Vladimir '?-coder/phcoder' Serbinenko wrote: >>>> clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. Hence following patch: >> >> On Fri, 29 Nov 2013 08:56, phcoder at gmail.com said: >>> ARMv3 code uses __CLOBBER_CC at the end of clobber list while it should have been __AND_CLOBBER_CC >> >> Jussi: any reason not to apply them? > > Otherwise they look good, but these are not against libgcrypt repository: > diff --git a/grub-core/lib/libgcrypt/mpi/longlong.h b/grub-core/lib/libgcrypt/mpi/longlong.h > > And don't have changelog. > > -Jussi Well, I've made the fixes and will push commits to repository soon. -Jussi > >> >> >> Salam-Shalom, >> >> Werner >> > > > _______________________________________________ > Gcrypt-devel mailing list > Gcrypt-devel at gnupg.org > http://lists.gnupg.org/mailman/listinfo/gcrypt-devel > From cvs at cvs.gnupg.org Fri Nov 29 12:07:36 2013 From: cvs at cvs.gnupg.org (by Vladimir 'φ-coder/phcoder' Serbinenko) Date: Fri, 29 Nov 2013 12:07:36 +0100 Subject: [git] GCRYPT - branch, master, updated. libgcrypt-1.5.0-406-g3b1cc9e Message-ID: This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "The GNU crypto library". The branch, master has been updated via 3b1cc9e6c357574f54160298d731c18f3d717b6c (commit) via 1ecbd0bca31d462719a2a6590c1d03244e76ef89 (commit) from 3ef21e7e1b8003db9792155044db95f9d9ced184 (commit) Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below. - Log ----------------------------------------------------------------- commit 3b1cc9e6c357574f54160298d731c18f3d717b6c Author: Vladimir '?-coder/phcoder' Serbinenko Date: Fri Nov 29 08:56:43 2013 +0100 Fix armv3 compile error * mpi/longlong.h [__arm__ && __ARM_ARCH < 4] (umul_ppmm): Use __AND_CLOBBER_CC instead of __CLOBBER_CC. -- ARMv3 code uses __CLOBBER_CC at the end of clobber list while it should have been __AND_CLOBBER_CC. [jk: add changelog, rebase on libgcrypt repository] Signed-off-by: Jussi Kivilinna diff --git a/mpi/longlong.h b/mpi/longlong.h index 90b0fd5..146830b 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -247,7 +247,7 @@ extern UDItype __udiv_qrnnd (); "=r" ((xl)) \ : "r" ((USItype)(a)), \ "r" ((USItype)(b)) \ - : "r0", "r1", "r2" __CLOBBER_CC) + : "r0", "r1", "r2" __AND_CLOBBER_CC) #else /* __ARM_ARCH >= 4 */ #define umul_ppmm(xh, xl, a, b) \ __asm__ ("@ Inlined umul_ppmm\n" \ commit 1ecbd0bca31d462719a2a6590c1d03244e76ef89 Author: Vladimir '?-coder/phcoder' Serbinenko Date: Fri Nov 22 05:24:44 2013 +0100 longlong.h on mips with clang * mpi/longlong.h [__mips__]: Use C-language version with clang. -- clang doesn't recognise =l / =h assembly operand specifiers but apparently handles C version well. [jk: add changelog, rebase on libgcrypt repository, reformat changed line so it does not go over 80 characters] Signed-off-by: Jussi Kivilinna diff --git a/mpi/longlong.h b/mpi/longlong.h index 8c8260e..90b0fd5 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -749,7 +749,8 @@ extern USItype __udiv_qrnnd (); ************** MIPS ***************** ***************************************/ #if defined (__mips__) && W_TYPE_SIZE == 32 -#if (__GNUC__ >= 5) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4) +#if defined (__clang__) || (__GNUC__ >= 5) || (__GNUC__ == 4 && \ + __GNUC_MINOR__ >= 4) #define umul_ppmm(w1, w0, u, v) \ do { \ UDItype _r; \ ----------------------------------------------------------------------- Summary of changes: mpi/longlong.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) hooks/post-receive -- The GNU crypto library http://git.gnupg.org _______________________________________________ Gnupg-commits mailing list Gnupg-commits at gnupg.org http://lists.gnupg.org/mailman/listinfo/gnupg-commits From jussi.kivilinna at iki.fi Sat Nov 30 22:22:43 2013 From: jussi.kivilinna at iki.fi (Jussi Kivilinna) Date: Sat, 30 Nov 2013 23:22:43 +0200 Subject: [PATCH] Add aarch64 (arm64) mpi assembly Message-ID: <20131130212243.3070.12569.stgit@localhost6.localdomain6> * mpi/aarch64/mpi-asm-defs.h: New. * mpi/aarch64/mpih-add1.S: New. * mpi/aarch64/mpih-mul1.S: New. * mpi/aarch64/mpih-mul2.S: New. * mpi/aarch64/mpih-mul3.S: New. * mpi/aarch64/mpih-sub1.S: New. * mpi/config.links [host=aarch64-*-*]: Add configguration for aarch64 assembly. * mpi/longlong.h [__aarch64__] (add_ssaaaa, sub_ddmmss, umul_ppmm) (count_leading_zeros): New. -- Add preliminary aarch64 assembly implementations for mpi. Signed-off-by: Jussi Kivilinna --- mpi/aarch64/mpi-asm-defs.h | 4 + mpi/aarch64/mpih-add1.S | 71 ++++++++++++++++++++++++++ mpi/aarch64/mpih-mul1.S | 96 +++++++++++++++++++++++++++++++++++ mpi/aarch64/mpih-mul2.S | 108 +++++++++++++++++++++++++++++++++++++++ mpi/aarch64/mpih-mul3.S | 121 ++++++++++++++++++++++++++++++++++++++++++++ mpi/aarch64/mpih-sub1.S | 71 ++++++++++++++++++++++++++ mpi/config.links | 5 ++ mpi/longlong.h | 35 +++++++++++++ 8 files changed, 511 insertions(+) create mode 100644 mpi/aarch64/mpi-asm-defs.h create mode 100644 mpi/aarch64/mpih-add1.S create mode 100644 mpi/aarch64/mpih-mul1.S create mode 100644 mpi/aarch64/mpih-mul2.S create mode 100644 mpi/aarch64/mpih-mul3.S create mode 100644 mpi/aarch64/mpih-sub1.S diff --git a/mpi/aarch64/mpi-asm-defs.h b/mpi/aarch64/mpi-asm-defs.h new file mode 100644 index 0000000..6519065 --- /dev/null +++ b/mpi/aarch64/mpi-asm-defs.h @@ -0,0 +1,4 @@ +/* This file defines some basic constants for the MPI machinery. We + * need to define the types on a per-CPU basis, so it is done with + * this file here. */ +#define BYTES_PER_MPI_LIMB (SIZEOF_UNSIGNED_LONG_LONG) diff --git a/mpi/aarch64/mpih-add1.S b/mpi/aarch64/mpih-add1.S new file mode 100644 index 0000000..9f7e2e6 --- /dev/null +++ b/mpi/aarch64/mpih-add1.S @@ -0,0 +1,71 @@ +/* ARM64 add_n -- Add two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright ? 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 "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_add_n( mpi_ptr_t res_ptr, x0 + * mpi_ptr_t s1_ptr, x1 + * mpi_ptr_t s2_ptr, x2 + * mpi_size_t size) x3 + */ + +.text + +.globl _gcry_mpih_add_n +.type _gcry_mpih_add_n,%function +_gcry_mpih_add_n: + and x5, x3, #3; + adds xzr, xzr, xzr; /* clear carry flag */ + + cbz x5, .Large_loop; + +.Loop: + ldr x4, [x1], #8; + sub x3, x3, #1; + ldr x11, [x2], #8; + and x5, x3, #3; + adcs x4, x4, x11; + str x4, [x0], #8; + cbz x3, .Lend; + cbnz x5, .Loop; + +.Large_loop: + ldp x4, x6, [x1], #16; + ldp x5, x7, [x2], #16; + ldp x8, x10, [x1], #16; + ldp x9, x11, [x2], #16; + sub x3, x3, #4; + adcs x4, x4, x5; + adcs x6, x6, x7; + adcs x8, x8, x9; + adcs x10, x10, x11; + stp x4, x6, [x0], #16; + stp x8, x10, [x0], #16; + cbnz x3, .Large_loop; + +.Lend: + adc x0, xzr, xzr; + ret; +.size _gcry_mpih_add_n,.-_gcry_mpih_add_n; diff --git a/mpi/aarch64/mpih-mul1.S b/mpi/aarch64/mpih-mul1.S new file mode 100644 index 0000000..cbb333f --- /dev/null +++ b/mpi/aarch64/mpih-mul1.S @@ -0,0 +1,96 @@ +/* ARM64 mul_1 -- Multiply a limb vector with a limb and store the result in + * a second limb vector. + * + * Copyright ? 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 "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_mul_1( mpi_ptr_t res_ptr, x0 + * mpi_ptr_t s1_ptr, x1 + * mpi_size_t s1_size, x2 + * mpi_limb_t s2_limb) x3 + */ + +.text + +.globl _gcry_mpih_mul_1 +.type _gcry_mpih_mul_1,%function +_gcry_mpih_mul_1: + and x5, x2, #3; + mov x4, xzr; + + cbz x5, .Large_loop; + +.Loop: + ldr x5, [x1], #8; + sub x2, x2, #1; + mul x9, x5, x3; + umulh x10, x5, x3; + and x5, x2, #3; + adds x4, x4, x9; + str x4, [x0], #8; + adc x4, x10, xzr; + + cbz x2, .Lend; + cbnz x5, .Loop; + +.Large_loop: + ldp x5, x6, [x1]; + sub x2, x2, #4; + + mul x9, x5, x3; + ldp x7, x8, [x1, #16]; + umulh x10, x5, x3; + add x1, x1, #32; + + adds x4, x4, x9; + str x4, [x0], #8; + mul x11, x6, x3; + adc x4, x10, xzr; + + umulh x12, x6, x3; + + adds x4, x4, x11; + str x4, [x0], #8; + mul x13, x7, x3; + adc x4, x12, xzr; + + umulh x14, x7, x3; + + adds x4, x4, x13; + str x4, [x0], #8; + mul x15, x8, x3; + adc x4, x14, xzr; + + umulh x16, x8, x3; + + adds x4, x4, x15; + str x4, [x0], #8; + adc x4, x16, xzr; + + cbnz x2, .Large_loop; + +.Lend: + mov x0, x4; + ret; +.size _gcry_mpih_mul_1,.-_gcry_mpih_mul_1; diff --git a/mpi/aarch64/mpih-mul2.S b/mpi/aarch64/mpih-mul2.S new file mode 100644 index 0000000..bfb3571 --- /dev/null +++ b/mpi/aarch64/mpih-mul2.S @@ -0,0 +1,108 @@ +/* ARM64 mul_2 -- Multiply a limb vector with a limb and add the result to + * a second limb vector. + * + * Copyright ? 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 "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_addmul_1( mpi_ptr_t res_ptr, x0 + * mpi_ptr_t s1_ptr, x1 + * mpi_size_t s1_size, x2 + * mpi_limb_t s2_limb) x3 + */ + +.text + +.globl _gcry_mpih_addmul_1 +.type _gcry_mpih_addmul_1,%function +_gcry_mpih_addmul_1: + and x5, x2, #3; + mov x6, xzr; + mov x7, xzr; + + cbz x5, .Large_loop; + +.Loop: + ldr x5, [x1], #8; + + mul x12, x5, x3; + ldr x4, [x0]; + umulh x13, x5, x3; + sub x2, x2, #1; + + adds x12, x12, x4; + and x5, x2, #3; + adc x13, x13, x7; + adds x12, x12, x6; + str x12, [x0], #8; + adc x6, x7, x13; + + cbz x2, .Lend; + cbnz x5, .Loop; + +.Large_loop: + ldp x5, x9, [x1], #16; + sub x2, x2, #4; + ldp x4, x8, [x0]; + + mul x12, x5, x3; + umulh x13, x5, x3; + + adds x12, x12, x4; + mul x14, x9, x3; + adc x13, x13, x7; + adds x12, x12, x6; + umulh x15, x9, x3; + str x12, [x0], #8; + adc x6, x7, x13; + + adds x14, x14, x8; + ldp x5, x9, [x1], #16; + adc x15, x15, x7; + adds x14, x14, x6; + mul x12, x5, x3; + str x14, [x0], #8; + ldp x4, x8, [x0]; + umulh x13, x5, x3; + adc x6, x7, x15; + + adds x12, x12, x4; + mul x14, x9, x3; + adc x13, x13, x7; + adds x12, x12, x6; + umulh x15, x9, x3; + str x12, [x0], #8; + adc x6, x7, x13; + + adds x14, x14, x8; + adc x15, x15, x7; + adds x14, x14, x6; + str x14, [x0], #8; + adc x6, x7, x15; + + cbnz x2, .Large_loop; + +.Lend: + mov x0, x6; + ret; +.size _gcry_mpih_addmul_1,.-_gcry_mpih_addmul_1; diff --git a/mpi/aarch64/mpih-mul3.S b/mpi/aarch64/mpih-mul3.S new file mode 100644 index 0000000..6f12b7b --- /dev/null +++ b/mpi/aarch64/mpih-mul3.S @@ -0,0 +1,121 @@ +/* ARM mul_3 -- Multiply a limb vector with a limb and subtract the result + * from a second limb vector. + * + * Copyright ? 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 "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_submul_1( mpi_ptr_t res_ptr, x0 + * mpi_ptr_t s1_ptr, x1 + * mpi_size_t s1_size, x2 + * mpi_limb_t s2_limb) x3 + */ + +.text + +.globl _gcry_mpih_submul_1 +.type _gcry_mpih_submul_1,%function +_gcry_mpih_submul_1: + and x5, x2, #3; + mov x7, xzr; + cbz x5, .Large_loop; + + subs xzr, xzr, xzr; + +.Loop: + ldr x4, [x1], #8; + cinc x7, x7, cc; + ldr x5, [x0]; + sub x2, x2, #1; + + mul x6, x4, x3; + subs x5, x5, x7; + umulh x4, x4, x3; + and x10, x2, #3; + + cset x7, cc; + subs x5, x5, x6; + add x7, x7, x4; + str x5, [x0], #8; + + cbz x2, .Loop_end; + cbnz x10, .Loop; + + cinc x7, x7, cc; + +.Large_loop: + ldp x4, x8, [x1], #16; + sub x2, x2, #4; + ldp x5, x9, [x0]; + + mul x6, x4, x3; + subs x5, x5, x7; + umulh x4, x4, x3; + + cset x7, cc; + subs x5, x5, x6; + mul x6, x8, x3; + add x7, x7, x4; + str x5, [x0], #8; + cinc x7, x7, cc; + + umulh x8, x8, x3; + + subs x9, x9, x7; + cset x7, cc; + subs x9, x9, x6; + ldp x4, x10, [x1], #16; + str x9, [x0], #8; + add x7, x7, x8; + ldp x5, x9, [x0]; + cinc x7, x7, cc; + + mul x6, x4, x3; + subs x5, x5, x7; + umulh x4, x4, x3; + + cset x7, cc; + subs x5, x5, x6; + mul x6, x10, x3; + add x7, x7, x4; + str x5, [x0], #8; + cinc x7, x7, cc; + + umulh x10, x10, x3; + + subs x9, x9, x7; + cset x7, cc; + subs x9, x9, x6; + add x7, x7, x10; + str x9, [x0], #8; + cinc x7, x7, cc; + + cbnz x2, .Large_loop; + + mov x0, x7; + ret; + +.Loop_end: + cinc x0, x7, cc; + ret; +.size _gcry_mpih_submul_1,.-_gcry_mpih_submul_1; diff --git a/mpi/aarch64/mpih-sub1.S b/mpi/aarch64/mpih-sub1.S new file mode 100644 index 0000000..f18b1cd --- /dev/null +++ b/mpi/aarch64/mpih-sub1.S @@ -0,0 +1,71 @@ +/* ARM64 sub_n -- Subtract two limb vectors of the same length > 0 and store + * sum in a third limb vector. + * + * Copyright ? 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 "sysdep.h" +#include "asm-syntax.h" + +/******************* + * mpi_limb_t + * _gcry_mpih_sub_n( mpi_ptr_t res_ptr, x0 + * mpi_ptr_t s1_ptr, x1 + * mpi_ptr_t s2_ptr, x2 + * mpi_size_t size) x3 + */ + +.text + +.globl _gcry_mpih_sub_n +.type _gcry_mpih_sub_n,%function +_gcry_mpih_sub_n: + and x5, x3, #3; + subs xzr, xzr, xzr; /* prepare carry flag for sub */ + + cbz x5, .Large_loop; + +.Loop: + ldr x4, [x1], #8; + sub x3, x3, #1; + ldr x11, [x2], #8; + and x5, x3, #3; + sbcs x4, x4, x11; + str x4, [x0], #8; + cbz x3, .Lend; + cbnz x5, .Loop; + +.Large_loop: + ldp x4, x6, [x1], #16; + ldp x5, x7, [x2], #16; + ldp x8, x10, [x1], #16; + ldp x9, x11, [x2], #16; + sub x3, x3, #4; + sbcs x4, x4, x5; + sbcs x6, x6, x7; + sbcs x8, x8, x9; + sbcs x10, x10, x11; + stp x4, x6, [x0], #16; + stp x8, x10, [x0], #16; + cbnz x3, .Large_loop; + +.Lend: + cset x0, cc; + ret; +.size _gcry_mpih_sub_n,.-_gcry_mpih_sub_n; diff --git a/mpi/config.links b/mpi/config.links index 90d1077..a79b03b 100644 --- a/mpi/config.links +++ b/mpi/config.links @@ -136,6 +136,11 @@ case "${host}" in mpi_extra_modules="udiv-qrnnd" mpi_cpu_arch="alpha" ;; + aarch64-*-*) + echo '/* configured for aarch64 */' >>./mpi/asm-syntax.h + path="aarch64" + mpi_cpu_arch="aarch64" + ;; arm*-*-*) if test "$gcry_cv_gcc_arm_platform_as_ok" = "yes" ; then echo '/* configured for arm */' >>./mpi/asm-syntax.h diff --git a/mpi/longlong.h b/mpi/longlong.h index 8c8260e..aad644e 100644 --- a/mpi/longlong.h +++ b/mpi/longlong.h @@ -268,6 +268,41 @@ extern UDItype __udiv_qrnnd (); #endif /* __arm__ */ /*************************************** + ********** ARM64 / Aarch64 ********** + ***************************************/ +#if defined(__aarch64__) && W_TYPE_SIZE == 64 +#define add_ssaaaa(sh, sl, ah, al, bh, bl) \ + __asm__ ("adds %1, %4, %5\n" \ + "adc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((UDItype)(ah)), \ + "r" ((UDItype)(bh)), \ + "r" ((UDItype)(al)), \ + "r" ((UDItype)(bl)) __CLOBBER_CC) +#define sub_ddmmss(sh, sl, ah, al, bh, bl) \ + __asm__ ("subs %1, %4, %5\n" \ + "sbc %0, %2, %3" \ + : "=r" ((sh)), \ + "=&r" ((sl)) \ + : "r" ((UDItype)(ah)), \ + "r" ((UDItype)(bh)), \ + "r" ((UDItype)(al)), \ + "r" ((UDItype)(bl)) __CLOBBER_CC) +#define umul_ppmm(xh, xl, a, b) \ + __asm__ ("mul %1, %2, %3\n" \ + "umulh %0, %2, %3" \ + : "=&r" ((xh)), \ + "=r" ((xl)) \ + : "r" ((UDItype)(a)), \ + "r" ((UDItype)(b))) +#define count_leading_zeros(count, x) \ + __asm__ ("clz %0, %1" \ + : "=r" ((count)) \ + : "r" ((UDItype)(x))) +#endif /* __aarch64__ */ + +/*************************************** ************** CLIPPER ************** ***************************************/ #if defined (__clipper__) && W_TYPE_SIZE == 32