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