/src/nss-nspr/nss/lib/freebl/cmac.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
2 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
3 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
4 | | |
5 | | #ifdef FREEBL_NO_DEPEND |
6 | | #include "stubs.h" |
7 | | #endif |
8 | | |
9 | | #include "rijndael.h" |
10 | | #include "blapi.h" |
11 | | #include "cmac.h" |
12 | | #include "secerr.h" |
13 | | #include "nspr.h" |
14 | | |
15 | | struct CMACContextStr { |
16 | | /* Information about the block cipher to use internally. The cipher should |
17 | | * be placed in ECB mode so that we can use it to directly encrypt blocks. |
18 | | * |
19 | | * |
20 | | * To add a new cipher, add an entry to CMACCipher, update CMAC_Init, |
21 | | * cmac_Encrypt, and CMAC_Destroy methods to handle the new cipher, and |
22 | | * add a new Context pointer to the cipher union with the correct type. */ |
23 | | CMACCipher cipherType; |
24 | | union { |
25 | | AESContext *aes; |
26 | | } cipher; |
27 | | unsigned int blockSize; |
28 | | |
29 | | /* Internal keys which are conditionally used by the algorithm. Derived |
30 | | * from encrypting the NULL block. We leave the storing of (and the |
31 | | * cleanup of) the CMAC key to the underlying block cipher. */ |
32 | | unsigned char k1[MAX_BLOCK_SIZE]; |
33 | | unsigned char k2[MAX_BLOCK_SIZE]; |
34 | | |
35 | | /* When Update is called with data which isn't a multiple of the block |
36 | | * size, we need a place to put it. HMAC handles this by passing it to |
37 | | * the underlying hash function right away; we can't do that as the |
38 | | * contract on the cipher object is different. */ |
39 | | unsigned int partialIndex; |
40 | | unsigned char partialBlock[MAX_BLOCK_SIZE]; |
41 | | |
42 | | /* Last encrypted block. This gets xor-ed with partialBlock prior to |
43 | | * encrypting it. NIST defines this to be the empty string to begin. */ |
44 | | unsigned char lastBlock[MAX_BLOCK_SIZE]; |
45 | | }; |
46 | | |
47 | | static void |
48 | | cmac_ShiftLeftOne(unsigned char *out, const unsigned char *in, int length) |
49 | 2 | { |
50 | 2 | int i = 0; |
51 | 32 | for (; i < length - 1; i++) { |
52 | 30 | out[i] = in[i] << 1; |
53 | 30 | out[i] |= in[i + 1] >> 7; |
54 | 30 | } |
55 | 2 | out[i] = in[i] << 1; |
56 | 2 | } |
57 | | |
58 | | static SECStatus |
59 | | cmac_Encrypt(CMACContext *ctx, unsigned char *output, |
60 | | const unsigned char *input, |
61 | | unsigned int inputLen) |
62 | 757 | { |
63 | 757 | if (ctx->cipherType == CMAC_AES) { |
64 | 757 | unsigned int tmpOutputLen; |
65 | 757 | SECStatus rv = AES_Encrypt(ctx->cipher.aes, output, &tmpOutputLen, |
66 | 757 | ctx->blockSize, input, inputLen); |
67 | | |
68 | | /* Assumption: AES_Encrypt (when in ECB mode) always returns an |
69 | | * output of length equal to blockSize (what was pass as the value |
70 | | * of the maxOutputLen parameter). */ |
71 | 757 | PORT_Assert(tmpOutputLen == ctx->blockSize); |
72 | 757 | return rv; |
73 | 757 | } |
74 | | |
75 | 0 | return SECFailure; |
76 | 757 | } |
77 | | |
78 | | /* NIST SP.800-38B, 6.1 Subkey Generation */ |
79 | | static SECStatus |
80 | | cmac_GenerateSubkeys(CMACContext *ctx) |
81 | 1 | { |
82 | 1 | unsigned char null_block[MAX_BLOCK_SIZE] = { 0 }; |
83 | 1 | unsigned char L[MAX_BLOCK_SIZE]; |
84 | 1 | unsigned char v; |
85 | 1 | unsigned char i; |
86 | | |
87 | | /* Step 1: L = AES(key, null_block) */ |
88 | 1 | if (cmac_Encrypt(ctx, L, null_block, ctx->blockSize) != SECSuccess) { |
89 | 0 | return SECFailure; |
90 | 0 | } |
91 | | |
92 | | /* In the following, some effort has been made to be constant time. Rather |
93 | | * than conditioning on the value of the MSB (of L or K1), we use the loop |
94 | | * to build a mask for the conditional constant. */ |
95 | | |
96 | | /* Step 2: If MSB(L) = 0, K1 = L << 1. Else, K1 = (L << 1) ^ R_b. */ |
97 | 1 | cmac_ShiftLeftOne(ctx->k1, L, ctx->blockSize); |
98 | 1 | v = L[0] >> 7; |
99 | 4 | for (i = 1; i <= 7; i <<= 1) { |
100 | 3 | v |= (v << i); |
101 | 3 | } |
102 | 1 | ctx->k1[ctx->blockSize - 1] ^= (0x87 & v); |
103 | | |
104 | | /* Step 3: If MSB(K1) = 0, K2 = K1 << 1. Else, K2 = (K1 <, 1) ^ R_b. */ |
105 | 1 | cmac_ShiftLeftOne(ctx->k2, ctx->k1, ctx->blockSize); |
106 | 1 | v = ctx->k1[0] >> 7; |
107 | 4 | for (i = 1; i <= 7; i <<= 1) { |
108 | 3 | v |= (v << i); |
109 | 3 | } |
110 | 1 | ctx->k2[ctx->blockSize - 1] ^= (0x87 & v); |
111 | | |
112 | | /* Any intermediate value in the computation of the subkey shall be |
113 | | * secret. */ |
114 | 1 | PORT_Memset(null_block, 0, MAX_BLOCK_SIZE); |
115 | 1 | PORT_Memset(L, 0, MAX_BLOCK_SIZE); |
116 | | |
117 | | /* Step 4: Return the values. */ |
118 | 1 | return SECSuccess; |
119 | 1 | } |
120 | | |
121 | | /* NIST SP.800-38B, 6.2 MAC Generation step 6 */ |
122 | | static SECStatus |
123 | | cmac_UpdateState(CMACContext *ctx) |
124 | 756 | { |
125 | 756 | if (ctx == NULL || ctx->partialIndex != ctx->blockSize) { |
126 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
127 | 0 | return SECFailure; |
128 | 0 | } |
129 | | |
130 | | /* Step 6: C_i = CIPHER(key, C_{i-1} ^ M_i) for 1 <= i <= n, and |
131 | | * C_0 is defined as the empty string. */ |
132 | | |
133 | 12.8k | for (unsigned int index = 0; index < ctx->blockSize; index++) { |
134 | 12.0k | ctx->partialBlock[index] ^= ctx->lastBlock[index]; |
135 | 12.0k | } |
136 | | |
137 | 756 | return cmac_Encrypt(ctx, ctx->lastBlock, ctx->partialBlock, ctx->blockSize); |
138 | 756 | } |
139 | | |
140 | | SECStatus |
141 | | CMAC_Init(CMACContext *ctx, CMACCipher type, |
142 | | const unsigned char *key, unsigned int key_len) |
143 | 1 | { |
144 | 1 | if (ctx == NULL) { |
145 | 0 | PORT_SetError(SEC_ERROR_NO_MEMORY); |
146 | 0 | return SECFailure; |
147 | 0 | } |
148 | | |
149 | | /* We only currently support AES-CMAC. */ |
150 | 1 | if (type != CMAC_AES) { |
151 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
152 | 0 | return SECFailure; |
153 | 0 | } |
154 | | |
155 | 1 | PORT_Memset(ctx, 0, sizeof(*ctx)); |
156 | | |
157 | 1 | ctx->blockSize = AES_BLOCK_SIZE; |
158 | 1 | ctx->cipherType = CMAC_AES; |
159 | 1 | ctx->cipher.aes = AES_CreateContext(key, NULL, NSS_AES, 1, key_len, |
160 | 1 | ctx->blockSize); |
161 | 1 | if (ctx->cipher.aes == NULL) { |
162 | 0 | return SECFailure; |
163 | 0 | } |
164 | | |
165 | 1 | return CMAC_Begin(ctx); |
166 | 1 | } |
167 | | |
168 | | CMACContext * |
169 | | CMAC_Create(CMACCipher type, const unsigned char *key, |
170 | | unsigned int key_len) |
171 | 1 | { |
172 | 1 | CMACContext *result = PORT_New(CMACContext); |
173 | | |
174 | 1 | if (CMAC_Init(result, type, key, key_len) != SECSuccess) { |
175 | 0 | CMAC_Destroy(result, PR_TRUE); |
176 | 0 | return NULL; |
177 | 0 | } |
178 | | |
179 | 1 | return result; |
180 | 1 | } |
181 | | |
182 | | SECStatus |
183 | | CMAC_Begin(CMACContext *ctx) |
184 | 1 | { |
185 | 1 | if (ctx == NULL) { |
186 | 0 | return SECFailure; |
187 | 0 | } |
188 | | |
189 | | /* Ensure that our blockSize is less than the maximum. When this fails, |
190 | | * a cipher with a larger block size was added and MAX_BLOCK_SIZE needs |
191 | | * to be updated accordingly. */ |
192 | 1 | PORT_Assert(ctx->blockSize <= MAX_BLOCK_SIZE); |
193 | | |
194 | 1 | if (cmac_GenerateSubkeys(ctx) != SECSuccess) { |
195 | 0 | return SECFailure; |
196 | 0 | } |
197 | | |
198 | | /* Set the index to write partial blocks at to zero. This saves us from |
199 | | * having to clear ctx->partialBlock. */ |
200 | 1 | ctx->partialIndex = 0; |
201 | | |
202 | | /* Step 5: Let C_0 = 0^b. */ |
203 | 1 | PORT_Memset(ctx->lastBlock, 0, ctx->blockSize); |
204 | | |
205 | 1 | return SECSuccess; |
206 | 1 | } |
207 | | |
208 | | /* NIST SP.800-38B, 6.2 MAC Generation */ |
209 | | SECStatus |
210 | | CMAC_Update(CMACContext *ctx, const unsigned char *data, |
211 | | unsigned int data_len) |
212 | 1 | { |
213 | 1 | unsigned int data_index = 0; |
214 | 1 | if (ctx == NULL) { |
215 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
216 | 0 | return SECFailure; |
217 | 0 | } |
218 | | |
219 | 1 | if (data == NULL || data_len == 0) { |
220 | 0 | return SECSuccess; |
221 | 0 | } |
222 | | |
223 | | /* Copy as many bytes from data into ctx->partialBlock as we can, up to |
224 | | * the maximum of the remaining data and the remaining space in |
225 | | * ctx->partialBlock. |
226 | | * |
227 | | * Note that we swap the order (encrypt *then* copy) because the last |
228 | | * block is different from the rest. If we end on an even multiple of |
229 | | * the block size, we have to be able to XOR it with K1. But we won't know |
230 | | * that it is the last until CMAC_Finish is called (and by then, CMAC_Update |
231 | | * has already returned). */ |
232 | 757 | while (data_index < data_len) { |
233 | 756 | if (ctx->partialIndex == ctx->blockSize) { |
234 | 755 | if (cmac_UpdateState(ctx) != SECSuccess) { |
235 | 0 | return SECFailure; |
236 | 0 | } |
237 | | |
238 | 755 | ctx->partialIndex = 0; |
239 | 755 | } |
240 | | |
241 | 756 | unsigned int copy_len = data_len - data_index; |
242 | 756 | if (copy_len > (ctx->blockSize - ctx->partialIndex)) { |
243 | 755 | copy_len = ctx->blockSize - ctx->partialIndex; |
244 | 755 | } |
245 | | |
246 | 756 | PORT_Memcpy(ctx->partialBlock + ctx->partialIndex, data + data_index, copy_len); |
247 | 756 | data_index += copy_len; |
248 | 756 | ctx->partialIndex += copy_len; |
249 | 756 | } |
250 | | |
251 | 1 | return SECSuccess; |
252 | 1 | } |
253 | | |
254 | | /* NIST SP.800-38B, 6.2 MAC Generation */ |
255 | | SECStatus |
256 | | CMAC_Finish(CMACContext *ctx, unsigned char *result, |
257 | | unsigned int *result_len, |
258 | | unsigned int max_result_len) |
259 | 1 | { |
260 | 1 | if (ctx == NULL || result == NULL || max_result_len == 0) { |
261 | 0 | PORT_SetError(SEC_ERROR_INVALID_ARGS); |
262 | 0 | return SECFailure; |
263 | 0 | } |
264 | | |
265 | 1 | if (max_result_len > ctx->blockSize) { |
266 | | /* This is a weird situation. The PKCS #11 soft tokencode passes |
267 | | * sizeof(result) here, which is hard-coded as SFTK_MAX_MAC_LENGTH. |
268 | | * This later gets truncated to min(SFTK_MAX_MAC_LENGTH, requested). */ |
269 | 1 | max_result_len = ctx->blockSize; |
270 | 1 | } |
271 | | |
272 | | /* Step 4: If M_n* is a complete block, M_n = K1 ^ M_n*. Else, |
273 | | * M_n = K2 ^ (M_n* || 10^j). */ |
274 | 1 | if (ctx->partialIndex == ctx->blockSize) { |
275 | | /* XOR in K1. */ |
276 | 0 | for (unsigned int index = 0; index < ctx->blockSize; index++) { |
277 | 0 | ctx->partialBlock[index] ^= ctx->k1[index]; |
278 | 0 | } |
279 | 1 | } else { |
280 | | /* Use 10* padding on the partial block. */ |
281 | 1 | ctx->partialBlock[ctx->partialIndex++] = 0x80; |
282 | 1 | PORT_Memset(ctx->partialBlock + ctx->partialIndex, 0, |
283 | 1 | ctx->blockSize - ctx->partialIndex); |
284 | 1 | ctx->partialIndex = ctx->blockSize; |
285 | | |
286 | | /* XOR in K2. */ |
287 | 17 | for (unsigned int index = 0; index < ctx->blockSize; index++) { |
288 | 16 | ctx->partialBlock[index] ^= ctx->k2[index]; |
289 | 16 | } |
290 | 1 | } |
291 | | |
292 | | /* Encrypt the block. */ |
293 | 1 | if (cmac_UpdateState(ctx) != SECSuccess) { |
294 | 0 | return SECFailure; |
295 | 0 | } |
296 | | |
297 | | /* Step 7 & 8: T = MSB_tlen(C_n); return T. */ |
298 | 1 | PORT_Memcpy(result, ctx->lastBlock, max_result_len); |
299 | 1 | if (result_len != NULL) { |
300 | 1 | *result_len = max_result_len; |
301 | 1 | } |
302 | 1 | return SECSuccess; |
303 | 1 | } |
304 | | |
305 | | void |
306 | | CMAC_Destroy(CMACContext *ctx, PRBool free_it) |
307 | 1 | { |
308 | 1 | if (ctx == NULL) { |
309 | 0 | return; |
310 | 0 | } |
311 | | |
312 | 1 | if (ctx->cipherType == CMAC_AES && ctx->cipher.aes != NULL) { |
313 | 1 | AES_DestroyContext(ctx->cipher.aes, PR_TRUE); |
314 | 1 | } |
315 | | |
316 | | /* Destroy everything in the context. This includes sensitive data in |
317 | | * K1, K2, and lastBlock. */ |
318 | 1 | PORT_Memset(ctx, 0, sizeof(*ctx)); |
319 | | |
320 | 1 | if (free_it == PR_TRUE) { |
321 | 1 | PORT_Free(ctx); |
322 | 1 | } |
323 | 1 | } |