1 /*
2 * PSA MAC layer on top of Mbed TLS software crypto
3 */
4 /*
5 * Copyright The Mbed TLS Contributors
6 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
7 */
8
9 #include "common.h"
10
11 #if defined(MBEDTLS_PSA_CRYPTO_C)
12
13 #include <psa/crypto.h>
14 #include "psa_crypto_core.h"
15 #include "psa_crypto_cipher.h"
16 #include "psa_crypto_mac.h"
17 #include <mbedtls/md.h>
18
19 #include <mbedtls/error.h>
20 #include "mbedtls/constant_time.h"
21 #include <string.h>
22
23 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
psa_hmac_abort_internal(mbedtls_psa_hmac_operation_t * hmac)24 static psa_status_t psa_hmac_abort_internal(
25 mbedtls_psa_hmac_operation_t *hmac)
26 {
27 mbedtls_platform_zeroize(hmac->opad, sizeof(hmac->opad));
28 return psa_hash_abort(&hmac->hash_ctx);
29 }
30
psa_hmac_setup_internal(mbedtls_psa_hmac_operation_t * hmac,const uint8_t * key,size_t key_length,psa_algorithm_t hash_alg)31 static psa_status_t psa_hmac_setup_internal(
32 mbedtls_psa_hmac_operation_t *hmac,
33 const uint8_t *key,
34 size_t key_length,
35 psa_algorithm_t hash_alg)
36 {
37 uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
38 size_t i;
39 size_t hash_size = PSA_HASH_LENGTH(hash_alg);
40 size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
41 psa_status_t status;
42
43 hmac->alg = hash_alg;
44
45 /* Sanity checks on block_size, to guarantee that there won't be a buffer
46 * overflow below. This should never trigger if the hash algorithm
47 * is implemented correctly. */
48 /* The size checks against the ipad and opad buffers cannot be written
49 * `block_size > sizeof( ipad ) || block_size > sizeof( hmac->opad )`
50 * because that triggers -Wlogical-op on GCC 7.3. */
51 if (block_size > sizeof(ipad)) {
52 return PSA_ERROR_NOT_SUPPORTED;
53 }
54 if (block_size > sizeof(hmac->opad)) {
55 return PSA_ERROR_NOT_SUPPORTED;
56 }
57 if (block_size < hash_size) {
58 return PSA_ERROR_NOT_SUPPORTED;
59 }
60
61 if (key_length > block_size) {
62 status = psa_hash_compute(hash_alg, key, key_length,
63 ipad, sizeof(ipad), &key_length);
64 if (status != PSA_SUCCESS) {
65 goto cleanup;
66 }
67 }
68 /* A 0-length key is not commonly used in HMAC when used as a MAC,
69 * but it is permitted. It is common when HMAC is used in HKDF, for
70 * example. Don't call `memcpy` in the 0-length because `key` could be
71 * an invalid pointer which would make the behavior undefined. */
72 else if (key_length != 0) {
73 memcpy(ipad, key, key_length);
74 }
75
76 /* ipad contains the key followed by garbage. Xor and fill with 0x36
77 * to create the ipad value. */
78 for (i = 0; i < key_length; i++) {
79 ipad[i] ^= 0x36;
80 }
81 memset(ipad + key_length, 0x36, block_size - key_length);
82
83 /* Copy the key material from ipad to opad, flipping the requisite bits,
84 * and filling the rest of opad with the requisite constant. */
85 for (i = 0; i < key_length; i++) {
86 hmac->opad[i] = ipad[i] ^ 0x36 ^ 0x5C;
87 }
88 memset(hmac->opad + key_length, 0x5C, block_size - key_length);
89
90 status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
91 if (status != PSA_SUCCESS) {
92 goto cleanup;
93 }
94
95 status = psa_hash_update(&hmac->hash_ctx, ipad, block_size);
96
97 cleanup:
98 mbedtls_platform_zeroize(ipad, sizeof(ipad));
99
100 return status;
101 }
102
psa_hmac_update_internal(mbedtls_psa_hmac_operation_t * hmac,const uint8_t * data,size_t data_length)103 static psa_status_t psa_hmac_update_internal(
104 mbedtls_psa_hmac_operation_t *hmac,
105 const uint8_t *data,
106 size_t data_length)
107 {
108 return psa_hash_update(&hmac->hash_ctx, data, data_length);
109 }
110
psa_hmac_finish_internal(mbedtls_psa_hmac_operation_t * hmac,uint8_t * mac,size_t mac_size)111 static psa_status_t psa_hmac_finish_internal(
112 mbedtls_psa_hmac_operation_t *hmac,
113 uint8_t *mac,
114 size_t mac_size)
115 {
116 uint8_t tmp[PSA_HASH_MAX_SIZE];
117 psa_algorithm_t hash_alg = hmac->alg;
118 size_t hash_size = 0;
119 size_t block_size = PSA_HASH_BLOCK_LENGTH(hash_alg);
120 psa_status_t status;
121
122 status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
123 if (status != PSA_SUCCESS) {
124 return status;
125 }
126 /* From here on, tmp needs to be wiped. */
127
128 status = psa_hash_setup(&hmac->hash_ctx, hash_alg);
129 if (status != PSA_SUCCESS) {
130 goto exit;
131 }
132
133 status = psa_hash_update(&hmac->hash_ctx, hmac->opad, block_size);
134 if (status != PSA_SUCCESS) {
135 goto exit;
136 }
137
138 status = psa_hash_update(&hmac->hash_ctx, tmp, hash_size);
139 if (status != PSA_SUCCESS) {
140 goto exit;
141 }
142
143 status = psa_hash_finish(&hmac->hash_ctx, tmp, sizeof(tmp), &hash_size);
144 if (status != PSA_SUCCESS) {
145 goto exit;
146 }
147
148 memcpy(mac, tmp, mac_size);
149
150 exit:
151 mbedtls_platform_zeroize(tmp, hash_size);
152 return status;
153 }
154 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
155
156 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
cmac_setup(mbedtls_psa_mac_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer)157 static psa_status_t cmac_setup(mbedtls_psa_mac_operation_t *operation,
158 const psa_key_attributes_t *attributes,
159 const uint8_t *key_buffer)
160 {
161 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
162
163 #if defined(PSA_WANT_KEY_TYPE_DES)
164 /* Mbed TLS CMAC does not accept 3DES with only two keys, nor does it accept
165 * to do CMAC with pure DES, so return NOT_SUPPORTED here. */
166 if (psa_get_key_type(attributes) == PSA_KEY_TYPE_DES &&
167 (psa_get_key_bits(attributes) == 64 ||
168 psa_get_key_bits(attributes) == 128)) {
169 return PSA_ERROR_NOT_SUPPORTED;
170 }
171 #endif
172
173 const mbedtls_cipher_info_t *cipher_info =
174 mbedtls_cipher_info_from_psa(
175 PSA_ALG_CMAC,
176 psa_get_key_type(attributes),
177 psa_get_key_bits(attributes),
178 NULL);
179
180 if (cipher_info == NULL) {
181 return PSA_ERROR_NOT_SUPPORTED;
182 }
183
184 ret = mbedtls_cipher_setup(&operation->ctx.cmac, cipher_info);
185 if (ret != 0) {
186 goto exit;
187 }
188
189 ret = mbedtls_cipher_cmac_starts(&operation->ctx.cmac,
190 key_buffer,
191 psa_get_key_bits(attributes));
192 exit:
193 return mbedtls_to_psa_error(ret);
194 }
195 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
196
197 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC) || \
198 defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
199
200 /* Initialize this driver's MAC operation structure. Once this function has been
201 * called, mbedtls_psa_mac_abort can run and will do the right thing. */
mac_init(mbedtls_psa_mac_operation_t * operation,psa_algorithm_t alg)202 static psa_status_t mac_init(
203 mbedtls_psa_mac_operation_t *operation,
204 psa_algorithm_t alg)
205 {
206 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
207
208 operation->alg = alg;
209
210 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
211 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
212 mbedtls_cipher_init(&operation->ctx.cmac);
213 status = PSA_SUCCESS;
214 } else
215 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
216 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
217 if (PSA_ALG_IS_HMAC(operation->alg)) {
218 /* We'll set up the hash operation later in psa_hmac_setup_internal. */
219 operation->ctx.hmac.alg = 0;
220 status = PSA_SUCCESS;
221 } else
222 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
223 {
224 (void) operation;
225 status = PSA_ERROR_NOT_SUPPORTED;
226 }
227
228 if (status != PSA_SUCCESS) {
229 memset(operation, 0, sizeof(*operation));
230 }
231 return status;
232 }
233
mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t * operation)234 psa_status_t mbedtls_psa_mac_abort(mbedtls_psa_mac_operation_t *operation)
235 {
236 if (operation->alg == 0) {
237 /* The object has (apparently) been initialized but it is not
238 * in use. It's ok to call abort on such an object, and there's
239 * nothing to do. */
240 return PSA_SUCCESS;
241 } else
242 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
243 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
244 mbedtls_cipher_free(&operation->ctx.cmac);
245 } else
246 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
247 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
248 if (PSA_ALG_IS_HMAC(operation->alg)) {
249 psa_hmac_abort_internal(&operation->ctx.hmac);
250 } else
251 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
252 {
253 /* Sanity check (shouldn't happen: operation->alg should
254 * always have been initialized to a valid value). */
255 goto bad_state;
256 }
257
258 operation->alg = 0;
259
260 return PSA_SUCCESS;
261
262 bad_state:
263 /* If abort is called on an uninitialized object, we can't trust
264 * anything. Wipe the object in case it contains confidential data.
265 * This may result in a memory leak if a pointer gets overwritten,
266 * but it's too late to do anything about this. */
267 memset(operation, 0, sizeof(*operation));
268 return PSA_ERROR_BAD_STATE;
269 }
270
psa_mac_setup(mbedtls_psa_mac_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)271 static psa_status_t psa_mac_setup(mbedtls_psa_mac_operation_t *operation,
272 const psa_key_attributes_t *attributes,
273 const uint8_t *key_buffer,
274 size_t key_buffer_size,
275 psa_algorithm_t alg)
276 {
277 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
278
279 /* A context must be freshly initialized before it can be set up. */
280 if (operation->alg != 0) {
281 return PSA_ERROR_BAD_STATE;
282 }
283
284 status = mac_init(operation, alg);
285 if (status != PSA_SUCCESS) {
286 return status;
287 }
288
289 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
290 if (PSA_ALG_FULL_LENGTH_MAC(alg) == PSA_ALG_CMAC) {
291 /* Key buffer size for CMAC is dictated by the key bits set on the
292 * attributes, and previously validated by the core on key import. */
293 (void) key_buffer_size;
294 status = cmac_setup(operation, attributes, key_buffer);
295 } else
296 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
297 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
298 if (PSA_ALG_IS_HMAC(alg)) {
299 status = psa_hmac_setup_internal(&operation->ctx.hmac,
300 key_buffer,
301 key_buffer_size,
302 PSA_ALG_HMAC_GET_HASH(alg));
303 } else
304 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
305 {
306 (void) attributes;
307 (void) key_buffer;
308 (void) key_buffer_size;
309 status = PSA_ERROR_NOT_SUPPORTED;
310 }
311
312 if (status != PSA_SUCCESS) {
313 mbedtls_psa_mac_abort(operation);
314 }
315
316 return status;
317 }
318
mbedtls_psa_mac_sign_setup(mbedtls_psa_mac_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)319 psa_status_t mbedtls_psa_mac_sign_setup(
320 mbedtls_psa_mac_operation_t *operation,
321 const psa_key_attributes_t *attributes,
322 const uint8_t *key_buffer,
323 size_t key_buffer_size,
324 psa_algorithm_t alg)
325 {
326 return psa_mac_setup(operation, attributes,
327 key_buffer, key_buffer_size, alg);
328 }
329
mbedtls_psa_mac_verify_setup(mbedtls_psa_mac_operation_t * operation,const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg)330 psa_status_t mbedtls_psa_mac_verify_setup(
331 mbedtls_psa_mac_operation_t *operation,
332 const psa_key_attributes_t *attributes,
333 const uint8_t *key_buffer,
334 size_t key_buffer_size,
335 psa_algorithm_t alg)
336 {
337 return psa_mac_setup(operation, attributes,
338 key_buffer, key_buffer_size, alg);
339 }
340
mbedtls_psa_mac_update(mbedtls_psa_mac_operation_t * operation,const uint8_t * input,size_t input_length)341 psa_status_t mbedtls_psa_mac_update(
342 mbedtls_psa_mac_operation_t *operation,
343 const uint8_t *input,
344 size_t input_length)
345 {
346 if (operation->alg == 0) {
347 return PSA_ERROR_BAD_STATE;
348 }
349
350 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
351 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
352 return mbedtls_to_psa_error(
353 mbedtls_cipher_cmac_update(&operation->ctx.cmac,
354 input, input_length));
355 } else
356 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
357 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
358 if (PSA_ALG_IS_HMAC(operation->alg)) {
359 return psa_hmac_update_internal(&operation->ctx.hmac,
360 input, input_length);
361 } else
362 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
363 {
364 /* This shouldn't happen if `operation` was initialized by
365 * a setup function. */
366 (void) input;
367 (void) input_length;
368 return PSA_ERROR_BAD_STATE;
369 }
370 }
371
psa_mac_finish_internal(mbedtls_psa_mac_operation_t * operation,uint8_t * mac,size_t mac_size)372 static psa_status_t psa_mac_finish_internal(
373 mbedtls_psa_mac_operation_t *operation,
374 uint8_t *mac, size_t mac_size)
375 {
376 #if defined(MBEDTLS_PSA_BUILTIN_ALG_CMAC)
377 if (PSA_ALG_FULL_LENGTH_MAC(operation->alg) == PSA_ALG_CMAC) {
378 uint8_t tmp[PSA_BLOCK_CIPHER_BLOCK_MAX_SIZE];
379 int ret = mbedtls_cipher_cmac_finish(&operation->ctx.cmac, tmp);
380 if (ret == 0) {
381 memcpy(mac, tmp, mac_size);
382 }
383 mbedtls_platform_zeroize(tmp, sizeof(tmp));
384 return mbedtls_to_psa_error(ret);
385 } else
386 #endif /* MBEDTLS_PSA_BUILTIN_ALG_CMAC */
387 #if defined(MBEDTLS_PSA_BUILTIN_ALG_HMAC)
388 if (PSA_ALG_IS_HMAC(operation->alg)) {
389 return psa_hmac_finish_internal(&operation->ctx.hmac,
390 mac, mac_size);
391 } else
392 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC */
393 {
394 /* This shouldn't happen if `operation` was initialized by
395 * a setup function. */
396 (void) operation;
397 (void) mac;
398 (void) mac_size;
399 return PSA_ERROR_BAD_STATE;
400 }
401 }
402
mbedtls_psa_mac_sign_finish(mbedtls_psa_mac_operation_t * operation,uint8_t * mac,size_t mac_size,size_t * mac_length)403 psa_status_t mbedtls_psa_mac_sign_finish(
404 mbedtls_psa_mac_operation_t *operation,
405 uint8_t *mac,
406 size_t mac_size,
407 size_t *mac_length)
408 {
409 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
410
411 if (operation->alg == 0) {
412 return PSA_ERROR_BAD_STATE;
413 }
414
415 status = psa_mac_finish_internal(operation, mac, mac_size);
416 if (status == PSA_SUCCESS) {
417 *mac_length = mac_size;
418 }
419
420 return status;
421 }
422
mbedtls_psa_mac_verify_finish(mbedtls_psa_mac_operation_t * operation,const uint8_t * mac,size_t mac_length)423 psa_status_t mbedtls_psa_mac_verify_finish(
424 mbedtls_psa_mac_operation_t *operation,
425 const uint8_t *mac,
426 size_t mac_length)
427 {
428 uint8_t actual_mac[PSA_MAC_MAX_SIZE];
429 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
430
431 if (operation->alg == 0) {
432 return PSA_ERROR_BAD_STATE;
433 }
434
435 /* Consistency check: requested MAC length fits our local buffer */
436 if (mac_length > sizeof(actual_mac)) {
437 return PSA_ERROR_INVALID_ARGUMENT;
438 }
439
440 status = psa_mac_finish_internal(operation, actual_mac, mac_length);
441 if (status != PSA_SUCCESS) {
442 goto cleanup;
443 }
444
445 if (mbedtls_ct_memcmp(mac, actual_mac, mac_length) != 0) {
446 status = PSA_ERROR_INVALID_SIGNATURE;
447 }
448
449 cleanup:
450 mbedtls_platform_zeroize(actual_mac, sizeof(actual_mac));
451
452 return status;
453 }
454
mbedtls_psa_mac_compute(const psa_key_attributes_t * attributes,const uint8_t * key_buffer,size_t key_buffer_size,psa_algorithm_t alg,const uint8_t * input,size_t input_length,uint8_t * mac,size_t mac_size,size_t * mac_length)455 psa_status_t mbedtls_psa_mac_compute(
456 const psa_key_attributes_t *attributes,
457 const uint8_t *key_buffer,
458 size_t key_buffer_size,
459 psa_algorithm_t alg,
460 const uint8_t *input,
461 size_t input_length,
462 uint8_t *mac,
463 size_t mac_size,
464 size_t *mac_length)
465 {
466 psa_status_t status = PSA_ERROR_CORRUPTION_DETECTED;
467 mbedtls_psa_mac_operation_t operation = MBEDTLS_PSA_MAC_OPERATION_INIT;
468
469 status = psa_mac_setup(&operation,
470 attributes, key_buffer, key_buffer_size,
471 alg);
472 if (status != PSA_SUCCESS) {
473 goto exit;
474 }
475
476 if (input_length > 0) {
477 status = mbedtls_psa_mac_update(&operation, input, input_length);
478 if (status != PSA_SUCCESS) {
479 goto exit;
480 }
481 }
482
483 status = psa_mac_finish_internal(&operation, mac, mac_size);
484 if (status == PSA_SUCCESS) {
485 *mac_length = mac_size;
486 }
487
488 exit:
489 mbedtls_psa_mac_abort(&operation);
490
491 return status;
492 }
493
494 #endif /* MBEDTLS_PSA_BUILTIN_ALG_HMAC || MBEDTLS_PSA_BUILTIN_ALG_CMAC */
495
496 #endif /* MBEDTLS_PSA_CRYPTO_C */
497