From 30bff1d0f43799835e12276866450786bbf594e1 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Fri, 23 Jan 2015 16:59:33 +0200 Subject: [PATCH] Extend AES-CMAC routines to support 256-bit keys omac1_aes_256() and omac1_aes_vector() can now be used to perform 256-bit CMAC operations similarly to the previously supported 128-bit cases. Signed-off-by: Jouni Malinen --- src/crypto/aes-omac1.c | 51 ++++++++++++++++++++++++++++++++----- src/crypto/aes_wrap.h | 7 ++++- src/crypto/crypto_openssl.c | 26 ++++++++++++++++--- 3 files changed, 74 insertions(+), 10 deletions(-) diff --git a/src/crypto/aes-omac1.c b/src/crypto/aes-omac1.c index c2b06867e..375db5735 100644 --- a/src/crypto/aes-omac1.c +++ b/src/crypto/aes-omac1.c @@ -1,5 +1,5 @@ /* - * One-key CBC MAC (OMAC1) hash with AES-128 + * One-key CBC MAC (OMAC1) hash with AES * * Copyright (c) 2003-2007, Jouni Malinen * @@ -27,8 +27,9 @@ static void gf_mulx(u8 *pad) /** - * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 - * @key: 128-bit key for the hash operation + * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES + * @key: Key for the hash operation + * @key_len: Key length in octets * @num_elem: Number of elements in the data vector * @addr: Pointers to the data areas * @len: Lengths of the data blocks @@ -39,15 +40,15 @@ static void gf_mulx(u8 *pad) * OMAC1 was standardized with the name CMAC by NIST in a Special Publication * (SP) 800-38B. */ -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) +int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) { void *ctx; u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; const u8 *pos, *end; size_t i, e, left, total_len; - ctx = aes_encrypt_init(key, 16); + ctx = aes_encrypt_init(key, key_len); if (ctx == NULL) return -1; os_memset(cbc, 0, AES_BLOCK_SIZE); @@ -113,6 +114,26 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem, } +/** + * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128 + * @key: 128-bit key for the hash operation + * @num_elem: Number of elements in the data vector + * @addr: Pointers to the data areas + * @len: Lengths of the data blocks + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); +} + + /** * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC) * @key: 128-bit key for the hash operation @@ -129,3 +150,21 @@ int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } + + +/** + * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC) + * @key: 256-bit key for the hash operation + * @data: Data buffer for which a MAC is determined + * @data_len: Length of data buffer in bytes + * @mac: Buffer for MAC (128 bits, i.e., 16 bytes) + * Returns: 0 on success, -1 on failure + * + * This is a mode for using block cipher (AES in this case) for authentication. + * OMAC1 was standardized with the name CMAC by NIST in a Special Publication + * (SP) 800-38B. + */ +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); +} diff --git a/src/crypto/aes_wrap.h b/src/crypto/aes_wrap.h index 6b3727c79..4a142093b 100644 --- a/src/crypto/aes_wrap.h +++ b/src/crypto/aes_wrap.h @@ -2,7 +2,7 @@ * AES-based functions * * - AES Key Wrap Algorithm (RFC3394) - * - One-Key CBC MAC (OMAC1) hash with AES-128 + * - One-Key CBC MAC (OMAC1) hash with AES-128 and AES-256 * - AES-128 CTR mode encryption * - AES-128 EAX mode encryption/decryption * - AES-128 CBC @@ -22,11 +22,16 @@ int __must_check aes_wrap(const u8 *kek, size_t kek_len, int n, const u8 *plain, u8 *cipher); int __must_check aes_unwrap(const u8 *kek, size_t kek_len, int n, const u8 *cipher, u8 *plain); +int __must_check omac1_aes_vector(const u8 *key, size_t key_len, + size_t num_elem, const u8 *addr[], + const size_t *len, u8 *mac); int __must_check omac1_aes_128_vector(const u8 *key, size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac); int __must_check omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac); +int __must_check omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, + u8 *mac); int __must_check aes_128_encrypt_block(const u8 *key, const u8 *in, u8 *out); int __must_check aes_128_ctr_encrypt(const u8 *key, const u8 *nonce, u8 *data, size_t data_len); diff --git a/src/crypto/crypto_openssl.c b/src/crypto/crypto_openssl.c index adb42a45f..8b2947236 100644 --- a/src/crypto/crypto_openssl.c +++ b/src/crypto/crypto_openssl.c @@ -795,8 +795,8 @@ int crypto_get_random(void *buf, size_t len) #ifdef CONFIG_OPENSSL_CMAC -int omac1_aes_128_vector(const u8 *key, size_t num_elem, - const u8 *addr[], const size_t *len, u8 *mac) +int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) { CMAC_CTX *ctx; int ret = -1; @@ -806,8 +806,15 @@ int omac1_aes_128_vector(const u8 *key, size_t num_elem, if (ctx == NULL) return -1; - if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL)) + if (key_len == 32) { + if (!CMAC_Init(ctx, key, 32, EVP_aes_256_cbc(), NULL)) + goto fail; + } else if (key_len == 16) { + if (!CMAC_Init(ctx, key, 16, EVP_aes_128_cbc(), NULL)) + goto fail; + } else { goto fail; + } for (i = 0; i < num_elem; i++) { if (!CMAC_Update(ctx, addr[i], len[i])) goto fail; @@ -822,10 +829,23 @@ fail: } +int omac1_aes_128_vector(const u8 *key, size_t num_elem, + const u8 *addr[], const size_t *len, u8 *mac) +{ + return omac1_aes_vector(key, 16, num_elem, addr, len, mac); +} + + int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) { return omac1_aes_128_vector(key, 1, &data, &data_len, mac); } + + +int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) +{ + return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); +} #endif /* CONFIG_OPENSSL_CMAC */