| @@ -518,9 +518,8 @@ void decaf_255_point_debugging_torque ( | |||
| * | |||
| * @param [in] hashed_data Output of some hash function. | |||
| * @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_t pt, | |||
| 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. | |||
| * | |||
| * 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 [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_FAILURE The pt isn't the image of | |||
| @@ -549,7 +546,7 @@ decaf_bool_t | |||
| decaf_255_invert_elligator_nonuniform ( | |||
| unsigned char recovered_hash[DECAF_255_SER_BYTES], | |||
| const decaf_255_point_t pt, | |||
| uint16_t hint | |||
| uint16_t which | |||
| ) 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 | |||
| * 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 [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_FAILURE The pt isn't the image of | |||
| * 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_255_invert_elligator_uniform ( | |||
| unsigned char recovered_hash[2*DECAF_255_SER_BYTES], | |||
| const decaf_255_point_t pt, | |||
| uint16_t hint | |||
| uint16_t which | |||
| ) 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 [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, | |||
| const unsigned char hashed_data[2*DECAF_255_SER_BYTES] | |||
| ) 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, | |||
| * 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) { | |||
| SecureBuffer b(HASH_BYTES); | |||
| 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) { | |||
| return decaf_255_point_from_hash_nonuniform(p,s); | |||
| decaf_255_point_from_hash_nonuniform(p,s); | |||
| } else if (s.size() < 2*HASH_BYTES) { | |||
| SecureBuffer b(2*HASH_BYTES); | |||
| 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 { | |||
| 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 ( t, ZERO, t ); | |||
| gf DEBUG; | |||
| gf_add ( a, p->z, x ); | |||
| gf_sub ( b, p->z, x ); | |||
| gf_mul ( c, a, b ); /* "zx" = Z^2 - X^2 */ | |||
| gf_cpy(DEBUG,c); | |||
| gf_mul ( a, p->z, t ); /* "tz" = T*Z */ | |||
| gf_sqr ( b, a ); | |||
| 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; | |||
| } | |||
| uint16_t API_NS(point_from_hash_nonuniform) ( | |||
| void API_NS(point_from_hash_nonuniform) ( | |||
| point_t p, | |||
| 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; | |||
| decaf_bool_t over = ~gf_deser(r0,ser); | |||
| decaf_bool_t sgn_r0 = hibit(r0); | |||
| gf_deser(r0,ser); | |||
| gf_canon(r0); | |||
| gf_sqr(a,r0); | |||
| //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 */ | |||
| decaf_bool_t neg_s = hibit(a)^~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 */ | |||
| 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 */ | |||
| assert(API_NS(point_valid)(p)); | |||
| return (~square & 1) | (sgn_t_over_s & 2) | (sgn_r0 & 4) | (over & 16); | |||
| } | |||
| decaf_bool_t | |||
| @@ -1212,17 +1209,14 @@ API_NS(invert_elligator_nonuniform) ( | |||
| return succ; | |||
| } | |||
| uint16_t API_NS(point_from_hash_uniform) ( | |||
| void API_NS(point_from_hash_uniform) ( | |||
| point_t pt, | |||
| const unsigned char hashed_data[2*SER_BYTES] | |||
| ) { | |||
| 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); | |||
| return ret1 | ((uint16_t)ret2<<8); | |||
| } | |||
| decaf_bool_t | |||
| @@ -164,30 +164,12 @@ static void test_elligator() { | |||
| decaf::SpongeRng rng(decaf::Block("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; | |||
| decaf::SecureBuffer *alts[NHINTS]; | |||
| bool successes[NHINTS]; | |||
| 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); | |||
| rng.read(b1); | |||
| if (i==1) b1[0] = 1; /* special case test */ | |||