Platform: Extend crypto key API with attestation key

Details:
 - Add new functions to API to get the initial attestion key
   or its size
 - Add a new file, which contains an ECDSA P-256 key pair
   in hard coded raw format (without any encoding)
 - Add the orignal *.pem file, ASN.1 encoding
 - Create dummy implementation per target to retrive the
   hard coded key

Change-Id: Ie7dfac9d6df631f87c50f755cb80ffc7f00f5cbd
Signed-off-by: Tamas Ban <tamas.ban@arm.com>
diff --git a/platform/ext/Mps2AN519.cmake b/platform/ext/Mps2AN519.cmake
index a515199..532c4d7 100644
--- a/platform/ext/Mps2AN519.cmake
+++ b/platform/ext/Mps2AN519.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -123,6 +123,7 @@
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_HARDWARE_KEYS (true|false) is undefined!")
 elseif(BUILD_TARGET_HARDWARE_KEYS)
+  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/common/tfm_initial_attestation_key_material.c")
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an519/dummy_crypto_keys.c")
 endif()
 
diff --git a/platform/ext/Mps2AN521.cmake b/platform/ext/Mps2AN521.cmake
index 3e7902a..3502a11 100644
--- a/platform/ext/Mps2AN521.cmake
+++ b/platform/ext/Mps2AN521.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -124,6 +124,7 @@
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_HARDWARE_KEYS (true|false) is undefined!")
 elseif(BUILD_TARGET_HARDWARE_KEYS)
+  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/common/tfm_initial_attestation_key_material.c")
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/mps2/an521/dummy_crypto_keys.c")
 endif()
 
