230 lines
5.2 KiB
C
230 lines
5.2 KiB
C
#include <curve.h>
|
|
#include <sha256.h>
|
|
#include <mpztools.h>
|
|
|
|
int __ec_point_size = sizeof(struct ec_point);
|
|
|
|
int32_t curve_create(curve_t curve, mpz_t p, mpz_t a, mpz_t b, mpz_t n, int32_t h, mpz_t xg, mpz_t yg)
|
|
{
|
|
mpz_init_set( curve->p, p);
|
|
mpz_init_set( curve->a, a);
|
|
mpz_init_set( curve->b, b);
|
|
mpz_init_set( curve->n, n);
|
|
curve->h = h;
|
|
|
|
curve->bitwidth = (mpz_sizeinbase( p , 2 ) + 7) & 0xFFFFFFF8;
|
|
|
|
curve_point_init_set_xy(curve->G, xg, yg);
|
|
|
|
if (curve->G)
|
|
return 0;
|
|
|
|
mpz_clear( curve->n );
|
|
mpz_clear( curve->b );
|
|
mpz_clear( curve->a );
|
|
mpz_clear( curve->p );
|
|
|
|
return -1;
|
|
};
|
|
|
|
int32_t curve_destroy(curve_t curve)
|
|
{
|
|
if (curve)
|
|
{
|
|
if (!curve_point_clear( curve->G ))
|
|
{
|
|
mpz_clear( curve->n );
|
|
mpz_clear( curve->b );
|
|
mpz_clear( curve->a );
|
|
mpz_clear( curve->p );
|
|
return 0;
|
|
}
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int32_t curve_get_generator( ec_point_t dst, curve_t curve )
|
|
{
|
|
mpz_set( dst->x, curve->G->x );
|
|
mpz_set( dst->y, curve->G->y );
|
|
}
|
|
|
|
int32_t curve_point_init(ec_point_t point)
|
|
{
|
|
mpz_init(point->x);
|
|
mpz_init(point->y);
|
|
return 0;
|
|
}
|
|
|
|
int32_t curve_point_init_set(ec_point_t point, ec_point_t src)
|
|
{
|
|
mpz_init_set(point->x, src->x);
|
|
mpz_init_set(point->y, src->y);
|
|
return 0;
|
|
}
|
|
|
|
int32_t curve_point_init_set_xy(ec_point_t point, mpz_t x, mpz_t y)
|
|
{
|
|
mpz_init_set(point->x, x);
|
|
mpz_init_set(point->y, y);
|
|
return 0;
|
|
}
|
|
|
|
|
|
int32_t curve_point_clear(ec_point_t point)
|
|
{
|
|
mpz_clear(point->x);
|
|
mpz_clear(point->y);
|
|
return 0;
|
|
}
|
|
|
|
int32_t curve_point_is_valid(ec_point_t point, curve_t curve)
|
|
{
|
|
mpz_t yy, yy2;
|
|
mpz_inits( yy, yy2, NULL );
|
|
|
|
mpz_powm_ui( yy, point->x, 3, curve->p );
|
|
mpz_addmul( yy, curve->a, point->x );
|
|
mpz_add( yy, yy, curve->b );
|
|
mpz_mod( yy, yy, curve->p );
|
|
|
|
mpz_powm_ui( yy2, point->y, 2, curve->p );
|
|
|
|
int result = mpz_cmp( yy, yy2 ) == 0;
|
|
mpz_clears( yy, yy2, NULL );
|
|
return result;
|
|
}
|
|
|
|
int32_t curve_point_is_infinity(ec_point_t point)
|
|
{
|
|
return (mpz_cmp_ui(point->x, 0) == 0) && (mpz_cmp_ui(point->y, 0) == 0);
|
|
}
|
|
|
|
int32_t curve_point_add(ec_point_t dst, ec_point_t p1, ec_point_t p2, curve_t curve)
|
|
{
|
|
int xeq, yeq;
|
|
|
|
xeq = mpz_cmp(p1->x, p2->x) == 0;
|
|
yeq = mpz_cmp(p1->y, p2->y) == 0;
|
|
|
|
if (xeq && !yeq)
|
|
{
|
|
mpz_set_ui( dst->x, 0);
|
|
mpz_set_ui( dst->y, 0);
|
|
return 0;
|
|
} else {
|
|
int result = -1;
|
|
mpz_t lambda;
|
|
mpz_t divlambda;
|
|
|
|
ec_point_t _p1;
|
|
ec_point_t _p2;
|
|
|
|
curve_point_init_set( _p1, p1 );
|
|
curve_point_init_set( _p2, p2 );
|
|
|
|
mpz_inits( lambda, divlambda, NULL );
|
|
|
|
if (xeq)
|
|
{
|
|
mpz_powm_ui(lambda, _p1->x, 2, curve->p);
|
|
mpz_mul_ui(lambda, lambda, 3);
|
|
mpz_add(lambda, lambda, curve->a);
|
|
mpz_mul_ui(divlambda, _p1->y, 2);
|
|
} else {
|
|
mpz_sub( lambda, _p2->y, _p1->y);
|
|
mpz_sub( divlambda, _p2->x, _p1->x);
|
|
}
|
|
|
|
mpz_mod( lambda, lambda, curve->p );
|
|
mpz_mod( divlambda, divlambda, curve->p );
|
|
|
|
if (mpz_invert( divlambda, divlambda, curve->p )==0)
|
|
{
|
|
printf("%s: no inverse found\n", __func__);
|
|
} else {
|
|
mpz_mul( lambda, lambda, divlambda );
|
|
mpz_mod( lambda, lambda, curve->p );
|
|
|
|
mpz_powm_ui( dst->x, lambda, 2, curve->p );
|
|
mpz_sub( dst->x, dst->x, _p1->x );
|
|
mpz_sub( dst->x, dst->x, _p2->x );
|
|
mpz_mod( dst->x, dst->x, curve->p );
|
|
|
|
mpz_sub( dst->y, _p1->x, dst->x );
|
|
mpz_mul( dst->y, dst->y, lambda );
|
|
mpz_sub( dst->y, dst->y, _p1->y );
|
|
mpz_mod( dst->y, dst->y, curve->p );
|
|
|
|
result = 0;
|
|
}
|
|
|
|
mpz_clears( lambda, divlambda, NULL );
|
|
|
|
curve_point_clear(_p1);
|
|
curve_point_clear(_p2);
|
|
|
|
return result;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
int32_t curve_point_mul(ec_point_t dst, ec_point_t p1, mpz_t i, curve_t curve)
|
|
{
|
|
if (curve_point_is_infinity(p1) || (mpz_cmp_ui(p1->y, 0)==0))
|
|
{
|
|
mpz_set_ui( dst->x, 0);
|
|
mpz_set_ui( dst->y, 0);
|
|
return 0;
|
|
}
|
|
|
|
int firstOne = mpz_scan1( i, 0 );
|
|
int size = (mpz_size( i ) * sizeof(mp_limb_t)) << 3;
|
|
|
|
ec_point_t p;
|
|
curve_point_init_set(p, p1);
|
|
|
|
int n=0;
|
|
for (;n<firstOne;n++)
|
|
curve_point_add( p, p, p, curve );
|
|
n++;
|
|
|
|
curve_point_set( dst, p );
|
|
|
|
for (;n<size;n++)
|
|
{
|
|
curve_point_add( p, p, p, curve );
|
|
if (mpz_tstbit(i, n))
|
|
curve_point_add( dst, dst, p, curve );
|
|
}
|
|
|
|
curve_point_clear(p);
|
|
return 0;
|
|
}
|
|
|
|
int32_t curve_map_to_curve( ec_point_t dst, mpz_t u, curve_t curve)
|
|
{
|
|
mpz_t_cleanup_set(u2, u);
|
|
mpz_mod( u2, u2, curve->n );
|
|
curve_point_mul( dst, curve->G, u2, curve );
|
|
return 0;
|
|
}
|
|
|
|
int32_t curve_hash_to_point( ec_point_t dst, char *message, int len, curve_t curve)
|
|
{
|
|
char hash[32];
|
|
SHA256_CTX sha256;
|
|
|
|
sha256_init(&sha256);
|
|
sha256_update(&sha256, message, len );
|
|
sha256_final(&sha256, hash);
|
|
|
|
mpz_cleanup(k);
|
|
mpz_import(k, 32, -1, 1, -1, 0, hash);
|
|
mpz_mul_ui( k, k, 0xdeadbeef );
|
|
mpz_mod( k, k, curve->n);
|
|
|
|
return curve_map_to_curve( dst, k, curve );
|
|
}
|
|
|