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