Crypto: Add support for NV seed entropy

Add support for NV seed entropy based on MbedTLS in Crypto service.
Seed read and write operations use ITS services. Currently, only
support in IPC model since library model doesn't allow one partition
call another one during partition init process.
Port a reference implementation on AN521.

Change-Id: I4b5dd5ed667509a94a03efd97b80dd7420d9621e
Signed-off-by: Summer Qin <summer.qin@arm.com>
diff --git a/config/config_default.cmake b/config/config_default.cmake
index 9158809..82a76e3 100644
--- a/config/config_default.cmake
+++ b/config/config_default.cmake
@@ -89,6 +89,7 @@
 set(PLATFORM_DUMMY_ROTPK                TRUE        CACHE BOOL      "Use dummy root of trust public key. Dummy key is the public key for the default keys in bl2. Should not be used in production.")
 set(PLATFORM_DUMMY_IAK                  TRUE        CACHE BOOL      "Use dummy initial attestation_key. Should not be used in production.")
 set(PLATFORM_DEFAULT_UART_STDOUT        TRUE        CACHE BOOL      "Use default uart stdout implementation.")
+set(PLATFORM_DUMMY_NV_SEED              FALSE       CACHE BOOL      "Use dummy NV seed implementation. Should not be used in production.")
 
 ############################ Partitions ########################################
 
diff --git a/platform/ext/common/template/crypto_dummy_nv_seed.c b/platform/ext/common/template/crypto_dummy_nv_seed.c
new file mode 100644
index 0000000..cb21fc7
--- /dev/null
+++ b/platform/ext/common/template/crypto_dummy_nv_seed.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include "mbedtls/entropy.h"
+#include "tfm_plat_crypto_dummy_nv_seed.h"
+
+/* NOTE: The seed value here is only an example, please do not use it in
+ * production. Platform vendor should implement their own seed value.
+ */
+const unsigned char seed_value[MBEDTLS_ENTROPY_BLOCK_SIZE] = {
+            0x12, 0x13, 0x23, 0x34, 0x0a, 0x05, 0x89, 0x78,
+            0xa3, 0x66, 0x8c, 0x0d, 0x97, 0x55, 0x53, 0xca,
+            0xb5, 0x76, 0x18, 0x62, 0x29, 0xc6, 0xb6, 0x79,
+            0x75, 0xc8, 0x5a, 0x8d, 0x9e, 0x11, 0x8f, 0x85,
+            0xde, 0xc4, 0x5f, 0x66, 0x21, 0x52, 0xf9, 0x39,
+            0xd9, 0x77, 0x93, 0x28, 0xb0, 0x5e, 0x02, 0xfa,
+            0x58, 0xb4, 0x16, 0xc8, 0x0f, 0x38, 0x91, 0xbb,
+            0x28, 0x17, 0xcd, 0x8a, 0xc9, 0x53, 0x72, 0x66,
+};
+
+int tfm_plat_crypto_create_entropy_seed(void)
+{
+    return tfm_plat_crypto_nv_seed_write(seed_value,
+                                         MBEDTLS_ENTROPY_BLOCK_SIZE);
+}
diff --git a/platform/ext/common/template/crypto_nv_seed.c b/platform/ext/common/template/crypto_nv_seed.c
new file mode 100644
index 0000000..97535da
--- /dev/null
+++ b/platform/ext/common/template/crypto_nv_seed.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+
+#include <stddef.h>
+#include "tfm_plat_crypto_nv_seed.h"
+#include "psa/internal_trusted_storage.h"
+
+int tfm_plat_crypto_nv_seed_read(unsigned char *buf, size_t buf_len)
+{
+    psa_storage_uid_t uid = NV_SEED_FILE_ID;
+    psa_status_t status;
+    size_t data_length = 0;
+
+    status = psa_its_get(uid, 0, buf_len, buf, &data_length);
+
+    if (status == PSA_SUCCESS && data_length == buf_len) {
+        return TFM_CRYPTO_NV_SEED_SUCCESS;
+    } else {
+        return TFM_CRYPTO_NV_SEED_FAILED;
+    }
+}
+
+int tfm_plat_crypto_nv_seed_write(unsigned char *buf, size_t buf_len)
+{
+    psa_storage_uid_t uid = NV_SEED_FILE_ID;
+    psa_status_t status;
+
+    status = psa_its_set(uid, buf_len, buf, 0);
+
+    if (status == PSA_SUCCESS) {
+        return TFM_CRYPTO_NV_SEED_SUCCESS;
+    } else {
+        return TFM_CRYPTO_NV_SEED_FAILED;
+    }
+}
diff --git a/platform/ext/target/mps2/an521/CMakeLists.txt b/platform/ext/target/mps2/an521/CMakeLists.txt
index d1ca90d..e4f798c 100644
--- a/platform/ext/target/mps2/an521/CMakeLists.txt
+++ b/platform/ext/target/mps2/an521/CMakeLists.txt
@@ -167,3 +167,16 @@
             native_drivers
     )
 endif()
