Browse Source

decaf ladder is "correct", but not yet serializing to decaf

master
Michael Hamburg 10 years ago
parent
commit
4f27b22a1d
6 changed files with 145 additions and 30 deletions
  1. +31
    -18
      src/ec_point.c
  2. +7
    -0
      src/include/ec_point.h
  3. +34
    -0
      src/include/scalarmul.h
  4. +35
    -0
      src/scalarmul.c
  5. +7
    -0
      test/bench.c
  6. +31
    -12
      test/test_pointops.c

+ 31
- 18
src/ec_point.c View File

@@ -248,34 +248,47 @@ deserialize_montgomery_decaf (
const field_a_t s
) {
field_copy ( a->s0, s );
field_copy ( a->xa, s );
field_sqr ( a->xa, s );
field_set_ui ( a->za, 1 );
field_set_ui ( a->xd, 1 );
field_set_ui ( a->zd, 0 );
}

mask_t
serialize_montgomery_decaf (
field_a_t b,
const montgomery_aux_a_t a,
const field_a_t sbz
) {
field_a_t L0, L1;
field_isr(L0,a->zd);
field_sqr(L1,L0);
field_mul(b,a->xd,L1);
(void)sbz;
return 0; // Fail, because this routine isn't done yet.
}

void
montgomery_aux_step (
struct montgomery_aux_t* a
) {
ANALYZE_THIS_ROUTINE_CAREFULLY;
field_add_nr ( a->xs, a->xa, a->za );
field_subx_nr ( a->zs, a->xa, a->za );
field_add_nr ( a->xa, a->xd, a->zd );
field_subx_nr ( a->za, a->xd, a->zd );
field_mul ( a->xd, a->xa, a->zs );
field_mul ( a->zd, a->xs, a->za );
field_add_nr ( a->xs, a->xd, a->zd );
field_subx_nr ( a->zd, a->xd, a->zd );
field_mul ( a->zs, a->zd, a->s0 );
field_sqr ( a->zd, a->xa );
field_sqr ( a->xa, a->za );
field_subx_nr ( a->za, a->zd, a->xa );
IF32( field_weak_reduce( a->za ) );
field_mul ( a->xd, a->xa, a->zd );
field_mulw_scc_wr ( a->zd, a->xa, 1-EDWARDS_D );
field_add_nr ( a->xa, a->za, a->zd );
field_mul ( a->zd, a->xa, a->za );
field_add_nr ( a->xs, a->xa, a->za );
field_subx_nr ( a->zs, a->xa, a->za );
field_add_nr ( a->xa, a->xd, a->zd );
field_subx_nr ( a->za, a->xd, a->zd );
field_mul ( a->xd, a->xa, a->zs );
field_mul ( a->zd, a->xs, a->za );
field_add_nr ( a->xs, a->xd, a->zd );
field_subx_nr ( a->zd, a->xd, a->zd );
field_mul ( a->zs, a->zd, a->s0 );
field_sqr ( a->zd, a->xa );
field_sqr ( a->xa, a->za );
field_subx_nr ( a->za, a->zd, a->xa );
field_mul ( a->xd, a->xa, a->zd );
field_mulw_scc_wr ( a->zd, a->za, 1-EDWARDS_D );
field_add_nr ( a->xa, a->xa, a->zd );
field_mul ( a->zd, a->xa, a->za );
field_sqr ( a->xa, a->xs );
field_sqr ( a->za, a->zs );
}


+ 7
- 0
src/include/ec_point.h View File

@@ -294,6 +294,13 @@ serialize_montgomery (
const montgomery_a_t a,
const field_a_t sbz
);

