Line data Source code
1 : /*
2 : * One-key CBC MAC (OMAC1) hash with AES
3 : *
4 : * Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
5 : *
6 : * This software may be distributed under the terms of the BSD license.
7 : * See README for more details.
8 : */
9 :
10 : #include "includes.h"
11 :
12 : #include "common.h"
13 : #include "aes.h"
14 : #include "aes_wrap.h"
15 :
16 29376 : static void gf_mulx(u8 *pad)
17 : {
18 : int i, carry;
19 :
20 29376 : carry = pad[0] & 0x80;
21 470016 : for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22 440640 : pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23 29376 : pad[AES_BLOCK_SIZE - 1] <<= 1;
24 29376 : if (carry)
25 16196 : pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26 29376 : }
27 :
28 :
29 : /**
30 : * omac1_aes_vector - One-Key CBC MAC (OMAC1) hash with AES
31 : * @key: Key for the hash operation
32 : * @key_len: Key length in octets
33 : * @num_elem: Number of elements in the data vector
34 : * @addr: Pointers to the data areas
35 : * @len: Lengths of the data blocks
36 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
37 : * Returns: 0 on success, -1 on failure
38 : *
39 : * This is a mode for using block cipher (AES in this case) for authentication.
40 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
41 : * (SP) 800-38B.
42 : */
43 15277 : int omac1_aes_vector(const u8 *key, size_t key_len, size_t num_elem,
44 : const u8 *addr[], const size_t *len, u8 *mac)
45 : {
46 : void *ctx;
47 : u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE];
48 : const u8 *pos, *end;
49 : size_t i, e, left, total_len;
50 :
51 15277 : if (TEST_FAIL())
52 17 : return -1;
53 :
54 15260 : ctx = aes_encrypt_init(key, key_len);
55 15260 : if (ctx == NULL)
56 5 : return -1;
57 15255 : os_memset(cbc, 0, AES_BLOCK_SIZE);
58 :
59 15255 : total_len = 0;
60 44969 : for (e = 0; e < num_elem; e++)
61 29714 : total_len += len[e];
62 15255 : left = total_len;
63 :
64 15255 : e = 0;
65 15255 : pos = addr[0];
66 15255 : end = pos + len[0];
67 :
68 105272 : while (left >= AES_BLOCK_SIZE) {
69 1269820 : for (i = 0; i < AES_BLOCK_SIZE; i++) {
70 1196192 : cbc[i] ^= *pos++;
71 1196192 : if (pos >= end) {
72 : /*
73 : * Stop if there are no more bytes to process
74 : * since there are no more entries in the array.
75 : */
76 15583 : if (i + 1 == AES_BLOCK_SIZE &&
77 : left == AES_BLOCK_SIZE)
78 1134 : break;
79 14449 : e++;
80 14449 : pos = addr[e];
81 14449 : end = pos + len[e];
82 : }
83 : }
84 74762 : if (left > AES_BLOCK_SIZE)
85 73628 : aes_encrypt(ctx, cbc, cbc);
86 74762 : left -= AES_BLOCK_SIZE;
87 : }
88 :
89 15255 : os_memset(pad, 0, AES_BLOCK_SIZE);
90 15255 : aes_encrypt(ctx, pad, pad);
91 15255 : gf_mulx(pad);
92 :
93 15255 : if (left || total_len == 0) {
94 101360 : for (i = 0; i < left; i++) {
95 101359 : cbc[i] ^= *pos++;
96 101359 : if (pos >= end) {
97 : /*
98 : * Stop if there are no more bytes to process
99 : * since there are no more entries in the array.
100 : */
101 14130 : if (i + 1 == left)
102 14120 : break;
103 10 : e++;
104 10 : pos = addr[e];
105 10 : end = pos + len[e];
106 : }
107 : }
108 14121 : cbc[left] ^= 0x80;
109 14121 : gf_mulx(pad);
110 : }
111 :
112 259335 : for (i = 0; i < AES_BLOCK_SIZE; i++)
113 244080 : pad[i] ^= cbc[i];
114 15255 : aes_encrypt(ctx, pad, mac);
115 15255 : aes_encrypt_deinit(ctx);
116 15255 : return 0;
117 : }
118 :
119 :
120 : /**
121 : * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
122 : * @key: 128-bit key for the hash operation
123 : * @num_elem: Number of elements in the data vector
124 : * @addr: Pointers to the data areas
125 : * @len: Lengths of the data blocks
126 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
127 : * Returns: 0 on success, -1 on failure
128 : *
129 : * This is a mode for using block cipher (AES in this case) for authentication.
130 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
131 : * (SP) 800-38B.
132 : */
133 15277 : int omac1_aes_128_vector(const u8 *key, size_t num_elem,
134 : const u8 *addr[], const size_t *len, u8 *mac)
135 : {
136 15277 : return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
137 : }
138 :
139 :
140 : /**
141 : * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
142 : * @key: 128-bit key for the hash operation
143 : * @data: Data buffer for which a MAC is determined
144 : * @data_len: Length of data buffer in bytes
145 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
146 : * Returns: 0 on success, -1 on failure
147 : *
148 : * This is a mode for using block cipher (AES in this case) for authentication.
149 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
150 : * (SP) 800-38B.
151 : */
152 6280 : int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
153 : {
154 6280 : return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
155 : }
156 :
157 :
158 : /**
159 : * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
160 : * @key: 256-bit key for the hash operation
161 : * @data: Data buffer for which a MAC is determined
162 : * @data_len: Length of data buffer in bytes
163 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
164 : * Returns: 0 on success, -1 on failure
165 : *
166 : * This is a mode for using block cipher (AES in this case) for authentication.
167 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
168 : * (SP) 800-38B.
169 : */
170 0 : int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
171 : {
172 0 : return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
173 : }
|