diff --git a/platform/ext/common/tfm_initial_attestation_key.pem b/platform/ext/common/tfm_initial_attestation_key.pem
new file mode 100644
index 0000000..f2c928e
--- /dev/null
+++ b/platform/ext/common/tfm_initial_attestation_key.pem
@@ -0,0 +1,5 @@
+-----BEGIN PRIVATE KEY-----
+MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgx0ZwvLfoWzgD77Qo
+lASS5z4/6dT3taitXkgMvby1VMKhRANCAATc8ND0vNXialTuNsrWYNKD0Sq8X3MH
+3lhonnfNYEUudYy621/p+JpxB+Wi6OpE7BsJt9oqGoKgJSpMHCbuHtfP
+-----END PRIVATE KEY-----
diff --git a/platform/ext/common/tfm_initial_attestation_key_material.c b/platform/ext/common/tfm_initial_attestation_key_material.c
new file mode 100644
index 0000000..b3ef451
--- /dev/null
+++ b/platform/ext/common/tfm_initial_attestation_key_material.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2019, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stdint.h>
+#include "platform/include/tfm_plat_defs.h"
+#include "platform/include/tfm_plat_crypto_keys.h"
+
+/*
+ * This file contains the hard coded version of the ECDSA P-256 key pair in:
+ * platform/common/tfm_initial_attestation_key.pem
+ *
+ * This key is used to sign the initial attestation token.
+ * The key pair is stored in raw format, without any encoding(ASN.1, COSE).
+ *
+ * This ECDSA P-256 key is the construction of:
+ *   - private key:      32 bytes
+ *   - public key:
+ *       - X-coordinate: 32 bytes
+ *       - Y-coordinate: 32 bytes
+ *
+ * The hash of the raw public key (H(X || Y)) is also included, because it is
+ * used as an instance ID. It is a unique identifier of the device instance.
+ *
+ * Instance ID is mapped to:
+ *   - UEID in the EAT token
+ *
+ *   #######  DO NOT USE THIS KEY IN PRODUCTION #######
+ */
+
+/* Type of the EC curve which the key belongs to */
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const enum ecc_curve_t initial_attestation_curve_type = P_256;
+
+/* Initial attestation private key in raw format, without any encoding.
+ * It belongs to the ECDSA P-256 curve.
+ * It MUST present on the device-
+ */
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint8_t initial_attestation_private_key[] =
+{
+    0xC7, 0x46, 0x70, 0xBC, 0xB7, 0xE8, 0x5B, 0x38,
+    0x03, 0xEF, 0xB4, 0x28, 0x94, 0x04, 0x92, 0xE7,
+    0x3E, 0x3F, 0xE9, 0xD4, 0xF7, 0xB5, 0xA8, 0xAD,
+    0x5E, 0x48, 0x0C, 0xBD, 0xBC, 0xB5, 0x54, 0xC2
+};
+
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint32_t initial_attestation_private_key_size =
+        sizeof(initial_attestation_private_key);
+
+/* Initial attestation x-coordinate of the public key in raw format,
+ * without any encoding.
+ * It belongs to the ECDSA P-256 curve.
+ * It MIGHT be present on the device.
+ */
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint8_t initial_attestation_public_x_key[] =
+{
+    0xDC, 0xF0, 0xD0, 0xF4, 0xBC, 0xD5, 0xE2, 0x6A,
+    0x54, 0xEE, 0x36, 0xCA, 0xD6, 0x60, 0xD2, 0x83,
+    0xD1, 0x2A, 0xBC, 0x5F, 0x73, 0x07, 0xDE, 0x58,
+    0x68, 0x9E, 0x77, 0xCD, 0x60, 0x45, 0x2E, 0x75,
+};
+
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint32_t initial_attestation_public_x_key_size =
+        sizeof(initial_attestation_public_x_key);
+
+/* Initial attestation y-coordinate of the public key in raw format,
+ * without any encoding.
+ * It belongs to the ECDSA P-256 curve.
+ * It MIGHT be present on the device.
+ */
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint8_t initial_attestation_public_y_key[] =
+{
+    0x8C, 0xBA, 0xDB, 0x5F, 0xE9, 0xF8, 0x9A, 0x71,
+    0x07, 0xE5, 0xA2, 0xE8, 0xEA, 0x44, 0xEC, 0x1B,
+    0x09, 0xB7, 0xDA, 0x2A, 0x1A, 0x82, 0xA0, 0x25,
+    0x2A, 0x4C, 0x1C, 0x26, 0xEE, 0x1E, 0xD7, 0xCF,
+};
+
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint32_t initial_attestation_public_y_key_size =
+        sizeof(initial_attestation_public_y_key);
+
+/* Hash (SHA256) of initial attestation public key */
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint8_t initial_attestation_raw_public_key_hash[] =
+{
+    0xf4, 0x0c, 0x8f, 0xbf, 0x12, 0xdb, 0x78, 0x2a,
+    0xfd, 0xf4, 0x75, 0x96, 0x6a, 0x06, 0x82, 0x36,
+    0xe0, 0x32, 0xab, 0x80, 0xd1, 0xb7, 0xf1, 0xbc,
+    0x9f, 0xe7, 0xd8, 0x7a, 0x88, 0xcb, 0x26, 0xd0,
+};
+
+TFM_LINK_SET_OBJECT_IN_PARTITION_SECTION("TFM_SP_INITIAL_ATTESTATION")
+const uint32_t initial_attestation_raw_public_key_hash_size =
+        sizeof(initial_attestation_raw_public_key_hash);
diff --git a/platform/ext/musca_a.cmake b/platform/ext/musca_a.cmake
index 5f0e88a..daf11cd 100755
--- a/platform/ext/musca_a.cmake
+++ b/platform/ext/musca_a.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -127,6 +127,7 @@
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
   message(FATAL_ERROR "Configuration variable BUILD_TARGET_HARDWARE_KEYS (true|false) is undefined!")
 elseif(BUILD_TARGET_HARDWARE_KEYS)
+  list(APPEND ALL_SRC_C "${PLATFORM_DIR}/common/tfm_initial_attestation_key_material.c")
   list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_a/dummy_crypto_keys.c")
 endif()
 
