| @@ -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 | 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: clean | ||||
| scan-build --use-analyzer=`which clang` \ | scan-build --use-analyzer=`which clang` \ | ||||
| @@ -101,6 +101,13 @@ else | |||||
| $(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf | $(LDXX) $(LDFLAGS) -Wl,-rpath,`pwd`/$(BUILD_LIB) -o $@ $< -L$(BUILD_LIB) -ldecaf | ||||
| endif | 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. | # Internal test programs, which are not part of the final build/bin directory. | ||||
| $(BUILD_IBIN)/test_ct: $(BUILD_OBJ)/test_ct.o lib | $(BUILD_IBIN)/test_ct: $(BUILD_OBJ)/test_ct.o lib | ||||
| ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
| @@ -127,14 +127,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) { | |||||
| gf_copy(y, t2); | 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) */ | /** identity = (0,1) */ | ||||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | 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) ( | extern void API_NS(deisogenize) ( | ||||
| gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
| gf_s *__restrict__ minus_t_over_s, | |||||
| gf_s *__restrict__ altx, | |||||
| const point_t p, | const point_t p, | ||||
| mask_t toggle_hibit_s, | mask_t toggle_hibit_s, | ||||
| mask_t toggle_hibit_t_over_s, | |||||
| mask_t toggle_altx, | |||||
| mask_t toggle_rotation | mask_t toggle_rotation | ||||
| ); | ); | ||||
| @@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
| /* s@a = +-|N.e| */ | /* s@a = +-|N.e| */ | ||||
| gf_mul(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 */ | /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | ||||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | 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); | 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) */ | /** identity = (0,1) */ | ||||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | 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) ( | extern void API_NS(deisogenize) ( | ||||
| gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
| gf_s *__restrict__ minus_t_over_s, | |||||
| gf_s *__restrict__ altx, | |||||
| const point_t p, | const point_t p, | ||||
| mask_t toggle_hibit_s, | mask_t toggle_hibit_s, | ||||
| mask_t toggle_hibit_t_over_s, | |||||
| mask_t toggle_altx, | |||||
| mask_t toggle_rotation | mask_t toggle_rotation | ||||
| ); | ); | ||||
| @@ -61,7 +61,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
| /* s@a = +-|N.e| */ | /* s@a = +-|N.e| */ | ||||
| gf_mul(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 */ | /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | ||||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | 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_s gf_25519_s | ||||
| #define gf_eq gf_25519_eq | #define gf_eq gf_25519_eq | ||||
| #define gf_hibit gf_25519_hibit | #define gf_hibit gf_25519_hibit | ||||
| #define gf_lobit gf_25519_lobit | |||||
| #define gf_copy gf_25519_copy | #define gf_copy gf_25519_copy | ||||
| #define gf_add gf_25519_add | #define gf_add gf_25519_add | ||||
| #define gf_sub gf_25519_sub | #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); | 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_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_eq (const gf x, const gf y); | ||||
| mask_t gf_lobit (const gf x); | |||||
| mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | 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 -(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. */ | /** 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) { | mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | ||||
| unsigned int j=0, fill=0; | unsigned int j=0, fill=0; | ||||
| @@ -38,6 +38,7 @@ typedef struct gf_448_s { | |||||
| #define gf_s gf_448_s | #define gf_s gf_448_s | ||||
| #define gf_eq gf_448_eq | #define gf_eq gf_448_eq | ||||
| #define gf_hibit gf_448_hibit | #define gf_hibit gf_448_hibit | ||||
| #define gf_lobit gf_448_lobit | |||||
| #define gf_copy gf_448_copy | #define gf_copy gf_448_copy | ||||
| #define gf_add gf_448_add | #define gf_add gf_448_add | ||||
| #define gf_sub gf_448_sub | #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); | 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_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_eq (const gf x, const gf y); | ||||
| mask_t gf_lobit (const gf x); | |||||
| mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | 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 -(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. */ | /** 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) { | mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | ||||
| unsigned int j=0, fill=0; | unsigned int j=0, fill=0; | ||||
| @@ -58,6 +58,9 @@ struct IsoEd25519 { | |||||
| /** The name of the curve */ | /** The name of the curve */ | ||||
| static inline const char *name() { return "Iso-Ed25519"; } | 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) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
| static const int REMOVED_COFACTOR = 8; | static const int REMOVED_COFACTOR = 8; | ||||
| @@ -58,6 +58,9 @@ struct Ed448Goldilocks { | |||||
| /** The name of the curve */ | /** The name of the curve */ | ||||
| static inline const char *name() { return "Ed448-Goldilocks"; } | 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) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
| static const int REMOVED_COFACTOR = 4; | static const int REMOVED_COFACTOR = 4; | ||||
| @@ -116,14 +116,6 @@ gf_invert(gf y, const gf x, int assert_nonzero) { | |||||
| gf_copy(y, t2); | 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) */ | /** identity = (0,1) */ | ||||
| const point_t API_NS(point_identity) = {{{{{0}}},{{{1}}},{{{1}}},{{{0}}}}}; | 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) ( | extern void API_NS(deisogenize) ( | ||||
| gf_s *__restrict__ s, | gf_s *__restrict__ s, | ||||
| gf_s *__restrict__ minus_t_over_s, | |||||
| gf_s *__restrict__ altx, | |||||
| const point_t p, | const point_t p, | ||||
| mask_t toggle_hibit_s, | mask_t toggle_hibit_s, | ||||
| mask_t toggle_hibit_t_over_s, | |||||
| mask_t toggle_altx, | |||||
| mask_t toggle_rotation | mask_t toggle_rotation | ||||
| ); | ); | ||||
| @@ -50,7 +50,7 @@ void API_NS(point_from_hash_nonuniform) ( | |||||
| /* s@a = +-|N.e| */ | /* s@a = +-|N.e| */ | ||||
| gf_mul(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 */ | /* t@b = -+ cN(r-1)((a-2d)e)^2 - 1 */ | ||||
| gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | gf_mulw(c,e,1-2*EDWARDS_D); /* (a-2d)e */ | ||||
| @@ -45,6 +45,9 @@ struct $(cxx_ns) { | |||||
| /** The name of the curve */ | /** The name of the curve */ | ||||
| static inline const char *name() { return "$(name)"; } | 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) */ | /** The curve's cofactor (removed, but useful for testing) */ | ||||
| static const int REMOVED_COFACTOR = $(cofactor); | 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_s gf_$(gf_shortname)_s | ||||
| #define gf_eq gf_$(gf_shortname)_eq | #define gf_eq gf_$(gf_shortname)_eq | ||||
| #define gf_hibit gf_$(gf_shortname)_hibit | #define gf_hibit gf_$(gf_shortname)_hibit | ||||
| #define gf_lobit gf_$(gf_shortname)_lobit | |||||
| #define gf_copy gf_$(gf_shortname)_copy | #define gf_copy gf_$(gf_shortname)_copy | ||||
| #define gf_add gf_$(gf_shortname)_add | #define gf_add gf_$(gf_shortname)_add | ||||
| #define gf_sub gf_$(gf_shortname)_sub | #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); | 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_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_eq (const gf x, const gf y); | ||||
| mask_t gf_lobit (const gf x); | |||||
| mask_t gf_hibit (const gf x); | mask_t gf_hibit (const gf x); | ||||
| void gf_serialize (uint8_t *serial, const gf x,int with_highbit); | 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 -(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. */ | /** 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) { | mask_t gf_deserialize (gf x, const uint8_t serial[SER_BYTES], int with_hibit) { | ||||
| unsigned int j=0, fill=0; | 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; | |||||
| } | |||||