1 /*
2  * Copyright (c) 2024, The TrustedFirmware-M Contributors. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 
9 #include "cc3xx_ec.h"
10 
11 #include "cc3xx_error.h"
12 #include "cc3xx_ec_curve_data.h"
13 #include "cc3xx_ec_projective_point.h"
14 #include "cc3xx_config.h"
15 
16 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
17 #include "cc3xx_rng.h"
18 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
19 
20 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
21 #include "cc3xx_ec_weierstrass.h"
22 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
23 
24 #include "fatal_error.h"
25 #include "cmsis.h"
26 
27 #include <string.h>
28 
29 /* To be called on entry to every public function in this module */
set_modulus_to_curve_modulus(cc3xx_ec_curve_t * curve)30 static void set_modulus_to_curve_modulus(cc3xx_ec_curve_t *curve)
31 {
32     cc3xx_lowlevel_pka_set_modulus(curve->field_modulus, false, CC3XX_PKA_REG_NP);
33 }
34 
35 /* To be called on exit of every public function in this module */
set_modulus_to_curve_order(cc3xx_ec_curve_t * curve)36 static void set_modulus_to_curve_order(cc3xx_ec_curve_t *curve)
37 {
38     cc3xx_lowlevel_pka_set_modulus(curve->order, false, CC3XX_PKA_REG_NP);
39 }
40 
41 /* Using the procedure from appendix D.1 of NIST SP800-168 */
validate_point(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p)42 static bool validate_point(cc3xx_ec_curve_t *curve,
43                            cc3xx_ec_point_affine *p)
44 {
45     if (!cc3xx_lowlevel_pka_less_than(p->x, CC3XX_PKA_REG_N)) {
46         return false;
47     }
48 
49     if (!cc3xx_lowlevel_pka_less_than(p->y, CC3XX_PKA_REG_N)) {
50         return false;
51     }
52 
53     if (cc3xx_lowlevel_pka_are_equal_si(p->x, 0)) {
54         return false;
55     }
56 
57     if (cc3xx_lowlevel_pka_are_equal_si(p->y, 0)) {
58         return false;
59     }
60 
61     switch (curve->type) {
62     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
63         return cc3xx_lowlevel_ec_weierstrass_validate_point(curve, p);
64     default:
65         return false;
66     }
67 }
68 
allocate_point_from_data(cc3xx_ec_curve_t * curve,const uint32_t * x,size_t x_len,const uint32_t * y,size_t y_len,cc3xx_ec_point_affine * res)69 static cc3xx_err_t allocate_point_from_data(cc3xx_ec_curve_t *curve,
70                                             const uint32_t *x,
71                                             size_t x_len,
72                                             const uint32_t *y,
73                                             size_t y_len,
74                                             cc3xx_ec_point_affine *res)
75 {
76     *res = cc3xx_lowlevel_ec_allocate_point();
77 
78     cc3xx_lowlevel_pka_write_reg_swap_endian(res->x, x, x_len);
79     cc3xx_lowlevel_pka_write_reg_swap_endian(res->y, y, y_len);
80 
81     return validate_point(curve, res) ? CC3XX_ERR_SUCCESS
82                                       : CC3XX_ERR_EC_POINT_OUTSIDE_FIELD;
83 }
84 
cc3xx_lowlevel_ec_allocate_point_from_data(cc3xx_ec_curve_t * curve,const uint32_t * x,size_t x_len,const uint32_t * y,size_t y_len,cc3xx_ec_point_affine * res)85 cc3xx_err_t cc3xx_lowlevel_ec_allocate_point_from_data(cc3xx_ec_curve_t *curve,
86                                                        const uint32_t *x,
87                                                        size_t x_len,
88                                                        const uint32_t *y,
89                                                        size_t y_len,
90                                                        cc3xx_ec_point_affine *res)
91 {
92     cc3xx_err_t err;
93 
94     /* Because this function is part of the external interface, first swap the
95      * modulus to use the curve modulus
96      */
97     set_modulus_to_curve_modulus(curve);
98 
99     err = allocate_point_from_data(curve, x, x_len, y, y_len, res);
100 
101     /* Then reset the modulus */
102     set_modulus_to_curve_order(curve);
103 
104     return err;
105 }
106 
cc3xx_lowlevel_ec_allocate_point(void)107 cc3xx_ec_point_affine cc3xx_lowlevel_ec_allocate_point(void)
108 {
109     cc3xx_ec_point_affine res;
110 
111     res.x = cc3xx_lowlevel_pka_allocate_reg();
112     res.y = cc3xx_lowlevel_pka_allocate_reg();
113 
114     return res;
115 }
116 
cc3xx_lowlevel_ec_free_point(cc3xx_ec_point_affine * p)117 void cc3xx_lowlevel_ec_free_point(cc3xx_ec_point_affine *p)
118 {
119     cc3xx_lowlevel_pka_free_reg(p->y);
120     cc3xx_lowlevel_pka_free_reg(p->x);
121 }
122 
123 static cc3xx_ec_curve_data_t *curve_data_map[_CURVE_ID_MAX] = {
124 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
125 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_192_R1_ENABLE
126     [CC3XX_EC_CURVE_SECP_192_R1] = &secp_192_r1,
127 #endif
128 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_224_R1_ENABLE
129     [CC3XX_EC_CURVE_SECP_224_R1] = &secp_224_r1,
130 #endif
131 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_256_R1_ENABLE
132     [CC3XX_EC_CURVE_SECP_256_R1] = &secp_256_r1,
133 #endif
134 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_384_R1_ENABLE
135     [CC3XX_EC_CURVE_SECP_384_R1] = &secp_384_r1,
136 #endif
137 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_521_R1_ENABLE
138     [CC3XX_EC_CURVE_SECP_521_R1] = &secp_521_r1,
139 #endif
140 
141 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_192_K1_ENABLE
142     [CC3XX_EC_CURVE_SECP_192_K1] = &secp_192_k1,
143 #endif
144 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_224_K1_ENABLE
145     [CC3XX_EC_CURVE_SECP_224_K1] = &secp_224_k1,
146 #endif
147 #ifdef CC3XX_CONFIG_EC_CURVE_SECP_256_K1_ENABLE
148     [CC3XX_EC_CURVE_SECP_256_K1] = &secp_256_k1,
149 #endif
150 
151 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_192_R1_ENABLE
152     [CC3XX_EC_CURVE_BRAINPOOLP_192_R1] = &brainpoolp_192_r1,
153 #endif
154 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_224_R1_ENABLE
155     [CC3XX_EC_CURVE_BRAINPOOLP_224_R1] = &brainpoolp_224_r1,
156 #endif
157 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_256_R1_ENABLE
158     [CC3XX_EC_CURVE_BRAINPOOLP_256_R1] = &brainpoolp_256_r1,
159 #endif
160 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_320_R1_ENABLE
161     [CC3XX_EC_CURVE_BRAINPOOLP_320_R1] = &brainpoolp_320_r1,
162 #endif
163 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_384_R1_ENABLE
164     [CC3XX_EC_CURVE_BRAINPOOLP_384_R1] = &brainpoolp_384_r1,
165 #endif
166 #ifdef CC3XX_CONFIG_EC_CURVE_BRAINPOOLP_512_R1_ENABLE
167     [CC3XX_EC_CURVE_BRAINPOOLP_512_R1] = &brainpoolp_512_r1,
168 #endif
169 
170 #ifdef CC3XX_CONFIG_EC_CURVE_FRP_256_V1_ENABLE
171     [CC3XX_EC_CURVE_FRP_256_V1] = &frp_256_v1,
172 #endif
173 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
174 
175 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_MONTGOMERY_ENABLE
176 #ifdef CC3XX_CONFIG_EC_CURVE_25519_ENABLE
177     [CC3XX_EC_CURVE_25519] = &curve_25519,
178 #endif
179 #ifdef CC3XX_CONFIG_EC_CURVE_448_ENABLE
180     [CC3XX_EC_CURVE_448] = &curve_448,
181 #endif
182 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_MONTGOMERY_ENABLE */
183 
184 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_TWISTED_EDWARDS_ENABLE
185 #ifdef CC3XX_CONFIG_EC_CURVE_ED25519_ENABLE
186     [CC3XX_EC_CURVE_ED25519] = &ed25519,
187 #endif
188 #ifdef CC3XX_CONFIG_EC_CURVE_ED448_ENABLE
189     [CC3XX_EC_CURVE_ED448] = &ed448,
190 #endif
191 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_TWISTED_EDWARDS_ENABLE */
192 };
193 
cc3xx_lowlevel_ec_get_modulus_size_from_curve(cc3xx_ec_curve_id_t curve_id)194 size_t cc3xx_lowlevel_ec_get_modulus_size_from_curve(cc3xx_ec_curve_id_t curve_id) {
195     return (curve_data_map[curve_id])->modulus_size;
196 }
197 
198 #ifdef CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE
validate_reg_is_equal_to_buf(cc3xx_pka_reg_id_t reg,uint32_t * buf,size_t len)199 static bool validate_reg_is_equal_to_buf(cc3xx_pka_reg_id_t reg, uint32_t *buf,
200                                          size_t len)
201 {
202     uint32_t validate_buf[CC3XX_EC_MAX_POINT_SIZE / sizeof(uint32_t)];
203 
204     cc3xx_lowlevel_pka_read_reg(reg, validate_buf, len);
205     return memcmp(validate_buf, buf, len) == 0;
206 }
207 
validate_curve(cc3xx_ec_curve_t * curve)208 static bool validate_curve(cc3xx_ec_curve_t *curve)
209 {
210     cc3xx_ec_curve_data_t *curve_data = curve_data_map[curve->id];
211     bool result = true;
212 
213     result &= validate_reg_is_equal_to_buf(curve->param_a,
214                                            curve_data->field_param_a,
215                                            curve->modulus_size);
216 
217     result &= validate_reg_is_equal_to_buf(curve->param_b,
218                                            curve_data->field_param_b,
219                                            curve->modulus_size);
220 
221     result &= validate_reg_is_equal_to_buf(curve->order,
222                                            curve_data->order,
223                                            curve->modulus_size);
224 
225     result &= validate_reg_is_equal_to_buf(curve->field_modulus,
226                                            curve_data->field_modulus,
227                                            curve->modulus_size);
228 
229     result &= validate_point(curve, &curve->generator);
230 
231     return result;
232 }
233 #endif /* CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE */
234 
cc3xx_lowlevel_ec_init(cc3xx_ec_curve_id_t id,cc3xx_ec_curve_t * curve)235 cc3xx_err_t cc3xx_lowlevel_ec_init(cc3xx_ec_curve_id_t id,
236                           cc3xx_ec_curve_t *curve)
237 {
238     cc3xx_pka_reg_id_t barrett_tag;
239 
240     if (id >= _CURVE_ID_MAX) {
241         FATAL_ERR(CC3XX_ERR_EC_CURVE_NOT_SUPPORTED);
242         return CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
243     }
244 
245     cc3xx_ec_curve_data_t *curve_data = curve_data_map[id];
246 
247     if (curve_data == NULL) {
248         FATAL_ERR(CC3XX_ERR_EC_CURVE_NOT_SUPPORTED);
249         return CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
250     }
251 
252     cc3xx_lowlevel_pka_init(curve_data->register_size);
253 
254     curve->field_modulus = cc3xx_lowlevel_pka_allocate_reg();
255     curve->param_a = cc3xx_lowlevel_pka_allocate_reg();
256     curve->param_b = cc3xx_lowlevel_pka_allocate_reg();
257     curve->order = cc3xx_lowlevel_pka_allocate_reg();
258 
259     barrett_tag = cc3xx_lowlevel_pka_allocate_reg();
260 
261     cc3xx_lowlevel_pka_write_reg(curve->field_modulus, curve_data->field_modulus,
262                                  curve_data->modulus_size);
263 
264     cc3xx_lowlevel_pka_write_reg(barrett_tag, curve_data->barrett_tag,
265                                  curve_data->barrett_tag_size);
266 
267     cc3xx_lowlevel_pka_write_reg(curve->param_a, curve_data->field_param_a,
268                                  curve_data->modulus_size);
269 
270     cc3xx_lowlevel_pka_write_reg(curve->param_b, curve_data->field_param_b,
271                                  curve_data->modulus_size);
272 
273     cc3xx_lowlevel_pka_write_reg(curve->order, curve_data->order,
274                                  curve_data->modulus_size);
275 
276     curve->id = id;
277     curve->type = curve_data->type;
278     curve->modulus_size = curve_data->modulus_size;
279     curve->cofactor = curve_data->cofactor;
280 
281     cc3xx_lowlevel_pka_set_modulus(curve->field_modulus, false, barrett_tag);
282 
283     cc3xx_lowlevel_pka_free_reg(barrett_tag);
284 
285     /* Now that a and b parameters have been set up, we can create and verify a
286      * point on the curve. This is done manually, since having the coordinates
287      * in LE form is faster to load.
288      */
289     curve->generator.x = cc3xx_lowlevel_pka_allocate_reg();
290     curve->generator.y = cc3xx_lowlevel_pka_allocate_reg();
291     cc3xx_lowlevel_pka_write_reg(curve->generator.x, curve_data->generator_x,
292                                  curve_data->modulus_size);
293     cc3xx_lowlevel_pka_write_reg(curve->generator.y, curve_data->generator_y,
294                                  curve_data->modulus_size);
295 
296 #ifdef CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE
297     if (!validate_curve(curve)) {
298         cc3xx_lowlevel_pka_uninit();
299         FATAL_ERR(CC3XX_ERR_FAULT_DETECTED);
300         return CC3XX_ERR_FAULT_DETECTED;
301     }
302 #endif /* CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE */
303 
304     set_modulus_to_curve_order(curve);
305 
306     return CC3XX_ERR_SUCCESS;
307 }
308 
cc3xx_lowlevel_ec_add_points(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p,cc3xx_ec_point_affine * q,cc3xx_ec_point_affine * res)309 cc3xx_err_t cc3xx_lowlevel_ec_add_points(cc3xx_ec_curve_t *curve,
310                                          cc3xx_ec_point_affine *p,
311                                          cc3xx_ec_point_affine *q,
312                                          cc3xx_ec_point_affine *res)
313 {
314     cc3xx_err_t err;
315 
316     set_modulus_to_curve_modulus(curve);
317 
318     switch (curve->type) {
319 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
320     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
321         err = cc3xx_lowlevel_ec_weierstrass_add_points(curve, p, q, res);
322         break;
323 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
324     default:
325         err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
326         break;
327     }
328 
329     set_modulus_to_curve_order(curve);
330 
331     return err;
332 }
333 
cc3xx_lowlevel_ec_double_point(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p,cc3xx_ec_point_affine * res)334 cc3xx_err_t cc3xx_lowlevel_ec_double_point(cc3xx_ec_curve_t *curve,
335                                            cc3xx_ec_point_affine *p,
336                                            cc3xx_ec_point_affine *res)
337 {
338     cc3xx_err_t err;
339 
340     set_modulus_to_curve_modulus(curve);
341 
342     switch (curve->type) {
343 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
344     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
345         err = cc3xx_lowlevel_ec_weierstrass_double_point(curve, p, res);
346         break;
347 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
348     default:
349         err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
350         break;
351     }
352 
353     set_modulus_to_curve_order(curve);
354 
355     return err;
356 }
357 
358 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
blind_scalar(cc3xx_ec_curve_t * curve,cc3xx_pka_reg_id_t scalar,cc3xx_pka_reg_id_t res)359 static cc3xx_err_t blind_scalar(cc3xx_ec_curve_t *curve, cc3xx_pka_reg_id_t scalar,
360                                 cc3xx_pka_reg_id_t res)
361 {
362     cc3xx_err_t err;
363     uint32_t rand;
364     uint32_t idx;
365     cc3xx_pka_reg_id_t zero_reg = cc3xx_lowlevel_pka_allocate_reg();
366     cc3xx_lowlevel_pka_clear(zero_reg);
367 
368     err = cc3xx_lowlevel_rng_get_random_uint(CC3XX_CONFIG_EC_DPA_MAX_BLIND_MULTIPLE, &rand);
369 
370     cc3xx_lowlevel_pka_add(scalar, curve->order, res);
371     for (idx = 1; idx < rand; idx++) {
372         if (idx < rand) {
373             cc3xx_lowlevel_pka_add(res, curve->order, res);
374         } else {
375             /* This is a no-op to keep time constant */
376             cc3xx_lowlevel_pka_add(res, zero_reg, res);
377         }
378     }
379 
380     cc3xx_lowlevel_pka_free_reg(zero_reg);
381     return err;
382 }
383 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
384 
pad_scalar(cc3xx_ec_curve_t * curve,cc3xx_pka_reg_id_t scalar,cc3xx_pka_reg_id_t res)385 static bool pad_scalar(cc3xx_ec_curve_t *curve, cc3xx_pka_reg_id_t scalar,
386                        cc3xx_pka_reg_id_t res)
387 {
388     bool negate_at_end = false;
389 
390     /* If the size of the scalar isn't the same as of the modulus (i.e. we have
391      * leading zeroes), then instead we perform -(-s * P). This is done modulo
392      * the group order, so must be done before selecting the curve modulus
393      */
394     if (cc3xx_lowlevel_pka_get_bit_size(scalar)
395         != cc3xx_lowlevel_pka_get_bit_size(CC3XX_PKA_REG_N)) {
396         cc3xx_lowlevel_pka_mod_neg(scalar, res);
397         negate_at_end = true;
398     } else {
399         /* This should take the same time as mod_neg, while being a no-op */
400         cc3xx_lowlevel_pka_mod_sub_si(scalar, 0, res);
401         negate_at_end = false;
402     }
403 
404     return negate_at_end;
405 }
406 
407 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
split_scalar(cc3xx_ec_curve_t * curve,cc3xx_pka_reg_id_t scalar,cc3xx_pka_reg_id_t random,cc3xx_pka_reg_id_t quotient,cc3xx_pka_reg_id_t remainder)408 static bool split_scalar(cc3xx_ec_curve_t *curve, cc3xx_pka_reg_id_t scalar,
409                          cc3xx_pka_reg_id_t random, cc3xx_pka_reg_id_t quotient,
410                          cc3xx_pka_reg_id_t remainder)
411 {
412     cc3xx_err_t err;
413 
414     do {
415         /* Roughly half of the size of the scalar */
416         err = cc3xx_lowlevel_pka_set_to_random(random, curve->modulus_size * 8 / 2);
417         cc3xx_lowlevel_pka_div(scalar, random, quotient, remainder);
418     } while (cc3xx_lowlevel_pka_are_equal_si(quotient, 0)
419              || cc3xx_lowlevel_pka_are_equal_si(remainder, 0));
420 
421     return err;
422 }
423 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
424 
cc3xx_lowlevel_ec_multipy_point_by_scalar(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p,cc3xx_pka_reg_id_t scalar,cc3xx_ec_point_affine * res)425 cc3xx_err_t cc3xx_lowlevel_ec_multipy_point_by_scalar(cc3xx_ec_curve_t *curve,
426                                                       cc3xx_ec_point_affine *p,
427                                                       cc3xx_pka_reg_id_t scalar,
428                                                       cc3xx_ec_point_affine *res)
429 {
430     cc3xx_pka_reg_id_t padded_scalar = cc3xx_lowlevel_pka_allocate_reg();
431     cc3xx_pka_reg_id_t scalar_to_input = padded_scalar;
432     cc3xx_ec_point_affine temp_point = cc3xx_lowlevel_ec_allocate_point();
433 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
434     cc3xx_pka_reg_id_t split_scalar_quotient = cc3xx_lowlevel_pka_allocate_reg();
435     cc3xx_pka_reg_id_t split_scalar_remainder = cc3xx_lowlevel_pka_allocate_reg();
436     cc3xx_pka_reg_id_t split_scalar_random = cc3xx_lowlevel_pka_allocate_reg();
437 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
438     cc3xx_err_t err = CC3XX_ERR_SUCCESS;
439     bool negate_at_end = false;
440 
441     negate_at_end = pad_scalar(curve, scalar, padded_scalar);
442 
443     set_modulus_to_curve_modulus(curve);
444 
445 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
446     err = blind_scalar(curve, padded_scalar, padded_scalar);
447     if (err != CC3XX_ERR_SUCCESS) {
448         goto out;
449     }
450 
451     err = split_scalar(curve, padded_scalar, split_scalar_random,
452                        split_scalar_quotient, split_scalar_remainder);
453     if (err != CC3XX_ERR_SUCCESS) {
454         goto out;
455     }
456 
457     scalar_to_input = split_scalar_quotient;
458 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
459 
460     switch(curve->type) {
461 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
462     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
463         err |= cc3xx_lowlevel_ec_weierstrass_multipy_point_by_scalar(curve, p,
464                                                                      scalar_to_input,
465                                                                      res);
466         break;
467 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
468     default:
469         err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
470     }
471 
472 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
473     switch(curve->type) {
474 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
475     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
476         err |= cc3xx_lowlevel_ec_weierstrass_multipy_point_by_scalar(curve, res,
477                                                                      split_scalar_random,
478                                                                      res);
479 
480         err |= cc3xx_lowlevel_ec_weierstrass_multipy_point_by_scalar(curve, p,
481                                                                      split_scalar_remainder,
482                                                                      &temp_point);
483 
484         err |= cc3xx_lowlevel_ec_weierstrass_add_points(curve, res, &temp_point,
485                                                         res);
486         break;
487 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
488     default:
489         err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
490     }
491 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
492 
493     /* If we negated the scalar to pad the length, then it must be undone now */
494     if (negate_at_end) {
495         switch(curve->type) {
496 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
497         case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
498            cc3xx_lowlevel_ec_weierstrass_negate_point(res, res);
499         break;
500 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
501         default:
502             err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
503         }
504     } else {
505         switch(curve->type) {
506 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
507         case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
508            cc3xx_lowlevel_ec_weierstrass_negate_point(&temp_point, &temp_point);
509         break;
510 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
511         default:
512             err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
513         }
514     }
515 
516 #ifdef CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE
517     /* Validate the curve after the operation, to see if any of the parameters
518      * have been faulted. If so, then don't return a result.
519      */
520     if (!validate_curve(curve)) {
521         err = CC3XX_ERR_DFA_VIOLATION;
522     }
523 
524     if (!validate_point(curve, p)) {
525         err = CC3XX_ERR_DFA_VIOLATION;
526     }
527 
528     if (!validate_point(curve, res)) {
529         err = CC3XX_ERR_DFA_VIOLATION;
530     }
531 #endif /* CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE */
532 
533 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
534 out:
535 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
536     if (err != CC3XX_ERR_SUCCESS) {
537         /* If an error has occurred, then scrub the result */
538         cc3xx_lowlevel_pka_set_to_random(res->x, curve->modulus_size * 8);
539         cc3xx_lowlevel_pka_set_to_random(res->y, curve->modulus_size * 8);
540     }
541 
542     set_modulus_to_curve_order(curve);
543 
544 #ifdef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
545     cc3xx_lowlevel_pka_free_reg(split_scalar_random);
546     cc3xx_lowlevel_pka_free_reg(split_scalar_remainder);
547     cc3xx_lowlevel_pka_free_reg(split_scalar_quotient);
548 #endif /* CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE */
549     cc3xx_lowlevel_ec_free_point(&temp_point);
550     cc3xx_lowlevel_pka_free_reg(padded_scalar);
551 
552     cc3xx_lowlevel_pka_unmap_physical_registers();
553 
554     return err;
555 }
556 
cc3xx_lowlevel_ec_shamir_multiply_points_by_scalars_and_add(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p1,cc3xx_pka_reg_id_t scalar1,cc3xx_ec_point_affine * p2,cc3xx_pka_reg_id_t scalar2,cc3xx_ec_point_affine * res)557 cc3xx_err_t cc3xx_lowlevel_ec_shamir_multiply_points_by_scalars_and_add(
558                                              cc3xx_ec_curve_t *curve,
559                                              cc3xx_ec_point_affine *p1,
560                                              cc3xx_pka_reg_id_t    scalar1,
561                                              cc3xx_ec_point_affine *p2,
562                                              cc3xx_pka_reg_id_t    scalar2,
563                                              cc3xx_ec_point_affine *res)
564 {
565     cc3xx_err_t err = CC3XX_ERR_SUCCESS;
566 
567     set_modulus_to_curve_modulus(curve);
568 
569     switch(curve->type) {
570 #ifdef CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE
571     case CC3XX_EC_CURVE_TYPE_WEIERSTRASS:
572         err = cc3xx_lowlevel_ec_weierstrass_shamir_multiply_points_by_scalars_and_add(curve,
573                                                                                     p1,
574                                                                                     scalar1,
575                                                                                     p2,
576                                                                                     scalar2,
577                                                                                     res);
578     break;
579 #endif /* CC3XX_CONFIG_EC_CURVE_TYPE_WEIERSTRASS_ENABLE */
580     default:
581         err = CC3XX_ERR_EC_CURVE_NOT_SUPPORTED;
582     }
583 
584 #ifdef CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE
585     /* Validate the curve after the operation, to see if any of the parameters
586      * have been faulted. If so, then don't return a result.
587      */
588     if (!validate_curve(curve)) {
589         err = CC3XX_ERR_DFA_VIOLATION;
590     }
591 
592     if (!validate_point(curve, p1)) {
593         err = CC3XX_ERR_DFA_VIOLATION;
594     }
595 
596     if (!validate_point(curve, p2)) {
597         err = CC3XX_ERR_DFA_VIOLATION;
598     }
599 
600     if (!validate_point(curve, res)) {
601         err = CC3XX_ERR_DFA_VIOLATION;
602     }
603 #endif /* CC3XX_CONFIG_DFA_MITIGATIONS_ENABLE */
604 
605     if (err != CC3XX_ERR_SUCCESS) {
606         /* If an error has occurred, then scrub the result */
607         cc3xx_lowlevel_pka_set_to_random(res->x, curve->modulus_size * 8);
608         cc3xx_lowlevel_pka_set_to_random(res->y, curve->modulus_size * 8);
609     }
610 
611     set_modulus_to_curve_order(curve);
612 
613     return err;
614 }
615 
cc3xx_lowlevel_ec_uninit(void)616 void cc3xx_lowlevel_ec_uninit(void)
617 {
618     cc3xx_lowlevel_pka_uninit();
619 }
620