/src/hostap/src/crypto/aes-omac1.c
Line | Count | Source (jump to first uncovered line) |
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 | | static void gf_mulx(u8 *pad) |
17 | 12.9k | { |
18 | 12.9k | int i, carry; |
19 | | |
20 | 12.9k | carry = pad[0] & 0x80; |
21 | 206k | for (i = 0; i < AES_BLOCK_SIZE - 1; i++) |
22 | 193k | pad[i] = (pad[i] << 1) | (pad[i + 1] >> 7); |
23 | 12.9k | pad[AES_BLOCK_SIZE - 1] <<= 1; |
24 | 12.9k | if (carry) |
25 | 6.37k | pad[AES_BLOCK_SIZE - 1] ^= 0x87; |
26 | 12.9k | } |
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 | | 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 | 6.47k | { |
46 | 6.47k | void *ctx; |
47 | 6.47k | u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; |
48 | 6.47k | const u8 *pos, *end; |
49 | 6.47k | size_t i, e, left, total_len; |
50 | | |
51 | 6.47k | if (TEST_FAIL()) |
52 | 0 | return -1; |
53 | | |
54 | 6.47k | ctx = aes_encrypt_init(key, key_len); |
55 | 6.47k | if (ctx == NULL) |
56 | 0 | return -1; |
57 | 6.47k | os_memset(cbc, 0, AES_BLOCK_SIZE); |
58 | | |
59 | 6.47k | total_len = 0; |
60 | 12.9k | for (e = 0; e < num_elem; e++) |
61 | 6.47k | total_len += len[e]; |
62 | 6.47k | left = total_len; |
63 | | |
64 | 6.47k | e = 0; |
65 | 6.47k | pos = addr[0]; |
66 | 6.47k | end = pos + len[0]; |
67 | | |
68 | 81.1k | while (left >= AES_BLOCK_SIZE) { |
69 | 1.26M | for (i = 0; i < AES_BLOCK_SIZE; i++) { |
70 | 1.19M | cbc[i] ^= *pos++; |
71 | 1.19M | 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 | 28 | if (i + 1 == AES_BLOCK_SIZE && |
77 | 28 | left == AES_BLOCK_SIZE) |
78 | 28 | break; |
79 | 0 | e++; |
80 | 0 | pos = addr[e]; |
81 | 0 | end = pos + len[e]; |
82 | 0 | } |
83 | 1.19M | } |
84 | 74.6k | if (left > AES_BLOCK_SIZE) |
85 | 74.6k | aes_encrypt(ctx, cbc, cbc); |
86 | 74.6k | left -= AES_BLOCK_SIZE; |
87 | 74.6k | } |
88 | | |
89 | 6.47k | os_memset(pad, 0, AES_BLOCK_SIZE); |
90 | 6.47k | aes_encrypt(ctx, pad, pad); |
91 | 6.47k | gf_mulx(pad); |
92 | | |
93 | 6.47k | if (left || total_len == 0) { |
94 | 55.8k | for (i = 0; i < left; i++) { |
95 | 55.8k | cbc[i] ^= *pos++; |
96 | 55.8k | 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 | 6.44k | if (i + 1 == left) |
102 | 6.44k | break; |
103 | 0 | e++; |
104 | 0 | pos = addr[e]; |
105 | 0 | end = pos + len[e]; |
106 | 0 | } |
107 | 55.8k | } |
108 | 6.44k | cbc[left] ^= 0x80; |
109 | 6.44k | gf_mulx(pad); |
110 | 6.44k | } |
111 | | |
112 | 110k | for (i = 0; i < AES_BLOCK_SIZE; i++) |
113 | 103k | pad[i] ^= cbc[i]; |
114 | 6.47k | aes_encrypt(ctx, pad, mac); |
115 | 6.47k | aes_encrypt_deinit(ctx); |
116 | 6.47k | return 0; |
117 | 6.47k | } |
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 | | int omac1_aes_128_vector(const u8 *key, size_t num_elem, |
134 | | const u8 *addr[], const size_t *len, u8 *mac) |
135 | 6.47k | { |
136 | 6.47k | return omac1_aes_vector(key, 16, num_elem, addr, len, mac); |
137 | 6.47k | } |
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 | | int omac1_aes_128(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
153 | 6.47k | { |
154 | 6.47k | return omac1_aes_128_vector(key, 1, &data, &data_len, mac); |
155 | 6.47k | } |
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 | | int omac1_aes_256(const u8 *key, const u8 *data, size_t data_len, u8 *mac) |
171 | 0 | { |
172 | 0 | return omac1_aes_vector(key, 32, 1, &data, &data_len, mac); |
173 | 0 | } |