• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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