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