Commit d4f4d0ed authored by Michael Hamburg's avatar Michael Hamburg

ready for prime time?

parent 83c59a64
......@@ -29,6 +29,7 @@
#define NONNULL2 __attribute__((nonnull(1,2)))
#define NONNULL3 __attribute__((nonnull(1,2,3)))
/** Types of internal words. TODO: ARCH: make 32-bit clean */
typedef uint64_t decaf_word_t, decaf_bool_t;
/* TODO: prefix all these operations and factor to support multiple curves. */
......@@ -49,21 +50,20 @@ typedef struct decaf_point_s {
decaf_word_t x[DECAF_LIMBS],y[DECAF_LIMBS],z[DECAF_LIMBS],t[DECAF_LIMBS];
} decaf_point_t[1];
/** Scalar is stored packed, because we don't need the speed. */
typedef struct decaf_scalar_s {
decaf_word_t limb[DECAF_SCALAR_LIMBS];
} decaf_scalar_t[1];
/** DECAF_TRUE = -1 so that DECAF_TRUE & x = x */
static const decaf_bool_t DECAF_TRUE = -(decaf_bool_t)1, DECAF_FALSE = 0;
/** NB Success is -1, failure is 0. TODO: see if people would rather the reverse. */
static const decaf_bool_t DECAF_SUCCESS = -(decaf_bool_t)1 /*DECAF_TRUE*/,
DECAF_FAILURE = 0 /*DECAF_FALSE*/;
/** The identity point on the curve. */
const decaf_point_t decaf_identity API_VIS;
/** The prime p, for debugging purposes.
* FIXME: prevent this scalar from actually being used for non-debugging purposes?
* TODO: prevent this scalar from actually being used for non-debugging purposes?
*/
const decaf_scalar_t decaf_scalar_p API_VIS;
......@@ -73,17 +73,22 @@ const decaf_scalar_t decaf_scalar_one API_VIS;
/** A scalar equal to 0. */
const decaf_scalar_t decaf_scalar_zero API_VIS;
/** An arbitrarily chosen base point on the curve. TODO: define */
const decaf_point_t decaf_basepoint API_VIS;
/** The identity point on the curve. */
const decaf_point_t decaf_point_identity API_VIS;
/**
* An arbitrarily chosen base point on the curve.
* Equal to Ed448-Goldilocks base point defined by DJB, except of course that
* it's on the twist in this case. TODO: choose a base point with nice encoding?
*/
const decaf_point_t decaf_point_base API_VIS;
#ifdef __cplusplus
extern "C" {
#endif
/* TODO: scalar invert? */
// TODO: ser, deser, inv?.
// FIXME: scalar math is untested, and therefore probably wrong.
/**
* @brief Read a scalar from wire format or from bytes.
*
......@@ -96,7 +101,7 @@ extern "C" {
* @param [in] ser Serialized form of a scalar.
* @param [out] out Deserialized form.
*/
decaf_bool_t decaf_decode_scalar(
decaf_bool_t decaf_scalar_decode (
decaf_scalar_t s,
const unsigned char ser[DECAF_SER_BYTES]
) API_VIS NONNULL2;
......@@ -107,7 +112,7 @@ decaf_bool_t decaf_decode_scalar(
* @param [out] ser Serialized form of a scalar.
* @param [in] s Deserialized scalar.
*/
void decaf_encode_scalar(
void decaf_scalar_encode (
unsigned char ser[DECAF_SER_BYTES],
const decaf_scalar_t s
) API_VIS NONNULL2;
......@@ -118,7 +123,7 @@ void decaf_encode_scalar(
* @param [in] b Another scalar.
* @param [out] out a+b.
*/
void decaf_add_scalars (
void decaf_scalar_add (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -131,7 +136,7 @@ void decaf_add_scalars (
* @retval DECAF_TRUE The scalars are equal.
* @retval DECAF_FALSE The scalars are not equal.
*/
decaf_bool_t decaf_eq_scalars (
decaf_bool_t decaf_scalar_eq (
const decaf_scalar_t a,
const decaf_scalar_t b
) API_VIS WARN_UNUSED NONNULL2;
......@@ -142,7 +147,7 @@ decaf_bool_t decaf_eq_scalars (
* @param [in] b Another scalar.
* @param [out] out a-b.
*/
void decaf_sub_scalars (
void decaf_scalar_sub (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -154,7 +159,7 @@ void decaf_sub_scalars (
* @param [in] b Another scalar.
* @param [out] out a*b.
*/
void decaf_mul_scalars (
void decaf_scalar_mul (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -166,7 +171,7 @@ void decaf_mul_scalars (
* @param [out] ser The byte representation of the point.
* @param [in] pt The point to encode.
*/
void decaf_encode (
void decaf_point_encode (
uint8_t ser[DECAF_SER_BYTES],
const decaf_point_t pt
) API_VIS NONNULL2;
......@@ -184,7 +189,7 @@ void decaf_encode (
* @retval DECAF_FAILURE The decoding didn't succeed, because
* ser does not represent a point.
*/
decaf_bool_t decaf_decode (
decaf_bool_t decaf_point_decode (
decaf_point_t pt,
const uint8_t ser[DECAF_SER_BYTES],
decaf_bool_t allow_identity
......@@ -197,7 +202,7 @@ decaf_bool_t decaf_decode (
* @param [out] a A copy of the point.
* @param [in] b Any point.
*/
void decaf_copy (
void decaf_point_copy (
decaf_point_t a,
const decaf_point_t b
) API_VIS NONNULL2;
......@@ -211,7 +216,7 @@ void decaf_copy (
* @retval DECAF_TRUE The points are equal.
* @retval DECAF_FALSE The points are not equal.
*/
decaf_bool_t decaf_eq (
decaf_bool_t decaf_point_eq (
const decaf_point_t a,
const decaf_point_t b
) API_VIS WARN_UNUSED NONNULL2;
......@@ -225,7 +230,7 @@ decaf_bool_t decaf_eq (
* @param [in] a An addend.
* @param [in] b An addend.
*/
void decaf_add (
void decaf_point_add (
decaf_point_t sum,
const decaf_point_t a,
const decaf_point_t b
......@@ -240,7 +245,7 @@ void decaf_add (
* @param [in] a The minuend.
* @param [in] b The subtrahend.
*/
void decaf_sub (
void decaf_point_sub (
decaf_point_t diff,
const decaf_point_t a,
const decaf_point_t b
......@@ -252,13 +257,11 @@ void decaf_sub (
* @param [out] scaled The scaled point base*scalar
* @param [in] base The point to be scaled.
* @param [in] scalar The scalar to multilpy by.
* @param [in] scalar_words The number of words in the scalar [TODO]
*/
void decaf_scalarmul (
void decaf_point_scalarmul (
decaf_point_t scaled,
const decaf_point_t base,
const decaf_word_t *scalar,
unsigned int scalar_words
const decaf_scalar_t scalar
) API_VIS NONNULL3;
/**
......@@ -268,7 +271,7 @@ void decaf_scalarmul (
* @retval DECAF_TRUE The point is valid.
* @retval DECAF_FALSE The point is invalid.
*/
decaf_bool_t decaf_valid (
decaf_bool_t decaf_point_valid (
const decaf_point_t toTest
) API_VIS WARN_UNUSED NONNULL1;
......@@ -299,7 +302,7 @@ decaf_bool_t decaf_valid (
* @param [in] hashed_data Output of some hash function.
* @param [out] pt The data hashed to the curve.
*/
void decaf_nonuniform_map_to_curve (
void decaf_point_from_hash_nonuniform (
decaf_point_t pt,
const unsigned char hashed_data[DECAF_SER_BYTES]
) API_VIS NONNULL2;
......@@ -307,18 +310,21 @@ void decaf_nonuniform_map_to_curve (
/**
* @brief Indifferentiable hash function encoding to curve.
*
* Equivalent to calling decaf_nonuniform_map_to_curve twice and adding.
* Equivalent to calling decaf_point_from_hash_nonuniform twice and adding.
*
* @param [in] hashed_data Output of some hash function.
* @param [out] pt The data hashed to the curve.
*/
void decaf_uniform_map_to_curve (
void decaf_point_from_hash_uniform (
decaf_point_t pt,
const unsigned char hashed_data[2*DECAF_SER_BYTES]
) API_VIS NONNULL2;
/* TODO: functions to invert point_from_hash?? */
#undef API_VIS
#undef WARN_UNUSED
#undef NONNULL1
#undef NONNULL2
#undef NONNULL3
......
......@@ -279,7 +279,7 @@ sv decaf_montmul (
decaf_subx(out, accum, p, p, hi_carry);
}
void decaf_mul_scalars (
void decaf_scalar_mul (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -288,7 +288,7 @@ void decaf_mul_scalars (
decaf_montmul(out,out,decaf_scalar_r2,decaf_scalar_p,DECAF_MONTGOMERY_FACTOR);
}
void decaf_sub_scalars (
void decaf_scalar_sub (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -296,7 +296,7 @@ void decaf_sub_scalars (
decaf_subx(out, a->limb, b, decaf_scalar_p, 0);
}
void decaf_add_scalars (
void decaf_scalar_add (
decaf_scalar_t out,
const decaf_scalar_t a,
const decaf_scalar_t b
......@@ -311,7 +311,7 @@ void decaf_add_scalars (
decaf_subx(out, out->limb, decaf_scalar_p, decaf_scalar_p, chain);
}
decaf_bool_t decaf_eq_scalars (
decaf_bool_t decaf_scalar_eq (
const decaf_scalar_t a,
const decaf_scalar_t b
) {
......@@ -326,9 +326,20 @@ decaf_bool_t decaf_eq_scalars (
/* *** API begins here *** */
/** identity = (0,1) */
const decaf_point_t decaf_identity = {{{0},{1},{1},{0}}};
void decaf_encode( unsigned char ser[DECAF_SER_BYTES], const decaf_point_t p ) {
const decaf_point_t decaf_point_identity = {{{0},{1},{1},{0}}};
/** base = twist of Goldilocks base point (~,19). FIXME: ARCH */
const decaf_point_t decaf_point_base = {{
{ 0xb39a2d57e08c7bull,0xb38639c75ff281ull,0x2ec981082b3288ull,0x99fe8607e5237cull,
0x0e33fbb1fadd1full,0xe714f67055eb4aull,0xc9ae06d64067ddull,0xf7be45054760faull },
{ 0xbd8715f551617full,0x8c17fbeca8f5fcull,0xaae0eec209c06full,0xce41ad80cbe6b8ull,
0xdf360b5c828c00ull,0xaf25b6bbb40e3bull,0x8ed37f0ce4ed31ull,0x72a1c3214557b9ull },
{ 1 },
{ 0x97ca9c8ed8bde9ull,0xf0b780da83304cull,0x0d79c0a7729a69ull,0xc18d3f24aebc1cull,
0x1fbb5389b3fda5ull,0xbb24f674635948ull,0x723a55709a3983ull,0xe1c0107a823dd4ull }
}};
void decaf_point_encode( unsigned char ser[DECAF_SER_BYTES], const decaf_point_t p ) {
gf a, b, c, d;
gf_mlw ( a, p->y, 1-EDWARDS_D );
gf_mul ( c, a, p->t );
......@@ -380,7 +391,7 @@ static decaf_bool_t gf_deser(gf s, const unsigned char ser[DECAF_SER_BYTES]) {
}
/* Constant-time add or subtract */
sv decaf_add_sub (
sv decaf_point_add_sub (
decaf_point_t p,
const decaf_point_t q,
const decaf_point_t r,
......@@ -410,7 +421,7 @@ sv decaf_add_sub (
gf_mul ( p->t, b, c );
}
decaf_bool_t decaf_decode (
decaf_bool_t decaf_point_decode (
decaf_point_t p,
const unsigned char ser[DECAF_SER_BYTES],
decaf_bool_t allow_identity
......@@ -444,16 +455,16 @@ decaf_bool_t decaf_decode (
return succ;
}
void decaf_sub(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) {
decaf_add_sub(a,b,c,-1);
void decaf_point_sub(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) {
decaf_point_add_sub(a,b,c,-1);
}
void decaf_add(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) {
decaf_add_sub(a,b,c,0);
void decaf_point_add(decaf_point_t a, const decaf_point_t b, const decaf_point_t c) {
decaf_point_add_sub(a,b,c,0);
}
/* No dedicated point double (PERF) */
#define decaf_dbl(a,b) decaf_add(a,b,b)
#define decaf_dbl(a,b) decaf_point_add(a,b,b)
void decaf_copy (
decaf_point_t a,
......@@ -465,7 +476,7 @@ void decaf_copy (
gf_cpy(a->t, b->t);
}
decaf_bool_t decaf_decode_scalar(
decaf_bool_t decaf_scalar_decode(
decaf_scalar_t s,
const unsigned char ser[DECAF_SER_BYTES]
) {
......@@ -483,12 +494,12 @@ decaf_bool_t decaf_decode_scalar(
accum = (accum + s->limb[i] - decaf_scalar_p->limb[i]) >> WBITS;
}
//decaf_mul_scalars(s,s,decaf_scalar_one); /* ham-handed reduce */
decaf_scalar_mul(s,s,decaf_scalar_one); /* ham-handed reduce */
return accum;
}
void decaf_encode_scalar(
void decaf_scalar_encode(
unsigned char ser[DECAF_SER_BYTES],
const decaf_scalar_t s
) {
......@@ -500,16 +511,11 @@ void decaf_encode_scalar(
}
}
void decaf_scalarmul (
void decaf_point_scalarmul (
decaf_point_t a,
const decaf_point_t b,
const decaf_word_t *scalar,
unsigned int scalar_words
const decaf_scalar_t scalar
) {
if (scalar_words == 0) {
decaf_copy(a,decaf_identity);
return;
}
/* w=2 signed window uses about 1.5 adds per bit.
* I figured a few extra lines was worth the 25% speedup.
* NB: if adapting this function to scalarmul by a
......@@ -518,22 +524,22 @@ void decaf_scalarmul (
decaf_point_t w,b3,tmp;
decaf_dbl(w,b);
/* b3 = b*3 */
decaf_add(b3,w,b);
decaf_point_add(b3,w,b);
int i;
for (i=scalar_words*WBITS-2; i>0; i-=2) {
decaf_word_t bits = scalar[i/WBITS]>>(i%WBITS);
for (i=DECAF_SCALAR_LIMBS*WBITS-2; i>0; i-=2) {
decaf_word_t bits = scalar->limb[i/WBITS]>>(i%WBITS);
decaf_cond_sel(tmp,b,b3,((bits^(bits>>1))&1)-1);
decaf_dbl(w,w);
decaf_add_sub(w,w,tmp,((bits>>1)&1)-1);
decaf_point_add_sub(w,w,tmp,((bits>>1)&1)-1);
decaf_dbl(w,w);
}
decaf_add_sub(w,w,b,((scalar[0]>>1)&1)-1);
decaf_point_add_sub(w,w,b,((scalar->limb[0]>>1)&1)-1);
/* low bit is special because fo signed window */
decaf_cond_sel(tmp,b,decaf_identity,-(scalar[0]&1));
decaf_sub(a,w,tmp);
decaf_cond_sel(tmp,b,decaf_point_identity,-(scalar->limb[0]&1));
decaf_point_sub(a,w,tmp);
}
decaf_bool_t decaf_eq ( const decaf_point_t p, const decaf_point_t q ) {
decaf_bool_t decaf_point_eq ( const decaf_point_t p, const decaf_point_t q ) {
/* equality mod 2-torsion compares x/y */
gf a, b;
gf_mul ( a, p->y, q->x );
......@@ -543,7 +549,7 @@ decaf_bool_t decaf_eq ( const decaf_point_t p, const decaf_point_t q ) {
static const int QUADRATIC_NONRESIDUE = -1;
void decaf_nonuniform_map_to_curve (
void decaf_point_from_hash_nonuniform (
decaf_point_t p,
const unsigned char ser[DECAF_SER_BYTES]
) {
......@@ -583,17 +589,17 @@ void decaf_nonuniform_map_to_curve (
gf_mul(p->t,b,e);
}
void decaf_uniform_map_to_curve (
void decaf_point_from_hash_uniform (
decaf_point_t pt,
const unsigned char hashed_data[2*DECAF_SER_BYTES]
) {
decaf_point_t pt2;
decaf_nonuniform_map_to_curve(pt,hashed_data);
decaf_nonuniform_map_to_curve(pt2,&hashed_data[DECAF_SER_BYTES]);
decaf_add(pt,pt,pt2);
decaf_point_from_hash_nonuniform(pt,hashed_data);
decaf_point_from_hash_nonuniform(pt2,&hashed_data[DECAF_SER_BYTES]);
decaf_point_add(pt,pt,pt2);
}
decaf_bool_t decaf_valid (
decaf_bool_t decaf_point_valid (
const decaf_point_t p
) {
gf a,b,c;
......
......@@ -271,7 +271,7 @@ int main(int argc, char **argv) {
memset(bsc,0,sizeof(bsc));
when = now();
for (i=0; i<nbase*10; i++) {
decaf_mul_scalars(csc,asc,bsc);
decaf_scalar_mul(csc,asc,bsc);
}
when = now() - when;
printf("decaf mulsc: %5.1fns\n", when * 1e9 / i);
......@@ -302,7 +302,7 @@ int main(int argc, char **argv) {
memset(Dc,0,sizeof(Dc));
when = now();
for (i=0; i<nbase*100; i++) {
decaf_add(Da,Db,Dc);
decaf_point_add(Da,Db,Dc);
}
when = now() - when;
printf("dec + dec: %5.1fns\n", when * 1e9 / i);
......@@ -368,7 +368,7 @@ int main(int argc, char **argv) {
when = now();
for (i=0; i<nbase/10; i++) {
decaf_scalarmul(Da,Db,sk,sizeof(sk)/sizeof(word_t));
decaf_point_scalarmul(Da,Db,asc);
}
when = now() - when;
printf("decaf slow: %5.1fµs\n", when * 1e6 / i);
......
......@@ -44,7 +44,7 @@ static mask_t mpz_to_scalar (
mpz_init(modded);
mpz_mod(modded, in, mp_scalar_field);
mpz_export(ser, NULL, -1, 1, -1, 0, modded);
mask_t succ = decaf_decode_scalar(out, ser);
mask_t succ = decaf_scalar_decode(out, ser);
return succ;
}
......@@ -62,7 +62,7 @@ static mask_t scalar_assert_eq_gmp(
memset(yser,0,sizeof(yser));
decaf_encode_scalar(xser, x);
decaf_scalar_encode(xser, x);
mpz_init(modded);
mpz_mod(modded, y, mp_scalar_field);
......@@ -224,15 +224,15 @@ static mask_t test_scalar (
succ &= mpz_to_scalar(yy,y);
mpz_init(t);
decaf_add_scalars(tt,xx,yy);
decaf_scalar_add(tt,xx,yy);
mpz_add(t,x,y);
succ &= scalar_assert_eq_gmp("scalar add",xx,yy,tt,x,y,t);
decaf_sub_scalars(tt,xx,yy);
decaf_scalar_sub(tt,xx,yy);
mpz_sub(t,x,y);
succ &= scalar_assert_eq_gmp("scalar sub",xx,yy,tt,x,y,t);
decaf_mul_scalars(tt,xx,yy);
decaf_scalar_mul(tt,xx,yy);
mpz_mul(t,x,y);
succ &= scalar_assert_eq_gmp("scalar mul",xx,yy,tt,x,y,t);
......
......@@ -160,11 +160,11 @@ add_double_test (
decaf_point_t ted3;
convert_tw_extensible_to_tw_extended(&ted1, &text1);
convert_tw_extensible_to_tw_extended(&ted2, &text2);
decaf_add(ted3, (struct decaf_point_s*)&ted1, (struct decaf_point_s*)&ted2);
decaf_point_add(ted3, (struct decaf_point_s*)&ted1, (struct decaf_point_s*)&ted2);
add_tw_extended(&ted1, &ted2);
convert_tw_extensible_to_tw_extended(&ted2, &textb);
if (~decaf_eq_tw_extended(&ted1, &ted2) | ~decaf_eq((struct decaf_point_s*)&ted1, ted3)) {
if (~decaf_eq_tw_extended(&ted1, &ted2) | ~decaf_point_eq((struct decaf_point_s*)&ted1, ted3)) {
youfail();
succ = 0;
printf(" Tw extended simple compat:\n");
......@@ -359,8 +359,8 @@ int test_decaf_evil (void) {
uint8_t ser_de[56], ser_ed[56];
decaf_point_t pt_dec, pt_dec2;
memcpy(pt_dec, pt_ed, sizeof(pt_dec));
decaf_encode(ser_de, pt_dec);
mask_t succ_dec = decaf_decode(pt_dec2, ser_de, -1);
decaf_point_encode(ser_de, pt_dec);
mask_t succ_dec = decaf_point_decode(pt_dec2, ser_de, -1);
field_serialize(ser_ed, out_ed);
decaf_point_t p,q,m;
......@@ -373,17 +373,17 @@ int test_decaf_evil (void) {
field_serialize(oo_base_ser,oo_base);
field_neg(tmp,base);
field_serialize(n_base_ser,tmp); // = -base
decaf_nonuniform_map_to_curve (p,random_input);
decaf_nonuniform_map_to_curve (q,oo_base_ser);
decaf_nonuniform_map_to_curve (m,n_base_ser);
mask_t succ_nur = decaf_valid(p);
succ_nur &= decaf_valid(q);
succ_nur &= decaf_valid(m);
decaf_point_from_hash_nonuniform (p,random_input);
decaf_point_from_hash_nonuniform (q,oo_base_ser);
decaf_point_from_hash_nonuniform (m,n_base_ser);
mask_t succ_nur = decaf_point_valid(p);
succ_nur &= decaf_point_valid(q);
succ_nur &= decaf_point_valid(m);
mask_t eq_neg, eq_pos;
eq_neg = decaf_eq(m,p);
decaf_add(m,p,q);
eq_pos = decaf_eq(m,decaf_identity);
eq_neg = decaf_point_eq(m,p);
decaf_point_add(m,p,q);
eq_pos = decaf_point_eq(m,decaf_point_identity);
if ((care_should && should != s_m)
|| ~s_base || s_e != s_te || s_m != s_te || s_ed != s_te
......@@ -391,8 +391,8 @@ int test_decaf_evil (void) {
|| (s_ed && ~field_eq(out_e,out_ed))
|| memcmp(ser_de, ser_ed, 56)
|| (s_e & ~succ_dec)
|| (s_e & ~decaf_eq(pt_dec, pt_dec2)
|| (s_e & ~decaf_valid(pt_dec))
|| (s_e & ~decaf_point_eq(pt_dec, pt_dec2)
|| (s_e & ~decaf_point_valid(pt_dec))
|| ~succ_nur
|| ~eq_neg
|| ~eq_pos)
......@@ -429,6 +429,20 @@ int test_decaf (void) {
crandom_init_from_buffer(&crand, "my test_decaf random initializer");
int i, hits = 0, fails = 0;
if (~decaf_point_valid(decaf_point_base)) {
youfail();
printf(" Decaf base point invalid\n");
fails++;
}
if (~decaf_point_valid(decaf_point_identity)) {
youfail();
printf(" Decaf identity point invalid\n");
fails++;
}
for (i=0; i<1000; i++) {
uint8_t ser[FIELD_BYTES];
......
......@@ -114,7 +114,7 @@ single_scalarmul_compatibility_test (
decaf_point_t ed2;
tw_extended_a_t ed;
convert_tw_extensible_to_tw_extended(ed, &text);
decaf_scalarmul(ed2, (struct decaf_point_s *)ed, scalar, 7);
decaf_point_scalarmul(ed2, (struct decaf_point_s *)ed, (struct decaf_scalar_s *)scalar);
scalarmul_ed(ed, scalar);
field_copy(work.x, ed->x);
......@@ -125,8 +125,8 @@ single_scalarmul_compatibility_test (
untwist_and_double_and_serialize(sced, &work);
uint8_t ser1[(FIELD_BITS+6)/8], ser2[(FIELD_BITS+6)/8];
decaf_encode(ser1, (struct decaf_point_s *)ed);
decaf_encode(ser2, ed2);
decaf_point_encode(ser1, (struct decaf_point_s *)ed);
decaf_point_encode(ser2, ed2);
/* check consistency mont vs window */
consistent &= field_eq(mont, ct);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment