1 /*
2 * Copyright (c) 2021-2023, Arm Limited. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 *
6 */
7
8 #include "tfm_plat_provisioning.h"
9
10 #include "cmsis_compiler.h"
11 #include "tfm_plat_otp.h"
12 #include "tfm_attest_hal.h"
13 #include "crypto.h"
14 #include "region_defs.h"
15 #include "log.h"
16 #include "fwu_agent.h"
17
18 #include <string.h>
19
20 #define ASSEMBLY_AND_TEST_PROV_DATA_MAGIC 0xC0DEFEED
21
22 __PACKED_STRUCT bl1_assembly_and_test_provisioning_data_t {
23 uint32_t magic;
24 uint8_t bl2_encryption_key[32];
25 uint8_t guk[32];
26 uint8_t bl1_2_image_hash[32];
27 uint8_t bl2_image_hash[32];
28 uint8_t bl1_2_image[BL1_2_CODE_SIZE];
29 uint8_t bl1_2_image_len[4];
30 uint8_t bl1_rotpk_0[56];
31 };
32
33 static const struct bl1_assembly_and_test_provisioning_data_t *bl1_assembly_and_test_prov_data =
34 (struct bl1_assembly_and_test_provisioning_data_t *)PROVISIONING_DATA_START;
35
36
tfm_plat_provisioning_check_for_dummy_keys(void)37 void tfm_plat_provisioning_check_for_dummy_keys(void)
38 {
39 }
40
tfm_plat_provisioning_is_required(void)41 int tfm_plat_provisioning_is_required(void)
42 {
43 enum tfm_plat_err_t err;
44 enum plat_otp_lcs_t lcs;
45
46 err = tfm_plat_otp_read(PLAT_OTP_ID_LCS, sizeof(lcs), (uint8_t*)&lcs);
47 if (err != TFM_PLAT_ERR_SUCCESS) {
48 return err;
49 }
50
51 return lcs == PLAT_OTP_LCS_ASSEMBLY_AND_TEST
52 || lcs == PLAT_OTP_LCS_PSA_ROT_PROVISIONING;
53 }
54
provision_assembly_and_test(void)55 enum tfm_plat_err_t provision_assembly_and_test(void)
56 {
57 enum tfm_plat_err_t err;
58 err = tfm_plat_otp_write(PLAT_OTP_ID_BL1_ROTPK_0,
59 sizeof(bl1_assembly_and_test_prov_data->bl1_rotpk_0),
60 bl1_assembly_and_test_prov_data->bl1_rotpk_0);
61 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
62 return err;
63 }
64
65
66 err = tfm_plat_otp_write(PLAT_OTP_ID_BL1_2_IMAGE_HASH,
67 sizeof(bl1_assembly_and_test_prov_data->bl1_2_image_hash),
68 bl1_assembly_and_test_prov_data->bl1_2_image_hash);
69 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
70 return err;
71 }
72
73
74 err = tfm_plat_otp_write(PLAT_OTP_ID_BL1_2_IMAGE,
75 sizeof(bl1_assembly_and_test_prov_data->bl1_2_image),
76 bl1_assembly_and_test_prov_data->bl1_2_image);
77 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
78 return err;
79 }
80
81 err = tfm_plat_otp_write(PLAT_OTP_ID_BL1_2_IMAGE_LEN,
82 sizeof(bl1_assembly_and_test_prov_data->bl1_2_image_len),
83 bl1_assembly_and_test_prov_data->bl1_2_image_len);
84 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
85 return err;
86 }
87
88 err = tfm_plat_otp_write(PLAT_OTP_ID_KEY_BL2_ENCRYPTION,
89 sizeof(bl1_assembly_and_test_prov_data->bl2_encryption_key),
90 bl1_assembly_and_test_prov_data->bl2_encryption_key);
91 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
92 return err;
93 }
94
95 err = tfm_plat_otp_write(PLAT_OTP_ID_BL2_IMAGE_HASH,
96 sizeof(bl1_assembly_and_test_prov_data->bl2_image_hash),
97 bl1_assembly_and_test_prov_data->bl2_image_hash);
98 if (err != TFM_PLAT_ERR_SUCCESS && err != TFM_PLAT_ERR_UNSUPPORTED) {
99 return err;
100 }
101
102 err = fwu_metadata_provision();
103 if (err != FWU_AGENT_SUCCESS) {
104 return 1;
105 }
106
107 return err;
108 }
109
tfm_plat_provisioning_perform(void)110 enum tfm_plat_err_t tfm_plat_provisioning_perform(void)
111 {
112 enum tfm_plat_err_t err;
113 enum plat_otp_lcs_t lcs;
114
115 err = tfm_plat_otp_read(PLAT_OTP_ID_LCS, sizeof(lcs), (uint8_t*)&lcs);
116 if (err != TFM_PLAT_ERR_SUCCESS) {
117 return err;
118 }
119
120 BL1_LOG("[INF] Beginning BL1 provisioning\r\n");
121
122 #ifdef TFM_DUMMY_PROVISIONING
123 BL1_LOG("\033[1;31m[WRN]");
124 BL1_LOG("TFM_DUMMY_PROVISIONING is not suitable for production! ");
125 BL1_LOG("This device is \033[1;1mNOT SECURE");
126 BL1_LOG("\033[0m\r\n");
127 #endif /* TFM_DUMMY_PROVISIONING */
128
129 if (lcs == PLAT_OTP_LCS_ASSEMBLY_AND_TEST) {
130 if (bl1_assembly_and_test_prov_data->magic != ASSEMBLY_AND_TEST_PROV_DATA_MAGIC) {
131 BL1_LOG("[ERR] No valid ASSEMBLY_AND_TEST provisioning data found\r\n");
132 return TFM_PLAT_ERR_INVALID_INPUT;
133 }
134
135 err = provision_assembly_and_test();
136 if (err != TFM_PLAT_ERR_SUCCESS) {
137 return err;
138 }
139 }
140
141 return TFM_PLAT_ERR_SUCCESS;
142 }
143