mask_t
serialize_montgomery_decaf (
field_a_t b,
const montgomery_aux_a_t a,
const field_a_t sbz
);
void
deserialize_montgomery_decaf (


+ 34
- 0
src/include/scalarmul.h View File

@@ -97,6 +97,40 @@ montgomery_ladder (
unsigned int n_extra_doubles
) __attribute__((warn_unused_result));
/**
* Full Montgomery aux ladder in decaf format.
*
* Out = [2^n_extra_doubles * scalar] * in, where
* scalar is little-endian and has length $nbits$ bits.
*
* This function (once it's done; TODO) will always reject points
* on the twist.
*
* This function takes constant time with respect to $*in$
* and $*scalar$, but not of course with respect to nbits or
* n_extra_doubles.
*
* @param [out] out The output point.
* @param [in] in The base point.
* @param [in] scalar The scalar's little-endian representation.
* @param [in] nbits The number of bits in the scalar. Note that
* unlike in Curve25519, we do not require the top bit to be set.
* @param [in] n_extra_doubles The number of extra doubles to do at
* the end.
*
* @retval MASK_SUCCESS The operation was successful.
* @retval MASK_FAILURE The input point was invalid, or the output
* would be the identity or the point of order 2.
*/
mask_t
montgomery_ladder_decaf (
field_a_t out,
const field_a_t in,
const word_t *scalar,
unsigned int nbits,
unsigned int n_extra_doubles
) __attribute__((warn_unused_result));
/**
* Scalar multiply a twisted Edwards-form point.
*


+ 35
- 0
src/scalarmul.c View File

@@ -48,6 +48,41 @@ montgomery_ladder (
return serialize_montgomery(out, mont, in);
}

mask_t
montgomery_ladder_decaf (
field_a_t out,
const field_a_t in,
const word_t *scalar,
unsigned int nbits,
unsigned int n_extra_doubles
) {
montgomery_aux_a_t mont;
deserialize_montgomery_decaf(mont, in);
int i,j,n=(nbits-1)%WORD_BITS;
mask_t pflip = 0;
for (j=(nbits+WORD_BITS-1)/WORD_BITS-1; j>=0; j--) {
word_t w = scalar[j];
for (i=n; i>=0; i--) {
mask_t flip = -((w>>i)&1);
constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),flip^pflip);
constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),flip^pflip);
montgomery_aux_step(mont);
pflip = flip;
}
n = WORD_BITS-1;
}
constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),pflip);
constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),pflip);
assert(n_extra_doubles < INT_MAX);
for (j=0; j<(int)n_extra_doubles; j++) {
montgomery_aux_step(mont);
}
return serialize_montgomery_decaf(out, mont, in);
}

static __inline__ void
__attribute__((unused,always_inline))
constant_time_lookup_tw_pniels (


+ 7
- 0
test/bench.c View File

@@ -325,6 +325,13 @@ int main(int argc, char **argv) {
}
when = now() - when;
printf("full ladder: %5.1fµs\n", when * 1e6 / i);
when = now();
for (i=0; i<nbase/10; i++) {
ignore_result(montgomery_ladder_decaf(a,b,sk,FIELD_BITS,0));
}
when = now() - when;
printf("decafladder: %5.1fµs\n", when * 1e6 / i);
when = now();
for (i=0; i<nbase/10; i++) {


+ 31
- 12
test/test_pointops.c View File

@@ -3,6 +3,7 @@
#include <stdio.h>

#include "ec_point.h"
#include "scalarmul.h"
#include "magic.h"
#include "field.h"
#include "crandom.h"
@@ -261,22 +262,32 @@ int test_decaf (void) {
int i, hits = 0, fails = 0;
for (i=0; i<1000; i++) {
uint8_t ser[FIELD_BYTES];
crandom_generate(&crand, ser, sizeof(ser));
#if (FIELD_BITS % 8)
ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
#endif
ser[0] &= ~1;
int j;
mask_t succ = 0;
for (j=0; j<128 && !succ; j++) {
crandom_generate(&crand, ser, sizeof(ser));
#if (FIELD_BITS % 8)
ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1;
#endif
ser[0] &= ~1;

mask_t succ = field_deserialize(serf, ser);
succ = field_deserialize(serf, ser);
if (!succ) {
youfail();
printf(" Unlikely: fail at field_deserialize\n");
return -1;
}
succ &= decaf_deserialize_affine(&base, serf, 0);
}
if (!succ) {
youfail();
printf(" Unlikely: fail at field_deserialize\n");
printf("Unlikely: fail 128 desers\n");
return -1;
}
succ &= decaf_deserialize_affine(&base, serf, 0);
if (!succ) continue;
hits++;
field_a_t serf2;
struct extensible_t ext;
@@ -351,10 +362,18 @@ int test_decaf (void) {
fails ++;
}
word_t scalar = i;
mask_t res = montgomery_ladder_decaf(serf2,serf,&scalar,i,0);
// youfail();
// printf("Decaf Montgomery ladder i=%d res=%d\n", i, (int)res);
// field_print(" s", serf);
// field_print(" o", serf2);
// printf("\n");
(void)res;
}
if (hits < 350) {
if (hits < 1000) {
youfail();
printf(" Unlikely: only %d successes in decaf_deser\n", hits);
printf(" Fail: only %d successes in decaf_deser\n", hits);
return -1;
} else if (fails) {
return -1;


Loading…
Cancel
Save