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