blob: 57c965d3b4c0235af51a5db13b104114aadfda06 [file] [log] [blame]
/*
* attest_symmetric_iat_decode.c
*
* Copyright (c) 2019, Laurence Lundblade.
* Copyright (c) 2020, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
* See BSD-3-Clause license in README.md
*/
#include "attest_token_decode.h"
#include "attest.h"
#include "psa/crypto.h"
#include "q_useful_buf.h"
#include "qcbor_util.h"
#include "t_cose_common.h"
#include "t_cose_mac0_verify.h"
#include "tfm_plat_crypto_keys.h"
/* Only support HMAC as MAC algorithm in COSE_Mac0 so far */
#define SYMMETRIC_IAK_MAX_SIZE PSA_MAC_MAX_SIZE
#if DOMAIN_NS == 1U
/*
* Public function. See attest_token_decode.h
* It is not allowed to let NS side fetch the symmetric IAK and perform the MAC
* verification.
*/
enum attest_token_err_t
attest_token_decode_validate_token(struct attest_token_decode_context *me,
struct q_useful_buf_c token)
{
enum t_cose_err_t t_cose_error;
enum attest_token_err_t return_value;
/* Decode only without signature verification */
int32_t t_cose_options = T_COSE_OPT_DECODE_ONLY;
struct t_cose_mac0_verify_ctx verify_ctx;
struct t_cose_key attest_key = T_COSE_NULL_KEY;
t_cose_mac0_verify_init(&verify_ctx, t_cose_options);
t_cose_mac0_set_verify_key(&verify_ctx, attest_key);
t_cose_error = t_cose_mac0_verify(&verify_ctx,
token, /* COSE to verify */
&me->payload, /* Payload from token */
NULL
);
return_value = map_t_cose_errors(t_cose_error);
me->last_error = return_value;
return return_value;
}
#else /* DOMAIN_NS == 1U */
/*
* \note The symmetric Initial Attestation key (IAK) will be fetched for
* authentication tag verification in secure test cases.
* Authentication tag verification in tests is for debug purpose only.
* Do not fetch the IAK outside attestation service in real products.
*/
static inline enum attest_token_err_t
decode_register_verify_key(psa_key_handle_t *verify_key_handle)
{
uint8_t key_buf[SYMMETRIC_IAK_MAX_SIZE];
psa_algorithm_t key_alg;
psa_key_handle_t key_handle;
size_t key_len;
enum tfm_plat_err_t plat_res;
psa_status_t psa_res;
psa_key_attributes_t key_attributes = PSA_KEY_ATTRIBUTES_INIT;
/* Get the symmetric initial attestation key for HMAC operation */
plat_res = tfm_plat_get_symmetric_iak(key_buf, sizeof(key_buf),
&key_len, &key_alg);
if (plat_res != TFM_PLAT_ERR_SUCCESS) {
return ATTEST_TOKEN_ERR_VERIFICATION_KEY;
}
/*
* Verify if HMAC algorithm is valid.
* According to COSE (RFC 8152), only SHA-256, SHA-384 and SHA-512 are
* supported in HMAC.
*/
if ((key_alg != PSA_ALG_HMAC(PSA_ALG_SHA_256)) && \
(key_alg != PSA_ALG_HMAC(PSA_ALG_SHA_384)) && \
(key_alg != PSA_ALG_HMAC(PSA_ALG_SHA_512))) {
return ATTEST_TOKEN_ERR_VERIFICATION_KEY;
}
/* Setup the key attributes */
psa_set_key_usage_flags(&key_attributes, PSA_KEY_USAGE_VERIFY);
psa_set_key_algorithm(&key_attributes, key_alg);
psa_set_key_type(&key_attributes, PSA_KEY_TYPE_HMAC);
/* Register the symmetric key to Crypto service */
psa_res = psa_import_key(&key_attributes, key_buf, key_len, &key_handle);
if (psa_res != PSA_SUCCESS) {
return ATTEST_TOKEN_ERR_VERIFICATION_KEY;
}
*verify_key_handle = key_handle;
return ATTEST_TOKEN_ERR_SUCCESS;
}
static inline enum attest_token_err_t
decode_unregister_verify_key(psa_key_handle_t verify_key_handle)
{
psa_status_t status;
status = psa_destroy_key(verify_key_handle);
if (status == PSA_SUCCESS) {
return ATTEST_TOKEN_ERR_SUCCESS;
}
return ATTEST_TOKEN_ERR_GENERAL;
}
/*
* Public function. See attest_token_decode.h
* Decode the received COSE_Mac0 structure and verify the tag.
*/
enum attest_token_err_t
attest_token_decode_validate_token(struct attest_token_decode_context *me,
struct q_useful_buf_c token)
{
enum t_cose_err_t t_cose_error;
enum attest_token_err_t return_value;
int32_t t_cose_options = 0;
struct t_cose_mac0_verify_ctx verify_ctx;
struct t_cose_key attest_key;
psa_key_handle_t key_handle;
return_value = decode_register_verify_key(&key_handle);
if (return_value != ATTEST_TOKEN_ERR_SUCCESS) {
return return_value;
}
if (me->options & TOKEN_OPT_SHORT_CIRCUIT_SIGN) {
t_cose_options |= T_COSE_OPT_ALLOW_SHORT_CIRCUIT;
}
t_cose_mac0_verify_init(&verify_ctx, t_cose_options);
attest_key.crypto_lib = T_COSE_CRYPTO_LIB_PSA;
attest_key.k.key_handle = (uint64_t)key_handle;
t_cose_mac0_set_verify_key(&verify_ctx, attest_key);
t_cose_error = t_cose_mac0_verify(&verify_ctx,
token, /* COSE to verify */
&me->payload, /* Payload from token */
NULL);
return_value = map_t_cose_errors(t_cose_error);
me->last_error = return_value;
decode_unregister_verify_key(key_handle);
return return_value;
}
#endif /* DOMAIN_NS == 1U */