summaryrefslogtreecommitdiff
path: root/cipher/mac-cmac.c
diff options
context:
space:
mode:
authorJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-14 14:10:27 +0200
committerJussi Kivilinna <jussi.kivilinna@iki.fi>2013-11-19 19:18:56 +0200
commitb49cd64aaaff2e5488a84665362ef7150683226c (patch)
tree08a9aa2bd510d0231fa63ca481b03c5f42457aee /cipher/mac-cmac.c
parentfcd6da37d55f248d3558ee0ff385b41b866e7ded (diff)
downloadlibgcrypt-b49cd64aaaff2e5488a84665362ef7150683226c.tar.gz
Add CMAC (Cipher-based MAC) to MAC API
* cipher/Makefile.am: Add 'cipher-cmac.c' and 'mac-cmac.c'. * cipher/cipher-cmac.c: New. * cipher/cipher-internal.h (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' and do not clear subkeys in 'u_mode' in CMAC mode. * cipher/mac-cmac.c: New. * cipher/mac-internal.h: Add CMAC support and algorithms. * cipher/mac.c: Add CMAC algorithms. * doc/gcrypt.texi: Add documentation for CMAC. * 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. [v3]: - CMAC algorithm ids start from 201. - Coding style fixes. Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
Diffstat (limited to 'cipher/mac-cmac.c')
-rw-r--r--cipher/mac-cmac.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c
new file mode 100644
index 00000000..fddce394
--- /dev/null
+++ b/cipher/mac-cmac.c
@@ -0,0 +1,226 @@
+/* mac-cmac.c - CMAC 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_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