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 22680 : static void gf_mulx(u8 *pad)
17 : {
18 : int i, carry;
19 :
20 22680 : carry = pad[0] & 0x80;
21 362880 : for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22 340200 : pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23 22680 : pad[AES_BLOCK_SIZE - 1] <<= 1;
24 22680 : if (carry)
25 12602 : pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26 22680 : }
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 11595 : 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 11595 : ctx = aes_encrypt_init(key, key_len);
52 11595 : if (ctx == NULL)
53 8 : return -1;
54 11587 : os_memset(cbc, 0, AES_BLOCK_SIZE);
55 :
56 11587 : total_len = 0;
57 36421 : for (e = 0; e < num_elem; e++)
58 24834 : total_len += len[e];
59 11587 : left = total_len;
60 :
61 11587 : e = 0;
62 11587 : pos = addr[0];
63 11587 : end = pos + len[0];
64 :
65 85001 : while (left >= AES_BLOCK_SIZE) {
66 1050565 : for (i = 0; i < AES_BLOCK_SIZE; i++) {
67 989232 : cbc[i] ^= *pos++;
68 989232 : if (pos >= end) {
69 : /*
70 : * Stop if there are no more bytes to process
71 : * since there are no more entries in the array.
72 : */
73 13731 : if (i + 1 == AES_BLOCK_SIZE &&
74 : left == AES_BLOCK_SIZE)
75 494 : break;
76 13237 : e++;
77 13237 : pos = addr[e];
78 13237 : end = pos + len[e];
79 : }
80 : }
81 61827 : if (left > AES_BLOCK_SIZE)
82 61333 : aes_encrypt(ctx, cbc, cbc);
83 61827 : left -= AES_BLOCK_SIZE;
84 : }
85 :
86 11587 : os_memset(pad, 0, AES_BLOCK_SIZE);
87 11587 : aes_encrypt(ctx, pad, pad);
88 11587 : gf_mulx(pad);
89 :
90 11587 : if (left || total_len == 0) {
91 79540 : for (i = 0; i < left; i++) {
92 79539 : cbc[i] ^= *pos++;
93 79539 : if (pos >= end) {
94 : /*
95 : * Stop if there are no more bytes to process
96 : * since there are no more entries in the array.
97 : */
98 11102 : if (i + 1 == left)
99 11092 : break;
100 10 : e++;
101 10 : pos = addr[e];
102 10 : end = pos + len[e];
103 : }
104 : }
105 11093 : cbc[left] ^= 0x80;
106 11093 : gf_mulx(pad);
107 : }
108 :
109 196979 : for (i = 0; i < AES_BLOCK_SIZE; i++)
110 185392 : pad[i] ^= cbc[i];
111 11587 : aes_encrypt(ctx, pad, mac);
112 11587 : aes_encrypt_deinit(ctx);
113 11587 : return 0;
114 : }
115 :
116 :
117 : /**
118 : * omac1_aes_128_vector - One-Key CBC MAC (OMAC1) hash with AES-128
119 : * @key: 128-bit key for the hash operation
120 : * @num_elem: Number of elements in the data vector
121 : * @addr: Pointers to the data areas
122 : * @len: Lengths of the data blocks
123 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
124 : * Returns: 0 on success, -1 on failure
125 : *
126 : * This is a mode for using block cipher (AES in this case) for authentication.
127 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
128 : * (SP) 800-38B.
129 : */
130 11595 : int omac1_aes_128_vector(const u8 *key, size_t num_elem,
131 : const u8 *addr[], const size_t *len, u8 *mac)
132 : {
133 11595 : return omac1_aes_vector(key, 16, num_elem, addr, len, mac);
134 : }
135 :
136 :
137 : /**
138 : * omac1_aes_128 - One-Key CBC MAC (OMAC1) hash with AES-128 (aka AES-CMAC)
139 : * @key: 128-bit key for the hash operation
140 : * @data: Data buffer for which a MAC is determined
141 : * @data_len: Length of data buffer in bytes
142 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
143 : * Returns: 0 on success, -1 on failure
144 : *
145 : * This is a mode for using block cipher (AES in this case) for authentication.
146 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
147 : * (SP) 800-38B.
148 : */
149 3718 : int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
150 : {
151 3718 : return omac1_aes_128_vector(key, 1, &data, &data_len, mac);
152 : }
153 :
154 :
155 : /**
156 : * omac1_aes_256 - One-Key CBC MAC (OMAC1) hash with AES-256 (aka AES-CMAC)
157 : * @key: 256-bit key for the hash operation
158 : * @data: Data buffer for which a MAC is determined
159 : * @data_len: Length of data buffer in bytes
160 : * @mac: Buffer for MAC (128 bits, i.e., 16 bytes)
161 : * Returns: 0 on success, -1 on failure
162 : *
163 : * This is a mode for using block cipher (AES in this case) for authentication.
164 : * OMAC1 was standardized with the name CMAC by NIST in a Special Publication
165 : * (SP) 800-38B.
166 : */
167 0 : int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
168 : {
169 0 : return omac1_aes_vector(key, 32, 1, &data, &data_len, mac);
170 : }
|