@@ -37,7 +37,8 @@ curve_data = { | |||||
"eddsa_hash": "sha512", | "eddsa_hash": "sha512", | ||||
"eddsa_supports_contexts": 0, | "eddsa_supports_contexts": 0, | ||||
"eddsa_dom": "" | "eddsa_dom": "", | ||||
"eddsa_sigma_iso": 1 | |||||
}, | }, | ||||
"ed448goldilocks" : { | "ed448goldilocks" : { | ||||
"name" : "Ed448-Goldilocks", | "name" : "Ed448-Goldilocks", | ||||
@@ -116,6 +117,9 @@ for curve,data in curve_data.iteritems(): | |||||
if "cxx_ns" not in data: | if "cxx_ns" not in data: | ||||
data["cxx_ns"] = data["name"].replace("-","") | data["cxx_ns"] = data["name"].replace("-","") | ||||
if "eddsa_sigma_iso" not in data: | |||||
data["eddsa_sigma_iso"] = 0 | |||||
if "imagine_twist" not in data: | if "imagine_twist" not in data: | ||||
if data["modulus"]%4 == 3: data["imagine_twist"] = 0 | if data["modulus"]%4 == 3: data["imagine_twist"] = 0 | ||||
@@ -26,6 +26,8 @@ | |||||
#define DECAF_WNAF_FIXED_TABLE_BITS $(wnaf.fixed) | #define DECAF_WNAF_FIXED_TABLE_BITS $(wnaf.fixed) | ||||
#define DECAF_WNAF_VAR_TABLE_BITS $(wnaf.var) | #define DECAF_WNAF_VAR_TABLE_BITS $(wnaf.var) | ||||
#define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso) | |||||
static const int EDWARDS_D = $(d); | static const int EDWARDS_D = $(d); | ||||
static const scalar_t point_scalarmul_adjustment = {{{ | static const scalar_t point_scalarmul_adjustment = {{{ | ||||
$(ser((2**(scalar_bits-1+window_bits - ((scalar_bits-1)%window_bits)) - 1) % q,64,"SC_LIMB")) | $(ser((2**(scalar_bits-1+window_bits - ((scalar_bits-1)%window_bits)) - 1) % q,64,"SC_LIMB")) | ||||
@@ -35,7 +37,7 @@ static const scalar_t point_scalarmul_adjustment = {{{ | |||||
const uint8_t API_NS(x_base_point)[X_SER_BYTES] = { $(ser(mont_base,8)) }; | const uint8_t API_NS(x_base_point)[X_SER_BYTES] = { $(ser(mont_base,8)) }; | ||||
#if COFACTOR==8 | #if COFACTOR==8 || EDDSA_USE_SIGMA_ISOGENY | ||||
static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL( | static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL( | ||||
$(ser(msqrt(1-d,modulus),gf_lit_limb_bits) if cofactor == 8 else "/* NONE */") | $(ser(msqrt(1-d,modulus),gf_lit_limb_bits) if cofactor == 8 else "/* NONE */") | ||||
)}; | )}; | ||||
@@ -1058,7 +1060,36 @@ void API_NS(point_encode_like_eddsa) ( | |||||
#else | #else | ||||
API_NS(point_copy)(q,p); | API_NS(point_copy)(q,p); | ||||
#endif | #endif | ||||
#if IMAGINE_TWIST | #if EDDSA_USE_SIGMA_ISOGENY | ||||
{ | |||||
/* Use 4-isogeny like ed25519: | |||||
* 2*x*y*sqrt(d/a-1)/(ax^2 + y^2 - 2) | |||||
* (y^2 - ax^2)/(y^2 + ax^2) | |||||
* with a = -1, d = -EDWARDS_D: | |||||
* -2xysqrt(EDWARDS_D-1)/(2z^2-y^2+x^2) | |||||
* (y^2+x^2)/(y^2-x^2) | |||||
*/ | |||||
gf u; | |||||
gf_sqr ( x, q->x ); // x^2 | |||||
gf_sqr ( t, q->y ); // y^2 | |||||
gf_add( u, x, t ); // x^2 + y^2 | |||||
gf_add( z, q->y, q->x ); | |||||
gf_sqr ( y, z); | |||||
gf_sub ( y, y, u ); // 2xy | |||||
gf_sub ( z, t, x ); // y^2 - x^2 | |||||
gf_sqr ( x, q->z ); | |||||
gf_add ( t, x, x); | |||||
gf_sub ( t, t, z); // 2z^2 - y^2 + x^2 | |||||
gf_mul ( x, y, z ); // 2xy(y^2-x^2) | |||||
gf_mul ( y, u, t ); // (x^2+y^2)(2z^2-y^2+x^2) | |||||
gf_mul ( u, z, t ); | |||||
gf_copy( z, u ); | |||||
gf_mul ( u, x, SQRT_ONE_MINUS_D ); | |||||
gf_copy( x, u ); | |||||
decaf_bzero(u,sizeof(u)); | |||||
} | |||||
#elif IMAGINE_TWIST | |||||
{ | { | ||||
/* TODO: make sure cofactor is clear */ | /* TODO: make sure cofactor is clear */ | ||||
API_NS(point_double)(q,q); | API_NS(point_double)(q,q); | ||||
@@ -1083,7 +1114,7 @@ void API_NS(point_encode_like_eddsa) ( | |||||
gf_mul ( x, t, y ); | gf_mul ( x, t, y ); | ||||
gf_mul ( y, z, u ); | gf_mul ( y, z, u ); | ||||
gf_mul ( z, u, t ); | gf_mul ( z, u, t ); | ||||
decaf_bzero(t,sizeof(u)); | decaf_bzero(u,sizeof(u)); | ||||
} | } | ||||
#endif | #endif | ||||
/* Affinize */ | /* Affinize */ | ||||
@@ -1120,16 +1151,56 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
#endif | #endif | ||||
succ &= gf_deserialize(p->y, enc2, 1); | succ &= gf_deserialize(p->y, enc2, 1); | ||||
gf_sqr(p->z,p->y); | gf_sqr(p->x,p->y); | ||||
gf_mulw(p->t,p->z,EDWARDS_D); | gf_sub(p->z,ONE,p->x); /* num = 1-y^2 */ | ||||
gf_sub(p->z,ONE,p->z); /* 1-y^2 */ | #if EDDSA_USE_SIGMA_ISOGENY | ||||
gf_sub(p->t,ONE,p->t); /* 1-dy^2 */ | gf_mulw(p->t,p->z,EDWARDS_D); /* d-dy^2 */ | ||||
gf_mulw(p->x,p->z,EDWARDS_D-1); /* num = (1-y^2)(d-1) */ | |||||
gf_copy(p->z,p->x); | |||||
#else | |||||
gf_mulw(p->t,p->x,EDWARDS_D); /* dy^2 */ | |||||
#endif | |||||
gf_sub(p->t,ONE,p->t); /* denom = 1-dy^2 or 1-d + dy^2 */ | |||||
gf_mul(p->x,p->z,p->t); | gf_mul(p->x,p->z,p->t); | ||||
succ &= gf_isr(p->t,p->x); /* 1/sqrt((1-y^2)(1-dy^2)) */ | succ &= gf_isr(p->t,p->x); /* 1/sqrt(num * denom) */ | ||||
gf_mul(p->x,p->t,p->z); /* sqrt((1-y^2) / (1-dy^2)) */ | gf_mul(p->x,p->t,p->z); /* sqrt(num / denom) */ | ||||
gf_cond_neg(p->x,gf_lobit(p->x)^low); | gf_cond_neg(p->x,gf_lobit(p->x)^low); | ||||
gf_copy(p->z,ONE); | gf_copy(p->z,ONE); | ||||
#if IMAGINE_TWIST | #if EDDSA_USE_SIGMA_ISOGENY | ||||
{ | |||||
/* Use 4-isogeny like ed25519: | |||||
* 2*x*y/sqrt(d/a-1)/(ax^2 + y^2 - 2) | |||||
* (y^2 - ax^2)/(y^2 + ax^2) | |||||
* with a = -1, d = -EDWARDS_D: | |||||
* -2xy/sqrt(EDWARDS_D-1)/(2z^2-y^2+x^2) | |||||
* (y^2+x^2)/(y^2-x^2) | |||||
*/ | |||||
gf a, b, c, d; | |||||
gf_sqr ( c, p->x ); | |||||
gf_sqr ( a, p->y ); | |||||
gf_add ( d, c, a ); // x^2 + y^2 | |||||
gf_add ( p->t, p->y, p->x ); | |||||
gf_sqr ( b, p->t ); | |||||
gf_sub ( b, b, d ); // 2xy | |||||
gf_sub ( p->t, a, c ); // y^2 - x^2 | |||||
gf_sqr ( p->x, p->z ); | |||||
gf_add ( p->z, p->x, p->x ); | |||||
gf_sub ( a, p->z, p->t ); // 2z^2 - y^2 + x^2 | |||||
gf_mul ( c, a, SQRT_ONE_MINUS_D ); | |||||
gf_mul ( p->x, b, p->t); // (2xy)(y^2-x^2) | |||||
gf_mul ( p->z, p->t, c ); // (y^2-x^2)sd(2z^2 - y^2 + x^2) | |||||
gf_mul ( p->y, d, c ); // (y^2+x^2)sd(2z^2 - y^2 + x^2) | |||||
gf_mul ( p->t, d, b ); | |||||
decaf_bzero(a,sizeof(a)); | |||||
decaf_bzero(b,sizeof(b)); | |||||
decaf_bzero(c,sizeof(c)); | |||||
decaf_bzero(d,sizeof(d)); | |||||
} | |||||
#elif IMAGINE_TWIST | |||||
{ | { | ||||
gf_mul(p->t,p->x,SQRT_MINUS_ONE); | gf_mul(p->t,p->x,SQRT_MINUS_ONE); | ||||
gf_copy(p->x,p->t); | gf_copy(p->x,p->t); | ||||
@@ -20,16 +20,22 @@ | |||||
#define hash_hash $(eddsa_hash)_hash | #define hash_hash $(eddsa_hash)_hash | ||||
#define SUPPORTS_CONTEXTS $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | #define SUPPORTS_CONTEXTS $(C_NS)_EDDSA_SUPPORTS_CONTEXTS | ||||
#define EDDSA_USE_SIGMA_ISOGENY $(eddsa_sigma_iso) | |||||
#define COFACTOR $(cofactor) | |||||
static void clamp( | static void clamp( | ||||
uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES] | uint8_t secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES] | ||||
) { | ) { | ||||
/* Blarg */ | /* Blarg */ | ||||
secret_scalar_ser[0] &= -$(cofactor); | secret_scalar_ser[0] &= -COFACTOR; | ||||
uint8_t hibit = (1<<$(gf_bits % 8))>>1; | uint8_t hibit = (1<<$(gf_bits % 8))>>1; | ||||
secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 1] &= -hibit; | if (hibit == 0) { | ||||
secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 1] |= hibit; | secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 1] = 0; | ||||
if (hibit == 0) secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 2] |= 0x80; | secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 2] |= 0x80; | ||||
} else { | |||||
secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 1] &= hibit-1; | |||||
secret_scalar_ser[$(C_NS)_EDDSA_PRIVATE_BYTES - 1] |= hibit; | |||||
} | |||||
} | } | ||||
static void hash_init_with_dom( | static void hash_init_with_dom( | ||||
@@ -75,7 +81,7 @@ void API_NS(eddsa_derive_public_key) ( | |||||
/* TODO: write documentation for why (due to isogenies) this needs to be quartered */ | /* TODO: write documentation for why (due to isogenies) this needs to be quartered */ | ||||
API_NS(scalar_sub)(secret_scalar,API_NS(scalar_zero),secret_scalar); | API_NS(scalar_sub)(secret_scalar,API_NS(scalar_zero),secret_scalar); | ||||
for (unsigned int c = 1; c < $(cofactor); c <<= 1) { | for (unsigned int c = 1; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | ||||
API_NS(scalar_halve)(secret_scalar,secret_scalar); | API_NS(scalar_halve)(secret_scalar,secret_scalar); | ||||
} | } | ||||
@@ -146,8 +152,8 @@ void API_NS(eddsa_sign) ( | |||||
/* Scalarmul to create the nonce-point */ | /* Scalarmul to create the nonce-point */ | ||||
API_NS(scalar_t) nonce_scalar_2; | API_NS(scalar_t) nonce_scalar_2; | ||||
API_NS(scalar_sub)(nonce_scalar_2,API_NS(scalar_zero),nonce_scalar); | API_NS(scalar_sub)(nonce_scalar_2,API_NS(scalar_zero),nonce_scalar); | ||||
for (unsigned int c = 1; c < COFACTOR/(1+EDDSA_USE_SIGMA_ISOGENY); c <<= 1) { | |||||
for (unsigned int c = 1; c < $(cofactor); c <<= 1) { | |||||
API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | API_NS(scalar_halve)(nonce_scalar_2,nonce_scalar_2); | ||||
} | } | ||||
@@ -230,6 +236,10 @@ decaf_error_t API_NS(eddsa_verify) ( | |||||
$(C_NS)_EDDSA_PRIVATE_BYTES | $(C_NS)_EDDSA_PRIVATE_BYTES | ||||
); | ); | ||||
API_NS(scalar_sub)(response_scalar, API_NS(scalar_zero), response_scalar); /* TODO because nega-base point */ | API_NS(scalar_sub)(response_scalar, API_NS(scalar_zero), response_scalar); /* TODO because nega-base point */ | ||||
#if EDDSA_USE_SIGMA_ISOGENY | |||||
API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); | |||||
#endif | |||||
/* pk_point = -c(x(P)) + (cx + k)G = kG */ | /* pk_point = -c(x(P)) + (cx + k)G = kG */ | ||||
API_NS(base_double_scalarmul_non_secret)( | API_NS(base_double_scalarmul_non_secret)( | ||||
@@ -402,7 +402,7 @@ static void test_ec() { | |||||
test.fail(); | test.fail(); | ||||
printf(" Decode like EdDSA failed."); | printf(" Decode like EdDSA failed."); | ||||
} | } | ||||
point_check(test,-q,q,r,0,0,q,r,"Encode like EdDSA round-trip"); | point_check(test,-q,q,r,i,0,q,r,"Encode like EdDSA round-trip"); | ||||
} | } | ||||
} | } | ||||
@@ -714,6 +714,7 @@ template<> const Block Tests<IsoEd25519>::eddsa_sig0(ed25518_eddsa_sig0,64); | |||||
int main(int argc, char **argv) { | int main(int argc, char **argv) { | ||||
(void) argc; (void) argv; | (void) argc; (void) argv; | ||||
Tests<IsoEd25519>::test_cfrg_vectors(); | |||||
run_for_all_curves<Tests>(); | run_for_all_curves<Tests>(); | ||||
if (passing) printf("Passed all tests.\n"); | if (passing) printf("Passed all tests.\n"); | ||||
return passing ? 0 : 1; | return passing ? 0 : 1; | ||||