/* mac-cmac.c - CMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_CMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_CMAC_3DES: return GCRY_CIPHER_3DES; case GCRY_MAC_CMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_CMAC_IDEA: return GCRY_CIPHER_IDEA; case GCRY_MAC_CMAC_CAST5: return GCRY_CIPHER_CAST5; case GCRY_MAC_CMAC_BLOWFISH: return GCRY_CIPHER_BLOWFISH; case GCRY_MAC_CMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_CMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_CMAC_SEED: return GCRY_CIPHER_SEED; case GCRY_MAC_CMAC_RFC2268: return GCRY_CIPHER_RFC2268_128; case GCRY_MAC_CMAC_GOST28147: return GCRY_CIPHER_GOST28147; } } 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