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 */ 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