diff --git a/cipher/mac-cmac.c b/cipher/mac-cmac.c index e42a764d..aee5bb63 100644 --- a/cipher/mac-cmac.c +++ b/cipher/mac-cmac.c @@ -1,226 +1,227 @@ /* 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 + cmac_get_keylen, + NULL }; #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-gmac.c b/cipher/mac-gmac.c index 9bc86d97..aa78c7e3 100644 --- a/cipher/mac-gmac.c +++ b/cipher/mac-gmac.c @@ -1,185 +1,186 @@ /* mac-gmac.c - GMAC glue for MAC API * Copyright (C) 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include #include #include #include #include "g10lib.h" #include "cipher.h" #include "./mac-internal.h" static int map_mac_algo_to_cipher (int mac_algo) { switch (mac_algo) { default: return GCRY_CIPHER_NONE; case GCRY_MAC_GMAC_AES: return GCRY_CIPHER_AES; case GCRY_MAC_GMAC_CAMELLIA: return GCRY_CIPHER_CAMELLIA128; case GCRY_MAC_GMAC_TWOFISH: return GCRY_CIPHER_TWOFISH; case GCRY_MAC_GMAC_SERPENT: return GCRY_CIPHER_SERPENT128; case GCRY_MAC_GMAC_SEED: return GCRY_CIPHER_SEED; } } static gcry_err_code_t gmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_cipher_hd_t hd; int secure = (h->magic == CTX_MAGIC_SECURE); int 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 + gmac_get_keylen, + NULL }; #if USE_AES gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes = { GCRY_MAC_GMAC_AES, {0, 1}, "GMAC_AES", &gmac_ops }; #endif #if USE_TWOFISH gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish = { GCRY_MAC_GMAC_TWOFISH, {0, 0}, "GMAC_TWOFISH", &gmac_ops }; #endif #if USE_SERPENT gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent = { GCRY_MAC_GMAC_SERPENT, {0, 0}, "GMAC_SERPENT", &gmac_ops }; #endif #if USE_SEED gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed = { GCRY_MAC_GMAC_SEED, {0, 0}, "GMAC_SEED", &gmac_ops }; #endif #if USE_CAMELLIA gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia = { GCRY_MAC_GMAC_CAMELLIA, {0, 0}, "GMAC_CAMELLIA", &gmac_ops }; #endif diff --git a/cipher/mac-hmac.c b/cipher/mac-hmac.c index e488d03a..d0cc5775 100644 --- a/cipher/mac-hmac.c +++ b/cipher/mac-hmac.c @@ -1,396 +1,397 @@ /* mac-hmac.c - HMAC 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 "./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_MD2: return GCRY_MD_MD2; case GCRY_MAC_HMAC_MD4: return GCRY_MD_MD4; case GCRY_MAC_HMAC_MD5: return GCRY_MD_MD5; case GCRY_MAC_HMAC_SHA1: return GCRY_MD_SHA1; case GCRY_MAC_HMAC_SHA224: return GCRY_MD_SHA224; case GCRY_MAC_HMAC_SHA256: return GCRY_MD_SHA256; case GCRY_MAC_HMAC_SHA384: return GCRY_MD_SHA384; case GCRY_MAC_HMAC_SHA512: return GCRY_MD_SHA512; case GCRY_MAC_HMAC_SHA512_256: return GCRY_MD_SHA512_256; case GCRY_MAC_HMAC_SHA512_224: return GCRY_MD_SHA512_224; case GCRY_MAC_HMAC_SHA3_224: return GCRY_MD_SHA3_224; case GCRY_MAC_HMAC_SHA3_256: return GCRY_MD_SHA3_256; case GCRY_MAC_HMAC_SHA3_384: return GCRY_MD_SHA3_384; case GCRY_MAC_HMAC_SHA3_512: return GCRY_MD_SHA3_512; case GCRY_MAC_HMAC_RMD160: return GCRY_MD_RMD160; case GCRY_MAC_HMAC_TIGER1: return GCRY_MD_TIGER1; case GCRY_MAC_HMAC_WHIRLPOOL: return GCRY_MD_WHIRLPOOL; case GCRY_MAC_HMAC_GOSTR3411_94: return GCRY_MD_GOSTR3411_94; case GCRY_MAC_HMAC_GOSTR3411_CP: return GCRY_MD_GOSTR3411_CP; case GCRY_MAC_HMAC_STRIBOG256: return GCRY_MD_STRIBOG256; case GCRY_MAC_HMAC_STRIBOG512: return GCRY_MD_STRIBOG512; case GCRY_MAC_HMAC_BLAKE2B_512: return GCRY_MD_BLAKE2B_512; case GCRY_MAC_HMAC_BLAKE2B_384: return GCRY_MD_BLAKE2B_384; case GCRY_MAC_HMAC_BLAKE2B_256: return GCRY_MD_BLAKE2B_256; case GCRY_MAC_HMAC_BLAKE2B_160: return GCRY_MD_BLAKE2B_160; case GCRY_MAC_HMAC_BLAKE2S_256: return GCRY_MD_BLAKE2S_256; case GCRY_MAC_HMAC_BLAKE2S_224: return GCRY_MD_BLAKE2S_224; case GCRY_MAC_HMAC_BLAKE2S_160: return GCRY_MD_BLAKE2S_160; case GCRY_MAC_HMAC_BLAKE2S_128: return GCRY_MD_BLAKE2S_128; case GCRY_MAC_HMAC_SM3: return GCRY_MD_SM3; } } static gcry_err_code_t hmac_open (gcry_mac_hd_t h) { gcry_err_code_t err; gcry_md_hd_t hd; int secure = (h->magic == CTX_MAGIC_SECURE); unsigned int flags; int md_algo; md_algo = map_mac_algo_to_md (h->spec->algo); flags = GCRY_MD_FLAG_HMAC; flags |= (secure ? GCRY_MD_FLAG_SECURE : 0); err = _gcry_md_open (&hd, md_algo, flags); if (err) return err; h->u.hmac.md_algo = md_algo; h->u.hmac.md_ctx = hd; return 0; } static void hmac_close (gcry_mac_hd_t h) { _gcry_md_close (h->u.hmac.md_ctx); h->u.hmac.md_ctx = NULL; } static gcry_err_code_t hmac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { return _gcry_md_setkey (h->u.hmac.md_ctx, key, keylen); } static gcry_err_code_t hmac_reset (gcry_mac_hd_t h) { _gcry_md_reset (h->u.hmac.md_ctx); return 0; } static gcry_err_code_t hmac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { _gcry_md_write (h->u.hmac.md_ctx, buf, buflen); return 0; } static gcry_err_code_t hmac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t * outlen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (*outlen <= dlen) buf_cpy (outbuf, digest, *outlen); else { buf_cpy (outbuf, digest, dlen); *outlen = dlen; } return 0; } static gcry_err_code_t hmac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { unsigned int dlen; const unsigned char *digest; dlen = _gcry_md_get_algo_dlen (h->u.hmac.md_algo); digest = _gcry_md_read (h->u.hmac.md_ctx, h->u.hmac.md_algo); if (buflen > dlen) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, digest, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int hmac_get_maclen (int algo) { return _gcry_md_get_algo_dlen (map_mac_algo_to_md (algo)); } static unsigned int hmac_get_keylen (int algo) { /* Return blocksize for default key length. */ switch (algo) { case GCRY_MD_SHA3_224: return 1152 / 8; case GCRY_MD_SHA3_256: return 1088 / 8; case GCRY_MD_SHA3_384: return 832 / 8; case GCRY_MD_SHA3_512: return 576 / 8; case GCRY_MAC_HMAC_SHA384: case GCRY_MAC_HMAC_SHA512: return 128; case GCRY_MAC_HMAC_GOSTR3411_94: return 32; default: return 64; } } 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 + hmac_get_keylen, + NULL }; #if USE_SHA1 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1 = { GCRY_MAC_HMAC_SHA1, {0, 1}, "HMAC_SHA1", &hmac_ops }; #endif #if USE_SHA256 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256 = { GCRY_MAC_HMAC_SHA256, {0, 1}, "HMAC_SHA256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224 = { GCRY_MAC_HMAC_SHA224, {0, 1}, "HMAC_SHA224", &hmac_ops }; #endif #if USE_SHA512 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512 = { GCRY_MAC_HMAC_SHA512, {0, 1}, "HMAC_SHA512", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384 = { GCRY_MAC_HMAC_SHA384, {0, 1}, "HMAC_SHA384", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256 = { GCRY_MAC_HMAC_SHA512_256, {0, 1}, "HMAC_SHA512_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224 = { GCRY_MAC_HMAC_SHA512_224, {0, 1}, "HMAC_SHA512_224", &hmac_ops }; #endif #if USE_SHA3 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224 = { GCRY_MAC_HMAC_SHA3_224, {0, 1}, "HMAC_SHA3_224", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256 = { GCRY_MAC_HMAC_SHA3_256, {0, 1}, "HMAC_SHA3_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384 = { GCRY_MAC_HMAC_SHA3_384, {0, 1}, "HMAC_SHA3_384", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512 = { GCRY_MAC_HMAC_SHA3_512, {0, 1}, "HMAC_SHA3_512", &hmac_ops }; #endif #ifdef USE_GOST_R_3411_94 gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94 = { GCRY_MAC_HMAC_GOSTR3411_94, {0, 0}, "HMAC_GOSTR3411_94", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp = { GCRY_MAC_HMAC_GOSTR3411_CP, {0, 0}, "HMAC_GOSTR3411_CP", &hmac_ops }; #endif #ifdef USE_GOST_R_3411_12 gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256 = { GCRY_MAC_HMAC_STRIBOG256, {0, 0}, "HMAC_STRIBOG256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512 = { GCRY_MAC_HMAC_STRIBOG512, {0, 0}, "HMAC_STRIBOG512", &hmac_ops }; #endif #if USE_WHIRLPOOL gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool = { GCRY_MAC_HMAC_WHIRLPOOL, {0, 0}, "HMAC_WHIRLPOOL", &hmac_ops }; #endif #if USE_RMD160 gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160 = { GCRY_MAC_HMAC_RMD160, {0, 0}, "HMAC_RIPEMD160", &hmac_ops }; #endif #if USE_TIGER gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1 = { GCRY_MAC_HMAC_TIGER1, {0, 0}, "HMAC_TIGER", &hmac_ops }; #endif #if USE_MD5 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5 = { GCRY_MAC_HMAC_MD5, {0, 0}, "HMAC_MD5", &hmac_ops }; #endif #if USE_MD4 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4 = { GCRY_MAC_HMAC_MD4, {0, 0}, "HMAC_MD4", &hmac_ops }; #endif #if USE_MD2 gcry_mac_spec_t _gcry_mac_type_spec_hmac_md2 = { GCRY_MAC_HMAC_MD2, {0, 0}, "HMAC_MD2", &hmac_ops }; #endif #if USE_BLAKE2 gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512 = { GCRY_MAC_HMAC_BLAKE2B_512, {0, 0}, "HMAC_BLAKE2B_512", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384 = { GCRY_MAC_HMAC_BLAKE2B_384, {0, 0}, "HMAC_BLAKE2B_384", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256 = { GCRY_MAC_HMAC_BLAKE2B_256, {0, 0}, "HMAC_BLAKE2B_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160 = { GCRY_MAC_HMAC_BLAKE2B_160, {0, 0}, "HMAC_BLAKE2B_160", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256 = { GCRY_MAC_HMAC_BLAKE2S_256, {0, 0}, "HMAC_BLAKE2S_256", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224 = { GCRY_MAC_HMAC_BLAKE2S_224, {0, 0}, "HMAC_BLAKE2S_224", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160 = { GCRY_MAC_HMAC_BLAKE2S_160, {0, 0}, "HMAC_BLAKE2S_160", &hmac_ops }; gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128 = { GCRY_MAC_HMAC_BLAKE2S_128, {0, 0}, "HMAC_BLAKE2S_128", &hmac_ops }; #endif #if USE_SM3 gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3 = { GCRY_MAC_HMAC_SM3, {0, 0}, "HMAC_SM3", &hmac_ops }; #endif diff --git a/cipher/mac-internal.h b/cipher/mac-internal.h index 03f5b8da..15b4dfc2 100644 --- a/cipher/mac-internal.h +++ b/cipher/mac-internal.h @@ -1,256 +1,260 @@ /* mac-internal.h - Internal defs for mac.c * Copyright (C) 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include "g10lib.h" /* The data object used to hold a handle to an encryption object. */ struct gcry_mac_handle; /* The data object used to hold poly1305-mac context. */ struct poly1305mac_context_s; /* * * Message authentication code related definitions. * */ /* Magic values for the context structure. */ #define CTX_MAGIC_NORMAL 0x59d9b8af #define CTX_MAGIC_SECURE 0x12c27cd0 /* MAC module functions. */ typedef gcry_err_code_t (*gcry_mac_open_func_t)(gcry_mac_hd_t h); typedef void (*gcry_mac_close_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_setkey_func_t)(gcry_mac_hd_t h, const unsigned char *key, size_t keylen); typedef gcry_err_code_t (*gcry_mac_setiv_func_t)(gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen); typedef gcry_err_code_t (*gcry_mac_reset_func_t)(gcry_mac_hd_t h); typedef gcry_err_code_t (*gcry_mac_write_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef gcry_err_code_t (*gcry_mac_read_func_t)(gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen); typedef gcry_err_code_t (*gcry_mac_verify_func_t)(gcry_mac_hd_t h, const unsigned char *inbuf, size_t inlen); typedef unsigned int (*gcry_mac_get_maclen_func_t)(int algo); typedef unsigned int (*gcry_mac_get_keylen_func_t)(int algo); +/* The type used to convey additional information to a MAC. */ +typedef gpg_err_code_t (*gcry_mac_set_extra_info_t) + (gcry_mac_hd_t h, int what, const void *buffer, size_t buflen); typedef struct gcry_mac_spec_ops { gcry_mac_open_func_t open; gcry_mac_close_func_t close; gcry_mac_setkey_func_t setkey; gcry_mac_setiv_func_t setiv; gcry_mac_reset_func_t reset; gcry_mac_write_func_t write; gcry_mac_read_func_t read; gcry_mac_verify_func_t verify; gcry_mac_get_maclen_func_t get_maclen; gcry_mac_get_keylen_func_t get_keylen; + gcry_mac_set_extra_info_t set_extra_info; } gcry_mac_spec_ops_t; /* Module specification structure for message authentication codes. */ typedef struct gcry_mac_spec { int algo; struct { unsigned int disabled:1; unsigned int fips:1; } flags; const char *name; const gcry_mac_spec_ops_t *ops; } gcry_mac_spec_t; /* The handle structure. */ struct gcry_mac_handle { int magic; int algo; const gcry_mac_spec_t *spec; gcry_ctx_t gcry_ctx; union { struct { gcry_md_hd_t md_ctx; int md_algo; } hmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; unsigned int blklen; } cmac; struct { gcry_cipher_hd_t ctx; int cipher_algo; } gmac; struct { struct poly1305mac_context_s *ctx; } poly1305mac; } u; }; /* * The HMAC algorithm specifications (mac-hmac.c). */ #if USE_SHA1 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha1; #endif #if USE_SHA256 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha224; #endif #if USE_SHA512 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha384; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha512_256; #endif #if USE_SHA3 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_384; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sha3_512; #endif #ifdef USE_GOST_R_3411_94 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_94; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_gost3411_cp; #endif #ifdef USE_GOST_R_3411_12 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_stribog512; #endif #if USE_WHIRLPOOL extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_whirlpool; #endif #if USE_RMD160 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_rmd160; #endif #if USE_TIGER extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_tiger1; #endif #if USE_MD5 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md5; #endif #if USE_MD4 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_md4; #endif #if USE_BLAKE2 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_512; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_384; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2b_160; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_256; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_224; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_160; extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_blake2s_128; #endif #if USE_SM3 extern gcry_mac_spec_t _gcry_mac_type_spec_hmac_sm3; #endif /* * The CMAC algorithm specifications (mac-cmac.c). */ #if USE_BLOWFISH extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_blowfish; #endif #if USE_DES extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_tripledes; #endif #if USE_CAST5 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_cast5; #endif #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_aes; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_serpent; #endif #if USE_RFC2268 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_rfc2268; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_seed; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_camellia; #endif #ifdef USE_IDEA extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_idea; #endif #if USE_GOST28147 extern gcry_mac_spec_t _gcry_mac_type_spec_cmac_gost28147; #endif /* * The GMAC algorithm specifications (mac-gmac.c). */ #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_aes; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_serpent; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_seed; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_gmac_camellia; #endif /* * The Poly1305 MAC algorithm specifications (mac-poly1305.c). */ extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac; #if USE_AES extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes; #endif #if USE_CAMELLIA extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia; #endif #if USE_TWOFISH extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish; #endif #if USE_SERPENT extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent; #endif #if USE_SEED extern gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed; #endif diff --git a/cipher/mac-poly1305.c b/cipher/mac-poly1305.c index b80f87db..39ba790f 100644 --- a/cipher/mac-poly1305.c +++ b/cipher/mac-poly1305.c @@ -1,362 +1,363 @@ /* mac-poly1305.c - Poly1305 based MACs * Copyright (C) 2014 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" #include "poly1305-internal.h" struct poly1305mac_context_s { poly1305_context_t ctx; gcry_cipher_hd_t hd; struct { unsigned int key_set:1; unsigned int nonce_set:1; unsigned int tag:1; } marks; byte tag[POLY1305_TAGLEN]; byte key[POLY1305_KEYLEN]; }; static gcry_err_code_t poly1305mac_open (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx; int secure = (h->magic == CTX_MAGIC_SECURE); unsigned int flags = (secure ? GCRY_CIPHER_SECURE : 0); gcry_err_code_t err; int cipher_algo; if (secure) mac_ctx = xtrycalloc_secure (1, sizeof(*mac_ctx)); else mac_ctx = xtrycalloc (1, sizeof(*mac_ctx)); if (!mac_ctx) return gpg_err_code_from_syserror (); h->u.poly1305mac.ctx = mac_ctx; switch (h->spec->algo) { default: /* already checked. */ case GCRY_MAC_POLY1305: /* plain Poly1305. */ cipher_algo = -1; return 0; case GCRY_MAC_POLY1305_AES: cipher_algo = GCRY_CIPHER_AES; break; case GCRY_MAC_POLY1305_CAMELLIA: cipher_algo = GCRY_CIPHER_CAMELLIA128; break; case GCRY_MAC_POLY1305_TWOFISH: cipher_algo = GCRY_CIPHER_TWOFISH; break; case GCRY_MAC_POLY1305_SERPENT: cipher_algo = GCRY_CIPHER_SERPENT128; break; case GCRY_MAC_POLY1305_SEED: cipher_algo = GCRY_CIPHER_SEED; break; } err = _gcry_cipher_open_internal (&mac_ctx->hd, cipher_algo, GCRY_CIPHER_MODE_ECB, flags); if (err) goto err_free; return 0; err_free: xfree(h->u.poly1305mac.ctx); return err; } static void poly1305mac_close (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (h->spec->algo != GCRY_MAC_POLY1305) _gcry_cipher_close (mac_ctx->hd); xfree(mac_ctx); } static gcry_err_code_t poly1305mac_prepare_key (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; size_t block_keylen = keylen - 16; /* Need at least 16 + 1 byte key. */ if (keylen <= 16) return GPG_ERR_INV_KEYLEN; /* For Poly1305-AES, first part of key is passed to Poly1305 as is. */ memcpy (mac_ctx->key, key + block_keylen, 16); /* Remaining part is used as key for the block cipher. */ return _gcry_cipher_setkey (mac_ctx->hd, key, block_keylen); } static gcry_err_code_t poly1305mac_setkey (gcry_mac_hd_t h, const unsigned char *key, size_t keylen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); mac_ctx->marks.key_set = 0; mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; if (h->spec->algo != GCRY_MAC_POLY1305) { err = poly1305mac_prepare_key (h, key, keylen); if (err) return err; /* Poly1305-AES/etc also need nonce. */ mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 0; } else { /* For plain Poly1305, key is the nonce and setup is complete now. */ if (keylen != POLY1305_KEYLEN) return GPG_ERR_INV_KEYLEN; memcpy (mac_ctx->key, key, keylen); err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) { memset(&mac_ctx->key, 0, sizeof(mac_ctx->key)); return err; } mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; } return 0; } static gcry_err_code_t poly1305mac_setiv (gcry_mac_hd_t h, const unsigned char *iv, size_t ivlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; if (h->spec->algo == GCRY_MAC_POLY1305) return GPG_ERR_INV_ARG; if (ivlen != 16) return GPG_ERR_INV_ARG; if (!mac_ctx->marks.key_set) return 0; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.nonce_set = 0; mac_ctx->marks.tag = 0; /* Prepare second part of the poly1305 key. */ err = _gcry_cipher_encrypt (mac_ctx->hd, mac_ctx->key + 16, 16, iv, 16); if (err) return err; err = _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); if (err) return err; mac_ctx->marks.nonce_set = 1; return 0; } static gcry_err_code_t poly1305mac_reset (gcry_mac_hd_t h) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); memset(&mac_ctx->tag, 0, sizeof(mac_ctx->tag)); mac_ctx->marks.key_set = 1; mac_ctx->marks.nonce_set = 1; mac_ctx->marks.tag = 0; return _gcry_poly1305_init (&mac_ctx->ctx, mac_ctx->key, POLY1305_KEYLEN); } static gcry_err_code_t poly1305mac_write (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set || mac_ctx->marks.tag) return GPG_ERR_INV_STATE; _gcry_poly1305_update (&mac_ctx->ctx, buf, buflen); return 0; } static gcry_err_code_t poly1305mac_read (gcry_mac_hd_t h, unsigned char *outbuf, size_t *outlen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; if (!mac_ctx->marks.key_set || !mac_ctx->marks.nonce_set) return GPG_ERR_INV_STATE; if (!mac_ctx->marks.tag) { _gcry_poly1305_finish(&mac_ctx->ctx, mac_ctx->tag); memset(&mac_ctx->ctx, 0, sizeof(mac_ctx->ctx)); mac_ctx->marks.tag = 1; } if (*outlen == 0) return 0; if (*outlen <= POLY1305_TAGLEN) buf_cpy (outbuf, mac_ctx->tag, *outlen); else { buf_cpy (outbuf, mac_ctx->tag, POLY1305_TAGLEN); *outlen = POLY1305_TAGLEN; } return 0; } static gcry_err_code_t poly1305mac_verify (gcry_mac_hd_t h, const unsigned char *buf, size_t buflen) { struct poly1305mac_context_s *mac_ctx = h->u.poly1305mac.ctx; gcry_err_code_t err; size_t outlen = 0; /* Check and finalize tag. */ err = poly1305mac_read(h, NULL, &outlen); if (err) return err; if (buflen > POLY1305_TAGLEN) return GPG_ERR_INV_LENGTH; return buf_eq_const (buf, mac_ctx->tag, buflen) ? 0 : GPG_ERR_CHECKSUM; } static unsigned int poly1305mac_get_maclen (int algo) { (void)algo; return POLY1305_TAGLEN; } static unsigned int poly1305mac_get_keylen (int algo) { (void)algo; return POLY1305_KEYLEN; } static gcry_mac_spec_ops_t poly1305mac_ops = { poly1305mac_open, poly1305mac_close, poly1305mac_setkey, poly1305mac_setiv, poly1305mac_reset, poly1305mac_write, poly1305mac_read, poly1305mac_verify, poly1305mac_get_maclen, - poly1305mac_get_keylen + poly1305mac_get_keylen, + NULL }; gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac = { GCRY_MAC_POLY1305, {0, 0}, "POLY1305", &poly1305mac_ops }; #if USE_AES gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_aes = { GCRY_MAC_POLY1305_AES, {0, 0}, "POLY1305_AES", &poly1305mac_ops }; #endif #if USE_CAMELLIA gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_camellia = { GCRY_MAC_POLY1305_CAMELLIA, {0, 0}, "POLY1305_CAMELLIA", &poly1305mac_ops }; #endif #if USE_TWOFISH gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_twofish = { GCRY_MAC_POLY1305_TWOFISH, {0, 0}, "POLY1305_TWOFISH", &poly1305mac_ops }; #endif #if USE_SERPENT gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_serpent = { GCRY_MAC_POLY1305_SERPENT, {0, 0}, "POLY1305_SERPENT", &poly1305mac_ops }; #endif #if USE_SEED gcry_mac_spec_t _gcry_mac_type_spec_poly1305mac_seed = { GCRY_MAC_POLY1305_SEED, {0, 0}, "POLY1305_SEED", &poly1305mac_ops }; #endif diff --git a/cipher/mac.c b/cipher/mac.c index 0bbac3e4..1bc1aa98 100644 --- a/cipher/mac.c +++ b/cipher/mac.c @@ -1,763 +1,770 @@ /* mac.c - message authentication code dispatcher * Copyright (C) 2013 Jussi Kivilinna * * This file is part of Libgcrypt. * * Libgcrypt is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser general Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * Libgcrypt is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this program; if not, see . */ #include #include #include #include #include #include "g10lib.h" #include "mac-internal.h" /* This is the list of the digest implementations included in libgcrypt. */ static gcry_mac_spec_t * const mac_list[] = { #if USE_SHA1 &_gcry_mac_type_spec_hmac_sha1, #endif #if USE_SHA256 &_gcry_mac_type_spec_hmac_sha256, &_gcry_mac_type_spec_hmac_sha224, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #endif #if USE_SHA3 &_gcry_mac_type_spec_hmac_sha3_224, &_gcry_mac_type_spec_hmac_sha3_256, &_gcry_mac_type_spec_hmac_sha3_384, &_gcry_mac_type_spec_hmac_sha3_512, #endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, &_gcry_mac_type_spec_hmac_gost3411_cp, #endif #ifdef USE_GOST_R_3411_12 &_gcry_mac_type_spec_hmac_stribog256, &_gcry_mac_type_spec_hmac_stribog512, #endif #if USE_WHIRLPOOL &_gcry_mac_type_spec_hmac_whirlpool, #endif #if USE_RMD160 &_gcry_mac_type_spec_hmac_rmd160, #endif #if USE_TIGER &_gcry_mac_type_spec_hmac_tiger1, #endif #if USE_MD5 &_gcry_mac_type_spec_hmac_md5, #endif #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #endif #if USE_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #endif #if USE_BLOWFISH &_gcry_mac_type_spec_cmac_blowfish, #endif #if USE_DES &_gcry_mac_type_spec_cmac_tripledes, #endif #if USE_CAST5 &_gcry_mac_type_spec_cmac_cast5, #endif #if USE_AES &_gcry_mac_type_spec_cmac_aes, &_gcry_mac_type_spec_gmac_aes, &_gcry_mac_type_spec_poly1305mac_aes, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, &_gcry_mac_type_spec_gmac_twofish, &_gcry_mac_type_spec_poly1305mac_twofish, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, &_gcry_mac_type_spec_gmac_serpent, &_gcry_mac_type_spec_poly1305mac_serpent, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, #endif #if USE_SEED &_gcry_mac_type_spec_cmac_seed, &_gcry_mac_type_spec_gmac_seed, &_gcry_mac_type_spec_poly1305mac_seed, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, &_gcry_mac_type_spec_gmac_camellia, &_gcry_mac_type_spec_poly1305mac_camellia, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147, #endif &_gcry_mac_type_spec_poly1305mac, NULL, }; /* HMAC implementations start with index 101 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo101[] = { #if USE_SHA256 &_gcry_mac_type_spec_hmac_sha256, &_gcry_mac_type_spec_hmac_sha224, #else NULL, NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512, &_gcry_mac_type_spec_hmac_sha384, #else NULL, NULL, #endif #if USE_SHA1 &_gcry_mac_type_spec_hmac_sha1, #else NULL, #endif #if USE_MD5 &_gcry_mac_type_spec_hmac_md5, #else NULL, #endif #if USE_MD4 &_gcry_mac_type_spec_hmac_md4, #else NULL, #endif #if USE_RMD160 &_gcry_mac_type_spec_hmac_rmd160, #else NULL, #endif #if USE_TIGER &_gcry_mac_type_spec_hmac_tiger1, #else NULL, #endif #if USE_WHIRLPOOL &_gcry_mac_type_spec_hmac_whirlpool, #else NULL, #endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_94, #else NULL, #endif #ifdef USE_GOST_R_3411_12 &_gcry_mac_type_spec_hmac_stribog256, &_gcry_mac_type_spec_hmac_stribog512, #else NULL, NULL, #endif #if USE_MD2 &_gcry_mac_type_spec_hmac_md2, #else NULL, #endif #if USE_SHA3 &_gcry_mac_type_spec_hmac_sha3_224, &_gcry_mac_type_spec_hmac_sha3_256, &_gcry_mac_type_spec_hmac_sha3_384, &_gcry_mac_type_spec_hmac_sha3_512, #else NULL, NULL, NULL, NULL, #endif #ifdef USE_GOST_R_3411_94 &_gcry_mac_type_spec_hmac_gost3411_cp, #else NULL, #endif #if USE_BLAKE2 &_gcry_mac_type_spec_hmac_blake2b_512, &_gcry_mac_type_spec_hmac_blake2b_384, &_gcry_mac_type_spec_hmac_blake2b_256, &_gcry_mac_type_spec_hmac_blake2b_160, &_gcry_mac_type_spec_hmac_blake2s_256, &_gcry_mac_type_spec_hmac_blake2s_224, &_gcry_mac_type_spec_hmac_blake2s_160, &_gcry_mac_type_spec_hmac_blake2s_128, #else NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, #endif #if USE_SM3 &_gcry_mac_type_spec_hmac_sm3, #else NULL, #endif #if USE_SHA512 &_gcry_mac_type_spec_hmac_sha512_256, &_gcry_mac_type_spec_hmac_sha512_224, #else NULL, NULL, #endif }; /* CMAC implementations start with index 201 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo201[] = { #if USE_AES &_gcry_mac_type_spec_cmac_aes, #else NULL, #endif #if USE_DES &_gcry_mac_type_spec_cmac_tripledes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_cmac_camellia, #else NULL, #endif #if USE_CAST5 &_gcry_mac_type_spec_cmac_cast5, #else NULL, #endif #if USE_BLOWFISH &_gcry_mac_type_spec_cmac_blowfish, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_cmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_cmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_cmac_seed, #else NULL, #endif #if USE_RFC2268 &_gcry_mac_type_spec_cmac_rfc2268, #else NULL, #endif #ifdef USE_IDEA &_gcry_mac_type_spec_cmac_idea, #else NULL, #endif #if USE_GOST28147 &_gcry_mac_type_spec_cmac_gost28147 #else NULL #endif }; /* GMAC implementations start with index 401 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo401[] = { #if USE_AES &_gcry_mac_type_spec_gmac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_gmac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_gmac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_gmac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_gmac_seed #else NULL #endif }; /* Poly1305-MAC implementations start with index 501 (enum gcry_mac_algos) */ static gcry_mac_spec_t * const mac_list_algo501[] = { &_gcry_mac_type_spec_poly1305mac, #if USE_AES &_gcry_mac_type_spec_poly1305mac_aes, #else NULL, #endif #if USE_CAMELLIA &_gcry_mac_type_spec_poly1305mac_camellia, #else NULL, #endif #if USE_TWOFISH &_gcry_mac_type_spec_poly1305mac_twofish, #else NULL, #endif #if USE_SERPENT &_gcry_mac_type_spec_poly1305mac_serpent, #else NULL, #endif #if USE_SEED &_gcry_mac_type_spec_poly1305mac_seed #else NULL #endif }; /* Explicitly initialize this module. */ gcry_err_code_t _gcry_mac_init (void) { if (fips_mode()) { /* disable algorithms that are disallowed in fips */ int idx; gcry_mac_spec_t *spec; for (idx = 0; (spec = mac_list[idx]); idx++) if (!spec->flags.fips) spec->flags.disabled = 1; } return 0; } /* Return the spec structure for the MAC algorithm ALGO. For an unknown algorithm NULL is returned. */ static gcry_mac_spec_t * spec_from_algo (int algo) { gcry_mac_spec_t *spec = NULL; if (algo >= 101 && algo < 101 + DIM(mac_list_algo101)) spec = mac_list_algo101[algo - 101]; else if (algo >= 201 && algo < 201 + DIM(mac_list_algo201)) spec = mac_list_algo201[algo - 201]; else if (algo >= 401 && algo < 401 + DIM(mac_list_algo401)) spec = mac_list_algo401[algo - 401]; else if (algo >= 501 && algo < 501 + DIM(mac_list_algo501)) spec = mac_list_algo501[algo - 501]; if (spec) gcry_assert (spec->algo == algo); return spec; } /* Lookup a mac's spec by its name. */ static gcry_mac_spec_t * spec_from_name (const char *name) { gcry_mac_spec_t *spec; int idx; for (idx = 0; (spec = mac_list[idx]); idx++) if (!stricmp (name, spec->name)) return spec; return NULL; } /**************** * Map a string to the mac algo */ int _gcry_mac_map_name (const char *string) { gcry_mac_spec_t *spec; if (!string) return 0; /* Not found, search a matching mac name. */ spec = spec_from_name (string); if (spec) return spec->algo; return 0; } /**************** * This function simply returns the name of the algorithm or some constant * string when there is no algo. It will never return NULL. * Use the macro gcry_mac_test_algo() to check whether the algorithm * is valid. */ const char * _gcry_mac_algo_name (int algorithm) { gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); return spec ? spec->name : "?"; } static gcry_err_code_t check_mac_algo (int algorithm) { gcry_mac_spec_t *spec; spec = spec_from_algo (algorithm); if (spec && !spec->flags.disabled) return 0; return GPG_ERR_MAC_ALGO; } /**************** * Open a message digest handle for use with algorithm ALGO. */ static gcry_err_code_t mac_open (gcry_mac_hd_t * hd, int algo, int secure, gcry_ctx_t ctx) { gcry_mac_spec_t *spec; gcry_err_code_t err; gcry_mac_hd_t h; spec = spec_from_algo (algo); if (!spec) return GPG_ERR_MAC_ALGO; else if (spec->flags.disabled) return GPG_ERR_MAC_ALGO; else if (!spec->ops) return GPG_ERR_MAC_ALGO; else if (!spec->ops->open || !spec->ops->write || !spec->ops->setkey || !spec->ops->read || !spec->ops->verify || !spec->ops->reset) return GPG_ERR_MAC_ALGO; if (secure) h = xtrycalloc_secure (1, sizeof (*h)); else h = xtrycalloc (1, sizeof (*h)); if (!h) return gpg_err_code_from_syserror (); h->magic = secure ? CTX_MAGIC_SECURE : CTX_MAGIC_NORMAL; h->spec = spec; h->algo = algo; h->gcry_ctx = ctx; err = h->spec->ops->open (h); if (err) xfree (h); else *hd = h; return err; } static gcry_err_code_t mac_reset (gcry_mac_hd_t hd) { if (hd->spec->ops->reset) return hd->spec->ops->reset (hd); return 0; } static void mac_close (gcry_mac_hd_t hd) { if (hd->spec->ops->close) hd->spec->ops->close (hd); wipememory (hd, sizeof (*hd)); xfree (hd); } static gcry_err_code_t mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) { if (!hd->spec->ops->setkey) return GPG_ERR_INV_ARG; if (keylen > 0 && !key) return GPG_ERR_INV_ARG; return hd->spec->ops->setkey (hd, key, keylen); } static gcry_err_code_t mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) { if (!hd->spec->ops->setiv) return GPG_ERR_INV_ARG; if (ivlen > 0 && !iv) return GPG_ERR_INV_ARG; return hd->spec->ops->setiv (hd, iv, ivlen); } static gcry_err_code_t mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) { if (!hd->spec->ops->write) return GPG_ERR_INV_ARG; if (inlen > 0 && !inbuf) return GPG_ERR_INV_ARG; return hd->spec->ops->write (hd, inbuf, inlen); } static gcry_err_code_t mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen) { if (!outbuf || !outlen || *outlen == 0 || !hd->spec->ops->read) return GPG_ERR_INV_ARG; return hd->spec->ops->read (hd, outbuf, outlen); } static gcry_err_code_t mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) { if (!buf || buflen == 0 || !hd->spec->ops->verify) return GPG_ERR_INV_ARG; return hd->spec->ops->verify (hd, buf, buflen); } /* Create a MAC object for algorithm ALGO. FLAGS may be given as an bitwise OR of the gcry_mac_flags values. H is guaranteed to be a valid handle or NULL on error. */ gpg_err_code_t _gcry_mac_open (gcry_mac_hd_t * h, int algo, unsigned int flags, gcry_ctx_t ctx) { gcry_err_code_t rc; gcry_mac_hd_t hd = NULL; if ((flags & ~GCRY_MAC_FLAG_SECURE)) rc = GPG_ERR_INV_ARG; else rc = mac_open (&hd, algo, !!(flags & GCRY_MAC_FLAG_SECURE), ctx); *h = rc ? NULL : hd; return rc; } void _gcry_mac_close (gcry_mac_hd_t hd) { if (hd) mac_close (hd); } gcry_err_code_t _gcry_mac_setkey (gcry_mac_hd_t hd, const void *key, size_t keylen) { return mac_setkey (hd, key, keylen); } gcry_err_code_t _gcry_mac_setiv (gcry_mac_hd_t hd, const void *iv, size_t ivlen) { return mac_setiv (hd, iv, ivlen); } gcry_err_code_t _gcry_mac_write (gcry_mac_hd_t hd, const void *inbuf, size_t inlen) { return mac_write (hd, inbuf, inlen); } gcry_err_code_t _gcry_mac_read (gcry_mac_hd_t hd, void *outbuf, size_t * outlen) { return mac_read (hd, outbuf, outlen); } gcry_err_code_t _gcry_mac_verify (gcry_mac_hd_t hd, const void *buf, size_t buflen) { return mac_verify (hd, buf, buflen); } int _gcry_mac_get_algo (gcry_mac_hd_t hd) { return hd->algo; } unsigned int _gcry_mac_get_algo_maclen (int algo) { gcry_mac_spec_t *spec; spec = spec_from_algo (algo); if (!spec || !spec->ops || !spec->ops->get_maclen) return 0; return spec->ops->get_maclen (algo); } unsigned int _gcry_mac_get_algo_keylen (int algo) { gcry_mac_spec_t *spec; spec = spec_from_algo (algo); if (!spec || !spec->ops || !spec->ops->get_keylen) return 0; return spec->ops->get_keylen (algo); } gcry_err_code_t _gcry_mac_ctl (gcry_mac_hd_t hd, int cmd, void *buffer, size_t buflen) { gcry_err_code_t rc; /* Currently not used. */ (void) hd; (void) buffer; (void) buflen; switch (cmd) { case GCRYCTL_RESET: rc = mac_reset (hd); break; + case GCRYCTL_SET_SBOX: + if (hd->spec->ops->set_extra_info) + rc = hd->spec->ops->set_extra_info + (hd, GCRYCTL_SET_SBOX, buffer, buflen); + else + rc = GPG_ERR_NOT_SUPPORTED; + break; default: rc = GPG_ERR_INV_OP; } return rc; } /* Return information about the given MAC algorithm ALGO. GCRYCTL_TEST_ALGO: Returns 0 if the specified algorithm ALGO is available for use. BUFFER and NBYTES must be zero. Note: Because this function is in most cases used to return an integer value, we can make it easier for the caller to just look at the return value. The caller will in all cases consult the value and thereby detecting whether a error occurred or not (i.e. while checking the block size) */ gcry_err_code_t _gcry_mac_algo_info (int algo, int what, void *buffer, size_t * nbytes) { gcry_err_code_t rc = 0; unsigned int ui; switch (what) { case GCRYCTL_GET_KEYLEN: if (buffer || (!nbytes)) rc = GPG_ERR_INV_ARG; else { ui = _gcry_mac_get_algo_keylen (algo); if (ui > 0) *nbytes = (size_t) ui; else /* The only reason for an error is an invalid algo. */ rc = GPG_ERR_MAC_ALGO; } break; case GCRYCTL_TEST_ALGO: if (buffer || nbytes) rc = GPG_ERR_INV_ARG; else rc = check_mac_algo (algo); break; default: rc = GPG_ERR_INV_OP; } return rc; }