Commit 2e23ac74 authored by Michael Hamburg's avatar Michael Hamburg

move (some of the?) per-field code to src/per_field.c

parent 825751d0
......@@ -126,7 +126,7 @@ $(GEN_HEADERS): src/gen_headers/*.py src/public_include/decaf/*
################################################################
define define_field
ARCH_FOR_$(1) ?= $(2)
COMPONENTS_OF_$(1) = $$(BUILD_OBJ)/$(1)_impl.o $$(BUILD_OBJ)/$(1)_arithmetic.o
COMPONENTS_OF_$(1) = $$(BUILD_OBJ)/$(1)_impl.o $$(BUILD_OBJ)/$(1)_arithmetic.o $$(BUILD_OBJ)/$(1)_per_field.o
LIBCOMPONENTS += $$(COMPONENTS_OF_$(1))
$$(BUILD_ASM)/$(1)_arithmetic.s: src/$(1)/f_arithmetic.c $$(HEADERS)
......@@ -138,6 +138,11 @@ $$(BUILD_ASM)/$(1)_impl.s: src/$(1)/$$(ARCH_FOR_$(1))/f_impl.c $$(HEADERS)
$$(CC) $$(CFLAGS) -I src/$(1) -I src/$(1)/$$(ARCH_FOR_$(1)) -I $(BUILD_H)/$(1) \
-I $(BUILD_H)/$(1)/$$(ARCH_FOR_$(1)) -I src/include/$$(ARCH_FOR_$(1)) \
-S -c -o $$@ $$<
$$(BUILD_ASM)/$(1)_per_field.s: src/per_field.c $$(HEADERS)
$$(CC) $$(CFLAGS) -I src/$(1) -I src/$(1)/$$(ARCH_FOR_$(1)) -I $(BUILD_H)/$(1) \
-I $(BUILD_H)/$(1)/$$(ARCH_FOR_$(1)) -I src/include/$$(ARCH_FOR_$(1)) \
-S -c -o $$@ $$<
endef
################################################################
......@@ -171,8 +176,8 @@ $$(BUILD_ASM)/decaf_$(1).s: src/decaf.c $$(HEADERS)
$$(BUILD_ASM)/decaf_crypto_$(1).s: src/decaf_crypto.c $$(HEADERS)
$$(CC) $$(CFLAGS) \
-I src/curve_$(1)/ \
-I $(BUILD_H)/curve_$(1) \
-I src/curve_$(1)/ -I src/$(2) -I src/$(2)/$$(ARCH_FOR_$(2)) -I src/include/$$(ARCH_FOR_$(2)) \
-I $(BUILD_H)/curve_$(1) -I $(BUILD_H)/$(2) -I $(BUILD_H)/$(2)/$$(ARCH_FOR_$(2)) \
-S -c -o $$@ $$<
LIBCOMPONENTS += $$(BUILD_OBJ)/decaf_$(1).o $$(BUILD_OBJ)/decaf_tables_$(1).o
......
......@@ -8,7 +8,6 @@
#define scalar_t decaf_255_scalar_t
#define point_t decaf_255_point_t
#define precomputed_s decaf_255_precomputed_s
#define SER_BYTES DECAF_255_SER_BYTES
#define IMAGINE_TWIST 1
#define P_MOD_8 5
#define COFACTOR 8
......
......@@ -7,7 +7,6 @@
#define scalar_t decaf_448_scalar_t
#define point_t decaf_448_point_t
#define precomputed_s decaf_448_precomputed_s
#define SER_BYTES DECAF_448_SER_BYTES
#define IMAGINE_TWIST 0
#define P_MOD_8 7
#define COFACTOR 4
......
......@@ -50,17 +50,8 @@ extern const gf SQRT_ONE_MINUS_D; /* TODO: Intern this? */
const scalar_t API_NS(scalar_one) = {{{1}}}, API_NS(scalar_zero) = {{{0}}};
extern const scalar_t API_NS(sc_r2);
extern const decaf_word_t API_NS(MONTGOMERY_FACTOR);
extern const point_t API_NS(point_base);
/* These are externally exposed (but private) instead of static so that
* f_arithmetic.c can use it
*/
#define ONE API_NS(ONE)
#define ZERO API_NS(ZERO)
#define gf_eq API_NS(gf_eq)
const gf ZERO = {{{0}}}, ONE = {{{1}}};
/* Projective Niels coordinates */
typedef struct { gf a, b, c; } niels_s, niels_t[1];
typedef struct { niels_t n; gf z; } __attribute__((aligned(32))) pniels_s, pniels_t[1]; /* MAGIC alignment */
......@@ -75,93 +66,9 @@ const precomputed_s *API_NS(precomputed_base) =
const size_t API_NS2(sizeof,precomputed_s) = sizeof(precomputed_s);
const size_t API_NS2(alignof,precomputed_s) = 32;
/* TODO PERF: Vectorize vs unroll */
#ifdef __clang__
#if 100*__clang_major__ + __clang_minor__ > 305
#define UNROLL _Pragma("clang loop unroll(full)") // PERF TODO: vectorize?
#endif
#endif
#ifndef UNROLL
#define UNROLL
#endif
#define FOR_LIMB(i,op) { unsigned int i=0; for (i=0; i<NLIMBS; i++) { op; }}
#define FOR_LIMB_U(i,op) { unsigned int i=0; UNROLL for (i=0; i<NLIMBS; i++) { op; }}
/* FUTURE: move this code from per-curve to per-field header
* (like f_arithmetic.c but same for all fields)
*/
void gf_serialize (uint8_t serial[SER_BYTES], const gf x) {
gf red;
gf_copy(red, x);
gf_strong_reduce(red);
unsigned int j=0, fill=0;
dword_t buffer = 0;
UNROLL for (unsigned int i=0; i<SER_BYTES; i++) {
if (fill < 8 && j < NLIMBS) {
buffer |= ((dword_t)red->limb[LIMBPERM(j)]) << fill;
fill += LIMB_PLACE_VALUE(LIMBPERM(j));
j++;
}
serial[i] = buffer;
fill -= 8;
buffer >>= 8;
}
}
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES]) {
unsigned int j=0, fill=0;
dword_t buffer = 0;
dsword_t scarry = 0;
UNROLL for (unsigned int i=0; i<NLIMBS; i++) {
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < SER_BYTES) {
buffer |= ((dword_t)serial[j]) << fill;
fill += 8;
j++;
}
x->limb[LIMBPERM(i)] = (i<NLIMBS-1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer;
fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
scarry = (scarry + x->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]) >> (8*sizeof(word_t));
}
return word_is_zero(buffer) & ~word_is_zero(scarry);
}
void gf_strong_reduce (gf a) {
/* first, clear high */
gf_weak_reduce(a); /* PERF: only really need one step of this, but whatevs */
/* now the total is less than 2p */
/* compute total_value - p. No need to reduce mod p. */
dsword_t scarry = 0;
for (unsigned int i=0; i<NLIMBS; i++) {
scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
a->limb[i] = scarry & LIMB_MASK(LIMBPERM(i));
scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
/* uncommon case: it was >= p, so now scarry = 0 and this = x
* 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));
word_t scarry_0 = scarry;
dword_t carry = 0;
/* add it back */
for (unsigned int i=0; i<NLIMBS; i++) {
carry = carry + a->limb[LIMBPERM(i)] + (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
a->limb[i] = carry & LIMB_MASK(LIMBPERM(i));
carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
assert(word_is_zero(carry + scarry_0));
}
/** Constant time, x = is_z ? z : y */
static INLINE void
cond_sel(gf x, const gf y, const gf z, decaf_bool_t is_z) {
......@@ -186,21 +93,6 @@ cond_swap(gf x, gf_s *__restrict__ y, decaf_bool_t swap) {
}
}
/** Compare a==b */
/* Not static because it's used in inverse square root. */
decaf_word_t gf_eq(const gf a, const gf b);
decaf_word_t gf_eq(const gf a, const gf b) {
gf c;
gf_sub(c,a,b);
gf_strong_reduce(c);
decaf_word_t ret=0;
for (unsigned int i=0; i<sizeof(c->limb)/sizeof(c->limb[0]); i++) {
ret |= c->limb[i];
}
return word_is_zero(ret);
}
/** Inverse square root using addition chain. */
static decaf_bool_t
gf_isqrt_chk(gf y, const gf x, decaf_bool_t allow_zero) {
......
......@@ -8,6 +8,7 @@
* @brief Example Decaf crypto routines
*/
#include "f_field.h" /* for SER_BYTES; FUTURE: find a better way to do this? */
#include <decaf/crypto.h>
#include <string.h>
......
......@@ -14,14 +14,19 @@ f_field_h = gen_file(
#define __DECAF_%(gf_shortname)s_GF_DEFINED__ 1
#define NLIMBS (%(gf_impl_bits)d/sizeof(word_t)/8)
#define SER_BYTES ((%(gf_bits)d-1)/8 + 1)
typedef struct gf_%(gf_shortname)s_s {
word_t limb[NLIMBS];
} __attribute__((aligned(32))) gf_%(gf_shortname)s_s, gf_%(gf_shortname)s_t[1];
#define GF_LIT_LIMB_BITS %(gf_lit_limb_bits)d
#define GF_BITS %(gf_bits)d
#define ZERO gf_%(gf_shortname)s_ZERO
#define ONE gf_%(gf_shortname)s_ONE
#define MODULUS gf_%(gf_shortname)s_MODULUS
#define gf gf_%(gf_shortname)s_t
#define gf_s gf_%(gf_shortname)s_s
#define gf_eq gf_%(gf_shortname)s_eq
#define gf_copy gf_%(gf_shortname)s_copy
#define gf_add_RAW gf_%(gf_shortname)s_add_RAW
#define gf_sub_RAW gf_%(gf_shortname)s_sub_RAW
......@@ -34,7 +39,6 @@ typedef struct gf_%(gf_shortname)s_s {
#define gf_isr gf_%(gf_shortname)s_isr
#define gf_serialize gf_%(gf_shortname)s_serialize
#define gf_deserialize gf_%(gf_shortname)s_deserialize
#define MODULUS gf_%(gf_shortname)s_MODULUS
#define SQRT_MINUS_ONE P%(gf_shortname)s_SQRT_MINUS_ONE /* might not be defined */
......@@ -44,7 +48,7 @@ typedef struct gf_%(gf_shortname)s_s {
extern "C" {
#endif
const gf MODULUS;
const gf MODULUS, ZERO, ONE;
/* Defined below in f_impl.h */
static INLINE_UNUSED void gf_copy (gf out, const gf a) { *out = *a; }
......@@ -58,6 +62,7 @@ void gf_mul (gf_s *__restrict__ out, const gf a, const gf b);
void gf_mulw (gf_s *__restrict__ out, const gf a, uint64_t b);
void gf_sqr (gf_s *__restrict__ out, const gf a);
void gf_serialize (uint8_t *serial, const gf x);
mask_t gf_eq (const gf x, const gf y);
mask_t gf_deserialize (gf x, const uint8_t serial[(GF_BITS-1)/8+1]);
#ifdef __cplusplus
......
......@@ -241,4 +241,15 @@ malloc_vector(size_t size) {
}
}
/* PERF: vectorize vs unroll */
#ifdef __clang__
#if 100*__clang_major__ + __clang_minor__ > 305
#define UNROLL _Pragma("clang loop unroll(full)") // PERF TODO: vectorize?
#endif
#endif
#ifndef UNROLL
#define UNROLL
#endif
#endif /* __WORD_H__ */
......@@ -11,7 +11,7 @@
#include "field.h"
#include "constant_time.h"
const gf_25519_t P25519_SQRT_MINUS_ONE = {FIELD_LITERAL(
const gf_25519_t SQRT_MINUS_ONE = {FIELD_LITERAL(
0x61b274a0ea0b0,
0x0d5a5fc8f189d,
0x7ef5e9cbd0c60,
......@@ -22,10 +22,6 @@ const gf_25519_t P25519_SQRT_MINUS_ONE = {FIELD_LITERAL(
const gf MODULUS = {FIELD_LITERAL(
0x7ffffffffffed, 0x7ffffffffffff, 0x7ffffffffffff, 0x7ffffffffffff, 0x7ffffffffffff
)};
/* TODO put in header */
extern const gf_25519_t decaf_255_ONE;
extern mask_t decaf_255_gf_eq(const gf_25519_t a, const gf_25519_t b);
/* Guarantee: a^2 x = 0 if x = 0; else a^2 x = 1 or SQRT_MINUS_ONE; */
void gf_isr (
......@@ -44,8 +40,8 @@ void gf_isr (
st[i&1][0] = tmp2[0];
}
mask_t mask = decaf_255_gf_eq(st[1],decaf_255_ONE) | decaf_255_gf_eq(st[1],SQRT_MINUS_ONE);
mask_t mask = gf_eq(st[1],ONE) | gf_eq(st[1],SQRT_MINUS_ONE);
constant_time_select(tmp1, decaf_255_ONE, SQRT_MINUS_ONE, sizeof(tmp1), mask, 0);
constant_time_select(tmp1, ONE, SQRT_MINUS_ONE, sizeof(tmp1), mask, 0);
gf_mul(a,tmp1,st[0]);
}
/**
* @cond internal
* @file decaf_crypto.c
* @copyright
* Copyright (c) 2015-2016 Cryptography Research, Inc. \n
* Released under the MIT License. See LICENSE.txt for license information.
* @author Mike Hamburg
* @brief Generic arithmetic which has to be compiled per field.
*/
#include "field.h"
const gf ZERO = {{{0}}}, ONE = {{{1}}};
/** Serialize to wire format. */
void gf_serialize (uint8_t serial[SER_BYTES], const gf x) {
gf red;
gf_copy(red, x);
gf_strong_reduce(red);
unsigned int j=0, fill=0;
dword_t buffer = 0;
UNROLL for (unsigned int i=0; i<SER_BYTES; i++) {
if (fill < 8 && j < NLIMBS) {
buffer |= ((dword_t)red->limb[LIMBPERM(j)]) << fill;
fill += LIMB_PLACE_VALUE(LIMBPERM(j));
j++;
}
serial[i] = buffer;
fill -= 8;
buffer >>= 8;
}
}
/** Deserialize from wire format; return -1 on success and 0 on failure. */
mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES]) {
unsigned int j=0, fill=0;
dword_t buffer = 0;
dsword_t scarry = 0;
UNROLL for (unsigned int i=0; i<NLIMBS; i++) {
UNROLL while (fill < LIMB_PLACE_VALUE(LIMBPERM(i)) && j < SER_BYTES) {
buffer |= ((dword_t)serial[j]) << fill;
fill += 8;
j++;
}
x->limb[LIMBPERM(i)] = (i<NLIMBS-1) ? buffer & LIMB_MASK(LIMBPERM(i)) : buffer;
fill -= LIMB_PLACE_VALUE(LIMBPERM(i));
buffer >>= LIMB_PLACE_VALUE(LIMBPERM(i));
scarry = (scarry + x->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)]) >> (8*sizeof(word_t));
}
return word_is_zero(buffer) & ~word_is_zero(scarry);
}
/** Reduce to canonical form. */
void gf_strong_reduce (gf a) {
/* first, clear high */
gf_weak_reduce(a); /* Determined to have negligible perf impact. */
/* now the total is less than 2p */
/* compute total_value - p. No need to reduce mod p. */
dsword_t scarry = 0;
for (unsigned int i=0; i<NLIMBS; i++) {
scarry = scarry + a->limb[LIMBPERM(i)] - MODULUS->limb[LIMBPERM(i)];
a->limb[i] = scarry & LIMB_MASK(LIMBPERM(i));
scarry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
/* uncommon case: it was >= p, so now scarry = 0 and this = x
* 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));
word_t scarry_0 = scarry;
dword_t carry = 0;
/* add it back */
for (unsigned int i=0; i<NLIMBS; i++) {
carry = carry + a->limb[LIMBPERM(i)] + (scarry_0 & MODULUS->limb[LIMBPERM(i)]);
a->limb[i] = carry & LIMB_MASK(LIMBPERM(i));
carry >>= LIMB_PLACE_VALUE(LIMBPERM(i));
}
assert(word_is_zero(carry + scarry_0));
}
/** Compare a==b */
mask_t gf_eq(const gf a, const gf b) {
gf c;
gf_sub(c,a,b);
gf_strong_reduce(c);
mask_t ret=0;
for (unsigned int i=0; i<sizeof(c->limb)/sizeof(c->limb[0]); i++) {
ret |= c->limb[i];
}
return word_is_zero(ret);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment