From cea1b5ab2d5505d367d5c99556cebd692b778259 Mon Sep 17 00:00:00 2001 From: hololeap Date: Wed, 16 Oct 2024 22:01:43 -0600 Subject: [PATCH 1/3] Revert "Compilation warnings on OpenBSD" Restore the old stack alignment in order to provide AVX2 compatibility. This reverts commit 8be985640270695522700375cfb468c1b226dc3e. Signed-off-by: hololeap --- cbits/decaf/include/decaf/point_448.h | 2 +- cbits/decaf/p448/f_field.h | 2 +- cbits/decaf/tools/generate.sh | 14 -------------- 3 files changed, 2 insertions(+), 16 deletions(-) diff --git a/cbits/decaf/include/decaf/point_448.h b/cbits/decaf/include/decaf/point_448.h index b47247da..edb29461 100644 --- a/cbits/decaf/include/decaf/point_448.h +++ b/cbits/decaf/include/decaf/point_448.h @@ -34,7 +34,7 @@ extern "C" { /** @brief Galois field element internal structure */ typedef struct crypton_gf_448_s { crypton_decaf_word_t limb[512/CRYPTON_DECAF_WORD_BITS]; -} __attribute__((aligned(16))) crypton_gf_448_s, crypton_gf_448_t[1]; +} __attribute__((aligned(32))) crypton_gf_448_s, crypton_gf_448_t[1]; #endif /* __CRYPTON_DECAF_448_GF_DEFINED__ */ /** @endcond */ diff --git a/cbits/decaf/p448/f_field.h b/cbits/decaf/p448/f_field.h index c43f9e4a..9c7074a6 100644 --- a/cbits/decaf/p448/f_field.h +++ b/cbits/decaf/p448/f_field.h @@ -27,7 +27,7 @@ #define SER_BYTES 56 typedef struct crypton_gf_448_s { word_t limb[NLIMBS]; -} __attribute__((aligned(16))) crypton_gf_448_s, crypton_gf_448_t[1]; +} __attribute__((aligned(32))) crypton_gf_448_s, crypton_gf_448_t[1]; #define GF_LIT_LIMB_BITS 56 #define GF_BITS 448 diff --git a/cbits/decaf/tools/generate.sh b/cbits/decaf/tools/generate.sh index 132e1ab8..ef2f445a 100755 --- a/cbits/decaf/tools/generate.sh +++ b/cbits/decaf/tools/generate.sh @@ -22,11 +22,6 @@ # * code related to SHAKE is replaced by crypton code, referenced from # a custom shake.h. As a consequence, portable_endian.h is not needed. # -# * aligned(32) attributes used for stack alignment are replaced by -# aligned(16). This removes warnings on OpenBSD with GCC 4.2.1, and makes -# sure we get at least 16-byte alignment. 32-byte alignment is necessary -# only for AVX2 and arch_x86_64, which we don't have. -# # * visibility("hidden") attributes are removed, as this is not supported # on Windows/MinGW, and we have name mangling instead # @@ -49,19 +44,10 @@ fi convert() { local FILE_NAME="`basename "$1"`" - local REPL - - if [ "$FILE_NAME" = word.h ]; then - REPL='__attribute__((aligned(32)))' - else - REPL='__attribute__((aligned(16)))' - fi - sed <"$1" >"$2/$FILE_NAME" \ -e 's/ __attribute((visibility("hidden")))//g' \ -e 's/ __attribute__((visibility("hidden")))//g' \ -e 's/ __attribute__ ((visibility ("hidden")))//g' \ - -e "s/__attribute__((aligned(32)))/$REPL/g" \ -e 's/decaf_/crypton_decaf_/g' \ -e 's/DECAF_/CRYPTON_DECAF_/g' \ -e 's/gf_/crypton_gf_/g' \ From a00fb179a17634382d181bc7977227c83d64fa1e Mon Sep 17 00:00:00 2001 From: hololeap Date: Wed, 16 Oct 2024 22:08:38 -0600 Subject: [PATCH 2/3] Update cbits/decaf/tools/generate.sh Update upstream commit and path for decaf_tables.c Signed-off-by: hololeap --- cbits/decaf/tools/generate.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cbits/decaf/tools/generate.sh b/cbits/decaf/tools/generate.sh index ef2f445a..3eae038e 100755 --- a/cbits/decaf/tools/generate.sh +++ b/cbits/decaf/tools/generate.sh @@ -6,7 +6,7 @@ # (available at ). # # Project is synced with upstream commit -# '807a7e67decbf8ccc10be862cdf9ae03653ffe70'. +# 'cede6185df1dad9d6e465dddc7f02698d8553726'. # # Notes about transformations applied: # @@ -77,7 +77,7 @@ convert "$SRC_DIR"/GENERATED/include/decaf/point_448.h "$DEST_DIR"/include/decaf for CURVE in ed448goldilocks; do mkdir -p "$DEST_DIR"/$CURVE convert "$SRC_DIR"/GENERATED/c/$CURVE/decaf.c "$DEST_DIR"/$CURVE - convert "$SRC_DIR"/GENERATED/c/$CURVE/decaf_tables.c "$DEST_DIR"/$CURVE + convert "$SRC_DIR"/$CURVE/decaf_tables.c "$DEST_DIR"/$CURVE convert "$SRC_DIR"/GENERATED/c/$CURVE/eddsa.c "$DEST_DIR"/$CURVE convert "$SRC_DIR"/GENERATED/c/$CURVE/scalar.c "$DEST_DIR"/$CURVE From b6bac16ce2aefbf3a688c36fa25a452e7aa5d7d0 Mon Sep 17 00:00:00 2001 From: hololeap Date: Wed, 16 Oct 2024 22:10:22 -0600 Subject: [PATCH 3/3] Update decaf library Generate C code from upstream commit cede6185df1dad9d6e465dddc7f02698d8553726 The following code in the upstream repo was run: cmake . make decaf_tables decaf-static all Signed-off-by: hololeap --- cbits/decaf/ed448goldilocks/decaf.c | 473 +++++++-------- cbits/decaf/ed448goldilocks/decaf_tables.c | 552 +++++++++--------- cbits/decaf/ed448goldilocks/eddsa.c | 136 ++++- cbits/decaf/ed448goldilocks/scalar.c | 32 +- cbits/decaf/include/arch_32/arch_intrinsics.h | 5 + cbits/decaf/include/decaf/common.h | 63 +- cbits/decaf/include/decaf/ed448.h | 204 ++++++- cbits/decaf/include/decaf/point_448.h | 285 +++++---- cbits/decaf/include/field.h | 5 + cbits/decaf/include/word.h | 23 +- cbits/decaf/p448/arch_32/f_impl.c | 4 +- cbits/decaf/p448/f_field.h | 11 +- cbits/decaf/p448/f_generic.c | 32 +- 13 files changed, 1086 insertions(+), 739 deletions(-) diff --git a/cbits/decaf/ed448goldilocks/decaf.c b/cbits/decaf/ed448goldilocks/decaf.c index 1dbfde65..47121dd5 100644 --- a/cbits/decaf/ed448goldilocks/decaf.c +++ b/cbits/decaf/ed448goldilocks/decaf.c @@ -18,6 +18,23 @@ #include #include +/* MSVC has no builtint ctz, this is a fix as in +https://stackoverflow.com/questions/355967/how-to-use-msvc-intrinsics-to-get-the-equivalent-of-this-gcc-code/5468852#5468852 +*/ +#ifdef _MSC_VER +#include + +uint32_t __inline ctz(uint32_t value) +{ + DWORD trailing_zero = 0; + if ( _BitScanForward( &trailing_zero, value ) ) + return trailing_zero; + else + return 32; // This is undefined, I better choose 32 than 0 +} +#define __builtin_ctz(x) ctz(x) +#endif + /* Template stuff */ #define API_NS(_id) crypton_decaf_448_##_id #define SCALAR_BITS CRYPTON_DECAF_448_SCALAR_BITS @@ -48,10 +65,23 @@ static const scalar_t point_scalarmul_adjustment = {{{ const uint8_t crypton_decaf_x448_base_point[CRYPTON_DECAF_X448_PUBLIC_BYTES] = { 0x05 }; -#if COFACTOR==8 || EDDSA_USE_SIGMA_ISOGENY - static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL( - /* NONE */ - )}; +#define RISTRETTO_FACTOR CRYPTON_DECAF_448_RISTRETTO_FACTOR +const gf RISTRETTO_FACTOR = {FIELD_LITERAL( + 0x42ef0f45572736, 0x7bf6aa20ce5296, 0xf4fd6eded26033, 0x968c14ba839a66, 0xb8d54b64a2d780, 0x6aa0a1f1a7b8a5, 0x683bf68d722fa2, 0x22d962fbeb24f7 +)}; + +#if IMAGINE_TWIST +#define TWISTED_D (-(EDWARDS_D)) +#else +#define TWISTED_D ((EDWARDS_D)-1) +#endif + +#if TWISTED_D < 0 +#define EFF_D (-(TWISTED_D)) +#define NEG_D 1 +#else +#define EFF_D TWISTED_D +#define NEG_D 0 #endif /* End of template stuff */ @@ -109,128 +139,112 @@ crypton_gf_invert(gf y, const gf x, int assert_nonzero) { crypton_gf_copy(y, t2); } -/** Return high bit of x = low bit of 2x mod p */ -static mask_t crypton_gf_lobit(const gf x) { - gf y; - crypton_gf_copy(y,x); - crypton_gf_strong_reduce(y); - return -(y->limb[0]&1); -} - /** identity = (0,1) */ const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; +/* Predeclare because not static: called by elligator */ void API_NS(deisogenize) ( crypton_gf_s *__restrict__ s, - crypton_gf_s *__restrict__ minus_t_over_s, + crypton_gf_s *__restrict__ inv_el_sum, + crypton_gf_s *__restrict__ inv_el_m1, const point_t p, - mask_t toggle_hibit_s, - mask_t toggle_hibit_t_over_s, + mask_t toggle_s, + mask_t toggle_altx, mask_t toggle_rotation ); void API_NS(deisogenize) ( crypton_gf_s *__restrict__ s, - crypton_gf_s *__restrict__ minus_t_over_s, + crypton_gf_s *__restrict__ inv_el_sum, + crypton_gf_s *__restrict__ inv_el_m1, const point_t p, - mask_t toggle_hibit_s, - mask_t toggle_hibit_t_over_s, + mask_t toggle_s, + mask_t toggle_altx, mask_t toggle_rotation ) { #if COFACTOR == 4 && !IMAGINE_TWIST - (void) toggle_rotation; - - gf b, d; - crypton_gf_s *c = s, *a = minus_t_over_s; - crypton_gf_mulw(a, p->y, 1-EDWARDS_D); - crypton_gf_mul(c, a, p->t); /* -dYT, with EDWARDS_D = d-1 */ - crypton_gf_mul(a, p->x, p->z); - crypton_gf_sub(d, c, a); /* aXZ-dYT with a=-1 */ - crypton_gf_add(a, p->z, p->y); - crypton_gf_sub(b, p->z, p->y); - crypton_gf_mul(c, b, a); - crypton_gf_mulw(b, c, -EDWARDS_D); /* (a-d)(Z+Y)(Z-Y) */ - mask_t ok = crypton_gf_isr (a,b); /* r in the paper */ - (void)ok; assert(ok | crypton_gf_eq(b,ZERO)); - crypton_gf_mulw (b, a, -EDWARDS_D); /* u in the paper */ - - crypton_gf_mul(c,a,d); /* r(aZX-dYT) */ - crypton_gf_mul(a,b,p->z); /* uZ */ - crypton_gf_add(a,a,a); /* 2uZ */ - - mask_t tg = toggle_hibit_t_over_s ^ ~crypton_gf_hibit(minus_t_over_s); - crypton_gf_cond_neg(minus_t_over_s, tg); /* t/s <-? -t/s */ - crypton_gf_cond_neg(c, tg); /* u <- -u if negative. */ - - crypton_gf_add(d,c,p->y); - crypton_gf_mul(s,b,d); - crypton_gf_cond_neg(s, toggle_hibit_s ^ crypton_gf_hibit(s)); -#else + (void)toggle_rotation; /* Only applies to cofactor 8 */ + gf t1; + crypton_gf_s *t2 = s, *t3=inv_el_sum, *t4=inv_el_m1; + + crypton_gf_add(t1,p->x,p->t); + crypton_gf_sub(t2,p->x,p->t); + crypton_gf_mul(t3,t1,t2); /* t3 = num */ + crypton_gf_sqr(t2,p->x); + crypton_gf_mul(t1,t2,t3); + crypton_gf_mulw(t2,t1,-1-TWISTED_D); /* -x^2 * (a-d) * num */ + crypton_gf_isr(t1,t2); /* t1 = isr */ + crypton_gf_mul(t2,t1,t3); /* t2 = ratio */ + crypton_gf_mul(t4,t2,RISTRETTO_FACTOR); + mask_t negx = crypton_gf_lobit(t4) ^ toggle_altx; + crypton_gf_cond_neg(t2, negx); + crypton_gf_mul(t3,t2,p->z); + crypton_gf_sub(t3,t3,p->t); + crypton_gf_mul(t2,t3,p->x); + crypton_gf_mulw(t4,t2,-1-TWISTED_D); + crypton_gf_mul(s,t4,t1); + mask_t lobs = crypton_gf_lobit(s); + crypton_gf_cond_neg(s,lobs); + crypton_gf_copy(inv_el_m1,p->x); + crypton_gf_cond_neg(inv_el_m1,~lobs^negx^toggle_s); + crypton_gf_add(inv_el_m1,inv_el_m1,p->t); + +#elif COFACTOR == 8 && IMAGINE_TWIST /* More complicated because of rotation */ - /* MAGIC This code is wrong for certain non-Curve25519 curves; - * check if it's because of Cofactor==8 or IMAGINE_TWIST */ - - gf c, d; - crypton_gf_s *b = s, *a = minus_t_over_s; - - #if IMAGINE_TWIST - gf x, t; - crypton_gf_div_qnr(x,p->x); - crypton_gf_div_qnr(t,p->t); - crypton_gf_add ( a, p->z, x ); - crypton_gf_sub ( b, p->z, x ); - crypton_gf_mul ( c, a, b ); /* "zx" = Z^2 - aX^2 = Z^2 - X^2 */ - #else - const crypton_gf_s *x = p->x, *t = p->t; - crypton_gf_sqr ( a, p->z ); - crypton_gf_sqr ( b, p->x ); - crypton_gf_add ( c, a, b ); /* "zx" = Z^2 - aX^2 = Z^2 + X^2 */ - #endif - /* Here: c = "zx" in the SAGE code = Z^2 - aX^2 */ - - crypton_gf_mul ( a, p->z, t ); /* "tz" = T*Z */ - crypton_gf_sqr ( b, a ); - crypton_gf_mul ( d, b, c ); /* (TZ)^2 * (Z^2-aX^2) */ - mask_t ok = crypton_gf_isr(b, d); - (void)ok; assert(ok | crypton_gf_eq(d,ZERO)); - crypton_gf_mul ( d, b, a ); /* "osx" = 1 / sqrt(z^2-ax^2) */ - crypton_gf_mul ( a, b, c ); - crypton_gf_mul ( b, a, d ); /* 1/tz */ - - mask_t rotate; - #if (COFACTOR == 8) - gf e; - crypton_gf_sqr(e, p->z); - crypton_gf_mul(a, e, b); /* z^2 / tz = z/t = 1/xy */ - rotate = crypton_gf_hibit(a) ^ toggle_rotation; - /* Curve25519: cond select between zx * 1/tz or sqrt(1-d); y=-x */ - crypton_gf_mul ( a, b, c ); - crypton_gf_cond_sel ( a, a, SQRT_ONE_MINUS_D, rotate ); - crypton_gf_cond_sel ( e, p->y, x, rotate ); - #else - const crypton_gf_s *e = x; - (void)toggle_rotation; - rotate = 0; - #endif - - crypton_gf_mul ( c, a, d ); // new "osx" - crypton_gf_mul ( a, c, p->z ); - crypton_gf_add ( minus_t_over_s, a, a ); // 2 * "osx" * Z - crypton_gf_mul ( d, b, p->z ); - - mask_t tg = toggle_hibit_t_over_s ^~ crypton_gf_hibit(minus_t_over_s); - crypton_gf_cond_neg ( minus_t_over_s, tg ); - crypton_gf_cond_neg ( c, rotate ^ tg ); - crypton_gf_add ( d, d, c ); - crypton_gf_mul ( s, d, e ); /* here "x" = y unless rotate */ - crypton_gf_cond_neg ( s, toggle_hibit_s ^ crypton_gf_hibit(s) ); + gf t1,t2,t3,t4,t5; + crypton_gf_add(t1,p->z,p->y); + crypton_gf_sub(t2,p->z,p->y); + crypton_gf_mul(t3,t1,t2); /* t3 = num */ + crypton_gf_mul(t2,p->x,p->y); /* t2 = den */ + crypton_gf_sqr(t1,t2); + crypton_gf_mul(t4,t1,t3); + crypton_gf_mulw(t1,t4,-1-TWISTED_D); + crypton_gf_isr(t4,t1); /* isqrt(num*(a-d)*den^2) */ + crypton_gf_mul(t1,t2,t4); + crypton_gf_mul(t2,t1,RISTRETTO_FACTOR); /* t2 = "iden" in ristretto.sage */ + crypton_gf_mul(t1,t3,t4); /* t1 = "inum" in ristretto.sage */ + + /* Calculate altxy = iden*inum*i*t^2*(d-a) */ + crypton_gf_mul(t3,t1,t2); + crypton_gf_mul_i(t4,t3); + crypton_gf_mul(t3,t4,p->t); + crypton_gf_mul(t4,t3,p->t); + crypton_gf_mulw(t3,t4,TWISTED_D+1); /* iden*inum*i*t^2*(d-1) */ + mask_t rotate = toggle_rotation ^ crypton_gf_lobit(t3); + + /* Rotate if altxy is negative */ + crypton_gf_cond_swap(t1,t2,rotate); + crypton_gf_mul_i(t4,p->x); + crypton_gf_cond_sel(t4,p->y,t4,rotate); /* t4 = "fac" = ix if rotate, else y */ + + crypton_gf_mul_i(t5,RISTRETTO_FACTOR); /* t5 = imi */ + crypton_gf_mul(t3,t5,t2); /* iden * imi */ + crypton_gf_mul(t2,t5,t1); + crypton_gf_mul(t5,t2,p->t); /* "altx" = iden*imi*t */ + mask_t negx = crypton_gf_lobit(t5) ^ toggle_altx; + + crypton_gf_cond_neg(t1,negx^rotate); + crypton_gf_mul(t2,t1,p->z); + crypton_gf_add(t2,t2,ONE); + crypton_gf_mul(inv_el_sum,t2,t4); + crypton_gf_mul(s,inv_el_sum,t3); + + mask_t negs = crypton_gf_lobit(s); + crypton_gf_cond_neg(s,negs); + + mask_t negz = ~negs ^ toggle_s ^ negx; + crypton_gf_copy(inv_el_m1,p->z); + crypton_gf_cond_neg(inv_el_m1,negz); + crypton_gf_sub(inv_el_m1,inv_el_m1,t4); +#else +#error "Cofactor must be 4 (with no IMAGINE_TWIST) or 8 (with IMAGINE_TWIST)" #endif } void API_NS(point_encode)( unsigned char ser[SER_BYTES], const point_t p ) { - gf s, mtos; - API_NS(deisogenize)(s,mtos,p,0,0,0); - crypton_gf_serialize(ser,s,0); + gf s,ie1,ie2; + API_NS(deisogenize)(s,ie1,ie2,p,0,0,0); + crypton_gf_serialize(ser,s); } crypton_decaf_error_t API_NS(point_decode) ( @@ -238,89 +252,54 @@ crypton_decaf_error_t API_NS(point_decode) ( const unsigned char ser[SER_BYTES], crypton_decaf_bool_t allow_identity ) { - gf s, a, b, c, d, e, f; + gf s, s2, num, tmp; + crypton_gf_s *tmp2=s2, *ynum=p->z, *isr=p->x, *den=p->t; + mask_t succ = crypton_gf_deserialize(s, ser, 0); - mask_t zero = crypton_gf_eq(s, ZERO); - succ &= bool_to_mask(allow_identity) | ~zero; - crypton_gf_sqr ( a, s ); /* s^2 */ + succ &= bool_to_mask(allow_identity) | ~crypton_gf_eq(s, ZERO); + succ &= ~crypton_gf_lobit(s); + + crypton_gf_sqr(s2,s); /* s^2 = -as^2 */ #if IMAGINE_TWIST - crypton_gf_sub ( f, ONE, a ); /* f = 1-as^2 = 1-s^2*/ -#else - crypton_gf_add ( f, ONE, a ); /* f = 1-as^2 = 1+s^2 */ + crypton_gf_sub(s2,ZERO,s2); /* -as^2 */ #endif - succ &= ~ crypton_gf_eq( f, ZERO ); - crypton_gf_sqr ( b, f ); /* (1-as^2)^2 = 1 - 2as^2 + a^2 s^4 */ - crypton_gf_mulw ( c, a, 4*IMAGINE_TWIST-4*EDWARDS_D ); - crypton_gf_add ( c, c, b ); /* t^2 = 1 + (2a-4d) s^2 + s^4 */ - crypton_gf_mul ( d, f, s ); /* s * (1-as^2) for denoms */ - crypton_gf_sqr ( e, d ); /* s^2 * (1-as^2)^2 */ - crypton_gf_mul ( b, c, e ); /* t^2 * s^2 * (1-as^2)^2 */ - - succ &= crypton_gf_isr(e,b) | crypton_gf_eq(b,ZERO); /* e = 1/(t s (1-as^2)) */ - crypton_gf_mul ( b, e, d ); /* 1 / t */ - crypton_gf_mul ( d, e, c ); /* t / (s(1-as^2)) */ - crypton_gf_mul ( e, d, f ); /* t / s */ - mask_t negtos = crypton_gf_hibit(e); - crypton_gf_cond_neg(b, negtos); - crypton_gf_cond_neg(d, negtos); - -#if IMAGINE_TWIST - crypton_gf_add ( p->z, ONE, a); /* Z = 1+as^2 = 1-s^2 */ -#else - crypton_gf_sub ( p->z, ONE, a); /* Z = 1+as^2 = 1-s^2 */ + crypton_gf_sub(den,ONE,s2); /* 1+as^2 */ + crypton_gf_add(ynum,ONE,s2); /* 1-as^2 */ + crypton_gf_mulw(num,s2,-4*TWISTED_D); + crypton_gf_sqr(tmp,den); /* tmp = den^2 */ + crypton_gf_add(num,tmp,num); /* num = den^2 - 4*d*s^2 */ + crypton_gf_mul(tmp2,num,tmp); /* tmp2 = num*den^2 */ + succ &= crypton_gf_isr(isr,tmp2); /* isr = 1/sqrt(num*den^2) */ + crypton_gf_mul(tmp,isr,den); /* isr*den */ + crypton_gf_mul(p->y,tmp,ynum); /* isr*den*(1-as^2) */ + crypton_gf_mul(tmp2,tmp,s); /* s*isr*den */ + crypton_gf_add(tmp2,tmp2,tmp2); /* 2*s*isr*den */ + crypton_gf_mul(tmp,tmp2,isr); /* 2*s*isr^2*den */ + crypton_gf_mul(p->x,tmp,num); /* 2*s*isr^2*den*num */ + crypton_gf_mul(tmp,tmp2,RISTRETTO_FACTOR); /* 2*s*isr*den*magic */ + crypton_gf_cond_neg(p->x,crypton_gf_lobit(tmp)); /* flip x */ + +#if COFACTOR==8 + /* Additionally check y != 0 and x*y*isomagic nonegative */ + succ &= ~crypton_gf_eq(p->y,ZERO); + crypton_gf_mul(tmp,p->x,p->y); + crypton_gf_mul(tmp2,tmp,RISTRETTO_FACTOR); + succ &= ~crypton_gf_lobit(tmp2); #endif -#if COFACTOR == 8 - crypton_gf_mul ( a, p->z, d); /* t(1+s^2) / s(1-s^2) = 2/xy */ - succ &= ~crypton_gf_lobit(a); /* = ~crypton_gf_hibit(a/2), since crypton_gf_hibit(x) = crypton_gf_lobit(2x) */ -#endif - - crypton_gf_mul ( a, f, b ); /* y = (1-s^2) / t */ - crypton_gf_mul ( p->y, p->z, a ); /* Y = yZ */ #if IMAGINE_TWIST - crypton_gf_add ( b, s, s ); - crypton_gf_mul(p->x, b, SQRT_MINUS_ONE); /* Curve25519 */ -#else - crypton_gf_add ( p->x, s, s ); -#endif - crypton_gf_mul ( p->t, p->x, a ); /* T = 2s (1-as^2)/t */ - -#if UNSAFE_CURVE_HAS_POINTS_AT_INFINITY - /* This can't happen for any of the supported configurations. - * - * If it can happen (because s=1), it's because the curve has points - * at infinity, which means that there may be critical security bugs - * elsewhere in the library. In that case, it's better that you hit - * the assertion in point_valid, which will happen in the test suite - * since it tests s=1. - * - * This debugging option is to allow testing of IMAGINE_TWIST = 0 on - * Ed25519, without hitting that assertion. Don't use it in - * production. - */ - succ &= ~crypton_gf_eq(p->z,ZERO); + crypton_gf_copy(tmp,p->x); + crypton_gf_mul_i(p->x,tmp); #endif + + /* Fill in z and t */ + crypton_gf_copy(p->z,ONE); + crypton_gf_mul(p->t,p->x,p->y); - p->y->limb[0] -= zero; assert(API_NS(point_valid)(p) | ~succ); - return crypton_decaf_succeed_if(mask_to_bool(succ)); } -#if IMAGINE_TWIST -#define TWISTED_D (-(EDWARDS_D)) -#else -#define TWISTED_D ((EDWARDS_D)-1) -#endif - -#if TWISTED_D < 0 -#define EFF_D (-(TWISTED_D)) -#define NEG_D 1 -#else -#define EFF_D TWISTED_D -#define NEG_D 0 -#endif - void API_NS(point_sub) ( point_t p, const point_t q, @@ -563,6 +542,7 @@ void API_NS(point_scalarmul) ( const point_t b, const scalar_t scalar ) { + const int WINDOW = CRYPTON_DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, @@ -573,7 +553,7 @@ void API_NS(point_scalarmul) ( API_NS(scalar_halve)(scalar1x,scalar1x); /* Set up a precomputed table with odd multiples of b. */ - pniels_t pn, multiples[NTABLE]; + pniels_t pn, multiples[1<<((int)(CRYPTON_DECAF_WINDOW_BITS)-1)]; // == NTABLE (MSVC compatibility issue) point_t tmp; prepare_fixed_window(multiples, b, NTABLE); @@ -624,12 +604,13 @@ void API_NS(point_double_scalarmul) ( const scalar_t scalarb, const point_t c, const scalar_t scalarc -) { +) { + const int WINDOW = CRYPTON_DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, NTABLE = 1<<(WINDOW-1); - + scalar_t scalar1x, scalar2x; API_NS(scalar_add)(scalar1x, scalarb, point_scalarmul_adjustment); API_NS(scalar_halve)(scalar1x,scalar1x); @@ -637,9 +618,10 @@ void API_NS(point_double_scalarmul) ( API_NS(scalar_halve)(scalar2x,scalar2x); /* Set up a precomputed table with odd multiples of b. */ - pniels_t pn, multiples1[NTABLE], multiples2[NTABLE]; + pniels_t pn, multiples1[1<<((int)(CRYPTON_DECAF_WINDOW_BITS)-1)], multiples2[1<<((int)(CRYPTON_DECAF_WINDOW_BITS)-1)]; + // Array size above equal NTABLE (MSVC compatibility issue) point_t tmp; - prepare_fixed_window(multiples1, b, NTABLE); + prepare_fixed_window(multiples1, b, NTABLE); prepare_fixed_window(multiples2, c, NTABLE); /* Initialize. */ @@ -701,11 +683,13 @@ void API_NS(point_dual_scalarmul) ( const scalar_t scalar1, const scalar_t scalar2 ) { + const int WINDOW = CRYPTON_DECAF_WINDOW_BITS, WINDOW_MASK = (1<> 1, NTABLE = 1<<(WINDOW-1); - + + scalar_t scalar1x, scalar2x; API_NS(scalar_add)(scalar1x, scalar1, point_scalarmul_adjustment); API_NS(scalar_halve)(scalar1x,scalar1x); @@ -713,7 +697,9 @@ void API_NS(point_dual_scalarmul) ( API_NS(scalar_halve)(scalar2x,scalar2x); /* Set up a precomputed table with odd multiples of b. */ - point_t multiples1[NTABLE], multiples2[NTABLE], working, tmp; + point_t multiples1[1<<((int)(CRYPTON_DECAF_WINDOW_BITS)-1)], multiples2[1<<((int)(CRYPTON_DECAF_WINDOW_BITS)-1)], working, tmp; + // Array sizes above equal NTABLE (MSVC compatibility issue) + pniels_t pn; API_NS(point_copy)(working, b); @@ -801,7 +787,7 @@ crypton_decaf_bool_t API_NS(point_eq) ( const point_t p, const point_t q ) { crypton_gf_mul ( b, q->y, p->x ); mask_t succ = crypton_gf_eq(a,b); - #if (COFACTOR == 8) && IMAGINE_TWIST + #if (COFACTOR == 8) crypton_gf_mul ( a, p->y, q->y ); crypton_gf_mul ( b, q->x, p->x ); #if !(IMAGINE_TWIST) @@ -936,11 +922,11 @@ void API_NS(precompute) ( const unsigned int n = COMBS_N, t = COMBS_T, s = COMBS_S; assert(n*t*s >= SCALAR_BITS); - point_t working, start, doubles[t-1]; + point_t working, start, doubles[COMBS_T-1]; API_NS(point_copy)(working, base); pniels_t pn_tmp; - gf zs[n<<(t-1)], zis[n<<(t-1)]; + gf zs[(unsigned int)(COMBS_N)<<(unsigned int)(COMBS_T-1)], zis[(unsigned int)(COMBS_N)<<(unsigned int)(COMBS_T-1)]; unsigned int i,j,k; @@ -1078,7 +1064,7 @@ crypton_decaf_error_t API_NS(direct_scalarmul) ( return succ; } -void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( +void API_NS(point_mul_by_ratio_and_encode_like_eddsa) ( uint8_t enc[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const point_t p ) { @@ -1116,15 +1102,20 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( crypton_gf_mul ( y, u, t ); // (x^2+y^2)(2z^2-y^2+x^2) crypton_gf_mul ( u, z, t ); crypton_gf_copy( z, u ); - crypton_gf_mul ( u, x, SQRT_ONE_MINUS_D ); + crypton_gf_mul ( u, x, RISTRETTO_FACTOR ); +#if IMAGINE_TWIST + crypton_gf_mul_i( x, u ); +#else +#error "... probably wrong" crypton_gf_copy( x, u ); +#endif crypton_decaf_bzero(u,sizeof(u)); } #elif IMAGINE_TWIST { API_NS(point_double)(q,q); API_NS(point_double)(q,q); - crypton_gf_mul_qnr(x, q->x); + crypton_gf_mul_i(x, q->x); crypton_gf_copy(y, q->y); crypton_gf_copy(z, q->z); } @@ -1137,7 +1128,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( crypton_gf_add( u, x, t ); crypton_gf_add( z, q->y, q->x ); crypton_gf_sqr ( y, z); - crypton_gf_sub ( y, u, y ); + crypton_gf_sub ( y, y, u ); crypton_gf_sub ( z, t, x ); crypton_gf_sqr ( x, q->z ); crypton_gf_add ( t, x, x); @@ -1155,7 +1146,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( /* Encode */ enc[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES-1] = 0; - crypton_gf_serialize(enc, x, 1); + crypton_gf_serialize(enc, x); enc[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES-1] |= 0x80 & crypton_gf_lobit(t); crypton_decaf_bzero(x,sizeof(x)); @@ -1166,7 +1157,7 @@ void API_NS(point_mul_by_cofactor_and_encode_like_eddsa) ( } -crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( +crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_mul_by_ratio) ( point_t p, const uint8_t enc[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES] ) { @@ -1176,7 +1167,7 @@ crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( mask_t low = ~word_is_zero(enc2[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES-1] & 0x80); enc2[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES-1] &= ~0x80; - mask_t succ = crypton_gf_deserialize(p->y, enc2, 1); + mask_t succ = crypton_gf_deserialize(p->y, enc2, 0); #if 0 == 0 succ &= word_is_zero(enc2[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES-1]); #endif @@ -1196,7 +1187,7 @@ crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( succ &= crypton_gf_isr(p->t,p->x); /* 1/sqrt(num * denom) */ crypton_gf_mul(p->x,p->t,p->z); /* sqrt(num / denom) */ - crypton_gf_cond_neg(p->x,~crypton_gf_lobit(p->x)^low); + crypton_gf_cond_neg(p->x,crypton_gf_lobit(p->x)^low); crypton_gf_copy(p->z,ONE); #if EDDSA_USE_SIGMA_ISOGENY @@ -1221,8 +1212,9 @@ crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( crypton_gf_sub ( p->t, a, c ); // y^2 - x^2 crypton_gf_sqr ( p->x, p->z ); crypton_gf_add ( p->z, p->x, p->x ); - crypton_gf_sub ( a, p->z, p->t ); // 2z^2 - y^2 + x^2 - crypton_gf_mul ( c, a, SQRT_ONE_MINUS_D ); + crypton_gf_sub ( c, p->z, p->t ); // 2z^2 - y^2 + x^2 + crypton_gf_div_i ( a, c ); + crypton_gf_mul ( c, a, RISTRETTO_FACTOR ); crypton_gf_mul ( p->x, b, p->t); // (2xy)(y^2-x^2) crypton_gf_mul ( p->z, p->t, c ); // (y^2-x^2)sd(2z^2 - y^2 + x^2) crypton_gf_mul ( p->y, d, c ); // (y^2+x^2)sd(2z^2 - y^2 + x^2) @@ -1265,6 +1257,7 @@ crypton_decaf_error_t API_NS(point_decode_like_eddsa_and_ignore_cofactor) ( crypton_decaf_bzero(enc2,sizeof(enc2)); assert(API_NS(point_valid)(p) || ~succ); + return crypton_decaf_succeed_if(mask_to_bool(succ)); } @@ -1274,7 +1267,7 @@ crypton_decaf_error_t crypton_decaf_x448 ( const uint8_t scalar[X_PRIVATE_BYTES] ) { gf x1, x2, z2, x3, z3, t1, t2; - ignore_result(crypton_gf_deserialize(x1,base,1)); + ignore_result(crypton_gf_deserialize(x1,base,0)); crypton_gf_copy(x2,ONE); crypton_gf_copy(z2,ZERO); crypton_gf_copy(x3,x1); @@ -1290,8 +1283,7 @@ crypton_decaf_error_t crypton_decaf_x448 ( if (t/8==0) sb &= -(uint8_t)COFACTOR; else if (t == X_PRIVATE_BITS-1) sb = -1; - mask_t k_t = (sb>>(t%8)) & 1; - k_t = -k_t; /* set to all 0s or all 1s */ + mask_t k_t = bit_to_mask((sb>>(t%8)) & 1); swap ^= k_t; crypton_gf_cond_swap(x2,x3,swap); @@ -1325,7 +1317,7 @@ crypton_decaf_error_t crypton_decaf_x448 ( crypton_gf_cond_swap(z2,z3,swap); crypton_gf_invert(z2,z2,0); crypton_gf_mul(x1,x2,z2); - crypton_gf_serialize(out,x1,1); + crypton_gf_serialize(out,x1); mask_t nz = ~crypton_gf_eq(x1,ZERO); crypton_decaf_bzero(x1,sizeof(x1)); @@ -1345,15 +1337,8 @@ void crypton_decaf_ed448_convert_public_key_to_x448 ( const uint8_t ed[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES] ) { gf y; - { - uint8_t enc2[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES]; - memcpy(enc2,ed,sizeof(enc2)); - - /* retrieve y from the ed compressed point */ - enc2[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES-1] &= ~0x80; - ignore_result(crypton_gf_deserialize(y, enc2, 0)); - crypton_decaf_bzero(enc2,sizeof(enc2)); - } + const uint8_t mask = (uint8_t)(0xFE<<(7)); + ignore_result(crypton_gf_deserialize(y, ed, mask)); { gf n,d; @@ -1364,7 +1349,7 @@ void crypton_decaf_ed448_convert_public_key_to_x448 ( crypton_gf_sub(d, ONE, y); /* d = 1-y */ crypton_gf_invert(d, d, 0); /* d = 1/(1-y) */ crypton_gf_mul(y, n, d); /* u = (y+1)/(1-y) */ - crypton_gf_serialize(x,y,1); + crypton_gf_serialize(x,y); #else /* EDDSA_USE_SIGMA_ISOGENY */ /* u = y^2 * (1-dy^2) / (1-y^2) */ crypton_gf_sqr(n,y); /* y^2*/ @@ -1374,7 +1359,7 @@ void crypton_decaf_ed448_convert_public_key_to_x448 ( crypton_gf_mulw(d,n,EDWARDS_D); /* dy^2*/ crypton_gf_sub(d, ONE, d); /* 1-dy^2*/ crypton_gf_mul(n, y, d); /* y^2 * (1-dy^2) / (1-y^2) */ - crypton_gf_serialize(x,n,1); + crypton_gf_serialize(x,n); #endif /* EDDSA_USE_SIGMA_ISOGENY */ crypton_decaf_bzero(y,sizeof(y)); @@ -1390,6 +1375,26 @@ void crypton_decaf_x448_generate_key ( crypton_decaf_x448_derive_public_key(out,scalar); } +void API_NS(point_mul_by_ratio_and_encode_like_x448) ( + uint8_t out[X_PUBLIC_BYTES], + const point_t p +) { + point_t q; +#if COFACTOR == 8 + point_double_internal(q,p,1); +#else + API_NS(point_copy)(q,p); +#endif + crypton_gf_invert(q->t,q->x,0); /* 1/x */ + crypton_gf_mul(q->z,q->t,q->y); /* y/x */ + crypton_gf_sqr(q->y,q->z); /* (y/x)^2 */ +#if IMAGINE_TWIST + crypton_gf_sub(q->y,ZERO,q->y); +#endif + crypton_gf_serialize(out,q->y); + API_NS(point_destroy(q)); +} + void crypton_decaf_x448_derive_public_key ( uint8_t out[X_PUBLIC_BYTES], const uint8_t scalar[X_PRIVATE_BYTES] @@ -1399,45 +1404,19 @@ void crypton_decaf_x448_derive_public_key ( memcpy(scalar2,scalar,sizeof(scalar2)); scalar2[0] &= -(uint8_t)COFACTOR; - scalar2[X_PRIVATE_BYTES-1] &= ~(-1u<<((X_PRIVATE_BITS+7)%8)); + scalar2[X_PRIVATE_BYTES-1] &= ~(0xFF<<((X_PRIVATE_BITS+7)%8)); scalar2[X_PRIVATE_BYTES-1] |= 1<<((X_PRIVATE_BITS+7)%8); scalar_t the_scalar; API_NS(scalar_decode_long)(the_scalar,scalar2,sizeof(scalar2)); - /* We're gonna isogenize by 2, so divide by 2. - * - * Why by 2, even though it's a 4-isogeny? - * - * The isogeny map looks like - * Montgomery <-2-> Jacobi <-2-> Edwards - * - * Since the Jacobi base point is the PREimage of the iso to - * the Montgomery curve, and we're going - * Jacobi -> Edwards -> Jacobi -> Montgomery, - * we pick up only a factor of 2 over Jacobi -> Montgomery. - */ - API_NS(scalar_halve)(the_scalar,the_scalar); + /* Compensate for the encoding ratio */ + for (unsigned i=1; it,p->x,0); /* 1/x */ - crypton_gf_mul(p->z,p->t,p->y); /* y/x */ - crypton_gf_sqr(p->y,p->z); /* (y/x)^2 */ -#if IMAGINE_TWIST - crypton_gf_sub(p->y,ZERO,p->y); -#endif - crypton_gf_serialize(out,p->y,1); - - crypton_decaf_bzero(scalar2,sizeof(scalar2)); - API_NS(scalar_destroy)(the_scalar); + API_NS(point_mul_by_ratio_and_encode_like_x448)(out,p); API_NS(point_destroy)(p); } @@ -1566,13 +1545,13 @@ void API_NS(base_double_scalarmul_non_secret) ( ) { const int table_bits_var = CRYPTON_DECAF_WNAF_VAR_TABLE_BITS, table_bits_pre = CRYPTON_DECAF_WNAF_FIXED_TABLE_BITS; - struct smvt_control control_var[SCALAR_BITS/(table_bits_var+1)+3]; - struct smvt_control control_pre[SCALAR_BITS/(table_bits_pre+1)+3]; + struct smvt_control control_var[SCALAR_BITS/((int)(CRYPTON_DECAF_WNAF_VAR_TABLE_BITS)+1)+3]; + struct smvt_control control_pre[SCALAR_BITS/((int)(CRYPTON_DECAF_WNAF_FIXED_TABLE_BITS)+1)+3]; int ncb_pre = recode_wnaf(control_pre, scalar1, table_bits_pre); int ncb_var = recode_wnaf(control_var, scalar2, table_bits_var); - pniels_t precmp_var[1<privkey, privkey, CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES); + crypton_decaf_ed448_derive_public_key(keypair->pubkey, keypair->privkey); +} + +void crypton_decaf_ed448_keypair_extract_public_key ( + uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair +) { + memcpy(pubkey,keypair->pubkey,CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES); +} + +void crypton_decaf_ed448_keypair_extract_private_key ( + uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair +) { + memcpy(privkey,keypair->privkey,CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES); +} + +void crypton_decaf_ed448_keypair_destroy ( + crypton_decaf_eddsa_448_keypair_t keypair +) { + crypton_decaf_bzero(keypair, sizeof(crypton_decaf_eddsa_448_keypair_t)); +} + +void crypton_decaf_ed448_keypair_sign ( + uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair, + const uint8_t *message, + size_t message_len, + uint8_t prehashed, + const uint8_t *context, + uint8_t context_len +) { + crypton_decaf_ed448_sign_internal(signature,keypair->privkey,keypair->pubkey,message, + message_len,prehashed,context,context_len); +} + +void crypton_decaf_ed448_keypair_sign_prehash ( + uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair, + const crypton_decaf_ed448_prehash_ctx_t hash, + const uint8_t *context, + uint8_t context_len +) { + uint8_t hash_output[EDDSA_PREHASH_BYTES]; { crypton_decaf_ed448_prehash_ctx_t hash_too; memcpy(hash_too,hash,sizeof(hash_too)); @@ -245,7 +325,8 @@ void crypton_decaf_ed448_sign_prehash ( hash_destroy(hash_too); } - crypton_decaf_ed448_sign(signature,privkey,pubkey,hash_output,sizeof(hash_output),1,context,context_len); + crypton_decaf_ed448_sign_internal(signature,keypair->privkey,keypair->pubkey,hash_output, + sizeof(hash_output),1,context,context_len); crypton_decaf_bzero(hash_output,sizeof(hash_output)); } @@ -259,10 +340,10 @@ crypton_decaf_error_t crypton_decaf_ed448_verify ( uint8_t context_len ) { API_NS(point_t) pk_point, r_point; - crypton_decaf_error_t error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(pk_point,pubkey); + crypton_decaf_error_t error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(pk_point,pubkey); if (CRYPTON_DECAF_SUCCESS != error) { return error; } - error = API_NS(point_decode_like_eddsa_and_ignore_cofactor)(r_point,signature); + error = API_NS(point_decode_like_eddsa_and_mul_by_ratio)(r_point,signature); if (CRYPTON_DECAF_SUCCESS != error) { return error; } API_NS(scalar_t) challenge_scalar; @@ -282,15 +363,26 @@ crypton_decaf_error_t crypton_decaf_ed448_verify ( API_NS(scalar_sub)(challenge_scalar, API_NS(scalar_zero), challenge_scalar); API_NS(scalar_t) response_scalar; - API_NS(scalar_decode_long)( + error = API_NS(scalar_decode)( response_scalar, - &signature[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], - CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES + &signature[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES] ); -#if EDDSA_BASE_POINT_RATIO == 2 - API_NS(scalar_add)(response_scalar,response_scalar,response_scalar); + if (CRYPTON_DECAF_SUCCESS != error) { return error; } + +#if CRYPTON_DECAF_448_SCALAR_BYTES < CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES + for (unsigned i = CRYPTON_DECAF_448_SCALAR_BYTES; + i < CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES; + i++) { + if (signature[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES+i] != 0x00) { + return CRYPTON_DECAF_FAILURE; + } + } #endif + for (unsigned c=1; climb[i]; - out->limb[i] = chain; + out->limb[i] = (crypton_decaf_word_t)chain; chain >>= WBITS; } - crypton_decaf_word_t borrow = chain+extra; /* = 0 or -1 */ + crypton_decaf_word_t borrow = (crypton_decaf_word_t)chain+extra; /* = 0 or -1 */ chain = 0; for (i=0; ilimb[i]) + (p->limb[i] & borrow); - out->limb[i] = chain; + out->limb[i] = (crypton_decaf_word_t)chain; chain >>= WBITS; } } @@ -77,22 +77,22 @@ static CRYPTON_DECAF_NOINLINE void sc_montmul ( crypton_decaf_dword_t chain = 0; for (j=0; j>= WBITS; } - accum[j] = chain; + accum[j] = (crypton_decaf_word_t)chain; mand = accum[0] * MONTGOMERY_FACTOR; chain = 0; mier = sc_p->limb; for (j=0; j>= WBITS; } chain += accum[j]; chain += hi_carry; - accum[j-1] = chain; + accum[j-1] = (crypton_decaf_word_t)chain; hi_carry = chain >> WBITS; } @@ -121,7 +121,7 @@ crypton_decaf_error_t API_NS(scalar_invert) ( * Sliding window is fine here because the modulus isn't secret. */ const int SCALAR_WINDOW_BITS = 3; - scalar_t precmp[1<limb[i]) + b->limb[i]; - out->limb[i] = chain; + out->limb[i] = (crypton_decaf_word_t)chain; chain >>= WBITS; } - sc_subx(out, out->limb, sc_p, sc_p, chain); + sc_subx(out, out->limb, sc_p, sc_p, (crypton_decaf_word_t)chain); } void @@ -204,7 +204,7 @@ API_NS(scalar_set_unsigned) ( memset(out,0,sizeof(scalar_t)); unsigned int i = 0; for (; ilimb[i] = w; + out->limb[i] = (crypton_decaf_word_t)w; #if CRYPTON_DECAF_WORD_BITS < 64 w >>= 8*sizeof(crypton_decaf_word_t); #endif @@ -227,7 +227,7 @@ API_NS(scalar_eq) ( static CRYPTON_DECAF_INLINE void scalar_decode_short ( scalar_t s, const unsigned char *ser, - unsigned int nbytes + size_t nbytes ) { unsigned int i,j,k=0; for (i=0; ilimb[0] & 1); + crypton_decaf_word_t mask = bit_to_mask((a->limb[0]) & 1); crypton_decaf_dword_t chain = 0; unsigned int i; for (i=0; ilimb[i]) + (sc_p->limb[i] & mask); - out->limb[i] = chain; + out->limb[i] = (crypton_decaf_word_t)chain; chain >>= CRYPTON_DECAF_WORD_BITS; } for (i=0; ilimb[i] = out->limb[i]>>1 | out->limb[i+1]<<(WBITS-1); } - out->limb[i] = out->limb[i]>>1 | chain<<(WBITS-1); + out->limb[i] = out->limb[i]>>1 | (crypton_decaf_word_t)(chain<<(WBITS-1)); } diff --git a/cbits/decaf/include/arch_32/arch_intrinsics.h b/cbits/decaf/include/arch_32/arch_intrinsics.h index f3908a25..46be539c 100644 --- a/cbits/decaf/include/arch_32/arch_intrinsics.h +++ b/cbits/decaf/include/arch_32/arch_intrinsics.h @@ -7,6 +7,11 @@ #define ARCH_WORD_BITS 32 +#if defined _MSC_VER +#define __attribute(x) +#define __inline__ __inline +#endif // MSVC + static __inline__ __attribute((always_inline,unused)) uint32_t word_is_zero(uint32_t a) { /* let's hope the compiler isn't clever enough to optimize this. */ diff --git a/cbits/decaf/include/decaf/common.h b/cbits/decaf/include/decaf/common.h index 43481ebb..3e6d521b 100644 --- a/cbits/decaf/include/decaf/common.h +++ b/cbits/decaf/include/decaf/common.h @@ -13,7 +13,9 @@ #define __CRYPTON_DECAF_COMMON_H__ 1 #include +#if defined (__GNUC__) // File only exists for GNU compilers #include +#endif #ifdef __cplusplus extern "C" { @@ -21,14 +23,35 @@ extern "C" { /* Goldilocks' build flags default to hidden and stripping executables. */ /** @cond internal */ -#if defined(DOXYGEN) && !defined(__attribute__) -#define __attribute__((x)) +#if DOXYGEN || defined(__attribute__) +#define __attribute__(x) +#define NOINLINE #endif + +/* Aliasing MSVC preprocessing to GNU preprocessing */ +#if defined _MSC_VER +# define __attribute__(x) // Turn off attribute code +# define __attribute(x) +# define __restrict__ __restrict // Use MSVC restrict code +# if defined _DLL +# define CRYPTON_DECAF_API_VIS __declspec(dllexport) // MSVC for visibility +# else +# define CRYPTON_DECAF_API_VIS __declspec(dllimport) +# endif + +//# define CRYPTON_DECAF_NOINLINE __declspec(noinline) // MSVC for noinline +//# define CRYPTON_DECAF_INLINE __forceinline // MSVC for always inline +//# define CRYPTON_DECAF_WARN_UNUSED _Check_return_ +#else // MSVC #define CRYPTON_DECAF_API_VIS __attribute__((visibility("default"))) +#define CRYPTON_DECAF_API_IMPORT +#endif + +// The following are disabled for MSVC #define CRYPTON_DECAF_NOINLINE __attribute__((noinline)) -#define CRYPTON_DECAF_WARN_UNUSED __attribute__((warn_unused_result)) -#define CRYPTON_DECAF_NONNULL __attribute__((nonnull)) #define CRYPTON_DECAF_INLINE inline __attribute__((always_inline,unused)) +#define CRYPTON_DECAF_WARN_UNUSED __attribute__((warn_unused_result)) +#define CRYPTON_DECAF_NONNULL __attribute__((nonnull)) // Cribbed from libnotmuch #if defined (__clang_major__) && __clang_major__ >= 3 \ || defined (__GNUC__) && __GNUC__ >= 5 \ @@ -70,8 +93,25 @@ typedef int64_t crypton_decaf_dsword_t; /**< Signed double-word size for int #error "Only supporting CRYPTON_DECAF_WORD_BITS = 32 or 64 for now" #endif -/** CRYPTON_DECAF_TRUE = -1 so that CRYPTON_DECAF_TRUE & x = x */ -static const crypton_decaf_bool_t CRYPTON_DECAF_TRUE = -(crypton_decaf_bool_t)1; +/* MSCV compiler doesn't like the trick to have -1 assigned to an unsigned int to + * set it to all ones, so do it openly */ +#if CRYPTON_DECAF_WORD_BITS == 64 +/** CRYPTON_DECAF_TRUE = all ones so that CRYPTON_DECAF_TRUE & x = x */ +static const crypton_decaf_bool_t CRYPTON_DECAF_TRUE = (crypton_decaf_bool_t)0xFFFFFFFFFFFFFFFF; +/** CRYPTON_DECAF_WORD_ALL_SET : all ones */ +static const crypton_decaf_word_t CRYPTON_DECAF_WORD_ALL_SET = (crypton_decaf_word_t)0xFFFFFFFFFFFFFFFF; +/** CRYPTON_DECAF_WORD_ALL_UNSET : all zeros */ +static const crypton_decaf_word_t CRYPTON_DECAF_WORD_ALL_UNSET = (crypton_decaf_word_t)0x0; +#elif CRYPTON_DECAF_WORD_BITS == 32 /**< The number of bits in a word */ +/** CRYPTON_DECAF_TRUE = all ones so that CRYPTON_DECAF_TRUE & x = x */ +static const crypton_decaf_bool_t CRYPTON_DECAF_TRUE = (crypton_decaf_bool_t)0xFFFFFFFF; +/** CRYPTON_DECAF_WORD_ALL_SET : all ones */ +static const crypton_decaf_word_t CRYPTON_DECAF_WORD_ALL_SET = (crypton_decaf_word_t)0xFFFFFFFF; +/** CRYPTON_DECAF_WORD_ALL_UNSET : all zeros */ +static const crypton_decaf_word_t CRYPTON_DECAF_WORD_ALL_UNSET = (crypton_decaf_word_t)0x0; +#else +#error "Only supporting CRYPTON_DECAF_WORD_BITS = 32 or 64 for now" +#endif /** CRYPTON_DECAF_FALSE = 0 so that CRYPTON_DECAF_FALSE & x = 0 */ static const crypton_decaf_bool_t CRYPTON_DECAF_FALSE = 0; @@ -92,22 +132,23 @@ crypton_decaf_succeed_if(crypton_decaf_bool_t x) { /** Return CRYPTON_DECAF_TRUE iff x == CRYPTON_DECAF_SUCCESS */ static CRYPTON_DECAF_INLINE crypton_decaf_bool_t crypton_decaf_successful(crypton_decaf_error_t e) { - crypton_decaf_dword_t w = ((crypton_decaf_word_t)e) ^ ((crypton_decaf_word_t)CRYPTON_DECAF_SUCCESS); + crypton_decaf_word_t succ = CRYPTON_DECAF_SUCCESS; + crypton_decaf_dword_t w = ((crypton_decaf_word_t)e) ^ succ; return (w-1)>>CRYPTON_DECAF_WORD_BITS; } /** Overwrite data with zeros. Uses memset_s if available. */ -void crypton_decaf_bzero ( +void CRYPTON_DECAF_API_VIS crypton_decaf_bzero ( void *data, size_t size -) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_API_VIS; +) CRYPTON_DECAF_NONNULL; /** Compare two buffers, returning CRYPTON_DECAF_TRUE if they are equal. */ -crypton_decaf_bool_t crypton_decaf_memeq ( +crypton_decaf_bool_t CRYPTON_DECAF_API_VIS crypton_decaf_memeq ( const void *data1, const void *data2, size_t size -) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_API_VIS; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED; #ifdef __cplusplus } /* extern "C" */ diff --git a/cbits/decaf/include/decaf/ed448.h b/cbits/decaf/include/decaf/ed448.h index 6d08269e..54fb3669 100644 --- a/cbits/decaf/include/decaf/ed448.h +++ b/cbits/decaf/include/decaf/ed448.h @@ -33,14 +33,45 @@ extern "C" { #define CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES (CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES + CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES) /** Does EdDSA support non-contextual signatures? */ +#if defined _MSC_VER /* Different syntax for exposing API */ #define CRYPTON_DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS 0 -/** Prehash context renaming macros. */ +#else +#define CRYPTON_DECAF_EDDSA_448_SUPPORTS_CONTEXTLESS_SIGS 0 + +#endif + +/** Prehash context (raw), because each EdDSA instance has a different prehash. */ #define crypton_decaf_ed448_prehash_ctx_s crypton_decaf_shake256_ctx_s + +/** Prehash context, array[1] form. */ #define crypton_decaf_ed448_prehash_ctx_t crypton_decaf_shake256_ctx_t + +/** Prehash update. */ #define crypton_decaf_ed448_prehash_update crypton_decaf_shake256_update + +/** Prehash destroy. */ #define crypton_decaf_ed448_prehash_destroy crypton_decaf_shake256_destroy +/** EdDSA encoding ratio. */ +#define CRYPTON_DECAF_448_EDDSA_ENCODE_RATIO 4 + +/** EdDSA decoding ratio. */ +#define CRYPTON_DECAF_448_EDDSA_DECODE_RATIO (4 / 4) + +#ifndef CRYPTON_DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED +/** If 1, add deprecation attribute to non-keypair API functions. Now deprecated. */ +#define CRYPTON_DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED 1 +#endif + +/** @cond internal */ +/** @brief Scheduled EdDSA keypair */ +typedef struct crypton_decaf_eddsa_448_keypair_s { + uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES]; + uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES]; +} crypton_decaf_eddsa_448_keypair_s, crypton_decaf_eddsa_448_keypair_t[1]; +/** @endcond */ + /** * @brief EdDSA key generation. This function uses a different (non-Decaf) * encoding. @@ -48,13 +79,59 @@ extern "C" { * @param [out] pubkey The public key. * @param [in] privkey The private key. */ -void crypton_decaf_ed448_derive_public_key ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_derive_public_key ( uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** - * @brief EdDSA signing. + * @brief EdDSA keypair scheduling. This is to add a safer version of the signing algorithm, + * where it is harder to use the wrong pubkey for your private key.. + * + * @param [out] keypair The scheduled keypair. + * @param [in] privkey The private key. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_derive_keypair ( + crypton_decaf_eddsa_448_keypair_t keypair, + const uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES] +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; + +/** + * @brief Extract the public key from an EdDSA keypair. + * + * @param [out] pubkey The public key. + * @param [in] keypair The keypair. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_extract_public_key ( + uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; + +/** + * @brief Extract the private key from an EdDSA keypair. + * + * @param [out] privkey The private key. + * @param [in] keypair The keypair. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_extract_private_key ( + uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; + +/** + * @brief EdDSA keypair destructor. + * @param [in] pubkey The keypair. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_destroy ( + crypton_decaf_eddsa_448_keypair_t keypair +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; + +/** + * @brief EdDSA signing. However, this API is deprecated because it isn't safe: if the wrong + * public key is passed, it would reveal the private key. Instead, this function checks that + * the public key is correct, and otherwise aborts. + * + * @deprecated Use CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_sign instead. * * @param [out] signature The signature. * @param [in] privkey The private key. @@ -70,7 +147,7 @@ void crypton_decaf_ed448_derive_public_key ( * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives * you no seat belt. */ -void crypton_decaf_ed448_sign ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_sign ( uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], const uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES], const uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], @@ -79,10 +156,18 @@ void crypton_decaf_ed448_sign ( uint8_t prehashed, const uint8_t *context, uint8_t context_len -) CRYPTON_DECAF_API_VIS __attribute__((nonnull(1,2,3))) CRYPTON_DECAF_NOINLINE; +) __attribute__((nonnull(1,2,3))) CRYPTON_DECAF_NOINLINE +#if CRYPTON_DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED + CRYPTON_DECAF_DEPRECATED("Passing the pubkey and privkey separately is unsafe, use crypton_decaf_ed448_keypair_sign") +#endif +; /** - * @brief EdDSA signing with prehash. + * @brief EdDSA signing with prehash. However, this API is deprecated because it isn't safe: if the wrong + * public key is passed, it would reveal the private key. Instead, this function checks that + * the public key is correct, and otherwise aborts. + * + * @deprecated Use CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_sign_prehash instead. * * @param [out] signature The signature. * @param [in] privkey The private key. @@ -90,29 +175,66 @@ void crypton_decaf_ed448_sign ( * @param [in] hash The hash of the message. This object will not be modified by the call. * @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. * @param [in] context_len Length of the context. - * - * @warning For Ed25519, it is unsafe to use the same key for both prehashed and non-prehashed - * messages, at least without some very careful protocol-level disambiguation. For Ed448 it is - * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives - * you no seat belt. */ -void crypton_decaf_ed448_sign_prehash ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_sign_prehash ( uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], const uint8_t privkey[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES], const uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const crypton_decaf_ed448_prehash_ctx_t hash, const uint8_t *context, uint8_t context_len -) CRYPTON_DECAF_API_VIS __attribute__((nonnull(1,2,3,4))) CRYPTON_DECAF_NOINLINE; +) __attribute__((nonnull(1,2,3,4))) CRYPTON_DECAF_NOINLINE +#if CRYPTON_DECAF_EDDSA_NON_KEYPAIR_API_IS_DEPRECATED + CRYPTON_DECAF_DEPRECATED("Passing the pubkey and privkey separately is unsafe, use crypton_decaf_ed448_keypair_sign_prehash") +#endif +; + +/** + * @brief EdDSA signing. + * + * @param [out] signature The signature. + * @param [in] keypair The private and public key. + * @param [in] message The message to sign. + * @param [in] message_len The length of the message. + * @param [in] prehashed Nonzero if the message is actually the hash of something you want to sign. + * @param [in] context A "context" for this signature of up to 255 bytes. + * @param [in] context_len Length of the context. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_sign ( + uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair, + const uint8_t *message, + size_t message_len, + uint8_t prehashed, + const uint8_t *context, + uint8_t context_len +) __attribute__((nonnull(1,2,3))) CRYPTON_DECAF_NOINLINE; + +/** + * @brief EdDSA signing with prehash. + * + * @param [out] signature The signature. + * @param [in] keypair The private and public key. + * @param [in] hash The hash of the message. This object will not be modified by the call. + * @param [in] context A "context" for this signature of up to 255 bytes. Must be the same as what was used for the prehash. + * @param [in] context_len Length of the context. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_keypair_sign_prehash ( + uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], + const crypton_decaf_eddsa_448_keypair_t keypair, + const crypton_decaf_ed448_prehash_ctx_t hash, + const uint8_t *context, + uint8_t context_len +) __attribute__((nonnull(1,2,3,4))) CRYPTON_DECAF_NOINLINE; /** * @brief Prehash initialization, with contexts if supported. * * @param [out] hash The hash object to be initialized. */ -void crypton_decaf_ed448_prehash_init ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_prehash_init ( crypton_decaf_ed448_prehash_ctx_t hash -) CRYPTON_DECAF_API_VIS __attribute__((nonnull(1))) CRYPTON_DECAF_NOINLINE; +) __attribute__((nonnull(1))) CRYPTON_DECAF_NOINLINE; /** * @brief EdDSA signature verification. @@ -132,7 +254,7 @@ void crypton_decaf_ed448_prehash_init ( * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives * you no seat belt. */ -crypton_decaf_error_t crypton_decaf_ed448_verify ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_ed448_verify ( const uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], const uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const uint8_t *message, @@ -140,7 +262,7 @@ crypton_decaf_error_t crypton_decaf_ed448_verify ( uint8_t prehashed, const uint8_t *context, uint8_t context_len -) CRYPTON_DECAF_API_VIS __attribute__((nonnull(1,2))) CRYPTON_DECAF_NOINLINE; +) __attribute__((nonnull(1,2))) CRYPTON_DECAF_NOINLINE; /** * @brief EdDSA signature verification. @@ -158,38 +280,56 @@ crypton_decaf_error_t crypton_decaf_ed448_verify ( * safe. The C++ wrapper is designed to make it harder to screw this up, but this C code gives * you no seat belt. */ -crypton_decaf_error_t crypton_decaf_ed448_verify_prehash ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_ed448_verify_prehash ( const uint8_t signature[CRYPTON_DECAF_EDDSA_448_SIGNATURE_BYTES], const uint8_t pubkey[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const crypton_decaf_ed448_prehash_ctx_t hash, const uint8_t *context, uint8_t context_len -) CRYPTON_DECAF_API_VIS __attribute__((nonnull(1,2))) CRYPTON_DECAF_NOINLINE; +) __attribute__((nonnull(1,2))) CRYPTON_DECAF_NOINLINE; /** * @brief EdDSA point encoding. Used internally, exposed externally. - * Multiplies the point by the current cofactor first. + * Multiplies by CRYPTON_DECAF_448_EDDSA_ENCODE_RATIO first. + * + * The multiplication is required because the EdDSA encoding represents + * the cofactor information, but the Decaf encoding ignores it (which + * is the whole point). So if you decode from EdDSA and re-encode to + * EdDSA, the cofactor info must get cleared, because the intermediate + * representation doesn't track it. + * + * The way libdecaf handles this is to multiply by + * CRYPTON_DECAF_448_EDDSA_DECODE_RATIO when decoding, and by + * CRYPTON_DECAF_448_EDDSA_ENCODE_RATIO when encoding. The product of these + * ratios is always exactly the cofactor 4, so the cofactor + * ends up cleared one way or another. But exactly how that shakes + * out depends on the base points specified in RFC 8032. + * + * The upshot is that if you pass the Decaf/Ristretto base point to + * this function, you will get CRYPTON_DECAF_448_EDDSA_ENCODE_RATIO times the + * EdDSA base point. * * @param [out] enc The encoded point. * @param [in] p The point. */ -void crypton_decaf_448_point_mul_by_cofactor_and_encode_like_eddsa ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_mul_by_ratio_and_encode_like_eddsa ( uint8_t enc[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES], const crypton_decaf_448_point_t p -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** - * @brief EdDSA point decoding. Remember that while points on the - * EdDSA curves have cofactor information, Decaf ignores (quotients - * out) all cofactor information. + * @brief EdDSA point decoding. Multiplies by CRYPTON_DECAF_448_EDDSA_DECODE_RATIO, + * and ignores cofactor information. + * + * See notes on crypton_decaf_448_point_mul_by_ratio_and_encode_like_eddsa * * @param [out] enc The encoded point. * @param [in] p The point. */ -crypton_decaf_error_t crypton_decaf_448_point_decode_like_eddsa_and_ignore_cofactor ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_decode_like_eddsa_and_mul_by_ratio ( crypton_decaf_448_point_t p, const uint8_t enc[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief EdDSA to ECDH public key conversion @@ -202,10 +342,10 @@ crypton_decaf_error_t crypton_decaf_448_point_decode_like_eddsa_and_ignore_cofac * @param[out] x The ECDH public key as in RFC7748(point on Montgomery curve) * @param[in] ed The EdDSA public key(point on Edwards curve) */ -void crypton_decaf_ed448_convert_public_key_to_x448 ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_convert_public_key_to_x448 ( uint8_t x[CRYPTON_DECAF_X448_PUBLIC_BYTES], const uint8_t ed[CRYPTON_DECAF_EDDSA_448_PUBLIC_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief EdDSA to ECDH private key conversion @@ -215,10 +355,10 @@ void crypton_decaf_ed448_convert_public_key_to_x448 ( * @param[out] x The ECDH private key as in RFC7748 * @param[in] ed The EdDSA private key */ -void crypton_decaf_ed448_convert_private_key_to_x448 ( +void CRYPTON_DECAF_API_VIS crypton_decaf_ed448_convert_private_key_to_x448 ( uint8_t x[CRYPTON_DECAF_X448_PRIVATE_BYTES], const uint8_t ed[CRYPTON_DECAF_EDDSA_448_PRIVATE_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; #ifdef __cplusplus } /* extern "C" */ diff --git a/cbits/decaf/include/decaf/point_448.h b/cbits/decaf/include/decaf/point_448.h index edb29461..7c599349 100644 --- a/cbits/decaf/include/decaf/point_448.h +++ b/cbits/decaf/include/decaf/point_448.h @@ -52,16 +52,22 @@ typedef struct crypton_gf_448_s { /** Number of bits in the "which" field of an elligator inverse */ #define CRYPTON_DECAF_448_INVERT_ELLIGATOR_WHICH_BITS 3 +/** The cofactor the curve would have, if we hadn't removed it */ +#define CRYPTON_DECAF_448_REMOVED_COFACTOR 4 + +/** X448 encoding ratio. */ +#define CRYPTON_DECAF_X448_ENCODE_RATIO 2 + /** Number of bytes in an x448 public key */ #define CRYPTON_DECAF_X448_PUBLIC_BYTES 56 /** Number of bytes in an x448 private key */ #define CRYPTON_DECAF_X448_PRIVATE_BYTES 56 -/** Twisted Edwards extended homogeneous coordinates */ +/** Representation of a point on the elliptic curve. */ typedef struct crypton_decaf_448_point_s { /** @cond internal */ - crypton_gf_448_t x,y,z,t; + crypton_gf_448_t x,y,z,t; /* Twisted extended homogeneous coordinates */ /** @endcond */ } crypton_decaf_448_point_t[1]; @@ -72,30 +78,51 @@ struct crypton_decaf_448_precomputed_s; typedef struct crypton_decaf_448_precomputed_s crypton_decaf_448_precomputed_s; /** Size and alignment of precomputed point tables. */ -extern const size_t crypton_decaf_448_sizeof_precomputed_s CRYPTON_DECAF_API_VIS, crypton_decaf_448_alignof_precomputed_s CRYPTON_DECAF_API_VIS; +CRYPTON_DECAF_API_VIS extern const size_t crypton_decaf_448_sizeof_precomputed_s, crypton_decaf_448_alignof_precomputed_s; -/** Scalar is stored packed, because we don't need the speed. */ +/** Representation of an element of the scalar field. */ typedef struct crypton_decaf_448_scalar_s { /** @cond internal */ crypton_decaf_word_t limb[CRYPTON_DECAF_448_SCALAR_LIMBS]; /** @endcond */ } crypton_decaf_448_scalar_t[1]; -/** A scalar equal to 1. */ -extern const crypton_decaf_448_scalar_t crypton_decaf_448_scalar_one CRYPTON_DECAF_API_VIS; +#if defined _MSC_VER + +/** The scalar 1. */ +extern const crypton_decaf_448_scalar_t CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_one; + +/** The scalar 0. */ +extern const crypton_decaf_448_scalar_t CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_zero; + +/** The identity (zero) point on the curve. */ +extern const crypton_decaf_448_point_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_identity; + +/** An arbitrarily-chosen base point on the curve. */ +extern const crypton_decaf_448_point_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_base; + +/** Precomputed table of multiples of the base point on the curve. */ +extern const struct CRYPTON_DECAF_API_VIS crypton_decaf_448_precomputed_s *crypton_decaf_448_precomputed_base; + + +#else // _MSC_VER -/** A scalar equal to 0. */ -extern const crypton_decaf_448_scalar_t crypton_decaf_448_scalar_zero CRYPTON_DECAF_API_VIS; +/** The scalar 1. */ +CRYPTON_DECAF_API_VIS extern const crypton_decaf_448_scalar_t crypton_decaf_448_scalar_one; -/** The identity point on the curve. */ -extern const crypton_decaf_448_point_t crypton_decaf_448_point_identity CRYPTON_DECAF_API_VIS; +/** The scalar 0. */ +CRYPTON_DECAF_API_VIS extern const crypton_decaf_448_scalar_t crypton_decaf_448_scalar_zero; -/** An arbitrarily chosen base point on the curve. */ -extern const crypton_decaf_448_point_t crypton_decaf_448_point_base CRYPTON_DECAF_API_VIS; +/** The identity (zero) point on the curve. */ +CRYPTON_DECAF_API_VIS extern const crypton_decaf_448_point_t crypton_decaf_448_point_identity; -/** Precomputed table for the base point on the curve. */ -extern const struct crypton_decaf_448_precomputed_s *crypton_decaf_448_precomputed_base CRYPTON_DECAF_API_VIS; +/** An arbitrarily-chosen base point on the curve. */ +CRYPTON_DECAF_API_VIS extern const crypton_decaf_448_point_t crypton_decaf_448_point_base; +/** Precomputed table of multiples of the base point on the curve. */ +CRYPTON_DECAF_API_VIS extern const struct crypton_decaf_448_precomputed_s *crypton_decaf_448_precomputed_base; + +#endif // _MSC_VER /** * @brief Read a scalar from wire format or from bytes. * @@ -106,10 +133,10 @@ extern const struct crypton_decaf_448_precomputed_s *crypton_decaf_448_precomput * @retval CRYPTON_DECAF_FAILURE The scalar was greater than the modulus, * and has been reduced modulo that modulus. */ -crypton_decaf_error_t crypton_decaf_448_scalar_decode ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_decode ( crypton_decaf_448_scalar_t out, const unsigned char ser[CRYPTON_DECAF_448_SCALAR_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Read a scalar from wire format or from bytes. Reduces mod @@ -119,11 +146,11 @@ crypton_decaf_error_t crypton_decaf_448_scalar_decode ( * @param [in] ser_len Length of serialized form. * @param [out] out Deserialized form. */ -void crypton_decaf_448_scalar_decode_long ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_decode_long ( crypton_decaf_448_scalar_t out, const unsigned char *ser, size_t ser_len -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Serialize a scalar to wire format. @@ -131,10 +158,10 @@ void crypton_decaf_448_scalar_decode_long ( * @param [out] ser Serialized form of a scalar. * @param [in] s Deserialized scalar. */ -void crypton_decaf_448_scalar_encode ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_encode ( unsigned char ser[CRYPTON_DECAF_448_SCALAR_BYTES], const crypton_decaf_448_scalar_t s -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_NOINLINE; /** * @brief Add two scalars. The scalars may use the same memory. @@ -142,11 +169,11 @@ void crypton_decaf_448_scalar_encode ( * @param [in] b Another scalar. * @param [out] out a+b. */ -void crypton_decaf_448_scalar_add ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_add ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a, const crypton_decaf_448_scalar_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Compare two scalars. @@ -155,10 +182,10 @@ void crypton_decaf_448_scalar_add ( * @retval CRYPTON_DECAF_TRUE The scalars are equal. * @retval CRYPTON_DECAF_FALSE The scalars are not equal. */ -crypton_decaf_bool_t crypton_decaf_448_scalar_eq ( +crypton_decaf_bool_t CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_eq ( const crypton_decaf_448_scalar_t a, const crypton_decaf_448_scalar_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Subtract two scalars. The scalars may use the same memory. @@ -166,11 +193,11 @@ crypton_decaf_bool_t crypton_decaf_448_scalar_eq ( * @param [in] b Another scalar. * @param [out] out a-b. */ -void crypton_decaf_448_scalar_sub ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_sub ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a, const crypton_decaf_448_scalar_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Multiply two scalars. The scalars may use the same memory. @@ -178,21 +205,21 @@ void crypton_decaf_448_scalar_sub ( * @param [in] b Another scalar. * @param [out] out a*b. */ -void crypton_decaf_448_scalar_mul ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_mul ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a, const crypton_decaf_448_scalar_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Halve a scalar. The scalars may use the same memory. * @param [in] a A scalar. * @param [out] out a/2. */ -void crypton_decaf_448_scalar_halve ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_halve ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Invert a scalar. When passed zero, return 0. The input and output may alias. @@ -200,10 +227,10 @@ void crypton_decaf_448_scalar_halve ( * @param [out] out 1/a. * @return CRYPTON_DECAF_SUCCESS The input is nonzero. */ -crypton_decaf_error_t crypton_decaf_448_scalar_invert ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_invert ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Copy a scalar. The scalars may use the same memory, in which @@ -223,10 +250,10 @@ static inline void CRYPTON_DECAF_NONNULL crypton_decaf_448_scalar_copy ( * @param [in] a An integer. * @param [out] out Will become equal to a. */ -void crypton_decaf_448_scalar_set_unsigned ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_set_unsigned ( crypton_decaf_448_scalar_t out, uint64_t a -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL; +) CRYPTON_DECAF_NONNULL; /** * @brief Encode a point as a sequence of bytes. @@ -234,10 +261,10 @@ void crypton_decaf_448_scalar_set_unsigned ( * @param [out] ser The byte representation of the point. * @param [in] pt The point to encode. */ -void crypton_decaf_448_point_encode ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_encode ( uint8_t ser[CRYPTON_DECAF_448_SER_BYTES], const crypton_decaf_448_point_t pt -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Decode a point from a sequence of bytes. @@ -253,11 +280,11 @@ void crypton_decaf_448_point_encode ( * @retval CRYPTON_DECAF_FAILURE The decoding didn't succeed, because * ser does not represent a point. */ -crypton_decaf_error_t crypton_decaf_448_point_decode ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_decode ( crypton_decaf_448_point_t pt, const uint8_t ser[CRYPTON_DECAF_448_SER_BYTES], crypton_decaf_bool_t allow_identity -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Copy a point. The input and output may alias, @@ -282,10 +309,10 @@ static inline void CRYPTON_DECAF_NONNULL crypton_decaf_448_point_copy ( * @retval CRYPTON_DECAF_TRUE The points are equal. * @retval CRYPTON_DECAF_FALSE The points are not equal. */ -crypton_decaf_bool_t crypton_decaf_448_point_eq ( +crypton_decaf_bool_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_eq ( const crypton_decaf_448_point_t a, const crypton_decaf_448_point_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Add two points to produce a third point. The @@ -296,11 +323,11 @@ crypton_decaf_bool_t crypton_decaf_448_point_eq ( * @param [in] a An addend. * @param [in] b An addend. */ -void crypton_decaf_448_point_add ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_add ( crypton_decaf_448_point_t sum, const crypton_decaf_448_point_t a, const crypton_decaf_448_point_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL; +) CRYPTON_DECAF_NONNULL; /** * @brief Double a point. Equivalent to @@ -309,10 +336,10 @@ void crypton_decaf_448_point_add ( * @param [out] two_a The sum a+a. * @param [in] a A point. */ -void crypton_decaf_448_point_double ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_double ( crypton_decaf_448_point_t two_a, const crypton_decaf_448_point_t a -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL; +) CRYPTON_DECAF_NONNULL; /** * @brief Subtract two points to produce a third point. The @@ -323,11 +350,11 @@ void crypton_decaf_448_point_double ( * @param [in] a The minuend. * @param [in] b The subtrahend. */ -void crypton_decaf_448_point_sub ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_sub ( crypton_decaf_448_point_t diff, const crypton_decaf_448_point_t a, const crypton_decaf_448_point_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL; +) CRYPTON_DECAF_NONNULL; /** * @brief Negate a point to produce another point. The input @@ -336,10 +363,10 @@ void crypton_decaf_448_point_sub ( * @param [out] nega The negated input point * @param [in] a The input point. */ -void crypton_decaf_448_point_negate ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_negate ( crypton_decaf_448_point_t nega, const crypton_decaf_448_point_t a -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL; +) CRYPTON_DECAF_NONNULL; /** * @brief Multiply a base point by a scalar: scaled = scalar*base. @@ -348,11 +375,11 @@ void crypton_decaf_448_point_negate ( * @param [in] base The point to be scaled. * @param [in] scalar The scalar to multiply by. */ -void crypton_decaf_448_point_scalarmul ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_scalarmul ( crypton_decaf_448_point_t scaled, const crypton_decaf_448_point_t base, const crypton_decaf_448_scalar_t scalar -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Multiply a base point by a scalar: scaled = scalar*base. @@ -371,34 +398,64 @@ void crypton_decaf_448_point_scalarmul ( * @retval CRYPTON_DECAF_FAILURE The scalarmul didn't succeed, because * base does not represent a point. */ -crypton_decaf_error_t crypton_decaf_448_direct_scalarmul ( +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_direct_scalarmul ( uint8_t scaled[CRYPTON_DECAF_448_SER_BYTES], const uint8_t base[CRYPTON_DECAF_448_SER_BYTES], const crypton_decaf_448_scalar_t scalar, crypton_decaf_bool_t allow_identity, crypton_decaf_bool_t short_circuit -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NOINLINE; /** - * @brief RFC 7748 Diffie-Hellman scalarmul. This function uses a different - * (non-Decaf) encoding. + * @brief RFC 7748 Diffie-Hellman scalarmul, used to compute shared secrets. + * This function uses a different (non-Decaf) encoding. * - * @param [out] scaled The scaled point base*scalar - * @param [in] base The point to be scaled. - * @param [in] scalar The scalar to multiply by. + * @param [out] shared The shared secret base*scalar + * @param [in] base The other party's public key, used as the base of the scalarmul. + * @param [in] scalar The private scalar to multiply by. * * @retval CRYPTON_DECAF_SUCCESS The scalarmul succeeded. * @retval CRYPTON_DECAF_FAILURE The scalarmul didn't succeed, because the base * point is in a small subgroup. */ -crypton_decaf_error_t crypton_decaf_x448 ( - uint8_t out[CRYPTON_DECAF_X448_PUBLIC_BYTES], +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_x448 ( + uint8_t shared[CRYPTON_DECAF_X448_PUBLIC_BYTES], const uint8_t base[CRYPTON_DECAF_X448_PUBLIC_BYTES], const uint8_t scalar[CRYPTON_DECAF_X448_PRIVATE_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NOINLINE; + +/** + * @brief Multiply a point by CRYPTON_DECAF_X448_ENCODE_RATIO, + * then encode it like RFC 7748. + * + * This function is mainly used internally, but is exported in case + * it will be useful. + * + * The ratio is necessary because the internal representation doesn't + * track the cofactor information, so on output we must clear the cofactor. + * This would multiply by the cofactor, but in fact internally libdecaf's + * points are always even, so it multiplies by half the cofactor instead. + * + * As it happens, this aligns with the base point definitions; that is, + * if you pass the Decaf/Ristretto base point to this function, the result + * will be CRYPTON_DECAF_X448_ENCODE_RATIO times the X448 + * base point. + * + * @param [out] out The scaled and encoded point. + * @param [in] p The point to be scaled and encoded. + */ +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_mul_by_ratio_and_encode_like_x448 ( + uint8_t out[CRYPTON_DECAF_X448_PUBLIC_BYTES], + const crypton_decaf_448_point_t p +) CRYPTON_DECAF_NONNULL; /** The base point for X448 Diffie-Hellman */ -extern const uint8_t crypton_decaf_x448_base_point[CRYPTON_DECAF_X448_PUBLIC_BYTES] CRYPTON_DECAF_API_VIS; +extern const uint8_t +#ifndef DOXYGEN + /* For some reason Doxygen chokes on this despite the defense in common.h... */ + CRYPTON_DECAF_API_VIS +#endif + crypton_decaf_x448_base_point[CRYPTON_DECAF_X448_PUBLIC_BYTES]; /** * @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses @@ -407,13 +464,13 @@ extern const uint8_t crypton_decaf_x448_base_point[CRYPTON_DECAF_X448_PUBLIC_BYT * @deprecated Renamed to crypton_decaf_x448_derive_public_key. * I have no particular timeline for removing this name. * - * @param [out] scaled The scaled point base*scalar - * @param [in] scalar The scalar to multiply by. + * @param [out] out The public key base*scalar. + * @param [in] scalar The private scalar. */ -void crypton_decaf_x448_generate_key ( +void CRYPTON_DECAF_API_VIS crypton_decaf_x448_generate_key ( uint8_t out[CRYPTON_DECAF_X448_PUBLIC_BYTES], const uint8_t scalar[CRYPTON_DECAF_X448_PRIVATE_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_DEPRECATED("Renamed to crypton_decaf_x448_derive_public_key"); +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_DEPRECATED("Renamed to crypton_decaf_x448_derive_public_key"); /** * @brief RFC 7748 Diffie-Hellman base point scalarmul. This function uses @@ -422,13 +479,13 @@ void crypton_decaf_x448_generate_key ( * Does exactly the same thing as crypton_decaf_x448_generate_key, * but has a better name. * - * @param [out] scaled The scaled point base*scalar - * @param [in] scalar The scalar to multiply by. + * @param [out] out The public key base*scalar + * @param [in] scalar The private scalar. */ -void crypton_decaf_x448_derive_public_key ( +void CRYPTON_DECAF_API_VIS crypton_decaf_x448_derive_public_key ( uint8_t out[CRYPTON_DECAF_X448_PUBLIC_BYTES], const uint8_t scalar[CRYPTON_DECAF_X448_PRIVATE_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /* FUTURE: uint8_t crypton_decaf_448_encode_like_curve448) */ @@ -441,10 +498,10 @@ void crypton_decaf_x448_derive_public_key ( * @param [out] a A precomputed table of multiples of the point. * @param [in] b Any point. */ -void crypton_decaf_448_precompute ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_precompute ( crypton_decaf_448_precomputed_s *a, const crypton_decaf_448_point_t b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Multiply a precomputed base point by a scalar: @@ -457,11 +514,11 @@ void crypton_decaf_448_precompute ( * @param [in] base The point to be scaled. * @param [in] scalar The scalar to multiply by. */ -void crypton_decaf_448_precomputed_scalarmul ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_precomputed_scalarmul ( crypton_decaf_448_point_t scaled, const crypton_decaf_448_precomputed_s *base, const crypton_decaf_448_scalar_t scalar -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Multiply two base points by two scalars: @@ -476,13 +533,13 @@ void crypton_decaf_448_precomputed_scalarmul ( * @param [in] base2 A second point to be scaled. * @param [in] scalar2 A second scalar to multiply by. */ -void crypton_decaf_448_point_double_scalarmul ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_double_scalarmul ( crypton_decaf_448_point_t combo, const crypton_decaf_448_point_t base1, const crypton_decaf_448_scalar_t scalar1, const crypton_decaf_448_point_t base2, const crypton_decaf_448_scalar_t scalar2 -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * Multiply one base point by two scalars: @@ -499,13 +556,13 @@ void crypton_decaf_448_point_double_scalarmul ( * @param [in] scalar1 A first scalar to multiply by. * @param [in] scalar2 A second scalar to multiply by. */ -void crypton_decaf_448_point_dual_scalarmul ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_dual_scalarmul ( crypton_decaf_448_point_t a1, crypton_decaf_448_point_t a2, const crypton_decaf_448_point_t base1, const crypton_decaf_448_scalar_t scalar1, const crypton_decaf_448_scalar_t scalar2 -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Multiply two base points by two scalars: @@ -522,12 +579,12 @@ void crypton_decaf_448_point_dual_scalarmul ( * @warning: This function takes variable time, and may leak the scalars * used. It is designed for signature verification. */ -void crypton_decaf_448_base_double_scalarmul_non_secret ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_base_double_scalarmul_non_secret ( crypton_decaf_448_point_t combo, const crypton_decaf_448_scalar_t scalar1, const crypton_decaf_448_point_t base2, const crypton_decaf_448_scalar_t scalar2 -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Constant-time decision between two points. If pick_b @@ -538,12 +595,12 @@ void crypton_decaf_448_base_double_scalarmul_non_secret ( * @param [in] b Any point. * @param [in] pick_b If nonzero, choose point b. */ -void crypton_decaf_448_point_cond_sel ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_cond_sel ( crypton_decaf_448_point_t out, const crypton_decaf_448_point_t a, const crypton_decaf_448_point_t b, crypton_decaf_word_t pick_b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Constant-time decision between two scalars. If pick_b @@ -554,12 +611,12 @@ void crypton_decaf_448_point_cond_sel ( * @param [in] b Any scalar. * @param [in] pick_b If nonzero, choose scalar b. */ -void crypton_decaf_448_scalar_cond_sel ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_cond_sel ( crypton_decaf_448_scalar_t out, const crypton_decaf_448_scalar_t a, const crypton_decaf_448_scalar_t b, crypton_decaf_word_t pick_b -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Test that a point is valid, for debugging purposes. @@ -568,9 +625,9 @@ void crypton_decaf_448_scalar_cond_sel ( * @retval CRYPTON_DECAF_TRUE The point is valid. * @retval CRYPTON_DECAF_FALSE The point is invalid. */ -crypton_decaf_bool_t crypton_decaf_448_point_valid ( +crypton_decaf_bool_t CRYPTON_DECAF_API_VIS crypton_decaf_448_point_valid ( const crypton_decaf_448_point_t to_test -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_WARN_UNUSED CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Torque a point, for debugging purposes. The output @@ -579,10 +636,10 @@ crypton_decaf_bool_t crypton_decaf_448_point_valid ( * @param [out] q The point to torque. * @param [in] p The point to torque. */ -void crypton_decaf_448_point_debugging_torque ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_debugging_torque ( crypton_decaf_448_point_t q, const crypton_decaf_448_point_t p -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Projectively scale a point, for debugging purposes. @@ -593,11 +650,11 @@ void crypton_decaf_448_point_debugging_torque ( * @param [in] p The point to scale. * @param [in] factor Serialized GF factor to scale. */ -void crypton_decaf_448_point_debugging_pscale ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_debugging_pscale ( crypton_decaf_448_point_t q, const crypton_decaf_448_point_t p, const unsigned char factor[CRYPTON_DECAF_448_SER_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Almost-Elligator-like hash to curve. @@ -627,11 +684,11 @@ void crypton_decaf_448_point_debugging_pscale ( * @param [in] hashed_data Output of some hash function. * @param [out] pt The data hashed to the curve. */ -void +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_from_hash_nonuniform ( crypton_decaf_448_point_t pt, const unsigned char hashed_data[CRYPTON_DECAF_448_HASH_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Indifferentiable hash function encoding to curve. @@ -641,10 +698,10 @@ crypton_decaf_448_point_from_hash_nonuniform ( * @param [in] hashed_data Output of some hash function. * @param [out] pt The data hashed to the curve. */ -void crypton_decaf_448_point_from_hash_uniform ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_from_hash_uniform ( crypton_decaf_448_point_t pt, const unsigned char hashed_data[2*CRYPTON_DECAF_448_HASH_BYTES] -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE; /** * @brief Inverse of elligator-like hash to curve. @@ -656,6 +713,16 @@ void crypton_decaf_448_point_from_hash_uniform ( * inverse sampling, this function succeeds or fails * independently for different "which" values. * + * This function isn't guaranteed to find every possible + * preimage, but it finds all except a small finite number. + * In particular, when the number of bits in the modulus isn't + * a multiple of 8 (i.e. for curve25519), it sets the high bits + * independently, which enables the generated data to be uniform. + * But it doesn't add p, so you'll never get exactly p from this + * function. This might change in the future, especially if + * we ever support eg Brainpool curves, where this could cause + * real nonuniformity. + * * @param [out] recovered_hash Encoded data. * @param [in] pt The point to encode. * @param [in] which A value determining which inverse point @@ -664,12 +731,12 @@ void crypton_decaf_448_point_from_hash_uniform ( * @retval CRYPTON_DECAF_SUCCESS The inverse succeeded. * @retval CRYPTON_DECAF_FAILURE The inverse failed. */ -crypton_decaf_error_t +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_invert_elligator_nonuniform ( unsigned char recovered_hash[CRYPTON_DECAF_448_HASH_BYTES], const crypton_decaf_448_point_t pt, uint32_t which -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_WARN_UNUSED; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_WARN_UNUSED; /** * @brief Inverse of elligator-like hash to curve. @@ -689,33 +756,31 @@ crypton_decaf_448_invert_elligator_nonuniform ( * @retval CRYPTON_DECAF_SUCCESS The inverse succeeded. * @retval CRYPTON_DECAF_FAILURE The inverse failed. */ -crypton_decaf_error_t +crypton_decaf_error_t CRYPTON_DECAF_API_VIS crypton_decaf_448_invert_elligator_uniform ( unsigned char recovered_hash[2*CRYPTON_DECAF_448_HASH_BYTES], const crypton_decaf_448_point_t pt, uint32_t which -) CRYPTON_DECAF_API_VIS CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_WARN_UNUSED; +) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_NOINLINE CRYPTON_DECAF_WARN_UNUSED; -/** - * @brief Overwrite scalar with zeros. - */ -void crypton_decaf_448_scalar_destroy ( +/** Securely erase a scalar. */ +void CRYPTON_DECAF_API_VIS crypton_decaf_448_scalar_destroy ( crypton_decaf_448_scalar_t scalar -) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_API_VIS; +) CRYPTON_DECAF_NONNULL; -/** - * @brief Overwrite point with zeros. +/** Securely erase a point by overwriting it with zeros. + * @warning This causes the point object to become invalid. */ -void crypton_decaf_448_point_destroy ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_point_destroy ( crypton_decaf_448_point_t point -) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_API_VIS; +) CRYPTON_DECAF_NONNULL; -/** - * @brief Overwrite precomputed table with zeros. +/** Securely erase a precomputed table by overwriting it with zeros. + * @warning This causes the table object to become invalid. */ -void crypton_decaf_448_precomputed_destroy ( +void CRYPTON_DECAF_API_VIS crypton_decaf_448_precomputed_destroy ( crypton_decaf_448_precomputed_s *pre -) CRYPTON_DECAF_NONNULL CRYPTON_DECAF_API_VIS; +) CRYPTON_DECAF_NONNULL; #ifdef __cplusplus } /* extern "C" */ diff --git a/cbits/decaf/include/field.h b/cbits/decaf/include/field.h index 74814b68..ab857d7e 100644 --- a/cbits/decaf/include/field.h +++ b/cbits/decaf/include/field.h @@ -103,5 +103,10 @@ static CRYPTON_DECAF_INLINE void crypton_gf_div_qnr(crypton_gf_s *__restrict__ o #endif } +#if P_MOD_8 == 5 +#define crypton_gf_mul_i crypton_gf_mul_qnr +#define crypton_gf_div_i crypton_gf_div_qnr +#endif + #endif // __GF_H__ diff --git a/cbits/decaf/include/word.h b/cbits/decaf/include/word.h index 2f491b84..363e8eb7 100644 --- a/cbits/decaf/include/word.h +++ b/cbits/decaf/include/word.h @@ -13,6 +13,11 @@ extern int posix_memalign(void **, size_t, size_t); #endif +// MSVC has no posix_memalign +#if defined(_MSC_VER) +#define posix_memalign(p, a, s) (((*(p)) = _aligned_malloc((s), (a))), *(p) ?0 :errno) +#endif + #include #include #include "arch_intrinsics.h" @@ -58,6 +63,22 @@ extern int posix_memalign(void **, size_t, size_t); #else #error "For now, libdecaf only supports 32- and 64-bit architectures." #endif + +/** + * Expand bit 0 of the given uint8_t to a mask_t all 1 or all 0 + * The input must be either 0 or 1 + */ +CRYPTON_DECAF_INLINE mask_t bit_to_mask(uint8_t bit) { +#ifdef _MSC_VER +#pragma warning ( push) +#pragma warning ( disable : 4146) +#endif + return -(mask_t)bit; +#ifdef _MSC_VER +#pragma warning ( pop) +#endif + +} /* Scalar limbs are keyed off of the API word size instead of the arch word size. */ #if CRYPTON_DECAF_WORD_BITS == 64 @@ -130,7 +151,7 @@ extern int posix_memalign(void **, size_t, size_t); br_set_to_mask(mask_t x) { return vdupq_n_u32(x); } -#elif _WIN64 || __amd64__ || __X86_64__ || __aarch64__ +#elif __amd64__ || __X86_64__ || __aarch64__ /* || _WIN64 -> WIN64 does not support int128 so force the build on arch32 default so do not use this define for _WIN64*/ #define VECTOR_ALIGNED __attribute__((aligned(8))) typedef uint64_t big_register_t, uint64xn_t; diff --git a/cbits/decaf/p448/arch_32/f_impl.c b/cbits/decaf/p448/arch_32/f_impl.c index 054f5d56..00ae4c50 100644 --- a/cbits/decaf/p448/arch_32/f_impl.c +++ b/cbits/decaf/p448/arch_32/f_impl.c @@ -88,11 +88,11 @@ void crypton_gf_mulw_unsigned (crypton_gf_s *__restrict__ cs, const gf as, uint3 accum0 += accum8 + c[8]; c[8] = accum0 & mask; - c[9] += accum0 >> 28; + c[9] += (uint32_t)(accum0 >> 28); accum8 += c[0]; c[0] = accum8 & mask; - c[1] += accum8 >> 28; + c[1] += (uint32_t)(accum8 >> 28); } void crypton_gf_sqr (crypton_gf_s *__restrict__ cs, const gf as) { diff --git a/cbits/decaf/p448/f_field.h b/cbits/decaf/p448/f_field.h index 9c7074a6..68c5ae37 100644 --- a/cbits/decaf/p448/f_field.h +++ b/cbits/decaf/p448/f_field.h @@ -23,7 +23,6 @@ #define __CRYPTON_DECAF_448_GF_DEFINED__ 1 #define NLIMBS (64/sizeof(word_t)) -#define X_SER_BYTES 56 #define SER_BYTES 56 typedef struct crypton_gf_448_s { word_t limb[NLIMBS]; @@ -37,7 +36,7 @@ typedef struct crypton_gf_448_s { #define gf crypton_gf_448_t #define crypton_gf_s crypton_gf_448_s #define crypton_gf_eq crypton_gf_448_eq -#define crypton_gf_hibit crypton_gf_448_hibit +#define crypton_gf_lobit crypton_gf_448_lobit #define crypton_gf_copy crypton_gf_448_copy #define crypton_gf_add crypton_gf_448_add #define crypton_gf_sub crypton_gf_448_sub @@ -54,7 +53,7 @@ typedef struct crypton_gf_448_s { #define crypton_gf_deserialize crypton_gf_448_deserialize /* RFC 7748 support */ -#define X_PUBLIC_BYTES X_SER_BYTES +#define X_PUBLIC_BYTES SER_BYTES #define X_PRIVATE_BYTES X_PUBLIC_BYTES #define X_PRIVATE_BITS 448 @@ -81,10 +80,10 @@ void crypton_gf_mulw_unsigned (crypton_gf_s *__restrict__ out, const gf a, uint3 void crypton_gf_sqr (crypton_gf_s *__restrict__ out, const gf a); mask_t crypton_gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ mask_t crypton_gf_eq (const gf x, const gf y); -mask_t crypton_gf_hibit (const gf x); +mask_t crypton_gf_lobit (const gf x); -void crypton_gf_serialize (uint8_t *serial, const gf x,int with_highbit); -mask_t crypton_gf_deserialize (gf x, const uint8_t serial[SER_BYTES],int with_highbit); +void crypton_gf_serialize (uint8_t serial[SER_BYTES], const gf x); +mask_t crypton_gf_deserialize (gf x, const uint8_t serial[SER_BYTES],uint8_t hi_nmask); #ifdef __cplusplus diff --git a/cbits/decaf/p448/f_generic.c b/cbits/decaf/p448/f_generic.c index e1a924f0..a476577f 100644 --- a/cbits/decaf/p448/f_generic.c +++ b/cbits/decaf/p448/f_generic.c @@ -24,52 +24,52 @@ static const gf MODULUS = {FIELD_LITERAL( #endif /** Serialize to wire format. */ -void crypton_gf_serialize (uint8_t serial[SER_BYTES], const gf x, int with_hibit) { +void crypton_gf_serialize (uint8_t serial[SER_BYTES], const gf x) { gf red; crypton_gf_copy(red, x); crypton_gf_strong_reduce(red); - if (!with_hibit) { assert(crypton_gf_hibit(red) == 0); } unsigned int j=0, fill=0; dword_t buffer = 0; - UNROLL for (unsigned int i=0; i<(with_hibit ? X_SER_BYTES : SER_BYTES); i++) { + UNROLL for (unsigned int i=0; ilimb[LIMBPERM(j)]) << fill; fill += LIMB_PLACE_VALUE(LIMBPERM(j)); j++; } - serial[i] = buffer; + serial[i] = (uint8_t)buffer; fill -= 8; buffer >>= 8; } } /** Return high bit of x = low bit of 2x mod p */ -mask_t crypton_gf_hibit(const gf x) { +mask_t crypton_gf_lobit(const gf x) { gf y; - crypton_gf_add(y,x,x); + crypton_gf_copy(y,x); crypton_gf_strong_reduce(y); - return -(y->limb[0]&1); + return bit_to_mask((y->limb[0]) & 1); } /** Deserialize from wire format; return -1 on success and 0 on failure. */ -mask_t crypton_gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { +mask_t crypton_gf_deserialize (gf x, const uint8_t serial[SER_BYTES], uint8_t hi_nmask) { unsigned int j=0, fill=0; dword_t buffer = 0; dsword_t scarry = 0; UNROLL for (unsigned int i=0; ilimb[LIMBPERM(i)] = (ilimb[LIMBPERM(i)] = (word_t)((i>= LIMB_PLACE_VALUE(LIMBPERM(i)); scarry = (scarry + x->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]) >> (8*sizeof(word_t)); } - mask_t succ = with_hibit ? -(mask_t)1 : ~crypton_gf_hibit(x); - return succ & word_is_zero(buffer) & ~word_is_zero(scarry); + return word_is_zero((word_t)buffer) & ~word_is_zero((word_t)scarry); } /** Reduce to canonical form. */ @@ -91,9 +91,9 @@ void crypton_gf_strong_reduce (gf a) { * common case: it was < p, so now scarry = -1 and this = x - p + 2^255 * so let's add back in p. will carry back off the top for 2^255. */ - assert(word_is_zero(scarry) | word_is_zero(scarry+1)); + assert(word_is_zero((word_t)scarry) | word_is_zero((word_t)scarry+1)); - word_t scarry_0 = scarry; + word_t scarry_0 = (word_t)scarry; dword_t carry = 0; /* add it back */ @@ -103,7 +103,7 @@ void crypton_gf_strong_reduce (gf a) { carry >>= LIMB_PLACE_VALUE(LIMBPERM(i)); } - assert(word_is_zero(carry + scarry_0)); + assert(word_is_zero((word_t)(carry) + scarry_0)); } /** Subtract two gf elements d=a-b */