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_projective_point.h"
10 
11 #include "cc3xx_config.h"
12 #include "cc3xx_pka.h"
13 #include "cc3xx_ec.h"
14 
15 #include "fatal_error.h"
16 
cc3xx_lowlevel_ec_allocate_projective_point(void)17 cc3xx_ec_point_projective cc3xx_lowlevel_ec_allocate_projective_point(void)
18 {
19     cc3xx_ec_point_projective res;
20 
21     res.x = cc3xx_lowlevel_pka_allocate_reg();
22     res.y = cc3xx_lowlevel_pka_allocate_reg();
23     res.z = cc3xx_lowlevel_pka_allocate_reg();
24 
25     return res;
26 }
27 
cc3xx_lowlevel_ec_free_projective_point(cc3xx_ec_point_projective * p)28 void cc3xx_lowlevel_ec_free_projective_point(cc3xx_ec_point_projective *p)
29 {
30     cc3xx_lowlevel_pka_free_reg(p->z);
31     cc3xx_lowlevel_pka_free_reg(p->y);
32     cc3xx_lowlevel_pka_free_reg(p->x);
33 }
34 
cc3xx_lowlevel_ec_projective_point_is_infinity(cc3xx_ec_point_projective * p)35 bool cc3xx_lowlevel_ec_projective_point_is_infinity(cc3xx_ec_point_projective *p)
36 {
37     return cc3xx_lowlevel_pka_are_equal_si(p->z, 0);
38 }
39 
cc3xx_lowlevel_ec_copy_projective_point(cc3xx_ec_point_projective * p,cc3xx_ec_point_projective * res)40 void cc3xx_lowlevel_ec_copy_projective_point(cc3xx_ec_point_projective *p,
41                                     cc3xx_ec_point_projective *res)
42 {
43     cc3xx_lowlevel_pka_copy(p->x, res->x);
44     cc3xx_lowlevel_pka_copy(p->y, res->y);
45     cc3xx_lowlevel_pka_copy(p->z, res->z);
46 }
47 
cc3xx_lowlevel_ec_affine_to_jacobian_with_random_z(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p,cc3xx_ec_point_projective * res)48 void cc3xx_lowlevel_ec_affine_to_jacobian_with_random_z(cc3xx_ec_curve_t *curve,
49                                                         cc3xx_ec_point_affine *p,
50                                                         cc3xx_ec_point_projective *res)
51 {
52 #ifndef CC3XX_CONFIG_DPA_MITIGATIONS_ENABLE
53     return cc3xx_lowlevel_ec_affine_to_jacobian(curve, p, res);
54 #endif
55 
56     cc3xx_pka_reg_id_t temp = cc3xx_lowlevel_pka_allocate_reg();
57 
58     /* Z is random, between 0 and N-1. Realistically, the RNG will never output
59      * 0.
60      */
61     do {
62         cc3xx_lowlevel_pka_set_to_random_within_modulus(res->z);
63     } while (cc3xx_lowlevel_pka_are_equal_si(res->z, 0));
64 
65     /* Construct Z^2 */
66     cc3xx_lowlevel_pka_mod_mul(res->z, res->z, temp);
67 
68     /* Divide X by Z^2 */
69     cc3xx_lowlevel_pka_mod_mul(p->x, temp, res->x);
70 
71     /* Construct Z^3 */
72     cc3xx_lowlevel_pka_mod_mul(temp, res->z, temp);
73 
74     /* Divide Y by Z^3 */
75     cc3xx_lowlevel_pka_mod_mul(p->y, temp, res->y);
76 
77     cc3xx_lowlevel_pka_free_reg(temp);
78 }
79 
cc3xx_lowlevel_ec_affine_to_jacobian(cc3xx_ec_curve_t * curve,cc3xx_ec_point_affine * p,cc3xx_ec_point_projective * res)80 void cc3xx_lowlevel_ec_affine_to_jacobian(cc3xx_ec_curve_t *curve,
81                                           cc3xx_ec_point_affine *p,
82                                           cc3xx_ec_point_projective *res)
83 {
84     cc3xx_lowlevel_pka_copy(p->x, res->x);
85     cc3xx_lowlevel_pka_copy(p->y, res->y);
86     cc3xx_lowlevel_pka_clear(res->z);
87     cc3xx_lowlevel_pka_add_si(res->z, 1, res->z);
88 }
89 
cc3xx_lowlevel_ec_jacobian_to_affine(cc3xx_ec_curve_t * curve,cc3xx_ec_point_projective * p,cc3xx_ec_point_affine * res)90 cc3xx_err_t cc3xx_lowlevel_ec_jacobian_to_affine(cc3xx_ec_curve_t *curve,
91                                                  cc3xx_ec_point_projective *p,
92                                                  cc3xx_ec_point_affine *res)
93 {
94     if (cc3xx_lowlevel_ec_projective_point_is_infinity(p)) {
95         FATAL_ERR(CC3XX_ERR_EC_POINT_IS_INFINITY);
96         return CC3XX_ERR_EC_POINT_IS_INFINITY;
97     }
98 
99     cc3xx_pka_reg_id_t z_inv = cc3xx_lowlevel_pka_allocate_reg();
100     cc3xx_pka_reg_id_t temp = cc3xx_lowlevel_pka_allocate_reg();
101 
102     /* Construct 1/(Z^2) */
103     cc3xx_lowlevel_pka_mod_inv(p->z, z_inv);
104     cc3xx_lowlevel_pka_mod_mul(z_inv, z_inv, temp);
105 
106     /* Divide X by Z^2 */
107     cc3xx_lowlevel_pka_mod_mul(p->x, temp, res->x);
108 
109     /* Construct 1/(Z^3) */
110     cc3xx_lowlevel_pka_mod_mul(temp, z_inv, temp);
111 
112     /* Divide Y by Z^3 */
113     cc3xx_lowlevel_pka_mod_mul(p->y, temp, res->y);
114 
115     cc3xx_lowlevel_pka_free_reg(temp);
116     cc3xx_lowlevel_pka_free_reg(z_inv);
117 
118     return CC3XX_ERR_SUCCESS;
119 }
120