blob: a13a00bc239d66870eeef131c7fdf55c1797e1e7 [file] [log] [blame]
Louis Mayencourt7a36f782018-09-24 14:00:57 +01001/*
2 * Copyright (c) 2019, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8#include "secure_fw/core/secure_utilities.h"
9#include "tfm_crypto_defs.h"
10
11#include "psa_crypto.h"
12
13#include "tfm_crypto_struct.h"
14
15#include "tfm_crypto_api.h"
16#include "crypto_utils.h"
17
Jamie Fox82b87ca2018-12-11 16:41:11 +000018/**
19 * \def CRYPTO_HMAC_MAX_KEY_LENGTH
20 *
21 * \brief Specifies the maximum key length supported by the
22 * HMAC operations in this implementation
23 */
24#ifndef CRYPTO_HMAC_MAX_KEY_LENGTH
25#define CRYPTO_HMAC_MAX_KEY_LENGTH (32)
26#endif
27
Louis Mayencourt7a36f782018-09-24 14:00:57 +010028static void mac_zeroize(void *data, size_t size)
29{
30 tfm_memset(data, 0, size);
31}
32
33static size_t get_hash_block_size(psa_algorithm_t alg)
34{
35 switch (alg) {
36 case PSA_ALG_MD2:
37 return 16;
38 case PSA_ALG_MD4:
39 return 64;
40 case PSA_ALG_MD5:
41 return 64;
42 case PSA_ALG_RIPEMD160:
43 return 64;
44 case PSA_ALG_SHA_1:
45 return 64;
46 case PSA_ALG_SHA_224:
47 return 64;
48 case PSA_ALG_SHA_256:
49 return 64;
50 case PSA_ALG_SHA_384:
51 return 128;
52 case PSA_ALG_SHA_512:
53 return 128;
54 default:
55 return 0;
56 }
57}
58
59static enum tfm_crypto_err_t tfm_crypto_hmac_setup(
60 struct tfm_mac_operation_s *ctx,
61 psa_key_slot_t key,
62 psa_algorithm_t alg)
63{
64 enum tfm_crypto_err_t err;
65 psa_key_type_t key_type;
66 size_t key_size;
Jamie Fox82b87ca2018-12-11 16:41:11 +000067 uint8_t key_data[CRYPTO_HMAC_MAX_KEY_LENGTH];
Louis Mayencourt7a36f782018-09-24 14:00:57 +010068 uint8_t hashed_key[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
69 size_t block_size;
70 uint8_t ipad[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
71 uint8_t *opad = ctx->ctx.hmac.opad;
72 size_t i;
Jamie Foxefd82732018-11-26 10:34:32 +000073 psa_key_usage_t usage;
Louis Mayencourt7a36f782018-09-24 14:00:57 +010074
75 /* Check provided key */
76 err = tfm_crypto_get_key_information(key, &key_type, &key_size);
77 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
78 return err;
79 }
80
81 if (key_type != PSA_KEY_TYPE_HMAC){
82 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
83 }
84
Jamie Foxefd82732018-11-26 10:34:32 +000085 /* Set the key usage based on whether this is a sign or verify operation */
86 if ((ctx->key_usage_sign == 1) && (ctx->key_usage_verify == 0)) {
87 usage = PSA_KEY_USAGE_SIGN;
88 } else if ((ctx->key_usage_sign == 0) && (ctx->key_usage_verify == 1)) {
89 usage = PSA_KEY_USAGE_VERIFY;
90 } else {
91 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
92 }
93
Louis Mayencourt7a36f782018-09-24 14:00:57 +010094 /* Get the key data to start the HMAC */
Jamie Foxefd82732018-11-26 10:34:32 +000095 err = tfm_crypto_get_key(key,
96 usage,
97 alg,
98 key_data,
Jamie Fox82b87ca2018-12-11 16:41:11 +000099 CRYPTO_HMAC_MAX_KEY_LENGTH,
Jamie Foxefd82732018-11-26 10:34:32 +0000100 &key_size);
Louis Mayencourt7a36f782018-09-24 14:00:57 +0100101 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
102 return err;
103 }
104
105 /* Bind the digest size to the MAC operation */
106 ctx->mac_size = PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg));
107
108 block_size = get_hash_block_size(PSA_ALG_HMAC_HASH(alg));
109
110 /* The HMAC algorithm is the standard procedure as described in
111 * RFC-2104 (https://tools.ietf.org/html/rfc2104)
112 */
113 if (key_size > block_size) {
114 /* Hash the key to reduce it to block size */
115 err = tfm_crypto_hash_setup(&(ctx->ctx.hmac.hash_operation),
116 PSA_ALG_HMAC_HASH(alg));
117 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
118 return err;
119 }
120
121 err = tfm_crypto_hash_update(&(ctx->ctx.hmac.hash_operation),
122 &key_data[0],
123 key_size);
124 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
125 tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
126 return err;
127 }
128
129 /* Replace the key with the hashed key */
130 err = tfm_crypto_hash_finish(&(ctx->ctx.hmac.hash_operation),
131 hashed_key, sizeof(hashed_key),
132 &key_size);
133 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
134 tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
135 return err;
136 }
137 } else {
138 /* Copy the key inside the hashed_key buffer */
139 for (i=0; i<key_size; i++) {
140 hashed_key[i] = key_data[i];
141 }
142 }
143
144 /* Create ipad = hashed_key XOR 0x36 and opad = hashed_key XOR 0x5C */
145 for (i=0; i<key_size; i++) {
146 ipad[i] = hashed_key[i] ^ 0x36;
147 opad[i] = hashed_key[i] ^ 0x5C;
148 }
149 /* Fill ipad and opad to match block size */
150 for (i=key_size; i<block_size; i++) {
151 ipad[i] = 0x36;
152 opad[i] = 0x5C;
153 }
154
155 /* Start hash1 = H(i_key_pad || message) */
156 err = tfm_crypto_hash_setup(&(ctx->ctx.hmac.hash_operation),
157 PSA_ALG_HMAC_HASH(alg));
158 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
159 /* Clear key information on stack */
160 for (i=0; i<key_size; i++) {
161 hashed_key[i] = 0;
162 ipad[i] = 0;
163 }
164 return err;
165 }
166
167 err = tfm_crypto_hash_update(&(ctx->ctx.hmac.hash_operation),
168 ipad,
169 block_size);
170 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
171 tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
172 return err;
173 }
174
175 return TFM_CRYPTO_ERR_PSA_SUCCESS;
176}
177
178static enum tfm_crypto_err_t tfm_crypto_mac_setup(psa_mac_operation_t *operation,
179 psa_key_slot_t key,
180 psa_algorithm_t alg,
181 uint8_t sign_operation)
182{
183 enum tfm_crypto_err_t err;
184
185 struct tfm_mac_operation_s *ctx = NULL;
186
187 if (!PSA_ALG_IS_MAC(alg)) {
188 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
189 }
190
191 /* Validate pointers */
192 err = tfm_crypto_memory_check(operation,
193 sizeof(psa_mac_operation_t),
194 TFM_MEMORY_ACCESS_RW);
195 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
196 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
197 }
198
199 /* Allocate the operation context in the secure world */
200 err = tfm_crypto_operation_alloc(TFM_CRYPTO_MAC_OPERATION,
201 &(operation->handle));
202 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
203 return err;
204 }
205
206 /* Look up the corresponding operation context */
207 err = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
208 operation->handle,
209 (void **)&ctx);
210 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
211 /* Release the operation context */
212 tfm_crypto_operation_release(&(operation->handle));
213 return err;
214 }
215
216 /* Bind the algorithm to the mac operation */
217 ctx->alg = alg;
218
219 /* Specify if this will be used for a sign or verify operation */
220 if (sign_operation) {
221 ctx->key_usage_verify = 0;
222 ctx->key_usage_sign = 1;
223 } else {
224 ctx->key_usage_verify = 1;
225 ctx->key_usage_sign = 0;
226 }
227
228 if (PSA_ALG_IS_HMAC(alg)) {
229 err = tfm_crypto_hmac_setup(ctx, key, alg);
230 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
231 /* Release the operation context */
232 tfm_crypto_operation_release(&(operation->handle));
233 return err;
234 }
235
236 ctx->key_set = 1;
237 } else {
238 /* Other MAC types constructions are not supported */
239 /* Release the operation context */
240 tfm_crypto_operation_release(&(operation->handle));
241 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
242 }
243
244 return TFM_CRYPTO_ERR_PSA_SUCCESS;
245}
246
247static enum tfm_crypto_err_t tfm_crypto_mac_finish(
248 struct tfm_mac_operation_s *ctx,
249 uint8_t *mac,
250 size_t mac_size,
251 size_t *mac_length)
252{
253 enum tfm_crypto_err_t err;
254 uint8_t hash1[PSA_HASH_MAX_SIZE];
255 size_t hash_size;
256 uint8_t *opad;
257 size_t block_size;
258
259 /* Sanity checks */
260 if (mac_size < ctx->mac_size) {
261 return TFM_CRYPTO_ERR_PSA_ERROR_BUFFER_TOO_SMALL;
262 }
263
264 if (!(ctx->has_input)) {
265 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
266 }
267
268 if (PSA_ALG_IS_HMAC(ctx->alg)) {
269 opad = ctx->ctx.hmac.opad;
270 block_size = get_hash_block_size(PSA_ALG_HMAC_HASH(ctx->alg));
271
272 /* finish the hash1 = H(ipad || message) */
273 err = tfm_crypto_hash_finish(&(ctx->ctx.hmac.hash_operation),
274 hash1,
275 sizeof(hash1),
276 &hash_size);
277 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
278 return err;
279 }
280
281 /* compute the final mac value = H(opad || hash1) */
282 err = tfm_crypto_hash_setup(&(ctx->ctx.hmac.hash_operation),
283 PSA_ALG_HMAC_HASH(ctx->alg));
284 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
285 mac_zeroize(hash1, sizeof(hash1));
286 return err;
287 }
288
289 err = tfm_crypto_hash_update(&(ctx->ctx.hmac.hash_operation),
290 opad,
291 block_size);
292 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
293 mac_zeroize(hash1, sizeof(hash1));
294 return err;
295 }
296
297 err = tfm_crypto_hash_update(&(ctx->ctx.hmac.hash_operation),
298 hash1,
299 hash_size);
300 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
301 mac_zeroize(hash1, sizeof(hash1));
302 return err;
303 }
304
305 err = tfm_crypto_hash_finish(&(ctx->ctx.hmac.hash_operation),
306 mac,
307 mac_size,
308 mac_length);
309 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
310 mac_zeroize(hash1, sizeof(hash1));
311 return err;
312 }
313
314 /* Clear intermediate hash value */
315 mac_zeroize(hash1, sizeof(hash1));
316
317 } else {
318 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
319 }
320
321 /* Clear the mac context */
322 mac_zeroize(ctx, sizeof(struct tfm_mac_operation_s));
323
324 return TFM_CRYPTO_ERR_PSA_SUCCESS;
325}
326
327/*!
328 * \defgroup public_psa Public functions, PSA
329 *
330 */
331
332/*!@{*/
333enum tfm_crypto_err_t tfm_crypto_mac_sign_setup(psa_mac_operation_t *operation,
334 psa_key_slot_t key,
335 psa_algorithm_t alg)
336{
337 return tfm_crypto_mac_setup(operation, key, alg, 1);
338}
339
340enum tfm_crypto_err_t tfm_crypto_mac_verify_setup(
341 psa_mac_operation_t *operation,
342 psa_key_slot_t key,
343 psa_algorithm_t alg)
344{
345 return tfm_crypto_mac_setup(operation, key, alg, 0);
346}
347
348enum tfm_crypto_err_t tfm_crypto_mac_update(psa_mac_operation_t *operation,
349 const uint8_t *input,
350 size_t input_length)
351{
352 enum tfm_crypto_err_t err;
353
354 struct tfm_mac_operation_s *ctx = NULL;
355
356 if (input_length == 0) {
357 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
358 }
359
360 /* Validate pointers */
361 err = tfm_crypto_memory_check(operation,
362 sizeof(psa_mac_operation_t),
363 TFM_MEMORY_ACCESS_RW);
364 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
365 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
366 }
367
368 err = tfm_crypto_memory_check((void *)input,
369 input_length,
370 TFM_MEMORY_ACCESS_RO);
371 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
372 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
373 }
374
375 /* Look up the corresponding operation context */
376 err = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
377 operation->handle,
378 (void **)&ctx);
379 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
380 return err;
381 }
382
383 /* Sanity check */
384 if (!(ctx->key_set)) {
385 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
386 }
387
388 /* Process the input chunk */
389 if (PSA_ALG_IS_HMAC(ctx->alg)) {
390 err = tfm_crypto_hash_update(&(ctx->ctx.hmac.hash_operation),
391 input,
392 input_length);
393 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
394 return err;
395 }
396
397 /* Set this flag to avoid HMAC without data */
398 ctx->has_input = 1;
399 } else {
400 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
401 }
402
403 return TFM_CRYPTO_ERR_PSA_SUCCESS;
404}
405
406enum tfm_crypto_err_t tfm_crypto_mac_sign_finish(psa_mac_operation_t *operation,
407 uint8_t *mac,
408 size_t mac_size,
409 size_t *mac_length)
410{
411 enum tfm_crypto_err_t err;
412 struct tfm_mac_operation_s *ctx = NULL;
413
414 if (mac_size == 0) {
415 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
416 }
417
418 /* Validate pointers */
419 err = tfm_crypto_memory_check(operation,
420 sizeof(psa_mac_operation_t),
421 TFM_MEMORY_ACCESS_RW);
422 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
423 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
424 }
425
426 err = tfm_crypto_memory_check((void *)mac,
427 mac_size,
428 TFM_MEMORY_ACCESS_RW);
429 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
430 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
431 }
432
433 err = tfm_crypto_memory_check(mac_length,
434 sizeof(size_t),
435 TFM_MEMORY_ACCESS_RW);
436 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
437 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
438 }
439
440 /* Look up the corresponding operation context */
441 err = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
442 operation->handle,
443 (void **)&ctx);
444 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
445 return err;
446 }
447
448 if ((ctx->key_usage_sign == 1) && (ctx->key_usage_verify == 0)) {
449 /* Finalise the mac operation */
450 err = tfm_crypto_mac_finish(ctx, mac, mac_size, mac_length);
451 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
452 return err;
453 }
454 /* Release the operation context */
455 err = tfm_crypto_operation_release(&(operation->handle));
456 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
457 return err;
458 }
459 } else {
460 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
461 }
462
463 return TFM_CRYPTO_ERR_PSA_SUCCESS;
464}
465
466enum tfm_crypto_err_t tfm_crypto_mac_verify_finish(
467 psa_mac_operation_t *operation,
468 const uint8_t *mac,
469 size_t mac_length)
470{
471 enum tfm_crypto_err_t err;
472 struct tfm_mac_operation_s *ctx = NULL;
473 uint8_t computed_mac[PSA_HMAC_MAX_HASH_BLOCK_SIZE];
474 size_t computed_mac_length;
475 size_t i;
476 uint32_t comp_mismatch = 0;
477
478 if (mac_length == 0) {
479 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
480 }
481
482 /* Validate pointers */
483 err = tfm_crypto_memory_check(operation,
484 sizeof(psa_mac_operation_t),
485 TFM_MEMORY_ACCESS_RW);
486 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
487 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
488 }
489
490 err = tfm_crypto_memory_check((void *)mac,
491 mac_length,
492 TFM_MEMORY_ACCESS_RO);
493 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
494 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
495 }
496
497 /* Look up the corresponding operation context */
498 err = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
499 operation->handle,
500 (void **)&ctx);
501 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
502 return err;
503 }
504
505 if ((ctx->key_usage_sign == 0) && (ctx->key_usage_verify == 1)) {
506 /* Finalise the mac operation */
507 err = tfm_crypto_mac_finish(ctx,
508 computed_mac,
509 sizeof(computed_mac),
510 &computed_mac_length);
511 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
512 return err;
513 }
514 /* Release the operation context */
515 err = tfm_crypto_operation_release(&(operation->handle));
516 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
517 return err;
518 }
519
520 /* Check that the computed mac match the expected one */
521 if (computed_mac_length != mac_length) {
522 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
523 }
524
525 for (i=0; i<computed_mac_length ; i++) {
526 if (computed_mac[i] != mac[i]) {
527 comp_mismatch = 1;
528 }
529 }
530
531 if (comp_mismatch == 1) {
532 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_SIGNATURE;
533 }
534 } else {
535 return TFM_CRYPTO_ERR_PSA_ERROR_BAD_STATE;
536 }
537
538 return TFM_CRYPTO_ERR_PSA_SUCCESS;
539}
540
541enum tfm_crypto_err_t tfm_crypto_mac_abort(psa_mac_operation_t *operation)
542{
543 enum tfm_crypto_err_t err;
544 struct tfm_mac_operation_s *ctx = NULL;
545
546 /* Validate pointers */
547 err = tfm_crypto_memory_check(operation,
548 sizeof(psa_mac_operation_t),
549 TFM_MEMORY_ACCESS_RW);
550 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
551 return TFM_CRYPTO_ERR_PSA_ERROR_INVALID_ARGUMENT;
552 }
553
554 /* Look up the corresponding operation context */
555 err = tfm_crypto_operation_lookup(TFM_CRYPTO_MAC_OPERATION,
556 operation->handle,
557 (void **)&ctx);
558 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
559 return err;
560 }
561
562 if (PSA_ALG_IS_HMAC(ctx->alg)){
563 /* Check if the HMAC internal context needs to be deallocated */
564 if (ctx->ctx.hmac.hash_operation.handle != TFM_CRYPTO_INVALID_HANDLE) {
565 /* Clear hash context */
566 err = tfm_crypto_hash_abort(&(ctx->ctx.hmac.hash_operation));
567 if (err != TFM_CRYPTO_ERR_PSA_SUCCESS) {
568 return err;
569 }
570 }
571
572 /* Release the operation context */
573 tfm_crypto_operation_release(&(operation->handle));
574 } else {
575 /* MACs other than HMACs not currently supported */
576 return TFM_CRYPTO_ERR_PSA_ERROR_NOT_SUPPORTED;
577 }
578
579 return TFM_CRYPTO_ERR_PSA_SUCCESS;
580}
581/*!@}*/