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