xref: /freebsd/contrib/wpa/src/crypto/aes-omac1.c (revision 780fb4a2)
1e28a4053SRui Paulo /*
25b9c547cSRui Paulo  * One-key CBC MAC (OMAC1) hash with AES
3e28a4053SRui Paulo  *
4e28a4053SRui Paulo  * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
5e28a4053SRui Paulo  *
6f05cddf9SRui Paulo  * This software may be distributed under the terms of the BSD license.
7f05cddf9SRui Paulo  * See README for more details.
8e28a4053SRui Paulo  */
9e28a4053SRui Paulo 
10e28a4053SRui Paulo #include "includes.h"
11e28a4053SRui Paulo 
12e28a4053SRui Paulo #include "common.h"
13e28a4053SRui Paulo #include "aes.h"
14e28a4053SRui Paulo #include "aes_wrap.h"
15e28a4053SRui Paulo 
gf_mulx(u8 * pad)16e28a4053SRui Paulo static void gf_mulx(u8 *pad)
17e28a4053SRui Paulo {
18e28a4053SRui Paulo 	int i, carry;
19e28a4053SRui Paulo 
20e28a4053SRui Paulo 	carry = pad[0] & 0x80;
21e28a4053SRui Paulo 	for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22e28a4053SRui Paulo 		pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23e28a4053SRui Paulo 	pad[AES_BLOCK_SIZE - 1] <<= 1;
24e28a4053SRui Paulo 	if (carry)
25e28a4053SRui Paulo 		pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26e28a4053SRui Paulo }
27e28a4053SRui Paulo 
28e28a4053SRui Paulo 
29e28a4053SRui Paulo /**
305b9c547cSRui Paulo  * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
315b9c547cSRui Paulo  * @key: Key for the hash operation
325b9c547cSRui Paulo  * @key_len: Key length in octets
33e28a4053SRui Paulo  * @num_elem: Number of elements in the data vector
34e28a4053SRui Paulo  * @addr: Pointers to the data areas
35e28a4053SRui Paulo  * @len: Lengths of the data blocks
36e28a4053SRui Paulo  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
37e28a4053SRui Paulo  * Returns: 0 on success, -1 on failure
38e28a4053SRui Paulo  *
39e28a4053SRui Paulo  * This is a mode for using block cipher (AES in this case) for authentication.
40e28a4053SRui Paulo  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
41e28a4053SRui Paulo  * (SP) 800-38B.
42e28a4053SRui Paulo  */
omac1_aes_vector(const u8 * key,size_t key_len,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)435b9c547cSRui Paulo int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
44e28a4053SRui Paulo 		     const u8 *addr[], const size_t *len, u8 *mac)
45e28a4053SRui Paulo {
46e28a4053SRui Paulo 	void *ctx;
47e28a4053SRui Paulo 	u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
48e28a4053SRui Paulo 	const u8 *pos, *end;
49e28a4053SRui Paulo 	size_t i, e, left, total_len;
50e28a4053SRui Paulo 
51*780fb4a2SCy Schubert 	if (TEST_FAIL())
52*780fb4a2SCy Schubert 		return -1;
53*780fb4a2SCy Schubert 
545b9c547cSRui Paulo 	ctx = aes_encrypt_init(key, key_len);
55e28a4053SRui Paulo 	if (ctx == NULL)
56e28a4053SRui Paulo 		return -1;
57e28a4053SRui Paulo 	os_memset(cbc, 0, AES_BLOCK_SIZE);
58e28a4053SRui Paulo 
59e28a4053SRui Paulo 	total_len = 0;
60e28a4053SRui Paulo 	for (e = 0; e < num_elem; e++)
61e28a4053SRui Paulo 		total_len += len[e];
62e28a4053SRui Paulo 	left = total_len;
63e28a4053SRui Paulo 
64e28a4053SRui Paulo 	e = 0;
65e28a4053SRui Paulo 	pos = addr[0];
66e28a4053SRui Paulo 	end = pos + len[0];
67e28a4053SRui Paulo 
68e28a4053SRui Paulo 	while (left >= AES_BLOCK_SIZE) {
69e28a4053SRui Paulo 		for (i = 0; i < AES_BLOCK_SIZE; i++) {
70e28a4053SRui Paulo 			cbc[i] ^= *pos++;
71e28a4053SRui Paulo 			if (pos >= end) {
725b9c547cSRui Paulo 				/*
735b9c547cSRui Paulo 				 * Stop if there are no more bytes to process
745b9c547cSRui Paulo 				 * since there are no more entries in the array.
755b9c547cSRui Paulo 				 */
765b9c547cSRui Paulo 				if (i + 1 == AES_BLOCK_SIZE &&
775b9c547cSRui Paulo 				    left == AES_BLOCK_SIZE)
785b9c547cSRui Paulo 					break;
79e28a4053SRui Paulo 				e++;
80e28a4053SRui Paulo 				pos = addr[e];
81e28a4053SRui Paulo 				end = pos + len[e];
82e28a4053SRui Paulo 			}
83e28a4053SRui Paulo 		}
84e28a4053SRui Paulo 		if (left > AES_BLOCK_SIZE)
85e28a4053SRui Paulo 			aes_encrypt(ctx, cbc, cbc);
86e28a4053SRui Paulo 		left -= AES_BLOCK_SIZE;
87e28a4053SRui Paulo 	}
88e28a4053SRui Paulo 
89e28a4053SRui Paulo 	os_memset(pad, 0, AES_BLOCK_SIZE);
90e28a4053SRui Paulo 	aes_encrypt(ctx, pad, pad);
91e28a4053SRui Paulo 	gf_mulx(pad);
92e28a4053SRui Paulo 
93e28a4053SRui Paulo 	if (left || total_len == 0) {
94e28a4053SRui Paulo 		for (i = 0; i < left; i++) {
95e28a4053SRui Paulo 			cbc[i] ^= *pos++;
96e28a4053SRui Paulo 			if (pos >= end) {
975b9c547cSRui Paulo 				/*
985b9c547cSRui Paulo 				 * Stop if there are no more bytes to process
995b9c547cSRui Paulo 				 * since there are no more entries in the array.
1005b9c547cSRui Paulo 				 */
1015b9c547cSRui Paulo 				if (i + 1 == left)
1025b9c547cSRui Paulo 					break;
103e28a4053SRui Paulo 				e++;
104e28a4053SRui Paulo 				pos = addr[e];
105e28a4053SRui Paulo 				end = pos + len[e];
106e28a4053SRui Paulo 			}
107e28a4053SRui Paulo 		}
108e28a4053SRui Paulo 		cbc[left] ^= 0x80;
109e28a4053SRui Paulo 		gf_mulx(pad);
110e28a4053SRui Paulo 	}
111e28a4053SRui Paulo 
112e28a4053SRui Paulo 	for (i = 0; i < AES_BLOCK_SIZE; i++)
113e28a4053SRui Paulo 		pad[i] ^= cbc[i];
114e28a4053SRui Paulo 	aes_encrypt(ctx, pad, mac);
115e28a4053SRui Paulo 	aes_encrypt_deinit(ctx);
116e28a4053SRui Paulo 	return 0;
117e28a4053SRui Paulo }
118e28a4053SRui Paulo 
119e28a4053SRui Paulo 
120e28a4053SRui Paulo /**
1215b9c547cSRui Paulo  * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
1225b9c547cSRui Paulo  * @key: 128-bit key for the hash operation
1235b9c547cSRui Paulo  * @num_elem: Number of elements in the data vector
1245b9c547cSRui Paulo  * @addr: Pointers to the data areas
1255b9c547cSRui Paulo  * @len: Lengths of the data blocks
1265b9c547cSRui Paulo  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
1275b9c547cSRui Paulo  * Returns: 0 on success, -1 on failure
1285b9c547cSRui Paulo  *
1295b9c547cSRui Paulo  * This is a mode for using block cipher (AES in this case) for authentication.
1305b9c547cSRui Paulo  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
1315b9c547cSRui Paulo  * (SP) 800-38B.
1325b9c547cSRui Paulo  */
omac1_aes_128_vector(const u8 * key,size_t num_elem,const u8 * addr[],const size_t * len,u8 * mac)1335b9c547cSRui Paulo int omac1_aes_128_vector(const u8 *key, size_t num_elem,
1345b9c547cSRui Paulo 			 const u8 *addr[], const size_t *len, u8 *mac)
1355b9c547cSRui Paulo {
1365b9c547cSRui Paulo 	return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
1375b9c547cSRui Paulo }
1385b9c547cSRui Paulo 
1395b9c547cSRui Paulo 
1405b9c547cSRui Paulo /**
141e28a4053SRui Paulo  * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
142e28a4053SRui Paulo  * @key: 128-bit key for the hash operation
143e28a4053SRui Paulo  * @data: Data buffer for which a MAC is determined
144e28a4053SRui Paulo  * @data_len: Length of data buffer in bytes
145e28a4053SRui Paulo  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
146e28a4053SRui Paulo  * Returns: 0 on success, -1 on failure
147e28a4053SRui Paulo  *
148e28a4053SRui Paulo  * This is a mode for using block cipher (AES in this case) for authentication.
149e28a4053SRui Paulo  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
150e28a4053SRui Paulo  * (SP) 800-38B.
151e28a4053SRui Paulo  */
omac1_aes_128(const u8 * key,const u8 * data,size_t data_len,u8 * mac)152e28a4053SRui Paulo int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
153e28a4053SRui Paulo {
154e28a4053SRui Paulo 	return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
155e28a4053SRui Paulo }
1565b9c547cSRui Paulo 
1575b9c547cSRui Paulo 
1585b9c547cSRui Paulo /**
1595b9c547cSRui Paulo  * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
1605b9c547cSRui Paulo  * @key: 256-bit key for the hash operation
1615b9c547cSRui Paulo  * @data: Data buffer for which a MAC is determined
1625b9c547cSRui Paulo  * @data_len: Length of data buffer in bytes
1635b9c547cSRui Paulo  * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
1645b9c547cSRui Paulo  * Returns: 0 on success, -1 on failure
1655b9c547cSRui Paulo  *
1665b9c547cSRui Paulo  * This is a mode for using block cipher (AES in this case) for authentication.
1675b9c547cSRui Paulo  * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
1685b9c547cSRui Paulo  * (SP) 800-38B.
1695b9c547cSRui Paulo  */
omac1_aes_256(const u8 * key,const u8 * data,size_t data_len,u8 * mac)1705b9c547cSRui Paulo int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
1715b9c547cSRui Paulo {
1725b9c547cSRui Paulo 	return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
1735b9c547cSRui Paulo }
174