1*f0865ec9SKyle Evans /*
2*f0865ec9SKyle Evans * Copyright (C) 2017 - This file is part of libecc project
3*f0865ec9SKyle Evans *
4*f0865ec9SKyle Evans * Authors:
5*f0865ec9SKyle Evans * Ryad BENADJILA <ryadbenadjila@gmail.com>
6*f0865ec9SKyle Evans * Arnaud EBALARD <arnaud.ebalard@ssi.gouv.fr>
7*f0865ec9SKyle Evans * Jean-Pierre FLORI <jean-pierre.flori@ssi.gouv.fr>
8*f0865ec9SKyle Evans *
9*f0865ec9SKyle Evans * Contributors:
10*f0865ec9SKyle Evans * Nicolas VIVET <nicolas.vivet@ssi.gouv.fr>
11*f0865ec9SKyle Evans * Karim KHALFALLAH <karim.khalfallah@ssi.gouv.fr>
12*f0865ec9SKyle Evans *
13*f0865ec9SKyle Evans * This software is licensed under a dual BSD and GPL v2 license.
14*f0865ec9SKyle Evans * See LICENSE file at the root folder of the project.
15*f0865ec9SKyle Evans */
16*f0865ec9SKyle Evans #include <libecc/curves/ec_params.h>
17*f0865ec9SKyle Evans #include <libecc/curves/curves.h>
18*f0865ec9SKyle Evans
19*f0865ec9SKyle Evans /*
20*f0865ec9SKyle Evans * Initialize (already allocated) curve parameters structure pointed by
21*f0865ec9SKyle Evans * ec_params using value provided in remaining parameters. The function
22*f0865ec9SKyle Evans * returns 0 on success, -1 on error.
23*f0865ec9SKyle Evans */
import_params(ec_params * out_params,const ec_str_params * in_str_params)24*f0865ec9SKyle Evans int import_params(ec_params *out_params, const ec_str_params *in_str_params)
25*f0865ec9SKyle Evans {
26*f0865ec9SKyle Evans nn tmp_p, tmp_p_bitlen, tmp_r, tmp_r_square, tmp_mpinv, tmp_p_shift;
27*f0865ec9SKyle Evans nn tmp_p_normalized, tmp_p_reciprocal, tmp_curve_order, tmp_order;
28*f0865ec9SKyle Evans nn tmp_order_bitlen, tmp_cofactor;
29*f0865ec9SKyle Evans fp tmp_a, tmp_b, tmp_gx, tmp_gy, tmp_gz;
30*f0865ec9SKyle Evans ec_curve_type curve_type;
31*f0865ec9SKyle Evans int ret;
32*f0865ec9SKyle Evans tmp_p.magic = tmp_r.magic = tmp_r_square.magic = tmp_mpinv.magic = WORD(0);
33*f0865ec9SKyle Evans tmp_p_shift.magic = tmp_p_normalized.magic = tmp_p_reciprocal.magic = WORD(0);
34*f0865ec9SKyle Evans tmp_a.magic = tmp_b.magic = tmp_curve_order.magic = tmp_gx.magic = WORD(0);
35*f0865ec9SKyle Evans tmp_gy.magic = tmp_gz.magic = tmp_order.magic = tmp_cofactor.magic = WORD(0);
36*f0865ec9SKyle Evans tmp_order_bitlen.magic = tmp_p_bitlen.magic = WORD(0);
37*f0865ec9SKyle Evans
38*f0865ec9SKyle Evans MUST_HAVE(((out_params != NULL) && (in_str_params != NULL)), ret, err);
39*f0865ec9SKyle Evans
40*f0865ec9SKyle Evans ret = local_memset(out_params, 0, sizeof(ec_params)); EG(ret, err);
41*f0865ec9SKyle Evans
42*f0865ec9SKyle Evans /*
43*f0865ec9SKyle Evans * We first need to import p, the prime defining Fp and associated
44*f0865ec9SKyle Evans * Montgomery parameters (r, r^2 and mpinv)
45*f0865ec9SKyle Evans */
46*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_p, PARAM_BUF_PTR(in_str_params->p),
47*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->p)); EG(ret, err);
48*f0865ec9SKyle Evans
49*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_p_bitlen,
50*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->p_bitlen),
51*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->p_bitlen)); EG(ret, err);
52*f0865ec9SKyle Evans
53*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_r, PARAM_BUF_PTR(in_str_params->r),
54*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->r)); EG(ret, err);
55*f0865ec9SKyle Evans
56*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_r_square,
57*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->r_square),
58*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->r_square)); EG(ret, err);
59*f0865ec9SKyle Evans
60*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_mpinv,
61*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->mpinv),
62*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->mpinv)); EG(ret, err);
63*f0865ec9SKyle Evans
64*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_p_shift,
65*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->p_shift),
66*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->p_shift)); EG(ret, err);
67*f0865ec9SKyle Evans
68*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_p_normalized,
69*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->p_normalized),
70*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->p_normalized)); EG(ret, err);
71*f0865ec9SKyle Evans
72*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_p_reciprocal,
73*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->p_reciprocal),
74*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->p_reciprocal)); EG(ret, err);
75*f0865ec9SKyle Evans
76*f0865ec9SKyle Evans /* From p, we can create global Fp context */
77*f0865ec9SKyle Evans ret = fp_ctx_init(&(out_params->ec_fp), &tmp_p,
78*f0865ec9SKyle Evans (bitcnt_t)(tmp_p_bitlen.val[0]),
79*f0865ec9SKyle Evans &tmp_r, &tmp_r_square,
80*f0865ec9SKyle Evans tmp_mpinv.val[0], (bitcnt_t)tmp_p_shift.val[0],
81*f0865ec9SKyle Evans &tmp_p_normalized, tmp_p_reciprocal.val[0]); EG(ret, err);
82*f0865ec9SKyle Evans
83*f0865ec9SKyle Evans /*
84*f0865ec9SKyle Evans * Having Fp context, we can import a and b, the coefficient of
85*f0865ec9SKyle Evans * of Weierstrass equation.
86*f0865ec9SKyle Evans */
87*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp_a, &(out_params->ec_fp),
88*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->a),
89*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->a)); EG(ret, err);
90*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp_b, &(out_params->ec_fp),
91*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->b),
92*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->b)); EG(ret, err);
93*f0865ec9SKyle Evans
94*f0865ec9SKyle Evans /*
95*f0865ec9SKyle Evans * Now we can store the number of points in the group generated
96*f0865ec9SKyle Evans * by g and the associated cofactor (i.e. npoints / order).
97*f0865ec9SKyle Evans */
98*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_order,
99*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gen_order),
100*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gen_order)); EG(ret, err);
101*f0865ec9SKyle Evans ret = nn_init(&(out_params->ec_gen_order), (u16)(tmp_order.wlen * WORD_BYTES)); EG(ret, err);
102*f0865ec9SKyle Evans ret = nn_copy(&(out_params->ec_gen_order), &tmp_order); EG(ret, err);
103*f0865ec9SKyle Evans
104*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_order_bitlen,
105*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gen_order_bitlen),
106*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gen_order_bitlen)); EG(ret, err);
107*f0865ec9SKyle Evans out_params->ec_gen_order_bitlen = (bitcnt_t)(tmp_order_bitlen.val[0]);
108*f0865ec9SKyle Evans
109*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_cofactor,
110*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->cofactor),
111*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->cofactor)); EG(ret, err);
112*f0865ec9SKyle Evans ret = nn_init(&(out_params->ec_gen_cofactor),
113*f0865ec9SKyle Evans (u16)(tmp_cofactor.wlen * WORD_BYTES)); EG(ret, err);
114*f0865ec9SKyle Evans ret = nn_copy(&(out_params->ec_gen_cofactor), &tmp_cofactor); EG(ret, err);
115*f0865ec9SKyle Evans
116*f0865ec9SKyle Evans /* Now we can store the number of points on the curve (curve order) */
117*f0865ec9SKyle Evans ret = nn_init_from_buf(&tmp_curve_order,
118*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->curve_order),
119*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->curve_order)); EG(ret, err);
120*f0865ec9SKyle Evans
121*f0865ec9SKyle Evans /* Now, we can create curve context from a and b. */
122*f0865ec9SKyle Evans ret = ec_shortw_crv_init(&(out_params->ec_curve), &tmp_a, &tmp_b, &tmp_curve_order); EG(ret, err);
123*f0865ec9SKyle Evans
124*f0865ec9SKyle Evans /* Let's now import G from its affine coordinates (gx,gy) */
125*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp_gx, &(out_params->ec_fp),
126*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gx),
127*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gx)); EG(ret, err);
128*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp_gy, &(out_params->ec_fp),
129*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gy),
130*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gy)); EG(ret, err);
131*f0865ec9SKyle Evans ret = fp_init_from_buf(&tmp_gz, &(out_params->ec_fp),
132*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gz),
133*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gz)); EG(ret, err);
134*f0865ec9SKyle Evans ret = prj_pt_init_from_coords(&(out_params->ec_gen),
135*f0865ec9SKyle Evans &(out_params->ec_curve),
136*f0865ec9SKyle Evans &tmp_gx, &tmp_gy, &tmp_gz); EG(ret, err);
137*f0865ec9SKyle Evans
138*f0865ec9SKyle Evans #if !defined(USE_SMALL_STACK)
139*f0865ec9SKyle Evans /* Let's get the optional alpha transfert coefficients */
140*f0865ec9SKyle Evans ret = fp_init_from_buf(&(out_params->ec_alpha_montgomery), &(out_params->ec_fp),
141*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->alpha_montgomery),
142*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->alpha_montgomery)); EG(ret, err);
143*f0865ec9SKyle Evans ret = fp_init_from_buf(&(out_params->ec_gamma_montgomery), &(out_params->ec_fp),
144*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->gamma_montgomery),
145*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->gamma_montgomery)); EG(ret, err);
146*f0865ec9SKyle Evans
147*f0865ec9SKyle Evans ret = fp_init_from_buf(&(out_params->ec_alpha_edwards), &(out_params->ec_fp),
148*f0865ec9SKyle Evans PARAM_BUF_PTR(in_str_params->alpha_edwards),
149*f0865ec9SKyle Evans PARAM_BUF_LEN(in_str_params->alpha_edwards)); EG(ret, err);
150*f0865ec9SKyle Evans #endif
151*f0865ec9SKyle Evans
152*f0865ec9SKyle Evans /* Import a local copy of curve OID */
153*f0865ec9SKyle Evans MUST_HAVE(in_str_params->oid->buflen < MAX_CURVE_OID_LEN, ret, err);
154*f0865ec9SKyle Evans ret = local_memset(out_params->curve_oid, 0, MAX_CURVE_OID_LEN); EG(ret, err);
155*f0865ec9SKyle Evans ret = local_strncpy((char *)(out_params->curve_oid),
156*f0865ec9SKyle Evans (const char *)(in_str_params->oid->buf),
157*f0865ec9SKyle Evans in_str_params->oid->buflen); EG(ret, err);
158*f0865ec9SKyle Evans
159*f0865ec9SKyle Evans /* Import a local copy of curve name */
160*f0865ec9SKyle Evans MUST_HAVE(in_str_params->name->buflen < MAX_CURVE_NAME_LEN, ret, err);
161*f0865ec9SKyle Evans ret = local_memset(out_params->curve_name, 0, MAX_CURVE_NAME_LEN); EG(ret, err);
162*f0865ec9SKyle Evans ret = local_strncpy((char *)(out_params->curve_name),
163*f0865ec9SKyle Evans (const char *)(in_str_params->name->buf),
164*f0865ec9SKyle Evans in_str_params->name->buflen); EG(ret, err);
165*f0865ec9SKyle Evans
166*f0865ec9SKyle Evans /* Get the curve type */
167*f0865ec9SKyle Evans ret = ec_get_curve_type_by_name(in_str_params->name->buf,
168*f0865ec9SKyle Evans in_str_params->name->buflen,
169*f0865ec9SKyle Evans &curve_type); EG(ret, err);
170*f0865ec9SKyle Evans MUST_HAVE(curve_type != UNKNOWN_CURVE, ret, err);
171*f0865ec9SKyle Evans out_params->curve_type = curve_type;
172*f0865ec9SKyle Evans
173*f0865ec9SKyle Evans err:
174*f0865ec9SKyle Evans /* Uninit temporary parameters */
175*f0865ec9SKyle Evans nn_uninit(&tmp_p_bitlen);
176*f0865ec9SKyle Evans nn_uninit(&tmp_order_bitlen);
177*f0865ec9SKyle Evans nn_uninit(&tmp_p);
178*f0865ec9SKyle Evans nn_uninit(&tmp_r);
179*f0865ec9SKyle Evans nn_uninit(&tmp_r_square);
180*f0865ec9SKyle Evans nn_uninit(&tmp_mpinv);
181*f0865ec9SKyle Evans nn_uninit(&tmp_p_shift);
182*f0865ec9SKyle Evans nn_uninit(&tmp_p_normalized);
183*f0865ec9SKyle Evans nn_uninit(&tmp_p_reciprocal);
184*f0865ec9SKyle Evans fp_uninit(&tmp_a);
185*f0865ec9SKyle Evans fp_uninit(&tmp_b);
186*f0865ec9SKyle Evans nn_uninit(&tmp_curve_order);
187*f0865ec9SKyle Evans fp_uninit(&tmp_gx);
188*f0865ec9SKyle Evans fp_uninit(&tmp_gy);
189*f0865ec9SKyle Evans fp_uninit(&tmp_gz);
190*f0865ec9SKyle Evans nn_uninit(&tmp_order);
191*f0865ec9SKyle Evans nn_uninit(&tmp_cofactor);
192*f0865ec9SKyle Evans
193*f0865ec9SKyle Evans return ret;
194*f0865ec9SKyle Evans }
195