Browse Source

decaf scalars work

master
Michael Hamburg 10 years ago
parent
commit
83c59a645a
4 changed files with 248 additions and 17 deletions
  1. +64
    -9
      include/decaf.h
  2. +57
    -8
      src/decaf.c
  3. +10
    -0
      test/bench.c
  4. +117
    -0
      test/test_arithmetic.c

+ 64
- 9
include/decaf.h View File

@@ -22,6 +22,13 @@

#include <stdint.h>

/* Goldilocks' build flags default to hidden and stripping executables. */
#define API_VIS __attribute__((visibility("default")))
#define WARN_UNUSED __attribute__((warn_unused_result))
#define NONNULL1 __attribute__((nonnull(1)))
#define NONNULL2 __attribute__((nonnull(1,2)))
#define NONNULL3 __attribute__((nonnull(1,2,3)))

typedef uint64_t decaf_word_t, decaf_bool_t;

/* TODO: prefix all these operations and factor to support multiple curves. */
@@ -34,6 +41,9 @@ typedef uint64_t decaf_word_t, decaf_bool_t;
/** Number of bytes in a serialized point. One less bit than you'd think. */
#define DECAF_SER_BYTES ((DECAF_FIELD_BITS+6)/8)

/** Number of bytes in a serialized scalar. Two less bits than you'd think. */
#define DECAF_SCALAR_BYTES ((DECAF_FIELD_BITS+5)/8)

