@@ -518,9 +518,8 @@ void decaf_255_point_debugging_torque ( | |||||
* | * | ||||
* @param [in] hashed_data Output of some hash function. | * @param [in] hashed_data Output of some hash function. | ||||
* @param [out] pt The data hashed to the curve. | * @param [out] pt The data hashed to the curve. | ||||
* @return A "hint" value which can be used to help invert the encoding. | |||||
*/ | */ | ||||
uint16_t | |||||
void | |||||
decaf_255_point_from_hash_nonuniform ( | decaf_255_point_from_hash_nonuniform ( | ||||
decaf_255_point_t pt, | decaf_255_point_t pt, | ||||
const unsigned char hashed_data[DECAF_255_SER_BYTES] | const unsigned char hashed_data[DECAF_255_SER_BYTES] | ||||
@@ -530,13 +529,11 @@ decaf_255_point_from_hash_nonuniform ( | |||||
* @brief Inverse of elligator-like hash to curve. | * @brief Inverse of elligator-like hash to curve. | ||||
* | * | ||||
* This function writes to the buffer, to make it so that | * This function writes to the buffer, to make it so that | ||||
* decaf_255_point_from_hash_nonuniform(buffer) = pt,hint | |||||
* if possible. | |||||
* decaf_255_point_from_hash_nonuniform(buffer) = pt if possible. | |||||
* | * | ||||
* @param [out] recovered_hash Encoded data. | * @param [out] recovered_hash Encoded data. | ||||
* @param [in] pt The point to encode. | * @param [in] pt The point to encode. | ||||
* @param [in] hint The hint value returned from | |||||
* decaf_255_point_from_hash_nonuniform. | |||||
* @param [in] which A "hint" that indicates which inverse to return. | |||||
* | * | ||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The pt isn't the image of | * @retval DECAF_FAILURE The pt isn't the image of | ||||
@@ -549,7 +546,7 @@ decaf_bool_t | |||||
decaf_255_invert_elligator_nonuniform ( | decaf_255_invert_elligator_nonuniform ( | ||||
unsigned char recovered_hash[DECAF_255_SER_BYTES], | unsigned char recovered_hash[DECAF_255_SER_BYTES], | ||||
const decaf_255_point_t pt, | const decaf_255_point_t pt, | ||||
uint16_t hint | |||||
uint16_t which | |||||
) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | ) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | ||||
/** | /** | ||||
@@ -557,26 +554,21 @@ decaf_255_invert_elligator_nonuniform ( | |||||
* | * | ||||
* This function modifies the first DECAF_255_SER_BYTES of the | * This function modifies the first DECAF_255_SER_BYTES of the | ||||
* buffer, to make it so that | * buffer, to make it so that | ||||
* decaf_255_point_from_hash_uniform(buffer) = pt,hint | |||||
* if possible. | |||||
* decaf_255_point_from_hash_uniform(buffer) = pt if possible. | |||||
* | * | ||||
* @param [out] recovered_hash Encoded data. | * @param [out] recovered_hash Encoded data. | ||||
* @param [in] pt The point to encode. | * @param [in] pt The point to encode. | ||||
* @param [in] hint The hint value returned from | |||||
* decaf_255_point_from_hash_nonuniform. | |||||
* @param [in] which A "hint" that indicates which inverse to return. | |||||
* | * | ||||
* @retval DECAF_SUCCESS The inverse succeeded. | * @retval DECAF_SUCCESS The inverse succeeded. | ||||
* @retval DECAF_FAILURE The pt isn't the image of | * @retval DECAF_FAILURE The pt isn't the image of | ||||
* decaf_255_point_from_hash_uniform with the given hint. | * decaf_255_point_from_hash_uniform with the given hint. | ||||
* | |||||
* @warning The hinting system is subject to change, especially in corner cases. | |||||
* @warning FIXME The hinting system doesn't work for certain inputs which have many 0xFF. | |||||
*/ | */ | ||||
decaf_bool_t | decaf_bool_t | ||||
decaf_255_invert_elligator_uniform ( | decaf_255_invert_elligator_uniform ( | ||||
unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | ||||
const decaf_255_point_t pt, | const decaf_255_point_t pt, | ||||
uint16_t hint | |||||
uint16_t which | |||||
) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | ) API_VIS NONNULL2 NOINLINE WARN_UNUSED; | ||||
/** | /** | ||||
@@ -586,9 +578,8 @@ decaf_255_invert_elligator_uniform ( | |||||
* | * | ||||
* @param [in] hashed_data Output of some hash function. | * @param [in] hashed_data Output of some hash function. | ||||
* @param [out] pt The data hashed to the curve. | * @param [out] pt The data hashed to the curve. | ||||
* @return A "hint" value which can be used to help invert the encoding. | |||||
*/ | */ | ||||
uint16_t decaf_255_point_from_hash_uniform ( | |||||
void decaf_255_point_from_hash_uniform ( | |||||
decaf_255_point_t pt, | decaf_255_point_t pt, | ||||
const unsigned char hashed_data[2*DECAF_255_SER_BYTES] | const unsigned char hashed_data[2*DECAF_255_SER_BYTES] | ||||
) API_VIS NONNULL2 NOINLINE; | ) API_VIS NONNULL2 NOINLINE; | ||||
@@ -491,19 +491,19 @@ public: | |||||
* If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, | * If the buffer is shorter than 2*HASH_BYTES, well, it won't be as uniform, | ||||
* but the buffer will be zero-padded on the right. | * but the buffer will be zero-padded on the right. | ||||
*/ | */ | ||||
inline unsigned char set_to_hash( const Block &s ) NOEXCEPT { | |||||
inline void set_to_hash( const Block &s ) NOEXCEPT { | |||||
if (s.size() < HASH_BYTES) { | if (s.size() < HASH_BYTES) { | ||||
SecureBuffer b(HASH_BYTES); | SecureBuffer b(HASH_BYTES); | ||||
memcpy(b.data(), s.data(), s.size()); | memcpy(b.data(), s.data(), s.size()); | ||||
return decaf_255_point_from_hash_nonuniform(p,b); | |||||
decaf_255_point_from_hash_nonuniform(p,b); | |||||
} else if (s.size() == HASH_BYTES) { | } else if (s.size() == HASH_BYTES) { | ||||
return decaf_255_point_from_hash_nonuniform(p,s); | |||||
decaf_255_point_from_hash_nonuniform(p,s); | |||||
} else if (s.size() < 2*HASH_BYTES) { | } else if (s.size() < 2*HASH_BYTES) { | ||||
SecureBuffer b(2*HASH_BYTES); | SecureBuffer b(2*HASH_BYTES); | ||||
memcpy(b.data(), s.data(), s.size()); | memcpy(b.data(), s.data(), s.size()); | ||||
return decaf_255_point_from_hash_uniform(p,b); | |||||
decaf_255_point_from_hash_uniform(p,b); | |||||
} else { | } else { | ||||
return decaf_255_point_from_hash_uniform(p,s); | |||||
decaf_255_point_from_hash_uniform(p,s); | |||||
} | } | ||||
} | } | ||||
@@ -493,9 +493,11 @@ static void deisogenize ( | |||||
gf_sub ( x, ZERO, x ); | gf_sub ( x, ZERO, x ); | ||||
gf_sub ( t, ZERO, t ); | gf_sub ( t, ZERO, t ); | ||||
gf DEBUG; | |||||
gf_add ( a, p->z, x ); | gf_add ( a, p->z, x ); | ||||
gf_sub ( b, p->z, x ); | gf_sub ( b, p->z, x ); | ||||
gf_mul ( c, a, b ); /* "zx" = Z^2 - X^2 */ | gf_mul ( c, a, b ); /* "zx" = Z^2 - X^2 */ | ||||
gf_cpy(DEBUG,c); | |||||
gf_mul ( a, p->z, t ); /* "tz" = T*Z */ | gf_mul ( a, p->z, t ); /* "tz" = T*Z */ | ||||
gf_sqr ( b, a ); | gf_sqr ( b, a ); | ||||
gf_mul ( d, b, c ); /* (TZ)^2 * (Z^2-X^2) */ | gf_mul ( d, b, c ); /* (TZ)^2 * (Z^2-X^2) */ | ||||
@@ -1082,13 +1084,13 @@ decaf_bool_t API_NS(point_eq) ( const point_t p, const point_t q ) { | |||||
return succ; | return succ; | ||||
} | } | ||||
uint16_t API_NS(point_from_hash_nonuniform) ( | |||||
void API_NS(point_from_hash_nonuniform) ( | |||||
point_t p, | point_t p, | ||||
const unsigned char ser[SER_BYTES] | const unsigned char ser[SER_BYTES] | ||||
) { | ) { | ||||
// TODO: simplify since we don't return a hint anymore | |||||
gf r0,r,a,b,c,dee,D,N,rN,e; | gf r0,r,a,b,c,dee,D,N,rN,e; | ||||
decaf_bool_t over = ~gf_deser(r0,ser); | |||||
decaf_bool_t sgn_r0 = hibit(r0); | |||||
gf_deser(r0,ser); | |||||
gf_canon(r0); | gf_canon(r0); | ||||
gf_sqr(a,r0); | gf_sqr(a,r0); | ||||
//gf_sub(r,ZERO,a); /*gf_mlw(r,a,QUADRATIC_NONRESIDUE);*/ | //gf_sub(r,ZERO,a); /*gf_mlw(r,a,QUADRATIC_NONRESIDUE);*/ | ||||
@@ -1143,9 +1145,6 @@ uint16_t API_NS(point_from_hash_nonuniform) ( | |||||
/* Normalize/negate */ | /* Normalize/negate */ | ||||
decaf_bool_t neg_s = hibit(a)^~square; | decaf_bool_t neg_s = hibit(a)^~square; | ||||
cond_neg(a,neg_s); /* ends up negative if ~square */ | cond_neg(a,neg_s); /* ends up negative if ~square */ | ||||
decaf_bool_t sgn_t_over_s = hibit(b)^neg_s; | |||||
sgn_t_over_s &= ~gf_eq(N,ZERO); | |||||
sgn_t_over_s |= gf_eq(D,ZERO); | |||||
/* b <- t */ | /* b <- t */ | ||||
cond_sel(b,c,ONE,gf_eq(c,ZERO)); /* 0,0 -> 1,0 */ | cond_sel(b,c,ONE,gf_eq(c,ZERO)); /* 0,0 -> 1,0 */ | ||||
@@ -1164,8 +1163,6 @@ uint16_t API_NS(point_from_hash_nonuniform) ( | |||||
gf_mul(p->z,a,b); /* (1-s^2)t */ | gf_mul(p->z,a,b); /* (1-s^2)t */ | ||||
assert(API_NS(point_valid)(p)); | assert(API_NS(point_valid)(p)); | ||||
return (~square & 1) | (sgn_t_over_s & 2) | (sgn_r0 & 4) | (over & 16); | |||||
} | } | ||||
decaf_bool_t | decaf_bool_t | ||||
@@ -1212,17 +1209,14 @@ API_NS(invert_elligator_nonuniform) ( | |||||
return succ; | return succ; | ||||
} | } | ||||
uint16_t API_NS(point_from_hash_uniform) ( | |||||
void API_NS(point_from_hash_uniform) ( | |||||
point_t pt, | point_t pt, | ||||
const unsigned char hashed_data[2*SER_BYTES] | const unsigned char hashed_data[2*SER_BYTES] | ||||
) { | ) { | ||||
point_t pt2; | point_t pt2; | ||||
unsigned char ret1 = | |||||
API_NS(point_from_hash_nonuniform)(pt,hashed_data); | |||||
unsigned char ret2 = | |||||
API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]); | |||||
API_NS(point_from_hash_nonuniform)(pt,hashed_data); | |||||
API_NS(point_from_hash_nonuniform)(pt2,&hashed_data[SER_BYTES]); | |||||
API_NS(point_add)(pt,pt,pt2); | API_NS(point_add)(pt,pt,pt2); | ||||
return ret1 | ((uint16_t)ret2<<8); | |||||
} | } | ||||
decaf_bool_t | decaf_bool_t | ||||
@@ -164,30 +164,12 @@ static void test_elligator() { | |||||
decaf::SpongeRng rng(decaf::Block("test_elligator")); | decaf::SpongeRng rng(decaf::Block("test_elligator")); | ||||
Test test("Elligator"); | Test test("Elligator"); | ||||
/* | |||||
for (int i=0; i<32; i++) { | |||||
decaf::SecureBuffer b1(Point::HASH_BYTES); | |||||
Point p = Point::identity(); | |||||
for (int j=0; j<i/8; j++) p.debugging_torque_in_place(); | |||||
bool succ = p.invert_elligator(b1,i&7); | |||||
Point q; | |||||
unsigned char hint = q.set_to_hash(b1); | |||||
if (succ != ((i&7) != 4) || (q != p) || (succ && (hint != (i&7)))) { | |||||
test.fail(); | |||||
printf("Elligator test: t=%d, h=%d->%d, q%sp, %s %02x%02x\n", | |||||
i/8, i&7, hint, (q==p)?"==":"!=",succ ? "SUCC" : "FAIL", | |||||
b1[0], b1[1]); | |||||
} | |||||
} | |||||
*/ | |||||
const int NHINTS = 1<<4; | const int NHINTS = 1<<4; | ||||
decaf::SecureBuffer *alts[NHINTS]; | decaf::SecureBuffer *alts[NHINTS]; | ||||
bool successes[NHINTS]; | bool successes[NHINTS]; | ||||
for (int i=0; i<NTESTS && (test.passing_now || i < 100); i++) { | for (int i=0; i<NTESTS && (test.passing_now || i < 100); i++) { | ||||
size_t len = 8 + (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | |||||
size_t len = (i % (2*Point::HASH_BYTES + 3)); // FIXME: 0 | |||||
decaf::SecureBuffer b1(len); | decaf::SecureBuffer b1(len); | ||||
rng.read(b1); | rng.read(b1); | ||||
if (i==1) b1[0] = 1; /* special case test */ | if (i==1) b1[0] = 1; /* special case test */ | ||||