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