@@ -66,18 +66,20 @@ HEADERS= Makefile $(shell find . -name "*.h") build/timestamp | |||
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/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 \ | |||
build/test_pointops.o build/test_arithmetic.o build/test_goldilocks.o build/magic.o \ | |||
build/shake.o | |||
BENCHCOMPONENTS=build/bench.o build/shake.o | |||
BENCHCOMPONENTS = build/bench.o build/shake.o | |||
BATBASE=ed448goldilocks-bats-$(TODAY) | |||
BATNAME=build/$(BATBASE) | |||
all: lib build/test build/bench build/shakesum | |||
all: lib decaf_lib build/test build/bench build/shakesum | |||
scan: clean | |||
scan-build --use-analyzer=`which clang` \ | |||
@@ -85,10 +87,10 @@ scan: clean | |||
-enable-checker osx -enable-checker security -enable-checker unix \ | |||
make build/bench build/test build/goldilocks.so | |||
build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) | |||
build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) $(DECAFCOMPONENTS) | |||
$(LD) $(LDFLAGS) -o $@ $^ | |||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) | |||
build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) | |||
$(LD) $(LDFLAGS) -o $@ $^ -lgmp | |||
build/shakesum: build/shakesum.o build/shake.o | |||
@@ -96,6 +98,8 @@ build/shakesum: build/shakesum.o build/shake.o | |||
lib: build/goldilocks.so | |||
decaf_lib: build/decaf.so | |||
build/goldilocks.so: $(LIBCOMPONENTS) | |||
rm -f $@ | |||
ifeq ($(UNAME),Darwin) | |||
@@ -107,6 +111,17 @@ else | |||
ln -sf `basename $@` build/goldilocks.so.1 | |||
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: | |||
mkdir -p build | |||
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 | |||
* @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. | |||
* | |||
* The Decaf library implements cryptographic operations on a an elliptic curve | |||
@@ -24,6 +25,7 @@ | |||
#define __DECAF_448_H__ 1 | |||
#include <stdint.h> | |||
#include <sys/types.h> | |||
/* Goldilocks' build flags default to hidden and stripping executables. */ | |||
/** @cond internal */ | |||
@@ -113,18 +115,30 @@ extern "C" { | |||
/** | |||
* @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 [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_448_scalar_t s, | |||
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; | |||
/** | |||
@@ -416,9 +430,24 @@ void decaf_448_point_from_hash_uniform ( | |||
decaf_448_point_t pt, | |||
const unsigned char hashed_data[2*DECAF_448_SER_BYTES] | |||
) 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?? */ | |||
#undef API_VIS | |||
#undef WARN_UNUSED | |||
#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__ | |||
#include <stdint.h> | |||
#include <sys/types.h> | |||
#define API_VIS __attribute__((visibility("default"))) | |||
@@ -98,7 +99,7 @@ void sponge_hash ( | |||
sha3_output(sponge, out, outlen); \ | |||
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); \ | |||
} \ | |||
static inline void shake##n##_destroy( keccak_sponge_t sponge ) { \ | |||
@@ -117,7 +118,7 @@ void sponge_hash ( | |||
sha3_output(sponge, out, outlen); \ | |||
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); \ | |||
} \ | |||
static inline void sha3_##n##_destroy( keccak_sponge_t sponge ) { \ | |||
@@ -8,7 +8,9 @@ | |||
* @brief Decaf high-level functions. | |||
*/ | |||
#define __STDC_WANT_LIB_EXT1__ 1 /* for memset_s */ | |||
#include "decaf.h" | |||
#include <string.h> | |||
#define WBITS DECAF_WORD_BITS | |||
@@ -548,6 +550,65 @@ decaf_bool_t decaf_448_scalar_decode( | |||
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( | |||
unsigned char ser[DECAF_448_SER_BYTES], | |||
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 ( | |||
keccak_sponge_t sponge | |||
) { | |||
@@ -17,6 +17,7 @@ | |||
#include "goldilocks.h" | |||
#include "sha512.h" | |||
#include "decaf.h" | |||
#include "decaf_crypto.h" | |||
#include "shake.h" | |||
static __inline__ void | |||
@@ -65,15 +66,6 @@ field_print_full ( | |||
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 | |||
#define N_TESTS_BASE 10000 | |||
#endif | |||
@@ -687,135 +679,37 @@ int main(int argc, char **argv) { | |||
when = now() - when; | |||
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++) { | |||
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++) { | |||
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; | |||