25
25
#include "esp_efuse.h"
26
26
#include "esp_efuse_table.h"
27
27
28
+ #include "esp32s2/rom/efuse.h"
28
29
#include "esp32s2/rom/secure_boot.h"
29
30
30
31
static const char * TAG = "secure_boot_v2" ;
@@ -37,19 +38,19 @@ static const char *TAG = "secure_boot_v2";
37
38
#define DIGEST_LEN 32
38
39
39
40
/* A signature block is valid when it has correct magic byte, crc and image digest. */
40
- static esp_err_t validate_signature_block (int block_num , const ets_secure_boot_signature_t * sig_block , uint8_t * digest )
41
+ static esp_err_t validate_signature_block (const ets_secure_boot_sig_block_t * block , int block_num , const uint8_t * image_digest )
41
42
{
42
- uint32_t crc = esp_rom_crc32_le (0 , (uint8_t * )& sig_block -> block [ block_num ] , CRC_SIGN_BLOCK_LEN );
43
- if (sig_block -> block [ block_num ]. magic_byte != SIG_BLOCK_MAGIC_BYTE ) {
43
+ uint32_t crc = esp_rom_crc32_le (0 , (uint8_t * )block , CRC_SIGN_BLOCK_LEN );
44
+ if (block -> magic_byte != SIG_BLOCK_MAGIC_BYTE ) {
44
45
// All signature blocks have been parsed, no new signature block present.
45
46
ESP_LOGD (TAG , "Signature block(%d) invalid/absent." , block_num );
46
47
return ESP_FAIL ;
47
48
}
48
- if (sig_block -> block [ block_num ]. block_crc != crc ) {
49
+ if (block -> block_crc != crc ) {
49
50
ESP_LOGE (TAG , "Magic byte correct but incorrect crc." );
50
51
return ESP_FAIL ;
51
52
}
52
- if (memcmp (digest , sig_block -> block [ block_num ]. image_digest , DIGEST_LEN )) {
53
+ if (memcmp (image_digest , block -> image_digest , DIGEST_LEN )) {
53
54
ESP_LOGE (TAG , "Magic byte & CRC correct but incorrect image digest." );
54
55
return ESP_FAIL ;
55
56
} else {
@@ -60,88 +61,100 @@ static esp_err_t validate_signature_block(int block_num, const ets_secure_boot_s
60
61
return ESP_FAIL ;
61
62
}
62
63
63
- // Inputs the flash_offset and length of an image(app or bootloader), validates & verifies its secure boot v2 signature.
64
- // Generates the public key digests of the valid public keys in a signature block and writes it into trusted_keys.
65
- // The key_digests in trusted keys whose signature blocks are invalid will be set to NULL.
66
- static esp_err_t secure_boot_v2_digest_generate (uint32_t flash_offset , uint32_t flash_size , ets_secure_boot_key_digests_t * const trusted_keys )
67
- {
68
- int i = 0 ;
69
- esp_err_t ret = ESP_FAIL ;
64
+ /* Structure to hold public key digests calculated from the signature blocks of a single image.
65
+
66
+ Each image can have one or more signature blocks (up to SECURE_BOOT_NUM_BLOCKS). Each signature block
67
+ includes a public key.
68
+
69
+ Different to the ROM ets_secure_boot_key_digests_t structure which holds pointers to eFuse data with digests,
70
+ in this data structure the digest data is included.
71
+ */
72
+ typedef struct {
73
+ uint8_t key_digests [SECURE_BOOT_NUM_BLOCKS ][DIGEST_LEN ];
74
+ unsigned num_digests ; /* Number of valid digests, starting at index 0 */
75
+ } image_sig_public_key_digests_t ;
76
+
77
+ /* Generates the public key digests of the valid public keys in an image's
78
+ signature block, verifies each signature, and stores the key digests in the
79
+ public_key_digests structure.
80
+
81
+ @param flash_offset Image offset in flash
82
+ @param flash_size Image size in flash (not including signature block)
83
+ @param[out] public_key_digests Pointer to structure to hold the key digests for valid sig blocks
70
84
85
+
86
+ Note that this function doesn't read any eFuses, so it doesn't know if the
87
+ keys are ultimately trusted by the hardware or not
88
+
89
+ @return - ESP_OK if no signatures failed to verify, or if no valid signature blocks are found at all.
90
+ - ESP_FAIL if there's a valid signature block that doesn't verify using the included public key (unexpected!)
91
+ */
92
+ static esp_err_t s_calculate_image_public_key_digests (uint32_t flash_offset , uint32_t flash_size , image_sig_public_key_digests_t * public_key_digests )
93
+ {
94
+ esp_err_t ret ;
71
95
uint8_t image_digest [DIGEST_LEN ] = {0 };
72
- uint8_t public_key_digests [ SECURE_BOOT_NUM_BLOCKS ][ DIGEST_LEN ];
96
+ uint8_t __attribute__(( aligned ( 4 ))) key_digest [ DIGEST_LEN ] = { 0 } ;
73
97
size_t sig_block_addr = flash_offset + ALIGN_UP (flash_size , FLASH_SECTOR_SIZE );
98
+
99
+ ESP_LOGD (TAG , "calculating public key digests for sig blocks of image offset 0x%x (sig block offset 0x%x)" , flash_offset , sig_block_addr );
100
+
101
+ bzero (public_key_digests , sizeof (image_sig_public_key_digests_t ));
102
+
74
103
ret = bootloader_sha256_flash_contents (flash_offset , sig_block_addr - flash_offset , image_digest );
75
104
if (ret != ESP_OK ) {
76
105
ESP_LOGE (TAG , "error generating image digest, %d" , ret );
77
106
return ret ;
78
107
}
79
108
80
- ESP_LOGD (TAG , "reading signature block " );
81
- const ets_secure_boot_signature_t * sig_block = bootloader_mmap (sig_block_addr , sizeof (ets_secure_boot_signature_t ));
82
- if (sig_block == NULL ) {
109
+ ESP_LOGD (TAG , "reading signatures " );
110
+ const ets_secure_boot_signature_t * signatures = bootloader_mmap (sig_block_addr , sizeof (ets_secure_boot_signature_t ));
111
+ if (signatures == NULL ) {
83
112
ESP_LOGE (TAG , "bootloader_mmap(0x%x, 0x%x) failed" , sig_block_addr , sizeof (ets_secure_boot_signature_t ));
84
113
return ESP_FAIL ;
85
114
}
86
115
87
- for (i = 0 ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
88
- ret = validate_signature_block (i , sig_block , image_digest );
116
+ for (int i = 0 ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
117
+ const ets_secure_boot_sig_block_t * block = & signatures -> block [i ];
118
+
119
+ ret = validate_signature_block (block , i , image_digest );
89
120
if (ret != ESP_OK ) {
121
+ ret = ESP_OK ; // past the last valid signature block
90
122
break ;
91
123
}
92
124
93
125
/* Generating the SHA of the public key components in the signature block */
94
126
bootloader_sha256_handle_t sig_block_sha ;
95
127
sig_block_sha = bootloader_sha256_start ();
96
- bootloader_sha256_data (sig_block_sha , & sig_block -> block [i ].key , sizeof (sig_block -> block [i ].key ));
97
- bootloader_sha256_finish (sig_block_sha , public_key_digests [i ]);
98
-
99
- memcpy ((uint8_t * )trusted_keys -> key_digests [0 ], public_key_digests [i ], DIGEST_LEN ); // Overwriting 0th index to verify each valid signature block
100
- /* A signature block is verified when it is valid and the signature in its signature block can be verified with a valid public key */
101
- uint8_t verified_digest [DIGEST_LEN ] = {0 };
102
- ets_secure_boot_status_t r = ets_secure_boot_verify_signature (sig_block , image_digest , trusted_keys , verified_digest );
103
- if (r != SB_SUCCESS ) {
104
- ESP_LOGE (TAG , "Secure boot key (%d) verification failed." , i );
128
+ bootloader_sha256_data (sig_block_sha , & block -> key , sizeof (block -> key ));
129
+ bootloader_sha256_finish (sig_block_sha , key_digest );
130
+
131
+ // Check we can verify the image using this signature and this key
132
+ uint8_t temp_verified_digest [DIGEST_LEN ];
133
+ bool verified = ets_rsa_pss_verify (& block -> key , block -> signature , image_digest , temp_verified_digest );
134
+
135
+ if (!verified ) {
136
+ /* We don't expect this: the signature blocks before we enable secure boot should all be verifiable or invalid,
137
+ so this is a fatal error
138
+ */
105
139
ret = ESP_FAIL ;
106
- goto exit ;
140
+ ESP_LOGE (TAG , "Secure boot key (%d) verification failed." , i );
141
+ break ;
107
142
}
143
+ ESP_LOGD (TAG , "Signature block (%d) is verified" , i );
144
+ /* Copy the key digest to the buffer provided by the caller */
145
+ memcpy ((void * )public_key_digests -> key_digests [i ], key_digest , DIGEST_LEN );
146
+ public_key_digests -> num_digests ++ ;
108
147
}
109
148
110
- // At least 1 verified signature block found.
111
- if (i > 0 ) {
112
- // validate_signature_block returns ESP_FAIL when a sig block is absent, which isn't an error.
113
- while (-- i ) {
114
- trusted_keys -> key_digests [i ] = public_key_digests [i ];
115
- }
116
- ret = ESP_OK ;
149
+ if (ret == ESP_OK && public_key_digests -> num_digests > 0 ) {
150
+ ESP_LOGI (TAG , "Digests successfully calculated, %d valid signatures (image offset 0x%x)" ,
151
+ public_key_digests -> num_digests , flash_offset );
117
152
}
118
153
119
- exit :
120
- /* Set the pointer to an invalid/absent block to NULL */
121
- while (i < SECURE_BOOT_NUM_BLOCKS ) {
122
- trusted_keys -> key_digests [i ] = NULL ;
123
- i ++ ;
124
- }
125
- ESP_LOGI (TAG , "Secure boot verification success." );
126
- bootloader_munmap (sig_block );
154
+ bootloader_munmap (signatures );
127
155
return ret ;
128
156
}
129
157
130
- /* Traverses ets_secure_boot_key_digests_t to find the number of non-null key_digests */
131
- static uint8_t get_signature_block_count (ets_secure_boot_key_digests_t * const trusted_keys ) {
132
- uint8_t bootloader_sig_block_count = 0 ;
133
- for (uint8_t i = 0 ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
134
- if (trusted_keys -> key_digests [i ] != NULL ) {
135
- bootloader_sig_block_count ++ ;
136
-
137
- for (uint8_t j = 0 ; j < DIGEST_LEN ; j ++ ) {
138
- ESP_LOGD (TAG , "Secure Boot Digest %d: 0x%x" , i , * (((uint8_t * )trusted_keys -> key_digests [i ]) + j ));
139
- }
140
- }
141
- }
142
- return bootloader_sig_block_count ;
143
- }
144
-
145
158
esp_err_t esp_secure_boot_v2_permanently_enable (const esp_image_metadata_t * image_data )
146
159
{
147
160
ESP_LOGI (TAG , "enabling secure boot v2 - ESP32-S2..." );
@@ -166,93 +179,84 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
166
179
has_secure_boot_digest |= ets_efuse_find_purpose (ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 , NULL );
167
180
ESP_LOGI (TAG , "Secure boot digests %s" , has_secure_boot_digest ? "already present" :"absent, generating.." );
168
181
169
-
170
182
ets_efuse_clear_program_registers ();
171
- uint8_t i , j , bootloader_sig_block_count = 0 ;
172
183
if (!has_secure_boot_digest ) {
173
- ets_secure_boot_key_digests_t boot_trusted_keys , app_trusted_keys ;
174
- uint8_t boot_trusted_key_data [SECURE_BOOT_NUM_BLOCKS ][DIGEST_LEN ] = {0 }, app_trusted_key_data [SECURE_BOOT_NUM_BLOCKS ][DIGEST_LEN ] = {0 };
175
-
176
- for (i = 0 ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
177
- boot_trusted_keys .key_digests [i ] = boot_trusted_key_data [i ];
178
- app_trusted_keys .key_digests [i ] = app_trusted_key_data [i ];
179
- }
184
+ image_sig_public_key_digests_t boot_key_digests = {0 };
185
+ image_sig_public_key_digests_t app_key_digests = {0 };
180
186
181
187
/* Generate the bootloader public key digests */
182
- ret = secure_boot_v2_digest_generate (bootloader_data .start_addr , bootloader_data .image_len - SIG_BLOCK_PADDING , & boot_trusted_keys );
188
+ ret = s_calculate_image_public_key_digests (bootloader_data .start_addr , bootloader_data .image_len - SIG_BLOCK_PADDING , & boot_key_digests );
183
189
if (ret != ESP_OK ) {
184
- ESP_LOGE (TAG , "Public key digest generation failed. " );
190
+ ESP_LOGE (TAG , "Bootloader signature block is invalid " );
185
191
return ret ;
186
192
}
187
193
188
- bootloader_sig_block_count = get_signature_block_count (& boot_trusted_keys );
189
- if (bootloader_sig_block_count <= 0 ) {
190
- ESP_LOGI (TAG , "No valid signature blocks found. %d signature block(s) found." , bootloader_sig_block_count );
194
+ if (boot_key_digests .num_digests == 0 ) {
195
+ ESP_LOGE (TAG , "No valid bootloader signature blocks found." );
191
196
return ESP_FAIL ;
192
197
}
193
- ESP_LOGI (TAG , "%d signature block(s) found appended to the bootloader." , bootloader_sig_block_count );
198
+ ESP_LOGI (TAG , "%d signature block(s) found appended to the bootloader." , boot_key_digests . num_digests );
194
199
195
200
int unused_key_slots = ets_efuse_count_unused_key_blocks ();
196
- if (bootloader_sig_block_count > unused_key_slots ) {
197
- ESP_LOGE (TAG , "Bootloader signatures(%d) more than available key slots(%d)." , bootloader_sig_block_count , unused_key_slots );
201
+ if (boot_key_digests . num_digests > unused_key_slots ) {
202
+ ESP_LOGE (TAG , "Bootloader signatures(%d) more than available key slots(%d)." , boot_key_digests . num_digests , unused_key_slots );
198
203
return ESP_FAIL ;
199
204
}
200
205
201
- for (i = 0 ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
202
- if (boot_trusted_keys .key_digests [i ] == NULL ) {
203
- break ;
204
- }
205
-
206
+ for (int i = 0 ; i < boot_key_digests .num_digests ; i ++ ) {
207
+ ets_efuse_block_t block ;
206
208
const uint32_t secure_boot_key_purpose [SECURE_BOOT_NUM_BLOCKS ] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0 ,
207
209
ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1 , ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 };
208
210
209
- ets_efuse_block_t block = ets_efuse_find_unused_key_block ();
211
+ block = ets_efuse_find_unused_key_block ();
210
212
if (block == ETS_EFUSE_BLOCK_MAX ) {
211
- ESP_LOGE (TAG , "Key blocks not available." );
213
+ ESP_LOGE (TAG , "No more unused key blocks available." );
212
214
return ESP_FAIL ;
213
215
}
214
216
215
- int r = ets_efuse_write_key (block , secure_boot_key_purpose [i ], boot_trusted_keys .key_digests [i ], DIGEST_LEN );
217
+ int r = ets_efuse_write_key (block , secure_boot_key_purpose [i ], boot_key_digests .key_digests [i ], DIGEST_LEN );
216
218
if (r != 0 ) {
217
219
ESP_LOGE (TAG , "Failed to write efuse block %d with purpose %d. Can't continue." , block , secure_boot_key_purpose [i ]);
218
220
return ESP_FAIL ;
219
221
}
220
222
221
- r = esp_efuse_set_write_protect (block );
222
- if (r != 0 ) {
223
- ESP_LOGE (TAG , "Failed to write protect efuse block %d. Can't continue." , block );
224
- return ESP_FAIL ;
225
- }
223
+ // Note: write key will write protect both the block and the purpose eFuse, always
226
224
}
227
225
228
226
/* Generate the application public key digests */
229
- ret = secure_boot_v2_digest_generate (image_data -> start_addr , image_data -> image_len - SIG_BLOCK_PADDING , & app_trusted_keys );
227
+ ret = s_calculate_image_public_key_digests (image_data -> start_addr , image_data -> image_len - SIG_BLOCK_PADDING , & app_key_digests );
230
228
if (ret != ESP_OK ) {
231
- ESP_LOGE (TAG , "Application signature block is invalid." );
229
+ ESP_LOGE (TAG , "App signature block is invalid." );
232
230
return ret ;
233
231
}
234
232
235
- int app_sig_block_count = get_signature_block_count (& app_trusted_keys );
236
- ESP_LOGI (TAG , "%d signature block(s) found appended to the application." , app_sig_block_count );
233
+ if (app_key_digests .num_digests == 0 ) {
234
+ ESP_LOGE (TAG , "No valid applications signature blocks found." );
235
+ return ESP_FAIL ;
236
+ }
237
+
238
+ ESP_LOGI (TAG , "%d signature block(s) found appended to the app." , app_key_digests .num_digests );
239
+ if (app_key_digests .num_digests > boot_key_digests .num_digests ) {
240
+ ESP_LOGW (TAG , "App has %d signature blocks but bootloader only has %d. Some keys missing from bootloader?" );
241
+ }
237
242
238
- /* Confirm if atleast one the public key from the application matches a public key in the bootloader
239
- (Also, ensure if that public revoke bit is not set for the matched key) */
243
+ /* Confirm if at least one public key from the application matches a public key in the bootloader
244
+ (Also, ensure if that public revoke bit is not set for the matched key) */
240
245
bool match = false;
241
246
const uint32_t revoke_bits [SECURE_BOOT_NUM_BLOCKS ] = { EFUSE_SECURE_BOOT_KEY_REVOKE0 ,
242
247
EFUSE_SECURE_BOOT_KEY_REVOKE1 , EFUSE_SECURE_BOOT_KEY_REVOKE2 };
243
248
244
- for (i = 0 ; i < SECURE_BOOT_NUM_BLOCKS && match == false ; i ++ ) {
249
+ for (int i = 0 ; i < boot_key_digests . num_digests ; i ++ ) {
245
250
246
251
if (REG_GET_BIT (EFUSE_RD_REPEAT_DATA1_REG , revoke_bits [i ])) {
247
252
ESP_LOGI (TAG , "Key block(%d) has been revoked." , i );
248
253
continue ; // skip if the key block is revoked
249
254
}
250
255
251
- for (j = 0 ; j < SECURE_BOOT_NUM_BLOCKS ; j ++ ) {
252
- if (!memcmp (boot_trusted_key_data [i ], app_trusted_key_data [j ], DIGEST_LEN )) {
256
+ for (int j = 0 ; j < app_key_digests . num_digests ; j ++ ) {
257
+ if (!memcmp (boot_key_digests . key_digests [i ], app_key_digests . key_digests [j ], DIGEST_LEN )) {
253
258
ESP_LOGI (TAG , "Application key(%d) matches with bootloader key(%d)." , j , i );
254
259
match = true;
255
- break ;
256
260
}
257
261
}
258
262
}
@@ -263,9 +267,9 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
263
267
}
264
268
265
269
/* Revoke the empty signature blocks */
266
- if (bootloader_sig_block_count < SECURE_BOOT_NUM_BLOCKS ) {
270
+ if (boot_key_digests . num_digests < SECURE_BOOT_NUM_BLOCKS ) {
267
271
/* The revocation index can be 0, 1, 2. Bootloader count can be 1,2,3. */
268
- for (uint8_t i = bootloader_sig_block_count ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
272
+ for (uint8_t i = boot_key_digests . num_digests ; i < SECURE_BOOT_NUM_BLOCKS ; i ++ ) {
269
273
ESP_LOGI (TAG , "Revoking empty key digest slot (%d)..." , i );
270
274
ets_secure_boot_revoke_public_key_digest (i );
271
275
}
0 commit comments