@@ -66,18 +66,20 @@ HEADERS= Makefile $(shell find . -name "*.h") build/timestamp | |||||
LIBCOMPONENTS= build/goldilocks.o build/barrett_field.o build/crandom.o \ | LIBCOMPONENTS= build/goldilocks.o build/barrett_field.o build/crandom.o \ | ||||
build/$(FIELD).o build/ec_point.o build/scalarmul.o build/sha512.o build/magic.o \ | build/$(FIELD).o build/ec_point.o build/scalarmul.o build/sha512.o build/magic.o \ | ||||
build/f_arithmetic.o build/arithmetic.o build/decaf.o build/shake.o | |||||
build/f_arithmetic.o build/arithmetic.o | |||||
DECAFCOMPONENTS= build/decaf.o build/shake.o build/decaf_crypto.o | |||||
TESTCOMPONENTS=build/test.o build/test_scalarmul.o build/test_sha512.o \ | TESTCOMPONENTS=build/test.o build/test_scalarmul.o build/test_sha512.o \ | ||||
build/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o \ | build/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o \ | ||||
build/shake.o | build/shake.o | ||||
BENCHCOMPONENTS=build/bench.o build/shake.o | |||||
BENCHCOMPONENTS = build/bench.o build/shake.o | |||||
BATBASE=ed448goldilocks-bats-$(TODAY) | BATBASE=ed448goldilocks-bats-$(TODAY) | ||||
BATNAME=build/$(BATBASE) | BATNAME=build/$(BATBASE) | ||||
all: lib build/test build/bench build/shakesum | |||||
all: lib decaf_lib build/test build/bench build/shakesum | |||||
scan: clean | scan: clean | ||||
scan-build --use-analyzer=`which clang` \ | scan-build --use-analyzer=`which clang` \ | ||||
@@ -85,10 +87,10 @@ scan: clean | |||||
-enable-checker osx -enable-checker security -enable-checker unix \ | -enable-checker osx -enable-checker security -enable-checker unix \ | ||||
make build/bench build/test build/goldilocks.so | make build/bench build/test build/goldilocks.so | ||||
build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) | |||||
build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) $(DECAFCOMPONENTS) | |||||
$(LD) $(LDFLAGS) -o $@ $^ | $(LD) $(LDFLAGS) -o $@ $^ | ||||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) | |||||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | |||||
$(LD) $(LDFLAGS) -o $@ $^ -lgmp | $(LD) $(LDFLAGS) -o $@ $^ -lgmp | ||||
build/shakesum: build/shakesum.o build/shake.o | build/shakesum: build/shakesum.o build/shake.o | ||||
@@ -96,6 +98,8 @@ build/shakesum: build/shakesum.o build/shake.o | |||||
lib: build/goldilocks.so | lib: build/goldilocks.so | ||||
decaf_lib: build/decaf.so | |||||
build/goldilocks.so: $(LIBCOMPONENTS) | build/goldilocks.so: $(LIBCOMPONENTS) | ||||
rm -f $@ | rm -f $@ | ||||
ifeq ($(UNAME),Darwin) | ifeq ($(UNAME),Darwin) | ||||
@@ -107,6 +111,17 @@ else | |||||
ln -sf `basename $@` build/goldilocks.so.1 | ln -sf `basename $@` build/goldilocks.so.1 | ||||
endif | endif | ||||
build/decaf.so: $(DECAFCOMPONENTS) | |||||
rm -f $@ | |||||
ifeq ($(UNAME),Darwin) | |||||
libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ | |||||
$(DECAFCOMPONENTS) | |||||
else | |||||
$(LD) $(LDFLAGS) -shared -Wl,-soname,goldilocks.so.1 -Wl,--gc-sections -o $@ $(DECAFCOMPONENTS) | |||||
strip --discard-all $@ | |||||
ln -sf `basename $@` build/goldilocks.so.1 | |||||
endif | |||||
build/timestamp: | build/timestamp: | ||||
mkdir -p build | mkdir -p build | ||||
touch $@ | touch $@ | ||||
@@ -1,10 +1,11 @@ | |||||
/* Copyright (c) 2015 Cryptography Research, Inc. | |||||
* Released under the MIT License. See LICENSE.txt for license information. | |||||
*/ | |||||
/** | /** | ||||
* @file decaf.h | * @file decaf.h | ||||
* @author Mike Hamburg | * @author Mike Hamburg | ||||
* | |||||
* @copyright | |||||
* Copyright (c) 2015 Cryptography Research, Inc. \n | |||||
* Released under the MIT License. See LICENSE.txt for license information. | |||||
* | |||||
* @brief A group of prime order p. | * @brief A group of prime order p. | ||||
* | * | ||||
* The Decaf library implements cryptographic operations on a an elliptic curve | * The Decaf library implements cryptographic operations on a an elliptic curve | ||||
@@ -24,6 +25,7 @@ | |||||
#define __DECAF_448_H__ 1 | #define __DECAF_448_H__ 1 | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <sys/types.h> | |||||
/* Goldilocks' build flags default to hidden and stripping executables. */ | /* Goldilocks' build flags default to hidden and stripping executables. */ | ||||
/** @cond internal */ | /** @cond internal */ | ||||
@@ -113,18 +115,30 @@ extern "C" { | |||||
/** | /** | ||||
* @brief Read a scalar from wire format or from bytes. | * @brief Read a scalar from wire format or from bytes. | ||||
* | * | ||||
* Return DECAF_SUCCESS if the scalar was in reduced form. This | |||||
* function is not WARN_UNUSED because eg challenges in signatures | |||||
* may need to be longer. | |||||
* | |||||
* TODO: create a decode long function, and make this WARN_UNUSED. | |||||
* | |||||
* @param [in] ser Serialized form of a scalar. | * @param [in] ser Serialized form of a scalar. | ||||
* @param [out] out Deserialized form. | * @param [out] out Deserialized form. | ||||
* | |||||
* @retval DECAF_SUCCESS The scalar was correctly encoded. | |||||
* @retval DECAF_FAILURE The scalar was greater than the modulus, | |||||
* and has been reduced modulo that modulus. | |||||
*/ | */ | ||||
decaf_bool_t decaf_448_scalar_decode ( | decaf_bool_t decaf_448_scalar_decode ( | ||||
decaf_448_scalar_t s, | decaf_448_scalar_t s, | ||||
const unsigned char ser[DECAF_448_SCALAR_BYTES] | const unsigned char ser[DECAF_448_SCALAR_BYTES] | ||||
) API_VIS WARN_UNUSED NONNULL2; | |||||
/** | |||||
* @brief Read a scalar from wire format or from bytes. Reduces mod | |||||
* scalar prime. | |||||
* | |||||
* @param [in] ser Serialized form of a scalar. | |||||
* @param [in] ser_len Length of serialized form. | |||||
* @param [out] out Deserialized form. | |||||
*/ | |||||
void decaf_448_scalar_decode_long ( | |||||
decaf_448_scalar_t s, | |||||
const unsigned char *ser, | |||||
size_t ser_len | |||||
) API_VIS NONNULL2; | ) API_VIS NONNULL2; | ||||
/** | /** | ||||
@@ -416,9 +430,24 @@ void decaf_448_point_from_hash_uniform ( | |||||
decaf_448_point_t pt, | decaf_448_point_t pt, | ||||
const unsigned char hashed_data[2*DECAF_448_SER_BYTES] | const unsigned char hashed_data[2*DECAF_448_SER_BYTES] | ||||
) API_VIS NONNULL2; | ) API_VIS NONNULL2; | ||||
/** | |||||
* @brief Overwrite data with zeros. Use memset_s if available. | |||||
*/ | |||||
void decaf_bzero ( | |||||
void *data, | |||||
size_t size | |||||
) NONNULL1 API_VIS; | |||||
/** | |||||
* @brief Overwrite scalar with zeros. | |||||
*/ | |||||
void decaf_448_scalar_destroy ( | |||||
decaf_448_scalar_t scalar | |||||
) NONNULL1 API_VIS; | |||||
/* TODO: functions to invert point_from_hash?? */ | /* TODO: functions to invert point_from_hash?? */ | ||||
#undef API_VIS | #undef API_VIS | ||||
#undef WARN_UNUSED | #undef WARN_UNUSED | ||||
#undef NONNULL1 | #undef NONNULL1 | ||||
@@ -0,0 +1,108 @@ | |||||
/** | |||||
* @file decaf_crypto.h | |||||
* @copyright | |||||
* Copyright (c) 2015 Cryptography Research, Inc. \n | |||||
* Released under the MIT License. See LICENSE.txt for license information. | |||||
* @author Mike Hamburg | |||||
* @brief Decaf cyrpto routines. | |||||
* @warning Experimental! The names, parameter orders etc are likely to change. | |||||
*/ | |||||
#ifndef __DECAF_CRYPTO_H__ | |||||
#define __DECAF_CRYPTO_H__ 1 | |||||
#include "decaf.h" | |||||
#include "shake.h" | |||||
#define DECAF_448_SYMMETRIC_KEY_BYTES 32 | |||||
/** @cond internal */ | |||||
#define API_VIS __attribute__((visibility("default"))) | |||||
#define WARN_UNUSED __attribute__((warn_unused_result)) | |||||
#define NONNULL1 __attribute__((nonnull(1))) | |||||
#define NONNULL2 __attribute__((nonnull(1,2))) | |||||
#define NONNULL3 __attribute__((nonnull(1,2,3))) | |||||
#define NONNULL134 __attribute__((nonnull(1,3,4))) | |||||
#define NONNULL5 __attribute__((nonnull(1,2,3,4,5))) | |||||
/** @endcond */ | |||||
/** A symmetric key, the compressed point of a private key. */ | |||||
typedef unsigned char decaf_448_symmetric_key_t[DECAF_448_SYMMETRIC_KEY_BYTES]; | |||||
/** An encoded public key. */ | |||||
typedef unsigned char decaf_448_public_key_t[DECAF_448_SER_BYTES]; | |||||
/** A private key. */ | |||||
typedef struct { | |||||
decaf_448_symmetric_key_t sym; | |||||
decaf_448_scalar_t secret_scalar; | |||||
decaf_448_public_key_t pub; | |||||
} decaf_448_private_key_t[1]; | |||||
#ifdef __cplusplus | |||||
extern "C" { | |||||
#endif | |||||
/** | |||||
* @brief Derive a key from its compressed form. | |||||
* @param [out] privkey The derived private key. | |||||
* @param [in] proto The compressed or proto-key, which must be 32 random bytes. | |||||
*/ | |||||
void decaf_448_derive_private_key ( | |||||
decaf_448_private_key_t priv, | |||||
const decaf_448_symmetric_key_t proto | |||||
) NONNULL2 API_VIS; | |||||
/** | |||||
* @brief Destroy a private key. | |||||
*/ | |||||
void decaf_448_destroy_private_key ( | |||||
decaf_448_private_key_t priv | |||||
) NONNULL1 API_VIS; | |||||
/** | |||||
* @brief Convert a private key to a public one. | |||||
* @param [out] pub The extracted private key. | |||||
* @param [in] priv The private key. | |||||
*/ | |||||
void decaf_448_private_to_public ( | |||||
decaf_448_public_key_t pub, | |||||
const decaf_448_private_key_t priv | |||||
) NONNULL2 API_VIS; | |||||
/** | |||||
* @brief Compute a Diffie-Hellman shared secret. | |||||
* | |||||
* This is an example routine; real protocols would use something | |||||
* protocol-specific. | |||||
* | |||||
* @param [out] shared A buffer to store the shared secret. | |||||
* @param [in] shared_bytes The size of the buffer. | |||||
* @param [in] my_privkey My private key. | |||||
* @param [in] your_pubkey Your public key. | |||||
* | |||||
* @retval DECAF_SUCCESS Key exchange was successful. | |||||
* @retval DECAF_FAILURE Key exchange failed. | |||||
*/ | |||||
decaf_bool_t | |||||
decaf_448_shared_secret ( | |||||
uint8_t *shared, | |||||
size_t shared_bytes, | |||||
const decaf_448_private_key_t my_privkey, | |||||
const decaf_448_public_key_t your_pubkey | |||||
) NONNULL134 WARN_UNUSED API_VIS; | |||||
#undef API_VIS | |||||
#undef WARN_UNUSED | |||||
#undef NONNULL1 | |||||
#undef NONNULL2 | |||||
#undef NONNULL3 | |||||
#undef NONNULL134 | |||||
#undef NONNULL5 | |||||
#ifdef __cplusplus | |||||
}; /* extern "C" */ | |||||
#endif | |||||
#endif /* __DECAF_CRYPTO_H__ */ | |||||
@@ -13,6 +13,7 @@ | |||||
#define __SHAKE_H__ | #define __SHAKE_H__ | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <sys/types.h> | |||||
#define API_VIS __attribute__((visibility("default"))) | #define API_VIS __attribute__((visibility("default"))) | ||||
@@ -98,7 +99,7 @@ void sponge_hash ( | |||||
sha3_output(sponge, out, outlen); \ | sha3_output(sponge, out, outlen); \ | ||||
sponge_init(sponge, SHAKE##n##_params); \ | sponge_init(sponge, SHAKE##n##_params); \ | ||||
} \ | } \ | ||||
static inline void shake##n##_hash(const uint8_t *in, size_t inlen, uint8_t *out, size_t outlen ) { \ | |||||
static inline void shake##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \ | |||||
sponge_hash(in,inlen,out,outlen,SHAKE##n##_params); \ | sponge_hash(in,inlen,out,outlen,SHAKE##n##_params); \ | ||||
} \ | } \ | ||||
static inline void shake##n##_destroy( keccak_sponge_t sponge ) { \ | static inline void shake##n##_destroy( keccak_sponge_t sponge ) { \ | ||||
@@ -117,7 +118,7 @@ void sponge_hash ( | |||||
sha3_output(sponge, out, outlen); \ | sha3_output(sponge, out, outlen); \ | ||||
sponge_init(sponge, SHA3_##n##_params); \ | sponge_init(sponge, SHA3_##n##_params); \ | ||||
} \ | } \ | ||||
static inline void sha3_##n##_hash(const uint8_t *in, size_t inlen, uint8_t *out, size_t outlen ) { \ | |||||
static inline void sha3_##n##_hash(uint8_t *out, size_t outlen, const uint8_t *in, size_t inlen) { \ | |||||
sponge_hash(in,inlen,out,outlen,SHA3_##n##_params); \ | sponge_hash(in,inlen,out,outlen,SHA3_##n##_params); \ | ||||
} \ | } \ | ||||
static inline void sha3_##n##_destroy( keccak_sponge_t sponge ) { \ | static inline void sha3_##n##_destroy( keccak_sponge_t sponge ) { \ | ||||
@@ -8,7 +8,9 @@ | |||||
* @brief Decaf high-level functions. | * @brief Decaf high-level functions. | ||||
*/ | */ | ||||
#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | |||||
#include "decaf.h" | #include "decaf.h" | ||||
#include <string.h> | |||||
#define WBITS DECAF_WORD_BITS | #define WBITS DECAF_WORD_BITS | ||||
@@ -548,6 +550,65 @@ decaf_bool_t decaf_448_scalar_decode( | |||||
return accum; | return accum; | ||||
} | } | ||||
void decaf_bzero ( | |||||
void *s, | |||||
size_t size | |||||
) { | |||||
#ifdef __STDC_LIB_EXT1__ | |||||
memset_s(s, size, 0, size); | |||||
#else | |||||
volatile uint8_t *destroy = (volatile uint8_t *)s; | |||||
unsigned i; | |||||
for (i=0; i<size; i++) { | |||||
destroy[i] = 0; | |||||
} | |||||
#endif | |||||
} | |||||
void decaf_448_scalar_destroy ( | |||||
decaf_448_scalar_t scalar | |||||
) { | |||||
decaf_bzero(scalar, sizeof(decaf_448_scalar_t)); | |||||
} | |||||
static inline void ignore_result ( decaf_bool_t boo ) { | |||||
(void)boo; | |||||
} | |||||
void decaf_448_scalar_decode_long( | |||||
decaf_448_scalar_t s, | |||||
const unsigned char *ser, | |||||
size_t ser_len | |||||
) { | |||||
if (ser_len == 0) { | |||||
decaf_448_scalar_copy(s, decaf_448_scalar_zero); | |||||
return; | |||||
} | |||||
size_t i; | |||||
unsigned char tmp[DECAF_448_SER_BYTES] = {0}; | |||||
decaf_448_scalar_t t1, t2; | |||||
i = ser_len - (ser_len%DECAF_448_SER_BYTES); | |||||
if (i==ser_len) i -= DECAF_448_SER_BYTES; | |||||
memcpy(tmp, ser+i, ser_len - i); | |||||
ignore_result( decaf_448_scalar_decode(t1, tmp) ); | |||||
decaf_bzero(tmp, sizeof(tmp)); | |||||
while (i) { | |||||
i -= DECAF_448_SER_BYTES; | |||||
decaf_448_montmul(t1,t1,decaf_448_scalar_r2,decaf_448_scalar_p,DECAF_MONTGOMERY_FACTOR); | |||||
ignore_result( decaf_448_scalar_decode(t2, ser+i) ); | |||||
decaf_448_scalar_add(t1, t1, t2); | |||||
} | |||||
decaf_448_scalar_copy(s, t1); | |||||
decaf_448_scalar_destroy(t1); | |||||
decaf_448_scalar_destroy(t2); | |||||
} | |||||
void decaf_448_scalar_encode( | void decaf_448_scalar_encode( | ||||
unsigned char ser[DECAF_448_SER_BYTES], | unsigned char ser[DECAF_448_SER_BYTES], | ||||
const decaf_448_scalar_t s | const decaf_448_scalar_t s | ||||
@@ -0,0 +1,116 @@ | |||||
/** | |||||
* @cond internal | |||||
* @file decaf_crypto.c | |||||
* @copyright | |||||
* Copyright (c) 2015 Cryptography Research, Inc. \n | |||||
* Released under the MIT License. See LICENSE.txt for license information. | |||||
* @author Mike Hamburg | |||||
* @brief Decaf cyrpto routines. | |||||
*/ | |||||
#include "decaf_crypto.h" | |||||
#include <string.h> | |||||
void decaf_448_derive_private_key ( | |||||
decaf_448_private_key_t priv, | |||||
const decaf_448_symmetric_key_t proto | |||||
) { | |||||
const char *magic = "decaf_448_derive_private_key"; | |||||
keccak_sponge_t sponge; | |||||
uint8_t encoded_scalar[64]; | |||||
decaf_448_point_t pub; | |||||
shake256_init(sponge); | |||||
shake256_update(sponge, proto, sizeof(decaf_448_symmetric_key_t)); | |||||
shake256_update(sponge, (const unsigned char *)magic, strlen(magic)); | |||||
shake256_final(sponge, encoded_scalar, sizeof(encoded_scalar)); | |||||
shake256_destroy(sponge); | |||||
memcpy(priv->sym, proto, sizeof(decaf_448_symmetric_key_t)); | |||||
decaf_448_scalar_decode_long(priv->secret_scalar, encoded_scalar, sizeof(encoded_scalar)); | |||||
decaf_448_precomputed_scalarmul(pub, decaf_448_precomputed_base, priv->secret_scalar); | |||||
decaf_448_point_encode(priv->pub, pub); | |||||
decaf_bzero(encoded_scalar, sizeof(encoded_scalar)); | |||||
} | |||||
void | |||||
decaf_448_destroy_private_key ( | |||||
decaf_448_private_key_t priv | |||||
) { | |||||
decaf_bzero((void*)priv, sizeof(decaf_448_private_key_t)); | |||||
} | |||||
void decaf_448_private_to_public ( | |||||
decaf_448_public_key_t pub, | |||||
const decaf_448_private_key_t priv | |||||
) { | |||||
memcpy(pub, priv->pub, sizeof(decaf_448_public_key_t)); | |||||
} | |||||
decaf_bool_t | |||||
decaf_448_shared_secret ( | |||||
uint8_t *shared, | |||||
size_t shared_bytes, | |||||
const decaf_448_private_key_t my_privkey, | |||||
const decaf_448_public_key_t your_pubkey | |||||
) { | |||||
decaf_448_point_t point; | |||||
uint8_t ss_ser[DECAF_448_SER_BYTES]; | |||||
const char *nope = "decaf_448_ss_invalid"; | |||||
decaf_bool_t ret = decaf_448_point_decode(point, your_pubkey, DECAF_FALSE); | |||||
decaf_448_point_scalarmul(point, point, my_privkey->secret_scalar); | |||||
unsigned i; | |||||
/* Lexsort keys. Less will be -1 if mine is less, and 0 otherwise. */ | |||||
uint16_t less = 0; | |||||
for (i=0; i<DECAF_448_SER_BYTES; i++) { | |||||
uint16_t delta = my_privkey->pub[i]; | |||||
delta -= your_pubkey[i]; | |||||
/* Case: | |||||
* = -> delta = 0 -> hi delta-1 = -1, hi delta = 0 | |||||
* > -> delta > 0 -> hi delta-1 = 0, hi delta = 0 | |||||
* < -> delta < 0 -> hi delta-1 = (doesnt matter), hi delta = -1 | |||||
*/ | |||||
less &= delta-1; | |||||
less |= delta; | |||||
} | |||||
less >>= 8; | |||||
keccak_sponge_t sponge; | |||||
shake256_init(sponge); | |||||
/* update the lesser */ | |||||
for (i=0; i<sizeof(ss_ser); i++) { | |||||
ss_ser[i] = (my_privkey->pub[i] & less) | (your_pubkey[i] & ~less); | |||||
} | |||||
shake256_update(sponge, ss_ser, sizeof(ss_ser)); | |||||
/* update the greater */ | |||||
for (i=0; i<sizeof(ss_ser); i++) { | |||||
ss_ser[i] = (my_privkey->pub[i] & ~less) | (your_pubkey[i] & less); | |||||
} | |||||
shake256_update(sponge, ss_ser, sizeof(ss_ser)); | |||||
/* encode the shared secret but mask with secret key */ | |||||
decaf_448_point_encode(ss_ser, point); | |||||
/* If invalid, then replace ... */ | |||||
for (i=0; i<sizeof(ss_ser); i++) { | |||||
ss_ser[i] &= ret; | |||||
if (i < sizeof(my_privkey->sym)) { | |||||
ss_ser[i] |= my_privkey->sym[i] & ~ret; | |||||
} else if (i - sizeof(my_privkey->sym) < strlen(nope)) { | |||||
ss_ser[i] |= nope[i-sizeof(my_privkey->sym)] & ~ret; | |||||
} | |||||
} | |||||
shake256_update(sponge, ss_ser, sizeof(ss_ser)); | |||||
shake256_final(sponge, shared, shared_bytes); | |||||
shake256_destroy(sponge); | |||||
decaf_bzero(ss_ser, sizeof(ss_ser)); | |||||
return ret; | |||||
} |
@@ -197,6 +197,7 @@ void sha3_output ( | |||||
} | } | ||||
} | } | ||||
/** TODO: unify with decaf_bzero? */ | |||||
void sponge_destroy ( | void sponge_destroy ( | ||||
keccak_sponge_t sponge | keccak_sponge_t sponge | ||||
) { | ) { | ||||
@@ -17,6 +17,7 @@ | |||||
#include "goldilocks.h" | #include "goldilocks.h" | ||||
#include "sha512.h" | #include "sha512.h" | ||||
#include "decaf.h" | #include "decaf.h" | ||||
#include "decaf_crypto.h" | |||||
#include "shake.h" | #include "shake.h" | ||||
static __inline__ void | static __inline__ void | ||||
@@ -65,15 +66,6 @@ field_print_full ( | |||||
printf("\n"); | printf("\n"); | ||||
} | } | ||||
static void q448_print( const char *descr, const word_t secret[SCALAR_WORDS] ) { | |||||
int j; | |||||
printf("%s = 0x", descr); | |||||
for (j=SCALAR_WORDS-1; j>=0; j--) { | |||||
printf(PRIxWORDfull, secret[j]); | |||||
} | |||||
printf("\n"); | |||||
} | |||||
#ifndef N_TESTS_BASE | #ifndef N_TESTS_BASE | ||||
#define N_TESTS_BASE 10000 | #define N_TESTS_BASE 10000 | ||||
#endif | #endif | ||||
@@ -687,135 +679,37 @@ int main(int argc, char **argv) { | |||||
when = now() - when; | when = now() - when; | ||||
printf("ecdh pre: %5.1fµs\n", when * 1e6 / i); | printf("ecdh pre: %5.1fµs\n", when * 1e6 / i); | ||||
printf("\nTesting...\n"); | |||||
printf("\nDecaf slow:\n"); | |||||
decaf_448_symmetric_key_t sym[2] = {{0},{1}}; | |||||
decaf_448_private_key_t dpriv[2]; | |||||
decaf_448_public_key_t dpub[2]; | |||||
int failures=0, successes = 0; | |||||
for (i=0; i<nbase/10; i++) { | |||||
ignore_result(goldilocks_keygen(&gsk,&gpk)); | |||||
goldilocks_sign(sout,(const unsigned char *)message,message_len,&gsk); | |||||
res = goldilocks_verify(sout,(const unsigned char *)message,message_len,&gpk); | |||||
if (res) failures++; | |||||
} | |||||
if (failures) { | |||||
printf("FAIL %d/%d signature checks!\n", failures, i); | |||||
} | |||||
unsigned char dshared[2][32]; | |||||
failures=0; successes = 0; | |||||
for (i=0; i<nbase/10; i++) { | |||||
field_randomize(&crand, a); | |||||
word_t two = 2; | |||||
mask_t good = montgomery_ladder(b,a,&two,2,0); | |||||
if (!good) continue; | |||||
word_t x,y; | |||||
crandom_generate(&crand, (unsigned char *)&x, sizeof(x)); | |||||
crandom_generate(&crand, (unsigned char *)&y, sizeof(y)); | |||||
x = (hword_t)x; | |||||
y = (hword_t)y; | |||||
word_t z=x*y; | |||||
ignore_result(montgomery_ladder(b,a,&x,WORD_BITS,0)); | |||||
ignore_result(montgomery_ladder(c,b,&y,WORD_BITS,0)); | |||||
ignore_result(montgomery_ladder(b,a,&z,WORD_BITS,0)); | |||||
field_sub(d,b,c); | |||||
if (!field_is_zero(d)) { | |||||
printf("Odd ladder validation failure %d!\n", ++failures); | |||||
field_print("a", a); | |||||
printf("x=%"PRIxWORD", y=%"PRIxWORD", z=%"PRIxWORD"\n", x,y,z); | |||||
field_print("c", c); | |||||
field_print("b", b); | |||||
printf("\n"); | |||||
} | |||||
} | |||||
failures = 0; | |||||
when = now(); | |||||
for (i=0; i<nbase/10; i++) { | for (i=0; i<nbase/10; i++) { | ||||
mask_t good; | |||||
do { | |||||
field_randomize(&crand, a); | |||||
good = deserialize_affine(&affine, a); | |||||
} while (!good); | |||||
convert_affine_to_extensible(&exta,&affine); | |||||
twist_and_double(&ext,&exta); | |||||
untwist_and_double(&exta,&ext); | |||||
serialize_extensible(b, &exta); | |||||
untwist_and_double_and_serialize(c, &ext); | |||||
field_sub(d,b,c); | |||||
if (good && !field_is_zero(d)){ | |||||
printf("Iso+serial validation failure %d!\n", ++failures); | |||||
field_print("a", a); | |||||
field_print("b", b); | |||||
field_print("c", c); | |||||
printf("\n"); | |||||
} else if (good) { | |||||
successes ++; | |||||
} | |||||
} | |||||
if (successes < i/3) { | |||||
printf("Iso+serial variation: only %d/%d successful.\n", successes, i); | |||||
decaf_448_derive_private_key(dpriv[i&1], sym[i&1]); | |||||
} | } | ||||
when = now() - when; | |||||
printf("derive priv: %5.1fµs\n", when * 1e6 / i); | |||||
decaf_448_private_to_public(dpub[0], dpriv[0]); | |||||
decaf_448_private_to_public(dpub[1], dpriv[1]); | |||||
successes = failures = 0; | |||||
when = now(); | |||||
for (i=0; i<nbase/10; i++) { | for (i=0; i<nbase/10; i++) { | ||||
field_a_t aa; | |||||
struct tw_extensible_t exu,exv,exw; | |||||
mask_t good; | |||||
do { | |||||
field_randomize(&crand, a); | |||||
good = deserialize_affine(&affine, a); | |||||
convert_affine_to_extensible(&exta,&affine); | |||||
twist_and_double(&ext,&exta); | |||||
} while (!good); | |||||
do { | |||||
field_randomize(&crand, aa); | |||||
good = deserialize_affine(&affine, aa); | |||||
convert_affine_to_extensible(&exta,&affine); | |||||
twist_and_double(&exu,&exta); | |||||
} while (!good); | |||||
field_randomize(&crand, aa); | |||||
q448_randomize(&crand, sk); | |||||
if (i==0 || i==2) memset(&sk, 0, sizeof(sk)); | |||||
q448_randomize(&crand, tk); | |||||
if (i==0 || i==1) memset(&tk, 0, sizeof(tk)); | |||||
copy_tw_extensible(&exv, &ext); | |||||
copy_tw_extensible(&exw, &exu); | |||||
scalarmul(&exv,sk); | |||||
scalarmul(&exw,tk); | |||||
convert_tw_extensible_to_tw_pniels(&pniels, &exw); | |||||
add_tw_pniels_to_tw_extensible(&exv,&pniels); | |||||
untwist_and_double(&exta,&exv); | |||||
serialize_extensible(b, &exta); | |||||
ignore_result(precompute_fixed_base_wnaf(wnaft,&exu,5)); | |||||
linear_combo_var_fixed_vt(&ext,sk,FIELD_BITS,tk,FIELD_BITS,(const tw_niels_a_t*)wnaft,5); | |||||
untwist_and_double(&exta,&exv); | |||||
serialize_extensible(c, &exta); | |||||
field_sub(d,b,c); | |||||
if (!field_is_zero(d)){ | |||||
printf("PreWNAF combo validation failure %d!\n", ++failures); | |||||
field_print("a", a); | |||||
field_print("A", aa); | |||||
q448_print("s", sk); | |||||
q448_print("t", tk); | |||||
field_print("c", c); | |||||
field_print("b", b); | |||||
printf("\n\n"); | |||||
} else if (good) { | |||||
successes ++; | |||||
decaf_bool_t ret = decaf_448_shared_secret(dshared[i&1], 32, dpriv[i&1], dpub[(i+1)&1]); | |||||
if (ret != DECAF_SUCCESS) { | |||||
printf("BUG: shared secret returns failure on %d.\n", i); | |||||
break; | |||||
} | } | ||||
} | } | ||||
if (successes < i) { | |||||
printf("PreWNAF combo variation: only %d/%d successful.\n", successes, i); | |||||
when = now() - when; | |||||
printf("ecdh: %5.1fµs\n", when * 1e6 / i); | |||||
if (memcmp(dshared[0], dshared[1], 32)) { | |||||
printf("BUG: mismatched shared secrets\n"); | |||||
} | } | ||||
return 0; | return 0; | ||||