1 /*
2 * Copyright (c) 2018-2022, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include <stdint.h>
9 #include <string.h>
10 #include <stddef.h>
11 #include "psa/client.h"
12 #include "attest.h"
13 #include "attest_boot_data.h"
14 #include "attest_key.h"
15 #include "attest_token.h"
16 #include "config_tfm.h"
17 #include "tfm_plat_defs.h"
18 #include "tfm_plat_device_id.h"
19 #include "tfm_plat_boot_seed.h"
20 #include "tfm_attest_hal.h"
21 #include "tfm_attest_iat_defs.h"
22 #include "t_cose_common.h"
23 #include "tfm_crypto_defs.h"
24 #include "tfm_sp_log.h"
25
26 #define ARRAY_LENGTH(array) (sizeof(array) / sizeof(*(array)))
27
28 /*!
29 * \brief Static function to map return values between \ref psa_attest_err_t
30 * and \ref psa_status_t
31 *
32 * \param[in] attest_err Attestation error code
33 *
34 * \return Returns error code as specified in \ref psa_status_t
35 */
36 static inline psa_status_t
error_mapping_to_psa_status_t(enum psa_attest_err_t attest_err)37 error_mapping_to_psa_status_t(enum psa_attest_err_t attest_err)
38 {
39 switch (attest_err) {
40 case PSA_ATTEST_ERR_SUCCESS:
41 return PSA_SUCCESS;
42 break;
43 case PSA_ATTEST_ERR_INIT_FAILED:
44 return PSA_ERROR_SERVICE_FAILURE;
45 break;
46 case PSA_ATTEST_ERR_BUFFER_OVERFLOW:
47 return PSA_ERROR_BUFFER_TOO_SMALL;
48 break;
49 case PSA_ATTEST_ERR_CLAIM_UNAVAILABLE:
50 return PSA_ERROR_GENERIC_ERROR;
51 break;
52 case PSA_ATTEST_ERR_INVALID_INPUT:
53 return PSA_ERROR_INVALID_ARGUMENT;
54 break;
55 case PSA_ATTEST_ERR_GENERAL:
56 return PSA_ERROR_GENERIC_ERROR;
57 break;
58 default:
59 return PSA_ERROR_GENERIC_ERROR;
60 }
61 }
62
attest_init(void)63 psa_status_t attest_init(void)
64 {
65 enum psa_attest_err_t res;
66
67 res = attest_boot_data_init();
68
69 return error_mapping_to_psa_status_t(res);
70 }
71
72 /*!
73 * \brief Static function to map return values between \ref attest_token_err_t
74 * and \ref psa_attest_err_t
75 *
76 * \param[in] token_err Token encoding return value
77 *
78 * \return Returns error code as specified in \ref psa_attest_err_t
79 */
80 static inline enum psa_attest_err_t
error_mapping_to_psa_attest_err_t(enum attest_token_err_t token_err)81 error_mapping_to_psa_attest_err_t(enum attest_token_err_t token_err)
82 {
83 switch (token_err) {
84 case ATTEST_TOKEN_ERR_SUCCESS:
85 return PSA_ATTEST_ERR_SUCCESS;
86 break;
87 case ATTEST_TOKEN_ERR_TOO_SMALL:
88 return PSA_ATTEST_ERR_BUFFER_OVERFLOW;
89 break;
90 default:
91 return PSA_ATTEST_ERR_GENERAL;
92 }
93 }
94
95 /*!
96 * \brief Static function to add the claims of all SW components to the
97 * attestation token.
98 *
99 * \param[in] token_ctx Token encoding context
100 *
101 * \return Returns error code as specified in \ref psa_attest_err_t
102 */
103 static enum psa_attest_err_t
attest_add_all_sw_components(struct attest_token_encode_ctx * token_ctx)104 attest_add_all_sw_components(struct attest_token_encode_ctx *token_ctx)
105 {
106 QCBOREncodeContext *cbor_encode_ctx = NULL;
107 uint32_t component_cnt;
108 int32_t map_label = IAT_SW_COMPONENTS;
109 enum psa_attest_err_t err;
110
111 cbor_encode_ctx = attest_token_encode_borrow_cbor_cntxt(token_ctx);
112
113 err = attest_encode_sw_components_array(cbor_encode_ctx,
114 &map_label,
115 &component_cnt);
116 if (err != PSA_ATTEST_ERR_SUCCESS) {
117 return err;
118 }
119
120 if (component_cnt == 0) {
121 #if ATTEST_TOKEN_PROFILE_PSA_IOT_1
122 /* Allowed to not have SW components claim, but it must be indicated
123 * that this state is intentional. In this case, include the
124 * IAT_NO_SW_COMPONENTS claim with a fixed value.
125 */
126 attest_token_encode_add_integer(token_ctx,
127 IAT_NO_SW_COMPONENTS,
128 (int64_t)NO_SW_COMPONENT_FIXED_VALUE);
129 #else
130 /* Mandatory to have SW components claim in the token */
131 return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
132 #endif
133 }
134
135 return PSA_ATTEST_ERR_SUCCESS;
136 }
137
138 /*!
139 * \brief Static function to add implementation id claim to attestation token.
140 *
141 * \param[in] token_ctx Token encoding context
142 *
143 * \return Returns error code as specified in \ref psa_attest_err_t
144 */
145 static enum psa_attest_err_t
attest_add_implementation_id_claim(struct attest_token_encode_ctx * token_ctx)146 attest_add_implementation_id_claim(struct attest_token_encode_ctx *token_ctx)
147 {
148 uint8_t implementation_id[IMPLEMENTATION_ID_MAX_SIZE];
149 enum tfm_plat_err_t res_plat;
150 uint32_t size = sizeof(implementation_id);
151 struct q_useful_buf_c claim_value;
152
153 res_plat = tfm_plat_get_implementation_id(&size, implementation_id);
154 if (res_plat != TFM_PLAT_ERR_SUCCESS) {
155 return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
156 }
157
158 claim_value.ptr = implementation_id;
159 claim_value.len = size;
160 attest_token_encode_add_bstr(token_ctx,
161 IAT_IMPLEMENTATION_ID,
162 &claim_value);
163
164 return PSA_ATTEST_ERR_SUCCESS;
165 }
166
167 /*!
168 * \brief Static function to add instance id claim to attestation token.
169 *
170 * \param[in] token_ctx Token encoding context
171 *
172 * \note This mandatory claim represents the unique identifier of the instance.
173 * So far, only GUID type is supported.
174 *
175 * \return Returns error code as specified in \ref psa_attest_err_t
176 */
177 static enum psa_attest_err_t
attest_add_instance_id_claim(struct attest_token_encode_ctx * token_ctx)178 attest_add_instance_id_claim(struct attest_token_encode_ctx *token_ctx)
179 {
180 struct q_useful_buf_c claim_value;
181 enum psa_attest_err_t err;
182
183 /* Leave the first byte for UEID type byte */
184 err = attest_get_instance_id(&claim_value);
185 if (err != PSA_ATTEST_ERR_SUCCESS) {
186 return err;
187 }
188
189 attest_token_encode_add_bstr(token_ctx,
190 IAT_INSTANCE_ID,
191 &claim_value);
192
193 return PSA_ATTEST_ERR_SUCCESS;
194 }
195
196 /*!
197 * \brief Static function to add security lifecycle claim to attestation token.
198 *
199 * \param[in] token_ctx Token encoding context
200 *
201 * \return Returns error code as specified in \ref psa_attest_err_t
202 */
203 static enum psa_attest_err_t
attest_add_security_lifecycle_claim(struct attest_token_encode_ctx * token_ctx)204 attest_add_security_lifecycle_claim(struct attest_token_encode_ctx *token_ctx)
205 {
206 enum tfm_security_lifecycle_t security_lifecycle;
207
208 /* Use callback function to get it from runtime SW */
209 security_lifecycle = tfm_attest_hal_get_security_lifecycle();
210
211 /* Sanity check */
212 if (security_lifecycle > TFM_SLC_MAX_VALUE) {
213 return PSA_ATTEST_ERR_GENERAL;
214 }
215
216 attest_token_encode_add_integer(token_ctx,
217 IAT_SECURITY_LIFECYCLE,
218 (int64_t)security_lifecycle);
219
220 return PSA_ATTEST_ERR_SUCCESS;
221 }
222
223 /*!
224 * \brief Static function to add the name of the profile definition document
225 *
226 * \note This function would be optional for PSA IoT 1/2 profiles but we keep it
227 * as mandatory for both CCA and PSA IoT for simplicity
228 *
229 * \param[in] token_ctx Token encoding context
230 *
231 * \return Returns error code as specified in \ref psa_attest_err_t
232 */
233 static enum psa_attest_err_t
attest_add_profile_definition(struct attest_token_encode_ctx * token_ctx)234 attest_add_profile_definition(struct attest_token_encode_ctx *token_ctx)
235 {
236 struct q_useful_buf_c profile;
237 uint8_t buf[PROFILE_DEFINITION_MAX_SIZE];
238 uint32_t size = sizeof(buf);
239 enum tfm_plat_err_t err;
240
241 err = tfm_attest_hal_get_profile_definition(&size, buf);
242 if (err != TFM_PLAT_ERR_SUCCESS) {
243 return PSA_ATTEST_ERR_GENERAL;
244 }
245
246 profile.ptr = &buf;
247 profile.len = size;
248 attest_token_encode_add_tstr(token_ctx,
249 IAT_PROFILE_DEFINITION,
250 &profile);
251
252 return PSA_ATTEST_ERR_SUCCESS;
253 }
254
255 #if ATTEST_INCLUDE_OPTIONAL_CLAIMS
256 /*!
257 * \brief Static function to add the verification service indicator claim
258 * to the attestation token.
259 *
260 * \param[in] token_ctx Token encoding context
261 *
262 * \return Returns error code as specified in \ref psa_attest_err_t
263 */
264 static enum psa_attest_err_t
attest_add_verification_service(struct attest_token_encode_ctx * token_ctx)265 attest_add_verification_service(struct attest_token_encode_ctx *token_ctx)
266 {
267 struct q_useful_buf_c service;
268 uint8_t buf[VERIFICATION_URL_MAX_SIZE];
269 uint32_t size = sizeof(buf);
270 enum tfm_plat_err_t err;
271
272 err = tfm_attest_hal_get_verification_service(&size, buf);
273 if (err != TFM_PLAT_ERR_SUCCESS) {
274 return PSA_ATTEST_ERR_GENERAL;
275 }
276
277 service.ptr = &buf;
278 service.len = size;
279 attest_token_encode_add_tstr(token_ctx,
280 IAT_VERIFICATION_SERVICE,
281 &service);
282
283 return PSA_ATTEST_ERR_SUCCESS;
284 }
285 #endif /* ATTEST_INCLUDE_OPTIONAL_CLAIMS */
286
287 #if ATTEST_TOKEN_PROFILE_PSA_IOT_1 || ATTEST_TOKEN_PROFILE_PSA_2_0_0
288 /*!
289 * \brief Static function to add boot seed claim to attestation token.
290 *
291 * \param[in] token_ctx Token encoding context
292 *
293 * \return Returns error code as specified in \ref psa_attest_err_t
294 */
295 static enum psa_attest_err_t
attest_add_boot_seed_claim(struct attest_token_encode_ctx * token_ctx)296 attest_add_boot_seed_claim(struct attest_token_encode_ctx *token_ctx)
297 {
298 uint8_t boot_seed[BOOT_SEED_SIZE];
299 enum tfm_plat_err_t res;
300 struct q_useful_buf_c claim_value = {0};
301
302 /* Use callback function to get it from runtime SW */
303 res = tfm_plat_get_boot_seed(sizeof(boot_seed), boot_seed);
304 if (res != TFM_PLAT_ERR_SUCCESS) {
305 return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
306 }
307 claim_value.ptr = boot_seed;
308 claim_value.len = BOOT_SEED_SIZE;
309
310 attest_token_encode_add_bstr(token_ctx,
311 IAT_BOOT_SEED,
312 &claim_value);
313
314 return PSA_ATTEST_ERR_SUCCESS;
315 }
316
317 /*!
318 * \brief Static function to add caller id claim to attestation token.
319 *
320 * \param[in] token_ctx Token encoding context
321 *
322 * \return Returns error code as specified in \ref psa_attest_err_t
323 */
324 static enum psa_attest_err_t
attest_add_caller_id_claim(struct attest_token_encode_ctx * token_ctx)325 attest_add_caller_id_claim(struct attest_token_encode_ctx *token_ctx)
326 {
327 enum psa_attest_err_t res;
328 int32_t caller_id;
329
330 res = attest_get_caller_client_id(&caller_id);
331 if (res != PSA_ATTEST_ERR_SUCCESS) {
332 return res;
333 }
334
335 attest_token_encode_add_integer(token_ctx,
336 IAT_CLIENT_ID,
337 (int64_t)caller_id);
338
339 return PSA_ATTEST_ERR_SUCCESS;
340 }
341
342 #if ATTEST_INCLUDE_OPTIONAL_CLAIMS
343 /*!
344 * \brief Static function to add certification reference claim to attestation
345 * token.
346 *
347 * \param[in] token_ctx Token encoding context
348 *
349 * \return Returns error code as specified in \ref psa_attest_err_t
350 */
351 static enum psa_attest_err_t
attest_add_cert_ref_claim(struct attest_token_encode_ctx * token_ctx)352 attest_add_cert_ref_claim(struct attest_token_encode_ctx *token_ctx)
353 {
354 uint8_t buf[CERTIFICATION_REF_MAX_SIZE];
355 enum tfm_plat_err_t res_plat;
356 uint32_t size = sizeof(buf);
357 struct q_useful_buf_c claim_value = {0};
358
359 /* Use callback function to get it from runtime SW */
360 res_plat = tfm_plat_get_cert_ref(&size, buf);
361 if (res_plat != TFM_PLAT_ERR_SUCCESS) {
362 return PSA_ATTEST_ERR_CLAIM_UNAVAILABLE;
363 }
364 claim_value.ptr = buf;
365 claim_value.len = size;
366
367 attest_token_encode_add_tstr(token_ctx,
368 IAT_CERTIFICATION_REFERENCE,
369 &claim_value);
370
371 return PSA_ATTEST_ERR_SUCCESS;
372 }
373 #endif /* ATTEST_INCLUDE_OPTIONAL_CLAIMS */
374 #endif /* ATTEST_TOKEN_PROFILE_PSA_IOT_1 || ATTEST_TOKEN_PROFILE_PSA_2_0_0 */
375
376 #if ATTEST_TOKEN_PROFILE_ARM_CCA
377 /*!
378 * \brief Static function to add the platform hash algorithm identifier
379 * claim to the attestation token. This hash algo is used for extending
380 * the boot measurements.
381 *
382 * \param[in] token_ctx Token encoding context
383 * \param[in] challenge Pointer to buffer which stores the hash algo.
384 *
385 * \return Returns error code as specified in \ref psa_attest_err_t
386 */
387 static enum psa_attest_err_t
attest_add_hash_algo_claim(struct attest_token_encode_ctx * token_ctx)388 attest_add_hash_algo_claim(struct attest_token_encode_ctx *token_ctx)
389 {
390 struct q_useful_buf_c hash_algo;
391 uint8_t buf[PLATFORM_HASH_ALGO_ID_MAX_SIZE];
392 uint32_t size = sizeof(buf);
393 enum tfm_plat_err_t err;
394
395 err = tfm_attest_hal_get_platform_hash_algo(&size, buf);
396 if (err != TFM_PLAT_ERR_SUCCESS) {
397 return PSA_ATTEST_ERR_GENERAL;
398 }
399
400 hash_algo.ptr = &buf;
401 hash_algo.len = size;
402 attest_token_encode_add_tstr(token_ctx,
403 IAT_PLATFORM_HASH_ALGO_ID,
404 &hash_algo);
405
406 return PSA_ATTEST_ERR_SUCCESS;
407 }
408
409 /*!
410 * \brief Static function to add the platform hash algorithm identifier
411 * claim to the attestation token. This hash algo is used for extending
412 * the boot measurements.
413 *
414 * \param[in] token_ctx Token encoding context
415 * \param[in] challenge Pointer to buffer which stores the hash algo.
416 *
417 * \return Returns error code as specified in \ref psa_attest_err_t
418 */
419 static enum psa_attest_err_t
attest_add_platform_config_claim(struct attest_token_encode_ctx * token_ctx)420 attest_add_platform_config_claim(struct attest_token_encode_ctx *token_ctx)
421 {
422
423 uint8_t plat_config[PLATFORM_CONFIG_MAX_SIZE];
424 enum tfm_plat_err_t res;
425 uint32_t size = sizeof(plat_config);
426 struct q_useful_buf_c claim_value;
427
428 res = tfm_attest_hal_get_platform_config(&size, plat_config);
429 if (res != TFM_PLAT_ERR_SUCCESS) {
430 return PSA_ATTEST_ERR_GENERAL;
431 }
432
433 claim_value.ptr = plat_config;
434 claim_value.len = size;
435
436 attest_token_encode_add_bstr(token_ctx,
437 IAT_PLATFORM_CONFIG,
438 &claim_value);
439
440 return PSA_ATTEST_ERR_SUCCESS;
441 }
442 #endif /* ATTEST_TOKEN_PROFILE_ARM_CCA */
443
444 /*!
445 * \brief Static function to add the nonce claim to attestation token.
446 *
447 * \param[in] token_ctx Token encoding context
448 * \param[in] nonce Pointer to buffer which stores the challenge
449 *
450 * \return Returns error code as specified in \ref psa_attest_err_t
451 */
452 static enum psa_attest_err_t
attest_add_nonce_claim(struct attest_token_encode_ctx * token_ctx,const struct q_useful_buf_c * nonce)453 attest_add_nonce_claim(struct attest_token_encode_ctx *token_ctx,
454 const struct q_useful_buf_c *nonce)
455 {
456 attest_token_encode_add_bstr(token_ctx,
457 IAT_NONCE,
458 nonce);
459
460 return PSA_ATTEST_ERR_SUCCESS;
461 }
462
463 /*!
464 * \brief Static function to verify the input challenge size
465 *
466 * Only discrete sizes are accepted.
467 *
468 * \param[in] challenge_size Size of challenge object in bytes.
469 *
470 * \retval PSA_ATTEST_ERR_SUCCESS
471 * \retval PSA_ATTEST_ERR_INVALID_INPUT
472 */
attest_verify_challenge_size(size_t challenge_size)473 static enum psa_attest_err_t attest_verify_challenge_size(size_t challenge_size)
474 {
475 switch (challenge_size) {
476 /* Intentional fall through */
477 case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_32:
478 case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_48:
479 case PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64:
480 return PSA_ATTEST_ERR_SUCCESS;
481 }
482
483 return PSA_ATTEST_ERR_INVALID_INPUT;
484 }
485
486 #ifdef INCLUDE_TEST_CODE
487 /*!
488 * \brief Static function to get the option flags from challenge object
489 *
490 * Option flags are passed in if the challenge is 64 bytes long and the last
491 * 60 bytes are all 0. In this case the first 4 bytes of the challenge is
492 * the option flags for test.
493 *
494 * See flag definition in attest_token.h
495 *
496 * \param[in] challenge Structure to carry the challenge value:
497 * pointer + challeng's length.
498 * \param[out] option_flags Flags to select different custom options,
499 * for example \ref TOKEN_OPT_OMIT_CLAIMS.
500 * \param[out] key_select Selects which attestation key to sign with.
501 */
attest_get_option_flags(struct q_useful_buf_c * challenge,uint32_t * option_flags,int32_t * key_select)502 static void attest_get_option_flags(struct q_useful_buf_c *challenge,
503 uint32_t *option_flags,
504 int32_t *key_select)
505 {
506 uint32_t found_option_flags = 1;
507 uint32_t option_flags_size = sizeof(uint32_t);
508 uint8_t *challenge_end;
509 uint8_t *challenge_data;
510
511 /* Get option flags if there is encoded in the challenge object */
512 if ((challenge->len == PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64) &&
513 (challenge->ptr)) {
514 challenge_end = ((uint8_t *)challenge->ptr) + challenge->len;
515 challenge_data = ((uint8_t *)challenge->ptr) + option_flags_size;
516
517 /* Compare bytes(4-63) with 0 */
518 while (challenge_data < challenge_end) {
519 if (*challenge_data++ != 0) {
520 found_option_flags = 0;
521 break;
522 }
523 }
524 } else {
525 found_option_flags = 0;
526 }
527
528 if (found_option_flags) {
529 (void)memcpy(option_flags, challenge->ptr, option_flags_size);
530
531 /* Lower three bits are the key select */
532 *key_select = *option_flags & 0x7;
533 } else {
534 *option_flags = 0;
535 *key_select = 0;
536 }
537 }
538 #endif /* INCLUDE_TEST_CODE */
539
attest_get_t_cose_algorithm(int32_t * cose_algorithm_id)540 static enum psa_attest_err_t attest_get_t_cose_algorithm(
541 int32_t *cose_algorithm_id)
542 {
543 psa_status_t status;
544 psa_key_attributes_t attr;
545 psa_key_handle_t handle = TFM_BUILTIN_KEY_ID_IAK;
546 psa_key_type_t key_type;
547
548 status = psa_get_key_attributes(handle, &attr);
549 if (status != PSA_SUCCESS) {
550 return PSA_ATTEST_ERR_GENERAL;
551 }
552
553 key_type = psa_get_key_type(&attr);
554 if (status != PSA_SUCCESS) {
555 return PSA_ATTEST_ERR_GENERAL;
556 }
557
558 if (PSA_KEY_TYPE_IS_ECC(key_type) &&
559 PSA_KEY_TYPE_ECC_GET_FAMILY(key_type) == PSA_ECC_FAMILY_SECP_R1) {
560 switch (psa_get_key_bits(&attr)) {
561 case 256:
562 *cose_algorithm_id = T_COSE_ALGORITHM_ES256;
563 break;
564 case 384:
565 *cose_algorithm_id = T_COSE_ALGORITHM_ES384;
566 break;
567 case 512:
568 *cose_algorithm_id = T_COSE_ALGORITHM_ES512;
569 break;
570 default:
571 return PSA_ATTEST_ERR_GENERAL;
572 }
573 } else if (key_type == PSA_KEY_TYPE_HMAC) {
574 switch (psa_get_key_bits(&attr)) {
575 case 256:
576 *cose_algorithm_id = T_COSE_ALGORITHM_HMAC256;
577 break;
578 case 384:
579 *cose_algorithm_id = T_COSE_ALGORITHM_HMAC384;
580 break;
581 case 512:
582 *cose_algorithm_id = T_COSE_ALGORITHM_HMAC512;
583 break;
584 default:
585 return PSA_ATTEST_ERR_GENERAL;
586 }
587 } else {
588 LOG_DBGFMT("Attestation: Unexpected key_type for TFM_BUILTIN_KEY_ID_IAK. Key storage may be corrupted!\r\n");
589 return PSA_ATTEST_ERR_GENERAL;
590 }
591
592 return PSA_ATTEST_ERR_SUCCESS;
593 }
594
595 #if ATTEST_TOKEN_PROFILE_PSA_IOT_1 || ATTEST_TOKEN_PROFILE_PSA_2_0_0
596 static enum psa_attest_err_t
597 (*claim_query_funcs[])(struct attest_token_encode_ctx *) = {
598 &attest_add_boot_seed_claim,
599 &attest_add_instance_id_claim,
600 &attest_add_implementation_id_claim,
601 &attest_add_caller_id_claim,
602 &attest_add_security_lifecycle_claim,
603 &attest_add_all_sw_components,
604 &attest_add_profile_definition,
605 #if ATTEST_INCLUDE_OPTIONAL_CLAIMS
606 &attest_add_verification_service,
607 &attest_add_cert_ref_claim
608 #endif
609 };
610 #elif ATTEST_TOKEN_PROFILE_ARM_CCA
611
612 static enum psa_attest_err_t
613 (*claim_query_funcs[])(struct attest_token_encode_ctx *) = {
614 &attest_add_instance_id_claim,
615 &attest_add_implementation_id_claim,
616 &attest_add_security_lifecycle_claim,
617 &attest_add_all_sw_components,
618 &attest_add_profile_definition,
619 &attest_add_hash_algo_claim,
620 &attest_add_platform_config_claim,
621 #if ATTEST_INCLUDE_OPTIONAL_CLAIMS
622 &attest_add_verification_service,
623 #endif
624 };
625 #endif
626
627 /*!
628 * \brief Static function to create the initial attestation token
629 *
630 * \param[in] challenge Structure to carry the challenge value:
631 * pointer + challeng's length
632 * \param[in] token Structure to carry the token info, where to
633 * create it: pointer + buffer's length
634 * \param[out] completed_token Structure to carry the info about the created
635 * token: pointer + final token's length
636 *
637 * \return Returns error code as specified in \ref psa_attest_err_t
638 */
639 static enum psa_attest_err_t
attest_create_token(struct q_useful_buf_c * challenge,struct q_useful_buf * token,struct q_useful_buf_c * completed_token)640 attest_create_token(struct q_useful_buf_c *challenge,
641 struct q_useful_buf *token,
642 struct q_useful_buf_c *completed_token)
643 {
644 enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
645 enum attest_token_err_t token_err;
646 struct attest_token_encode_ctx attest_token_ctx;
647 int32_t key_select = 0;
648 uint32_t option_flags = 0;
649 int i;
650 int32_t cose_algorithm_id;
651
652 attest_err = attest_get_t_cose_algorithm(&cose_algorithm_id);
653 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
654 return attest_err;
655 }
656
657 #ifdef INCLUDE_TEST_CODE
658 attest_get_option_flags(challenge, &option_flags, &key_select);
659 if (option_flags) {
660 /* If any option flags are provided (TOKEN_OPT_OMIT_CLAIMS or
661 * TOKEN_OPT_SHORT_CIRCUIT_SIGN) then force the cose_algorithm_id
662 * to be either:
663 * - T_COSE_ALGORITHM_ES256 or (SYMMETRIC_INITIAL_ATTESTATION=OFF)
664 * - T_COSE_ALGORITHM_HMAC256 (SYMMETRIC_INITIAL_ATTESTATION=ON)
665 * for testing purposes to match with expected minimal token.
666 */
667 /* ESxxx range is smaller than 0; HMACxxx range is greater than 0 */
668 cose_algorithm_id = cose_algorithm_id < 0 ? T_COSE_ALGORITHM_ES256 :
669 T_COSE_ALGORITHM_HMAC256;
670 }
671 #endif
672
673 /* Get started creating the token. This sets up the CBOR and COSE contexts
674 * which causes the COSE headers to be constructed.
675 */
676 token_err = attest_token_encode_start(&attest_token_ctx,
677 option_flags, /* option_flags */
678 key_select, /* key_select */
679 cose_algorithm_id, /* alg_select */
680 token);
681
682 if (token_err != ATTEST_TOKEN_ERR_SUCCESS) {
683 attest_err = error_mapping_to_psa_attest_err_t(token_err);
684 goto error;
685 }
686
687 attest_err = attest_add_nonce_claim(&attest_token_ctx,
688 challenge);
689 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
690 goto error;
691 }
692
693 if (!(option_flags & TOKEN_OPT_OMIT_CLAIMS)) {
694 for (i = 0; i < ARRAY_LENGTH(claim_query_funcs); ++i) {
695 /* Calling the attest_add_XXX_claim functions */
696 attest_err = claim_query_funcs[i](&attest_token_ctx);
697 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
698 goto error;
699 }
700 }
701 }
702
703 /* Finish up creating the token. This is where the actual signature
704 * is generated. This finishes up the CBOR encoding too.
705 */
706 token_err = attest_token_encode_finish(&attest_token_ctx, completed_token);
707 attest_err = error_mapping_to_psa_attest_err_t(token_err);
708
709 error:
710 return attest_err;
711 }
712
713 psa_status_t
initial_attest_get_token(const void * challenge_buf,size_t challenge_size,void * token_buf,size_t token_buf_size,size_t * token_size)714 initial_attest_get_token(const void *challenge_buf, size_t challenge_size,
715 void *token_buf, size_t token_buf_size,
716 size_t *token_size)
717 {
718 enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
719 struct q_useful_buf_c challenge;
720 struct q_useful_buf token;
721 struct q_useful_buf_c completed_token;
722
723 challenge.ptr = challenge_buf;
724 challenge.len = challenge_size;
725 token.ptr = token_buf;
726 token.len = token_buf_size;
727
728 attest_err = attest_verify_challenge_size(challenge.len);
729 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
730 goto error;
731 }
732
733 if (token.len == 0) {
734 attest_err = PSA_ATTEST_ERR_INVALID_INPUT;
735 goto error;
736 }
737
738 attest_err = attest_create_token(&challenge, &token, &completed_token);
739 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
740 goto error;
741 }
742
743 *token_size = completed_token.len;
744
745 error:
746 return error_mapping_to_psa_status_t(attest_err);
747 }
748
749 psa_status_t
initial_attest_get_token_size(const size_t challenge_size,size_t * token_size)750 initial_attest_get_token_size(const size_t challenge_size,
751 size_t *token_size)
752 {
753 enum psa_attest_err_t attest_err = PSA_ATTEST_ERR_SUCCESS;
754 struct q_useful_buf_c challenge;
755 struct q_useful_buf token;
756 struct q_useful_buf_c completed_token;
757
758 /* Only the size of the challenge is needed */
759 challenge.ptr = NULL;
760 challenge.len = challenge_size;
761
762 /* Special value to get the size of the token, but token is not created */
763 token.ptr = NULL;
764 token.len = INT32_MAX;
765
766 attest_err = attest_verify_challenge_size(challenge_size);
767 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
768 goto error;
769 }
770
771 attest_err = attest_create_token(&challenge, &token, &completed_token);
772 if (attest_err != PSA_ATTEST_ERR_SUCCESS) {
773 goto error;
774 }
775
776 *token_size = completed_token.len;
777
778 error:
779 return error_mapping_to_psa_status_t(attest_err);
780 }
781