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