Skip to content

Commit a91bd40

Browse files
projectgusespressif-bot
authored andcommitted
secure boot: Fixes for ESP32-S2 first boot logic
1 parent f3b914d commit a91bd40

File tree

2 files changed

+105
-101
lines changed

2 files changed

+105
-101
lines changed

components/bootloader_support/src/esp32s2/secure_boot.c

Lines changed: 104 additions & 100 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "esp_efuse.h"
2626
#include "esp_efuse_table.h"
2727

28+
#include "esp32s2/rom/efuse.h"
2829
#include "esp32s2/rom/secure_boot.h"
2930

3031
static const char *TAG = "secure_boot_v2";
@@ -37,19 +38,19 @@ static const char *TAG = "secure_boot_v2";
3738
#define DIGEST_LEN 32
3839

3940
/* 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)
4142
{
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) {
4445
// All signature blocks have been parsed, no new signature block present.
4546
ESP_LOGD(TAG, "Signature block(%d) invalid/absent.", block_num);
4647
return ESP_FAIL;
4748
}
48-
if (sig_block->block[block_num].block_crc != crc) {
49+
if (block->block_crc != crc) {
4950
ESP_LOGE(TAG, "Magic byte correct but incorrect crc.");
5051
return ESP_FAIL;
5152
}
52-
if (memcmp(digest, sig_block->block[block_num].image_digest, DIGEST_LEN)) {
53+
if (memcmp(image_digest, block->image_digest, DIGEST_LEN)) {
5354
ESP_LOGE(TAG, "Magic byte & CRC correct but incorrect image digest.");
5455
return ESP_FAIL;
5556
} else {
@@ -60,88 +61,100 @@ static esp_err_t validate_signature_block(int block_num, const ets_secure_boot_s
6061
return ESP_FAIL;
6162
}
6263

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
7084
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;
7195
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};
7397
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+
74103
ret = bootloader_sha256_flash_contents(flash_offset, sig_block_addr - flash_offset, image_digest);
75104
if (ret != ESP_OK) {
76105
ESP_LOGE(TAG, "error generating image digest, %d", ret);
77106
return ret;
78107
}
79108

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) {
83112
ESP_LOGE(TAG, "bootloader_mmap(0x%x, 0x%x) failed", sig_block_addr, sizeof(ets_secure_boot_signature_t));
84113
return ESP_FAIL;
85114
}
86115

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);
89120
if (ret != ESP_OK) {
121+
ret = ESP_OK; // past the last valid signature block
90122
break;
91123
}
92124

93125
/* Generating the SHA of the public key components in the signature block */
94126
bootloader_sha256_handle_t sig_block_sha;
95127
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+
*/
105139
ret = ESP_FAIL;
106-
goto exit;
140+
ESP_LOGE(TAG, "Secure boot key (%d) verification failed.", i);
141+
break;
107142
}
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++;
108147
}
109148

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);
117152
}
118153

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);
127155
return ret;
128156
}
129157

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-
145158
esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *image_data)
146159
{
147160
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
166179
has_secure_boot_digest |= ets_efuse_find_purpose(ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2, NULL);
167180
ESP_LOGI(TAG, "Secure boot digests %s", has_secure_boot_digest ? "already present":"absent, generating..");
168181

169-
170182
ets_efuse_clear_program_registers();
171-
uint8_t i, j, bootloader_sig_block_count = 0;
172183
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};
180186

181187
/* 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);
183189
if (ret != ESP_OK) {
184-
ESP_LOGE(TAG, "Public key digest generation failed.");
190+
ESP_LOGE(TAG, "Bootloader signature block is invalid");
185191
return ret;
186192
}
187193

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.");
191196
return ESP_FAIL;
192197
}
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);
194199

195200
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);
198203
return ESP_FAIL;
199204
}
200205

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;
206208
const uint32_t secure_boot_key_purpose[SECURE_BOOT_NUM_BLOCKS] = { ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST0,
207209
ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST1, ETS_EFUSE_KEY_PURPOSE_SECURE_BOOT_DIGEST2 };
208210

209-
ets_efuse_block_t block = ets_efuse_find_unused_key_block();
211+
block = ets_efuse_find_unused_key_block();
210212
if (block == ETS_EFUSE_BLOCK_MAX) {
211-
ESP_LOGE(TAG, "Key blocks not available.");
213+
ESP_LOGE(TAG, "No more unused key blocks available.");
212214
return ESP_FAIL;
213215
}
214216

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);
216218
if (r != 0) {
217219
ESP_LOGE(TAG, "Failed to write efuse block %d with purpose %d. Can't continue.", block, secure_boot_key_purpose[i]);
218220
return ESP_FAIL;
219221
}
220222

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
226224
}
227225

228226
/* 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);
230228
if (ret != ESP_OK) {
231-
ESP_LOGE(TAG, "Application signature block is invalid.");
229+
ESP_LOGE(TAG, "App signature block is invalid.");
232230
return ret;
233231
}
234232

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+
}
237242

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) */
240245
bool match = false;
241246
const uint32_t revoke_bits[SECURE_BOOT_NUM_BLOCKS] = { EFUSE_SECURE_BOOT_KEY_REVOKE0,
242247
EFUSE_SECURE_BOOT_KEY_REVOKE1, EFUSE_SECURE_BOOT_KEY_REVOKE2 };
243248

244-
for (i = 0; i < SECURE_BOOT_NUM_BLOCKS && match == false; i++) {
249+
for (int i = 0; i < boot_key_digests.num_digests; i++) {
245250

246251
if (REG_GET_BIT(EFUSE_RD_REPEAT_DATA1_REG, revoke_bits[i])) {
247252
ESP_LOGI(TAG, "Key block(%d) has been revoked.", i);
248253
continue; // skip if the key block is revoked
249254
}
250255

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)) {
253258
ESP_LOGI(TAG, "Application key(%d) matches with bootloader key(%d).", j, i);
254259
match = true;
255-
break;
256260
}
257261
}
258262
}
@@ -263,9 +267,9 @@ esp_err_t esp_secure_boot_v2_permanently_enable(const esp_image_metadata_t *imag
263267
}
264268

265269
/* 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) {
267271
/* 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++) {
269273
ESP_LOGI(TAG, "Revoking empty key digest slot (%d)...", i);
270274
ets_secure_boot_revoke_public_key_digest(i);
271275
}

components/esp_rom/include/esp32s2/rom/rsa_pss.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ typedef struct {
3232
uint32_t mdash;
3333
} ets_rsa_pubkey_t;
3434

35-
bool ets_rsa_pss_verify(const ets_rsa_pubkey_t *key, const uint8_t *sig, const uint8_t *digest);
35+
bool ets_rsa_pss_verify(const ets_rsa_pubkey_t *key, const uint8_t *sig, const uint8_t *digest, uint8_t *verified_digest);
3636

3737
void ets_mgf1_sha256(const uint8_t *mgfSeed, size_t seedLen, size_t maskLen, uint8_t *mask);
3838

0 commit comments

Comments
 (0)