@@ -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; | |||
} |