diff --git a/platform/ext/musca_b1.cmake b/platform/ext/musca_b1.cmake
index 510e90f..63fc134 100755
--- a/platform/ext/musca_b1.cmake
+++ b/platform/ext/musca_b1.cmake
@@ -1,5 +1,5 @@
 #-------------------------------------------------------------------------------
-# Copyright (c) 2018, Arm Limited. All rights reserved.
+# Copyright (c) 2018-2019, Arm Limited. All rights reserved.
 #
 # SPDX-License-Identifier: BSD-3-Clause
 #
@@ -123,6 +123,7 @@
 if (NOT DEFINED BUILD_TARGET_HARDWARE_KEYS)
     message(FATAL_ERROR "Configuration variable BUILD_TARGET_HARDWARE_KEYS (true|false) is undefined!")
 elseif (BUILD_TARGET_HARDWARE_KEYS)
+    list(APPEND ALL_SRC_C "${PLATFORM_DIR}/common/tfm_initial_attestation_key_material.c")
     list(APPEND ALL_SRC_C "${PLATFORM_DIR}/target/musca_b1/dummy_crypto_keys.c")
 endif()
 
diff --git a/platform/ext/target/mps2/an519/dummy_crypto_keys.c b/platform/ext/target/mps2/an519/dummy_crypto_keys.c
index 3263b28..014b140 100644
--- a/platform/ext/target/mps2/an519/dummy_crypto_keys.c
+++ b/platform/ext/target/mps2/an519/dummy_crypto_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited
+ * Copyright (c) 2017-2019 ARM Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,16 @@
  */
 
 #include "platform/include/tfm_plat_crypto_keys.h"
+#include <stddef.h>
+
+/* FIXME: Functions in this file should be implemented by platform vendor. For
+ * the security of the storage system, it is critical to use a hardware unique
+ * key. For the security of the attestation, it is critical to use a unique key
+ * pair and keep the private key is secret.
+ *
+ * AN519 does not have any available hardware unique key engine, so a
+ * software stub has been implemented in this case.
+ */
 
 #define TFM_KEY_LEN_BYTES  16
 
@@ -22,29 +32,96 @@
              {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
 
+extern const enum ecc_curve_t initial_attestation_curve_type;
+extern const uint8_t  initial_attestation_private_key[];
+extern const uint32_t initial_attestation_private_key_size;
+extern const uint8_t  initial_attestation_public_x_key[];
+extern const uint32_t initial_attestation_public_x_key_size;
+extern const uint8_t  initial_attestation_public_y_key[];
+extern const uint32_t initial_attestation_public_y_key_size;
+
+/**
+ * \brief Copy the key to the destination buffer
+ *
+ * \param[out]  p_dst  Pointer to buffer where to store the key
+ * \param[in]   p_src  Pointer to the key
+ * \param[in]   size   Length of the key
+ */
+static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size)
+{
+    uint32_t i;
+
+    for (i = size; i > 0; i--) {
+        *p_dst = *p_src;
+        p_src++;
+        p_dst++;
+    }
+}
+
 enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size)
 {
-    /* FIXME: this function should be implemented by platform vendor. For the
-     * security of the storage system, it is critical to use a hardware unique
-     * key.
-     *
-     * AN519 does not have any available hardware unique key engine, so a
-     * software stub has been implemented in this case.
-     */
-    uint32_t i;
-    uint8_t *p_dst = key;
-    const uint8_t *p_huk = sample_tfm_key;
-
     if(size > TFM_KEY_LEN_BYTES) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
 
-    for (i = size; i > 0; i--) {
-        *p_dst = *p_huk;
-        p_huk++;
-        p_dst++;
-    }
+    copy_key(key, sample_tfm_key, size);
 
     return TFM_PLAT_ERR_SUCCESS;
 }
 
