#include <libecc/libec.h>
#include <libecc/external_deps/print.h>
#include <libecc/external_deps/time.h>
ATTRIBUTE_WARN_UNUSED_RET int get_random_point_on_curve(ec_params *curve_params, prj_pt *out_point);
int get_random_point_on_curve(ec_params *curve_params, prj_pt *out_point)
{
nn nn_tmp;
int ret, is_oncurve;
fp x, y, fp_tmp1, fp_tmp2;
fp_ctx_src_t ctx;
MUST_HAVE((curve_params != NULL), ret, err);
nn_tmp.magic = WORD(0);
x.magic = y.magic = fp_tmp1.magic = fp_tmp2.magic = WORD(0);
ctx = &(curve_params->ec_fp);
ret = fp_init(&x, ctx); EG(ret, err);
ret = fp_init(&y, ctx); EG(ret, err);
ret = fp_init(&fp_tmp1, ctx); EG(ret, err);
ret = fp_init(&fp_tmp2, ctx); EG(ret, err);
ret = nn_init(&nn_tmp, 0); EG(ret, err);
ret = nn_set_word_value(&nn_tmp, WORD(3)); EG(ret, err);
while (1) {
ret = fp_get_random(&x, ctx); EG(ret, err);
ret = fp_copy(&fp_tmp1, &x); EG(ret, err);
ret = fp_copy(&fp_tmp2, &x); EG(ret, err);
ret = fp_pow(&fp_tmp1, &fp_tmp1, &nn_tmp); EG(ret, err);
ret = fp_mul(&fp_tmp2, &fp_tmp2, &(curve_params->ec_curve.a)); EG(ret, err);
ret = fp_add(&fp_tmp1, &fp_tmp1, &fp_tmp2); EG(ret, err);
ret = fp_add(&fp_tmp1, &fp_tmp1, &(curve_params->ec_curve.b)); EG(ret, err);
if (fp_sqrt(&y, &fp_tmp2, &fp_tmp1) == 0) {
ret = is_on_shortw_curve(&x, &y, &(curve_params->ec_curve), &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: Tonelli-Shanks found a bad "
"solution to curve equation ...\n");
continue;
}
break;
}
}
ret = fp_one(&fp_tmp1); EG(ret, err);
ret = prj_pt_init_from_coords(out_point, &(curve_params->ec_curve), &x, &y,
&fp_tmp1); EG(ret, err);
err:
fp_uninit(&x);
fp_uninit(&y);
fp_uninit(&fp_tmp1);
fp_uninit(&fp_tmp2);
nn_uninit(&nn_tmp);
return ret;
}
#define PERF_SCALAR_MUL 40
ATTRIBUTE_WARN_UNUSED_RET int check_curve(const u8 *curve_name);
int check_curve(const u8 *curve_name)
{
unsigned int i;
u64 t1, t2;
int ret, is_oncurve, isone, iszero;
nn nn_k;
ec_params curve_params;
prj_pt A, B, C, D;
prj_pt TMP;
aff_pt T;
u32 len;
const ec_str_params *the_curve_const_parameters;
nn_k.magic = WORD(0);
A.magic = B.magic = C.magic = D.magic = WORD(0);
TMP.magic = T.magic = WORD(0);
MUST_HAVE((curve_name != NULL), ret, err);
ret = local_strnlen((const char *)curve_name, MAX_CURVE_NAME_LEN, &len); EG(ret, err);
len += 1;
MUST_HAVE((len < 256), ret, err);
ret = ec_get_curve_params_by_name(curve_name,
(u8)len, &the_curve_const_parameters); EG(ret, err);
if (the_curve_const_parameters == NULL) {
ext_printf("Error: error when importing curve %s "
"parameters ...\n", curve_name);
ret = -1;
goto err;
}
ret = import_params(&curve_params, the_curve_const_parameters); EG(ret, err);
ret = get_random_point_on_curve(&curve_params, &A); EG(ret, err);
ret = get_random_point_on_curve(&curve_params, &B); EG(ret, err);
ret = prj_pt_add(&C, &A, &B); EG(ret, err);
ret = prj_pt_to_aff(&T, &C); EG(ret, err);
ret = prj_pt_is_on_curve(&C, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: C = A+B is not on the %s curve!\n",
curve_params.curve_name);
ret = -1;
goto err;
}
ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: C = A+B is not on the %s curve!\n",
curve_params.curve_name);
ret = -1;
goto err;
}
ret = prj_pt_dbl(&C, &A); EG(ret, err);
ret = prj_pt_to_aff(&T, &C); EG(ret, err);
ret = prj_pt_is_on_curve(&C, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: C = A+B is not on the %s curve!\n",
curve_params.curve_name);
ret = -1;
goto err;
}
ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: C = A+B is not on the %s curve!\n",
curve_params.curve_name);
ret = -1;
goto err;
}
ret = prj_pt_add(&C, &A, &B); EG(ret, err);
ret = prj_pt_dbl(&D, &A); EG(ret, err);
ret = nn_isone(&(curve_params.ec_gen_cofactor), &isone); EG(ret, err);
if (isone) {
ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &A); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qA is not 0! (regular mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &A); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qA is not 0! (regular blind mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &B); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qB is not 0! (regular mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &B); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qB is not 0! (regular blind mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &C); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qC is not 0! (regular mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &C); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qC is not 0! (regular bind mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul(&TMP, &(curve_params.ec_gen_order), &D); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qD is not 0! (regular mul)\n");
ret = -1;
goto err;
}
ret = prj_pt_mul_blind(&TMP, &(curve_params.ec_gen_order), &D); EG(ret, err);
ret = prj_pt_iszero(&TMP, &iszero); EG(ret, err);
if (!iszero) {
ext_printf("Error: qD is not 0! (regular blind mul)\n");
ret = -1;
goto err;
}
}
ret = nn_init(&nn_k, 0); EG(ret, err);
if (get_ms_time(&t1)) {
ext_printf("Error: cannot get time with get_ms_time\n");
ret = -1;
goto err;
}
for (i = 0; i < PERF_SCALAR_MUL; i++) {
ret = nn_get_random_mod(&nn_k, &(curve_params.ec_gen_order)); EG(ret, err);
ret = prj_pt_mul(&TMP, &nn_k, &A); EG(ret, err);
ret = prj_pt_to_aff(&T, &TMP); EG(ret, err);
ret = prj_pt_is_on_curve(&TMP, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: kA is not on the %s curve!\n",
curve_params.curve_name);
nn_print("k=", &nn_k);
ret = -1;
goto err;
}
ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: kA is not on the %s curve!\n",
curve_params.curve_name);
nn_print("k=", &nn_k);
ret = -1;
goto err;
}
}
if (get_ms_time(&t2)) {
ext_printf("Error: cannot get time with get_ms_time\n");
ret = -1;
goto err;
}
ext_printf(" [*] Regular EC scalar multiplication took %f seconds "
"on average\n",
(double)(t2 - t1) / (double)(PERF_SCALAR_MUL * 1000ULL));
if (get_ms_time(&t1)) {
ext_printf("Error: cannot get time with get_ms_time\n");
ret = -1;
goto err;
}
for (i = 0; i < PERF_SCALAR_MUL; i++) {
ret = nn_get_random_mod(&nn_k, &(curve_params.ec_gen_order)); EG(ret, err);
ret = prj_pt_mul_blind(&TMP, &nn_k, &A); EG(ret, err);
ret = prj_pt_to_aff(&T, &TMP); EG(ret, err);
ret = prj_pt_is_on_curve(&TMP, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: kA is not on the %s curve!\n",
curve_params.curve_name);
nn_print("k=", &nn_k);
ret = -1;
goto err;
}
ret = aff_pt_is_on_curve(&T, &is_oncurve); EG(ret, err);
if (!is_oncurve) {
ext_printf("Error: kA is not on the %s curve!\n",
curve_params.curve_name);
nn_print("k=", &nn_k);
ret = -1;
goto err;
}
}
if (get_ms_time(&t2)) {
ext_printf("Error: cannot get time with get_ms_time\n");
ret = -1;
goto err;
}
ext_printf(" [*] Regular blind EC scalar multiplication took %f seconds "
"on average\n",
(double)(t2 - t1) / (double)(PERF_SCALAR_MUL * 1000ULL));
err:
prj_pt_uninit(&A);
prj_pt_uninit(&B);
prj_pt_uninit(&C);
prj_pt_uninit(&D);
prj_pt_uninit(&TMP);
aff_pt_uninit(&T);
nn_uninit(&nn_k);
return ret;
}
#ifdef CURVE_BASIC_EXAMPLES
int main(int argc, char *argv[])
{
unsigned int i;
u8 curve_name[MAX_CURVE_NAME_LEN] = { 0 };
FORCE_USED_VAR(argc);
FORCE_USED_VAR(argv);
for (i = 0; i < EC_CURVES_NUM; i++) {
if(ec_get_curve_name_by_type(ec_maps[i].type, curve_name,
sizeof(curve_name))){
ext_printf("Error when treating %s\n", curve_name);
return -1;
}
ext_printf("[+] Checking curve %s\n", curve_name);
if (check_curve(curve_name)) {
ext_printf("Error: error performing check on "
"curve %s\n", curve_name);
return -1;
}
}
return 0;
}
#endif