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