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