+enum tfm_plat_err_t
+tfm_plat_get_initial_attest_key(uint8_t          *key_buf,
+                                uint32_t          size,
+                                struct ecc_key_t *ecc_key,
+                                enum ecc_curve_t *curve_type)
+{
+    uint8_t *key_dst;
+    const uint8_t *key_src;
+    uint32_t key_size;
+    uint32_t full_key_size = initial_attestation_private_key_size  +
+                             initial_attestation_public_x_key_size +
+                             initial_attestation_public_y_key_size;
+
+    if (size < full_key_size) {
+        return TFM_PLAT_ERR_SYSTEM_ERR;
+    }
+
+    /* Set the EC curve type which the key belongs to */
+    *curve_type = initial_attestation_curve_type;
+
+    /* Copy the private key to the buffer, it MUST be present */
+    key_dst  = key_buf;
+    key_src  = initial_attestation_private_key;
+    key_size = initial_attestation_private_key_size;
+    copy_key(key_dst, key_src, key_size);
+    ecc_key->priv_key = key_dst;
+    ecc_key->priv_key_size = key_size;
+
+    /* Copy the x-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_x_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_x_key;
+        key_size = initial_attestation_public_x_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->pubx_key = key_dst;
+        ecc_key->pubx_key_size = key_size;
+    } else {
+        ecc_key->pubx_key = NULL;
+        ecc_key->pubx_key_size = 0;
+    }
+
+    /* Copy the y-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_y_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_y_key;
+        key_size = initial_attestation_public_y_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->puby_key = key_dst;
+        ecc_key->puby_key_size = key_size;
+    } else {
+        ecc_key->puby_key = NULL;
+        ecc_key->puby_key_size = 0;
+    }
+
+    return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
index 7bd8fbd..c01cd10 100644
--- a/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
+++ b/platform/ext/target/mps2/an521/armclang/mps2_an521_s.sct
@@ -89,7 +89,7 @@
 
     TFM_SP_INITIAL_ATTESTATION +0 ALIGN 32 {
         *tfm_attest* (+RO)
-        *(TFM_SP_INITIAL_ATTESTATION_PLATFORM_ATTR_FN)
+        *(TFM_SP_INITIAL_ATTESTATION_ATTR_FN)
     }
 
 #ifdef TFM_PARTITION_TEST_CORE
diff --git a/platform/ext/target/mps2/an521/dummy_crypto_keys.c b/platform/ext/target/mps2/an521/dummy_crypto_keys.c
index 0d74ffd..a2c3459 100644
--- a/platform/ext/target/mps2/an521/dummy_crypto_keys.c
+++ b/platform/ext/target/mps2/an521/dummy_crypto_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited
+ * Copyright (c) 2017-2019 ARM Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,16 @@
  */
 
 #include "platform/include/tfm_plat_crypto_keys.h"
+#include <stddef.h>
+
+/* FIXME: Functions in this file should be implemented by platform vendor. For
+ * the security of the storage system, it is critical to use a hardware unique
+ * key. For the security of the attestation, it is critical to use a unique key
+ * pair and keep the private key is secret.
+ *
+ * AN521 does not have any available hardware unique key engine, so a
+ * software stub has been implemented in this case.
+ */
 
 #define TFM_KEY_LEN_BYTES  16
 
@@ -22,29 +32,96 @@
              {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
 
+extern const enum ecc_curve_t initial_attestation_curve_type;
+extern const uint8_t  initial_attestation_private_key[];
+extern const uint32_t initial_attestation_private_key_size;
+extern const uint8_t  initial_attestation_public_x_key[];
+extern const uint32_t initial_attestation_public_x_key_size;
+extern const uint8_t  initial_attestation_public_y_key[];
+extern const uint32_t initial_attestation_public_y_key_size;
+
+/**
+ * \brief Copy the key to the destination buffer
+ *
+ * \param[out]  p_dst  Pointer to buffer where to store the key
+ * \param[in]   p_src  Pointer to the key
+ * \param[in]   size   Length of the key
+ */
+static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size)
+{
+    uint32_t i;
+
+    for (i = size; i > 0; i--) {
+        *p_dst = *p_src;
+        p_src++;
+        p_dst++;
+    }
+}
+
 enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size)
 {
-    /* FIXME: this function should be implemented by platform vendor. For the
-     * security of the storage system, it is critical to use a hardware unique
-     * key.
-     *
-     * AN521 does not have any available hardware unique key engine, so a
-     * software stub has been implemented in this case.
-     */
-    uint32_t i;
-    uint8_t *p_dst = key;
-    const uint8_t *p_huk = sample_tfm_key;
-
     if(size > TFM_KEY_LEN_BYTES) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
 
-    for (i = size; i > 0; i--) {
-        *p_dst = *p_huk;
-        p_huk++;
-        p_dst++;
-    }
+    copy_key(key, sample_tfm_key, size);
 
     return TFM_PLAT_ERR_SUCCESS;
 }
 
