feat(bootloader_support): Support Secure Boot using ECDSA-P384 curve
This commit is contained in:
@@ -105,7 +105,6 @@ static esp_err_t verify_segment_header(int index, const esp_image_segment_header
|
||||
static esp_err_t process_image_header(esp_image_metadata_t *data, uint32_t part_offset, bootloader_sha256_handle_t *sha_handle, bool do_verify, bool silent);
|
||||
static esp_err_t process_appended_hash_and_sig(esp_image_metadata_t *data, uint32_t part_offset, uint32_t part_len, bool do_verify, bool silent);
|
||||
static esp_err_t process_checksum(bootloader_sha256_handle_t sha_handle, uint32_t checksum_word, esp_image_metadata_t *data, bool silent, bool skip_check_checksum);
|
||||
|
||||
static esp_err_t __attribute__((unused)) verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest);
|
||||
static esp_err_t __attribute__((unused)) verify_simple_hash(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data);
|
||||
|
||||
@@ -160,8 +159,8 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
bool verify_sha;
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
/* used for anti-FI checks */
|
||||
uint8_t image_digest[HASH_LEN] = { [ 0 ... 31] = 0xEE };
|
||||
uint8_t verified_digest[HASH_LEN] = { [ 0 ... 31 ] = 0x01 };
|
||||
uint8_t image_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0xEE };
|
||||
uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN] = { [ 0 ... ESP_SECURE_BOOT_DIGEST_LEN - 1 ] = 0x01 };
|
||||
#endif
|
||||
|
||||
if (data == NULL || part == NULL) {
|
||||
@@ -237,7 +236,7 @@ static esp_err_t image_load(esp_image_load_mode_t mode, const esp_partition_pos_
|
||||
"only verify signature in bootloader" into the macro so it's tested multiple times.
|
||||
*/
|
||||
#if CONFIG_SECURE_BOOT_V2_ENABLED
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
ESP_FAULT_ASSERT(!esp_secure_boot_enabled() || memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) == 0);
|
||||
#else // Secure Boot V1 on ESP32, only verify signatures for apps not bootloaders
|
||||
ESP_FAULT_ASSERT(is_bootloader(data->start_addr) || memcmp(image_digest, verified_digest, HASH_LEN) == 0);
|
||||
#endif
|
||||
@@ -1023,43 +1022,14 @@ err:
|
||||
return err;
|
||||
}
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
bootloader_munmap(padding);
|
||||
end = padded_end;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_digest, HASH_LEN, "Calculated secure boot hash");
|
||||
|
||||
static esp_err_t verify_signature_and_adjust_image_len(esp_image_metadata_t *data, uint32_t end, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
// Use hash to verify signature block
|
||||
esp_err_t err = ESP_ERR_IMAGE_INVALID;
|
||||
#if CONFIG_SECURE_BOOT || CONFIG_SECURE_SIGNED_APPS_NO_SECURE_BOOT
|
||||
const void *sig_block;
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, HASH_LEN) != 0); /* sanity check that these values start differently */
|
||||
ESP_FAULT_ASSERT(memcmp(image_digest, verified_digest, ESP_SECURE_BOOT_DIGEST_LEN) != 0); /* sanity check that these values start differently */
|
||||
#if defined(CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME)
|
||||
sig_block = bootloader_mmap(data->start_addr + data->image_len, sizeof(esp_secure_boot_sig_block_t));
|
||||
err = esp_secure_boot_verify_ecdsa_signature_block(sig_block, image_digest, verified_digest);
|
||||
@@ -1076,7 +1046,7 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
ESP_LOGI(TAG, "Calculating simple hash to check for corruption...");
|
||||
const void *whole_image = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
||||
if (whole_image != NULL) {
|
||||
sha_handle = bootloader_sha256_start();
|
||||
bootloader_sha256_handle_t sha_handle = bootloader_sha256_start();
|
||||
bootloader_sha256_data(sha_handle, whole_image, data->image_len - HASH_LEN);
|
||||
bootloader_munmap(whole_image);
|
||||
if (verify_simple_hash(sha_handle, data) != ESP_OK) {
|
||||
@@ -1097,6 +1067,64 @@ static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_han
|
||||
}
|
||||
#endif
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif /* SECURE_BOOT_CHECK_SIGNATURE */
|
||||
|
||||
static esp_err_t verify_secure_boot_signature(bootloader_sha256_handle_t sha_handle, esp_image_metadata_t *data, uint8_t *image_digest, uint8_t *verified_digest)
|
||||
{
|
||||
#if (SECURE_BOOT_CHECK_SIGNATURE == 1)
|
||||
uint32_t end = data->start_addr + data->image_len;
|
||||
|
||||
ESP_LOGI(TAG, "Verifying image signature...");
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
(void) sha_handle;
|
||||
/* Re-calculating image digest using SHA384 */
|
||||
const void *image_data = bootloader_mmap(data->start_addr, data->image_len - HASH_LEN);
|
||||
bootloader_sha_handle_t sha384_handle = bootloader_sha512_start(true);
|
||||
bootloader_sha512_data(sha384_handle, image_data, data->image_len - HASH_LEN);
|
||||
bootloader_munmap(image_data);
|
||||
#endif
|
||||
|
||||
// For secure boot, we calculate the signature hash over the whole file, which includes any "simple" hash
|
||||
// appended to the image for corruption detection
|
||||
if (data->image.hash_appended) {
|
||||
const void *simple_hash = bootloader_mmap(end - HASH_LEN, HASH_LEN);
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_data(sha384_handle, simple_hash, HASH_LEN);
|
||||
#else
|
||||
bootloader_sha256_data(sha_handle, simple_hash, HASH_LEN);
|
||||
#endif
|
||||
bootloader_munmap(simple_hash);
|
||||
}
|
||||
|
||||
#if CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
// End of the image needs to be padded all the way to a 4KB boundary, after the simple hash
|
||||
// (for apps they are usually already padded due to --secure-pad-v2, only a problem if this option was not used.)
|
||||
uint32_t padded_end = ALIGN_UP(end, FLASH_SECTOR_SIZE);
|
||||
if (padded_end > end) {
|
||||
const void *padding = bootloader_mmap(end, padded_end - end);
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_data(sha384_handle, padding, padded_end - end);
|
||||
#else
|
||||
bootloader_sha256_data(sha_handle, padding, padded_end - end);
|
||||
#endif
|
||||
bootloader_munmap(padding);
|
||||
end = padded_end;
|
||||
}
|
||||
#endif // CONFIG_SECURE_SIGNED_APPS_RSA_SCHEME || CONFIG_SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
|
||||
|
||||
#if CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
|
||||
bootloader_sha512_finish(sha384_handle, image_digest);
|
||||
#else
|
||||
bootloader_sha256_finish(sha_handle, image_digest);
|
||||
#endif
|
||||
|
||||
// Log the hash for debugging
|
||||
bootloader_debug_buffer(image_digest, ESP_SECURE_BOOT_DIGEST_LEN, "Calculated secure boot hash");
|
||||
|
||||
return verify_signature_and_adjust_image_len(data, end, image_digest, verified_digest);
|
||||
#endif // SECURE_BOOT_CHECK_SIGNATURE
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user