1 /*
2 * t_cose_psa_crypto.c
3 *
4 * Copyright 2019, Laurence Lundblade
5 * Copyright (c) 2020-2021, Arm Limited. All rights reserved
6 *
7 * SPDX-License-Identifier: BSD-3-Clause
8 *
9 * See BSD-3-Clause license in README.md
10 */
11
12
13 /**
14 * \file t_cose_psa_crypto.c
15 *
16 * \brief Crypto Adaptation for t_cose to use ARM's PSA Crypto APIs.
17 *
18 * This connects up the abstract interface in t_cose_crypto.h to the
19 * implementations of ECDSA signing, hashing and HMAC in ARM's PSA crypto
20 * library.
21 *
22 * This adapter layer doesn't bloat the implementation as everything
23 * here had to be done anyway -- the mapping of algorithm IDs, the
24 * data format rearranging, the error code translation.
25 *
26 * This code should just work out of the box if compiled and linked
27 * against ARM's PSA crypto. No preprocessor #defines are needed.
28 *
29 * You can disable SHA-384 and SHA-512 to save code and space by
30 * defining T_COSE_DISABLE_ES384 or T_COSE_DISABLE_ES512. This saving
31 * is most in stack space in the main t_cose implementation. (It seems
32 * likely that changes to PSA itself would be needed to remove the
33 * SHA-384 and SHA-512 implementations to save that code. Lack of
34 * reference and dead stripping the executable won't do it).
35 */
36
37
38 #include "t_cose_crypto.h" /* The interface this implements */
39 #include "psa/crypto.h" /* PSA Crypto Interface to mbed crypto or such */
40
41
42 /* Here's the auto-detect and manual override logic for managing PSA
43 * Crypto API compatibility.
44 *
45 * PSA_GENERATOR_UNBRIDLED_CAPACITY happens to be defined in MBed
46 * Crypto 1.1 and not in MBed Crypto 2.0 so it is what auto-detect
47 * hinges off of.
48 *
49 * T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO20 can be defined to force
50 * setting to MBed Crypto 2.0
51 *
52 * T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 can be defined to force
53 * setting to MBed Crypt 1.1. It is also what the code below hinges
54 * on.
55 */
56 #if defined(PSA_GENERATOR_UNBRIDLED_CAPACITY) && !defined(T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO20)
57 #define T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11
58 #endif
59
60
61 /* Avoid compiler warning due to unused argument */
62 #define ARG_UNUSED(arg) (void)(arg)
63
64 #ifndef T_COSE_DISABLE_SIGN1
65 /**
66 * \brief Map a COSE signing algorithm ID to a PSA signing algorithm ID
67 *
68 * \param[in] cose_alg_id The COSE algorithm ID.
69 *
70 * \return The PSA algorithm ID or 0 if this doesn't map the COSE ID.
71 */
cose_alg_id_to_psa_alg_id(int32_t cose_alg_id)72 static psa_algorithm_t cose_alg_id_to_psa_alg_id(int32_t cose_alg_id)
73 {
74 /* The #ifdefs save a little code when algorithms are disabled */
75
76 return cose_alg_id == COSE_ALGORITHM_ES256 ? PSA_ALG_ECDSA(PSA_ALG_SHA_256) :
77 #ifndef T_COSE_DISABLE_ES384
78 cose_alg_id == COSE_ALGORITHM_ES384 ? PSA_ALG_ECDSA(PSA_ALG_SHA_384) :
79 #endif
80 #ifndef T_COSE_DISABLE_ES512
81 cose_alg_id == COSE_ALGORITHM_ES512 ? PSA_ALG_ECDSA(PSA_ALG_SHA_512) :
82 #endif
83 0;
84 /* psa/crypto_values.h doesn't seem to define a "no alg" value,
85 * but zero seems OK for that use in the ECDSA context. */
86 }
87
88
89 /**
90 * \brief Map a PSA error into a t_cose error for signing.
91 *
92 * \param[in] err The PSA status.
93 *
94 * \return The \ref t_cose_err_t.
95 */
psa_status_to_t_cose_error_signing(psa_status_t err)96 static enum t_cose_err_t psa_status_to_t_cose_error_signing(psa_status_t err)
97 {
98 /* Intentionally keeping to fewer mapped errors to save object code */
99 return err == PSA_SUCCESS ? T_COSE_SUCCESS :
100 err == PSA_ERROR_INVALID_SIGNATURE ? T_COSE_ERR_SIG_VERIFY :
101 err == PSA_ERROR_NOT_SUPPORTED ? T_COSE_ERR_UNSUPPORTED_SIGNING_ALG:
102 err == PSA_ERROR_INSUFFICIENT_MEMORY ? T_COSE_ERR_INSUFFICIENT_MEMORY :
103 err == PSA_ERROR_CORRUPTION_DETECTED ? T_COSE_ERR_TAMPERING_DETECTED :
104 T_COSE_ERR_SIG_FAIL;
105 }
106
107
108 /*
109 * See documentation in t_cose_crypto.h
110 */
111 enum t_cose_err_t
t_cose_crypto_pub_key_verify(int32_t cose_algorithm_id,struct t_cose_key verification_key,struct q_useful_buf_c kid,struct q_useful_buf_c hash_to_verify,struct q_useful_buf_c signature)112 t_cose_crypto_pub_key_verify(int32_t cose_algorithm_id,
113 struct t_cose_key verification_key,
114 struct q_useful_buf_c kid,
115 struct q_useful_buf_c hash_to_verify,
116 struct q_useful_buf_c signature)
117 {
118 psa_algorithm_t psa_alg_id;
119 psa_status_t psa_result;
120 enum t_cose_err_t return_value;
121 psa_key_handle_t verification_key_psa;
122
123 /* This implementation does no look up keys by kid in the key
124 * store */
125 ARG_UNUSED(kid);
126
127 /* Convert to PSA algorithm ID scheme */
128 psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
129
130 /* This implementation supports ECDSA and only ECDSA. The
131 * interface allows it to support other, but none are implemented.
132 * This implementation works for different keys lengths and
133 * curves. That is the curve and key length as associated with the
134 * signing_key passed in, not the cose_algorithm_id This check
135 * looks for ECDSA signing as indicated by COSE and rejects what
136 * is not. (Perhaps this check can be removed to save object code
137 * if it is the case that psa_verify_hash() does the right
138 * checks).
139 */
140 if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
141 return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
142 goto Done;
143 }
144
145 verification_key_psa = (psa_key_handle_t)verification_key.k.key_handle;
146
147 psa_result = psa_verify_hash(verification_key_psa,
148 psa_alg_id,
149 hash_to_verify.ptr,
150 hash_to_verify.len,
151 signature.ptr,
152 signature.len);
153
154 return_value = psa_status_to_t_cose_error_signing(psa_result);
155
156 Done:
157 return return_value;
158 }
159
160
161 /*
162 * See documentation in t_cose_crypto.h
163 */
164 enum t_cose_err_t
t_cose_crypto_pub_key_sign(int32_t cose_algorithm_id,struct t_cose_key signing_key,struct q_useful_buf_c hash_to_sign,struct q_useful_buf signature_buffer,struct q_useful_buf_c * signature)165 t_cose_crypto_pub_key_sign(int32_t cose_algorithm_id,
166 struct t_cose_key signing_key,
167 struct q_useful_buf_c hash_to_sign,
168 struct q_useful_buf signature_buffer,
169 struct q_useful_buf_c *signature)
170 {
171 enum t_cose_err_t return_value;
172 psa_status_t psa_result;
173 psa_algorithm_t psa_alg_id;
174 psa_key_handle_t signing_key_psa;
175 size_t signature_len;
176
177 psa_alg_id = cose_alg_id_to_psa_alg_id(cose_algorithm_id);
178
179 /* This implementation supports ECDSA and only ECDSA. The
180 * interface allows it to support other, but none are implemented.
181 * This implementation works for different keys lengths and
182 * curves. That is the curve and key length as associated with the
183 * signing_key passed in, not the cose_algorithm_id This check
184 * looks for ECDSA signing as indicated by COSE and rejects what
185 * is not. (Perhaps this check can be removed to save object code
186 * if it is the case that psa_verify_hash() does the right
187 * checks).
188 */
189 if(!PSA_ALG_IS_ECDSA(psa_alg_id)) {
190 return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
191 goto Done;
192 }
193
194 signing_key_psa = (psa_key_handle_t)signing_key.k.key_handle;
195
196 /* It is assumed that this call is checking the signature_buffer
197 * length and won't write off the end of it.
198 */
199 psa_result = psa_sign_hash(signing_key_psa,
200 psa_alg_id,
201 hash_to_sign.ptr,
202 hash_to_sign.len,
203 signature_buffer.ptr, /* Sig buf */
204 signature_buffer.len, /* Sig buf size */
205 &signature_len); /* Sig length */
206
207 return_value = psa_status_to_t_cose_error_signing(psa_result);
208
209 if(return_value == T_COSE_SUCCESS) {
210 /* Success, fill in the return useful_buf */
211 signature->ptr = signature_buffer.ptr;
212 signature->len = signature_len;
213 }
214
215 Done:
216 return return_value;
217 }
218
219
220 /*
221 * See documentation in t_cose_crypto.h
222 */
t_cose_crypto_sig_size(int32_t cose_algorithm_id,struct t_cose_key signing_key,size_t * sig_size)223 enum t_cose_err_t t_cose_crypto_sig_size(int32_t cose_algorithm_id,
224 struct t_cose_key signing_key,
225 size_t *sig_size)
226 {
227 enum t_cose_err_t return_value;
228 psa_key_handle_t signing_key_psa;
229 size_t key_len_bits;
230 size_t key_len_bytes;
231
232 /* If desperate to save code, this can return the constant
233 * T_COSE_MAX_SIG_SIZE instead of doing an exact calculation. The
234 * buffer size calculation will return too large of a value and
235 * waste a little heap / stack, but everything will still work
236 * (except the tests that test for exact values will fail). This
237 * will save 100 bytes or so of obejct code.
238 */
239
240 if(!t_cose_algorithm_is_ecdsa(cose_algorithm_id)) {
241 return_value = T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
242 goto Done;
243 }
244
245 signing_key_psa = (psa_key_handle_t)signing_key.k.key_handle;
246
247 #ifdef T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11
248 /* This code is for MBed Crypto 1.1. It uses an older version of
249 * the PSA Crypto API that is not compatible with the new
250 * versions. When all environments (particularly TF-M) are on the
251 * latest API, this code will no longer be necessary.
252 */
253
254 psa_key_type_t key_type;
255
256 psa_status_t status = psa_get_key_information(signing_key_psa,
257 &key_type,
258 &key_len_bits);
259
260 (void)key_type; /* Avoid unused parameter error */
261
262 #else /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
263 /* This code is for Mbed Crypto 2.0 circa 2019. The PSA Crypto API
264 * is supposed to be offically locked down in 2020 and should be
265 * very close to this, so this is likely the code to use with MBed
266 * Crypto going forward.
267 */
268
269 psa_key_attributes_t key_attributes = psa_key_attributes_init();
270
271 psa_status_t status = psa_get_key_attributes(signing_key_psa, &key_attributes);
272
273 key_len_bits = psa_get_key_bits(&key_attributes);
274
275 #endif /* T_COSE_USE_PSA_CRYPTO_FROM_MBED_CRYPTO11 */
276
277 return_value = psa_status_to_t_cose_error_signing(status);
278 if(return_value == T_COSE_SUCCESS) {
279 /* Calculation of size per RFC 8152 section 8.1 -- round up to
280 * number of bytes. */
281 key_len_bytes = key_len_bits / 8;
282 if(key_len_bits % 8) {
283 key_len_bytes++;
284 }
285 /* Double because signature is made of up r and s values */
286 *sig_size = key_len_bytes * 2;
287 }
288
289 return_value = T_COSE_SUCCESS;
290 Done:
291 return return_value;
292 }
293 #endif /* !T_COSE_DISABLE_SIGN1 */
294
295
296
297
298 #if !defined(T_COSE_DISABLE_SHORT_CIRCUIT_SIGN) || \
299 !defined(T_COSE_DISABLE_SIGN1)
300 /**
301 * \brief Convert COSE hash algorithm ID to a PSA hash algorithm ID
302 *
303 * \param[in] cose_hash_alg_id The COSE-based ID for the
304 *
305 * \return PSA-based hash algorithm ID, or USHRT_MAX on error.
306 *
307 */
308 static inline psa_algorithm_t
cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id)309 cose_hash_alg_id_to_psa(int32_t cose_hash_alg_id)
310 {
311 return cose_hash_alg_id == COSE_ALGORITHM_SHA_256 ? PSA_ALG_SHA_256 :
312 #ifndef T_COSE_DISABLE_ES384
313 cose_hash_alg_id == COSE_ALGORITHM_SHA_384 ? PSA_ALG_SHA_384 :
314 #endif
315 #ifndef T_COSE_DISABLE_ES512
316 cose_hash_alg_id == COSE_ALGORITHM_SHA_512 ? PSA_ALG_SHA_512 :
317 #endif
318 UINT16_MAX;
319 }
320
321
322 /**
323 * \brief Map a PSA error into a t_cose error for hashes.
324 *
325 * \param[in] status The PSA status.
326 *
327 * \return The \ref t_cose_err_t.
328 */
329 static enum t_cose_err_t
psa_status_to_t_cose_error_hash(psa_status_t status)330 psa_status_to_t_cose_error_hash(psa_status_t status)
331 {
332 /* Intentionally limited to just this minimum set of errors to
333 * save object code as hashes don't really fail much
334 */
335 return status == PSA_SUCCESS ? T_COSE_SUCCESS :
336 status == PSA_ERROR_NOT_SUPPORTED ? T_COSE_ERR_UNSUPPORTED_HASH :
337 status == PSA_ERROR_BUFFER_TOO_SMALL ? T_COSE_ERR_HASH_BUFFER_SIZE :
338 T_COSE_ERR_HASH_GENERAL_FAIL;
339 }
340
341
342 /*
343 * See documentation in t_cose_crypto.h
344 */
t_cose_crypto_hash_start(struct t_cose_crypto_hash * hash_ctx,int32_t cose_hash_alg_id)345 enum t_cose_err_t t_cose_crypto_hash_start(struct t_cose_crypto_hash *hash_ctx,
346 int32_t cose_hash_alg_id)
347 {
348 psa_algorithm_t psa_alg;
349
350 /* Map the algorithm ID */
351 psa_alg = cose_hash_alg_id_to_psa(cose_hash_alg_id);
352
353 /* initialize PSA hash context */
354 hash_ctx->ctx = psa_hash_operation_init();
355
356 /* Actually do the hash set up */
357 hash_ctx->status = psa_hash_setup(&(hash_ctx->ctx), psa_alg);
358
359 /* Map errors and return */
360 return psa_status_to_t_cose_error_hash((psa_status_t)hash_ctx->status);
361 }
362
363
364 /*
365 * See documentation in t_cose_crypto.h
366 */
t_cose_crypto_hash_update(struct t_cose_crypto_hash * hash_ctx,struct q_useful_buf_c data_to_hash)367 void t_cose_crypto_hash_update(struct t_cose_crypto_hash *hash_ctx,
368 struct q_useful_buf_c data_to_hash)
369 {
370 if(hash_ctx->status != PSA_SUCCESS) {
371 /* In error state. Nothing to do. */
372 return;
373 }
374
375 if(data_to_hash.ptr == NULL) {
376 /* This allows for NULL buffers to be passed in all the way at
377 * the top of signer or message creator when all that is
378 * happening is the size of the result is being computed.
379 */
380 return;
381 }
382
383 /* Actually hash the data */
384 hash_ctx->status = psa_hash_update(&(hash_ctx->ctx),
385 data_to_hash.ptr,
386 data_to_hash.len);
387 }
388
389
390 /*
391 * See documentation in t_cose_crypto.h
392 */
393 enum t_cose_err_t
t_cose_crypto_hash_finish(struct t_cose_crypto_hash * hash_ctx,struct q_useful_buf buffer_to_hold_result,struct q_useful_buf_c * hash_result)394 t_cose_crypto_hash_finish(struct t_cose_crypto_hash *hash_ctx,
395 struct q_useful_buf buffer_to_hold_result,
396 struct q_useful_buf_c *hash_result)
397 {
398 if(hash_ctx->status != PSA_SUCCESS) {
399 /* Error state. Nothing to do */
400 goto Done;
401 }
402
403 /* Actually finish up the hash */
404 hash_ctx->status = psa_hash_finish(&(hash_ctx->ctx),
405 buffer_to_hold_result.ptr,
406 buffer_to_hold_result.len,
407 &(hash_result->len));
408
409 hash_result->ptr = buffer_to_hold_result.ptr;
410
411 Done:
412 return psa_status_to_t_cose_error_hash(hash_ctx->status);
413 }
414 #endif /* !T_COSE_DISABLE_SHORT_CIRCUIT_SIGN || !T_COSE_DISABLE_SIGN1 */
415
416 #ifndef T_COSE_DISABLE_MAC0
417 /**
418 * \brief Convert COSE algorithm ID to a PSA HMAC algorithm ID
419 *
420 * \param[in] cose_hmac_alg_id The COSE-based ID for the
421 *
422 * \return PSA-based MAC algorithm ID, or a vendor flag in the case of error.
423 *
424 */
cose_hmac_alg_id_to_psa(int32_t cose_hmac_alg_id)425 static inline psa_algorithm_t cose_hmac_alg_id_to_psa(int32_t cose_hmac_alg_id)
426 {
427 switch(cose_hmac_alg_id) {
428 case T_COSE_ALGORITHM_HMAC256:
429 return PSA_ALG_HMAC(PSA_ALG_SHA_256);
430 case T_COSE_ALGORITHM_HMAC384:
431 return PSA_ALG_HMAC(PSA_ALG_SHA_384);
432 case T_COSE_ALGORITHM_HMAC512:
433 return PSA_ALG_HMAC(PSA_ALG_SHA_512);
434 default:
435 return PSA_ALG_VENDOR_FLAG;
436 }
437 }
438
439 /**
440 * \brief Map a PSA error into a t_cose error for HMAC.
441 *
442 * \param[in] status The PSA status.
443 *
444 * \return The \ref t_cose_err_t.
445 */
446 static enum t_cose_err_t
psa_status_to_t_cose_error_hmac(psa_status_t status)447 psa_status_to_t_cose_error_hmac(psa_status_t status)
448 {
449 /* Intentionally limited to just this minimum set of errors to
450 * save object code as hashes don't really fail much
451 */
452 return status == PSA_SUCCESS ? T_COSE_SUCCESS :
453 status == PSA_ERROR_NOT_SUPPORTED ? T_COSE_ERR_UNSUPPORTED_HASH :
454 status == PSA_ERROR_INVALID_ARGUMENT ? T_COSE_ERR_INVALID_ARGUMENT :
455 status == PSA_ERROR_INSUFFICIENT_MEMORY ? T_COSE_ERR_INSUFFICIENT_MEMORY :
456 status == PSA_ERROR_BUFFER_TOO_SMALL ? T_COSE_ERR_TOO_SMALL :
457 status == PSA_ERROR_INVALID_SIGNATURE ? T_COSE_ERR_SIG_VERIFY :
458 T_COSE_ERR_FAIL;
459 }
460
461 /*
462 * See documentation in t_cose_crypto.h
463 */
464 enum t_cose_err_t
t_cose_crypto_hmac_sign_setup(struct t_cose_crypto_hmac * hmac_ctx,struct t_cose_key signing_key,const int32_t cose_alg_id)465 t_cose_crypto_hmac_sign_setup(struct t_cose_crypto_hmac *hmac_ctx,
466 struct t_cose_key signing_key,
467 const int32_t cose_alg_id)
468 {
469 psa_algorithm_t psa_alg;
470 psa_status_t psa_ret;
471
472 if(!hmac_ctx) {
473 return T_COSE_ERR_INVALID_ARGUMENT;
474 }
475
476 /* Map the algorithm ID */
477 psa_alg = cose_hmac_alg_id_to_psa(cose_alg_id);
478 if(!PSA_ALG_IS_MAC(psa_alg)) {
479 return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
480 }
481
482 /*
483 * Verify if HMAC algorithm is valid.
484 * According to COSE (RFC 8152), only SHA-256, SHA-384 and SHA-512 are
485 * supported in COSE_Mac0 with HMAC.
486 */
487 if((psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_256)) && \
488 (psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_384)) && \
489 (psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_512))) {
490 return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
491 }
492
493 hmac_ctx->op_ctx = psa_mac_operation_init();
494
495 psa_ret = psa_mac_sign_setup(&hmac_ctx->op_ctx,
496 (psa_key_handle_t)signing_key.k.key_handle,
497 psa_alg);
498
499 return psa_status_to_t_cose_error_hmac(psa_ret);
500 }
501
502 /*
503 * See documentation in t_cose_crypto.h
504 */
505 enum t_cose_err_t
t_cose_crypto_hmac_update(struct t_cose_crypto_hmac * hmac_ctx,struct q_useful_buf_c payload)506 t_cose_crypto_hmac_update(struct t_cose_crypto_hmac *hmac_ctx,
507 struct q_useful_buf_c payload)
508 {
509 psa_status_t psa_ret;
510
511 if(!hmac_ctx) {
512 return T_COSE_ERR_INVALID_ARGUMENT;
513 }
514
515 psa_ret = psa_mac_update(&hmac_ctx->op_ctx,
516 payload.ptr, payload.len);
517
518 return psa_status_to_t_cose_error_hmac(psa_ret);
519 }
520
521 /*
522 * See documentation in t_cose_crypto.h
523 */
524 enum t_cose_err_t
t_cose_crypto_hmac_sign_finish(struct t_cose_crypto_hmac * hmac_ctx,struct q_useful_buf tag_buf,struct q_useful_buf_c * tag)525 t_cose_crypto_hmac_sign_finish(struct t_cose_crypto_hmac *hmac_ctx,
526 struct q_useful_buf tag_buf,
527 struct q_useful_buf_c *tag)
528 {
529 psa_status_t psa_ret;
530
531 if(!hmac_ctx) {
532 return T_COSE_ERR_INVALID_ARGUMENT;
533 }
534
535 psa_ret = psa_mac_sign_finish(&hmac_ctx->op_ctx,
536 tag_buf.ptr, tag_buf.len,
537 &(tag->len));
538 if(psa_ret == PSA_SUCCESS) {
539 tag->ptr = tag_buf.ptr;
540 }
541
542 return psa_status_to_t_cose_error_hmac(psa_ret);
543 }
544
545 /*
546 * See documentation in t_cose_crypto.h
547 */
548 enum t_cose_err_t
t_cose_crypto_hmac_verify_setup(struct t_cose_crypto_hmac * hmac_ctx,const int cose_alg_id,struct t_cose_key verify_key)549 t_cose_crypto_hmac_verify_setup(struct t_cose_crypto_hmac *hmac_ctx,
550 const int cose_alg_id,
551 struct t_cose_key verify_key)
552 {
553 psa_algorithm_t psa_alg;
554 psa_status_t psa_ret;
555
556 if(!hmac_ctx) {
557 return T_COSE_ERR_INVALID_ARGUMENT;
558 }
559
560 /* Map the algorithm ID */
561 psa_alg = cose_hmac_alg_id_to_psa(cose_alg_id);
562 if(!PSA_ALG_IS_MAC(psa_alg)) {
563 return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
564 }
565
566 /*
567 * Verify if HMAC algorithm is valid.
568 * According to COSE (RFC 8152), only SHA-256, SHA-384 and SHA-512 are
569 * supported in HMAC.
570 */
571 if((psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_256)) && \
572 (psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_384)) && \
573 (psa_alg != PSA_ALG_HMAC(PSA_ALG_SHA_512))) {
574 return T_COSE_ERR_UNSUPPORTED_SIGNING_ALG;
575 }
576
577 hmac_ctx->op_ctx = psa_mac_operation_init();
578
579 psa_ret = psa_mac_verify_setup(&hmac_ctx->op_ctx,
580 (psa_key_handle_t)verify_key.k.key_handle,
581 psa_alg);
582
583 return psa_status_to_t_cose_error_hmac(psa_ret);
584 }
585
586 /*
587 * See documentation in t_cose_crypto.h
588 */
589 enum t_cose_err_t
t_cose_crypto_hmac_verify_finish(struct t_cose_crypto_hmac * hmac_ctx,struct q_useful_buf_c tag)590 t_cose_crypto_hmac_verify_finish(struct t_cose_crypto_hmac *hmac_ctx,
591 struct q_useful_buf_c tag)
592 {
593 psa_status_t psa_ret;
594
595 if(!hmac_ctx) {
596 return T_COSE_ERR_INVALID_ARGUMENT;
597 }
598
599 psa_ret = psa_mac_verify_finish(&hmac_ctx->op_ctx, tag.ptr, tag.len);
600
601 return psa_status_to_t_cose_error_hmac(psa_ret);
602 }
603 #endif /* !T_COSE_DISABLE_MAC0 */
604