+enum tfm_plat_err_t
+tfm_plat_get_initial_attest_key(uint8_t          *key_buf,
+                                uint32_t          size,
+                                struct ecc_key_t *ecc_key,
+                                enum ecc_curve_t *curve_type)
+{
+    uint8_t *key_dst;
+    const uint8_t *key_src;
+    uint32_t key_size;
+    uint32_t full_key_size = initial_attestation_private_key_size  +
+                             initial_attestation_public_x_key_size +
+                             initial_attestation_public_y_key_size;
+
+    if (size < full_key_size) {
+        return TFM_PLAT_ERR_SYSTEM_ERR;
+    }
+
+    /* Set the EC curve type which the key belongs to */
+    *curve_type = initial_attestation_curve_type;
+
+    /* Copy the private key to the buffer, it MUST be present */
+    key_dst  = key_buf;
+    key_src  = initial_attestation_private_key;
+    key_size = initial_attestation_private_key_size;
+    copy_key(key_dst, key_src, key_size);
+    ecc_key->priv_key = key_dst;
+    ecc_key->priv_key_size = key_size;
+
+    /* Copy the x-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_x_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_x_key;
+        key_size = initial_attestation_public_x_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->pubx_key = key_dst;
+        ecc_key->pubx_key_size = key_size;
+    } else {
+        ecc_key->pubx_key = NULL;
+        ecc_key->pubx_key_size = 0;
+    }
+
+    /* Copy the y-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_y_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_y_key;
+        key_size = initial_attestation_public_y_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->puby_key = key_dst;
+        ecc_key->puby_key_size = key_size;
+    } else {
+        ecc_key->puby_key = NULL;
+        ecc_key->puby_key_size = 0;
+    }
+
+    return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/musca_a/dummy_crypto_keys.c b/platform/ext/target/musca_a/dummy_crypto_keys.c
index dafb837..7ce5c8d 100644
--- a/platform/ext/target/musca_a/dummy_crypto_keys.c
+++ b/platform/ext/target/musca_a/dummy_crypto_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited
+ * Copyright (c) 2017-2019 ARM Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,16 @@
  */
 
 #include "platform/include/tfm_plat_crypto_keys.h"
+#include <stddef.h>
+
+/* FIXME: Functions in this file should be implemented by platform vendor. For
+ * the security of the storage system, it is critical to use a hardware unique
+ * key. For the security of the attestation, it is critical to use a unique key
+ * pair and keep the private key is secret.
+ *
+ * Musca A does not have any available hardware unique key engine, so a
+ * software stub has been implemented in this case.
+ */
 
 #define TFM_KEY_LEN_BYTES  16
 
@@ -22,29 +32,96 @@
              {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
 
+extern const enum ecc_curve_t initial_attestation_curve_type;
+extern const uint8_t  initial_attestation_private_key[];
+extern const uint32_t initial_attestation_private_key_size;
+extern const uint8_t  initial_attestation_public_x_key[];
+extern const uint32_t initial_attestation_public_x_key_size;
+extern const uint8_t  initial_attestation_public_y_key[];
+extern const uint32_t initial_attestation_public_y_key_size;
+
+/**
+ * \brief Copy the key to the destination buffer
+ *
+ * \param[out]  p_dst  Pointer to buffer where to store the key
+ * \param[in]   p_src  Pointer to the key
+ * \param[in]   size   Length of the key
+ */
+static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size)
+{
+    uint32_t i;
+
+    for (i = size; i > 0; i--) {
+        *p_dst = *p_src;
+        p_src++;
+        p_dst++;
+    }
+}
+
 enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size)
 {
-    /* FIXME: this function should be implemented by platform vendor. For the
-     * security of the storage system, it is critical to use a hardware unique
-     * key.
-     *
-     * Musca A does not have any available hardware unique key engine, so a
-     * software stub has been implemented in this case.
-     */
-    uint32_t i;
-    uint8_t *p_dst = key;
-    const uint8_t *p_huk = sample_tfm_key;
-
     if(size > TFM_KEY_LEN_BYTES) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
 
-    for (i = size; i > 0; i--) {
-        *p_dst = *p_huk;
-        p_huk++;
-        p_dst++;
-    }
+    copy_key(key, sample_tfm_key, size);
 
     return TFM_PLAT_ERR_SUCCESS;
 }
 
