Dev APIs: Updating the testsuite with enhancements and fixes

- Attest: Move token verification from PAL to VAL layer
- Attest: Support to obtain public key from platform
- Crypto: Bug fixes and resolving stack overflow issues
- Crypto: HKDF does not take a LABEL or SEED input
- Attest: Utilizing token size buffer from PSA spec
- Attest: Key ID not mandatory in attestation token

Signed-off-by: Gowtham Siddarth <gowtham.siddarth@arm.com>
diff --git a/api-tests/val/nspe/val_attestation.c b/api-tests/val/nspe/val_attestation.c
index 82d7191..50e400a 100644
--- a/api-tests/val/nspe/val_attestation.c
+++ b/api-tests/val/nspe/val_attestation.c
@@ -21,24 +21,415 @@
 #include "val_client_defs.h"
 #include "val_attestation.h"
 
+#ifdef INITIAL_ATTESTATION
+
+uint32_t    mandatory_claims = 0;
+uint32_t    mandaroty_sw_components = 0;
+bool_t      sw_component_present = 0;
+
+static int get_items_in_map(QCBORDecodeContext *decode_context,
+                            struct items_to_get_t *item_list)
+{
+    int                     item_index;
+    QCBORItem               item;
+    struct items_to_get_t  *item_ptr = item_list;
+
+    /* initialize the data type of all items in the list */
+    while (item_ptr->label != 0)
+    {
+        item_ptr->item.uDataType = QCBOR_TYPE_NONE;
+        item_ptr++;
+    }
+
+    QCBORDecode_GetNext(decode_context, &item);
+    if (item.uDataType != QCBOR_TYPE_MAP)
+    {
+        return VAL_ATTEST_ERROR;
+    }
+
+    for (item_index = item.val.uCount; item_index != 0; item_index--)
+    {
+        if (QCBORDecode_GetNext(decode_context, &item) != QCBOR_SUCCESS)
+        {
+            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+        }
+        if (item.uLabelType != QCBOR_TYPE_INT64)
+        {
+            continue;
+        }
+
+        item_ptr = item_list;
+        while (item_ptr->label != 0)
+        {
+            if (item.label.int64 == item_ptr->label)
+            {
+                item_ptr->item = item;
+            }
+            item_ptr++;
+        }
+    }
+
+    return VAL_ATTEST_SUCCESS;
+}
+
+static int get_item_in_map(QCBORDecodeContext *decode_context,
+                           int32_t label,
+                           QCBORItem *item)
+{
+    struct items_to_get_t   item_list[2];
+
+    item_list[0].label = label;
+    item_list[1].label = 0;
+
+    if (get_items_in_map(decode_context, item_list))
+    {
+        return VAL_ATTEST_ERROR;
+    }
+
+    if (item_list[0].item.uDataType == QCBOR_TYPE_NONE)
+    {
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+    }
+
+    *item = item_list[0].item;
+
+    return VAL_ATTEST_SUCCESS;
+}
+
+static int parse_unprotected_headers(QCBORDecodeContext *decode_context,
+                                     struct q_useful_buf_c *child)
+{
+    struct items_to_get_t   item_list[3];
+
+    item_list[0].label = COSE_HEADER_PARAM_KID;
+    item_list[1].label = 0;
+
+    if (get_items_in_map(decode_context, item_list))
+    {
+        return VAL_ATTEST_ERR_CBOR_STRUCTURE;
+    }
+
+    return VAL_ATTEST_SUCCESS;
+}
+
+static int parse_protected_headers(struct q_useful_buf_c protected_headers,
+                                   int32_t *alg_id)
+{
+    QCBORDecodeContext  decode_context;
+    QCBORItem           item;
+
+    QCBORDecode_Init(&decode_context, protected_headers, 0);
+
+    if (get_item_in_map(&decode_context, COSE_HEADER_PARAM_ALG, &item))
+    {
+        return VAL_ATTEST_ERROR;
+    }
+
+    if (QCBORDecode_Finish(&decode_context))
+    {
+        return VAL_ATTEST_ERROR;
+    }
+
+    if ((item.uDataType != QCBOR_TYPE_INT64) || (item.val.int64 > INT32_MAX))
+    {
+        return VAL_ATTEST_ERROR;
+    }
+
+    *alg_id = (int32_t)item.val.int64;
+
+    return VAL_ATTEST_SUCCESS;
+}
+
+/**
+    @brief    - This API will verify the claims
+    @param    - decode_context      : The buffer containing the challenge
+                item                : context for decoding the data items
+                completed_challenge : Buffer containing the challenge
+    @return   - error status
+**/
+static int parse_claims(QCBORDecodeContext *decode_context, QCBORItem item,
+                                   struct q_useful_buf_c completed_challenge)
+{
+    int i, count = 0;
+    int status = VAL_ATTEST_SUCCESS;
+
+    /* Parse each claim and validate their data type */
+    while (status == VAL_ATTEST_SUCCESS)
+    {
+        status = QCBORDecode_GetNext(decode_context, &item);
+        if (status != VAL_ATTEST_SUCCESS)
+            break;
+
+        mandatory_claims |= 1 << (EAT_CBOR_ARM_RANGE_BASE - item.label.int64);
+        if (item.uLabelType == QCBOR_TYPE_INT64)
+        {
+            if (item.label.int64 == EAT_CBOR_ARM_LABEL_NONCE)
+            {
+                if (item.uDataType == QCBOR_TYPE_BYTE_STRING)
+                {
+                    /* Given challenge vs challenge in token */
+                    if (UsefulBuf_Compare(item.val.string, completed_challenge))
+                        return VAL_ATTEST_TOKEN_CHALLENGE_MISMATCH;
+                }
+                else
+                    return VAL_ATTEST_TOKEN_NOT_SUPPORTED;
+            }
+            else if (item.label.int64 == EAT_CBOR_ARM_LABEL_BOOT_SEED ||
+                     item.label.int64 == EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID ||
+                     item.label.int64 == EAT_CBOR_ARM_LABEL_UEID)
+            {
+                if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+                    return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+            }
+            else if (item.label.int64 == EAT_CBOR_ARM_LABEL_ORIGINATION ||
+                     item.label.int64 == EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION ||
+                     item.label.int64 == EAT_CBOR_ARM_LABEL_HW_VERSION)
+            {
+                if (item.uDataType != QCBOR_TYPE_TEXT_STRING)
+                    return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+            }
+            else if (item.label.int64 == EAT_CBOR_ARM_LABEL_CLIENT_ID ||
+                     item.label.int64 == EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE)
+            {
+                if (item.uDataType != QCBOR_TYPE_INT64)
+                    return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+            }
+            else if (item.label.int64 == EAT_CBOR_ARM_LABEL_SW_COMPONENTS)
+            {
+                if (item.uDataType != QCBOR_TYPE_ARRAY)
+                    return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+                sw_component_present = 1;
+                status = QCBORDecode_GetNext(decode_context, &item);
+                if (status != VAL_ATTEST_SUCCESS)
+                    continue;
+
+                count = item.val.uCount;
+                for (i = 0; i <= count; i++)
+                {
+                    mandaroty_sw_components |= 1 << item.label.int64;
+
+                    if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT)
+                    {
+                         if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                    else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC)
+                    {
+                        if (item.uDataType != QCBOR_TYPE_TEXT_STRING)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                    else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_VERSION)
+                    {
+                        if (item.uDataType != QCBOR_TYPE_TEXT_STRING)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                    else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_SIGNER_ID)
+                    {
+                        if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                    else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_EPOCH)
+                    {
+                        if (item.uDataType != QCBOR_TYPE_INT64)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                    else if (item.label.int64 == EAT_CBOR_SW_COMPONENT_TYPE)
+                    {
+                        if (item.uDataType != QCBOR_TYPE_TEXT_STRING)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+
+                    if (i < count)
+                    {
+                        status = QCBORDecode_GetNext(decode_context, &item);
+                        if (status != VAL_ATTEST_SUCCESS)
+                            return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+                    }
+                }
+
+            }
+        }
+        else
+        {
+            /* For other claim types */
+        }
+    }
+
+    if (status == QCBOR_ERR_HIT_END)
+        return VAL_ATTEST_SUCCESS;
+    else
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+}
+
+/**
+    @brief    - This API will verify the attestation token
+    @param    - challenge       : The buffer containing the challenge
+                challenge_size  : Size of the challenge buffer
+                token           : The buffer containing the attestation token
+                token_size      : Size of the token buffer
+    @return   - error status
+**/
+int32_t val_initial_attest_verify_token(uint8_t *challenge, size_t challenge_size,
+                                        uint8_t *token, size_t token_size)
+{
+    int32_t               status = VAL_ATTEST_SUCCESS;
+    int32_t               cose_algorithm_id;
+    QCBORItem             item;
+    QCBORDecodeContext    decode_context;
+    struct q_useful_buf_c completed_challenge;
+    struct q_useful_buf_c completed_token;
+    struct q_useful_buf_c payload;
+    struct q_useful_buf_c signature;
+    struct q_useful_buf_c protected_headers;
+    struct q_useful_buf_c kid;
+    struct q_useful_buf_c token_hash;
+
+    USEFUL_BUF_MAKE_STACK_UB(buffer_for_encoded_key, MAX_ENCODED_COSE_KEY_SIZE);
+    USEFUL_BUF_MAKE_STACK_UB(buffer_for_token_hash, T_COSE_CRYPTO_SHA256_SIZE);
+
+    kid.ptr = buffer_for_encoded_key.ptr;
+
+    /* Construct the token buffer for validation */
+    completed_token.ptr = token;
+    completed_token.len = token_size;
+
+    /* Construct the challenge buffer for validation */
+    completed_challenge.ptr = challenge;
+    completed_challenge.len = challenge_size;
+
+/*
+    -------------------------
+    |  CBOR Array Type      |
+    -------------------------
+    |  Protected Headers    |
+    -------------------------
+    |  Unprotected Headers  |
+    -------------------------
+    |  Payload              |
+    -------------------------
+    |  Signature            |
+    -------------------------
+*/
+
+    /* Initialize the decorder */
+    QCBORDecode_Init(&decode_context, completed_token, QCBOR_DECODE_MODE_NORMAL);
+
+    /* Get the Header */
+    QCBORDecode_GetNext(&decode_context, &item);
+
+    /* Check the CBOR Array type. Check if the count is 4.
+     * Only COSE_SIGN1 is supported now.
+     */
+    if (item.uDataType != QCBOR_TYPE_ARRAY || item.val.uCount != 4 ||
+       !QCBORDecode_IsTagged(&decode_context, &item, CBOR_TAG_COSE_SIGN1))
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+    /* Get the next headers */
+    QCBORDecode_GetNext(&decode_context, &item);
+    if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+    protected_headers = item.val.string;
+
+    /* Parse the protected headers and check the data type and value*/
+    status = parse_protected_headers(protected_headers, &cose_algorithm_id);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    /* Parse the unprotected headers and check the data type and value */
+    status = parse_unprotected_headers(&decode_context, &kid);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    /* Get the payload */
+    QCBORDecode_GetNext(&decode_context, &item);
+    if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+    payload = item.val.string;
+
+    /* Get the digital signature */
+    QCBORDecode_GetNext(&decode_context, &item);
+    if (item.uDataType != QCBOR_TYPE_BYTE_STRING)
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+    signature = item.val.string;
+
+    /* Compute the hash from the token */
+    status = val_attestation_function(VAL_INITIAL_ATTEST_COMPUTE_HASH, cose_algorithm_id,
+                                      buffer_for_token_hash, &token_hash,
+                                      protected_headers, payload);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    /* Verify the signature */
+    status = val_attestation_function(VAL_INITIAL_ATTEST_VERIFY_WITH_PK, cose_algorithm_id,
+                                      token_hash, signature);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    /* Initialize the Decoder and validate the payload format */
+    QCBORDecode_Init(&decode_context, payload, QCBOR_DECODE_MODE_NORMAL);
+    status = QCBORDecode_GetNext(&decode_context, &item);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    if (item.uDataType != QCBOR_TYPE_MAP)
+        return VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING;
+
+    /* Parse the payload and check the data type of each claim */
+    status = parse_claims(&decode_context, item, completed_challenge);
+    if (status != VAL_ATTEST_SUCCESS)
+        return status;
+
+    if ((mandatory_claims & MANDATORY_CLAIM_WITH_SW_COMP) == MANDATORY_CLAIM_WITH_SW_COMP)
+    {
+        if ((mandaroty_sw_components & MANDATORY_SW_COMP) != MANDATORY_SW_COMP)
+            return VAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS;
+    }
+    else if ((mandatory_claims & MANDATORY_CLAIM_NO_SW_COMP) != MANDATORY_CLAIM_NO_SW_COMP)
+    {
+        return VAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS;
+    }
+
+    return VAL_ATTEST_SUCCESS;
+}
+#endif /* INITIAL_ATTESTATION */
+
 /**
     @brief    - This API will call the requested attestation function
     @param    - type : function code
                 ...  : variable number of arguments
     @return   - Error status
 **/
-
 int32_t val_attestation_function(int type, ...)
 {
 #ifdef INITIAL_ATTESTATION
     va_list      valist;
     val_status_t status;
+    uint8_t      *challenge, *token;
+    size_t       challenge_size, verify_token_size;
 
     va_start(valist, type);
-    status = pal_attestation_function(type, valist);
+    switch (type)
+    {
+        case VAL_INITIAL_ATTEST_VERIFY_TOKEN:
+            challenge = va_arg(valist, uint8_t*);
+            challenge_size = va_arg(valist, size_t);
+            token = va_arg(valist, uint8_t*);
+            verify_token_size = va_arg(valist, size_t);
+            status = val_initial_attest_verify_token(challenge, challenge_size,
+                                                   token, verify_token_size);
+            break;
+        default:
+            status = pal_attestation_function(type, valist);
+            break;
+    }
+
     va_end(valist);
     return status;
 #else
     return VAL_STATUS_ERROR;
-#endif
+#endif /* INITIAL_ATTESTATION */
 }
diff --git a/api-tests/val/nspe/val_attestation.h b/api-tests/val/nspe/val_attestation.h
index 58ea59c..f810fcc 100644
--- a/api-tests/val/nspe/val_attestation.h
+++ b/api-tests/val/nspe/val_attestation.h
@@ -18,14 +18,130 @@
 #ifndef _VAL_INITIAL_ATTESTATION_H_
 #define _VAL_INITIAL_ATTESTATION_H_
 
+#ifdef INITIAL_ATTESTATION
+
 #include "val.h"
+#include "qcbor.h"
+
+#define COSE_HEADER_PARAM_ALG             1
+#define COSE_HEADER_PARAM_KID             4
+
+/**
+ * The size of X and Y coordinate in 2 parameter style EC public
+ * key. Format is as defined in [COSE (RFC 8152)]
+ * (https://tools.ietf.org/html/rfc8152) and [SEC 1: Elliptic Curve
+ * Cryptography](http://www.secg.org/sec1-v2.pdf).
+ *
+ * This size is well-known and documented in public standards.
+ */
+#define T_COSE_CRYPTO_EC_P256_COORD_SIZE  32
+#define T_COSE_CRYPTO_SHA256_SIZE         32
+
+#define MAX_ENCODED_COSE_KEY_SIZE \
+   (1 + /* 1 byte to encode map */ \
+    2 + /* 2 bytes to encode key type */ \
+    2 + /* 2 bytes to encode curve */ \
+    2 * /* the X and Y coordinates at 32 bytes each */ \
+        (T_COSE_CRYPTO_EC_P256_COORD_SIZE + 1 + 2))
+
+#define USEFUL_BUF_MAKE_STACK_UB UsefulBuf_MAKE_STACK_UB
+
 #define MAX_CHALLENGE_SIZE      PSA_INITIAL_ATTEST_CHALLENGE_SIZE_64
 
+#define EAT_CBOR_ARM_RANGE_BASE                 (-75000)
+#define EAT_CBOR_ARM_LABEL_PROFILE_DEFINITION   (EAT_CBOR_ARM_RANGE_BASE - 0)
+#define EAT_CBOR_ARM_LABEL_CLIENT_ID            (EAT_CBOR_ARM_RANGE_BASE - 1)
+#define EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE   (EAT_CBOR_ARM_RANGE_BASE - 2)
+#define EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID    (EAT_CBOR_ARM_RANGE_BASE - 3)
+#define EAT_CBOR_ARM_LABEL_BOOT_SEED            (EAT_CBOR_ARM_RANGE_BASE - 4)
+#define EAT_CBOR_ARM_LABEL_HW_VERSION           (EAT_CBOR_ARM_RANGE_BASE - 5)
+#define EAT_CBOR_ARM_LABEL_SW_COMPONENTS        (EAT_CBOR_ARM_RANGE_BASE - 6)
+#define EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS     (EAT_CBOR_ARM_RANGE_BASE - 7)
+#define EAT_CBOR_ARM_LABEL_NONCE                (EAT_CBOR_ARM_RANGE_BASE - 8)
+#define EAT_CBOR_ARM_LABEL_UEID                 (EAT_CBOR_ARM_RANGE_BASE - 9)
+#define EAT_CBOR_ARM_LABEL_ORIGINATION          (EAT_CBOR_ARM_RANGE_BASE - 10)
+
+#define CBOR_ARM_TOTAL_CLAIM_INSTANCE           10
+
+#define EAT_CBOR_SW_COMPONENT_TYPE              (1u)
+#define EAT_CBOR_SW_COMPONENT_MEASUREMENT       (2u)
+#define EAT_CBOR_SW_COMPONENT_EPOCH             (3u)
+#define EAT_CBOR_SW_COMPONENT_VERSION           (4u)
+#define EAT_CBOR_SW_COMPONENT_SIGNER_ID         (5u)
+#define EAT_CBOR_SW_COMPONENT_MEASUREMENT_DESC  (6u)
+
+#define MANDATORY_CLAIM_WITH_SW_COMP           (1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_NONCE)              |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_UEID)               |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID)  |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_CLIENT_ID)          |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE) |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_BOOT_SEED)          |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_SW_COMPONENTS))
+
+#define MANDATORY_CLAIM_NO_SW_COMP             (1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_NONCE)              |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_UEID)               |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_IMPLEMENTATION_ID)  |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_CLIENT_ID)          |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_SECURITY_LIFECYCLE) |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_BOOT_SEED)          |     \
+                                                1 << (EAT_CBOR_ARM_RANGE_BASE                      \
+                                                    - EAT_CBOR_ARM_LABEL_NO_SW_COMPONENTS))
+
+#define MANDATORY_SW_COMP                      (1 << EAT_CBOR_SW_COMPONENT_MEASUREMENT      |     \
+                                                1 << EAT_CBOR_SW_COMPONENT_VERSION          |     \
+                                                1 << EAT_CBOR_SW_COMPONENT_SIGNER_ID)
+
+#define VAL_ATTEST_MIN_ERROR                    70
+
+enum attestation_error_code {
+    VAL_ATTEST_SUCCESS = 0,
+    VAL_ATTEST_TOKEN_ERR_CBOR_FORMATTING = VAL_ATTEST_MIN_ERROR,
+    VAL_ATTEST_TOKEN_CHALLENGE_MISMATCH,
+    VAL_ATTEST_TOKEN_NOT_SUPPORTED,
+    VAL_ATTEST_TOKEN_NOT_ALL_MANDATORY_CLAIMS,
+    VAL_ATTEST_HASH_LENGTH_MISMATCH,
+    VAL_ATTEST_HASH_MISMATCH,
+    VAL_ATTEST_HASH_FAIL,
+    VAL_ATTEST_HASH_UNSUPPORTED,
+    VAL_ATTEST_HASH_BUFFER_SIZE,
+    VAL_ATTEST_ERR_PROTECTED_HEADERS,
+    VAL_ATTEST_ERR_SIGN_STRUCT,
+    VAL_ATTEST_ERR_KEY_FAIL,
+    VAL_ATTEST_ERR_SIGNATURE_FAIL,
+    VAL_ATTEST_ERR_CBOR_STRUCTURE,
+    VAL_ATTEST_ERR_SMALL_BUFFER,
+    VAL_ATTEST_ERROR,
+};
+
+struct items_to_get_t {
+    int64_t label;
+    QCBORItem item;
+};
+
 enum attestation_function_code {
     VAL_INITIAL_ATTEST_GET_TOKEN        = 0x1,
     VAL_INITIAL_ATTEST_GET_TOKEN_SIZE   = 0x2,
     VAL_INITIAL_ATTEST_VERIFY_TOKEN     = 0x3,
+    VAL_INITIAL_ATTEST_COMPUTE_HASH     = 0x4,
+    VAL_INITIAL_ATTEST_VERIFY_WITH_PK   = 0x5,
 };
 
+int32_t val_initial_attest_verify_token(uint8_t *challenge, size_t challenge_size,
+                                        uint8_t *token, size_t token_size);
+#endif /* INITIAL_ATTESTATION */
+
 int32_t val_attestation_function(int type, ...);
 #endif /* _VAL_INITIAL_ATTESTATION_H_ */
diff --git a/api-tests/val/val_nspe.cmake b/api-tests/val/val_nspe.cmake
index 91113b0..4494ed2 100644
--- a/api-tests/val/val_nspe.cmake
+++ b/api-tests/val/val_nspe.cmake
@@ -38,6 +38,12 @@
         target_include_directories(${PSA_TARGET_VAL_NSPE_LIB} PRIVATE ${psa_inc_path})
 endforeach()
 
+if(${SUITE} STREQUAL "INITIAL_ATTESTATION")
+target_include_directories(${PSA_TARGET_VAL_NSPE_LIB} PRIVATE
+    ${PSA_QCBOR_INCLUDE_PATH}
+)
+endif()
+
 target_include_directories(${PSA_TARGET_VAL_NSPE_LIB} PRIVATE
 	${CMAKE_CURRENT_BINARY_DIR}
 	${PSA_ROOT_DIR}/val/common