1 /*
2  * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "hal/assert.h"
8 #include "hal/ecdsa_ll.h"
9 #include "hal/ecdsa_hal.h"
10 #include "hal/efuse_hal.h"
11 
12 #if CONFIG_HAL_ECDSA_GEN_SIG_CM
13 #include "esp_fault.h"
14 #include "esp_random.h"
15 #endif
16 
17 #define ECDSA_HAL_P192_COMPONENT_LEN        24
18 #define ECDSA_HAL_P256_COMPONENT_LEN        32
19 
configure_ecdsa_periph(ecdsa_hal_config_t * conf)20 static void configure_ecdsa_periph(ecdsa_hal_config_t *conf)
21 {
22     efuse_hal_set_ecdsa_key(conf->efuse_key_blk);
23 
24     ecdsa_ll_set_mode(conf->mode);
25     ecdsa_ll_set_curve(conf->curve);
26     ecdsa_ll_set_z_mode(conf->sha_mode);
27 }
28 
ecdsa_hal_get_operation_result(void)29 bool ecdsa_hal_get_operation_result(void)
30 {
31     return ecdsa_ll_get_operation_result();
32 }
33 
ecdsa_hal_gen_signature_inner(const uint8_t * hash,uint8_t * r_out,uint8_t * s_out,uint16_t len)34 static void ecdsa_hal_gen_signature_inner(const uint8_t *hash, uint8_t *r_out,
35                               uint8_t *s_out, uint16_t len)
36 {
37     ecdsa_ll_set_stage(ECDSA_STAGE_START_CALC);
38 
39     while(ecdsa_ll_get_state() != ECDSA_STATE_LOAD) {
40         ;
41     }
42 
43     ecdsa_ll_write_param(ECDSA_PARAM_Z, hash, len);
44 
45     ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE);
46 
47     while (ecdsa_ll_get_state() != ECDSA_STATE_GET) {
48         ;
49     }
50 
51     ecdsa_ll_read_param(ECDSA_PARAM_R, r_out, len);
52     ecdsa_ll_read_param(ECDSA_PARAM_S, s_out, len);
53 
54     ecdsa_ll_set_stage(ECDSA_STAGE_GET_DONE);
55 
56     while (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) {
57         ;
58     }
59 }
60 
61 #if CONFIG_HAL_ECDSA_GEN_SIG_CM
ecdsa_hal_gen_signature_with_countermeasure(const uint8_t * hash,uint8_t * r_out,uint8_t * s_out,uint16_t len)62 __attribute__((optimize("O0"))) static void ecdsa_hal_gen_signature_with_countermeasure(const uint8_t *hash, uint8_t *r_out,
63                        uint8_t *s_out, uint16_t len)
64 {
65     uint8_t tmp_r_out[32] = {};
66     uint8_t tmp_s_out[32] = {};
67     uint8_t tmp_hash[64] = {};
68 
69     uint8_t dummy_op_count_prior = esp_random() % ECDSA_SIGN_MAX_DUMMY_OP_COUNT;
70     uint8_t dummy_op_count_later = ECDSA_SIGN_MAX_DUMMY_OP_COUNT - dummy_op_count_prior;
71     ESP_FAULT_ASSERT((dummy_op_count_prior != 0) || (dummy_op_count_later != 0));
72     ESP_FAULT_ASSERT(dummy_op_count_prior + dummy_op_count_later == ECDSA_SIGN_MAX_DUMMY_OP_COUNT);
73 
74     esp_fill_random(tmp_hash, 64);
75     /* Dummy ecdsa signature operations prior to the actual one */
76     for (int i = 0; i < dummy_op_count_prior; i++) {
77         ecdsa_hal_gen_signature_inner(tmp_hash + ((6 * i) % 32), (uint8_t *) tmp_r_out, (uint8_t *) tmp_s_out, len);
78     }
79 
80     /* Actual ecdsa signature operation */
81     ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len);
82 
83     /* Dummy ecdsa signature operations after the actual one */
84     for (int i = 0; i < dummy_op_count_later; i++) {
85         ecdsa_hal_gen_signature_inner(tmp_hash + ((6 * i) % 32), (uint8_t *)tmp_r_out, (uint8_t *)tmp_s_out, len);
86     }
87 
88 }
89 #endif /* CONFIG_HAL_ECDSA_GEN_SIG_CM */
90 
91 
92 
ecdsa_hal_gen_signature(ecdsa_hal_config_t * conf,const uint8_t * hash,uint8_t * r_out,uint8_t * s_out,uint16_t len)93 void ecdsa_hal_gen_signature(ecdsa_hal_config_t *conf, const uint8_t *hash,
94                         uint8_t *r_out, uint8_t *s_out, uint16_t len)
95 {
96     if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) {
97         HAL_ASSERT(false && "Incorrect length");
98     }
99 
100     if (conf->sha_mode == ECDSA_Z_USER_PROVIDED && hash == NULL) {
101         HAL_ASSERT(false && "Mismatch in SHA configuration");
102     }
103 
104     if (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) {
105         HAL_ASSERT(false && "Incorrect ECDSA state");
106     }
107 
108     configure_ecdsa_periph(conf);
109 
110 #if CONFIG_HAL_ECDSA_GEN_SIG_CM
111     ecdsa_hal_gen_signature_with_countermeasure(hash, r_out, s_out, len);
112 #else /* CONFIG_HAL_ECDSA_GEN_SIG_CM */
113     ecdsa_hal_gen_signature_inner(hash, r_out, s_out, len);
114 #endif /* !CONFIG_HAL_ECDSA_GEN_SIG_CM */
115 
116 }
117 
ecdsa_hal_verify_signature(ecdsa_hal_config_t * conf,const uint8_t * hash,const uint8_t * r,const uint8_t * s,const uint8_t * pub_x,const uint8_t * pub_y,uint16_t len)118 int ecdsa_hal_verify_signature(ecdsa_hal_config_t *conf, const uint8_t *hash, const uint8_t *r, const uint8_t *s,
119                                const uint8_t *pub_x, const uint8_t *pub_y, uint16_t len)
120 {
121     if (len != ECDSA_HAL_P192_COMPONENT_LEN && len != ECDSA_HAL_P256_COMPONENT_LEN) {
122         HAL_ASSERT(false && "Incorrect length");
123     }
124 
125     if (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) {
126         HAL_ASSERT(false && "Incorrect ECDSA state");
127     }
128 
129     configure_ecdsa_periph(conf);
130 
131     ecdsa_ll_set_stage(ECDSA_STAGE_START_CALC);
132 
133     while(ecdsa_ll_get_state() != ECDSA_STATE_LOAD) {
134         ;
135     }
136 
137     ecdsa_ll_write_param(ECDSA_PARAM_Z, hash, len);
138     ecdsa_ll_write_param(ECDSA_PARAM_R, r, len);
139     ecdsa_ll_write_param(ECDSA_PARAM_S, s, len);
140     ecdsa_ll_write_param(ECDSA_PARAM_QAX, pub_x, len);
141     ecdsa_ll_write_param(ECDSA_PARAM_QAY, pub_y, len);
142 
143     ecdsa_ll_set_stage(ECDSA_STAGE_LOAD_DONE);
144 
145     while (ecdsa_ll_get_state() != ECDSA_STATE_IDLE) {
146         ;
147     }
148 
149     bool res = ecdsa_hal_get_operation_result();
150 
151     return (res ? 0 : -1);
152 }
153