1 /*
2 * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "sdkconfig.h"
7
8 #include "bootloader_flash_priv.h"
9 #include "bootloader_sha.h"
10 #include "bootloader_utility.h"
11 #include "esp_log.h"
12 #include "esp_image_format.h"
13 #include "esp_secure_boot.h"
14 #include "mbedtls/sha256.h"
15 #include "mbedtls/x509.h"
16 #include "mbedtls/md.h"
17 #include "mbedtls/platform.h"
18 #include "mbedtls/entropy.h"
19 #include "mbedtls/ctr_drbg.h"
20 #include <string.h>
21 #include <sys/param.h>
22
23 #ifdef CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
24 static const char *TAG = "secure_boot_v1";
25
26 extern const uint8_t signature_verification_key_start[] asm("_binary_signature_verification_key_bin_start");
27 extern const uint8_t signature_verification_key_end[] asm("_binary_signature_verification_key_bin_end");
28
29 #define SIGNATURE_VERIFICATION_KEYLEN 64
30
esp_secure_boot_verify_signature(uint32_t src_addr,uint32_t length)31 esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length)
32 {
33 uint8_t digest[ESP_SECURE_BOOT_DIGEST_LEN];
34 uint8_t verified_digest[ESP_SECURE_BOOT_DIGEST_LEN];
35 const esp_secure_boot_sig_block_t *sigblock;
36
37 ESP_LOGD(TAG, "verifying signature src_addr 0x%"PRIx32" length 0x%"PRIx32, src_addr, length);
38
39 esp_err_t err = bootloader_sha256_flash_contents(src_addr, length, digest);
40 if (err != ESP_OK) {
41 ESP_LOGE(TAG, "Digest calculation failed 0x%"PRIx32", 0x%"PRIx32, src_addr, length);
42 return err;
43 }
44
45 // Map the signature block and verify the signature
46 sigblock = (const esp_secure_boot_sig_block_t *)bootloader_mmap(src_addr + length, sizeof(esp_secure_boot_sig_block_t));
47 if (sigblock == NULL) {
48 ESP_LOGE(TAG, "bootloader_mmap(0x%"PRIx32", 0x%x) failed", src_addr + length, sizeof(esp_secure_boot_sig_block_t));
49 return ESP_FAIL;
50 }
51 err = esp_secure_boot_verify_ecdsa_signature_block(sigblock, digest, verified_digest);
52 bootloader_munmap(sigblock);
53 return err;
54 }
55
esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t * sig_block,const uint8_t * image_digest,uint8_t * verified_digest)56 esp_err_t esp_secure_boot_verify_ecdsa_signature_block(const esp_secure_boot_sig_block_t *sig_block, const uint8_t *image_digest, uint8_t *verified_digest)
57 {
58 #if !(defined(CONFIG_MBEDTLS_ECDSA_C) && defined(CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED))
59 ESP_LOGE(TAG, "Signature verification requires ECDSA & SECP256R1 curve enabled");
60 return ESP_ERR_NOT_SUPPORTED;
61 #else
62 ptrdiff_t keylen;
63
64 /* Note: in IDF app image verification we don't add any fault injection resistance, boot-time checks only */
65 memset(verified_digest, 0, ESP_SECURE_BOOT_DIGEST_LEN);
66
67 keylen = signature_verification_key_end - signature_verification_key_start;
68 if (keylen != SIGNATURE_VERIFICATION_KEYLEN) {
69 ESP_LOGE(TAG, "Embedded public verification key has wrong length %d", keylen);
70 return ESP_FAIL;
71 }
72
73 if (sig_block->version != 0) {
74 ESP_LOGE(TAG, "image has invalid signature version field 0x%08"PRIx32" (image without a signature?)", sig_block->version);
75 return ESP_FAIL;
76 }
77
78 ESP_LOGD(TAG, "Verifying secure boot signature");
79
80 int ret;
81 mbedtls_mpi r, s;
82
83 mbedtls_mpi_init(&r);
84 mbedtls_mpi_init(&s);
85
86 /* Extract r and s components from RAW ECDSA signature of 64 bytes */
87 #define ECDSA_INTEGER_LEN 32
88 ret = mbedtls_mpi_read_binary(&r, &sig_block->signature[0], ECDSA_INTEGER_LEN);
89 if (ret != 0) {
90 ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(1), err:%d", ret);
91 return ESP_FAIL;
92 }
93
94 ret = mbedtls_mpi_read_binary(&s, &sig_block->signature[ECDSA_INTEGER_LEN], ECDSA_INTEGER_LEN);
95 if (ret != 0) {
96 ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(2), err:%d", ret);
97 mbedtls_mpi_free(&r);
98 return ESP_FAIL;
99 }
100
101 /* Initialise ECDSA context */
102 mbedtls_ecdsa_context ecdsa_context;
103 mbedtls_ecdsa_init(&ecdsa_context);
104
105 mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
106 size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
107 if (keylen != 2 * plen) {
108 ESP_LOGE(TAG, "Incorrect ECDSA key length %d", keylen);
109 ret = ESP_FAIL;
110 goto cleanup;
111 }
112
113 /* Extract X and Y components from ECDSA public key */
114 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), signature_verification_key_start, plen));
115 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), signature_verification_key_start + plen, plen));
116 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1));
117
118 ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s);
119 ESP_LOGD(TAG, "Verification result %d", ret);
120
121 cleanup:
122 mbedtls_mpi_free(&r);
123 mbedtls_mpi_free(&s);
124 mbedtls_ecdsa_free(&ecdsa_context);
125 return ret == 0 ? ESP_OK : ESP_ERR_IMAGE_INVALID;
126 #endif // CONFIG_MBEDTLS_ECDSA_C && CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED
127 }
128 #endif // CONFIG_SECURE_SIGNED_APPS_ECDSA_SCHEME
129