+
+#========================= Crypto =============================================#
+
+target_sources(tfm_psa_rot_partition_crypto
+    PRIVATE
+        $<$<BOOL:${TFM_PSA_API}>:${CMAKE_SOURCE_DIR}/platform/ext/common/template/crypto_nv_seed.c>
+        $<$<AND:$<BOOL:${TFM_PSA_API}>,$<BOOL:${PLATFORM_DUMMY_NV_SEED}>>:${CMAKE_SOURCE_DIR}/platform/ext/common/template/crypto_dummy_nv_seed.c>
+)
+
+target_compile_definitions(tfm_psa_rot_partition_crypto
+    PRIVATE
+        $<$<AND:$<BOOL:${TFM_PSA_API}>,$<BOOL:${PLATFORM_DUMMY_NV_SEED}>>:PLATFORM_DUMMY_NV_SEED>
+)
diff --git a/platform/ext/target/mps2/an521/config.cmake b/platform/ext/target/mps2/an521/config.cmake
index 945a30e..1d3b682 100644
--- a/platform/ext/target/mps2/an521/config.cmake
+++ b/platform/ext/target/mps2/an521/config.cmake
@@ -6,3 +6,8 @@
 #-------------------------------------------------------------------------------
 
 set(TFM_EXTRA_GENERATED_FILE_LIST_PATH  ${CMAKE_CURRENT_SOURCE_DIR}/platform/ext/target/mps2/an521/generated_file_list.yaml  CACHE PATH "Path to extra generated file list. Appended to stardard TFM generated file list." FORCE)
