1 /*
2  * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #pragma once
7 
8 #include <stdbool.h>
9 #include <string.h>
10 #include "hal/assert.h"
11 #include "soc/ecdsa_reg.h"
12 #include "hal/ecdsa_types.h"
13 
14 #ifdef __cplusplus
15 extern "C" {
16 #endif
17 
18 /**
19  * @brief Memory blocks of ECDSA parameters
20  */
21 typedef enum {
22     ECDSA_PARAM_R,
23     ECDSA_PARAM_S,
24     ECDSA_PARAM_Z,
25     ECDSA_PARAM_QAX,
26     ECDSA_PARAM_QAY
27 } ecdsa_ll_param_t;
28 
29 /**
30  * @brief Interrupt types in ECDSA
31  */
32 typedef enum {
33     ECDSA_INT_CALC_DONE,
34     ECDSA_INT_SHA_RELEASE,
35 } ecdsa_ll_intr_type_t;
36 
37 /**
38  * @brief Stages of ECDSA operation
39  */
40 typedef enum {
41     ECDSA_STAGE_START_CALC,
42     ECDSA_STAGE_LOAD_DONE,
43     ECDSA_STAGE_GET_DONE
44 } ecdsa_ll_stage_t;
45 
46 /**
47  * @brief States of ECDSA peripheral
48  */
49 typedef enum {
50     ECDSA_STATE_IDLE,
51     ECDSA_STATE_LOAD,
52     ECDSA_STATE_GET,
53     ECDSA_STATE_BUSY
54 } ecdsa_ll_state_t;
55 
56 /**
57  * @brief Types of SHA
58  */
59 typedef enum {
60     ECDSA_SHA_224,
61     ECDSA_SHA_256
62 } ecdsa_ll_sha_type_t;
63 
64 /**
65  * @brief Operation modes of SHA
66  */
67 typedef enum {
68     ECDSA_MODE_SHA_START,
69     ECDSA_MODE_SHA_CONTINUE
70 } ecdsa_ll_sha_mode_t;
71 
72 /**
73  * @brief Enable interrupt of a given type
74  *
75  * @param type Interrupt type
76  */
ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type)77 static inline void ecdsa_ll_enable_intr(ecdsa_ll_intr_type_t type)
78 {
79     switch (type) {
80         case ECDSA_INT_CALC_DONE:
81             REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 1);
82             break;
83         case ECDSA_INT_SHA_RELEASE:
84             REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 1);
85             break;
86         default:
87             HAL_ASSERT(false && "Unsupported interrupt type");
88             break;
89     }
90 }
91 
92 /**
93  * @brief Disable interrupt of a given type
94  *
95  * @param type Interrupt type
96  */
ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type)97 static inline void ecdsa_ll_disable_intr(ecdsa_ll_intr_type_t type)
98 {
99     switch (type) {
100         case ECDSA_INT_CALC_DONE:
101             REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_CALC_DONE_INT_ENA, 0);
102             break;
103         case ECDSA_INT_SHA_RELEASE:
104             REG_SET_FIELD(ECDSA_INT_ENA_REG, ECDSA_SHA_RELEASE_INT_ENA, 0);
105             break;
106         default:
107             HAL_ASSERT(false && "Unsupported interrupt type");
108             break;
109     }
110 }
111 
112 /**
113  * @brief Clear interrupt of a given type
114  *
115  * @param type Interrupt type
116  */
ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type)117 static inline void ecdsa_ll_clear_intr(ecdsa_ll_intr_type_t type)
118 {
119     switch (type) {
120         case ECDSA_INT_CALC_DONE:
121             REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_CALC_DONE_INT_CLR, 1);
122             break;
123         case ECDSA_INT_SHA_RELEASE:
124             REG_SET_FIELD(ECDSA_INT_CLR_REG, ECDSA_SHA_RELEASE_INT_CLR, 1);
125             break;
126         default:
127             HAL_ASSERT(false && "Unsupported interrupt type");
128             break;
129     }
130 }
131 
132 /**
133  * @brief Set working mode of ECDSA
134  *
135  * @param mode Mode of operation
136  */
ecdsa_ll_set_mode(ecdsa_mode_t mode)137 static inline void ecdsa_ll_set_mode(ecdsa_mode_t mode)
138 {
139     switch (mode) {
140         case ECDSA_MODE_SIGN_VERIFY:
141             REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 0);
142             break;
143         case ECDSA_MODE_SIGN_GEN:
144             REG_SET_FIELD(ECDSA_CONF_REG, ECDSA_WORK_MODE, 1);
145             break;
146         default:
147             HAL_ASSERT(false && "Unsupported mode");
148             break;
149     }
150 }
151 
152 /**
153  * @brief Set curve for ECDSA operation
154  *
155  * @param curve ECDSA curve
156  */
ecdsa_ll_set_curve(ecdsa_curve_t curve)157 static inline void ecdsa_ll_set_curve(ecdsa_curve_t curve)
158 {
159     switch (curve) {
160         case ECDSA_CURVE_SECP256R1:
161             REG_SET_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE);
162             break;
163         case ECDSA_CURVE_SECP192R1:
164             REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_ECC_CURVE);
165             break;
166         default:
167             HAL_ASSERT(false && "Unsupported curve");
168             return;
169     }
170 }
171 
172 /**
173  * @brief Set the source of `Z` (SHA message)
174  *
175  * @param mode Mode of SHA generation
176  */
ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode)177 static inline void ecdsa_ll_set_z_mode(ecdsa_ll_sha_mode_t mode)
178 {
179     switch (mode) {
180         case ECDSA_Z_USE_SHA_PERI:
181             REG_CLR_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z);
182             break;
183         case ECDSA_Z_USER_PROVIDED:
184             REG_SET_BIT(ECDSA_CONF_REG, ECDSA_SOFTWARE_SET_Z);
185             break;
186         default:
187             HAL_ASSERT(false && "Unsupported curve");
188             break;
189     }
190 }
191 
192 /**
193  * @brief Set the stage of ECDSA operation
194  *
195  * @param stage Stage of operation
196  */
ecdsa_ll_set_stage(ecdsa_ll_stage_t stage)197 static inline void ecdsa_ll_set_stage(ecdsa_ll_stage_t stage)
198 {
199     switch (stage) {
200         case ECDSA_STAGE_START_CALC:
201             REG_SET_BIT(ECDSA_START_REG, ECDSA_START);
202             break;
203         case ECDSA_STAGE_LOAD_DONE:
204             REG_SET_BIT(ECDSA_START_REG, ECDSA_LOAD_DONE);
205             break;
206         case ECDSA_STAGE_GET_DONE:
207             REG_SET_BIT(ECDSA_START_REG, ECDSA_GET_DONE);
208             break;
209         default:
210             HAL_ASSERT(false && "Unsupported state");
211             break;
212     }
213 }
214 
215 /**
216  * @brief Get the state of ECDSA peripheral
217  *
218  * @return State of ECDSA
219  */
ecdsa_ll_get_state(void)220 static inline ecdsa_ll_state_t ecdsa_ll_get_state(void)
221 {
222     return REG_GET_FIELD(ECDSA_STATE_REG, ECDSA_BUSY);
223 }
224 
225 /**
226  * @brief Set the SHA type
227  *
228  * @param type Type of SHA
229  */
ecdsa_ll_sha_set_type(ecdsa_ll_sha_type_t type)230 static inline void ecdsa_ll_sha_set_type(ecdsa_ll_sha_type_t type)
231 {
232     switch (type) {
233         case ECDSA_SHA_224:
234             REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 1);
235             break;
236         case ECDSA_SHA_256:
237             REG_SET_FIELD(ECDSA_SHA_MODE_REG, ECDSA_SHA_MODE, 2);
238             break;
239         default:
240             HAL_ASSERT(false && "Unsupported type");
241             break;
242     }
243 }
244 
245 /**
246  * @brief Set the SHA operation mode
247  *
248  * @param mode Mode of SHA operation
249  */
ecdsa_ll_sha_set_mode(ecdsa_ll_sha_mode_t mode)250 static inline void ecdsa_ll_sha_set_mode(ecdsa_ll_sha_mode_t mode)
251 {
252     switch (mode) {
253         case ECDSA_MODE_SHA_START:
254             REG_SET_BIT(ECDSA_SHA_START_REG, ECDSA_SHA_START);
255             break;
256         case ECDSA_MODE_SHA_CONTINUE:
257             REG_SET_BIT(ECDSA_SHA_CONTINUE_REG, ECDSA_SHA_CONTINUE);
258             break;
259         default:
260             HAL_ASSERT(false && "Unsupported type");
261             break;
262     }
263 }
264 
265 /**
266  * @brief Check if SHA is busy
267  *
268  * @return - true, if SHA is busy
269  *         - false, if SHA is IDLE
270  */
ecdsa_ll_sha_is_busy(void)271 static inline bool ecdsa_ll_sha_is_busy(void)
272 {
273     return REG_GET_BIT(ECDSA_SHA_BUSY_REG, ECDSA_SHA_BUSY);
274 }
275 
276 /**
277  * @brief Write the ECDSA parameter
278  *
279  * @param param Parameter to be written
280  * @param buf   Buffer containing data
281  * @param len   Length of buffer
282  */
ecdsa_ll_write_param(ecdsa_ll_param_t param,const uint8_t * buf,uint16_t len)283 static inline void ecdsa_ll_write_param(ecdsa_ll_param_t param, const uint8_t *buf, uint16_t len)
284 {
285     uint32_t reg;
286     uint32_t word;
287     switch (param) {
288         case ECDSA_PARAM_R:
289             reg = ECDSA_R_MEM;
290             break;
291         case ECDSA_PARAM_S:
292             reg = ECDSA_S_MEM;
293             break;
294         case ECDSA_PARAM_Z:
295             reg = ECDSA_Z_MEM;
296             break;
297         case ECDSA_PARAM_QAX:
298             reg = ECDSA_QAX_MEM;
299             break;
300         case ECDSA_PARAM_QAY:
301             reg = ECDSA_QAY_MEM;
302             break;
303         default:
304             HAL_ASSERT(false && "Invalid parameter");
305             return;
306     }
307 
308     for (int i = 0; i < len; i += 4) {
309         memcpy(&word, buf + i, 4);
310         REG_WRITE(reg + i, word);
311     }
312 }
313 
314 /**
315  * @brief Read the ECDSA parameter
316  *
317  * @param param Parameter to be read
318  * @param buf   Buffer where the data will be written
319  * @param len   Length of buffer
320  */
ecdsa_ll_read_param(ecdsa_ll_param_t param,uint8_t * buf,uint16_t len)321 static inline void ecdsa_ll_read_param(ecdsa_ll_param_t param, uint8_t *buf, uint16_t len)
322 {
323     uint32_t reg;
324     switch (param) {
325         case ECDSA_PARAM_R:
326             reg = ECDSA_R_MEM;
327             break;
328         case ECDSA_PARAM_S:
329             reg = ECDSA_S_MEM;
330             break;
331         case ECDSA_PARAM_Z:
332             reg = ECDSA_Z_MEM;
333             break;
334         case ECDSA_PARAM_QAX:
335             reg = ECDSA_QAX_MEM;
336             break;
337         case ECDSA_PARAM_QAY:
338             reg = ECDSA_QAY_MEM;
339             break;
340         default:
341             HAL_ASSERT(false && "Invalid parameter");
342             return;
343     }
344 
345     memcpy(buf, (void *)reg, len);
346 }
347 
348 /**
349  * @brief Check if the ECDSA operation is successful
350  *
351  * @return - 1, if ECDSA operation succeeds
352  *         - 0, otherwise
353  */
ecdsa_ll_get_operation_result(void)354 static inline int ecdsa_ll_get_operation_result(void)
355 {
356     return REG_GET_BIT(ECDSA_RESULT_REG, ECDSA_OPERATION_RESULT);
357 }
358 
359 #ifdef __cplusplus
360 }
361 #endif
362