Platform: Get attestation private key from OTP on Musca-B1
Change-Id: I3059bc09b1fd07631e0c0213dc176773cdc4a7e5
Signed-off-by: Xu Yong <yong.xu@arm.com>
diff --git a/platform/ext/common/cc312/cc312.c b/platform/ext/common/cc312/cc312.c
index f1a65e3..29fe268 100644
--- a/platform/ext/common/cc312/cc312.c
+++ b/platform/ext/common/cc312/cc312.c
@@ -17,6 +17,8 @@
#include "arm_cmse.h"
#include "mbedtls_cc_util_key_derivation.h"
#include "tfm_attest_hal.h"
+#include "prod_hw_defs.h"
+#include "cc_otp_defs.h"
#define CC312_NULL_CONTEXT "NO SALT!"
@@ -127,7 +129,79 @@
label, label_size,
context, context_size,
key, key_size);
+}
+/*
+ * Count number of zero bits in 32-bit word.
+ * Copied from:
+ * lib/ext/cryptocell-312-runtime/host/src/ \
+ * cc3x_productionlib/common/prod_util.c: CC_PROD_GetZeroCount(..)
+ */
+static int get_zero_bits_count(uint32_t *buf,
+ uint32_t buf_word_size,
+ uint32_t *zero_count)
+{
+ uint32_t val;
+ uint32_t index = 0;
+
+ *zero_count = 0;
+ for (index = 0; index < buf_word_size; index++) {
+ val = buf[index];
+ val = val - ((val >> 1) & 0x55555555);
+ val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
+ val = ((((val + (val >> 4)) & 0xF0F0F0F) * 0x1010101) >> 24);
+ *zero_count += (32 - val);
+ }
+ /* All 0's and all 1's is forbidden */
+ if ((*zero_count == 0)
+ || (*zero_count == buf_word_size*CC_BITS_IN_32BIT_WORD)) {
+ *zero_count = 0;
+ return -1;
+ }
+
+ return 0;
+}
+
+/*
+ * Get attestation private key from CC312 OTP
+ */
+int crypto_hw_accelerator_get_attestation_private_key(uint8_t *buf,
+ uint32_t *size)
+{
+ uint32_t *key = (uint32_t *)buf;
+ uint32_t otp_val;
+ uint32_t otp_zero_count;
+ uint32_t zero_count;
+ int i;
+ int rc;
+
+ if (key == NULL ||
+ *size < CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS * sizeof(uint32_t)) {
+ return -1;
+ }
+ *size = CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS * sizeof(uint32_t);
+
+ /* Get provisioned key from OTP, 8 words */
+ for (i = 0; i < CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS; i++) {
+ CC_PROD_OTP_READ(otp_val, CC_OTP_ATTESTATION_KEY_OFFSET + i);
+ *key = otp_val;
+ key++;
+ }
+
+ /* Verify the zero number of private key */
+ rc = get_zero_bits_count((uint32_t *)buf,
+ CC_OTP_ATTESTATION_KEY_SIZE_IN_WORDS,
+ &zero_count);
+ if (rc) {
+ return -1;
+ }
+
+ CC_PROD_OTP_READ(otp_zero_count, CC_OTP_ATTESTATION_KEY_ZERO_COUNT_OFFSET);
+ if (otp_zero_count != zero_count) {
+ return -1;
+ }
+
+ return 0;
}
int crypto_hw_accelerator_get_rotpk_hash(uint8_t image_id,
diff --git a/platform/ext/common/cc312/crypto_hw.h b/platform/ext/common/cc312/crypto_hw.h
index d3c513d..d4c7aaf 100644
--- a/platform/ext/common/cc312/crypto_hw.h
+++ b/platform/ext/common/cc312/crypto_hw.h
@@ -88,6 +88,18 @@
uint32_t *rotpk_hash_size);
/**
+ * \brief Retrieve the attestation private key from OTP
+ *
+ * \param[out] buf Buffer to store the key in
+ * \param[in,out] size As input the size of the buffer. As output the actual
+ * size of the key in bytes.
+ *
+ * \return 0 on success, non-zero otherwise
+ */
+int crypto_hw_accelerator_get_attestation_private_key(uint8_t *buf,
+ uint32_t *size);
+
+/**
* \brief Retrieve the device lifecycle
*
* \param[out] lcs Pointer to store lifecycle state
diff --git a/platform/ext/target/musca_b1/dummy_crypto_keys.c b/platform/ext/target/musca_b1/dummy_crypto_keys.c
index 4af3404..83e768f 100644
--- a/platform/ext/target/musca_b1/dummy_crypto_keys.c
+++ b/platform/ext/target/musca_b1/dummy_crypto_keys.c
@@ -45,6 +45,7 @@
extern const struct tfm_plat_rotpk_t device_rotpk[];
extern const uint32_t rotpk_key_cnt;
+#ifndef CRYPTO_HW_ACCELERATOR_OTP_ENABLED
/**
* \brief Copy the key to the destination buffer
*
@@ -62,6 +63,7 @@
p_dst++;
}
}
+#endif /* !CRYPTO_HW_ACCELERATOR_OTP_ENABLED */
enum tfm_plat_err_t tfm_plat_get_huk_derived_key(const uint8_t *label,
size_t label_size,
@@ -110,12 +112,10 @@
struct ecc_key_t *ecc_key,
psa_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;
+ uint32_t key_size = initial_attestation_private_key_size;
+ int rc;
- if (size < full_key_size) {
+ if (size < key_size) {
return TFM_PLAT_ERR_SYSTEM_ERR;
}
@@ -123,11 +123,19 @@
*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;
+#ifdef CRYPTO_HW_ACCELERATOR_OTP_ENABLED
+ rc = crypto_hw_accelerator_get_attestation_private_key(key_buf, &size);
+ key_size = size;
+#else
+ copy_key(key_buf, initial_attestation_private_key, key_size);
+ rc = 0;
+#endif /* CRYPTO_HW_ACCELERATOR_OTP_ENABLED */
+
+ if (rc) {
+ return TFM_PLAT_ERR_SYSTEM_ERR;
+ }
+
+ ecc_key->priv_key = key_buf;
ecc_key->priv_key_size = key_size;
ecc_key->pubx_key = NULL;