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