| @@ -85,7 +85,7 @@ LIBCOMPONENTS = $(BUILD_OBJ)/utils.o $(BUILD_OBJ)/shake.o $(BUILD_OBJ)/sha512.o | |||
| BENCHCOMPONENTS = $(BUILD_OBJ)/bench.o $(BUILD_OBJ)/shake.o | |||
| all: lib $(BUILD_IBIN)/test $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum | |||
| all: lib $(BUILD_IBIN)/test $(BUILD_BIN)/ristretto $(BUILD_IBIN)/bench $(BUILD_BIN)/shakesum | |||
| scan: clean | |||
| scan-build --use-analyzer=`which clang` \ | |||
| @@ -101,6 +101,13 @@ else | |||
| $(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf | |||
| endif | |||
| $(BUILD_BIN)/ristretto: $(BUILD_OBJ)/ristretto.o lib | |||
| ifeq ($(UNAME),Darwin) | |||
| $(LDXX) $(LDFLAGS) -o $@ $< -L$(BUILD_LIB) -ldecaf | |||
| else | |||
| $(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf | |||
| endif | |||
| # Internal test programs, which are not part of the final build/bin directory. | |||
| $(BUILD_IBIN)/test_ct: $(BUILD_OBJ)/test_ct.o lib | |||
| ifeq ($(UNAME),Darwin) | |||
| @@ -127,14 +127,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) { | |||
| gf_copy(y, t2); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| static mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** identity = (0,1) */ | |||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | |||
| @@ -25,10 +25,10 @@ static const int EDWARDS_D = -121665; | |||
| extern void API_NS(deisogenize) ( | |||
| gf_s *__restrict__ s, | |||
| gf_s *__restrict__ minus_t_over_s, | |||
| gf_s *__restrict__ altx, | |||
| const point_t p, | |||
| mask_t toggle_hibit_s, | |||
| mask_t toggle_hibit_t_over_s, | |||
| mask_t toggle_altx, | |||
| mask_t toggle_rotation | |||
| ); | |||
| @@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||
| /* s@a = +-|N.e| */ | |||
| gf_mul(a,N,e); | |||
| gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */ | |||
| gf_cond_neg(a,gf_lobit(a) ^ ~square); | |||
| /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | |||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | |||
| @@ -127,14 +127,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) { | |||
| gf_copy(y, t2); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| static mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** identity = (0,1) */ | |||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | |||
| @@ -25,10 +25,10 @@ static const int EDWARDS_D = -39081; | |||
| extern void API_NS(deisogenize) ( | |||
| gf_s *__restrict__ s, | |||
| gf_s *__restrict__ minus_t_over_s, | |||
| gf_s *__restrict__ altx, | |||
| const point_t p, | |||
| mask_t toggle_hibit_s, | |||
| mask_t toggle_hibit_t_over_s, | |||
| mask_t toggle_altx, | |||
| mask_t toggle_rotation | |||
| ); | |||
| @@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||
| /* s@a = +-|N.e| */ | |||
| gf_mul(a,N,e); | |||
| gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */ | |||
| gf_cond_neg(a,gf_lobit(a) ^ ~square); | |||
| /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | |||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | |||
| @@ -38,6 +38,7 @@ typedef struct gf_25519_s { | |||
| #define gf_s gf_25519_s | |||
| #define gf_eq gf_25519_eq | |||
| #define gf_hibit gf_25519_hibit | |||
| #define gf_lobit gf_25519_lobit | |||
| #define gf_copy gf_25519_copy | |||
| #define gf_add gf_25519_add | |||
| #define gf_sub gf_25519_sub | |||
| @@ -81,6 +82,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b); | |||
| void gf_sqr (gf_s *__restrict__ out, const gf a); | |||
| mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ | |||
| mask_t gf_eq (const gf x, const gf y); | |||
| mask_t gf_lobit (const gf x); | |||
| mask_t gf_hibit (const gf x); | |||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | |||
| @@ -52,6 +52,14 @@ mask_t gf_hibit(const gf x) { | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Deserialize from wire format; return -1 on success and 0 on failure. */ | |||
| mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | |||
| unsigned int j=0, fill=0; | |||
| @@ -38,6 +38,7 @@ typedef struct gf_448_s { | |||
| #define gf_s gf_448_s | |||
| #define gf_eq gf_448_eq | |||
| #define gf_hibit gf_448_hibit | |||
| #define gf_lobit gf_448_lobit | |||
| #define gf_copy gf_448_copy | |||
| #define gf_add gf_448_add | |||
| #define gf_sub gf_448_sub | |||
| @@ -81,6 +82,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b); | |||
| void gf_sqr (gf_s *__restrict__ out, const gf a); | |||
| mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ | |||
| mask_t gf_eq (const gf x, const gf y); | |||
| mask_t gf_lobit (const gf x); | |||
| mask_t gf_hibit (const gf x); | |||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | |||
| @@ -52,6 +52,14 @@ mask_t gf_hibit(const gf x) { | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Deserialize from wire format; return -1 on success and 0 on failure. */ | |||
| mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | |||
| unsigned int j=0, fill=0; | |||
| @@ -58,6 +58,9 @@ struct IsoEd25519 { | |||
| /** The name of the curve */ | |||
| static inline const char *name() { return "Iso-Ed25519"; } | |||
| /** The name of the curve */ | |||
| static inline int bits() { return 255; } | |||
| /** The curve's cofactor (removed, but useful for testing) */ | |||
| static const int REMOVED_COFACTOR = 8; | |||
| @@ -58,6 +58,9 @@ struct Ed448Goldilocks { | |||
| /** The name of the curve */ | |||
| static inline const char *name() { return "Ed448-Goldilocks"; } | |||
| /** The name of the curve */ | |||
| static inline int bits() { return 448; } | |||
| /** The curve's cofactor (removed, but useful for testing) */ | |||
| static const int REMOVED_COFACTOR = 4; | |||
| @@ -116,14 +116,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) { | |||
| gf_copy(y, t2); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| static mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** identity = (0,1) */ | |||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | |||
| @@ -14,10 +14,10 @@ static const int EDWARDS_D = $(d); | |||
| extern void API_NS(deisogenize) ( | |||
| gf_s *__restrict__ s, | |||
| gf_s *__restrict__ minus_t_over_s, | |||
| gf_s *__restrict__ altx, | |||
| const point_t p, | |||
| mask_t toggle_hibit_s, | |||
| mask_t toggle_hibit_t_over_s, | |||
| mask_t toggle_altx, | |||
| mask_t toggle_rotation | |||
| ); | |||
| @@ -50,7 +50,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||
| /* s@a = +-|N.e| */ | |||
| gf_mul(a,N,e); | |||
| gf_cond_neg(a,gf_hibit(a)^square); /* NB this is - what is listed in the paper */ | |||
| gf_cond_neg(a,gf_lobit(a) ^ ~square); | |||
| /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | |||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | |||
| @@ -45,6 +45,9 @@ struct $(cxx_ns) { | |||
| /** The name of the curve */ | |||
| static inline const char *name() { return "$(name)"; } | |||
| /** The name of the curve */ | |||
| static inline int bits() { return $(gf_bits); } | |||
| /** The curve's cofactor (removed, but useful for testing) */ | |||
| static const int REMOVED_COFACTOR = $(cofactor); | |||
| @@ -23,6 +23,7 @@ typedef struct gf_$(gf_shortname)_s { | |||
| #define gf_s gf_$(gf_shortname)_s | |||
| #define gf_eq gf_$(gf_shortname)_eq | |||
| #define gf_hibit gf_$(gf_shortname)_hibit | |||
| #define gf_lobit gf_$(gf_shortname)_lobit | |||
| #define gf_copy gf_$(gf_shortname)_copy | |||
| #define gf_add gf_$(gf_shortname)_add | |||
| #define gf_sub gf_$(gf_shortname)_sub | |||
| @@ -66,6 +67,7 @@ void gf_mulw_unsigned (gf_s *__restrict__ out, const gf a, uint32_t b); | |||
| void gf_sqr (gf_s *__restrict__ out, const gf a); | |||
| mask_t gf_isr(gf a, const gf x); /** a^2 x = 1, QNR, or 0 if x=0. Return true if successful */ | |||
| mask_t gf_eq (const gf x, const gf y); | |||
| mask_t gf_lobit (const gf x); | |||
| mask_t gf_hibit (const gf x); | |||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | |||
| @@ -41,6 +41,14 @@ mask_t gf_hibit(const gf x) { | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Return high bit of x = low bit of 2x mod p */ | |||
| mask_t gf_lobit(const gf x) { | |||
| gf y; | |||
| gf_copy(y,x); | |||
| gf_strong_reduce(y); | |||
| return -(y->limb[0]&1); | |||
| } | |||
| /** Deserialize from wire format; return -1 on success and 0 on failure. */ | |||
| mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | |||
| unsigned int j=0, fill=0; | |||
| @@ -0,0 +1,161 @@ | |||
| /** | |||
| * @file ristretto.cxx | |||
| * @author Mike Hamburg | |||
| * | |||
| * @copyright | |||
| * Copyright (c) 2015 Cryptography Research, Inc. \n | |||
| * Released under the MIT License. See LICENSE.txt for license information. | |||
| * | |||
| * @brief Ristretto implementation widget | |||
| */ | |||
| #include <decaf.hxx> | |||
| #include <stdio.h> | |||
| using namespace decaf; | |||
| inline int hexi(char c) { | |||
| if (c >= '0' && c < '9') return c-'0'; | |||
| if (c >= 'a' && c < 'f') return c-'a'+0xa; | |||
| if (c >= 'A' && c < 'F') return c-'A'+0xa; | |||
| return -1; | |||
| } | |||
| int parsehex(uint8_t *out, size_t sizeof_out, const char *hex) { | |||
| size_t l = strlen(hex); | |||
| if (l%2 != 0) { | |||
| fprintf(stderr,"String should be hex, but has odd length\n: %s\n", hex); | |||
| return -1; | |||
| } else if (l/2 > sizeof_out) { | |||
| fprintf(stderr,"Argument is too long: %s\n", hex); | |||
| return -1; | |||
| } | |||
| memset(out,0,sizeof_out); | |||
| int ret1,ret2; | |||
| for (size_t i=0; i<l/2; i++) { | |||
| if ( (ret1 = hexi(hex[2*i ])) < 0 | |||
| || (ret2 = hexi(hex[2*i+1])) < 0) { | |||
| fprintf(stderr,"Invalid hex %s\n",hex); | |||
| return -1; | |||
| } | |||
| out[i] = ret1*16+ret2; | |||
| } | |||
| return 0; | |||
| } | |||
| void printhex(const uint8_t *in, size_t sizeof_in) { | |||
| for (; sizeof_in > 0; in++,sizeof_in--) { | |||
| printf("%02x",*in); | |||
| } | |||
| } | |||
| static int g_argc = 0; | |||
| static char **g_argv = NULL; | |||
| static int error = 0; | |||
| static int done = 0; | |||
| void usage() { | |||
| const char *me=g_argv[0]; | |||
| if (!me) me = "ristretto"; | |||
| for (unsigned i=0; g_argv[0][i]; i++) { | |||
| if (g_argv[0][i] == '/' && g_argv[0][i+1] != 0 && g_argv[0][i+1] != '/') { | |||
| me = &g_argv[0][i]; | |||
| } | |||
| } | |||
| fprintf(stderr,"Usage: %s [points] [operations] ...\n", me); | |||
| fprintf(stderr," -b 255|448: Set which group to use (sometimes inferred from lengths)\n"); | |||
| fprintf(stderr,"\n"); | |||
| fprintf(stderr," Ways to create points:\n"); | |||
| fprintf(stderr," [hex]: Point from point data as hex\n"); | |||
| fprintf(stderr," -e [hex]: Create point by hashing to curve using elligator\n"); | |||
| fprintf(stderr," base: Base point of curve\n"); | |||
| fprintf(stderr,"\n"); | |||
| fprintf(stderr," Operations:\n"); | |||
| fprintf(stderr," -n [point]: negative of point\n"); | |||
| fprintf(stderr," -s [scalar] * [point]: Hash to curve using elligator\n"); | |||
| fprintf(stderr," [point] + [point]: Add two poitns\n"); | |||
| fprintf(stderr,"\n"); | |||
| fprintf(stderr," NB: this is a debugging widget. It doesn't yet have order of operations.\n"); | |||
| fprintf(stderr," *** DON'T USE THIS UTILITY FOR ACTUAL CRYPTO! ***\n"); | |||
| fprintf(stderr," It's only for debugging!\n"); | |||
| fprintf(stderr,"\n"); | |||
| exit(-2); | |||
| } | |||
| template<typename Group> class Run { | |||
| public: | |||
| static void run() { | |||
| uint8_t tmp[Group::Point::SER_BYTES]; | |||
| typename Group::Point a,b; | |||
| typename Group::Scalar s; | |||
| bool plus=false, empty=true, elligator=false, mul=false, scalar=false, scalarempty=true, neg=false; | |||
| if (done || error) return; | |||
| for (int i=1; i<g_argc && !error; i++) { | |||
| bool point = false; | |||
| if (!strcmp(g_argv[i],"-b") && ++i<g_argc) { | |||
| if (atoi(g_argv[i]) == Group::bits()) continue; | |||
| else return; | |||
| } else if (!strcmp(g_argv[i],"+")) { | |||
| if (elligator || scalar || empty) usage(); | |||
| plus = true; | |||
| } else if (!strcmp(g_argv[i],"-n")) { | |||
| neg = !neg; | |||
| } else if (!strcmp(g_argv[i],"*")) { | |||
| if (elligator || scalar || scalarempty) usage(); | |||
| mul = true; | |||
| } else if (!strcmp(g_argv[i],"-s")) { | |||
| if (elligator || scalar || !scalarempty) usage(); | |||
| scalar = true; | |||
| } else if (!strcmp(g_argv[i],"-e")) { | |||
| if (elligator || scalar) usage(); | |||
| elligator = true; | |||
| } else if (!strcmp(g_argv[i],"base")) { | |||
| if (elligator || scalar) usage(); | |||
| b = b.base(); | |||
| point = true; | |||
| } else if ((strlen(g_argv[i]) == 2*sizeof(tmp) | |||
| || ((scalar || elligator) && strlen(g_argv[i]) <= 2*sizeof(tmp))) | |||
| && !(error=parsehex(tmp,sizeof(tmp),g_argv[i]))) { | |||
| if (scalar) { | |||
| s = Block(tmp,sizeof(tmp)); scalar=false; scalarempty=false; | |||
| } else if (elligator) { | |||
| point = true; | |||
| b.set_to_hash(Block(tmp,sizeof(tmp))); elligator=false; | |||
| } else if (DECAF_SUCCESS != b.decode(Block(tmp,sizeof(tmp)))) { | |||
| fprintf(stderr,"Error: %s isn't in the group\n",g_argv[i]); | |||
| error = -1; | |||
| } else { | |||
| point = true; | |||
| } | |||
| } else if (error || !empty) usage(); | |||
| if (point) { | |||
| if (neg) { b = -b; neg = false; } | |||
| if (mul) { b *= s; mul=false; } | |||
| if (empty) { a = b; empty=false; } | |||
| else if (plus) { a += b; plus=false; } | |||
| else usage(); | |||
| } | |||
| } | |||
| if (!error && !empty) { | |||
| a.serialize_into(tmp); | |||
| printhex(tmp,sizeof(tmp)); | |||
| printf("\n"); | |||
| done = true; | |||
| } | |||
| } | |||
| }; | |||
| int main(int argc, char **argv) { | |||
| g_argc = argc; | |||
| g_argv = argv; | |||
| run_for_all_curves<Run>(); | |||
| if (!done) usage(); | |||
| return (error<0) ? -error : error; | |||
| } | |||