+enum tfm_plat_err_t
+tfm_plat_get_initial_attest_key(uint8_t          *key_buf,
+                                uint32_t          size,
+                                struct ecc_key_t *ecc_key,
+                                enum ecc_curve_t *curve_type)
+{
+    uint8_t *key_dst;
+    const uint8_t *key_src;
+    uint32_t key_size;
+    uint32_t full_key_size = initial_attestation_private_key_size  +
+                             initial_attestation_public_x_key_size +
+                             initial_attestation_public_y_key_size;
+
+    if (size < full_key_size) {
+        return TFM_PLAT_ERR_SYSTEM_ERR;
+    }
+
+    /* Set the EC curve type which the key belongs to */
+    *curve_type = initial_attestation_curve_type;
+
+    /* Copy the private key to the buffer, it MUST be present */
+    key_dst  = key_buf;
+    key_src  = initial_attestation_private_key;
+    key_size = initial_attestation_private_key_size;
+    copy_key(key_dst, key_src, key_size);
+    ecc_key->priv_key = key_dst;
+    ecc_key->priv_key_size = key_size;
+
+    /* Copy the x-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_x_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_x_key;
+        key_size = initial_attestation_public_x_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->pubx_key = key_dst;
+        ecc_key->pubx_key_size = key_size;
+    } else {
+        ecc_key->pubx_key = NULL;
+        ecc_key->pubx_key_size = 0;
+    }
+
+    /* Copy the y-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_y_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_y_key;
+        key_size = initial_attestation_public_y_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->puby_key = key_dst;
+        ecc_key->puby_key_size = key_size;
+    } else {
+        ecc_key->puby_key = NULL;
+        ecc_key->puby_key_size = 0;
+    }
+
+    return TFM_PLAT_ERR_SUCCESS;
+}
diff --git a/platform/ext/target/musca_b1/dummy_crypto_keys.c b/platform/ext/target/musca_b1/dummy_crypto_keys.c
index 2ce83a6..1db8646 100644
--- a/platform/ext/target/musca_b1/dummy_crypto_keys.c
+++ b/platform/ext/target/musca_b1/dummy_crypto_keys.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018 ARM Limited
+ * Copyright (c) 2017-2019 ARM Limited
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -15,6 +15,13 @@
  */
 
 #include "platform/include/tfm_plat_crypto_keys.h"
+#include <stddef.h>
+
+/* FIXME: Functions in this file should be implemented by platform vendor. For
+ * the security of the storage system, it is critical to use a hardware unique
+ * key. For the security of the attestation, it is critical to use a unique key
+ * pair and keep the private key is secret.
+ */
 
 #define TFM_KEY_LEN_BYTES  16
 
@@ -22,24 +29,95 @@
              {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, \
               0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F};
 
+extern const enum ecc_curve_t initial_attestation_curve_type;
+extern const uint8_t  initial_attestation_private_key[];
+extern const uint32_t initial_attestation_private_key_size;
+extern const uint8_t  initial_attestation_public_x_key[];
+extern const uint32_t initial_attestation_public_x_key_size;
+extern const uint8_t  initial_attestation_public_y_key[];
+extern const uint32_t initial_attestation_public_y_key_size;
+
+/**
+ * \brief Copy the key to the destination buffer
+ *
+ * \param[out]  p_dst  Pointer to buffer where to store the key
+ * \param[in]   p_src  Pointer to the key
+ * \param[in]   size   Length of the key
+ */
+static inline void copy_key(uint8_t *p_dst, const uint8_t *p_src, size_t size)
+{
+    uint32_t i;
+
+    for (i = size; i > 0; i--) {
+        *p_dst = *p_src;
+        p_src++;
+        p_dst++;
+    }
+}
+
 enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size)
 {
-    /* FIXME: this function should be implemented by platform vendor. For the
-     * security of the storage system, it is critical to use a hardware unique
-     * key.
-     */
-    uint32_t i;
-    uint8_t *p_dst = key;
-    const uint8_t *p_huk = sample_tfm_key;
-
     if(size > TFM_KEY_LEN_BYTES) {
         return TFM_PLAT_ERR_SYSTEM_ERR;
     }
 
-    for (i = size; i > 0; i--) {
-        *p_dst = *p_huk;
-        p_huk++;
-        p_dst++;
+    copy_key(key, sample_tfm_key, size);
+
+    return TFM_PLAT_ERR_SUCCESS;
+}
+
+enum tfm_plat_err_t
+tfm_plat_get_initial_attest_key(uint8_t          *key_buf,
+                                uint32_t          size,
+                                struct ecc_key_t *ecc_key,
+                                enum ecc_curve_t *curve_type)
+{
+    uint8_t *key_dst;
+    const uint8_t *key_src;
+    uint32_t key_size;
+    uint32_t full_key_size = initial_attestation_private_key_size  +
+                             initial_attestation_public_x_key_size +
+                             initial_attestation_public_y_key_size;
+
+    if (size < full_key_size) {
+        return TFM_PLAT_ERR_SYSTEM_ERR;
+    }
+
+    /* Set the EC curve type which the key belongs to */
+    *curve_type = initial_attestation_curve_type;
+
+    /* Copy the private key to the buffer, it MUST be present */
+    key_dst  = key_buf;
+    key_src  = initial_attestation_private_key;
+    key_size = initial_attestation_private_key_size;
+    copy_key(key_dst, key_src, key_size);
+    ecc_key->priv_key = key_dst;
+    ecc_key->priv_key_size = key_size;
+
+    /* Copy the x-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_x_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_x_key;
+        key_size = initial_attestation_public_x_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->pubx_key = key_dst;
+        ecc_key->pubx_key_size = key_size;
+    } else {
+        ecc_key->pubx_key = NULL;
+        ecc_key->pubx_key_size = 0;
+    }
+
+    /* Copy the y-coordinate of public key to the buffer, it MIGHT be present */
+    if (initial_attestation_public_y_key_size != 0) {
+        key_dst  = key_dst + key_size;
+        key_src  = initial_attestation_public_y_key;
+        key_size = initial_attestation_public_y_key_size;
+        copy_key(key_dst, key_src, key_size);
+        ecc_key->puby_key = key_dst;
+        ecc_key->puby_key_size = key_size;
+    } else {
+        ecc_key->puby_key = NULL;
+        ecc_key->puby_key_size = 0;
     }
 
     return TFM_PLAT_ERR_SUCCESS;
diff --git a/platform/include/tfm_plat_crypto_keys.h b/platform/include/tfm_plat_crypto_keys.h
index 9682cc9..386d61f 100644
--- a/platform/include/tfm_plat_crypto_keys.h
+++ b/platform/include/tfm_plat_crypto_keys.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017-2018, Arm Limited. All rights reserved.
+ * Copyright (c) 2017-2019, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -20,6 +20,49 @@
 #endif
 
 /**
+ * Elliptic curve key type identifiers according to RFC8152 (COSE encoding)
+ * https://www.iana.org/assignments/cose/cose.xhtml#elliptic-curves
+ */
+enum ecc_curve_t {
+    P_256        = 1,  /* NIST P-256 also known as secp256r1 */
+    P_384        = 2,  /* NIST P-384 also known as secp384r1 */
+    P_521        = 3,  /* NIST P-521 also known as secp521r1 */
+    X25519       = 4,  /* X25519 for use with ECDH only      */
+    X448         = 5,  /* X448 for use with ECDH only        */
+    ED25519      = 6,  /* Ed25519 for use with EdDSA only    */
+    ED448        = 7,  /* Ed448 for use with EdDSA only      */
+};
+
+/**
+ * Structure definition to carry pointer and size information about an Elliptic
+ * curve key which is stored in a buffer(key_buf) in raw format (without
+ * encoding):
+ *   - priv_key       Base address of the private key in key_buf. It must be
+ *                    present on the device.
+ *   - priv_key_size  Size of the private key in bytes.
+ *   - pubx_key       Base address of x-coordinate of the public key in key_buf.
+ *                    It can be empty, because it can be recomputed based on
+ *                    private key.
+ *   - pubx_key_size  Length of x-coordinate of the public key in key_buf.
+ *                    It can be empty, because it can be recomputed based on
+ *                    private key.
+ *   - puby_key       Base address of y-coordinate of the public key in key_buf.
+ *                    It can be empty, because either it can be recomputed based
+ *                    on private key or some curve type works without it.
+ *   - puby_key_size  Length of y-coordinate of the public key in key_buf.
+ */
+struct ecc_key_t {
+    uint8_t  *priv_key;
+    uint32_t  priv_key_size;
+    uint8_t  *pubx_key;
+    uint32_t  pubx_key_size;
+    uint8_t  *puby_key;
+    uint32_t  puby_key_size;
+};
+
+#define ECC_P_256_KEY_SIZE  (96u)  /* 3 x 32 = 96 bytes priv + pub-x + pub-y */
+
+/**
  * \brief Gets hardware unique key for encryption
  *
  * \param[out] key   Buf to store the key in
@@ -29,6 +72,40 @@
  */
 enum tfm_plat_err_t tfm_plat_get_crypto_huk(uint8_t *key, uint32_t size);
 
+/**
+ * \brief Get the initial attestation key
+ *
+ * The device MUST contain an initial attestation key, which is used to sign the
+ * token. Initial attestation service supports elliptic curve signing
+ * algorithms. Device maker can decide whether store only the private key on the
+ * device or store both (public and private) key. Public key can be recomputed
+ * based on private key. Keys must be provided in raw format, just binary data
+ * without any encoding (DER, COSE). Caller provides a buffer to copy all the
+ * available key components to there. Key components must be copied after
+ * each other to the buffer. The base address and the length of each key
+ * component must be indicating in the corresponding field of ecc_key
+ * (\ref struct ecc_key_t).
+ * Curve_type indicates to which curve belongs the key.
+ *
+ *
+ * Keys must be provided in
+ *
+ * \param[in/out]  key_buf     Buffer to store the initial attestation key.
+ * \param[in]      size        Size of the buffer.
+ * \param[out]     ecc_key     A structure to carry pointer and size information
+ *                             about the initial attestation key, which is
+ *                             stored in key_buf.
+ * \param[out]     curve_type  The type of the EC curve, which the key belongs
+ *                             to according to \ref ecc_curve_t
+ *
+ * \return Returns error code specified in \ref tfm_plat_err_t
+ */
+enum tfm_plat_err_t
+tfm_plat_get_initial_attest_key(uint8_t          *key_buf,
+                                uint32_t          size,
+                                struct ecc_key_t *ecc_key,
+                                enum ecc_curve_t *curve_type);
+
 #ifdef __cplusplus
 }
 #endif