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 20257 : static void gf_mulx(u8 *pad)
17 : {
18 : int i, carry;
19 :
20 20257 : carry = pad[0] & 0x80;
21 324112 : for (i = 0; i < AES_BLOCK_SIZE - 1; i++)
22 303855 : pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7);
23 20257 : pad[AES_BLOCK_SIZE - 1] <<= 1;
24 20257 : if (carry)
25 11300 : pad[AES_BLOCK_SIZE - 1] ^= 0x87;
26 20257 : }
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 10248 : 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 10248 : ctx = aes_encrypt_init(key, key_len);
52 10248 : if (ctx == NULL)
53 0 : return -1;
54 10248 : os_memset(cbc, 0, AES_BLOCK_SIZE);
55 :
56 10248 : total_len = 0;
57 27077 : for (e = 0; e < num_elem; e++)
58 16829 : total_len += len[e];
59 10248 : left = total_len;
60 :
61 10248 : e = 0;
62 10248 : pos = addr[0];
63 10248 : end = pos + len[0];
64 :
65 76636 : while (left >= AES_BLOCK_SIZE) {
66 954141 : for (i = 0; i < AES_BLOCK_SIZE; i++) {
67 898240 : cbc[i] ^= *pos++;
68 898240 : 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 6810 : if (i + 1 == AES_BLOCK_SIZE &&
74 : left == AES_BLOCK_SIZE)
75 239 : break;
76 6571 : e++;
77 6571 : pos = addr[e];
78 6571 : end = pos + len[e];
79 : }
80 : }
81 56140 : if (left > AES_BLOCK_SIZE)
82 55901 : aes_encrypt(ctx, cbc, cbc);
83 56140 : left -= AES_BLOCK_SIZE;
84 : }
85 :
86 10248 : os_memset(pad, 0, AES_BLOCK_SIZE);
87 10248 : aes_encrypt(ctx, pad, pad);
88 10248 : gf_mulx(pad);
89 :
90 10248 : if (left || total_len == 0) {
91 71893 : for (i = 0; i < left; i++) {
92 71892 : cbc[i] ^= *pos++;
93 71892 : 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 10018 : if (i + 1 == left)
99 10008 : break;
100 10 : e++;
101 10 : pos = addr[e];
102 10 : end = pos + len[e];
103 : }
104 : }
105 10009 : cbc[left] ^= 0x80;
106 10009 : gf_mulx(pad);
107 : }
108 :
109 174216 : for (i = 0; i < AES_BLOCK_SIZE; i++)
110 163968 : pad[i] ^= cbc[i];
111 10248 : aes_encrypt(ctx, pad, mac);
112 10248 : aes_encrypt_deinit(ctx);
113 10248 : 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 10248 : int omac1_aes_128_vector(const u8 *key, size_t num_elem,
131 : const u8 *addr[], const size_t *len, u8 *mac)
132 : {
133 10248 : 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 3674 : int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac)
150 : {
151 3674 : 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 : }
|