| @@ -1091,7 +1091,7 @@ void API_NS(point_encode_like_eddsa) ( | |||||
| } | } | ||||
| #elif IMAGINE_TWIST | #elif IMAGINE_TWIST | ||||
| { | { | ||||
| /* TODO: make sure cofactor is clear */ | |||||
| API_NS(point_double)(q,q); | |||||
| API_NS(point_double)(q,q); | API_NS(point_double)(q,q); | ||||
| gf_div_qnr(x, q->x); | gf_div_qnr(x, q->x); | ||||
| gf_copy(y, q->y); | gf_copy(y, q->y); | ||||
| @@ -1154,13 +1154,13 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
| gf_sqr(p->x,p->y); | gf_sqr(p->x,p->y); | ||||
| gf_sub(p->z,ONE,p->x); /* num = 1-y^2 */ | gf_sub(p->z,ONE,p->x); /* num = 1-y^2 */ | ||||
| #if EDDSA_USE_SIGMA_ISOGENY | |||||
| 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 | |||||
| #if EDDSA_USE_SIGMA_ISOGENY | |||||
| 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_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); | ||||
| @@ -1170,13 +1170,16 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
| 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 EDDSA_USE_SIGMA_ISOGENY | |||||
| #if EDDSA_USE_SIGMA_ISOGENY | |||||
| { | { | ||||
| /* Use 4-isogeny like ed25519: | /* Use 4-isogeny like ed25519: | ||||
| * 2*x*y/sqrt(d/a-1)/(ax^2 + y^2 - 2) | |||||
| * 2*x*y/sqrt(1-d/a)/(ax^2 + y^2 - 2) | |||||
| * (y^2 - ax^2)/(y^2 + ax^2) | * (y^2 - ax^2)/(y^2 + ax^2) | ||||
| * (MAGIC: above formula may be off by a factor of -a | |||||
| * or something somewhere; check it for other a) | |||||
| * | |||||
| * with a = -1, d = -EDWARDS_D: | * with a = -1, d = -EDWARDS_D: | ||||
| * -2xy/sqrt(EDWARDS_D-1)/(2z^2-y^2+x^2) | |||||
| * -2xy/sqrt(1-EDWARDS_D)/(2z^2-y^2+x^2) | |||||
| * (y^2+x^2)/(y^2-x^2) | * (y^2+x^2)/(y^2-x^2) | ||||
| */ | */ | ||||
| gf a, b, c, d; | gf a, b, c, d; | ||||
| @@ -1200,15 +1203,15 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
| decaf_bzero(c,sizeof(c)); | decaf_bzero(c,sizeof(c)); | ||||
| decaf_bzero(d,sizeof(d)); | decaf_bzero(d,sizeof(d)); | ||||
| } | } | ||||
| #elif IMAGINE_TWIST | |||||
| #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); | ||||
| point_double_internal(p,p,0); | |||||
| gf_mul(p->t,p->x,p->y); | |||||
| } | } | ||||
| #else | |||||
| #else | |||||
| { | { | ||||
| /* 4-isogeny */ | |||||
| /* 4-isogeny 2xy/(y^2-ax^2), (y^2+ax^2)/(2-y^2-ax^2) */ | |||||
| gf a, b, c, d; | gf a, b, c, d; | ||||
| gf_sqr ( c, p->x ); | gf_sqr ( c, p->x ); | ||||
| gf_sqr ( a, p->y ); | gf_sqr ( a, p->y ); | ||||
| @@ -1229,14 +1232,14 @@ decaf_error_t API_NS(point_decode_like_eddsa) ( | |||||
| decaf_bzero(c,sizeof(c)); | decaf_bzero(c,sizeof(c)); | ||||
| decaf_bzero(d,sizeof(d)); | decaf_bzero(d,sizeof(d)); | ||||
| } | } | ||||
| #endif | |||||
| #endif | |||||
| decaf_bzero(enc2,sizeof(enc2)); | decaf_bzero(enc2,sizeof(enc2)); | ||||
| assert(API_NS(point_valid)(p) || ~succ); | assert(API_NS(point_valid)(p) || ~succ); | ||||
| return decaf_succeed_if(succ); | return decaf_succeed_if(succ); | ||||
| } | } | ||||
| decaf_error_t API_NS(x_direct_scalarmul) ( | |||||
| decaf_error_t decaf_x$(gf_shortname)_direct_scalarmul ( | |||||
| uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
| const uint8_t base[X_PUBLIC_BYTES], | const uint8_t base[X_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
| @@ -1307,7 +1310,7 @@ decaf_error_t API_NS(x_direct_scalarmul) ( | |||||
| return decaf_succeed_if(mask_to_bool(nz)); | return decaf_succeed_if(mask_to_bool(nz)); | ||||
| } | } | ||||
| void API_NS(x_base_scalarmul) ( | |||||
| void decaf_x$(gf_shortname)_base_scalarmul ( | |||||
| uint8_t out[X_PUBLIC_BYTES], | uint8_t out[X_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X_PRIVATE_BYTES] | const uint8_t scalar[X_PRIVATE_BYTES] | ||||
| ) { | ) { | ||||
| @@ -1335,18 +1338,8 @@ void API_NS(x_base_scalarmul) ( | |||||
| * we pick up only a factor of 2 over Jacobi -> Montgomery. | * we pick up only a factor of 2 over Jacobi -> Montgomery. | ||||
| */ | */ | ||||
| API_NS(scalar_halve)(the_scalar,the_scalar); | API_NS(scalar_halve)(the_scalar,the_scalar); | ||||
| #if COFACTOR==8 | |||||
| /* If the base point isn't in the prime-order subgroup (PERF: | |||||
| * guarantee that it is?) then a 4-isogeny isn't necessarily | |||||
| * enough to clear the cofactor. So add another doubling. | |||||
| */ | |||||
| API_NS(scalar_halve)(the_scalar,the_scalar); | |||||
| #endif | |||||
| point_t p; | point_t p; | ||||
| API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | API_NS(precomputed_scalarmul)(p,API_NS(precomputed_base),the_scalar); | ||||
| #if COFACTOR==8 | |||||
| API_NS(point_double)(p,p); | |||||
| #endif | |||||
| /* Isogenize to Montgomery curve */ | /* Isogenize to Montgomery curve */ | ||||
| gf_invert(p->t,p->x); /* 1/x */ | gf_invert(p->t,p->x); /* 1/x */ | ||||
| @@ -383,7 +383,7 @@ decaf_error_t $(c_ns)_direct_scalarmul ( | |||||
| * @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | * @retval DECAF_FAILURE The scalarmul didn't succeed, because the base | ||||
| * point is in a small subgroup. | * point is in a small subgroup. | ||||
| */ | */ | ||||
| decaf_error_t $(c_ns)_x_direct_scalarmul ( /* TODO: rename? */ | |||||
| decaf_error_t decaf_x$(gf_shortname)_direct_scalarmul ( | |||||
| uint8_t out[X$(gf_shortname)_PUBLIC_BYTES], | uint8_t out[X$(gf_shortname)_PUBLIC_BYTES], | ||||
| const uint8_t base[X$(gf_shortname)_PUBLIC_BYTES], | const uint8_t base[X$(gf_shortname)_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES] | const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES] | ||||
| @@ -399,11 +399,13 @@ extern const uint8_t $(c_ns)_x_base_point[X$(gf_shortname)_PUBLIC_BYTES] API_VIS | |||||
| * @param [out] scaled The scaled point base*scalar | * @param [out] scaled The scaled point base*scalar | ||||
| * @param [in] scalar The scalar to multiply by. | * @param [in] scalar The scalar to multiply by. | ||||
| */ | */ | ||||
| void $(c_ns)_x_base_scalarmul ( | |||||
| void decaf_x$(gf_shortname)_base_scalarmul ( | |||||
| uint8_t out[X$(gf_shortname)_PUBLIC_BYTES], | uint8_t out[X$(gf_shortname)_PUBLIC_BYTES], | ||||
| const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES] | const uint8_t scalar[X$(gf_shortname)_PRIVATE_BYTES] | ||||
| ) API_VIS NONNULL NOINLINE; | ) API_VIS NONNULL NOINLINE; | ||||
| /* FUTURE: uint8_t $(c_ns)_encode_like_curve$(gf_shortname)) */ | |||||
| /** | /** | ||||
| * @brief Precompute a table for fast scalar multiplication. | * @brief Precompute a table for fast scalar multiplication. | ||||
| * Some implementations do not include precomputed points; for | * Some implementations do not include precomputed points; for | ||||
| @@ -314,14 +314,19 @@ public: | |||||
| * @retval DECAF_SUCCESS the string was successfully decoded. | * @retval DECAF_SUCCESS the string was successfully decoded. | ||||
| * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | * @return DECAF_FAILURE the string was the wrong length, or wasn't the encoding of a point. | ||||
| * Contents of the point are undefined. | * Contents of the point are undefined. | ||||
| * TODO: rename to noexcept? | |||||
| */ | */ | ||||
| inline decaf_error_t WARN_UNUSED decode_like_eddsa ( | |||||
| inline decaf_error_t WARN_UNUSED decode_like_eddsa_noexcept ( | |||||
| const FixedBlock<$(C_NS)_EDDSA_PUBLIC_BYTES> &buffer | const FixedBlock<$(C_NS)_EDDSA_PUBLIC_BYTES> &buffer | ||||
| ) NOEXCEPT { | ) NOEXCEPT { | ||||
| return $(c_ns)_point_decode_like_eddsa(p,buffer.data()); | return $(c_ns)_point_decode_like_eddsa(p,buffer.data()); | ||||
| } | } | ||||
| inline void decode_like_eddsa ( | |||||
| const FixedBlock<$(C_NS)_EDDSA_PUBLIC_BYTES> &buffer | |||||
| ) throw(CryptoException) { | |||||
| if (DECAF_SUCCESS != decode_like_eddsa_noexcept(buffer)) throw(CryptoException()); | |||||
| } | |||||
| /** | /** | ||||
| * Encode like EdDSA. FIXME: and multiply by the cofactor... | * Encode like EdDSA. FIXME: and multiply by the cofactor... | ||||
| */ | */ | ||||
| @@ -635,7 +640,7 @@ public: | |||||
| const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
| ) throw(std::bad_alloc,CryptoException) { | ) throw(std::bad_alloc,CryptoException) { | ||||
| SecureBuffer out(PUBLIC_BYTES); | SecureBuffer out(PUBLIC_BYTES); | ||||
| if (DECAF_SUCCESS != $(c_ns)_x_direct_scalarmul(out.data(), pk.data(), scalar.data())) { | |||||
| if (DECAF_SUCCESS != decaf_x$(gf_shortname)_direct_scalarmul(out.data(), pk.data(), scalar.data())) { | |||||
| throw CryptoException(); | throw CryptoException(); | ||||
| } | } | ||||
| return out; | return out; | ||||
| @@ -648,7 +653,7 @@ public: | |||||
| const FixedBlock<PUBLIC_BYTES> &pk, | const FixedBlock<PUBLIC_BYTES> &pk, | ||||
| const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
| ) NOEXCEPT { | ) NOEXCEPT { | ||||
| return $(c_ns)_x_direct_scalarmul(out.data(), pk.data(), scalar.data()); | |||||
| return decaf_x$(gf_shortname)_direct_scalarmul(out.data(), pk.data(), scalar.data()); | |||||
| } | } | ||||
| /** Generate and return a public key; equivalent to shared_secret(base_point(),scalar) | /** Generate and return a public key; equivalent to shared_secret(base_point(),scalar) | ||||
| @@ -658,7 +663,7 @@ public: | |||||
| const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
| ) throw(std::bad_alloc) { | ) throw(std::bad_alloc) { | ||||
| SecureBuffer out(PUBLIC_BYTES); | SecureBuffer out(PUBLIC_BYTES); | ||||
| $(c_ns)_x_base_scalarmul(out.data(), scalar.data()); | |||||
| decaf_x$(gf_shortname)_base_scalarmul(out.data(), scalar.data()); | |||||
| return out; | return out; | ||||
| } | } | ||||
| @@ -670,7 +675,7 @@ public: | |||||
| FixedBuffer<PUBLIC_BYTES> &out, | FixedBuffer<PUBLIC_BYTES> &out, | ||||
| const FixedBlock<PRIVATE_BYTES> &scalar | const FixedBlock<PRIVATE_BYTES> &scalar | ||||
| ) NOEXCEPT { | ) NOEXCEPT { | ||||
| $(c_ns)_x_base_scalarmul(out.data(), scalar.data()); | |||||
| decaf_x$(gf_shortname)_base_scalarmul(out.data(), scalar.data()); | |||||
| } | } | ||||
| }; | }; | ||||
| @@ -112,8 +112,6 @@ void API_NS(eddsa_sign) ( | |||||
| const uint8_t *const context = NULL; | const uint8_t *const context = NULL; | ||||
| const uint8_t context_len = 0; | const uint8_t context_len = 0; | ||||
| #endif | #endif | ||||
| /* FIXME: of course, need a different hash for Curve25519 */ | |||||
| API_NS(scalar_t) secret_scalar; | API_NS(scalar_t) secret_scalar; | ||||
| hash_ctx_t hash; | hash_ctx_t hash; | ||||
| { | { | ||||
| @@ -7,13 +7,13 @@ extern "C" { | |||||
| #endif | #endif | ||||
| /** Number of bytes in an EdDSA public key. */ | /** Number of bytes in an EdDSA public key. */ | ||||
| #define $(C_NS)_EDDSA_PUBLIC_BYTES $((gf_bits)/8 + 1) /* TODO: change name? */ | |||||
| #define $(C_NS)_EDDSA_PUBLIC_BYTES $((gf_bits)/8 + 1) | |||||
| /** Number of bytes in an EdDSA private key. */ | /** Number of bytes in an EdDSA private key. */ | ||||
| #define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES /* TODO: change name? */ | |||||
| #define $(C_NS)_EDDSA_PRIVATE_BYTES $(C_NS)_EDDSA_PUBLIC_BYTES | |||||
| /** Number of bytes in an EdDSA private key. */ | /** Number of bytes in an EdDSA private key. */ | ||||
| #define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_EDDSA_PUBLIC_BYTES + $(C_NS)_EDDSA_PRIVATE_BYTES) /* TODO: change name? */ | |||||
| #define $(C_NS)_EDDSA_SIGNATURE_BYTES ($(C_NS)_EDDSA_PUBLIC_BYTES + $(C_NS)_EDDSA_PRIVATE_BYTES) | |||||
| /** Does EdDSA support contexts? */ | /** Does EdDSA support contexts? */ | ||||
| #define $(C_NS)_EDDSA_SUPPORTS_CONTEXTS $(eddsa_supports_contexts) | #define $(C_NS)_EDDSA_SUPPORTS_CONTEXTS $(eddsa_supports_contexts) | ||||
| @@ -397,7 +397,7 @@ static void test_ec() { | |||||
| q=p; | q=p; | ||||
| for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two(); | for (int j=1; j<Group::REMOVED_COFACTOR; j<<=1) q = q.times_two(); | ||||
| decaf_error_t error = r.decode_like_eddsa(p.encode_like_eddsa()); | |||||
| decaf_error_t error = r.decode_like_eddsa_noexcept(p.encode_like_eddsa()); | |||||
| if (error != DECAF_SUCCESS) { | if (error != DECAF_SUCCESS) { | ||||
| test.fail(); | test.fail(); | ||||
| printf(" Decode like EdDSA failed."); | printf(" Decode like EdDSA failed."); | ||||