From 5311dd5863db11cf52f5ceb84280ebc65a36908a Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Wed, 27 Jan 2016 18:43:24 -0800 Subject: [PATCH] auto-gen more field arithmetic data --- Makefile | 12 +-- src/curve_ed25519/curve_data.inc.c | 40 ---------- src/curve_ed448goldilocks/curve_data.inc.c | 34 --------- src/gen_headers/curve_data.py | 88 ++++++++++++++++------ src/gen_headers/curve_data_inc_c.py | 44 +++++++++++ src/gen_headers/f_field_h.py | 15 +++- src/gen_headers/main.py | 3 +- src/p25519/f_arithmetic.c | 12 --- src/p448/f_arithmetic.c | 53 ++++++------- src/per_field.c | 2 - 10 files changed, 156 insertions(+), 147 deletions(-) delete mode 100644 src/curve_ed25519/curve_data.inc.c delete mode 100644 src/curve_ed448goldilocks/curve_data.inc.c create mode 100644 src/gen_headers/curve_data_inc_c.py diff --git a/Makefile b/Makefile index ef69d8a..79e9c99 100644 --- a/Makefile +++ b/Makefile @@ -78,7 +78,7 @@ GEN_HEADERS=\ HEADERS= Makefile $(shell find src test -name "*.h") $(BUILD_OBJ)/timestamp $(GEN_HEADERS) # components needed by the lib -LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/decaf_crypto_ed25519.o $(BUILD_OBJ)/decaf_crypto_ed448goldilocks.o # and per-field components +LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/decaf_crypto_curve25519.o $(BUILD_OBJ)/decaf_crypto_ed448goldilocks.o # and per-field components BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o @@ -167,24 +167,24 @@ $$(BUILD_C)/decaf_tables_$(1).c: $$(BUILD_IBIN)/decaf_gen_tables_$(1) $$(BUILD_ASM)/decaf_tables_$(1).s: $$(BUILD_C)/decaf_tables_$(1).c $$(HEADERS) $$(CC) $$(CFLAGS) -S -c -o $$@ $$< \ - -I src/curve_$(1)/ -I src/$(2) -I src/$(2)/$$(ARCH_FOR_$(2)) -I src/include/$$(ARCH_FOR_$(2)) \ + -I build/obj/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)) $$(BUILD_ASM)/decaf_gen_tables_$(1).s: src/decaf_gen_tables.c $$(HEADERS) $$(CC) $$(CFLAGS) \ - -I src/curve_$(1) -I src/$(2) -I src/$(2)/$$(ARCH_FOR_$(2)) -I src/include/$$(ARCH_FOR_$(2)) \ + -I build/obj/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 $$@ $$< $$(BUILD_ASM)/decaf_$(1).s: src/decaf.c $$(HEADERS) $$(CC) $$(CFLAGS) \ - -I src/curve_$(1)/ -I src/$(2) -I src/$(2)/$$(ARCH_FOR_$(2)) -I src/include/$$(ARCH_FOR_$(2)) \ + -I build/obj/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 $$@ $$< $$(BUILD_ASM)/decaf_crypto_$(1).s: src/decaf_crypto.c $$(HEADERS) $$(CC) $$(CFLAGS) \ - -I src/curve_$(1)/ -I src/$(2) -I src/$(2)/$$(ARCH_FOR_$(2)) -I src/include/$$(ARCH_FOR_$(2)) \ + -I build/obj/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 $$@ $$< @@ -194,7 +194,7 @@ endef ################################################################ # call code above to generate curves and fields $(eval $(call define_field,p25519,arch_x86_64)) -$(eval $(call define_curve,ed25519,p25519)) +$(eval $(call define_curve,curve25519,p25519)) $(eval $(call define_field,p448,arch_x86_64)) $(eval $(call define_curve,ed448goldilocks,p448)) diff --git a/src/curve_ed25519/curve_data.inc.c b/src/curve_ed25519/curve_data.inc.c deleted file mode 100644 index e9b302a..0000000 --- a/src/curve_ed25519/curve_data.inc.c +++ /dev/null @@ -1,40 +0,0 @@ -#define API_NAME "decaf_255" -#define API_NS(_id) decaf_255_##_id -#define API_NS2(_pref,_id) _pref##_decaf_255_##_id - - -#define SCALAR_LIMBS DECAF_255_SCALAR_LIMBS -#define SCALAR_BITS DECAF_255_SCALAR_BITS -#define scalar_t decaf_255_scalar_t -#define point_t decaf_255_point_t -#define precomputed_s decaf_255_precomputed_s -#define IMAGINE_TWIST 1 -#define P_MOD_8 5 -#define COFACTOR 8 - -#ifndef DECAF_JUST_API -static const int EDWARDS_D = -121665; - -static const scalar_t sc_p = {{{ - SC_LIMB(0x5812631a5cf5d3ed), - SC_LIMB(0x14def9dea2f79cd6), - SC_LIMB(0), - SC_LIMB(0x1000000000000000) -}}}; - -#ifdef GEN_TABLES -/* sqrt(9) = 3 from the curve spec. Not exported, but used by pregen tool. */ -static const unsigned char base_point_ser_for_pregen[SER_BYTES] = { - 3,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 -}; -#endif - -static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL( - 0x6db8831bbddec, - 0x38d7b56c9c165, - 0x016b221394bdc, - 0x7540f7816214a, - 0x0a0d85b4032b1 -)}; - -#endif /* DECAF_JUST_API */ diff --git a/src/curve_ed448goldilocks/curve_data.inc.c b/src/curve_ed448goldilocks/curve_data.inc.c deleted file mode 100644 index 89b0cd0..0000000 --- a/src/curve_ed448goldilocks/curve_data.inc.c +++ /dev/null @@ -1,34 +0,0 @@ -#define API_NAME "decaf_448" -#define API_NS(_id) decaf_448_##_id -#define API_NS2(_pref,_id) _pref##_decaf_448_##_id - -#define SCALAR_LIMBS DECAF_448_SCALAR_LIMBS -#define SCALAR_BITS DECAF_448_SCALAR_BITS -#define scalar_t decaf_448_scalar_t -#define point_t decaf_448_point_t -#define precomputed_s decaf_448_precomputed_s -#define IMAGINE_TWIST 0 -#define P_MOD_8 7 -#define COFACTOR 4 - -#ifndef DECAF_JUST_API -static const int EDWARDS_D = -39081; - -static const scalar_t sc_p = {{{ - SC_LIMB(0x2378c292ab5844f3), - SC_LIMB(0x216cc2728dc58f55), - SC_LIMB(0xc44edb49aed63690), - SC_LIMB(0xffffffff7cca23e9), - SC_LIMB(0xffffffffffffffff), - SC_LIMB(0xffffffffffffffff), - SC_LIMB(0x3fffffffffffffff) -}}}; - -#ifdef GEN_TABLES -/* sqrt(5) = 2phi-1 from the curve spec. Not exported, but used by pregen tool. */ -static const unsigned char base_point_ser_for_pregen[SER_BYTES] = { - -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,1 -}; -#endif - -#endif /* DECAF_JUST_API */ diff --git a/src/gen_headers/curve_data.py b/src/gen_headers/curve_data.py index dad82ad..a458e85 100644 --- a/src/gen_headers/curve_data.py +++ b/src/gen_headers/curve_data.py @@ -19,16 +19,50 @@ curve_data = { "name" : "Iso-Ed25519", "cofactor" : 8, "field" : "p25519", - "scalar_bits" : 253 + "scalar_bits" : 253, + "d": -121665, + "trace": -0xa6f7cef517bce6b2c09318d2e7ae9f7a, + "mont_base": 9 }, "Ed448" : { "name" : "Ed448-Goldilocks", "cofactor" : 4, "field" : "p448", - "scalar_bits" : 446 + "scalar_bits" : 446, + "d": -39081, + "trace": 0x10cd77058eec492d944a725bf7a4cf635c8e9c2ab721cf5b5529eec34, + "mont_base": 5 } } +def ser(x,bits,paren=None): + out = "" + mask = 2**bits - 1 + first = True + while x > 0 or first: + desc = "0x%0*x" % ((bits+3)//4,x&mask) + if paren is not None: + desc = "%s(%s)" % (paren,desc) + if not first: out += ", " + out += desc + x = x >> bits + first = False + return out + +def msqrt(x,p,hi_bit_clear = True): + if p % 4 == 3: ret = pow(x,(p+1)//4,p) + elif p % 8 == 5: + for u in xrange(1,1000): + if pow(u,(p-1)//2,p) != 1: break + u = pow(u,(p-1)//4,p) + ret = pow(x,(p+3)//8,p) + if pow(ret,2,p) != (x % p): ret = (ret * u) % p + else: raise Exception("sqrt only for 3-mod-4 or 5-mod-8") + + if (ret**2-x) % p != 0: raise Exception("No sqrt") + if hi_bit_clear and ret > p//2: ret = p-ret + return ret + def ceil_log2(x): out = 0 cmp = 1 @@ -38,9 +72,10 @@ def ceil_log2(x): return out for field,data in field_data.iteritems(): - if "modulus" not in data: data["modulus"] = eval(data["gf_desc"].replace("^","**")) + + data["p_mod_8"] = data["modulus"] % 8 if "gf_bits" not in data: data["gf_bits"] = ceil_log2(data["modulus"]) @@ -52,41 +87,52 @@ for field,data in field_data.iteritems(): data["x_priv_bytes"] = (data["gf_bits"]-1)//8 + 1 if "x_priv_bits" not in data: - data["x_priv_bits"] = ceil_log2(data["modulus"]*0.99) + data["x_priv_bits"] = ceil_log2(data["modulus"]*0.99) # not per curve at least in 7748 + + data["ser_modulus"] = ser(data["modulus"], data["gf_lit_limb_bits"]) + if data["modulus"] % 4 == 1: data["sqrt_minus_one"] = ser(msqrt(-1,data["modulus"]), data["gf_lit_limb_bits"]) + else: data["sqrt_minus_one"] = "/* NONE */" for curve,data in curve_data.iteritems(): for key in field_data[data["field"]]: if key not in data: data[key] = field_data[data["field"]][key] - + + if "iso_to" not in data: data["iso_to"] = data["name"] if "cxx_ns" not in data: data["cxx_ns"] = data["name"].replace("-","") - if "modulus_type" not in data: - mod = data["modulus"] - ptwo = 2 - while mod % ptwo == 1: - ptwo *= 2 - data["modulus_type"] = mod % ptwo + if "c_filename" not in data: + data["c_filename"] = data["iso_to"].replace("-","").lower() + + mod = data["modulus"] + ptwo = 2 + while mod % ptwo == 1: + ptwo *= 2 + data["modulus_type"] = mod % ptwo + + if "imagine_twist" not in data: + if data["modulus_type"] == 3: data["imagine_twist"] = 0 + else: data["imagine_twist"] = 1 + + data["q"] = (data["modulus"]+1-data["trace"]) // data["cofactor"] + data["bits"] = ceil_log2(data["modulus"]) + data["decaf_base"] = ser(msqrt(data["mont_base"],data["modulus"]),8) + data["scalar_p"] = ser(data["q"],64,"SC_LIMB") - if "bits" not in data: - data["bits"] = ceil_log2(data["modulus"]) + if data["cofactor"] > 4: data["sqrt_one_minus_d"] = ser(msqrt(1-data["d"],data["modulus"]),data["gf_lit_limb_bits"]) + else: data["sqrt_one_minus_d"] = "/* NONE */" if "shortname" not in data: data["shortname"] = str(data["bits"]) if "c_ns" not in data: data["c_ns"] = "decaf_" + data["shortname"] + data["C_NS"] = data["c_ns"].upper() - if "ser_bytes" not in data: - data["ser_bytes"] = (data["bits"]-2)//8 + 1 - - if "scalar_ser_bytes" not in data: - data["scalar_ser_bytes"] = (data["scalar_bits"]-1)//8 + 1 + data["ser_bytes"] = (data["bits"]-2)//8 + 1 # TODO: split for decaf vs non-decaf + data["scalar_ser_bytes"] = (data["scalar_bits"]-1)//8 + 1 - if "C_NS" not in data: - data["C_NS"] = data["c_ns"].upper() - diff --git a/src/gen_headers/curve_data_inc_c.py b/src/gen_headers/curve_data_inc_c.py new file mode 100644 index 0000000..84dde82 --- /dev/null +++ b/src/gen_headers/curve_data_inc_c.py @@ -0,0 +1,44 @@ +from gen_file import gen_file + +curve_data_inc_c = gen_file( + public = False, + per = "curve", + name = "curve_%(c_filename)s/curve_data.inc.c", + doc = """@brief Curve data for %(name)s.""", + code = """ +#define API_NAME "%(c_ns)s" +#define API_NS(_id) %(c_ns)s_##_id +#define API_NS2(_pref,_id) _pref##_%(c_ns)s_##_id + +#define SCALAR_BITS %(C_NS)s_SCALAR_BITS + +#ifndef DECAF_JUST_API + +#define SCALAR_LIMBS %(C_NS)s_SCALAR_LIMBS +#define scalar_t API_NS(scalar_t) +#define point_t API_NS(point_t) +#define precomputed_s API_NS(precomputed_s) +#define IMAGINE_TWIST %(imagine_twist)d +#define COFACTOR %(cofactor)d + +static const int EDWARDS_D = %(d)d; + +static const scalar_t sc_p = {{{ + %(scalar_p)s +}}}; + +#ifdef GEN_TABLES +/* Not exported, but used by pregen tool. */ +static const unsigned char base_point_ser_for_pregen[SER_BYTES] = { + %(decaf_base)s +}; +#endif + +#if COFACTOR==8 + static const gf SQRT_ONE_MINUS_D = {FIELD_LITERAL( + %(sqrt_one_minus_d)s + )}; +#endif + +#endif /* DECAF_JUST_API */ +""") \ No newline at end of file diff --git a/src/gen_headers/f_field_h.py b/src/gen_headers/f_field_h.py index 03267e4..abc29d6 100644 --- a/src/gen_headers/f_field_h.py +++ b/src/gen_headers/f_field_h.py @@ -55,8 +55,6 @@ typedef struct gf_%(gf_shortname)s_s { extern "C" { #endif -const gf MODULUS, ZERO, ONE; - /* Defined below in f_impl.h */ static INLINE_UNUSED void gf_copy (gf out, const gf a) { *out = *a; } static INLINE_UNUSED void gf_add_RAW (gf out, const gf a, const gf b); @@ -82,8 +80,21 @@ mask_t gf_deserialize (gf x, const uint8_t serial[(GF_BITS-1)/8+1]); #include "f_impl.h" /* Bring in the inline implementations */ +static const gf MODULUS = {FIELD_LITERAL( + %(ser_modulus)s +)}; + +#define P_MOD_8 %(p_mod_8)d +#if P_MOD_8 == 5 + static const gf SQRT_MINUS_ONE = {FIELD_LITERAL( /* TODO make not static */ + %(sqrt_minus_one)s + )}; +#endif + #ifndef LIMBPERM #define LIMBPERM(i) (i) #endif #define LIMB_MASK(i) (((1ull)<" % name @@ -110,7 +111,7 @@ decaf_root_hxx = gen_file( for name,(public,code) in gend_files.iteritems(): - _,_,name_suffix = name.partition(".") + _,_,name_suffix = name.rpartition(".") prefix = prefixes[(public,name_suffix)] if not os.path.exists(os.path.dirname(prefix + "/" + name)): os.makedirs(os.path.dirname(prefix + "/" + name)) diff --git a/src/p25519/f_arithmetic.c b/src/p25519/f_arithmetic.c index 65dab48..8fe653f 100644 --- a/src/p25519/f_arithmetic.c +++ b/src/p25519/f_arithmetic.c @@ -11,18 +11,6 @@ #include "field.h" #include "constant_time.h" -const gf SQRT_MINUS_ONE = {FIELD_LITERAL( - 0x61b274a0ea0b0, - 0x0d5a5fc8f189d, - 0x7ef5e9cbd0c60, - 0x78595a6804c9e, - 0x2b8324804fc1d -)}; - -const gf MODULUS = {FIELD_LITERAL( - 0x7ffffffffffed, 0x7ffffffffffff, 0x7ffffffffffff, 0x7ffffffffffff, 0x7ffffffffffff -)}; - /* Guarantee: a^2 x = 0 if x = 0; else a^2 x = 1 or SQRT_MINUS_ONE; */ void gf_isr (gf a, const gf x) { gf st[3], tmp1, tmp2; diff --git a/src/p448/f_arithmetic.c b/src/p448/f_arithmetic.c index d631c81..9912e8c 100644 --- a/src/p448/f_arithmetic.c +++ b/src/p448/f_arithmetic.c @@ -10,39 +10,34 @@ #include "field.h" -const gf MODULUS = {FIELD_LITERAL( - 0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff, - 0xfffffffffffffe, 0xffffffffffffff, 0xffffffffffffff, 0xffffffffffffff -)}; - void gf_isr ( gf a, const gf x ) { gf L0, L1, L2; - gf_sqr ( L1, x ); - gf_mul ( L2, x, L1 ); - gf_sqr ( L1, L2 ); - gf_mul ( L2, x, L1 ); - gf_sqrn ( L1, L2, 3 ); - gf_mul ( L0, L2, L1 ); - gf_sqrn ( L1, L0, 3 ); - gf_mul ( L0, L2, L1 ); - gf_sqrn ( L2, L0, 9 ); - gf_mul ( L1, L0, L2 ); - gf_sqr ( L0, L1 ); - gf_mul ( L2, x, L0 ); - gf_sqrn ( L0, L2, 18 ); - gf_mul ( L2, L1, L0 ); - gf_sqrn ( L0, L2, 37 ); - gf_mul ( L1, L2, L0 ); - gf_sqrn ( L0, L1, 37 ); - gf_mul ( L1, L2, L0 ); - gf_sqrn ( L0, L1, 111 ); - gf_mul ( L2, L1, L0 ); - gf_sqr ( L0, L2 ); - gf_mul ( L1, x, L0 ); - gf_sqrn ( L0, L1, 223 ); - gf_mul ( a, L2, L0 ); + gf_sqr (L1, x ); + gf_mul (L2, x, L1 ); + gf_sqr (L1, L2 ); + gf_mul (L2, x, L1 ); + gf_sqrn (L1, L2, 3 ); + gf_mul (L0, L2, L1 ); + gf_sqrn (L1, L0, 3 ); + gf_mul (L0, L2, L1 ); + gf_sqrn (L2, L0, 9 ); + gf_mul (L1, L0, L2 ); + gf_sqr (L0, L1 ); + gf_mul (L2, x, L0 ); + gf_sqrn (L0, L2, 18 ); + gf_mul (L2, L1, L0 ); + gf_sqrn (L0, L2, 37 ); + gf_mul (L1, L2, L0 ); + gf_sqrn (L0, L1, 37 ); + gf_mul (L1, L2, L0 ); + gf_sqrn (L0, L1, 111 ); + gf_mul (L2, L1, L0 ); + gf_sqr (L0, L2 ); + gf_mul (L1, x, L0 ); + gf_sqrn (L0, L1, 223 ); + gf_mul ( a, L2, L0 ); } diff --git a/src/per_field.c b/src/per_field.c index 16030a6..c76be14 100644 --- a/src/per_field.c +++ b/src/per_field.c @@ -10,8 +10,6 @@ #include "field.h" -const gf ZERO = {{{0}}}, ONE = {{{ [LIMBPERM(0)] = 1 }}}; - /** Serialize to wire format. */ void gf_serialize (uint8_t serial[SER_BYTES], const gf x) { gf red;