1 // Copyright 2017-2018 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "esp_efuse.h"
16 #include "esp_efuse_utility.h"
17 #include "soc/efuse_periph.h"
18 #include "assert.h"
19 #include "sdkconfig.h"
20 #include "esp_efuse_table.h"
21
22 const static char *TAG = "efuse";
23
24 #if defined(BOOTLOADER_BUILD)
25 #define EFUSE_LOCK_ACQUIRE_RECURSIVE()
26 #define EFUSE_LOCK_RELEASE_RECURSIVE()
27 #else
28 #include <sys/lock.h>
29 static _lock_t s_efuse_lock = 0;
30 #define EFUSE_LOCK_ACQUIRE_RECURSIVE() _lock_acquire_recursive(&s_efuse_lock)
31 #define EFUSE_LOCK_RELEASE_RECURSIVE() _lock_release_recursive(&s_efuse_lock)
32 #endif
33
34 static int s_batch_writing_mode = 0;
35
36 // Public API functions
37
38 // read value from EFUSE, writing it into an array
esp_efuse_read_field_blob(const esp_efuse_desc_t * field[],void * dst,size_t dst_size_bits)39 esp_err_t esp_efuse_read_field_blob(const esp_efuse_desc_t* field[], void* dst, size_t dst_size_bits)
40 {
41 EFUSE_LOCK_ACQUIRE_RECURSIVE();
42 esp_err_t err = ESP_OK;
43 if (field == NULL || dst == NULL || dst_size_bits == 0) {
44 err = ESP_ERR_INVALID_ARG;
45 } else {
46 memset((uint8_t *)dst, 0, esp_efuse_utility_get_number_of_items(dst_size_bits, 8));
47 err = esp_efuse_utility_process(field, dst, dst_size_bits, esp_efuse_utility_fill_buff);
48 }
49 EFUSE_LOCK_RELEASE_RECURSIVE();
50 return err;
51 }
52
esp_efuse_read_field_bit(const esp_efuse_desc_t * field[])53 bool esp_efuse_read_field_bit(const esp_efuse_desc_t *field[])
54 {
55 uint8_t value = 0;
56 esp_err_t err = esp_efuse_read_field_blob(field, &value, 1);
57 assert(err == ESP_OK);
58 return (err == ESP_OK) && value;
59 }
60
61 // read number of bits programmed as "1" in the particular field
esp_efuse_read_field_cnt(const esp_efuse_desc_t * field[],size_t * out_cnt)62 esp_err_t esp_efuse_read_field_cnt(const esp_efuse_desc_t* field[], size_t* out_cnt)
63 {
64 EFUSE_LOCK_ACQUIRE_RECURSIVE();
65 esp_err_t err = ESP_OK;
66 if (field == NULL || out_cnt == NULL) {
67 err = ESP_ERR_INVALID_ARG;
68 } else {
69 *out_cnt = 0;
70 err = esp_efuse_utility_process(field, out_cnt, 0, esp_efuse_utility_count_once);
71 }
72 EFUSE_LOCK_RELEASE_RECURSIVE();
73 return err;
74 }
75
76 // write array to EFUSE
esp_efuse_write_field_blob(const esp_efuse_desc_t * field[],const void * src,size_t src_size_bits)77 esp_err_t esp_efuse_write_field_blob(const esp_efuse_desc_t* field[], const void* src, size_t src_size_bits)
78 {
79 EFUSE_LOCK_ACQUIRE_RECURSIVE();
80 esp_err_t err = ESP_OK;
81 if (field == NULL || src == NULL || src_size_bits == 0) {
82 err = ESP_ERR_INVALID_ARG;
83 } else {
84 if (s_batch_writing_mode == 0) {
85 esp_efuse_utility_reset();
86 }
87 err = esp_efuse_utility_process(field, (void*)src, src_size_bits, esp_efuse_utility_write_blob);
88
89 if (s_batch_writing_mode == 0) {
90 if (err == ESP_OK) {
91 err = esp_efuse_utility_apply_new_coding_scheme();
92 if (err == ESP_OK) {
93 esp_efuse_utility_burn_efuses();
94 }
95 }
96 esp_efuse_utility_reset();
97 }
98 }
99 EFUSE_LOCK_RELEASE_RECURSIVE();
100 return err;
101 }
102
103 // program cnt bits to "1"
esp_efuse_write_field_cnt(const esp_efuse_desc_t * field[],size_t cnt)104 esp_err_t esp_efuse_write_field_cnt(const esp_efuse_desc_t* field[], size_t cnt)
105 {
106 EFUSE_LOCK_ACQUIRE_RECURSIVE();
107 esp_err_t err = ESP_OK;
108 if (field == NULL || cnt == 0) {
109 err = ESP_ERR_INVALID_ARG;
110 } else {
111 if (s_batch_writing_mode == 0) {
112 esp_efuse_utility_reset();
113 }
114 err = esp_efuse_utility_process(field, &cnt, 0, esp_efuse_utility_write_cnt);
115
116 if (cnt != 0) {
117 ESP_LOGE(TAG, "The required number of bits can not be set. [Not set %d]", cnt);
118 err = ESP_ERR_EFUSE_CNT_IS_FULL;
119 }
120 if (err == ESP_OK_EFUSE_CNT) {
121 err = ESP_OK;
122 }
123
124 if (s_batch_writing_mode == 0) {
125 if (err == ESP_OK) {
126 err = esp_efuse_utility_apply_new_coding_scheme();
127 if (err == ESP_OK) {
128 esp_efuse_utility_burn_efuses();
129 }
130 }
131 esp_efuse_utility_reset();
132 }
133 }
134 EFUSE_LOCK_RELEASE_RECURSIVE();
135 return err;
136 }
137
esp_efuse_write_field_bit(const esp_efuse_desc_t * field[])138 esp_err_t esp_efuse_write_field_bit(const esp_efuse_desc_t* field[])
139 {
140 esp_err_t err;
141 uint8_t existing = 0;
142 const uint8_t one = 1;
143
144 if (field == NULL || field[0]->bit_count != 1) {
145 return ESP_ERR_INVALID_ARG;
146 }
147
148 /* Check existing value. esp_efuse_write_field_blob() also checks this, but will log an error */
149 err = esp_efuse_read_field_blob(field, &existing, 1);
150 if (err != ESP_OK || existing) {
151 return err; // Error reading, or the bit is already written and we can no-op this
152 }
153
154 return esp_efuse_write_field_blob(field, &one, 1);
155 }
156
157 // get the length of the field in bits
esp_efuse_get_field_size(const esp_efuse_desc_t * field[])158 int esp_efuse_get_field_size(const esp_efuse_desc_t* field[])
159 {
160 int bits_counter = 0;
161 if (field != NULL) {
162 int i = 0;
163 while (field[i] != NULL) {
164 bits_counter += field[i]->bit_count;
165 ++i;
166 }
167 }
168 return bits_counter;
169 }
170
171 // reading efuse register.
esp_efuse_read_reg(esp_efuse_block_t blk,unsigned int num_reg)172 uint32_t esp_efuse_read_reg(esp_efuse_block_t blk, unsigned int num_reg)
173 {
174 EFUSE_LOCK_ACQUIRE_RECURSIVE();
175 uint32_t ret_val = esp_efuse_utility_read_reg(blk, num_reg);
176 EFUSE_LOCK_RELEASE_RECURSIVE();
177 return ret_val;
178 }
179
180 // writing efuse register.
esp_efuse_write_reg(esp_efuse_block_t blk,unsigned int num_reg,uint32_t val)181 esp_err_t esp_efuse_write_reg(esp_efuse_block_t blk, unsigned int num_reg, uint32_t val)
182 {
183 EFUSE_LOCK_ACQUIRE_RECURSIVE();
184 if (s_batch_writing_mode == 0) {
185 esp_efuse_utility_reset();
186 }
187 esp_err_t err = esp_efuse_utility_write_reg(blk, num_reg, val);
188 if (s_batch_writing_mode == 0) {
189 if (err == ESP_OK) {
190 err = esp_efuse_utility_apply_new_coding_scheme();
191 if (err == ESP_OK) {
192 esp_efuse_utility_burn_efuses();
193 }
194 }
195 esp_efuse_utility_reset();
196 }
197 EFUSE_LOCK_RELEASE_RECURSIVE();
198 return err;
199 }
200
201 // This function reads the key from the efuse block, starting at the offset and the required size.
esp_efuse_read_block(esp_efuse_block_t blk,void * dst_key,size_t offset_in_bits,size_t size_bits)202 esp_err_t esp_efuse_read_block(esp_efuse_block_t blk, void* dst_key, size_t offset_in_bits, size_t size_bits)
203 {
204 esp_err_t err = ESP_OK;
205 if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || dst_key == NULL || size_bits == 0) {
206 err = ESP_ERR_INVALID_ARG;
207 } else {
208 const esp_efuse_desc_t field_desc[] = {
209 {blk, offset_in_bits, size_bits},
210 };
211
212 const esp_efuse_desc_t* field[] = {
213 &field_desc[0],
214 NULL
215 };
216 err = esp_efuse_read_field_blob(field, dst_key, size_bits);
217 }
218 return err;
219 }
220
221 // This function writes the key from the efuse block, starting at the offset and the required size.
esp_efuse_write_block(esp_efuse_block_t blk,const void * src_key,size_t offset_in_bits,size_t size_bits)222 esp_err_t esp_efuse_write_block(esp_efuse_block_t blk, const void* src_key, size_t offset_in_bits, size_t size_bits)
223 {
224 esp_err_t err = ESP_OK;
225 if (blk == EFUSE_BLK0 || blk >= EFUSE_BLK_MAX || src_key == NULL || size_bits == 0) {
226 err = ESP_ERR_INVALID_ARG;
227 } else {
228 const esp_efuse_desc_t field_desc[] = {
229 {blk, offset_in_bits, size_bits},
230 };
231
232 const esp_efuse_desc_t* field[] = {
233 &field_desc[0],
234 NULL
235 };
236 err = esp_efuse_write_field_blob(field, src_key, size_bits);
237 }
238 return err;
239 }
240
esp_efuse_batch_write_begin(void)241 esp_err_t esp_efuse_batch_write_begin(void)
242 {
243 EFUSE_LOCK_ACQUIRE_RECURSIVE();
244 assert(s_batch_writing_mode >= 0);
245 if (++s_batch_writing_mode == 1) {
246 esp_efuse_utility_reset();
247 ESP_LOGI(TAG, "Batch mode of writing fields is enabled");
248 };
249 return ESP_OK;
250 }
251
esp_efuse_batch_write_cancel(void)252 esp_err_t esp_efuse_batch_write_cancel(void)
253 {
254 if (s_batch_writing_mode == 0) {
255 ESP_LOGE(TAG, "Batch mode was not enabled");
256 return ESP_ERR_INVALID_STATE;
257 }
258 if (--s_batch_writing_mode == 0) {
259 esp_efuse_utility_reset();
260 ESP_LOGI(TAG, "Batch mode of writing fields is cancelled");
261 EFUSE_LOCK_RELEASE_RECURSIVE();
262 }
263 return ESP_OK;
264 }
265
esp_efuse_batch_write_commit(void)266 esp_err_t esp_efuse_batch_write_commit(void)
267 {
268 if (s_batch_writing_mode == 0) {
269 ESP_LOGE(TAG, "Batch mode was not enabled");
270 return ESP_ERR_INVALID_STATE;
271 }
272 if (--s_batch_writing_mode == 0) {
273 esp_err_t err = esp_efuse_utility_apply_new_coding_scheme();
274 if (err == ESP_OK) {
275 esp_efuse_utility_burn_efuses();
276 ESP_LOGI(TAG, "Batch mode. Prepared fields are committed");
277 } else {
278 esp_efuse_utility_reset();
279 }
280 EFUSE_LOCK_RELEASE_RECURSIVE();
281 return err;
282 }
283 return ESP_OK;
284 }
285
286
287 #ifndef CONFIG_IDF_TARGET_ESP32
288
289 /**
290 * @brief Keys and their attributes are packed into a structure
291 */
292 typedef struct {
293 const esp_efuse_desc_t** key; /**< Key */
294 const esp_efuse_desc_t** keypurpose; /**< Key purpose */
295 const esp_efuse_desc_t** key_rd_dis; /**< Read protection of a key */
296 const esp_efuse_desc_t** key_wr_dis; /**< Write protection of a key*/
297 const esp_efuse_desc_t** keypurpose_wr_dis; /**< Write protection of a key purpose*/
298 } esp_efuse_keys_t;
299
300 typedef struct {
301 const esp_efuse_desc_t** revoke;
302 const esp_efuse_desc_t** revoke_wr_dis;
303 } esp_efuse_revokes_t;
304
305 const esp_efuse_keys_t s_table[EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0] = {
306 {ESP_EFUSE_KEY0, ESP_EFUSE_KEY_PURPOSE_0, ESP_EFUSE_RD_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0, ESP_EFUSE_WR_DIS_KEY0_PURPOSE},
307 {ESP_EFUSE_KEY1, ESP_EFUSE_KEY_PURPOSE_1, ESP_EFUSE_RD_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1, ESP_EFUSE_WR_DIS_KEY1_PURPOSE},
308 {ESP_EFUSE_KEY2, ESP_EFUSE_KEY_PURPOSE_2, ESP_EFUSE_RD_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2, ESP_EFUSE_WR_DIS_KEY2_PURPOSE},
309 {ESP_EFUSE_KEY3, ESP_EFUSE_KEY_PURPOSE_3, ESP_EFUSE_RD_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3, ESP_EFUSE_WR_DIS_KEY3_PURPOSE},
310 {ESP_EFUSE_KEY4, ESP_EFUSE_KEY_PURPOSE_4, ESP_EFUSE_RD_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4, ESP_EFUSE_WR_DIS_KEY4_PURPOSE},
311 {ESP_EFUSE_KEY5, ESP_EFUSE_KEY_PURPOSE_5, ESP_EFUSE_RD_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5, ESP_EFUSE_WR_DIS_KEY5_PURPOSE},
312 #if 0
313 {ESP_EFUSE_KEY6, ESP_EFUSE_KEY_PURPOSE_6, ESP_EFUSE_RD_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6, ESP_EFUSE_WR_DIS_KEY6_PURPOSE},
314 #endif
315 };
316
317 const esp_efuse_revokes_t s_revoke_table[] = {
318 {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE0, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE0},
319 {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE1, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE1},
320 {ESP_EFUSE_SECURE_BOOT_KEY_REVOKE2, ESP_EFUSE_WR_DIS_SECURE_BOOT_KEY_REVOKE2},
321 };
322
323 #define ESP_EFUSE_CHK(ret) \
324 do \
325 { \
326 if( ( err = (ret) ) != ESP_OK ) \
327 goto err_exit; \
328 } while( 0 )
329
330
esp_efuse_get_purpose_field(esp_efuse_block_t block)331 const esp_efuse_desc_t **esp_efuse_get_purpose_field(esp_efuse_block_t block)
332 {
333 switch(block) {
334 case EFUSE_BLK_KEY0:
335 return ESP_EFUSE_KEY_PURPOSE_0;
336 case EFUSE_BLK_KEY1:
337 return ESP_EFUSE_KEY_PURPOSE_1;
338 case EFUSE_BLK_KEY2:
339 return ESP_EFUSE_KEY_PURPOSE_2;
340 case EFUSE_BLK_KEY3:
341 return ESP_EFUSE_KEY_PURPOSE_3;
342 case EFUSE_BLK_KEY4:
343 return ESP_EFUSE_KEY_PURPOSE_4;
344 case EFUSE_BLK_KEY5:
345 return ESP_EFUSE_KEY_PURPOSE_5;
346 default:
347 return NULL;
348 }
349 }
350
esp_efuse_get_key(esp_efuse_block_t block)351 const esp_efuse_desc_t** esp_efuse_get_key(esp_efuse_block_t block)
352 {
353 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
354 return NULL;
355 }
356 unsigned idx = block - EFUSE_BLK_KEY0;
357 return s_table[idx].key;
358 }
359
esp_efuse_get_key_dis_read(esp_efuse_block_t block)360 bool esp_efuse_get_key_dis_read(esp_efuse_block_t block)
361 {
362 assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
363 unsigned idx = block - EFUSE_BLK_KEY0;
364 return esp_efuse_read_field_bit(s_table[idx].key_rd_dis);
365 }
366
esp_efuse_set_key_dis_read(esp_efuse_block_t block)367 esp_err_t esp_efuse_set_key_dis_read(esp_efuse_block_t block)
368 {
369 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
370 return ESP_ERR_INVALID_ARG;
371 }
372 unsigned idx = block - EFUSE_BLK_KEY0;
373 const uint8_t one = 1;
374 return esp_efuse_write_field_blob(s_table[idx].key_rd_dis, &one, 1);
375 }
376
esp_efuse_get_key_dis_write(esp_efuse_block_t block)377 bool esp_efuse_get_key_dis_write(esp_efuse_block_t block)
378 {
379 assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
380 unsigned idx = block - EFUSE_BLK_KEY0;
381 return esp_efuse_read_field_bit(s_table[idx].key_wr_dis);
382 }
383
esp_efuse_set_key_dis_write(esp_efuse_block_t block)384 esp_err_t esp_efuse_set_key_dis_write(esp_efuse_block_t block)
385 {
386 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
387 return ESP_ERR_INVALID_ARG;
388 }
389 unsigned idx = block - EFUSE_BLK_KEY0;
390 const uint8_t one = 1;
391 return esp_efuse_write_field_blob(s_table[idx].key_wr_dis, &one, 1);
392 }
393
esp_efuse_get_key_purpose(esp_efuse_block_t block)394 esp_efuse_purpose_t esp_efuse_get_key_purpose(esp_efuse_block_t block)
395 {
396 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
397 return ESP_EFUSE_KEY_PURPOSE_MAX;
398 }
399 unsigned idx = block - EFUSE_BLK_KEY0;
400 uint8_t value = 0;
401 esp_err_t err = esp_efuse_read_field_blob(s_table[idx].keypurpose, &value, s_table[idx].keypurpose[0]->bit_count);
402 if (err != ESP_OK) {
403 return ESP_EFUSE_KEY_PURPOSE_MAX;
404 }
405 return value;
406 }
407
esp_efuse_set_key_purpose(esp_efuse_block_t block,esp_efuse_purpose_t purpose)408 esp_err_t esp_efuse_set_key_purpose(esp_efuse_block_t block, esp_efuse_purpose_t purpose)
409 {
410 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
411 return ESP_ERR_INVALID_ARG;
412 }
413 unsigned idx = block - EFUSE_BLK_KEY0;
414 return esp_efuse_write_field_blob(s_table[idx].keypurpose, &purpose, s_table[idx].keypurpose[0]->bit_count);
415 }
416
esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)417 bool esp_efuse_get_keypurpose_dis_write(esp_efuse_block_t block)
418 {
419 assert(block >= EFUSE_BLK_KEY0 && block < EFUSE_BLK_KEY_MAX);
420 unsigned idx = block - EFUSE_BLK_KEY0;
421 return esp_efuse_read_field_bit(s_table[idx].keypurpose_wr_dis);
422 }
423
esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block)424 esp_err_t esp_efuse_set_keypurpose_dis_write(esp_efuse_block_t block)
425 {
426 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
427 return ESP_ERR_INVALID_ARG;
428 }
429 unsigned idx = block - EFUSE_BLK_KEY0;
430 const uint8_t one = 1;
431 return esp_efuse_write_field_blob(s_table[idx].keypurpose_wr_dis, &one, 1);
432 }
433
esp_efuse_find_purpose(esp_efuse_purpose_t purpose,esp_efuse_block_t * block)434 bool esp_efuse_find_purpose(esp_efuse_purpose_t purpose, esp_efuse_block_t *block)
435 {
436 esp_efuse_block_t dummy;
437 if (block == NULL) {
438 block = &dummy;
439 }
440
441 for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
442 if (esp_efuse_get_key_purpose(b) == purpose) {
443 *block = b;
444 return true;
445 }
446 }
447
448 return false;
449 }
450
esp_efuse_find_unused_key_block(void)451 esp_efuse_block_t esp_efuse_find_unused_key_block(void)
452 {
453 for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
454 if (esp_efuse_key_block_unused(b)) {
455 return b;
456 }
457 }
458 return EFUSE_BLK_KEY_MAX; // nothing
459 }
460
esp_efuse_count_unused_key_blocks(void)461 unsigned esp_efuse_count_unused_key_blocks(void)
462 {
463 unsigned r = 0;
464 for (esp_efuse_block_t b = EFUSE_BLK_KEY0; b < EFUSE_BLK_KEY_MAX; b++) {
465 if (esp_efuse_key_block_unused(b)) {
466 r++;
467 }
468 }
469 return r;
470 }
471
esp_efuse_key_block_unused(esp_efuse_block_t block)472 bool esp_efuse_key_block_unused(esp_efuse_block_t block)
473 {
474 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX) {
475 return false; // Not a key block
476 }
477
478 if (esp_efuse_get_key_purpose(block) != ESP_EFUSE_KEY_PURPOSE_USER ||
479 esp_efuse_get_keypurpose_dis_write(block) ||
480 esp_efuse_get_key_dis_read(block) ||
481 esp_efuse_get_key_dis_write(block)) {
482 return false; // Block in use!
483 }
484
485 for (int i = 0; i < 8; ++i) {
486 if (esp_efuse_read_reg(block, i) != 0) {
487 return false; // Block in use!
488 }
489 }
490
491 return true; // Unused
492 }
493
esp_efuse_get_digest_revoke(unsigned num_digest)494 bool esp_efuse_get_digest_revoke(unsigned num_digest)
495 {
496 assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
497 return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke);
498 }
499
esp_efuse_set_digest_revoke(unsigned num_digest)500 esp_err_t esp_efuse_set_digest_revoke(unsigned num_digest)
501 {
502 if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
503 return ESP_ERR_INVALID_ARG;
504 }
505 return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke);
506 }
507
esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest)508 bool esp_efuse_get_write_protect_of_digest_revoke(unsigned num_digest)
509 {
510 assert(num_digest < sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t));
511 return esp_efuse_read_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
512 }
513
esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest)514 esp_err_t esp_efuse_set_write_protect_of_digest_revoke(unsigned num_digest)
515 {
516 if (num_digest >= sizeof(s_revoke_table) / sizeof(esp_efuse_revokes_t)) {
517 return ESP_ERR_INVALID_ARG;
518 }
519 return esp_efuse_write_field_bit(s_revoke_table[num_digest].revoke_wr_dis);
520 }
521
esp_efuse_write_key(esp_efuse_block_t block,esp_efuse_purpose_t purpose,const void * key,size_t key_size_bytes)522 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)
523 {
524 esp_err_t err = ESP_OK;
525 if (block < EFUSE_BLK_KEY0 || block >= EFUSE_BLK_KEY_MAX || key_size_bytes > 32 || purpose >= ESP_EFUSE_KEY_PURPOSE_MAX) {
526 return ESP_ERR_INVALID_ARG;
527 }
528
529 esp_efuse_batch_write_begin();
530
531 if (!esp_efuse_key_block_unused(block)) {
532 err = ESP_ERR_INVALID_STATE;
533 } else {
534 unsigned idx = block - EFUSE_BLK_KEY0;
535 ESP_EFUSE_CHK(esp_efuse_write_field_blob(s_table[idx].key, key, key_size_bytes * 8));
536 ESP_EFUSE_CHK(esp_efuse_set_key_dis_write(block));
537 if (purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_1 ||
538 purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_256_KEY_2 ||
539 purpose == ESP_EFUSE_KEY_PURPOSE_XTS_AES_128_KEY ||
540 purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL ||
541 purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG ||
542 purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_DIGITAL_SIGNATURE ||
543 purpose == ESP_EFUSE_KEY_PURPOSE_HMAC_UP) {
544 ESP_EFUSE_CHK(esp_efuse_set_key_dis_read(block));
545 }
546 ESP_EFUSE_CHK(esp_efuse_set_key_purpose(block, purpose));
547 ESP_EFUSE_CHK(esp_efuse_set_keypurpose_dis_write(block));
548 return esp_efuse_batch_write_commit();
549 }
550 err_exit:
551 esp_efuse_batch_write_cancel();
552 return err;
553 }
554
esp_efuse_write_keys(esp_efuse_purpose_t purposes[],uint8_t keys[][32],unsigned number_of_keys)555 esp_err_t esp_efuse_write_keys(esp_efuse_purpose_t purposes[], uint8_t keys[][32], unsigned number_of_keys)
556 {
557 esp_err_t err = ESP_OK;
558 if (number_of_keys == 0 || number_of_keys > (EFUSE_BLK_KEY_MAX - EFUSE_BLK_KEY0) || keys == NULL || purposes == NULL) {
559 return ESP_ERR_INVALID_ARG;
560 }
561
562 esp_efuse_purpose_t purpose = 0;
563 esp_efuse_block_t block = EFUSE_BLK_KEY0;
564
565 esp_efuse_batch_write_begin();
566
567 unsigned unused_keys = esp_efuse_count_unused_key_blocks();
568 if (number_of_keys > unused_keys) {
569 ESP_LOGE(TAG, "Not enough unused key blocks available. Required %d, was %d", number_of_keys, unused_keys);
570 err = ESP_ERR_NOT_ENOUGH_UNUSED_KEY_BLOCKS;
571 } else {
572 for (int i_key = 0; (block < EFUSE_BLK_KEY_MAX) && (i_key < number_of_keys); block++) {
573 if (esp_efuse_key_block_unused(block)) {
574 purpose = purposes[i_key];
575 ESP_LOGI(TAG, "Writing EFUSE_BLK_KEY%d with purpose %d", block - EFUSE_BLK_KEY0, purpose);
576 ESP_EFUSE_CHK(esp_efuse_write_key(block, purpose, keys[i_key], 32));
577 i_key++;
578 }
579 }
580 return esp_efuse_batch_write_commit();
581 err_exit:
582 ESP_LOGE(TAG, "Failed to write EFUSE_BLK_KEY%d with purpose %d. Can't continue.", block - EFUSE_BLK_KEY0, purpose);
583 }
584 esp_efuse_batch_write_cancel();
585 return err;
586 }
587
588 #endif // not CONFIG_IDF_TARGET_ESP32
589