| /* |
| * attest_token_decode.h |
| * |
| * 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 |
| */ |
| #ifndef __ATTEST_TOKEN_DECODE_H__ |
| #define __ATTEST_TOKEN_DECODE_H__ |
| |
| #include "q_useful_buf.h" |
| #include <stdbool.h> |
| #include "attest_token.h" |
| #include "attest_eat_defines.h" |
| |
| #ifdef __cplusplus |
| extern "C" { |
| #endif |
| |
| /** |
| * \file attest_token_decode.h |
| * |
| * \brief Attestation Token Decoding Interface |
| * |
| * The context and functions here are used to decode an attestation |
| * token as follows: |
| * |
| * -# Create a \ref attest_token_decode_context, most likely as a |
| * stack variable. |
| * |
| * -# Initialize it by calling attest_token_decode_init() |
| * |
| * -# Tell it which public key to use for verification using |
| * attest_token_decode_set_cose_pub_key() or |
| * attest_token_decode_set_pub_key_select(). |
| * |
| * -# Pass the token in and validate it by calling |
| * attest_token_decode_validate_token(). |
| * |
| * -# Call the various \c attest_token_get_xxx() methods in any |
| * order. The strings returned by the these functions will point into |
| * the token passed to attest_token_decode_validate_token(). A copy is |
| * NOT made. |
| * |
| * The entire token is validated and decoded in place. No copies are |
| * made internally. The data returned by the \c attest_token_get_xxx() |
| * methods is not a copy so the lifetime of the \c struct \c |
| * q_useful_buf_c containing the token must be maintained. |
| * |
| * Aside from the cryptographic functions, this allocates no |
| * memory. It works entirely off the stack. It makes use of t_cose to |
| * validate the signature and QCBOR for CBOR decoding. |
| * |
| * This decoder only works with labels (keys) that are integers even |
| * though labels can be any data type in CBOR. The presumption is that |
| * this is for small embedded use cases where space is a premium and |
| * only integer labels will be used. |
| * |
| * All claims are optional in tokens. This decoder will ignore all |
| * CBOR encoded data that it doesn't understand without error. |
| * |
| * This interface is primarily for the claims defined by Arm for |
| * TF-M. It includes only some of the claims from the EAT IETF draft, |
| * https://tools.ietf.org/html/draft-mandyam-eat-01. |
| * |
| * The claims are not described in detail here. That is left to the |
| * definition documents and eventually an IETF standard. |
| * |
| * If a method to get the claim you are interested in doesn't exist, |
| * there are several methods where you can give the label (the key) |
| * for the claim and have it returned. This only works for simple |
| * claims (strings and integers). |
| * |
| * The entire payload can be retrieved unparsed. Then you can use a |
| * separate CBOR parser to decode the claims out of it. Future work may |
| * include more general facilities for handling claims with complex |
| * structures made up of maps and arrays. |
| * |
| * This should not yet be considered a real commercial |
| * implementation of token decoding. It is |
| * close, but not there yet. It's purpose is to test |
| * token encoding. The main thing this needs to become |
| * a real commercial implementation is code that |
| * tests this. It is a parser / decoder, so a |
| * proper test involves a lot of hostile input. |
| */ |
| |
| |
| /** |
| * The context for decoding an attestation token. The caller of must |
| * create one of these and pass it to the functions here. It is small |
| * enough that it can go on the stack. It is most of the memory needed |
| * to create a token except the output buffer and any memory |
| * requirements for the cryptographic operations. |
| * |
| * The structure is opaque for the caller. |
| * |
| */ |
| struct attest_token_decode_context { |
| /* PRIVATE DATA STRUCTURE. USE ACCESSOR FUNCTIONS. */ |
| struct q_useful_buf_c payload; |
| uint32_t options; |
| enum attest_token_err_t last_error; |
| /* FIXME: This will have to expand when the pub key |
| handling functions are implemented */ |
| }; |
| |
| |
| /** |
| * \brief Initialize token decoder. |
| * |
| * \param[in] me The token decoder context to be initialized. |
| * \param[in] options Decoding options. |
| * |
| * Must be called on a \ref attest_token_decode_context before |
| * use. An instance of \ref attest_token_decode_context can |
| * be used again by calling this on it again. |
| **/ |
| void attest_token_decode_init(struct attest_token_decode_context *me, |
| uint32_t options); |
| |
| |
| |
| /** |
| * \brief Set specific public key to use for verification. |
| * |
| * \param[in] me The token decoder context to configure. |
| * \param[in] cose_pub_key A CBOR-encoded \c COSE_Key containing |
| * the public key to use for signature |
| * verification. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * (This has not been implemented yet) |
| * |
| * The key type must work with the signing algorithm in the token |
| * being verified. |
| * |
| * The \c kid in the \c COSE_Key must match the one in the token. |
| * |
| * If there is no kid in the \c COSE_Key it will be used no matter |
| * what kid is indicated in the token. |
| * |
| * Once set, a key can be used for multiple verifications. |
| * |
| * Calling this again will replace the previous key that was |
| * configured. It will also replace the key set by |
| * attest_token_decode_set_pub_key_select(). |
| */ |
| enum attest_token_err_t |
| attest_token_decode_set_cose_pub_key(struct attest_token_decode_context *me, |
| struct q_useful_buf cose_pub_key); |
| |
| |
| /** |
| * \brief Set specific public key to use for verification. |
| * |
| * \param[in] me The token decoder context to configure. |
| * \param[in] key_select Selects the key to verify. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * (This has not been implemented yet) |
| * |
| * The key type must work with the signing algorithm in the token |
| * being verified. |
| * |
| * The meaning of key_select depends on the platform this is running |
| * on. |
| * |
| * Once set, a key can be used for multiple verifications. |
| * |
| * Calling this again will replace the previous key that was |
| * configured. It will also replace the key set by |
| * attest_token_decode_set_cose_pub_key(). |
| * |
| */ |
| enum attest_token_err_t |
| attest_token_decode_set_pub_key_select(struct attest_token_decode_context *me, |
| int32_t key_select); |
| |
| |
| /** |
| * \brief Set the token to work on and validate its signature. |
| * |
| * \param[in] me The token decoder context to validate with. |
| * \param[in] token The CBOR-encoded token to validate and decode. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The signature on the token is validated. If it is successful the |
| * token and its payload is remembered in the \ref |
| * attest_token_decode_context \c me so the \c |
| * attest_token_decode_get_xxx() functions can be called to get the |
| * various claims out of it. |
| * |
| * Generally, a public key has to be configured for this to work. It |
| * can however validate short-circuit signatures even if one is not |
| * set. |
| * |
| * The code for any error that occurs during validation is remembered |
| * in decode context. The \c attest_token_decode_get_xxx() functions |
| * can be called and they will just return this error. The \c |
| * attest_token_decode_get_xxx() functions will generally return 0 or |
| * \c NULL if the token is in error. |
| * |
| * It is thus possible to call attest_token_decode_validate_token() |
| * and all the \c attest_token_decode_get_xxx() functions to parse the |
| * token and ignore the error codes as long as |
| * attest_token_decode_get_error() is called before any of the claim |
| * data returned is used. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_validate_token(struct attest_token_decode_context *me, |
| struct q_useful_buf_c token); |
| |
| |
| /** |
| * \brief Get the last decode error. |
| * |
| * \param[in] me The token decoder context. |
| * |
| * \return An error from \ref attest_token_err_t. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_error(struct attest_token_decode_context *me); |
| |
| |
| /** |
| * \brief Get undecoded CBOR payload from the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] payload The returned, verified token payload. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * This will return an error if the signature over the payload did not |
| * validate. |
| * |
| * This allows the caller to parse the payload with any CBOR decoder |
| * they wish to use. It also an "escape hatch" to get to claims in the |
| * token not supported by decoding in this implementation, for example |
| * claims that have non-integer labels. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_payload(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *payload); |
| |
| |
| /** Label for bits in \c item_flags in \ref |
| attest_token_iat_simple_t */ |
| enum attest_token_item_index_t { |
| NONCE_FLAG = 0, |
| UEID_FLAG = 1, |
| BOOT_SEED_FLAG = 2, |
| HW_VERSION_FLAG = 3, |
| IMPLEMENTATION_ID_FLAG = 4, |
| CLIENT_ID_FLAG = 5, |
| SECURITY_LIFECYCLE_FLAG = 6, |
| PROFILE_DEFINITION_FLAG = 7, |
| ORIGINATION_FLAG = 8, |
| NUMBER_OF_ITEMS = 9 |
| }; |
| |
| |
| /** |
| * This structure holds the simple-to-get fields from the |
| * token that can be bundled into one structure. |
| * |
| * This is 7 * 8 + 12 = 72 bytes on a 32-bit machine. |
| */ |
| struct attest_token_iat_simple_t { |
| struct q_useful_buf_c nonce; /* byte string */ |
| struct q_useful_buf_c ueid; /* byte string */ |
| struct q_useful_buf_c boot_seed; /* byte string */ |
| struct q_useful_buf_c hw_version; /* text string */ |
| struct q_useful_buf_c implementation_id; /* byte string */ |
| uint32_t security_lifecycle; |
| int32_t client_id; |
| struct q_useful_buf_c profile_definition; /* text string */ |
| struct q_useful_buf_c origination; /* text string */ |
| uint32_t item_flags; |
| }; |
| |
| |
| /** |
| * Macro to determine if data item is present in \ref |
| * attest_token_iat_simple_t |
| */ |
| #define IS_ITEM_FLAG_SET(item_index, item_flags) \ |
| (((0x01U << (item_index))) & (item_flags)) |
| |
| |
| /** |
| * \brief Batch fetch of all simple data items in a token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] items Structure into which all found items are placed. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_SUCCESS |
| * Indicates that the token was successfully searched. It |
| * could mean that all the data item were found, only |
| * some were found, or even none were found. |
| * |
| * This searches the token for the simple unstructured data items all |
| * at once. It can be a little more efficient than getting them one by |
| * one. |
| * |
| * Use \ref IS_ITEM_FLAG_SET on \c item_flags in \c |
| * attest_token_iat_simple_t to determine if the data item was found or |
| * not and whether the corresponding member in the structure is valid. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_iat_simple(struct attest_token_decode_context *me, |
| struct attest_token_iat_simple_t *items); |
| |
| |
| /** |
| \brief Get the nonce out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] nonce Returned pointer and length of nonce. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The nonce is a byte string. The nonce is also known as the |
| * challenge. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_nonce(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *nonce); |
| |
| |
| /** |
| * \brief Get the boot seed out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] boot_seed Returned pointer and length of boot_seed. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The boot seed is a byte string. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_boot_seed(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *boot_seed); |
| |
| |
| /** |
| * \brief Get the UEID out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] ueid Returned pointer and length of ueid. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The UEID is a byte string. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_ueid(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *ueid); |
| |
| |
| |
| /** |
| * \brief Get the HW Version out of the token |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] hw_version Returned pointer and length of |
| * \c hw_version. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * This is also known as the HW ID. |
| * |
| * The HW Version is a UTF-8 text string. It is returned as a pointer |
| * and length. It is NOT \c NULL terminated. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_hw_version(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *hw_version); |
| |
| |
| /** |
| * \brief Get the implementation ID out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] implementation_id Returned pointer and length of |
| * implementation_id. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The implementation ID is a byte string. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_implementation_id(struct attest_token_decode_context*me, |
| struct q_useful_buf_c *implementation_id); |
| |
| |
| /** |
| * \brief Get the origination out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] origination Returned pointer and length of origination. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * This is also known as the Verification Service Indicator. |
| * |
| * The \c origination is a UTF-8 text string. It is returned as a |
| * pointer* and length. It is NOT \c NULL terminated. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_origination(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *origination); |
| |
| |
| /** |
| * \brief Get the profile definition out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] profile_definition Returned pointer and length of |
| * profile_definition. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * The profile definition is a UTF-8 text string. It is returned as a |
| * pointer and length. It is NOT \c NULL terminated. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_profile_definition( |
| struct attest_token_decode_context *me, |
| struct q_useful_buf_c *profile_definition); |
| |
| |
| /** |
| * \brief Get the client ID out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] client_id Returned pointer and length of client_id. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_INTEGER_VALUE |
| * If integer is larger or smaller than will fit |
| * in an \c int32_t. |
| * |
| * Also called the caller ID. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_client_id(struct attest_token_decode_context *me, |
| int32_t *client_id); |
| |
| |
| /** |
| * \brief Get the security lifecycle out of the token. |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] lifecycle Returned pointer and length of lifecycle. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_INTEGER_VALUE |
| * If integer is larger |
| * or smaller than will fit in a \c uint32_t. |
| */ |
| static enum attest_token_err_t |
| attest_token_decode_get_security_lifecycle( |
| struct attest_token_decode_context *me, |
| uint32_t *lifecycle); |
| |
| |
| /** |
| * Use \ref IS_ITEM_FLAG_SET macro with these values and \c |
| * attest_token_sw_component_t.item_flags to find out if the |
| * data item is filled in in the attest_token_sw_component_t structure. |
| * |
| * Items that are of type \c struct \c q_useful_buf_c will also be \c |
| * NULL_Q_USEFUL_BUF_C when they are absent. |
| */ |
| enum attest_token_sw_index_t { |
| SW_MEASUREMENT_TYPE_FLAG = 0, |
| SW_MEASURMENT_VAL_FLAG = 1, |
| /* Reserved: 2 */ |
| SW_VERSION_FLAG = 3, |
| SW_SIGNER_ID_FLAG = 5, |
| SW_MEASUREMENT_DESC_FLAG = 6, |
| }; |
| |
| /** |
| * Structure to hold one SW component |
| * |
| * This is about 50 bytes on a 32-bit machine and 100 on a 64-bit |
| * machine. |
| * |
| * There will probably be an expanded version of this when more is |
| * added to describe a SW component. |
| */ |
| struct attest_token_sw_component_t { |
| struct q_useful_buf_c measurement_type; /* text string */ |
| struct q_useful_buf_c measurement_val; /* binary string */ |
| struct q_useful_buf_c version; /* text string */ |
| struct q_useful_buf_c signer_id; /* binary string */ |
| struct q_useful_buf_c measurement_desc; /* text string */ |
| uint32_t item_flags; |
| }; |
| |
| |
| /** |
| * \brief Get the number of SW components in the token |
| * |
| * \param[in] me The token decoder context. |
| * \param[out] num_sw_components The number of SW components in the |
| * token. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * If there are explicitly no SW components, this will return successfully |
| * and the \c num_sw_components will be zero. |
| * |
| * Per Arm's IAT specification the only two ways this will succeed |
| * are. |
| * - The SW components array is present and has one or more (not zero) |
| * SW components and the "no SW Components" claim is absent. |
| * - The "no SW Components" integer claim is present, its value |
| * is 1, and the SW Components array is absent. |
| */ |
| enum attest_token_err_t |
| attest_token_get_num_sw_components(struct attest_token_decode_context *me, |
| uint32_t *num_sw_components); |
| |
| |
| /** |
| * \brief Get the nth SW component. |
| * |
| * \param[in] me The token decoder context. |
| * \param[in] requested_index Index, from 0 to num_sw_components, |
| * of request component. |
| * \param[out] sw_components Place to return the details of the |
| * SW component |
| * |
| * \retval ATTEST_TOKEN_ERR_NOT_FOUND |
| * There were not \c requested_index in the token. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_TYPE |
| * The claim labeled to contain SW components is not an array. |
| */ |
| enum attest_token_err_t |
| attest_token_get_sw_component(struct attest_token_decode_context *me, |
| uint32_t requested_index, |
| struct attest_token_sw_component_t *sw_components); |
| |
| |
| /** |
| * |
| * \brief Get a top-level claim, by integer label that is a byte |
| * string. |
| * |
| * \param[in] me The token decoder context. |
| * \param[in] label The integer label identifying the claim. |
| * \param[out] claim The byte string or \c NULL_Q_USEFUL_BUF_C. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE |
| * General structure of the token is incorrect, for example |
| * the top level is not a map or some map wasn't closed. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED |
| * CBOR syntax is wrong and it is not decodable. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_TYPE |
| * Returned if the claim is not a byte string. |
| * |
| * \retval ATTEST_TOKEN_ERR_NOT_FOUND |
| * Data item for \c label was not found in token. |
| * |
| * If an error occurs, the claim will be set to \c NULL_Q_USEFUL_BUF_C |
| * and the error state inside \c attest_token_decode_context will |
| * be set. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_bstr(struct attest_token_decode_context *me, |
| int32_t label, |
| struct q_useful_buf_c *claim); |
| |
| |
| /** |
| * \brief Get a top-level claim, by integer label that is a text |
| * string. |
| * |
| * \param[in] me The token decoder context. |
| * \param[in] label The integer label identifying the claim. |
| * \param[out] claim The byte string or \c NULL_Q_USEFUL_BUF_C. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE |
| * General structure of the token is incorrect, for example |
| * the top level is not a map or some map wasn't closed. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED |
| * CBOR syntax is wrong and it is not decodable. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_TYPE |
| * Returned if the claim is not a byte string. |
| * |
| * \retval ATTEST_TOKEN_ERR_NOT_FOUND |
| * Data item for \c label was not found in token. |
| * |
| * Even though this is a text string, it is not NULL-terminated. |
| * |
| * If an error occurs, the claim will be set to \c NULL_Q_USEFUL_BUF_C |
| * and the error state inside \c attest_token_decode_context will |
| * be set. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_tstr(struct attest_token_decode_context *me, |
| int32_t label, |
| struct q_useful_buf_c *claim); |
| |
| |
| |
| /** |
| * \brief Get a top-level claim by integer label who's value is a |
| * signed integer |
| * |
| * \param[in] me The token decoder context. |
| * \param[in] label The integer label identifying the claim. |
| * \param[out] claim The signed integer or 0. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE |
| * General structure of the token is incorrect, for example |
| * the top level is not a map or some map wasn't closed. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED |
| * CBOR syntax is wrong and it is not decodable. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_TYPE |
| * Returned if the claim is not a byte string. |
| * |
| * \retval ATTEST_TOKEN_ERR_NOT_FOUND |
| * Data item for \c label was not found in token. |
| * |
| * \retval ATTEST_TOKEN_ERR_INTEGER_VALUE |
| * Returned if the integer value is larger |
| * than \c INT64_MAX. |
| * |
| * This will succeed if the CBOR type of the claim is either a |
| * positive or negative integer as long as the value is between \c |
| * INT64_MIN and \c INT64_MAX. |
| * |
| * See also attest_token_decode_get_uint(). |
| * |
| * If an error occurs the value 0 will be returned and the error |
| * inside the \c attest_token_decode_context will be set. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_int(struct attest_token_decode_context *me, |
| int32_t label, |
| int64_t *claim); |
| |
| |
| /** |
| * \brief Get a top-level claim by integer label who's value is an |
| * unsigned integer |
| * |
| * \param[in] me The token decoder context. |
| * \param[in] label The integer label identifying the claim. |
| * \param[out] claim The unsigned integer or 0. |
| * |
| * \return An error from \ref attest_token_err_t. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_STRUCTURE |
| * General structure of the token is incorrect, for example |
| * the top level is not a map or some map wasn't closed. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED |
| * CBOR syntax is wrong and it is not decodable. |
| * |
| * \retval ATTEST_TOKEN_ERR_CBOR_TYPE |
| * Returned if the claim is not a byte string. |
| * |
| * \retval ATTEST_TOKEN_ERR_NOT_FOUND |
| * Data item for \c label was not found in token. |
| * |
| * \retval ATTEST_TOKEN_ERR_INTEGER_VALUE |
| * Returned if the integer value is negative. |
| * |
| * This will succeed if the CBOR type of the claim is either a |
| * positive or negative integer as long as the value is between 0 and |
| * \c MAX_UINT64. |
| * |
| * See also attest_token_decode_get_int(). |
| * |
| * If an error occurs the value 0 will be returned and the error |
| * inside the \c attest_token_decode_context will be set. |
| */ |
| enum attest_token_err_t |
| attest_token_decode_get_uint(struct attest_token_decode_context *me, |
| int32_t label, |
| uint64_t *claim); |
| |
| |
| |
| |
| /* ==================================================================== |
| * Inline Implementations |
| * Typically, these are small and called only once. |
| * ==================================================================== */ |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_error(struct attest_token_decode_context *me) |
| { |
| return me->last_error; |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_nonce(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *nonce) |
| { |
| return attest_token_decode_get_bstr(me, |
| EAT_CBOR_ARM_LABEL_CHALLENGE, |
| nonce); |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_ueid(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *ueid) |
| { |
| return attest_token_decode_get_bstr(me, EAT_CBOR_ARM_LABEL_UEID, ueid); |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_boot_seed(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *boot_seed) |
| { |
| return attest_token_decode_get_bstr(me, |
| EAT_CBOR_ARM_LABEL_BOOT_SEED, |
| boot_seed); |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_hw_version(struct attest_token_decode_context *me, |
| struct q_useful_buf_c *hw_version) |
| { |
| return attest_token_decode_get_tstr(me, |
| EAT_CBOR_ARM_LABEL_HW_VERSION, |
| hw_version); |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_implementation_id( |
| struct attest_token_decode_context *me, |
| struct q_useful_buf_c*implementation_id) |
| { |
| return attest_token_decode_get_bstr(me, |
| EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID, |
| implementation_id); |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_client_id(struct attest_token_decode_context *me, |
| int32_t *caller_id) |
| { |
| enum attest_token_err_t return_value; |
| int64_t caller_id_64; |
| |
| return_value = attest_token_decode_get_int(me, |
| EAT_CBOR_ARM_LABEL_CLIENT_ID, |
| &caller_id_64); |
| if(return_value != ATTEST_TOKEN_ERR_SUCCESS) { |
| goto Done; |
| } |
| if(caller_id_64 > INT32_MAX || caller_id_64 < INT32_MIN) { |
| return_value = ATTEST_TOKEN_ERR_INTEGER_VALUE; |
| goto Done; |
| } |
| *caller_id = (int32_t)caller_id_64; |
| |
| Done: |
| return return_value; |
| } |
| |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_security_lifecycle( |
| struct attest_token_decode_context *me, |
| uint32_t *security_lifecycle) |
| { |
| enum attest_token_err_t return_value; |
| uint64_t security_lifecycle_64; |
| |
| return_value = attest_token_decode_get_uint(me, |
| EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE, |
| &security_lifecycle_64); |
| if(security_lifecycle_64 > UINT32_MAX) { |
| return_value = ATTEST_TOKEN_ERR_INTEGER_VALUE; |
| goto Done; |
| } |
| |
| *security_lifecycle = (uint32_t)security_lifecycle_64; |
| |
| Done: |
| return return_value; |
| } |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_profile_definition( |
| struct attest_token_decode_context *me, |
| struct q_useful_buf_c *profile_definition) |
| { |
| return attest_token_decode_get_tstr(me, |
| EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION, |
| profile_definition); |
| } |
| |
| static inline enum attest_token_err_t |
| attest_token_decode_get_origination(struct attest_token_decode_context*me, |
| struct q_useful_buf_c *origination) |
| { |
| return attest_token_decode_get_tstr(me, |
| EAT_CBOR_ARM_LABEL_ORIGINATION, |
| origination); |
| } |
| |
| /** |
| |
| \brief Map t_cose errors into attestation token errors |
| |
| \param[in] t_cose_error The t_cose error to map |
| |
| \return The attestation token error. |
| */ |
| static inline enum attest_token_err_t |
| map_t_cose_errors(enum t_cose_err_t t_cose_error) |
| { |
| switch (t_cose_error) { |
| case T_COSE_SUCCESS: |
| return ATTEST_TOKEN_ERR_SUCCESS; |
| break; |
| case T_COSE_ERR_UNSUPPORTED_SIGNING_ALG: |
| return ATTEST_TOKEN_ERR_UNSUPPORTED_SIG_ALG; |
| break; |
| case T_COSE_ERR_UNSUPPORTED_HASH: |
| return ATTEST_TOKEN_ERR_HASH_UNAVAILABLE; |
| break; |
| case T_COSE_ERR_CBOR_NOT_WELL_FORMED: |
| return ATTEST_TOKEN_ERR_CBOR_NOT_WELL_FORMED; |
| break; |
| case T_COSE_ERR_INSUFFICIENT_MEMORY: |
| return ATTEST_TOKEN_ERR_INSUFFICIENT_MEMORY; |
| break; |
| case T_COSE_ERR_TAMPERING_DETECTED: |
| return ATTEST_TOKEN_ERR_TAMPERING_DETECTED; |
| break; |
| case T_COSE_ERR_CBOR_FORMATTING: |
| return ATTEST_TOKEN_ERR_CBOR_FORMATTING; |
| break; |
| case T_COSE_ERR_TOO_SMALL: |
| return ATTEST_TOKEN_ERR_TOO_SMALL; |
| break; |
| |
| case T_COSE_ERR_PARAMETER_CBOR: |
| case T_COSE_ERR_NON_INTEGER_ALG_ID: |
| return ATTEST_TOKEN_ERR_CBOR_STRUCTURE; |
| break; |
| |
| case T_COSE_ERR_SIG_VERIFY: |
| case T_COSE_ERR_SHORT_CIRCUIT_SIG: |
| return ATTEST_TOKEN_ERR_COSE_VALIDATION; |
| break; |
| |
| case T_COSE_ERR_SIGN1_FORMAT: |
| return ATTEST_TOKEN_ERR_COSE_FORMAT; |
| break; |
| |
| case T_COSE_ERR_MAC0_FORMAT: |
| return ATTEST_TOKEN_ERR_COSE_FORMAT; |
| break; |
| |
| case T_COSE_ERR_NO_ALG_ID: |
| case T_COSE_ERR_NO_KID: |
| case T_COSE_ERR_BAD_SHORT_CIRCUIT_KID: |
| case T_COSE_ERR_SIG_STRUCT: |
| return ATTEST_TOKEN_ERR_COSE_FORMAT; |
| break; |
| |
| case T_COSE_ERR_UNKNOWN_KEY: |
| case T_COSE_ERR_WRONG_TYPE_OF_KEY: |
| return ATTEST_TOKEN_ERR_VERIFICATION_KEY; |
| break; |
| |
| case T_COSE_ERR_MAKING_PROTECTED: |
| case T_COSE_ERR_HASH_GENERAL_FAIL: |
| case T_COSE_ERR_HASH_BUFFER_SIZE: |
| case T_COSE_ERR_SIG_BUFFER_SIZE: |
| case T_COSE_ERR_INVALID_ARGUMENT: |
| case T_COSE_ERR_FAIL: |
| case T_COSE_ERR_SIG_FAIL: |
| case T_COSE_ERR_TOO_MANY_PARAMETERS: |
| case T_COSE_ERR_UNKNOWN_CRITICAL_PARAMETER: |
| case T_COSE_ERR_SHORT_CIRCUIT_SIG_DISABLED: |
| case T_COSE_ERR_INCORRECT_KEY_FOR_LIB: |
| case T_COSE_ERR_BAD_CONTENT_TYPE: |
| case T_COSE_ERR_INCORRECTLY_TAGGED: |
| case T_COSE_ERR_EMPTY_KEY: |
| case T_COSE_ERR_DUPLICATE_PARAMETER: |
| case T_COSE_ERR_PARAMETER_NOT_PROTECTED: |
| case T_COSE_ERR_CRIT_PARAMETER: |
| default: |
| return ATTEST_TOKEN_ERR_GENERAL; |
| } |
| } |
| |
| #ifdef __cplusplus |
| } |
| #endif |
| |
| |
| #endif /* __ATTEST_TOKEN_DECODE_H__ */ |