diff options
author | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-11-21 21:34:21 +0200 |
---|---|---|
committer | Jussi Kivilinna <jussi.kivilinna@iki.fi> | 2013-11-21 21:34:21 +0200 |
commit | a34448c929b13bfb7b66d69169c89e7319a18b31 (patch) | |
tree | b53d13266af4d87a0fda5353333f957e3fd0c0e1 | |
parent | dbfa651618693da7ea73b4d2d00d4efd411bfb46 (diff) | |
download | libgcrypt-a34448c929b13bfb7b66d69169c89e7319a18b31.tar.gz |
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 <jussi.kivilinna@iki.fi>
-rw-r--r-- | cipher/Makefile.am | 2 | ||||
-rw-r--r-- | cipher/mac-gmac.c | 185 | ||||
-rw-r--r-- | cipher/mac-internal.h | 23 | ||||
-rw-r--r-- | cipher/mac.c | 5 | ||||
-rw-r--r-- | doc/gcrypt.texi | 34 | ||||
-rw-r--r-- | src/gcrypt.h.in | 8 | ||||
-rw-r--r-- | tests/basic.c | 57 | ||||
-rw-r--r-- | tests/bench-slope.c | 2 | ||||
-rw-r--r-- | tests/benchmark.c | 2 |
9 files changed, 303 insertions, 15 deletions
diff --git a/cipher/Makefile.am b/cipher/Makefile.am index e29b28d0..ff9deca1 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 00000000..e040bfee --- /dev/null +++ b/cipher/mac-gmac.c @@ -0,0 +1,185 @@ +/* mac-gmac.c - GMAC glue for MAC API + * Copyright © 2013 Jussi Kivilinna <jussi.kivilinna@iki.fi> + * + * This file is part of Libgcrypt. + * + * Libgcrypt is free software; you can redistribute it and/or modify + * it under the terms of the GNU Lesser general Public License as + * published by the Free Software Foundation; either version 2.1 of + * the License, or (at your option) any later version. + * + * Libgcrypt is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this program; if not, see <http://www.gnu.org/licenses/>. + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <errno.h> + +#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 146b2180..2a5e7c67 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 8d1dec05..5ac87291 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 1f6ceec7..4870a1c1 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. +@item GCRY_MAC_GMAC_AES +This is GMAC (GCM mode based MAC) message authentication algorithm based on +the AES block cipher algorithm. + +@item GCRY_MAC_GMAC_CAMELLIA +This is GMAC message authentication algorithm based on the Camellia +block cipher algorithm. + +@item GCRY_MAC_GMAC_TWOFISH +This is GMAC message authentication algorithm based on the Twofish +block cipher algorithm. + +@item GCRY_MAC_GMAC_SERPENT +This is GMAC message authentication algorithm based on the Serpent +block cipher algorithm. + +@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 -@c Some MAC algorithms need initialization vector to be set, which can be -@c performed with function: -@c @c -@c @deftypefun gcry_error_t gcry_mac_setiv (gcry_mac_hd_t @var{h}, const void *@var{iv}, size_t @var{ivlen}) -@c @c -@c Set the IV to the value of @var{iv} of length @var{ivlen} bytes. -@c @end deftypefun +GMAC algorithms need initialization vector to be set, which can be +performed with function: + +@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. +@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 24f7af66..625fa9fc 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 a205f48e..789297f1 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 d29a4ade..fd9f64b9 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 3058bd5c..8bb85846 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) ) |