1 /*
2 * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "esp_log.h"
7 #include "esp_secure_boot.h"
8 #include "mbedtls/sha256.h"
9 #include "mbedtls/x509.h"
10 #include "mbedtls/md.h"
11 #include "mbedtls/platform.h"
12 #include "mbedtls/entropy.h"
13 #include "mbedtls/ctr_drbg.h"
14 #include "mbedtls/ecp.h"
15 #include "rom/ecdsa.h"
16
17 #include "secure_boot_signature_priv.h"
18
19 static const char *TAG = "secure_boot_v2_ecdsa";
20
21 #define ECDSA_INTEGER_LEN 32
22
verify_ecdsa_signature_block(const ets_secure_boot_signature_t * sig_block,const uint8_t * image_digest,const ets_secure_boot_sig_block_t * trusted_block)23 esp_err_t verify_ecdsa_signature_block(const ets_secure_boot_signature_t *sig_block, const uint8_t *image_digest, const ets_secure_boot_sig_block_t *trusted_block)
24 {
25 if (!sig_block || !image_digest || !trusted_block) {
26 return ESP_ERR_INVALID_ARG;
27 }
28
29 esp_err_t ret;
30
31 mbedtls_mpi r, s;
32
33 mbedtls_mpi_init(&r);
34 mbedtls_mpi_init(&s);
35
36 /* Initialise ECDSA context */
37 mbedtls_ecdsa_context ecdsa_context;
38 mbedtls_ecdsa_init(&ecdsa_context);
39
40 uint8_t key_size = 0;
41
42 switch(trusted_block->ecdsa.key.curve_id) {
43 case ECDSA_CURVE_P192:
44 key_size = 24;
45 mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP192R1);
46 break;
47 case ECDSA_CURVE_P256:
48 key_size = 32;
49 mbedtls_ecp_group_load(&ecdsa_context.MBEDTLS_PRIVATE(grp), MBEDTLS_ECP_DP_SECP256R1);
50 break;
51 default:
52 ESP_LOGE(TAG, "Invalid curve ID");
53 return ESP_ERR_INVALID_ARG;
54 }
55
56 uint8_t x_point[ECDSA_INTEGER_LEN] = {};
57 uint8_t y_point[ECDSA_INTEGER_LEN] = {};
58 uint8_t _r[ECDSA_INTEGER_LEN] = {};
59 uint8_t _s[ECDSA_INTEGER_LEN] = {};
60
61 /* Convert r and s components to big endian format */
62 for (int i = 0; i < key_size; i++) {
63 _r[i] = trusted_block->ecdsa.signature[key_size - i - 1];
64 _s[i] = trusted_block->ecdsa.signature[2 * key_size - i - 1];
65 }
66
67 /* Extract r and s components from RAW ECDSA signature of 64 bytes */
68 ret = mbedtls_mpi_read_binary(&r, _r, key_size);
69 if (ret != 0) {
70 ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(r), err:%d", ret);
71 mbedtls_ecdsa_free(&ecdsa_context);
72 return ESP_FAIL;
73 }
74
75 ret = mbedtls_mpi_read_binary(&s, _s, key_size);
76 if (ret != 0) {
77 ESP_LOGE(TAG, "Failed mbedtls_mpi_read_binary(s), err:%d", ret);
78 mbedtls_mpi_free(&r);
79 mbedtls_ecdsa_free(&ecdsa_context);
80 return ESP_FAIL;
81 }
82
83 size_t plen = mbedtls_mpi_size(&ecdsa_context.MBEDTLS_PRIVATE(grp).P);
84
85 for (int i = 0; i < plen; i++) {
86 x_point[i] = trusted_block->ecdsa.key.point[plen - 1 - i];
87 y_point[i] = trusted_block->ecdsa.key.point[2 * plen - 1 - i];
88 }
89
90 /* Extract X and Y components from ECDSA public key */
91 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(X), x_point, plen));
92 MBEDTLS_MPI_CHK(mbedtls_mpi_read_binary(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Y), y_point, plen));
93 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ecdsa_context.MBEDTLS_PRIVATE(Q).MBEDTLS_PRIVATE(Z), 1));
94
95 ret = mbedtls_ecdsa_verify(&ecdsa_context.MBEDTLS_PRIVATE(grp), image_digest, ESP_SECURE_BOOT_DIGEST_LEN, &ecdsa_context.MBEDTLS_PRIVATE(Q), &r, &s);
96
97 cleanup:
98 mbedtls_mpi_free(&r);
99 mbedtls_mpi_free(&s);
100 mbedtls_ecdsa_free(&ecdsa_context);
101 return ret;
102 }
103