Skip to content

Commit

Permalink
Small memory footprint option for New Hope
Browse files Browse the repository at this point in the history
  • Loading branch information
rweather committed Aug 23, 2016
1 parent 824e1c2 commit 5bdacd3
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 23 deletions.
84 changes: 61 additions & 23 deletions libraries/NewHope/NewHope.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -740,14 +740,6 @@ static void poly_invntt(uint16_t *r)
mul_coefficients(r, psis_inv_montgomery);
}

static void encode_a(unsigned char *r, const uint16_t *pk, const unsigned char *seed)
{
int i;
poly_tobytes(r, pk);
for(i=0;i<NEWHOPE_SEEDBYTES;i++)
r[POLY_BYTES+i] = seed[i];
}

static void encode_b(unsigned char *r, const uint16_t *b, const uint16_t *c)
{
int i;
Expand Down Expand Up @@ -942,7 +934,7 @@ static void poly_uniform_torref(uint16_t *a, const unsigned char *seed)

#endif // NEWHOPE_TORREF

static void poly_getnoise(uint16_t *r, unsigned char *seed, unsigned char nonce)
static void poly_getnoise(uint16_t *r, const unsigned char *seed, unsigned char nonce)
{
uint32_t input[16];
uint32_t buf[16];
Expand Down Expand Up @@ -1057,28 +1049,56 @@ void NewHopePoly::clear()
void NewHope::keygen(uint8_t send[NEWHOPE_SENDABYTES], NewHopePrivateKey &sk,
Variant variant, const uint8_t *random_seed)
{
// The order of calls is rearranged compared to the reference C version.
// This allows us to get away with two temporary poly objects (a, pk)
// instead of four (a, e, r, pk). This saves 4k of stack space.
#if NEWHOPE_SMALL_FOOTPRINT
NewHopePolyExtended a;
NewHopePoly pk;

if (!random_seed) {
RNG.rand(send + POLY_BYTES, NEWHOPE_SEEDBYTES);
RNG.rand(sk.seed, 32);
} else {
memcpy(send + POLY_BYTES, random_seed, NEWHOPE_SEEDBYTES);
memcpy(sk.seed, random_seed + NEWHOPE_SEEDBYTES, 32);
}
sha3256(send + POLY_BYTES, send + POLY_BYTES, NEWHOPE_SEEDBYTES);

if (variant == Ref)
poly_uniform(a.coeffs, send + POLY_BYTES);
else
poly_uniform_torref(a.coeffs, send + POLY_BYTES);

poly_getnoise(pk.coeffs, sk.seed, 0);
poly_ntt(pk.coeffs);

poly_pointwise(pk.coeffs, pk.coeffs, a.coeffs);

poly_getnoise(a.coeffs, sk.seed, 1);
poly_ntt(a.coeffs);

poly_add(pk.coeffs, a.coeffs, pk.coeffs);

poly_tobytes(send, pk.coeffs);
#else
NewHopePolyExtended a;
NewHopePoly pk;
uint8_t seed[NEWHOPE_SEEDBYTES];
uint8_t noiseseed[32];

if (!random_seed) {
RNG.rand(seed, NEWHOPE_SEEDBYTES);
RNG.rand(send + POLY_BYTES, NEWHOPE_SEEDBYTES);
RNG.rand(noiseseed, 32);
} else {
memcpy(seed, random_seed, NEWHOPE_SEEDBYTES);
memcpy(send + POLY_BYTES, random_seed, NEWHOPE_SEEDBYTES);
memcpy(noiseseed, random_seed + NEWHOPE_SEEDBYTES, 32);
}
sha3256(seed, seed, NEWHOPE_SEEDBYTES);

// The order of calls is rearranged compared to the reference C version.
// This allows us to get away with two temporary poly objects (a, pk)
// instead of four (a, e, r, pk). This saves 4k of stack space.
sha3256(send + POLY_BYTES, send + POLY_BYTES, NEWHOPE_SEEDBYTES);

if (variant == Ref)
poly_uniform(a.coeffs, seed);
poly_uniform(a.coeffs, send + POLY_BYTES);
else
poly_uniform_torref(a.coeffs, seed);
poly_uniform_torref(a.coeffs, send + POLY_BYTES);

poly_getnoise(sk.coeffs, noiseseed, 0);
poly_ntt(sk.coeffs);
Expand All @@ -1090,10 +1110,10 @@ void NewHope::keygen(uint8_t send[NEWHOPE_SENDABYTES], NewHopePrivateKey &sk,

poly_add(pk.coeffs, a.coeffs, pk.coeffs);

encode_a(send, pk.coeffs, seed);
poly_tobytes(send, pk.coeffs);

clean(seed);
clean(noiseseed);
#endif
}

/**
Expand Down Expand Up @@ -1178,11 +1198,28 @@ void NewHope::shareda(uint8_t shared_key[NEWHOPE_SHAREDBYTES],
const NewHopePrivateKey &sk,
uint8_t received[NEWHOPE_SENDBBYTES])
{
NewHopePoly v, bp;

// The order of calls is rearranged compared to the reference C version.
// This allows us to get away with two temporary poly objects (v, bp)
// instead of three (v, bp, c). This saves 2k of stack space.
#if NEWHOPE_SMALL_FOOTPRINT
NewHopePoly v, bp;

poly_frombytes(bp.coeffs, received);

// Re-create the full sk value for Alice from the seed.
poly_getnoise(v.coeffs, sk.seed, 0);
poly_ntt(v.coeffs);

poly_pointwise(v.coeffs, v.coeffs, bp.coeffs);
poly_invntt(v.coeffs);

decode_b_2nd_half(bp.coeffs, received);

rec(shared_key, v.coeffs, bp.coeffs);

sha3256(shared_key, shared_key, 32);
#else
NewHopePoly v, bp;

poly_frombytes(bp.coeffs, received);

Expand All @@ -1194,4 +1231,5 @@ void NewHope::shareda(uint8_t shared_key[NEWHOPE_SHAREDBYTES],
rec(shared_key, v.coeffs, bp.coeffs);

sha3256(shared_key, shared_key, 32);
#endif
}
6 changes: 6 additions & 0 deletions libraries/NewHope/NewHope.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,16 @@
#define NEWHOPE_SENDBBYTES 2048
#define NEWHOPE_SHAREDBYTES 32

#define NEWHOPE_SMALL_FOOTPRINT 1

typedef struct
{
/** @cond */
#if NEWHOPE_SMALL_FOOTPRINT
uint8_t seed[32];
#else
uint16_t coeffs[1024];
#endif
/** @endcond */

} NewHopePrivateKey;
Expand Down

0 comments on commit 5bdacd3

Please sign in to comment.