1 /*
2 * SPDX-FileCopyrightText: 2019-2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include "esp_efuse.h"
8 #include "esp_efuse_utility.h"
9 #include "hal/efuse_ll.h"
10 #include "assert.h"
11 #include "sdkconfig.h"
12 #include "esp_efuse_table.h"
13
14 /*
15 * FE uses eFuse block1.
16 * SB uses eFuse block2.
17 * Block3 can be used by customer.
18 * There are no eFuse key purpose fields (added only virtual key purposes to support key APIs).
19 */
20
21 static __attribute__((unused)) const char *TAG = "efuse";
22
23 /**
24 * @brief Keys and their attributes are packed into a structure
25 */
26 typedef struct {
27 const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
28 const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
29 } esp_efuse_keys_t;
30
31 const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
32 {ESP_EFUSE_RD_DIS_BLK1, ESP_EFUSE_WR_DIS_BLK1},
33 {ESP_EFUSE_RD_DIS_BLK2, ESP_EFUSE_WR_DIS_BLK2},
34 {ESP_EFUSE_RD_DIS_BLK3, ESP_EFUSE_WR_DIS_BLK3},
35 };
36
37
38 // Sets a write protection for the whole block.
esp_efuse_set_write_protect(esp_efuse_block_t blk)39 esp_err_t esp_efuse_set_write_protect(esp_efuse_block_t blk)
40 {
41 if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
42 return ESP_ERR_NOT_SUPPORTED;
43 }
44 unsigned idx = blk - EFUSE_BLK1;
45 return esp_efuse_write_field_cnt(s_table[idx].key_wr_dis, 1);
46 }
47
48 // read protect for blk.
esp_efuse_set_read_protect(esp_efuse_block_t blk)49 esp_err_t esp_efuse_set_read_protect(esp_efuse_block_t blk)
50 {
51 if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX) {
52 return ESP_ERR_NOT_SUPPORTED;
53 }
54 unsigned idx = blk - EFUSE_BLK1;
55 return esp_efuse_write_field_cnt(s_table[idx].key_rd_dis, 1);
56 }
57
58 // get efuse coding_scheme.
esp_efuse_get_coding_scheme(esp_efuse_block_t blk)59 esp_efuse_coding_scheme_t esp_efuse_get_coding_scheme(esp_efuse_block_t blk)
60 {
61 esp_efuse_coding_scheme_t scheme;
62 if (blk == EFUSE_BLK0) {
63 scheme = EFUSE_CODING_SCHEME_NONE;
64 } else {
65 uint32_t coding_scheme = efuse_ll_get_coding_scheme();
66 if (coding_scheme == EFUSE_CODING_SCHEME_VAL_NONE ||
67 coding_scheme == (EFUSE_CODING_SCHEME_VAL_34 | EFUSE_CODING_SCHEME_VAL_REPEAT)) {
68 scheme = EFUSE_CODING_SCHEME_NONE;
69 } else if (coding_scheme == EFUSE_CODING_SCHEME_VAL_34) {
70 scheme = EFUSE_CODING_SCHEME_3_4;
71 } else {
72 scheme = EFUSE_CODING_SCHEME_REPEAT;
73 }
74 }
75 return scheme;
76 }
77
esp_efuse_block_is_empty(esp_efuse_block_t block)78 bool esp_efuse_block_is_empty(esp_efuse_block_t block)
79 {
80 unsigned blk_len_bit = 256;
81 uint32_t key[8];
82 if (esp_efuse_get_coding_scheme(block) == EFUSE_CODING_SCHEME_3_4) {
83 blk_len_bit = 192;
84 }
85 esp_err_t err = esp_efuse_read_block(block, &key, 0, blk_len_bit);
86 if (err != ESP_OK) {
87 return false;
88 }
89 unsigned zeros = 0;
90 for (unsigned i = 0; i < blk_len_bit / 32; ++i) {
91 if (key[i] == 0) {
92 ++zeros;
93 }
94 }
95 if (zeros == blk_len_bit / 32) {
96 return true;
97 }
98 return false;
99 }
100
esp_efuse_get_key_dis_read(esp_efuse_block_t block)101 bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
102 {
103 assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
104 unsigned idx = block - EFUSE_BLK_KEY0;
105 return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
106 }
107
esp_efuse_set_key_dis_read(esp_efuse_block_t block)108 esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
109 {
110 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
111 return ESP_ERR_INVALID_ARG;
112 }
113 unsigned idx = block - EFUSE_BLK_KEY0;
114 return esp_efuse_write_field_bit(s_table[idx].key_rd_dis);
115 }
116
esp_efuse_get_key_dis_write(esp_efuse_block_t block)117 bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
118 {
119 assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
120 unsigned idx = block - EFUSE_BLK_KEY0;
121 return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
122 }
123
esp_efuse_set_key_dis_write(esp_efuse_block_t block)124 esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
125 {
126 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
127 return ESP_ERR_INVALID_ARG;
128 }
129 unsigned idx = block - EFUSE_BLK_KEY0;
130 return esp_efuse_write_field_bit(s_table[idx].key_wr_dis);
131 }
132
esp_efuse_key_block_unused(esp_efuse_block_t block)133 bool esp_efuse_key_block_unused(esp_efuse_block_t block)
134 {
135 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
136 return false; // Not a key block
137 }
138
139 if (esp_efuse_get_key_dis_read(block) || esp_efuse_get_key_dis_write(block) ||
140 !esp_efuse_block_is_empty(block)) {
141 return false; // Block in use!
142 }
143
144 return true; // Unused
145 }
146
esp_efuse_get_key_purpose(esp_efuse_block_t block)147 esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
148 {
149 esp_efuse_purpose_t ret_purpose;
150 if (block == EFUSE_BLK0) {
151 ret_purpose = ESP_EFUSE_KEY_PURPOSE_SYSTEM;
152 } else if (block == EFUSE_BLK_ENCRYPT_FLASH) {
153 ret_purpose = ESP_EFUSE_KEY_PURPOSE_FLASH_ENCRYPTION;
154 } else if (block == EFUSE_BLK_SECURE_BOOT) {
155 ret_purpose = ESP_EFUSE_KEY_PURPOSE_SECURE_BOOT_V2;
156 } else if (block == EFUSE_BLK3) {
157 ret_purpose = ESP_EFUSE_KEY_PURPOSE_USER;
158 } else {
159 ret_purpose = ESP_EFUSE_KEY_PURPOSE_MAX;
160 }
161 return ret_purpose;
162 }
163
esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)164 bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
165 {
166 (void)block;
167 return true;
168 }
169
esp_efuse_find_purpose(esp_efuse_purpose_t purpose,esp_efuse_block_t * block)170 bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
171 {
172 esp_efuse_block_t dummy;
173 if (block == NULL) {
174 block = &dummy;
175 }
176
177 for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
178 if (esp_efuse_get_key_purpose(b) == purpose) {
179 *block = b;
180 return true;
181 }
182 }
183
184 return false;
185 }
186
esp_efuse_write_key(esp_efuse_block_t block,esp_efuse_purpose_t purpose,const void * key,size_t key_size_bytes)187 esp_err_t esp_efuse_write_key(esp_efuse_block_t block, esp_efuse_purpose_t purpose, const void *key, size_t key_size_bytes)
188 {
189 esp_err_t err = ESP_OK;
190 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX
191 || esp_efuse_get_key_purpose(block) != purpose) {
192 return ESP_ERR_INVALID_ARG;
193 }
194
195 esp_efuse_batch_write_begin();
196
197 if (!esp_efuse_key_block_unused(block)) {
198 err = ESP_ERR_INVALID_STATE;
199 } else {
200 ESP_EFUSE_CHK(esp_efuse_write_block(block, key, 0, key_size_bytes * 8));
201 ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
202 if (purpose == ESP_EFUSE_KEY_PURPOSE_FLASH_ENCRYPTION) {
203 ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
204 }
205 return esp_efuse_batch_write_commit();
206 }
207 err_exit:
208 esp_efuse_batch_write_cancel();
209 return err;
210 }
211
esp_efuse_write_keys(const esp_efuse_purpose_t purposes[],uint8_t keys[][32],unsigned number_of_keys)212 esp_err_t esp_efuse_write_keys(const esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
213 {
214 esp_err_t err = ESP_FAIL;
215 if (number_of_keys == 0 || number_of_keys > (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) || keys == NULL || purposes == NULL) {
216 return ESP_ERR_INVALID_ARG;
217 }
218
219 size_t key_size = 32;
220 esp_efuse_coding_scheme_t coding_scheme = esp_efuse_get_coding_scheme(EFUSE_BLK_KEY0);
221 if (coding_scheme == EFUSE_CODING_SCHEME_3_4) {
222 key_size = 24;
223 }
224 esp_efuse_purpose_t purpose = 0;
225 esp_efuse_block_t block = EFUSE_BLK_KEY0;
226
227 esp_efuse_batch_write_begin();
228 for (unsigned i_key = 0; (block < EFUSE_BLK_KEY_MAX) && (i_key < number_of_keys); block++) {
229 purpose = purposes[i_key];
230 if (esp_efuse_get_key_purpose(block) == purpose) {
231 ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY%d with purpose %d", block - EFUSE_BLK_KEY0, purpose);
232 ESP_EFUSE_CHK(esp_efuse_write_key(block, purpose, keys[i_key], key_size));
233 i_key++;
234 }
235 }
236 return esp_efuse_batch_write_commit();
237 err_exit:
238 ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY%d with purpose %d. Can't continue.", block - EFUSE_BLK_KEY0, purpose);
239 esp_efuse_batch_write_cancel();
240 return err;
241 }
242
243 #if CONFIG_ESP32_REV_MIN_FULL >= 300
esp_secure_boot_read_key_digests(esp_secure_boot_key_digests_t * trusted_keys)244 esp_err_t esp_secure_boot_read_key_digests(esp_secure_boot_key_digests_t *trusted_keys)
245 {
246 if (trusted_keys == NULL) {
247 return ESP_FAIL;
248 }
249 trusted_keys->key_digests[0] = (const void *)esp_efuse_utility_get_read_register_address(EFUSE_BLK_SECURE_BOOT);
250 return ESP_OK;
251 }
252 #endif // CONFIG_ESP32_REV_MIN_FULL >= 300
253