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