/** Twisted Edwards (-1,d-1) extended homogeneous coordinates */
typedef struct decaf_point_s {
decaf_word_t x[DECAF_LIMBS],y[DECAF_LIMBS],z[DECAF_LIMBS],t[DECAF_LIMBS];
@@ -50,25 +60,58 @@ static const decaf_bool_t DECAF_SUCCESS = -(decaf_bool_t)1 /*DECAF_TRUE*/,
DECAF_FAILURE = 0 /*DECAF_FALSE*/;

/** The identity point on the curve. */
const decaf_point_t decaf_identity;
const decaf_point_t decaf_identity API_VIS;

/** The prime p, for debugging purposes.
* FIXME: prevent this scalar from actually being used for non-debugging purposes?
*/
const decaf_scalar_t decaf_scalar_p API_VIS;

/** A scalar equal to 1. */
const decaf_scalar_t decaf_scalar_one API_VIS;

/** A scalar equal to 0. */
const decaf_scalar_t decaf_scalar_zero API_VIS;

/** An arbitrarily chosen base point on the curve. TODO: define */
const decaf_point_t decaf_basepoint;
const decaf_point_t decaf_basepoint API_VIS;

#ifdef __cplusplus
extern "C" {
#endif

/* Goldilocks' build flags default to hidden and stripping executables. */
#define API_VIS __attribute__((visibility("default")))
#define WARN_UNUSED __attribute__((warn_unused_result))
#define NONNULL1 __attribute__((nonnull(1)))
#define NONNULL2 __attribute__((nonnull(1,2)))
#define NONNULL3 __attribute__((nonnull(1,2,3)))

// TODO: ser, deser, inv?.
// FIXME: scalar math is untested, and therefore probably wrong.

/**
* @brief Read a scalar from wire format or from bytes.
*
* Return DECAF_SUCCESS if the scalar was in reduced form. This
* function is not WARN_UNUSED because eg challenges in signatures
* may need to be longer.
*
* TODO: create a decode long function.
*
* @param [in] ser Serialized form of a scalar.
* @param [out] out Deserialized form.
*/
decaf_bool_t decaf_decode_scalar(
decaf_scalar_t s,
const unsigned char ser[DECAF_SER_BYTES]
) API_VIS NONNULL2;
/**
* @brief Serialize a scalar to wire format.
*
* @param [out] ser Serialized form of a scalar.
* @param [in] s Deserialized scalar.
*/
void decaf_encode_scalar(
unsigned char ser[DECAF_SER_BYTES],
const decaf_scalar_t s
) API_VIS NONNULL2;
/**
* @brief Add two scalars. The scalars may use the same memory.
* @param [in] a One scalar.
@@ -81,6 +124,18 @@ void decaf_add_scalars (
const decaf_scalar_t b
) API_VIS NONNULL3;

/**
* @brief Compare two scalars.
* @param [in] a One scalar.
* @param [in] b Another scalar.
* @retval DECAF_TRUE The scalars are equal.
* @retval DECAF_FALSE The scalars are not equal.
*/
decaf_bool_t decaf_eq_scalars (
const decaf_scalar_t a,
const decaf_scalar_t b
) API_VIS WARN_UNUSED NONNULL2;

/**
* @brief Subtract two scalars. The scalars may use the same memory.
* @param [in] a One scalar.


+ 57
- 8
src/decaf.c View File

@@ -215,7 +215,7 @@ sv decaf_subx(
}
}

static const decaf_scalar_t DECAF_SCALAR_P = {{{
const decaf_scalar_t decaf_scalar_p = {{{
0x2378c292ab5844f3ull,
0x216cc2728dc58f55ull,
0xc44edb49aed63690ull,
@@ -224,7 +224,9 @@ static const decaf_scalar_t DECAF_SCALAR_P = {{{
0xffffffffffffffffull,
0x3fffffffffffffffull
// TODO 32-bit clean
}}}, DECAF_SCALAR_R2 = {{{
}}}, decaf_scalar_one = {{{1}}}, decaf_scalar_zero = {{{0}}};

static const decaf_scalar_t decaf_scalar_r2 = {{{
0xe3539257049b9b60ull,
0x7af32c4bc1b195d9ull,
0x0d66de2388ea1859ull,
@@ -235,7 +237,7 @@ static const decaf_scalar_t DECAF_SCALAR_P = {{{
// TODO 32-bit clean
}}};

static const decaf_word_t DECAF_MONTGOMERY_FACTOR = 0xfc42bbf0516e743b;
static const decaf_word_t DECAF_MONTGOMERY_FACTOR = 0x3bd440fae918bc5ull;

sv decaf_montmul (
decaf_scalar_t out,
@@ -254,7 +256,7 @@ sv decaf_montmul (
decaf_dword_t chain = 0;
for (j=0; j<DECAF_SCALAR_LIMBS; j++) {
chain += (decaf_dword_t)mand*mier[j] + accum[j];
chain += ((decaf_dword_t)mand)*mier[j] + accum[j];
accum[j] = chain;
chain >>= WBITS;
}
@@ -282,8 +284,8 @@ void decaf_mul_scalars (
const decaf_scalar_t a,
const decaf_scalar_t b
) {
decaf_montmul(out,a,b,DECAF_SCALAR_P,DECAF_MONTGOMERY_FACTOR);
decaf_montmul(out,out,DECAF_SCALAR_R2,DECAF_SCALAR_P,DECAF_MONTGOMERY_FACTOR);
decaf_montmul(out,a,b,decaf_scalar_p,DECAF_MONTGOMERY_FACTOR);
decaf_montmul(out,out,decaf_scalar_r2,decaf_scalar_p,DECAF_MONTGOMERY_FACTOR);
}

void decaf_sub_scalars (
@@ -291,7 +293,7 @@ void decaf_sub_scalars (
const decaf_scalar_t a,
const decaf_scalar_t b
) {
decaf_subx(out, a->limb, b, DECAF_SCALAR_P, 0);
decaf_subx(out, a->limb, b, decaf_scalar_p, 0);
}

void decaf_add_scalars (
@@ -306,7 +308,19 @@ void decaf_add_scalars (
out->limb[i] = chain;
chain >>= WBITS;
}
decaf_subx(out, out->limb, b, DECAF_SCALAR_P, chain);
decaf_subx(out, out->limb, decaf_scalar_p, decaf_scalar_p, chain);
}

decaf_bool_t decaf_eq_scalars (
const decaf_scalar_t a,
const decaf_scalar_t b
) {
decaf_word_t diff = 0;
unsigned int i;
for (i=0; i<DECAF_SCALAR_LIMBS; i++) {
diff |= a->limb[i] ^ b->limb[i];
}
return (((decaf_dword_t)diff)-1)>>WBITS;
}

/* *** API begins here *** */
@@ -451,6 +465,41 @@ void decaf_copy (
gf_cpy(a->t, b->t);
}

decaf_bool_t decaf_decode_scalar(
decaf_scalar_t s,
const unsigned char ser[DECAF_SER_BYTES]
) {
unsigned int i,j,k=0;
for (i=0; i<DECAF_SCALAR_LIMBS; i++) {
decaf_word_t out = 0;
for (j=0; j<sizeof(decaf_word_t); j++,k++) {
out |= ((decaf_word_t)ser[k])<<(8*j);
}
s->limb[i] = out;
}
decaf_sdword_t accum = 0;
for (i=0; i<DECAF_SCALAR_LIMBS; i++) {
accum = (accum + s->limb[i] - decaf_scalar_p->limb[i]) >> WBITS;
}
//decaf_mul_scalars(s,s,decaf_scalar_one); /* ham-handed reduce */
return accum;
}

void decaf_encode_scalar(
unsigned char ser[DECAF_SER_BYTES],
const decaf_scalar_t s
) {
unsigned int i,j,k=0;
for (i=0; i<DECAF_SCALAR_LIMBS; i++) {
for (j=0; j<sizeof(decaf_word_t); j++,k++) {
ser[k] = s->limb[i] >> (8*j);
}
}
}

void decaf_scalarmul (
decaf_point_t a,
const decaf_point_t b,


+ 10
- 0
test/bench.c View File

@@ -266,6 +266,16 @@ int main(int argc, char **argv) {
when = now() - when;
printf("barrett mac: %5.1fns\n", when * 1e9 / i);
decaf_scalar_t asc,bsc,csc;
memset(asc,0,sizeof(asc));
memset(bsc,0,sizeof(bsc));
when = now();
for (i=0; i<nbase*10; i++) {
decaf_mul_scalars(csc,asc,bsc);
}
when = now() - when;
printf("decaf mulsc: %5.1fns\n", when * 1e9 / i);
memset(&ext,0,sizeof(ext));
memset(&niels,0,sizeof(niels)); /* avoid assertions in p521 even though this isn't a valid ext or niels */



+ 117
- 0
test/test_arithmetic.c View File

@@ -1,10 +1,24 @@
#include "field.h"
#include "test.h"
#include "decaf.h"
#include <gmp.h>
#include <string.h>
#include <stdio.h>

mpz_t mp_field;
mpz_t mp_scalar_field;

void decaf_scalar_print (
const char *descr,
const decaf_scalar_t scalar
) {
int j;
printf("%s = 0x", descr);
for (j=DECAF_SCALAR_LIMBS-1; j>=0; j--) {
printf(PRIxWORDfull, scalar->limb[j]);
}
printf("\n");
}

static mask_t mpz_to_field (
field_a_t out,
@@ -20,6 +34,78 @@ static mask_t mpz_to_field (
return succ;
}

static mask_t mpz_to_scalar (
decaf_scalar_t out,
const mpz_t in
) {
uint8_t ser[DECAF_SCALAR_BYTES];
mpz_t modded;
memset(ser,0,sizeof(ser));
mpz_init(modded);
mpz_mod(modded, in, mp_scalar_field);
mpz_export(ser, NULL, -1, 1, -1, 0, modded);
mask_t succ = decaf_decode_scalar(out, ser);
return succ;
}

static mask_t scalar_assert_eq_gmp(
const char *descr,
const decaf_scalar_t a,
const decaf_scalar_t b,
const decaf_scalar_t x,
const mpz_t ma,
const mpz_t mb,
const mpz_t y
) {
uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES];
mpz_t modded;
memset(yser,0,sizeof(yser));
decaf_encode_scalar(xser, x);
mpz_init(modded);
mpz_mod(modded, y, mp_scalar_field);
mpz_export(yser, NULL, -1, 1, -1, 0, modded);
if (memcmp(xser,yser,FIELD_BYTES)) {
youfail();
printf(" Failed arithmetic test %s\n", descr);
decaf_scalar_print(" a", a);
decaf_scalar_print(" b", b);
decaf_scalar_print(" decaf", x);
// printf(" gmpa = 0x");
int j;
// mpz_export(yser, NULL, -1, 1, -1, 0, ma);
// for (j=FIELD_BYTES-1; j>=0; j--) {
// printf("%02x", yser[j]);
// }
// printf("\n");
// printf(" gmpb = 0x");
//
//
// mpz_export(yser, NULL, -1, 1, -1, 0, mb);
// for (j=FIELD_BYTES-1; j>=0; j--) {
// printf("%02x", yser[j]);
// }
// printf("\n");
(void)ma; (void)mb;
printf(" gmpy = 0x");

mpz_export(yser, NULL, -1, 1, -1, 0, modded);
for (j=FIELD_BYTES-1; j>=0; j--) {
printf("%02x", yser[j]);
}
printf("\n");
return MASK_FAILURE;
}
mpz_clear(modded);
return MASK_SUCCESS;
}

static inline int BRANCH_ON_CONSTANT(int x) {
__asm__ ("" : "+r"(x));
return x;
@@ -127,6 +213,34 @@ static mask_t test_add_sub_RAW (
return succ;
}

static mask_t test_scalar (
const mpz_t x,
const mpz_t y
) {
decaf_scalar_t xx,yy,tt;
mpz_t t;
mask_t succ = MASK_SUCCESS;
succ = mpz_to_scalar(xx,x);
succ &= mpz_to_scalar(yy,y);
mpz_init(t);
decaf_add_scalars(tt,xx,yy);
mpz_add(t,x,y);
succ &= scalar_assert_eq_gmp("scalar add",xx,yy,tt,x,y,t);
decaf_sub_scalars(tt,xx,yy);
mpz_sub(t,x,y);
succ &= scalar_assert_eq_gmp("scalar sub",xx,yy,tt,x,y,t);
decaf_mul_scalars(tt,xx,yy);
mpz_mul(t,x,y);
succ &= scalar_assert_eq_gmp("scalar mul",xx,yy,tt,x,y,t);
mpz_clear(t);
return succ;
}

static mask_t test_mul_sqr (
const mpz_t x,
const mpz_t y,
@@ -208,6 +322,8 @@ int test_arithmetic (void) {
mpz_init(mp_field);
mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS);
mpz_import(mp_scalar_field, DECAF_SCALAR_LIMBS, -1, sizeof(decaf_word_t), -1, 0, decaf_scalar_p);
mpz_t x,y;
mpz_init(x);
mpz_init(y);
@@ -234,6 +350,7 @@ int test_arithmetic (void) {
succ &= test_add_sub_RAW(x,y,word);
succ &= test_mul_sqr(x,y,word);
succ &= test_scalar(x,y);
if (j < 1000)
succ &= test_isr(x);


Loading…
Cancel
Save