+
+if(TFM_PSA_API)
+    set(TFM_MBEDCRYPTO_PLATFORM_EXTRA_CONFIG_PATH ${CMAKE_CURRENT_LIST_DIR}/mbedtls_an521_conf.h CACHE FILEPATH "Config to append to standard Mbed Crypto config, used by platforms to configure feature support")
+    set(PLATFORM_DUMMY_NV_SEED        TRUE         CACHE BOOL      "Use dummy NV seed implementation. Should not be used in production.")
+endif()
diff --git a/platform/ext/target/mps2/an521/mbedtls_an521_conf.h b/platform/ext/target/mps2/an521/mbedtls_an521_conf.h
new file mode 100644
index 0000000..6094cb0
--- /dev/null
+++ b/platform/ext/target/mps2/an521/mbedtls_an521_conf.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __MBEDTLS_AN521_CONF_H__
+#define __MBEDTLS_AN521_CONF_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+#undef MBEDTLS_TEST_NULL_ENTROPY
+#undef MBEDTLS_PLATFORM_NO_STD_FUNCTIONS
+#undef MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES
+
+#define MBEDTLS_ENTROPY_NV_SEED
+#ifndef MBEDTLS_PLATFORM_NV_SEED_READ_MACRO
+#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO  tfm_plat_crypto_nv_seed_read
+#endif
+#ifndef MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO
+#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO tfm_plat_crypto_nv_seed_write
+#endif
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __MBEDTLS_AN521_CONF_H__ */
diff --git a/platform/include/tfm_plat_crypto_dummy_nv_seed.h b/platform/include/tfm_plat_crypto_dummy_nv_seed.h
new file mode 100644
index 0000000..08bec76
--- /dev/null
+++ b/platform/include/tfm_plat_crypto_dummy_nv_seed.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_PLAT_CRYPTO_DUMMY_NV_SEED_H__
+#define __TFM_PLAT_CRYPTO_DUMMY_NV_SEED_H__
+
+#include "tfm_plat_crypto_nv_seed.h"
+
+/**
+ * \brief Create a dummy entropy seed when platform doesn't provision the seed.
+ *        Do NOT call this function in production.
+ *
+ * \return Return TFM_CRYPTO_NV_SEED_SUCCESS on success,
+ *         or TFM_CRYPTO_NV_SEED_FAILED on failure.
+ */
+int tfm_plat_crypto_create_entropy_seed(void);
+
+#endif /* __TFM_PLAT_CRYPTO_DUMMY_NV_SEED_H__ */
diff --git a/platform/include/tfm_plat_crypto_nv_seed.h b/platform/include/tfm_plat_crypto_nv_seed.h
new file mode 100644
index 0000000..39b9e37
--- /dev/null
+++ b/platform/include/tfm_plat_crypto_nv_seed.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2021, Arm Limited. All rights reserved.
+ *
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#ifndef __TFM_PLAT_CRYPTO_NV_SEED_H__
+#define __TFM_PLAT_CRYPTO_NV_SEED_H__
+
+#include <stddef.h>
+
+#ifndef NV_SEED_FILE_ID
+#define NV_SEED_FILE_ID 9
+#endif
+
+#define TFM_CRYPTO_NV_SEED_SUCCESS 0
+#define TFM_CRYPTO_NV_SEED_FAILED  -1
+
+/**
+ * \brief Read Seed from NV storage.
+ *
+ * \param[out] buf        Buffer to store the seed
+ * \param[in]  buf_len    Buffer length to read
+ *
+ * \return Return TFM_CRYPTO_NV_SEED_SUCCESS on success,
+ *         or TFM_CRYPTO_NV_SEED_FAILED on failure.
+ */
+int tfm_plat_crypto_nv_seed_read(unsigned char *buf, size_t buf_len);
+
+/**
+ * \brief Write Seed to NV storage.
+ *
+ * \param[in]  buf        Buffer storing the seed
+ * \param[in]  buf_len    Buffer length to write
+ *
+ * \return Return TFM_CRYPTO_NV_SEED_SUCCESS on success,
+ *         or TFM_CRYPTO_NV_SEED_FAILED on failure.
+ */
+int tfm_plat_crypto_nv_seed_write(unsigned char *buf, size_t buf_len);
+
+#endif /* __TFM_PLAT_CRYPTO_NV_SEED_H__ */
diff --git a/secure_fw/partitions/crypto/crypto_init.c b/secure_fw/partitions/crypto/crypto_init.c
index 9b93ea8..d60e897 100644
--- a/secure_fw/partitions/crypto/crypto_init.c
+++ b/secure_fw/partitions/crypto/crypto_init.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2018-2020, Arm Limited. All rights reserved.
+ * Copyright (c) 2018-2021, Arm Limited. All rights reserved.
  *
  * SPDX-License-Identifier: BSD-3-Clause
  *
@@ -17,6 +17,10 @@
  */
 #include "mbedtls/memory_buffer_alloc.h"
 
+#ifdef PLATFORM_DUMMY_NV_SEED
+#include "tfm_plat_crypto_dummy_nv_seed.h"
+#endif
+
 #ifndef TFM_PSA_API
 #include "tfm_secure_api.h"
 #endif
@@ -281,6 +285,12 @@
     LOG_INFFMT("\033[1;34m[Crypto] MBEDTLS_TEST_NULL_ENTROPY is not suitable for production!\033[0m\r\n");
 #endif
 
+#ifdef PLATFORM_DUMMY_NV_SEED
+    if (tfm_plat_crypto_create_entropy_seed() != TFM_CRYPTO_NV_SEED_SUCCESS) {
+        return PSA_ERROR_GENERIC_ERROR;
+    }
+#endif
+
     /* Initialise the Mbed Crypto memory allocator to use static
      * memory allocation from the provided buffer instead of using
      * the heap