From f18cf359c67a519e976e808a6746b3b8d06a5477 Mon Sep 17 00:00:00 2001 From: Michael Hamburg Date: Thu, 23 Apr 2015 13:55:42 -0700 Subject: [PATCH] remove files used by goldilocks/master, leaving only decaf --- Makefile | 71 +- include/goldilocks.h | 380 ----------- include/ridinghood.h | 376 ----------- src/arithmetic.c | 87 --- src/barrett_field.c | 349 ---------- src/bat/api_dh.h | 8 +- src/bat/api_sign.h | 6 +- src/bat/dh.c | 27 +- src/bat/sign.c | 45 +- src/crandom.c | 488 -------------- src/decaf_crypto.c | 1 - src/ec_point.c | 1222 ----------------------------------- src/goldilocks.c | 576 ----------------- src/include/barrett_field.h | 190 ------ src/include/config.h | 76 --- src/include/crandom.h | 143 ---- src/include/ec_point.h | 697 -------------------- src/include/intrinsics.h | 276 -------- src/include/magic.h | 95 --- src/include/scalarmul.h | 373 ----------- src/include/sha512.h | 49 -- src/p448/arch_x86_64/p448.h | 2 +- src/p448/f_arithmetic.c | 2 +- src/p448/f_magic.h | 30 - src/p448/magic.c | 81 --- src/p480/f_arithmetic.c | 2 +- src/p480/f_magic.h | 30 - src/p480/magic.c | 68 -- src/p521/f_arithmetic.c | 2 +- src/p521/f_magic.h | 30 - src/p521/magic.c | 111 ---- src/scalarmul.c | 987 ---------------------------- src/sha512.c | 177 ----- test/bench.c | 780 ---------------------- test/test.c | 152 ----- test/test.h | 51 -- test/test_arithmetic.c | 392 ----------- test/test_goldilocks.c | 195 ------ test/test_pointops.c | 648 ------------------- test/test_scalarmul.c | 480 -------------- test/test_sha512.c | 270 -------- 41 files changed, 61 insertions(+), 9964 deletions(-) delete mode 100644 include/goldilocks.h delete mode 100644 include/ridinghood.h delete mode 100644 src/arithmetic.c delete mode 100644 src/barrett_field.c delete mode 100644 src/crandom.c delete mode 100644 src/ec_point.c delete mode 100644 src/goldilocks.c delete mode 100644 src/include/barrett_field.h delete mode 100644 src/include/config.h delete mode 100644 src/include/crandom.h delete mode 100644 src/include/ec_point.h delete mode 100644 src/include/intrinsics.h delete mode 100644 src/include/magic.h delete mode 100644 src/include/scalarmul.h delete mode 100644 src/include/sha512.h delete mode 100644 src/p448/f_magic.h delete mode 100644 src/p448/magic.c delete mode 100644 src/p480/f_magic.h delete mode 100644 src/p480/magic.c delete mode 100644 src/p521/f_magic.h delete mode 100644 src/p521/magic.c delete mode 100644 src/scalarmul.c delete mode 100644 src/sha512.c delete mode 100644 test/bench.c delete mode 100644 test/test.c delete mode 100644 test/test.h delete mode 100644 test/test_arithmetic.c delete mode 100644 test/test_goldilocks.c delete mode 100644 test/test_pointops.c delete mode 100644 test/test_scalarmul.c delete mode 100644 test/test_sha512.c diff --git a/Makefile b/Makefile index f68c23c..3c31f2d 100644 --- a/Makefile +++ b/Makefile @@ -28,7 +28,7 @@ endif FIELD ?= p448 WARNFLAGS = -pedantic -Wall -Wextra -Werror -Wunreachable-code \ - -Wmissing-declarations -Wunused-function -Wno-overlength-strings $(EXWARN) + -Wmissing-declarations -Wunused-function $(EXWARN) INCFLAGS = -Isrc/include -Iinclude -Isrc/$(FIELD) -Isrc/$(FIELD)/$(ARCH) @@ -55,26 +55,17 @@ ifeq ($(CC),clang) WARNFLAGS += -Wgcc-compat endif -ifeq (,$(findstring 64,$(ARCH))$(findstring gcc,$(CC))) -# ARCHFLAGS += -m32 -XCFLAGS += -DGOLDI_FORCE_32_BIT=1 -endif - ARCHFLAGS += $(XARCHFLAGS) CFLAGS = $(LANGFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCFLAGS) CXXFLAGS = $(LANGXXFLAGS) $(WARNFLAGS) $(INCFLAGS) $(OFLAGS) $(ARCHFLAGS) $(GENFLAGS) $(XCXXFLAGS) LDFLAGS = $(ARCHFLAGS) $(XLDFLAGS) ASFLAGS = $(ARCHFLAGS) $(XASFLAGS) -.PHONY: clean all test bench test_decaf bench_decaf todo doc lib bat +.PHONY: clean all test bench todo doc lib bat .PRECIOUS: build/%.s HEADERS= Makefile $(shell find . -name "*.h") $(shell find . -name "*.hxx") 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 - DECAFCOMPONENTS= build/$(DECAF).o build/shake.o build/decaf_crypto.o \ build/$(FIELD).o build/f_arithmetic.o # TODO @@ -82,19 +73,12 @@ ifeq ($(DECAF),decaf_fast) DECAFCOMPONENTS += build/decaf_tables.o endif -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 - -TESTDECAFCOMPONENTS=build/test_decaf.o -BENCHDECAFCOMPONENTS=build/bench_decaf.o - BENCHCOMPONENTS = build/bench.o build/shake.o -BATBASE=ed448goldilocks-bats-$(TODAY) +BATBASE=ed448goldilocks-decaf-bats-$(TODAY) BATNAME=build/$(BATBASE) -all: lib decaf_lib build/test build/bench build/shakesum +all: lib build/test build/bench build/shakesum scan: clean scan-build --use-analyzer=`which clang` \ @@ -102,36 +86,16 @@ scan: clean -enable-checker osx -enable-checker security -enable-checker unix \ make build/bench build/test all -build/bench: $(LIBCOMPONENTS) $(BENCHCOMPONENTS) $(DECAFCOMPONENTS) - $(LD) $(LDFLAGS) -o $@ $^ - -build/test: $(LIBCOMPONENTS) $(TESTCOMPONENTS) $(DECAFCOMPONENTS) - $(LD) $(LDFLAGS) -o $@ $^ -lgmp - -build/test_decaf: $(TESTDECAFCOMPONENTS) decaf_lib - $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -Wl,-rpath=`pwd`/build -ldecaf +build/test: build/test_decaf.o lib + $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -ldecaf -build/bench_decaf: $(BENCHDECAFCOMPONENTS) decaf_lib - $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -Wl,-rpath=`pwd`/build -ldecaf +build/bench: build/bench_decaf.o lib + $(LDXX) $(LDFLAGS) -o $@ $< -Lbuild -ldecaf build/shakesum: build/shakesum.o build/shake.o $(LD) $(LDFLAGS) -o $@ $^ -lib: build/libgoldilocks.so - -decaf_lib: build/libdecaf.so - -build/libgoldilocks.so: $(LIBCOMPONENTS) - rm -f $@ -ifeq ($(UNAME),Darwin) - libtool -macosx_version_min 10.6 -dynamic -dead_strip -lc -x -o $@ \ - $(LIBCOMPONENTS) -else - $(LD) $(LDFLAGS) -shared -Wl,-soname,libgoldilocks.so.1 -Wl,--gc-sections -o $@ $(LIBCOMPONENTS) - strip --discard-all $@ - ln -sf `basename $@` build/libgoldilocks.so.1 -endif - +lib: build/libdecaf.so build/libdecaf.so: $(DECAFCOMPONENTS) rm -f $@ @@ -190,18 +154,17 @@ bat: $(BATNAME) $(BATNAME): include/* src/* src/*/* test/batarch.map rm -fr $@ for prim in dh sign; do \ - targ="$@/crypto_$$prim/ed448goldilocks"; \ + targ="$@/crypto_$$prim/ed448goldilocks-decaf"; \ (while read arch where; do \ mkdir -p $$targ/`basename $$arch`; \ cp include/*.h src/*.c src/include/*.h src/bat/$$prim.c src/p448/$$where/*.c src/p448/$$where/*.h src/p448/*.c src/p448/*.h $$targ/`basename $$arch`; \ cp src/bat/api_$$prim.h $$targ/`basename $$arch`/api.h; \ - perl -p -i -e 's/.*endif.*GOLDILOCKS_CONFIG_H/#define SUPERCOP_WONT_LET_ME_OPEN_FILES 1\n\n$$&/' $$targ/`basename $$arch`/config.h; \ perl -p -i -e 's/SYSNAME/'`basename $(BATNAME)`_`basename $$arch`'/g' $$targ/`basename $$arch`/api.h; \ perl -p -i -e 's/__TODAY__/'$(TODAY)'/g' $$targ/`basename $$arch`/api.h; \ done \ ) < test/batarch.map; \ echo 'Mike Hamburg' > $$targ/designers; \ - echo 'Ed448-Goldilocks sign and dh' > $$targ/description; \ + echo 'Ed448-Goldilocks Decaf sign and dh' > $$targ/description; \ done (cd build && tar czf $(BATBASE).tgz $(BATBASE) ) @@ -223,17 +186,11 @@ todo:: bench: build/bench ./$< -test: build/test test_decaf +test: build/test build/test -test_decaf: build/test_decaf - build/test_decaf - -bench_decaf: build/bench_decaf - build/bench_decaf - -microbench_decaf: build/bench_decaf - build/bench_decaf --micro +microbench: build/bench + ./$< --micro clean: rm -fr build doc $(BATNAME) diff --git a/include/goldilocks.h b/include/goldilocks.h deleted file mode 100644 index e4d4496..0000000 --- a/include/goldilocks.h +++ /dev/null @@ -1,380 +0,0 @@ -/* Copyright (c) 2014-2015 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -/** - * @file goldilocks.h - * @author Mike Hamburg - * @brief Goldilocks high-level functions. - */ -#ifndef __GOLDILOCKS_H__ -#define __GOLDILOCKS_H__ 1 - -#include - -#ifndef GOLDI_IMPLEMENT_PRECOMPUTED_KEYS -/** If nonzero, implement precomputation for verify and ECDH. */ -#define GOLDI_IMPLEMENT_PRECOMPUTED_KEYS 1 -#endif - -#ifndef GOLDI_IMPLEMENT_SIGNATURES -/** If nonzero, implement signatures. */ -#define GOLDI_IMPLEMENT_SIGNATURES 1 -#endif - -/** The size of the Goldilocks field, in bits. - * Ifdef'd so you can override when testing experimental Ed480-Ridinghood or E-521. - */ -#ifndef GOLDI_FIELD_BITS -#define GOLDI_FIELD_BITS 448 -#endif - -/** The size of the Goldilocks scalars, in bits. */ -#define GOLDI_SCALAR_BITS (GOLDI_FIELD_BITS-2) - -/** The same size, in bytes. */ -#define GOLDI_FIELD_BYTES ((GOLDI_FIELD_BITS+7)/8) - -/** The size of a Goldilocks public key, in bytes. */ -#define GOLDI_PUBLIC_KEY_BYTES GOLDI_FIELD_BYTES - -/** The extra bytes in a Goldilocks private key for the symmetric key. */ -#define GOLDI_SYMKEY_BYTES 32 - -/** The size of a shared secret. */ -#define GOLDI_SHARED_SECRET_BYTES 64 - -/** The size of a Goldilocks private key, in bytes. */ -#define GOLDI_PRIVATE_KEY_BYTES (2*GOLDI_FIELD_BYTES + GOLDI_SYMKEY_BYTES) - -/** The size of a Goldilocks signature, in bytes. */ -#define GOLDI_SIGNATURE_BYTES (2*GOLDI_FIELD_BYTES) - -/** - * @brief Serialized form of a Goldilocks public key. - * - * @warning This isn't even my final form! - */ -struct goldilocks_public_key_t { - uint8_t opaque[GOLDI_PUBLIC_KEY_BYTES]; /**< Serialized data. */ -}; - -/** - * @brief Serialized form of a Goldilocks private key. - * - * Contains 56 bytes of actual private key, 56 bytes of - * public key, and 32 bytes of symmetric key for randomization. - * - * @warning This isn't even my final form! - */ -struct goldilocks_private_key_t { - uint8_t opaque[GOLDI_PRIVATE_KEY_BYTES]; /**< Serialized data. */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief No error. */ -static const int GOLDI_EOK = 0; - -/** @brief Error: your key or other state is corrupt. */ -static const int GOLDI_ECORRUPT = 44801; - -/** @brief Error: other party's key is corrupt. */ -static const int GOLDI_EINVAL = 44802; - -/** @brief Error: not enough entropy. */ -static const int GOLDI_ENODICE = 44804; - -/** @brief Error: you need to initialize the library first. */ -static const int GOLDI_EUNINIT = 44805; - -/** @brief Error: called init() but we are already initialized. */ -static const int GOLDI_EALREADYINIT = 44805; - -/** - * @brief Initialize Goldilocks' precomputed tables and - * random number generator. This function must be called before - * any of the other Goldilocks routines (except - * goldilocks_shared_secret in the current version) and should be - * called only once per process. - * - * There is currently no way to tear down this state. It is possible - * that a future version of this library will not require this function. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EALREADYINIT Already initialized. - * @retval GOLDI_ECORRUPT Memory is corrupted, or another thread is already init'ing. - * @retval Nonzero An error occurred. - */ -int -goldilocks_init (void) -__attribute__((warn_unused_result,visibility ("default"))); - - -/** - * @brief Generate a new random keypair. - * @param [out] privkey The generated private key. - * @param [out] pubkey The generated public key. - * - * @warning This isn't even my final form! - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ENODICE Insufficient entropy. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_keygen ( - struct goldilocks_private_key_t *privkey, - struct goldilocks_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2),visibility ("default"))); - -/** - * @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. - * - * @warning This isn't even my final form! - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_derive_private_key ( - struct goldilocks_private_key_t *privkey, - const unsigned char proto[GOLDI_SYMKEY_BYTES] -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Compress a private key (by copying out the proto-key) - * @param [out] proto The proto-key. - * @param [in] privkey The private key. - * - * @warning This isn't even my final form! - * @todo test. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -void -goldilocks_underive_private_key ( - unsigned char proto[GOLDI_SYMKEY_BYTES], - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Extract the public key from a private key. - * - * This is essentially a memcpy from the public part of the privkey. - * - * @param [out] pubkey The extracted private key. - * @param [in] privkey The private key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT The private key is corrupt. - */ -int -goldilocks_private_to_public ( - struct goldilocks_public_key_t *pubkey, - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Generate a Diffie-Hellman shared secret in constant time. - * - * This function uses some compile-time flags whose merit remains to - * be decided. - * - * If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes - * of zeros to the secret before hashing. In the case that the other - * party's key is detectably corrupt, instead the symmetric part - * of the secret key is used to produce a pseudorandom value. - * - * If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of - * the two parties' public keys is prepended to the hash. - * - * In the current version, this function can safely be run even without - * goldilocks_init(). But this property is not guaranteed for future - * versions, so call it anyway. - * - * @warning This isn't even my final form! - * - * @param [out] shared The shared secret established with the other party. - * @param [in] my_privkey My private key. - * @param [in] your_pubkey The other party's public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EINVAL The other party's key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_shared_secret ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_public_key_t *your_pubkey -) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default"))); - -#if GOLDI_IMPLEMENT_SIGNATURES -/** - * @brief Sign a message. - * - * The signature is deterministic, using the symmetric secret found in the - * secret key to form a nonce. - * - * The technique used in signing is a modified Schnorr system, like EdDSA. - * - * @warning This isn't even my final form! - * - * @param [out] signature_out Space for the output signature. - * @param [in] message The message to be signed. - * @param [in] message_len The length of the message to be signed. - * @param [in] privkey My private key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_sign ( - uint8_t signature_out[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2,4),visibility ("default"))); - -/** - * @brief Verify a signature. - * - * This function is fairly strict. It will correctly detect when - * the signature has the wrong cofactor component, or when the sig - * values aren't less than p or q. - * - * Currently this function does not detect when the public key is weird, - * eg 0, has cofactor, etc. As a result, a party with a bogus public - * key could create signatures that succeed on some systems and fail on - * others. - * - * @warning This isn't even my final form! - * - * @param [in] signature The signature. - * @param [in] message The message to be verified. - * @param [in] message_len The length of the message to be verified. - * @param [in] pubkey The signer's public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EINVAL The public key or signature is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_verify ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default"))); -#endif - -#if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS - -/** A public key which has been expanded by precomputation for higher speed. */ -struct goldilocks_precomputed_public_key_t; - -/** - * @brief Expand a public key by precomputation. - * - * @todo Give actual error returns, instead of ambiguous NULL. - * - * @warning This isn't even my final form! - * - * @param [in] pub The public key. - * @retval NULL We ran out of memory, or the - */ -struct goldilocks_precomputed_public_key_t * -goldilocks_precompute_public_key ( - const struct goldilocks_public_key_t *pub -) __attribute__((warn_unused_result,nonnull(1),visibility ("default"))); - -/** - * @brief Overwrite an expanded public key with zeros, then destroy it. - * - * If the input is NULL, this function does nothing. - * - * @param [in] precom The public key. - */ -void -goldilocks_destroy_precomputed_public_key ( - struct goldilocks_precomputed_public_key_t *precom -) __attribute__((visibility ("default"))); - -/** - * @brief Verify a signature. - * - * This function is fairly strict. It will correctly detect when - * the signature has the wrong cofactor component, or when the sig - * values aren't less than p or q. - * - * @warning This isn't even my final form! - * - * @param [in] signature The signature. - * @param [in] message The message to be verified. - * @param [in] message_len The length of the message to be verified. - * @param [in] pubkey The signer's public key, expanded by precomputation. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EINVAL The public key or signature is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_verify_precomputed ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_precomputed_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default"))); - -/** - * @brief Generate a Diffie-Hellman shared secret in constant time. - * Uses a precomputation on the other party's public key for efficiency. - * - * This function uses some compile-time flags whose merit remains to - * be decided. - * - * If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes - * of zeros to the secret before hashing. In the case that the other - * party's key is detectably corrupt, instead the symmetric part - * of the secret key is used to produce a pseudorandom value. - * - * If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of - * the two parties' public keys is prepended to the hash. - * - * In the current version, this function can safely be run even without - * goldilocks_init(). But this property is not guaranteed for future - * versions, so call it anyway. - * - * @warning This isn't even my final form! - * - * @param [out] shared The shared secret established with the other party. - * @param [in] my_privkey My private key. - * @param [in] your_pubkey The other party's precomputed public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EINVAL The other party's key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_shared_secret_precomputed ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_precomputed_public_key_t *your_pubkey -) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default"))); - -#endif /* GOLDI_IMPLEMENT_PRECOMPUTED_KEYS */ - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __GOLDILOCKS_H__ */ diff --git a/include/ridinghood.h b/include/ridinghood.h deleted file mode 100644 index 2c3919c..0000000 --- a/include/ridinghood.h +++ /dev/null @@ -1,376 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -/** - * @file goldilocks.h - * @author Mike Hamburg - * @brief Goldilocks high-level functions. - */ -#ifndef __GOLDILOCKS_H__ -#define __GOLDILOCKS_H__ 1 - -#include - -#ifndef GOLDI_IMPLEMENT_PRECOMPUTED_KEYS -/** If nonzero, implement precomputation for verify and ECDH. */ -#define GOLDI_IMPLEMENT_PRECOMPUTED_KEYS 1 -#endif - -#ifndef GOLDI_IMPLEMENT_SIGNATURES -/** If nonzero, implement signatures. */ -#define GOLDI_IMPLEMENT_SIGNATURES 1 -#endif - -/** The size of the Goldilocks field, in bits. */ -#define GOLDI_FIELD_BITS 448 - -/** The size of the Goldilocks scalars, in bits. */ -#define GOLDI_SCALAR_BITS 446 - -/** The same size, in bytes. */ -#define GOLDI_FIELD_BYTES (GOLDI_FIELD_BITS/8) - -/** The size of a Goldilocks public key, in bytes. */ -#define GOLDI_PUBLIC_KEY_BYTES GOLDI_FIELD_BYTES - -/** The extra bytes in a Goldilocks private key for the symmetric key. */ -#define GOLDI_SYMKEY_BYTES 32 - -/** The size of a shared secret. */ -#define GOLDI_SHARED_SECRET_BYTES 64 - -/** The size of a Goldilocks private key, in bytes. */ -#define GOLDI_PRIVATE_KEY_BYTES (2*GOLDI_FIELD_BYTES + GOLDI_SYMKEY_BYTES) - -/** The size of a Goldilocks signature, in bytes. */ -#define GOLDI_SIGNATURE_BYTES (2*GOLDI_FIELD_BYTES) - -/** - * @brief Serialized form of a Goldilocks public key. - * - * @warning This isn't even my final form! - */ -struct goldilocks_public_key_t { - uint8_t opaque[GOLDI_PUBLIC_KEY_BYTES]; /**< Serialized data. */ -}; - -/** - * @brief Serialized form of a Goldilocks private key. - * - * Contains 56 bytes of actual private key, 56 bytes of - * public key, and 32 bytes of symmetric key for randomization. - * - * @warning This isn't even my final form! - */ -struct goldilocks_private_key_t { - uint8_t opaque[GOLDI_PRIVATE_KEY_BYTES]; /**< Serialized data. */ -}; - -#ifdef __cplusplus -extern "C" { -#endif - -/** @brief No error. */ -static const int GOLDI_EOK = 0; - -/** @brief Error: your key or other state is corrupt. */ -static const int GOLDI_ECORRUPT = 44801; - -/** @brief Error: other party's key is corrupt. */ -static const int GOLDI_EINVAL = 44802; - -/** @brief Error: not enough entropy. */ -static const int GOLDI_ENODICE = 44804; - -/** @brief Error: you need to initialize the library first. */ -static const int GOLDI_EUNINIT = 44805; - -/** @brief Error: called init() but we are already initialized. */ -static const int GOLDI_EALREADYINIT = 44805; - -/** - * @brief Initialize Goldilocks' precomputed tables and - * random number generator. This function must be called before - * any of the other Goldilocks routines (except - * goldilocks_shared_secret in the current version) and should be - * called only once per process. - * - * There is currently no way to tear down this state. It is possible - * that a future version of this library will not require this function. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EALREADYINIT Already initialized. - * @retval GOLDI_ECORRUPT Memory is corrupted, or another thread is already init'ing. - * @retval Nonzero An error occurred. - */ -int -goldilocks_init (void) -__attribute__((warn_unused_result,visibility ("default"))); - - -/** - * @brief Generate a new random keypair. - * @param [out] privkey The generated private key. - * @param [out] pubkey The generated public key. - * - * @warning This isn't even my final form! - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ENODICE Insufficient entropy. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_keygen ( - struct goldilocks_private_key_t *privkey, - struct goldilocks_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2),visibility ("default"))); - -/** - * @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. - * - * @warning This isn't even my final form! - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_derive_private_key ( - struct goldilocks_private_key_t *privkey, - const unsigned char proto[GOLDI_SYMKEY_BYTES] -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Compress a private key (by copying out the proto-key) - * @param [out] proto The proto-key. - * @param [in] privkey The private key. - * - * @warning This isn't even my final form! - * @todo test. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -void -goldilocks_underive_private_key ( - unsigned char proto[GOLDI_SYMKEY_BYTES], - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Extract the public key from a private key. - * - * This is essentially a memcpy from the public part of the privkey. - * - * @param [out] pubkey The extracted private key. - * @param [in] privkey The private key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT The private key is corrupt. - */ -int -goldilocks_private_to_public ( - struct goldilocks_public_key_t *pubkey, - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2),visibility ("default"))); - -/** - * @brief Generate a Diffie-Hellman shared secret in constant time. - * - * This function uses some compile-time flags whose merit remains to - * be decided. - * - * If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes - * of zeros to the secret before hashing. In the case that the other - * party's key is detectably corrupt, instead the symmetric part - * of the secret key is used to produce a pseudorandom value. - * - * If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of - * the two parties' public keys is prepended to the hash. - * - * In the current version, this function can safely be run even without - * goldilocks_init(). But this property is not guaranteed for future - * versions, so call it anyway. - * - * @warning This isn't even my final form! - * - * @param [out] shared The shared secret established with the other party. - * @param [in] my_privkey My private key. - * @param [in] your_pubkey The other party's public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EINVAL The other party's key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_shared_secret ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_public_key_t *your_pubkey -) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default"))); - -#if GOLDI_IMPLEMENT_SIGNATURES -/** - * @brief Sign a message. - * - * The signature is deterministic, using the symmetric secret found in the - * secret key to form a nonce. - * - * The technique used in signing is a modified Schnorr system, like EdDSA. - * - * @warning This isn't even my final form! - * - * @param [out] signature_out Space for the output signature. - * @param [in] message The message to be signed. - * @param [in] message_len The length of the message to be signed. - * @param [in] privkey My private key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_sign ( - uint8_t signature_out[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_private_key_t *privkey -) __attribute__((nonnull(1,2,4),visibility ("default"))); - -/** - * @brief Verify a signature. - * - * This function is fairly strict. It will correctly detect when - * the signature has the wrong cofactor component, or when the sig - * values aren't less than p or q. - * - * Currently this function does not detect when the public key is weird, - * eg 0, has cofactor, etc. As a result, a party with a bogus public - * key could create signatures that succeed on some systems and fail on - * others. - * - * @warning This isn't even my final form! - * - * @param [in] signature The signature. - * @param [in] message The message to be verified. - * @param [in] message_len The length of the message to be verified. - * @param [in] pubkey The signer's public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EINVAL The public key or signature is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_verify ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default"))); -#endif - -#if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS - -/** A public key which has been expanded by precomputation for higher speed. */ -struct goldilocks_precomputed_public_key_t; - -/** - * @brief Expand a public key by precomputation. - * - * @todo Give actual error returns, instead of ambiguous NULL. - * - * @warning This isn't even my final form! - * - * @param [in] pub The public key. - * @retval NULL We ran out of memory, or the - */ -struct goldilocks_precomputed_public_key_t * -goldilocks_precompute_public_key ( - const struct goldilocks_public_key_t *pub -) __attribute__((warn_unused_result,nonnull(1),visibility ("default"))); - -/** - * @brief Overwrite an expanded public key with zeros, then destroy it. - * - * If the input is NULL, this function does nothing. - * - * @param [in] precom The public key. - */ -void -goldilocks_destroy_precomputed_public_key ( - struct goldilocks_precomputed_public_key_t *precom -) __attribute__((visibility ("default"))); - -/** - * @brief Verify a signature. - * - * This function is fairly strict. It will correctly detect when - * the signature has the wrong cofactor component, or when the sig - * values aren't less than p or q. - * - * @warning This isn't even my final form! - * - * @param [in] signature The signature. - * @param [in] message The message to be verified. - * @param [in] message_len The length of the message to be verified. - * @param [in] pubkey The signer's public key, expanded by precomputation. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_EINVAL The public key or signature is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_verify_precomputed ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_precomputed_public_key_t *pubkey -) __attribute__((warn_unused_result,nonnull(1,2,4),visibility ("default"))); - -/** - * @brief Generate a Diffie-Hellman shared secret in constant time. - * Uses a precomputation on the other party's public key for efficiency. - * - * This function uses some compile-time flags whose merit remains to - * be decided. - * - * If the flag EXPERIMENT_ECDH_OBLITERATE_CT is set, prepend 40 bytes - * of zeros to the secret before hashing. In the case that the other - * party's key is detectably corrupt, instead the symmetric part - * of the secret key is used to produce a pseudorandom value. - * - * If EXPERIMENT_ECDH_STIR_IN_PUBKEYS is set, the sum and product of - * the two parties' public keys is prepended to the hash. - * - * In the current version, this function can safely be run even without - * goldilocks_init(). But this property is not guaranteed for future - * versions, so call it anyway. - * - * @warning This isn't even my final form! - * - * @param [out] shared The shared secret established with the other party. - * @param [in] my_privkey My private key. - * @param [in] your_pubkey The other party's precomputed public key. - * - * @retval GOLDI_EOK Success. - * @retval GOLDI_ECORRUPT My key is corrupt. - * @retval GOLDI_EINVAL The other party's key is corrupt. - * @retval GOLDI_EUNINIT You must call goldilocks_init() first. - */ -int -goldilocks_shared_secret_precomputed ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_precomputed_public_key_t *your_pubkey -) __attribute__((warn_unused_result,nonnull(1,2,3),visibility ("default"))); - -#endif /* GOLDI_IMPLEMENT_PRECOMPUTED_KEYS */ - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __GOLDILOCKS_H__ */ diff --git a/src/arithmetic.c b/src/arithmetic.c deleted file mode 100644 index dee62e7..0000000 --- a/src/arithmetic.c +++ /dev/null @@ -1,87 +0,0 @@ -/** - * @cond internal - * @file field.c - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief High-level arithmetic routines, independent of field (except 3 mod 4). - */ - -#include "field.h" -#include "ec_point.h" - -mask_t -field_eq ( - const field_a_t a, - const field_a_t b -) { - field_a_t ra, rb; - field_copy(ra, a); - field_copy(rb, b); - field_weak_reduce(ra); - field_weak_reduce(rb); - field_sub_RAW(ra, ra, rb); - field_bias(ra, 2); - return field_is_zero(ra); -} - -void -field_inverse ( - field_a_t a, - const field_a_t x -) { - field_a_t L0, L1; - field_isr ( L0, x ); - field_sqr ( L1, L0 ); - field_sqr ( L0, L1 ); - field_mul ( a, x, L0 ); -} - -mask_t -field_is_square ( - const field_a_t x -) { - field_a_t L0, L1; - field_isr ( L0, x ); - field_sqr ( L1, L0 ); - field_mul ( L0, x, L1 ); - field_subw( L0, 1 ); - return field_is_zero( L0 ) | field_is_zero( x ); -} - -void -field_simultaneous_invert ( - field_a_t *__restrict__ out, - const field_a_t *in, - unsigned int n -) { - if (n==0) { - return; - } else if (n==1) { - field_inverse(out[0],in[0]); - return; - } - - field_copy(out[1], in[0]); - int i; - for (i=1; i<(int) (n-1); i++) { - field_mul(out[i+1], out[i], in[i]); - } - field_mul(out[0], out[n-1], in[n-1]); - - field_a_t tmp; - field_inverse(tmp, out[0]); - field_copy(out[0], tmp); - - /* at this point, out[0] = product(in[i]) ^ -1 - * out[i] = product(in[0]..in[i-1]) if i != 0 - */ - for (i=n-1; i>0; i--) { - field_mul(tmp, out[i], out[0]); - field_copy(out[i], tmp); - - field_mul(tmp, out[0], in[i]); - field_copy(out[0], tmp); - } -} diff --git a/src/barrett_field.c b/src/barrett_field.c deleted file mode 100644 index 55afe7d..0000000 --- a/src/barrett_field.c +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "barrett_field.h" -#include -#include - -word_t -add_nr_ext_packed( - word_t *out, - const word_t *a, - uint32_t nwords_a, - const word_t *c, - uint32_t nwords_c, - word_t mask -) { - uint32_t i; - dword_t carry = 0; - for (i=0; i>= WORD_BITS; - } - for (; i>= WORD_BITS; - } - return carry; -} - -static __inline__ word_t -add_nr_packed( - word_t *a, - const word_t *c, - uint32_t nwords -) { - uint32_t i; - dword_t carry = 0; - for (i=0; i>= WORD_BITS; - } - return carry; -} - -word_t -sub_nr_ext_packed( - word_t *out, - const word_t *a, - uint32_t nwords_a, - const word_t *c, - uint32_t nwords_c, - word_t mask -) { - uint32_t i; - dsword_t carry = 0; - for (i=0; i>= WORD_BITS; - } - for (; i>= WORD_BITS; - } - return carry; -} - -static word_t -widemac( - word_t *accum, - uint32_t nwords_accum, - const word_t *mier, - uint32_t nwords_mier, - word_t mand, - word_t carry -) { - uint32_t i; - assert(nwords_mier <= nwords_accum); - - for (i=0; i> WORD_BITS; - } - - for (; i> WORD_BITS; - } - - return carry; -} - -void -barrett_negate ( - word_t *a, - uint32_t nwords_a, - const struct barrett_prime_t *prime -) { - uint32_t i; - dsword_t carry = 0; - - barrett_reduce(a,nwords_a,0,prime); - - /* Have p = 2^big - p_lo. Want p - a = 2^big - p_lo - a */ - - for (i=0; inwords_lo; i++) { - a[i] = carry = carry - prime->p_lo[i] - a[i]; - carry >>= WORD_BITS; - } - for (; inwords_p; i++) { - a[i] = carry = carry - a[i]; - if (inwords_p-1) { - carry >>= WORD_BITS; - } - } - - a[prime->nwords_p-1] = carry = carry + (((word_t)1) << prime->p_shift); - - for (; i>WORD_BITS)); -} - -void -barrett_reduce( - word_t *a, - uint32_t nwords_a, - word_t a_carry, - const struct barrett_prime_t *prime -) { - uint32_t repeat, nwords_left_in_a=nwords_a; - - /* Is there a point to this a_carry business? */ - assert(a_carry < ((word_t)1) << prime->p_shift); - assert(nwords_a >= prime->nwords_p); - assert(prime->nwords_p > 0); /* scan-build: prevent underflow */ - - for (; nwords_left_in_a >= prime->nwords_p; nwords_left_in_a--) { - for (repeat=0; repeat<2; repeat++) { - /* PERF: surely a more careful implementation could - * avoid this double round - */ - word_t mand = a[nwords_left_in_a-1] >> prime->p_shift; - a[nwords_left_in_a-1] &= (((word_t)1)<p_shift)-1; - if (prime->p_shift && !repeat) { - /* collect high bits when there are any */ - if (nwords_left_in_a < nwords_a) { - mand |= a[nwords_left_in_a] << (WORD_BITS-prime->p_shift); - a[nwords_left_in_a] = 0; - } else { - mand |= a_carry << (WORD_BITS-prime->p_shift); - } - } - - word_t carry = widemac( - a+nwords_left_in_a-prime->nwords_p, - prime->nwords_p, - prime->p_lo, - prime->nwords_lo, - mand, - 0 - ); - assert(!carry); - (void)carry; - } - } - - assert(nwords_left_in_a == prime->nwords_p-1); - - /* OK, but it still isn't reduced. Add and subtract p_lo. */ - word_t cout = add_nr_ext_packed(a,a,prime->nwords_p,prime->p_lo,prime->nwords_lo,-1); - if (prime->p_shift) { - cout = (cout<<(WORD_BITS-prime->p_shift)) + (a[prime->nwords_p-1]>>prime->p_shift); - a[prime->nwords_p-1] &= (((word_t)1)<p_shift)-1; - } - - /* mask = carry-1: if no carry then do sub, otherwise don't */ - sub_nr_ext_packed(a,a,prime->nwords_p,prime->p_lo,prime->nwords_lo,cout-1); -} - -/* PERF: This function is horribly slow. Enough to break 1%. */ -void -barrett_mul_or_mac( - word_t *accum, - uint32_t nwords_accum, - - const word_t *a, - uint32_t nwords_a, - - const word_t *b, - uint32_t nwords_b, - - const struct barrett_prime_t *prime, - - mask_t doMac -) { - assert(nwords_accum >= prime->nwords_p); - - /* nwords_tmp = max(nwords_a + 1, nwords_p + 1, nwords_accum if doMac); */ - uint32_t nwords_tmp = (nwords_a > prime->nwords_p) ? nwords_a : prime->nwords_p; - nwords_tmp++; - assert(nwords_tmp > 0); /* scan-build: prevent underflow. */ - if (nwords_tmp < nwords_accum && doMac) - nwords_tmp = nwords_accum; - - word_t tmp[nwords_tmp]; - int bpos, idown; - uint32_t i; - - for (i=0; i= 0; bpos--) { - /* Invariant at the beginning of the loop: the high word is unused. */ - assert(tmp[nwords_tmp-1] == 0); - - /* shift up */ - for (idown=nwords_tmp-2; idown>=0; idown--) { - tmp[idown+1] = tmp[idown]; - } - tmp[0] = 0; - - /* mac and reduce */ - word_t carry = widemac(tmp, nwords_tmp, a, nwords_a, b[bpos], 0); - - /* the mac can't carry, because nwords_tmp >= nwords_a+1 and its high word is clear */ - assert(!carry); - barrett_reduce(tmp, nwords_tmp, carry, prime); - - /* at this point, the number of words used is nwords_p <= nwords_tmp-1, - * so the high word is again clear */ - } - - if (doMac) { - word_t cout = add_nr_packed(tmp, accum, nwords_accum); - barrett_reduce(tmp, nwords_tmp, cout, prime); - } - - for (i=0; inwords_p * sizeof(word_t); - if (prime->p_shift) { - nserial -= (WORD_BITS - prime->p_shift) / 8; - } - - - /* Track x < p, p = 2^k - p_lo <==> x + p_lo < 2^k */ - dword_t carry = 0; - - for (i=0; i*sizeof(word_t)>= WORD_BITS; - - word_t the = 0; - for (j=0; jnwords_lo) carry += prime->p_lo[i]; - } - - /* check for reduction */ - if (prime->p_shift) { - carry >>= prime->p_shift; - } else { - carry >>= WORD_BITS; - } - - /* at this point, carry > 0 indicates failure */ - dsword_t scarry = carry; - scarry = -scarry; - scarry >>= WORD_BITS; - scarry >>= WORD_BITS; - - return (mask_t) ~scarry; -} - -void -barrett_deserialize_and_reduce ( - word_t *x, - const uint8_t *serial, - uint32_t nserial, - const struct barrett_prime_t *prime -) { - unsigned int size = (nserial + sizeof(word_t) - 1)/sizeof(word_t); - if (size < prime->nwords_p) { - size = prime->nwords_p; - } - word_t tmp[size]; - memset(tmp,0,sizeof(tmp)); - - unsigned int i,j; - for (i=0; i*sizeof(word_t)nwords_p; i++) { - x[i] = tmp[i]; - } - for (; i>(8*j); - } - } -} diff --git a/src/bat/api_dh.h b/src/bat/api_dh.h index e266318..da81fce 100644 --- a/src/bat/api_dh.h +++ b/src/bat/api_dh.h @@ -8,11 +8,11 @@ */ #include -#include "goldilocks.h" +#include "decaf_crypto.h" -#define PUBLICKEY_BYTES GOLDI_PUBLIC_KEY_BYTES -#define SECRETKEY_BYTES GOLDI_PRIVATE_KEY_BYTES -#define SHAREDSECRET_BYTES GOLDI_SHARED_SECRET_BYTES +#define PUBLICKEY_BYTES (sizeof(decaf_448_public_key_t)) +#define SECRETKEY_BYTES (sizeof(decaf_448_private_key_t)) +#define SHAREDSECRET_BYTES 32 #define CRYPTO_PUBLICKEYBYTES PUBLICKEY_BYTES #define CRYPTO_SECRETKEYBYTES SECRETKEY_BYTES diff --git a/src/bat/api_sign.h b/src/bat/api_sign.h index 238ebbe..5488390 100644 --- a/src/bat/api_sign.h +++ b/src/bat/api_sign.h @@ -10,9 +10,9 @@ #include #include "goldilocks.h" -#define PUBLICKEY_BYTES GOLDI_PUBLIC_KEY_BYTES -#define SECRETKEY_BYTES GOLDI_PRIVATE_KEY_BYTES -#define SIGNATURE_BYTES GOLDI_SIGNATURE_BYTES +#define PUBLICKEY_BYTES (sizeof(decaf_448_public_key_t)) +#define SECRETKEY_BYTES (sizeof(decaf_448_private_key_t)) +#define SIGNATURE_BYTES (sizeof(decaf_448_signature_t)) #define CRYPTO_PUBLICKEYBYTES PUBLICKEY_BYTES #define CRYPTO_SECRETKEYBYTES SECRETKEY_BYTES diff --git a/src/bat/dh.c b/src/bat/dh.c index 51ded53..415971c 100644 --- a/src/bat/dh.c +++ b/src/bat/dh.c @@ -11,20 +11,20 @@ #include #include "api.h" #include "crypto_dh.h" +#include "randombytes.h" int crypto_dh_keypair ( unsigned char pk[SECRETKEY_BYTES], unsigned char sk[PUBLICKEY_BYTES] ) { - int ret; - ret = goldilocks_init(); - if (ret && ret != GOLDI_EALREADYINIT) - return ret; - if ((ret = goldilocks_keygen( - (struct goldilocks_private_key_t *)sk, - (struct goldilocks_public_key_t *)pk - ))) abort(); - return ret; + decaf_448_symmetric_key_t proto; + randombytes(proto,sizeof(proto)); + decaf_448_derive_private_key((decaf_448_private_key_s *)sk,proto); + decaf_448_private_to_public( + (decaf_448_public_key_s *)pk, + (decaf_448_private_key_s *)sk + ); + return 0; } int crypto_dh ( @@ -32,9 +32,10 @@ int crypto_dh ( const unsigned char pk[PUBLICKEY_BYTES], const unsigned char sk[SECRETKEY_BYTES] ) { - return goldilocks_shared_secret ( + return !decaf_448_shared_secret ( s, - (const struct goldilocks_private_key_t *)sk, - (const struct goldilocks_public_key_t *)pk - ); + SHAREDSECRET_BYTES, + (const decaf_448_private_key_s *)sk, + (const decaf_448_public_key_s *)pk + ); } diff --git a/src/bat/sign.c b/src/bat/sign.c index acedc49..ba2f762 100644 --- a/src/bat/sign.c +++ b/src/bat/sign.c @@ -16,15 +16,14 @@ int crypto_sign_keypair ( unsigned char pk[SECRETKEY_BYTES], unsigned char sk[PUBLICKEY_BYTES] ) { - int ret; - ret = goldilocks_init(); - if (ret && ret != GOLDI_EALREADYINIT) - return ret; - if ((ret = goldilocks_keygen( - (struct goldilocks_private_key_t *)sk, - (struct goldilocks_public_key_t *)pk - ))) abort(); - return ret; + decaf_448_symmetric_key_t proto; + randombytes(proto,sizeof(proto)); + decaf_448_derive_private_key((decaf_448_private_key_s *)sk,proto); + decaf_448_private_to_public( + (decaf_448_public_key_s *)pk, + (decaf_448_private_key_s *)sk + ); + return 0; } int crypto_sign ( @@ -35,16 +34,15 @@ int crypto_sign ( const unsigned char sk[SECRETKEY_BYTES] ) { unsigned char sig[SIGNATURE_BYTES]; - int ret = goldilocks_sign( - sig, m, mlen, - (const struct goldilocks_private_key_t *)sk + decaf_448_sign( + sig, + (const struct goldilocks_private_key_t *)sk, + m, mlen ); - if (!ret) { - memmove(sm + SIGNATURE_BYTES, m, mlen); - memcpy(sm, sig, SIGNATURE_BYTES); - *smlen = mlen + SIGNATURE_BYTES; - } - return ret ? -1 : 0; + memmove(sm + SIGNATURE_BYTES, m, mlen); + memcpy(sm, sig, SIGNATURE_BYTES); + *smlen = mlen + SIGNATURE_BYTES; + return 0; } int crypto_sign_open ( @@ -54,13 +52,14 @@ int crypto_sign_open ( unsigned long long smlen, const unsigned char pk[PUBLICKEY_BYTES] ) { - int ret = goldilocks_verify( - sm, sm + SIGNATURE_BYTES, smlen - SIGNATURE_BYTES, - (const struct goldilocks_public_key_t *)pk + int ret = decaf_448_verify( + sm, + (const struct goldilocks_public_key_t *)pk, + sm + SIGNATURE_BYTES, smlen - SIGNATURE_BYTES ); - if (!ret) { + if (ret) { *mlen = smlen - SIGNATURE_BYTES; memmove(m, sm + SIGNATURE_BYTES, *mlen); } - return ret ? -1 : 0; + return ret ? 0 : -1; } diff --git a/src/crandom.c b/src/crandom.c deleted file mode 100644 index 4808d3e..0000000 --- a/src/crandom.c +++ /dev/null @@ -1,488 +0,0 @@ -/* Copyright (c) 2011 Stanford University. - * Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -/* Chacha random number generator code copied from crandom */ - -#include "crandom.h" -#include "intrinsics.h" -#include "config.h" -#include "magic.h" - -#include - -volatile unsigned int crandom_features = 0; - -unsigned int crandom_detect_features(void) { - unsigned int out = GEN; - -# if (defined(__i386__) || defined(__x86_64__)) - u_int32_t a,b,c,d; - - a=1; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); - out |= GEN; - if (d & 1<<26) out |= SSE2; - if (d & 1<< 9) out |= SSSE3; - if (c & 1<<25) out |= AESNI; - if (c & 1<<28) out |= AVX; - if (b & 1<<5) out |= AVX2; - if (c & 1<<30) out |= RDRAND; - - a=0x80000001; __asm__("cpuid" : "+a"(a), "=b"(b), "=c"(c), "=d"(d)); - if (c & 1<<11) out |= XOP; -# endif - - return out; -} - - - -INTRINSIC u_int64_t rdrand(int abort_on_fail) { - uint64_t out = 0; - int tries = 1000; - - if (HAVE(RDRAND)) { - # if defined(__x86_64__) - u_int64_t out, a=0; - for (; tries && !a; tries--) { - __asm__ __volatile__ ( - "rdrand %0\n\tsetc %%al" - : "=r"(out), "+a"(a) :: "cc" - ); - } - # elif (defined(__i386__)) - u_int32_t reg, a=0; - uint64_t out; - for (; tries && !a; tries--) { - __asm__ __volatile__ ( - "rdrand %0\n\tsetc %%al" - : "=r"(reg), "+a"(a) :: "cc" - ); - } - out = reg; a = 0; - for (; tries && !a; tries--) { - __asm__ __volatile__ ( - "rdrand %0\n\tsetc %%al" - : "=r"(reg), "+a"(a) :: "cc" - ); - } - out = out << 32 | reg; - return out; - # else - abort(); /* whut */ - # endif - } else { - tries = 0; - } - - if (abort_on_fail && !tries) { - abort(); - } - - return out; -} - - -/* ------------------------------- Vectorized code ------------------------------- */ -#define shuffle(x,i) _mm_shuffle_epi32(x, \ - i + ((i+1)&3)*4 + ((i+2)&3)*16 + ((i+3)&3)*64) - -#define add _mm_add_epi32 -#define add64 _mm_add_epi64 - -#define NEED_XOP (MIGHT_HAVE(XOP)) -#define NEED_SSSE3 (MIGHT_HAVE(SSSE3) && !MUST_HAVE(XOP)) -#define NEED_SSE2 (MIGHT_HAVE(SSE2) && !MUST_HAVE(SSSE3)) -#define NEED_CONV (!MUST_HAVE(SSE2)) - -#if NEED_XOP -static __inline__ void -quarter_round_xop( - ssereg *a, - ssereg *b, - ssereg *c, - ssereg *d -) { - *a = add(*a,*b); *d = xop_rotate(16, *d ^ *a); - *c = add(*c,*d); *b = xop_rotate(12, *b ^ *c); - *a = add(*a,*b); *d = xop_rotate(8, *d ^ *a); - *c = add(*c,*d); *b = xop_rotate(7, *b ^ *c); -} -#endif - -#if NEED_SSSE3 -static const ssereg shuffle8 = { 0x0605040702010003ull, 0x0E0D0C0F0A09080Bull }; -static const ssereg shuffle16 = { 0x0504070601000302ull, 0x0D0C0F0E09080B0Aull }; - -INTRINSIC ssereg ssse3_rotate_8(ssereg a) { - return _mm_shuffle_epi8(a, shuffle8); -} - -INTRINSIC ssereg ssse3_rotate_16(ssereg a) { - return _mm_shuffle_epi8(a, shuffle16); -} - -static __inline__ void -quarter_round_ssse3( - ssereg *a, - ssereg *b, - ssereg *c, - ssereg *d -) { - *a = add(*a,*b); *d = ssse3_rotate_16(*d ^ *a); - *c = add(*c,*d); *b = sse2_rotate(12, *b ^ *c); - *a = add(*a,*b); *d = ssse3_rotate_8( *d ^ *a); - *c = add(*c,*d); *b = sse2_rotate(7, *b ^ *c); -} -#endif /* MIGHT_HAVE(SSSE3) && !MUST_HAVE(XOP) */ - -#if NEED_SSE2 -static __inline__ void -quarter_round_sse2( - ssereg *a, - ssereg *b, - ssereg *c, - ssereg *d -) { - *a = add(*a,*b); *d = sse2_rotate(16, *d ^ *a); - *c = add(*c,*d); *b = sse2_rotate(12, *b ^ *c); - *a = add(*a,*b); *d = sse2_rotate(8, *d ^ *a); - *c = add(*c,*d); *b = sse2_rotate(7, *b ^ *c); -} -#endif - -#define DOUBLE_ROUND(qrf) { \ - qrf(&a1,&b1,&c1,&d1); \ - qrf(&a2,&b2,&c2,&d2); \ - b1 = shuffle(b1,1); \ - c1 = shuffle(c1,2); \ - d1 = shuffle(d1,3); \ - b2 = shuffle(b2,1); \ - c2 = shuffle(c2,2); \ - d2 = shuffle(d2,3); \ - \ - qrf(&a1,&b1,&c1,&d1); \ - qrf(&a2,&b2,&c2,&d2); \ - b1 = shuffle(b1,3); \ - c1 = shuffle(c1,2); \ - d1 = shuffle(d1,1); \ - b2 = shuffle(b2,3); \ - c2 = shuffle(c2,2); \ - d2 = shuffle(d2,1); \ - } - -#define OUTPUT_FUNCTION { \ - output[0] = add(a1,aa); \ - output[1] = add(b1,bb); \ - output[2] = add(c1,cc); \ - output[3] = add(d1,dd); \ - output[4] = add(a2,aa); \ - output[5] = add(b2,bb); \ - output[6] = add(c2,add(cc,p)); \ - output[7] = add(d2,dd); \ - \ - output += 8; \ - \ - cc = add64(add64(cc,p), p); \ - a1 = a2 = aa; \ - b1 = b2 = bb; \ - c1 = cc; c2 = add64(cc,p);\ - d1 = d2 = dd; \ - } -/* ------------------------------------------------------------------------------- */ - -INTRINSIC u_int32_t rotate(int r, u_int32_t a) { - return a<>(32-r); -} - -static __inline__ __attribute__((unused)) void -quarter_round(u_int32_t *a, u_int32_t *b, u_int32_t *c, u_int32_t *d) { - *a = *a + *b; *d = rotate(16, *d^*a); - *c = *c + *d; *b = rotate(12, *b^*c); - *a = *a + *b; *d = rotate(8, *d^*a); - *c = *c + *d; *b = rotate(7, *b^*c); -} - -static void -crandom_chacha_expand(u_int64_t iv, - u_int64_t ctr, - int nr, - int output_size, - const unsigned char *key_, - unsigned char *output_) { -# if MIGHT_HAVE_SSE2 - if (HAVE(SSE2)) { - ssereg *key = (ssereg *)key_; - ssereg *output = (ssereg *)output_; - - ssereg a1 = key[0], a2 = a1, aa = a1, - b1 = key[1], b2 = b1, bb = b1, - c1 = {iv, ctr}, c2 = {iv, ctr+1}, cc = c1, - d1 = {0x3320646e61707865ull, 0x6b20657479622d32ull}, - d2 = d1, dd = d1, - p = {0, 1}; - - int i,r; -# if (NEED_XOP) - if (HAVE(XOP)) { - for (i=0; i0; r-=2) - DOUBLE_ROUND(quarter_round_xop); - OUTPUT_FUNCTION; - } - return; - } -# endif -# if (NEED_SSSE3) - if (HAVE(SSSE3)) { - for (i=0; i0; r-=2) - DOUBLE_ROUND(quarter_round_ssse3); - OUTPUT_FUNCTION; - } - return; - } -# endif -# if (NEED_SSE2) - if (HAVE(SSE2)) { - for (i=0; i0; r-=2) - DOUBLE_ROUND(quarter_round_sse2); - OUTPUT_FUNCTION; - } - return; - } -# endif - } -# endif - -# if NEED_CONV - { - const u_int32_t *key = (const u_int32_t *)key_; - u_int32_t - x[16], - input[16] = { - key[0], key[1], key[2], key[3], - key[4], key[5], key[6], key[7], - iv, iv>>32, ctr, ctr>>32, - 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574 - }, - *output = (u_int32_t *)output_; - int i, r; - - for (i=0; i0; r-=2) { - quarter_round(&x[0], &x[4], &x[8], &x[12]); - quarter_round(&x[1], &x[5], &x[9], &x[13]); - quarter_round(&x[2], &x[6], &x[10], &x[14]); - quarter_round(&x[3], &x[7], &x[11], &x[15]); - - quarter_round(&x[0], &x[5], &x[10], &x[15]); - quarter_round(&x[1], &x[6], &x[11], &x[12]); - quarter_round(&x[2], &x[7], &x[8], &x[13]); - quarter_round(&x[3], &x[4], &x[9], &x[14]); - } - for (r=0; r<16; r++) { - output[r] = x[r] + input[r]; - } - - output += 16; - input[11] ++; - if (!input[11]) input[12]++; - } - } - -#endif /* NEED_CONV */ -} - -int -crandom_init_from_file( - crandom_state_a_t state, - const char *filename, - int reseed_interval, - int reseeds_mandatory -) { - state->fill = 0; - state->reseed_countdown = reseed_interval; - state->reseed_interval = reseed_interval; - state->ctr = 0; - - state->randomfd = open(filename, O_RDONLY); - if (state->randomfd == -1) { - int err = errno; - return err ? err : -1; - } - - ssize_t offset = 0, red; - do { - red = read(state->randomfd, state->seedBuffer + offset, 32 - offset); - if (red > 0) offset += red; - } while (red > 0 && offset < 32); - - if (offset < 32) { - int err = errno; - return err ? err : -1; - } - - memset(state->seedBuffer+32, 0, 96); - - state->magic = CRANDOM_MAGIC; - state->reseeds_mandatory = reseeds_mandatory; - - return 0; -} - -void -crandom_init_from_buffer( - crandom_state_a_t state, - const char initial_seed[32] -) { - memcpy(state->seedBuffer, initial_seed, 32); - memset(state->seedBuffer+32, 0, 96); - state->reseed_countdown = state->reseed_interval = state->fill = state->ctr = state->reseeds_mandatory = 0; - state->randomfd = -1; - state->magic = CRANDOM_MAGIC; -} - -int -crandom_generate( - crandom_state_a_t state, - unsigned char *output, - unsigned long long length -) { - /* the generator isn't seeded; maybe they ignored the return value of init_from_file */ - if (unlikely(state->magic != CRANDOM_MAGIC)) { - abort(); - } - - int ret = 0; - - /* - * Addition 5/21/2014. - * - * If this is used in an application inside a VM, and the VM - * is snapshotted and restored, then crandom_generate() would - * produce the same output. - * - * Of course, the real defense against this is "don't do that", - * but we mitigate it by the RDRAND and/or rdtsc() in the refilling - * code. Since chacha is pseudorandom, when the attacker doesn't - * know the state, it's good enough if RDRAND/rdtsc() return - * different results. However, if (part of) the request is filled - * from the buffer, this won't help. - * - * So, add a flag EXPERIMENT_CRANDOM_BUFFER_CUTOFF_BYTES which - * disables the buffer for requests larger than this size. - * - * Suggest EXPERIMENT_CRANDOM_BUFFER_CUTOFF_BYTES = 0, which - * disables the buffer. But instead you can set it to say 16, - * so that pulls of at least 128 bits will be stirred. This - * could still be a problem for eg 64-bit nonces, but those - * aren't entirely collision-resistant anyway. - * - * Heuristic: large requests are more likely to be - * cryptographically important, and the buffer doesn't impact - * their performance as much. So if the request is bigger - * than a certain size, just drop the buffer on the floor. - * - * This code isn't activated if state->reseed_interval == 0, - * because then the PRNG is deterministic anyway. - * - * TODO: sample 128 bits out of RDRAND() instead of 64 bits. - * TODO: option to completely remove the buffer and fill? - * FUTURE: come up with a less band-aid-y solution to this problem. - */ -#ifdef EXPERIMENT_CRANDOM_BUFFER_CUTOFF_BYTES - if (state->reseed_interval -#if EXPERIMENT_CRANDOM_CUTOFF_BYTES > 0 - /* #if'd to a warning from -Wtype-limits in GCC when it's zero */ - && length >= EXPERIMENT_CRANDOM_BUFFER_CUTOFF_BYTES -#endif - ) { - state->fill = 0; - } -#endif - - while (length) { - if (unlikely(state->fill <= 0)) { - uint64_t iv = 0; - if (state->reseed_interval) { - /* it's nondeterministic, stir in some rdrand() or rdtsc() */ - if (HAVE(RDRAND)) { - iv = rdrand(0); - if (!iv) iv = rdtsc(); - } else { - iv = rdtsc(); - } - - state->reseed_countdown--; - if (unlikely(state->reseed_countdown <= 0)) { - /* reseed by xoring in random state */ - state->reseed_countdown = state->reseed_interval; - ssize_t offset = 0, red; - do { - red = read(state->randomfd, state->seedBuffer + 32 + offset, 32 - offset); - if (red > 0) offset += red; - } while (red > 0 && offset < 32); - - if (offset < 32) { - /* The read failed. Signal an error with the return code. - * - * If reseeds are mandatory, crash. - * - * If not, the generator is still probably safe to use, because reseeding - * is basically over-engineering for caution. Also, the user might ignore - * the return code, so we still need to fill the request. - * - * Set reseed_countdown = 1 so we'll try again later. If the user's - * performance sucks as a result of ignoring the error code while calling - * us in a loop, well, that's life. - */ - if (state->reseeds_mandatory) { - abort(); - } - - ret = errno; - if (ret == 0) ret = -1; - state->reseed_countdown = 1; - } - - int i; - for (i=0; i<32; i++) { - /* Stir in the buffer. If somehow the read failed, it'll be zeros. */ - state->seedBuffer[i] ^= state->seedBuffer[i+32]; - } - } - } - crandom_chacha_expand(iv,state->ctr,20,128,state->seedBuffer,state->seedBuffer); - state->ctr++; - state->fill = sizeof(state->seedBuffer)-32; - } - - unsigned long long copy = (length > state->fill) ? state->fill : length; - state->fill -= copy; - memcpy(output, state->seedBuffer + 32 + state->fill, copy); - really_memset(state->seedBuffer + 32 + state->fill, 0, copy); - output += copy; length -= copy; - } - - return ret; -} - -void -crandom_destroy( - crandom_state_a_t state -) { - if (state->magic == CRANDOM_MAGIC && state->randomfd) { - (void) close(state->randomfd); - /* Ignore the return value from close(), because what would it mean? - * "Your random device, which you were reading over NFS, lost some data"? - */ - } - - really_memset(state, 0, sizeof(*state)); -} diff --git a/src/decaf_crypto.c b/src/decaf_crypto.c index f2eea17..8d49c38 100644 --- a/src/decaf_crypto.c +++ b/src/decaf_crypto.c @@ -10,7 +10,6 @@ #include "decaf_crypto.h" #include -#include "sha512.h" static const unsigned int DECAF_448_SCALAR_OVERKILL_BYTES = DECAF_448_SCALAR_BYTES + 8; diff --git a/src/ec_point.c b/src/ec_point.c deleted file mode 100644 index 24c32f1..0000000 --- a/src/ec_point.c +++ /dev/null @@ -1,1222 +0,0 @@ -/** - * @cond internal - * @file ec_point.c - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @warning This file was automatically generated. - * Then it was edited by hand. Good luck, have fun. - * - * This file contains a huge number of different options for EC point arithmetic, - * but only a few of them will be used by any given library. They are here for - * reference and for consistency checks. The Goldilocks library link step strips - * out unused functions. - */ - -#include "ec_point.h" -#include "magic.h" - -void -add_tw_niels_to_tw_extensible ( - tw_extensible_a_t d, - const tw_niels_a_t e -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1; - field_subx_nr ( L1, d->y, d->x ); - field_mul ( L0, e->a, L1 ); - field_add_nr ( L1, d->x, d->y ); - field_mul ( d->y, e->b, L1 ); - field_mul ( L1, d->u, d->t ); - field_mul ( d->x, e->c, L1 ); - field_add_nr ( d->u, L0, d->y ); - field_subx_nr ( d->t, d->y, L0 ); - field_subx_nr ( d->y, d->z, d->x ); - field_add_nr ( L0, d->x, d->z ); - field_mul ( d->z, L0, d->y ); - field_mul ( d->x, d->y, d->t ); - field_mul ( d->y, L0, d->u ); -} - -void -add_tw_extended ( - tw_extended_a_t d, - const tw_extended_a_t e -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1, L2; - field_subx_nr ( L1, d->y, d->x ); - field_subx_nr ( L2, e->y, e->x ); - field_mul ( L0, L2, L1 ); - field_add_nr ( L1, d->y, d->x ); - field_add_nr ( L2, e->y, e->x ); - field_mul ( d->y, L2, L1 ); - field_mul ( L1, e->t, d->t ); - field_mulw_scc_wr ( d->x, L1, 2-2*EDWARDS_D ); - field_add_nr ( L1, L0, d->y ); - field_subx_nr ( L2, d->y, L0 ); - field_mul ( L0, d->z, e->z ); - field_add_nr ( L0, L0, L0 ); - field_add_nr ( d->y, L0, d->x ); - field_subx_nr ( L0, L0, d->x ); - field_mul ( d->z, L0, d->y ); - field_mul ( d->x, d->y, L2 ); - field_mul ( d->y, L0, L1 ); - field_mul ( d->t, L1, L2 ); -} - -void -add_sub_tw_extended ( - tw_extended_a_t c, - const tw_extended_a_t d, - const tw_extended_a_t e, - mask_t sub -) { - field_a_t L0, L1, L2, L3; - field_sub ( L1, d->y, d->x ); - field_sub ( L2, e->y, e->x ); - field_add ( L3, e->y, e->x ); - constant_time_cond_swap(L2,L3,sizeof(L2),sub); - field_mul ( L0, L2, L1 ); - field_add ( L1, d->y, d->x ); - field_mul ( c->y, L3, L1 ); - field_mul ( L1, e->t, d->t ); - field_mulw_scc_wr ( c->x, L1, 2-2*EDWARDS_D ); - field_add ( L1, L0, d->y ); - field_sub ( L2, c->y, L0 ); - field_mul ( L0, d->z, e->z ); - field_add ( L0, L0, L0 ); - field_add ( c->y, L0, c->x ); - field_sub ( L0, L0, c->x ); - constant_time_cond_swap(L0,c->y,sizeof(L0),sub); - field_mul ( c->z, L0, c->y ); - field_mul ( c->x, c->y, L2 ); - field_mul ( c->y, L0, L1 ); - field_mul ( c->t, L1, L2 ); -} - -void -sub_tw_niels_from_tw_extensible ( - tw_extensible_a_t d, - const tw_niels_a_t e -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1; - field_subx_nr ( L1, d->y, d->x ); - field_mul ( L0, e->b, L1 ); - field_add_nr ( L1, d->x, d->y ); - field_mul ( d->y, e->a, L1 ); - field_mul ( L1, d->u, d->t ); - field_mul ( d->x, e->c, L1 ); - field_add_nr ( d->u, L0, d->y ); - field_subx_nr ( d->t, d->y, L0 ); - field_add_nr ( d->y, d->x, d->z ); - field_subx_nr ( L0, d->z, d->x ); - field_mul ( d->z, L0, d->y ); - field_mul ( d->x, d->y, d->t ); - field_mul ( d->y, L0, d->u ); -} - -void -add_tw_pniels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t a -) { - field_a_t L0; - field_mul ( L0, e->z, a->z ); - field_copy ( e->z, L0 ); - add_tw_niels_to_tw_extensible( e, a->n ); -} - -void -sub_tw_pniels_from_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t a -) { - field_a_t L0; - field_mul ( L0, e->z, a->z ); - field_copy ( e->z, L0 ); - sub_tw_niels_from_tw_extensible( e, a->n ); -} - -void -double_tw_extensible ( - tw_extensible_a_t a -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1, L2; - field_sqr ( L2, a->x ); - field_sqr ( L0, a->y ); - field_add_nr ( a->u, L2, L0 ); - field_add_nr ( a->t, a->y, a->x ); - field_sqr ( L1, a->t ); - field_sub_nr ( a->t, L1, a->u ); - field_bias ( a->t, 3 ); - IF32( field_weak_reduce( a->t ) ); - field_subx_nr ( L1, L0, L2 ); - field_sqr ( a->x, a->z ); - field_bias ( a->x, 2-is32 /*is32 ? 1 : 2*/ ); - field_add_nr ( a->z, a->x, a->x ); - field_sub_nr ( L0, a->z, L1 ); - IF32( field_weak_reduce( L0 ) ); - field_mul ( a->z, L1, L0 ); - field_mul ( a->x, L0, a->t ); - field_mul ( a->y, L1, a->u ); -} - -void -double_extensible ( - extensible_a_t a -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1, L2; - field_sqr ( L2, a->x ); - field_sqr ( L0, a->y ); - field_add_nr ( L1, L2, L0 ); - field_add_nr ( a->t, a->y, a->x ); - field_sqr ( a->u, a->t ); - field_sub_nr ( a->t, a->u, L1 ); - field_bias ( a->t, 3 ); - IF32( field_weak_reduce( a->t ) ); - field_subx_nr ( a->u, L0, L2 ); - field_sqr ( a->x, a->z ); - field_bias ( a->x, 2 ); - field_add_nr ( a->z, a->x, a->x ); - field_sub_nr ( L0, a->z, L1 ); - IF32( field_weak_reduce( L0 ) ); - field_mul ( a->z, L1, L0 ); - field_mul ( a->x, L0, a->t ); - field_mul ( a->y, L1, a->u ); -} - -void -twist_and_double ( - tw_extensible_a_t b, - const extensible_a_t a -) { - field_a_t L0; - field_sqr ( b->x, a->x ); - field_sqr ( b->z, a->y ); - field_add ( b->u, b->x, b->z ); - field_add ( b->t, a->y, a->x ); - field_sqr ( L0, b->t ); - field_sub ( b->t, L0, b->u ); - field_sub ( L0, b->z, b->x ); - field_sqr ( b->x, a->z ); - field_add ( b->z, b->x, b->x ); - field_sub ( b->y, b->z, b->u ); - field_mul ( b->z, L0, b->y ); - field_mul ( b->x, b->y, b->t ); - field_mul ( b->y, L0, b->u ); -} - -void -untwist_and_double ( - extensible_a_t b, - const tw_extensible_a_t a -) { - field_a_t L0; - field_sqr ( b->x, a->x ); - field_sqr ( b->z, a->y ); - field_add ( L0, b->x, b->z ); - field_add ( b->t, a->y, a->x ); - field_sqr ( b->u, b->t ); - field_sub ( b->t, b->u, L0 ); - field_sub ( b->u, b->z, b->x ); - field_sqr ( b->x, a->z ); - field_add ( b->z, b->x, b->x ); - field_sub ( b->y, b->z, b->u ); - field_mul ( b->z, L0, b->y ); - field_mul ( b->x, b->y, b->t ); - field_mul ( b->y, L0, b->u ); -} - -void -convert_tw_affine_to_tw_pniels ( - tw_pniels_a_t b, - const tw_affine_a_t a -) { - field_sub ( b->n->a, a->y, a->x ); - field_add ( b->n->b, a->x, a->y ); - field_mul ( b->z, a->y, a->x ); - field_mulw_scc_wr ( b->n->c, b->z, 2*EDWARDS_D-2 ); - field_set_ui( b->z, 2 ); -} - -void -convert_tw_affine_to_tw_extensible ( - tw_extensible_a_t b, - const tw_affine_a_t a -) { - field_copy ( b->x, a->x ); - field_copy ( b->y, a->y ); - field_set_ui( b->z, 1 ); - field_copy ( b->t, a->x ); - field_copy ( b->u, a->y ); -} - -void -convert_tw_extensible_to_tw_extended ( - tw_extended_a_t b, - const tw_extensible_a_t a -) { - field_copy ( b->x, a->x ); - field_copy ( b->y, a->y ); - field_copy ( b->z, a->z ); - field_mul ( b->t, a->t, a->u ); -} - -void -convert_affine_to_extensible ( - extensible_a_t b, - const affine_a_t a -) { - field_copy ( b->x, a->x ); - field_copy ( b->y, a->y ); - field_set_ui( b->z, 1 ); - field_copy ( b->t, a->x ); - field_copy ( b->u, a->y ); -} - -void -convert_tw_extensible_to_tw_pniels ( - tw_pniels_a_t b, - const tw_extensible_a_t a -) { - field_sub ( b->n->a, a->y, a->x ); - field_add ( b->n->b, a->x, a->y ); - field_mul ( b->z, a->u, a->t ); - field_mulw_scc_wr ( b->n->c, b->z, 2*EDWARDS_D-2 ); - field_add ( b->z, a->z, a->z ); -} - -void -convert_tw_pniels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t d -) { - field_add ( e->u, d->n->b, d->n->a ); - field_sub ( e->t, d->n->b, d->n->a ); - field_mul ( e->x, d->z, e->t ); - field_mul ( e->y, d->z, e->u ); - field_sqr ( e->z, d->z ); -} - -void -convert_tw_niels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_niels_a_t d -) { - field_add ( e->y, d->b, d->a ); - field_sub ( e->x, d->b, d->a ); - field_set_ui( e->z, 1 ); - field_copy ( e->t, e->x ); - field_copy ( e->u, e->y ); -} - -void -decaf_deserialize_montgomery ( - montgomery_aux_a_t a, - const field_a_t s -) { - field_copy ( a->s0, s ); - field_sqr ( a->xa, s ); - field_set_ui ( a->za, 1 ); - field_set_ui ( a->xd, 1 ); - field_set_ui ( a->zd, 0 ); -} - -void -montgomery_aux_step ( - struct montgomery_aux_t* a -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_add_nr ( a->xs, a->xa, a->za ); - field_subx_nr ( a->zs, a->xa, a->za ); - field_add_nr ( a->xa, a->xd, a->zd ); - field_subx_nr ( a->za, a->xd, a->zd ); - field_mul ( a->xd, a->xa, a->zs ); - field_mul ( a->zd, a->xs, a->za ); - field_add_nr ( a->xs, a->xd, a->zd ); - field_subx_nr ( a->zd, a->xd, a->zd ); - field_mul ( a->zs, a->zd, a->s0 ); - field_sqr ( a->zd, a->xa ); - field_sqr ( a->xa, a->za ); - field_subx_nr ( a->za, a->zd, a->xa ); - field_mul ( a->xd, a->xa, a->zd ); - field_mulw_scc_wr ( a->zd, a->za, 1-EDWARDS_D ); - field_add_nr ( a->xa, a->xa, a->zd ); - field_mul ( a->zd, a->xa, a->za ); - field_sqr ( a->xa, a->xs ); - field_sqr ( a->za, a->zs ); -} - -void -montgomery_step ( - montgomery_a_t a -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t L0, L1; - field_add_nr ( L0, a->zd, a->xd ); - field_subx_nr ( L1, a->xd, a->zd ); - field_subx_nr ( a->zd, a->xa, a->za ); - field_mul ( a->xd, L0, a->zd ); - field_add_nr ( a->zd, a->za, a->xa ); - field_mul ( a->za, L1, a->zd ); - field_add_nr ( a->xa, a->za, a->xd ); - field_sqr ( a->zd, a->xa ); - field_mul ( a->xa, a->z0, a->zd ); - field_subx_nr ( a->zd, a->xd, a->za ); - field_sqr ( a->za, a->zd ); - field_sqr ( a->xd, L0 ); - field_sqr ( L0, L1 ); - field_mulw_scc ( a->zd, a->xd, 1-EDWARDS_D ); /* FIXME PERF MULW */ - field_subx_nr ( L1, a->xd, L0 ); - field_mul ( a->xd, L0, a->zd ); - field_sub_nr ( L0, a->zd, L1 ); - field_bias ( L0, 4 - 2*is32 /*is32 ? 2 : 4*/ ); - IF32( field_weak_reduce( L0 ) ); - field_mul ( a->zd, L0, L1 ); -} - -void -deserialize_montgomery ( - montgomery_a_t a, - const field_a_t sbz -) { - field_sqr ( a->z0, sbz ); - field_set_ui( a->xd, 1 ); - field_set_ui( a->zd, 0 ); - field_set_ui( a->xa, 1 ); - field_copy ( a->za, a->z0 ); -} - -mask_t -serialize_montgomery ( - field_a_t b, - const montgomery_a_t a, - const field_a_t sbz -) { - mask_t L4, L5, L6; - field_a_t L0, L1, L2, L3; - field_mul ( L3, a->z0, a->zd ); - field_sub ( L1, L3, a->xd ); - field_mul ( L3, a->za, L1 ); - field_mul ( L2, a->z0, a->xd ); - field_sub ( L1, L2, a->zd ); - field_mul ( L0, a->xa, L1 ); - field_add ( L2, L0, L3 ); - field_sub ( L1, L3, L0 ); - field_mul ( L3, L1, L2 ); - field_copy ( L2, a->z0 ); - field_addw ( L2, 1 ); - field_sqr ( L0, L2 ); - field_mulw_scc_wr ( L1, L0, EDWARDS_D-1 ); - field_add ( L2, a->z0, a->z0 ); - field_add ( L0, L2, L2 ); - field_add ( L2, L0, L1 ); - field_mul ( L0, a->xd, L2 ); - L5 = field_is_zero( a->zd ); - L6 = - L5; - constant_time_mask ( L1, L0, sizeof(L1), L5 ); - field_add ( L2, L1, a->zd ); - L4 = ~ L5; - field_mul ( L1, sbz, L3 ); - field_addw ( L1, L6 ); - field_mul ( L3, L2, L1 ); - field_mul ( L1, L3, L2 ); - field_mul ( L2, L3, a->xd ); - field_mul ( L3, L1, L2 ); - field_isr ( L0, L3 ); - field_mul ( L2, L1, L0 ); - field_sqr ( L1, L0 ); - field_mul ( L0, L3, L1 ); - constant_time_mask ( b, L2, sizeof(L1), L4 ); - field_subw( L0, 1 ); - L5 = field_is_zero( L0 ); - L4 = field_is_zero( sbz ); - return L5 | L4; -} - -void -serialize_extensible ( - field_a_t b, - const extensible_a_t a -) { - field_a_t L0, L1, L2; - field_sub ( L0, a->y, a->z ); - field_add ( b, a->z, a->y ); - field_mul ( L1, a->z, a->x ); - field_mul ( L2, L0, L1 ); - field_mul ( L1, L2, L0 ); - field_mul ( L0, L2, b ); - field_mul ( L2, L1, L0 ); - field_isr ( L0, L2 ); - field_mul ( b, L1, L0 ); - field_sqr ( L1, L0 ); - field_mul ( L0, L2, L1 ); -} - -static void -decaf_abs ( - field_a_t a -) { - field_cond_neg ( a, field_high_bit(a) ); - field_strong_reduce ( a ); -} - -mask_t -decaf_serialize_montgomery ( - field_a_t out, - const montgomery_aux_a_t a, - mask_t swapped -) { - field_a_t xz_d, xz_a, x0, den, L0, L1, L2, L3; - mask_t zcase, output_zero, flip, succ, za_zero; - field_mul(xz_d, a->xd, a->zd); - field_mul(xz_a, a->xa, a->za); - output_zero = field_is_zero(xz_d); - za_zero = field_is_zero(a->za); - field_addw(xz_d, -output_zero); /* make xz_d always nonzero */ - zcase = output_zero | field_is_zero(xz_a); - - field_sqr(x0, a->s0); - - /* Curve test in zcase */ - field_copy(L0,x0); - field_addw(L0,1); - field_sqr(L1,L0); - field_mulw_scc_wr(L0,x0,-4*EDWARDS_D); - field_add(L1,L1,L0); - constant_time_select(xz_a,L1,xz_a,sizeof(xz_a),zcase); - - /* Compute denominator */ - field_mul(L0, x0, xz_d); - field_mulw(L2, L0, 4); - field_mul(L1, L2, xz_a); - field_isr(den, L1); - - /* Check squareness */ - field_sqr(L2, den); - field_mul(L0, L1, L2); - field_addw(L0, 1); - succ = ~field_high_bit(a->s0) & ~field_is_zero(L0); - - /* Compute y/x */ - field_mul(L1, x0, a->xd); - field_sub(L1, a->zd, L1); - field_mul(L0, a->za, L1); /* L0 = "opq" */ - field_mul(L1, x0, a->zd); - field_sub(L1, L1, a->xd); - field_mul(L2, a->xa, L1); /* L2 = "pqr" */ - - field_sub(L1, L0, L2); - field_add(L0, L0, L2); - field_mul(L2, L1, den); /* L2 = y0 / x0 */ - field_mul(L1, L0, den); /* L1 = yO / xO */ - flip = field_high_bit(L1) ^ field_high_bit(L2) ^ za_zero; - constant_time_select(L0, a->zd, a->xd, sizeof(L0), flip); /* L0 = "times" */ - /* OK, done with y-coordinates */ - - /* OK, now correct for swappage */ - field_add(den,den,den); - field_mul(L1,den,a->s0); - field_sqr(L2,L1); - field_mul(L3,L2,xz_a); - constant_time_select(den,L3,L1,sizeof(den),swapped | zcase); - - /* compute the output */ - field_mul(L1,L0,den); - - constant_time_select(L2,a->s0,a->zs,sizeof(L2),zcase); /* zs, but s0 in zcase */ - field_mul(L0,L1,L2); - - constant_time_select(L3,a->zd,a->xd,sizeof(L3),za_zero); - constant_time_select(L2,L3,a->xs,sizeof(L2),zcase); /* xs, but zq or qq in zcase */ - field_mul(out,L0,L2); - - constant_time_mask(out,out,sizeof(field_a_t),~output_zero); - decaf_abs(out); - - return succ; -} - -void -decaf_serialize_extensible ( - field_a_t b, - const extensible_a_t a -) { - field_a_t L0, L1, L2, L3; - field_mulw_scc_wr ( L2, a->y, EDWARDS_D ); - field_mul ( L3, L2, a->t ); - field_mul ( L2, L3, a->u ); - field_mul ( L0, a->x, a->z ); - field_sub ( L3, L0, L2 ); - field_add ( L0, a->y, a->z ); - field_sub ( L1, a->z, a->y ); - field_mul ( L2, L1, L0 ); - field_mulw_scc_wr ( L1, L2, 1-EDWARDS_D ); - field_isr ( L0, L1 ); - field_mulw_scc_wr ( L1, L0, 1-EDWARDS_D ); - field_mul ( L2, L1, L0 ); - field_mul ( L0, L2, L3 ); - field_add ( L3, L1, L1 ); - field_mul ( L2, L3, a->z ); - field_cond_neg ( L1, ~field_high_bit(L2) ); - field_mul ( L2, L1, a->y ); - field_add ( b, L0, L2 ); - decaf_abs ( b ); -} - -void -decaf_serialize_tw_extensible ( - field_a_t b, - const tw_extensible_a_t a -) { - field_a_t L0, L1, L2, L3; - field_mulw_scc ( L2, a->y, 1-EDWARDS_D ); - field_mul ( L3, L2, a->t ); - field_mul ( L2, L3, a->u ); - field_mul ( L0, a->x, a->z ); - field_sub ( L3, L2, L0 ); - field_add ( L0, a->z, a->y ); - field_sub ( L1, a->z, a->y ); - field_mul ( L2, L1, L0 ); - field_mulw_scc ( L1, L2, -EDWARDS_D ); - field_isr ( L0, L1 ); - field_mulw_scc ( L1, L0, -EDWARDS_D ); - field_mul ( L2, L1, L0 ); - field_mul ( L0, L2, L3 ); - field_add ( L3, L1, L1 ); - field_mul ( L2, L3, a->z ); - field_cond_neg ( L1, ~field_high_bit(L2) ); - field_mul ( L2, L1, a->y ); - field_add ( b, L0, L2 ); - decaf_abs ( b ); -} - -void -decaf_serialize_tw_extended ( - field_a_t b, - const tw_extended_a_t a -) { - field_a_t L0, L1, L2, L3; - field_mulw_scc ( L0, a->y, 1-EDWARDS_D ); - field_mul ( L2, L0, a->t ); - field_mul ( L0, a->x, a->z ); - field_sub ( L3, L2, L0 ); - field_add ( L0, a->z, a->y ); - field_sub ( L1, a->z, a->y ); - field_mul ( L2, L1, L0 ); - field_mulw_scc ( L1, L2, -EDWARDS_D ); - field_isr ( L0, L1 ); - field_mulw_scc ( L1, L0, -EDWARDS_D ); - field_mul ( L2, L1, L0 ); - field_mul ( L0, L2, L3 ); - field_add ( L3, L1, L1 ); - field_mul ( L2, L3, a->z ); - field_cond_neg ( L1, ~field_high_bit(L2) ); - field_mul ( L2, L1, a->y ); - field_add ( b, L0, L2 ); - decaf_abs ( b ); -} - -/* -static void -tw_extended_efgh ( - tw_extended_a_t a, - field_a_t x, - field_a_t xz, - field_a_t y, - field_a_t yz -) { - field_mul(a->x,x,yz); - field_mul(a->y,y,xz); - field_mul(a->z,xz,yz); - field_mul(a->t,x,y); -} -*/ - -mask_t -decaf_deserialize_tw_extended ( - tw_extended_a_t a, - const field_a_t s, - mask_t allow_identity -) { - field_a_t L0, L1, L2, L3, L4; - mask_t succ, zero; - zero = field_is_zero(s); - succ = allow_identity | ~zero; - succ &= ~field_high_bit(s); - - field_sqr ( L0, s ); // L0 = s^2 - field_neg ( a->z, L0 ); - field_addw ( a->z, 1 ); - field_sqr ( L1, a->z ); - field_mulw_scc_wr ( L2, L0, 4-4*EDWARDS_D ); - field_add ( L2, L2, L1 ); // L2 = [t^2] - field_mul ( L1, L2, L0 ); // L1 = [t^2] s^2 - - field_isr ( L3, L1 ); // L3 =? 1/ts; check it - field_sqr ( L4, L3 ); - field_mul ( L0, L4, L1 ); - field_addw( L0, 1 ); - succ &= ~field_is_zero( L0 ); - - field_mul ( L1, L2, L3 ); // L1 = t^2 * 1/ts = t/s - field_cond_neg ( L3, field_high_bit(L1) ); // negate 1/ts? - - field_add( a->x, s, s ); - field_mul ( L2, L3, s ); - - field_neg ( L1, a->z ); - field_addw ( L1, 2 ); - field_mul ( L0, L1, L2 ); - field_mul(a->y,L0,a->z); - field_mul(a->t,a->x,L0); - field_addw ( a->y, -zero ); - - return succ; -} - -mask_t -decaf_deserialize_affine ( - affine_a_t a, - const field_a_t s, - mask_t allow_identity -) { - field_a_t L0, L1, L2, L3, L4, L5; - mask_t succ, zero; - zero = field_is_zero(s); - succ = allow_identity | ~zero; - succ &= ~field_high_bit(s); - field_sqr ( L0, s ); - field_copy ( L1, L0 ); - field_addw ( L1, 1 ); - field_make_nonzero ( L1 ); - field_sqr ( L2, L1 ); - field_mulw_scc_wr ( L3, L0, -4*EDWARDS_D ); - field_add ( L3, L3, L2 ); - field_mul ( L4, L3, L2 ); - field_mul ( L2, L4, L0 ); - field_isr ( L4, L2 ); - field_sqr ( L5, L4 ); - field_mul ( L0, L5, L2 ); - field_addw( L0, 1 ); - succ &= ~field_is_zero( L0 ); - field_mul ( L2, L3, L1 ); - field_mul ( L3, L2, L4 ); - field_cond_neg ( L4, field_high_bit(L3) ); - field_mul ( L3, L4, s ); - field_sqr ( L4, L3 ); - field_mul ( L0, L2, L4 ); - field_add ( L0, L0, L0 ); - field_mul ( a->x, L0, s ); - field_mul ( L2, L1, L3 ); - field_neg ( L1, L1 ); - field_addw ( L1, 2 ); - field_mul ( a->y, L1, L2 ); - field_addw ( a->y, -zero ); - return succ; -} - -mask_t -decaf_deserialize_tw_affine ( - tw_affine_a_t a, - const field_a_t s, - mask_t allow_identity -) { - field_a_t L0, L1, L2, L3, L4, L5; - mask_t succ, zero; - zero = field_is_zero(s); - succ = allow_identity | ~zero; - succ &= ~field_high_bit(s); - field_sqr ( L0, s ); - field_neg ( L1, L0 ); - field_addw ( L1, 1 ); - field_make_nonzero ( L1 ); - field_sqr ( L2, L1 ); - field_mulw_scc_wr ( L3, L0, 4-4*EDWARDS_D ); - field_add ( L3, L3, L2 ); - field_mul ( L4, L3, L2 ); - field_mul ( L2, L4, L0 ); - field_isr ( L4, L2 ); - field_sqr ( L5, L4 ); - field_mul ( L0, L5, L2 ); - field_addw( L0, 1 ); - succ &= ~field_is_zero( L0 ); - field_mul ( L2, L3, L1 ); - field_mul ( L3, L2, L4 ); - field_cond_neg ( L4, field_high_bit(L3) ); - field_mul ( L3, L4, s ); - field_sqr ( L4, L3 ); - field_mul ( L0, L2, L4 ); - field_add ( L0, L0, L0 ); - field_mul ( a->x, L0, s ); - field_mul ( L2, L1, L3 ); - field_neg ( L1, L1 ); - field_addw ( L1, 2 ); - field_mul ( a->y, L1, L2 ); - field_addw ( a->y, -zero ); - return succ; -} - -void -untwist_and_double_and_serialize ( - field_a_t b, - const tw_extensible_a_t a -) { - field_a_t L0, L1, L2, L3; - field_mul ( L3, a->y, a->x ); - field_add ( b, a->y, a->x ); - field_sqr ( L1, b ); - field_add ( L2, L3, L3 ); - field_sub ( b, L1, L2 ); - field_sqr ( L2, a->z ); - field_sqr ( L1, L2 ); - field_add ( b, b, b ); - field_mulw_scc ( L2, b, EDWARDS_D-1 ); - field_mulw_scc ( b, L2, EDWARDS_D-1 ); - field_mul ( L0, L2, L1 ); - field_mul ( L2, b, L0 ); - field_isr ( L0, L2 ); - field_mul ( L1, b, L0 ); - field_sqr ( b, L0 ); - field_mul ( L0, L2, b ); - field_mul ( b, L1, L3 ); -} - -void -twist_even ( - tw_extensible_a_t b, - const extensible_a_t a -) { - field_sqr ( b->y, a->z ); - field_sqr ( b->z, a->x ); - field_sub ( b->u, b->y, b->z ); - field_sub ( b->z, a->z, a->x ); - field_mul ( b->y, b->z, a->y ); - field_sub ( b->z, a->z, a->y ); - field_mul ( b->x, b->z, b->y ); - field_mul ( b->t, b->x, b->u ); - field_mul ( b->y, b->x, b->t ); - field_isr ( b->t, b->y ); - field_mul ( b->u, b->x, b->t ); - field_sqr ( b->x, b->t ); - field_mul ( b->t, b->y, b->x ); - field_mul ( b->x, a->x, b->u ); - field_mul ( b->y, a->y, b->u ); - field_addw ( b->y, -field_is_zero( b->z ) ); - field_set_ui( b->z, 1 ); - field_copy ( b->t, b->x ); - field_copy ( b->u, b->y ); -} - -void -test_only_twist ( - tw_extensible_a_t b, - const extensible_a_t a -) { - field_a_t L0, L1; - field_sqr ( b->u, a->z ); - field_sqr ( b->y, a->x ); - field_sub ( b->z, b->u, b->y ); - field_add ( b->y, b->z, b->z ); - field_add ( b->u, b->y, b->y ); - field_sub ( b->y, a->z, a->x ); - field_mul ( b->x, b->y, a->y ); - field_sub ( b->z, a->z, a->y ); - field_mul ( b->t, b->z, b->x ); - field_mul ( L1, b->t, b->u ); - field_mul ( b->x, b->t, L1 ); - field_isr ( L0, b->x ); - field_mul ( b->u, b->t, L0 ); - field_sqr ( L1, L0 ); - field_mul ( b->t, b->x, L1 ); - field_add ( L1, a->y, a->x ); - field_sub ( L0, a->x, a->y ); - field_mul ( b->x, b->t, L0 ); - field_add ( L0, b->x, L1 ); - field_sub ( b->t, L1, b->x ); - field_mul ( b->x, L0, b->u ); - field_addw ( b->x, -field_is_zero( b->y ) ); - field_mul ( b->y, b->t, b->u ); - field_addw ( b->y, -field_is_zero( b->z ) ); - field_set_ui( b->z, 1+field_is_zero( a->y ) ); - field_copy ( b->t, b->x ); - field_copy ( b->u, b->y ); -} - -mask_t -is_even_pt ( - const extensible_a_t a -) { - field_a_t L0, L1, L2; - field_sqr ( L2, a->z ); - field_sqr ( L1, a->x ); - field_sub ( L0, L2, L1 ); - return field_is_square ( L0 ); -} - -mask_t -is_even_tw ( - const tw_extensible_a_t a -) { - field_a_t L0, L1, L2; - field_sqr ( L2, a->z ); - field_sqr ( L1, a->x ); - field_add ( L0, L1, L2 ); - return field_is_square ( L0 ); -} - -mask_t -deserialize_affine ( - affine_a_t a, - const field_a_t sz -) { - field_a_t L0, L1, L2, L3; - field_sqr ( L1, sz ); - field_copy ( L3, L1 ); - field_addw ( L3, 1 ); - field_sqr ( L2, L3 ); - field_mulw_scc ( a->x, L2, EDWARDS_D-1 ); /* PERF MULW */ - field_add ( L3, L1, L1 ); - field_add ( a->y, L3, L3 ); - field_add ( L3, a->y, a->x ); - field_copy ( a->y, L1 ); - field_neg ( a->x, a->y ); - field_addw ( a->x, 1 ); - field_mul ( a->y, a->x, L3 ); - field_sqr ( L2, a->x ); - field_mul ( L0, L2, a->y ); - field_mul ( a->y, a->x, L0 ); - field_isr ( L3, a->y ); - field_mul ( a->y, L2, L3 ); - field_sqr ( L2, L3 ); - field_mul ( L3, L0, L2 ); - field_mul ( L0, a->x, L3 ); - field_add ( L2, a->y, a->y ); - field_mul ( a->x, sz, L2 ); - field_addw ( L1, 1 ); - field_mul ( a->y, L1, L3 ); - field_subw( L0, 1 ); - return field_is_zero( L0 ); -} - -mask_t -deserialize_and_twist_approx ( - tw_extensible_a_t a, - const field_a_t sz -) { - field_a_t L0, L1; - field_sqr ( a->z, sz ); - field_copy ( a->y, a->z ); - field_addw ( a->y, 1 ); - field_sqr ( L0, a->y ); - field_mulw_scc ( a->x, L0, EDWARDS_D-1 ); - field_add ( a->y, a->z, a->z ); - field_add ( a->u, a->y, a->y ); - field_add ( a->y, a->u, a->x ); - field_sqr ( a->x, a->z ); - field_neg ( a->u, a->x ); - field_addw ( a->u, 1 ); - field_mul ( a->x, sqrt_d_minus_1, a->u ); - field_mul ( L0, a->x, a->y ); - field_mul ( a->t, L0, a->y ); - field_mul ( a->u, a->x, a->t ); - field_mul ( a->t, a->u, L0 ); - field_mul ( a->y, a->x, a->t ); - field_isr ( L0, a->y ); - field_mul ( a->y, a->u, L0 ); - field_sqr ( L1, L0 ); - field_mul ( a->u, a->t, L1 ); - field_mul ( a->t, a->x, a->u ); - field_add ( a->x, sz, sz ); - field_mul ( L0, a->u, a->x ); - field_copy ( a->x, a->z ); - field_neg ( L1, a->x ); - field_addw ( L1, 1 ); - field_mul ( a->x, L1, L0 ); - field_mul ( L0, a->u, a->y ); - field_addw ( a->z, 1 ); - field_mul ( a->y, a->z, L0 ); - field_subw( a->t, 1 ); - mask_t ret = field_is_zero( a->t ); - field_set_ui( a->z, 1 ); - field_copy ( a->t, a->x ); - field_copy ( a->u, a->y ); - return ret; -} - -void -set_identity_extensible ( - extensible_a_t a -) { - field_set_ui( a->x, 0 ); - field_set_ui( a->y, 1 ); - field_set_ui( a->z, 1 ); - field_set_ui( a->t, 0 ); - field_set_ui( a->u, 0 ); -} - -void -set_identity_tw_extended ( - tw_extended_a_t a -) { - field_set_ui( a->x, 0 ); - field_set_ui( a->y, 1 ); - field_set_ui( a->z, 1 ); - field_set_ui( a->t, 0 ); -} - -void -set_identity_tw_extensible ( - tw_extensible_a_t a -) { - field_set_ui( a->x, 0 ); - field_set_ui( a->y, 1 ); - field_set_ui( a->z, 1 ); - field_set_ui( a->t, 0 ); - field_set_ui( a->u, 0 ); -} - -void -set_identity_affine ( - affine_a_t a -) { - field_set_ui( a->x, 0 ); - field_set_ui( a->y, 1 ); -} - -mask_t -decaf_eq_extensible ( - const struct extensible_t* a, - const struct extensible_t* b -) { - field_a_t L0, L1; - field_mul ( L0, b->y, a->x ); - field_mul ( L1, a->y, b->x ); - return field_eq(L0,L1); -} - -mask_t -decaf_eq_tw_extended ( - const tw_extended_a_t a, - const tw_extended_a_t b -) { - field_a_t L0, L1; - field_mul ( L0, b->y, a->x ); - field_mul ( L1, a->y, b->x ); - return field_eq(L0,L1); -} - -mask_t -decaf_eq_tw_extensible ( - const struct tw_extensible_t* a, - const struct tw_extensible_t* b -) { - field_a_t L0, L1, L2; - field_mul ( L2, b->y, a->x ); - field_mul ( L1, a->y, b->x ); - field_sub ( L0, L2, L1 ); - field_bias ( L0, 2 ); - return field_is_zero ( L0 ); -} - -mask_t -eq_affine ( - const affine_a_t a, - const affine_a_t b -) { - mask_t L1, L2; - field_a_t L0; - field_sub ( L0, a->x, b->x ); - L2 = field_is_zero( L0 ); - field_sub ( L0, a->y, b->y ); - L1 = field_is_zero( L0 ); - return L2 & L1; -} - -mask_t -eq_extensible ( - const extensible_a_t a, - const extensible_a_t b -) { - mask_t L3, L4; - field_a_t L0, L1, L2; - field_mul ( L2, b->z, a->x ); - field_mul ( L1, a->z, b->x ); - field_sub ( L0, L2, L1 ); - L4 = field_is_zero( L0 ); - field_mul ( L2, b->z, a->y ); - field_mul ( L1, a->z, b->y ); - field_sub ( L0, L2, L1 ); - L3 = field_is_zero( L0 ); - return L4 & L3; -} - -mask_t -eq_tw_extensible ( - const tw_extensible_a_t a, - const tw_extensible_a_t b -) { - mask_t L3, L4; - field_a_t L0, L1, L2; - field_mul ( L2, b->z, a->x ); - field_mul ( L1, a->z, b->x ); - field_sub ( L0, L2, L1 ); - L4 = field_is_zero( L0 ); - field_mul ( L2, b->z, a->y ); - field_mul ( L1, a->z, b->y ); - field_sub ( L0, L2, L1 ); - L3 = field_is_zero( L0 ); - return L4 & L3; -} - -void -elligator_2s_inject ( - affine_a_t a, - const field_a_t r -) { - field_a_t L2, L3, L4, L5, L6, L7, L8; - field_sqr ( a->x, r ); - field_sqr ( L3, a->x ); - field_copy ( a->y, L3 ); - field_neg ( L4, a->y ); - field_addw ( L4, 1 ); - field_sqr ( L2, L4 ); - field_mulw ( L7, L2, (EDWARDS_D-1)*(EDWARDS_D-1) ); - field_mulw ( L8, L3, 4*(EDWARDS_D+1)*(EDWARDS_D+1) ); - field_add ( a->y, L8, L7 ); - field_mulw ( L8, L2, 4*(EDWARDS_D)*(EDWARDS_D-1) ); - field_sub ( L7, a->y, L8 ); - field_mulw_scc ( L6, a->y, -2-2*EDWARDS_D ); - field_mul ( L5, L7, L6 ); - /* FIXME Stability problem (API stability, not crash) / possible bug. - * change to: p448_mul ( L5, L7, L4 ); ? - * This isn't a deep change: it's for sign adjustment. - * Need to check which one leads to the correct sign, probably by writig - * the invert routine. - * - * Also, the tool doesn't produce the optimal route to this. - * Let incoming L6 = a, L7 = e, L4 = b. - * - * Could compute be, (be)^2, (be)^3, a b^3 e^3, a b^3 e^4. = 4M+S - * instead of 6M. - */ - field_mul ( L8, L5, L4 ); - field_mul ( L4, L5, L6 ); - field_mul ( L5, L7, L8 ); - field_mul ( L8, L5, L4 ); - field_mul ( L4, L7, L8 ); - field_isr ( L6, L4 ); - field_mul ( L4, L5, L6 ); - field_sqr ( L5, L6 ); - field_mul ( L6, L8, L5 ); - field_mul ( L8, L7, L6 ); - field_mul ( L7, L8, L6 ); - field_copy ( L6, a->x ); - field_addw ( a->x, 1 ); - field_mul ( L5, a->x, L8 ); - field_addw ( L5, 1 ); - field_sub ( a->x, L6, L5 ); - field_mul ( L5, L4, a->x ); - field_mulw_scc_wr ( a->x, L5, -2-2*EDWARDS_D ); - field_add ( L4, L3, L3 ); - field_add ( L3, L4, L2 ); - field_subw( L3, 2 ); - field_mul ( L2, L3, L8 ); - field_mulw ( L3, L2, 2*(EDWARDS_D+1)*(EDWARDS_D-1) ); - field_add ( L2, L3, a->y ); - field_mul ( a->y, L7, L2 ); - field_addw ( a->y, -field_is_zero( L8 ) ); -} - -mask_t -validate_affine ( - const affine_a_t a -) { - field_a_t L0, L1, L2, L3; - field_sqr ( L0, a->y ); - field_sqr ( L1, a->x ); - field_add ( L3, L1, L0 ); - field_mulw_scc ( L2, L1, EDWARDS_D ); - field_mul ( L1, L0, L2 ); - field_addw ( L1, 1 ); - field_sub ( L0, L3, L1 ); - return field_is_zero( L0 ); -} - -mask_t -validate_tw_extensible ( - const tw_extensible_a_t ext -) { - mask_t L4, L5; - field_a_t L0, L1, L2, L3; - /* - * Check invariant: - * 0 = -x*y + z*t*u - */ - field_mul ( L1, ext->t, ext->u ); - field_mul ( L2, ext->z, L1 ); - field_mul ( L0, ext->x, ext->y ); - field_neg ( L1, L0 ); - field_add ( L0, L1, L2 ); - L5 = field_is_zero( L0 ); - /* - * Check invariant: - * 0 = d*t^2*u^2 + x^2 - y^2 + z^2 - t^2*u^2 - */ - field_sqr ( L2, ext->y ); - field_neg ( L1, L2 ); - field_sqr ( L0, ext->x ); - field_add ( L2, L0, L1 ); - field_sqr ( L3, ext->u ); - field_sqr ( L0, ext->t ); - field_mul ( L1, L0, L3 ); - field_mulw_scc ( L3, L1, EDWARDS_D ); - field_add ( L0, L3, L2 ); - field_neg ( L3, L1 ); - field_add ( L2, L3, L0 ); - field_sqr ( L1, ext->z ); - field_add ( L0, L1, L2 ); - L4 = field_is_zero( L0 ); - return L5 & L4 &~ field_is_zero(ext->z); -} - -mask_t -validate_extensible ( - const extensible_a_t ext -) { - mask_t L4, L5; - field_a_t L0, L1, L2, L3; - /* - * Check invariant: - * 0 = d*t^2*u^2 - x^2 - y^2 + z^2 - */ - field_sqr ( L2, ext->y ); - field_neg ( L1, L2 ); - field_sqr ( L0, ext->z ); - field_add ( L2, L0, L1 ); - field_sqr ( L3, ext->u ); - field_sqr ( L0, ext->t ); - field_mul ( L1, L0, L3 ); - field_mulw_scc ( L0, L1, EDWARDS_D ); - field_add ( L1, L0, L2 ); - field_sqr ( L0, ext->x ); - field_neg ( L2, L0 ); - field_add ( L0, L2, L1 ); - L5 = field_is_zero( L0 ); - /* - * Check invariant: - * 0 = -x*y + z*t*u - */ - field_mul ( L1, ext->t, ext->u ); - field_mul ( L2, ext->z, L1 ); - field_mul ( L0, ext->x, ext->y ); - field_neg ( L1, L0 ); - field_add ( L0, L1, L2 ); - L4 = field_is_zero( L0 ); - return L5 & L4 &~ field_is_zero(ext->z); -} diff --git a/src/goldilocks.c b/src/goldilocks.c deleted file mode 100644 index 866ed10..0000000 --- a/src/goldilocks.c +++ /dev/null @@ -1,576 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "config.h" -#include "word.h" - -#include - -#if GOLDILOCKS_USE_PTHREAD -#include -#endif - -#include "goldilocks.h" -#include "ec_point.h" -#include "scalarmul.h" -#include "barrett_field.h" -#include "crandom.h" -#include "sha512.h" -#include "intrinsics.h" - -#ifndef GOLDILOCKS_RANDOM_INIT_FILE -#define GOLDILOCKS_RANDOM_INIT_FILE "/dev/urandom" -#endif - -#ifndef GOLDILOCKS_RANDOM_RESEED_INTERVAL -#define GOLDILOCKS_RANDOM_RESEED_INTERVAL 10000 -#endif - -/* We'll check it ourselves */ -#ifndef GOLDILOCKS_RANDOM_RESEEDS_MANDATORY -#define GOLDILOCKS_RANDOM_RESEEDS_MANDATORY 0 -#endif - -#define GOLDI_DIVERSIFY_BYTES 8 - - -#if FIELD_BYTES <= SHA512_OUTPUT_BYTES -#define FIELD_HASH_BYTES SHA512_OUTPUT_BYTES -#define field_hash_final sha512_final -#else -#define FIELD_HASH_BYTES (SHA512_OUTPUT_BYTES * ((FIELD_BYTES-1)/SHA512_OUTPUT_BYTES + 1)) -static inline void field_hash_final ( - sha512_ctx_a_t ctx, - unsigned char out[FIELD_HASH_BYTES] -) { - /* SHA PRNG I guess? I really should have used SHAKE */ - int i; - for (i=0; i<= (FIELD_BYTES-1) / SHA512_OUTPUT_BYTES; i++) { - if (i) - sha512_update(ctx, &out[(i-1)*SHA512_OUTPUT_BYTES], SHA512_OUTPUT_BYTES); - sha512_final(ctx, &out[i*SHA512_OUTPUT_BYTES]); - } -} -#endif - - -/* These are just unique identifiers */ -static const char *G_INITING = "initializing"; -static const char *G_INITED = "initialized"; -static const char *G_FAILED = "failed to initialize"; - -struct goldilocks_precomputed_public_key_t { - struct goldilocks_public_key_t pub; - struct fixed_base_table_t table; -}; - -/* FUTURE: auto. */ -static struct { - const char * volatile status; -#if GOLDILOCKS_USE_PTHREAD - pthread_mutex_t mutex; -#endif - tw_niels_a_t combs[COMB_N << (COMB_T-1)]; - struct fixed_base_table_t fixed_base; - tw_niels_a_t wnafs[1<opaque[2*GOLDI_FIELD_BYTES], proto, GOLDI_SYMKEY_BYTES); - - unsigned char skb[FIELD_HASH_BYTES]; - word_t sk[GOLDI_FIELD_WORDS]; - assert(sizeof(skb) >= sizeof(sk)); - - sha512_ctx_a_t ctx; - tw_extensible_a_t exta; - field_a_t pk; - - sha512_init(ctx); - sha512_update(ctx, (const unsigned char *)"derivepk", GOLDI_DIVERSIFY_BYTES); - sha512_update(ctx, proto, GOLDI_SYMKEY_BYTES); - field_hash_final(ctx, (unsigned char *)skb); - - barrett_deserialize_and_reduce(sk, skb, sizeof(skb), &curve_prime_order); - barrett_serialize(privkey->opaque, sk, GOLDI_FIELD_BYTES); - - scalarmul_fixed_base(exta, sk, GOLDI_SCALAR_BITS, &goldilocks_global.fixed_base); - untwist_and_double_and_serialize(pk, exta); - - field_serialize(&privkey->opaque[GOLDI_FIELD_BYTES], pk); - - return GOLDI_EOK; -} - -void -goldilocks_underive_private_key ( - unsigned char proto[GOLDI_SYMKEY_BYTES], - const struct goldilocks_private_key_t *privkey -) { - memcpy(proto, &privkey->opaque[2*GOLDI_FIELD_BYTES], GOLDI_SYMKEY_BYTES); -} - -int -goldilocks_keygen ( - struct goldilocks_private_key_t *privkey, - struct goldilocks_public_key_t *pubkey -) { - if (!goldilocks_check_init()) { - return GOLDI_EUNINIT; - } - - unsigned char proto[GOLDI_SYMKEY_BYTES]; - -#if GOLDILOCKS_USE_PTHREAD - int ml_ret = pthread_mutex_lock(&goldilocks_global.mutex); - if (ml_ret) return ml_ret; -#endif - - int ret = crandom_generate(goldilocks_global.rand, proto, sizeof(proto)); - -#if GOLDILOCKS_USE_PTHREAD - ml_ret = pthread_mutex_unlock(&goldilocks_global.mutex); - if (ml_ret) abort(); -#endif - - int ret2 = goldilocks_derive_private_key(privkey, proto); - if (!ret) ret = ret2; - - ret2 = goldilocks_private_to_public(pubkey, privkey); - if (!ret) ret = ret2; - - return ret ? GOLDI_ENODICE : GOLDI_EOK; -} - -int -goldilocks_private_to_public ( - struct goldilocks_public_key_t *pubkey, - const struct goldilocks_private_key_t *privkey -) { - field_a_t pk; - mask_t msucc = field_deserialize(pk,&privkey->opaque[GOLDI_FIELD_BYTES]); - - if (msucc) { - field_serialize(pubkey->opaque, pk); - return GOLDI_EOK; - } else { - return GOLDI_ECORRUPT; - } -} - -static int -goldilocks_shared_secret_core ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_public_key_t *your_pubkey, - const struct goldilocks_precomputed_public_key_t *pre -) { - uint8_t gxy[GOLDI_FIELD_BYTES]; - - /* This function doesn't actually need anything in goldilocks_global, - * so it doesn't check init. - */ - - assert(GOLDI_SHARED_SECRET_BYTES == SHA512_OUTPUT_BYTES); - - word_t sk[GOLDI_FIELD_WORDS]; - field_a_t pk; - - mask_t succ = field_deserialize(pk,your_pubkey->opaque), msucc = -1; - -#ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS - field_a_t sum, prod; - msucc &= field_deserialize(sum,&my_privkey->opaque[GOLDI_FIELD_BYTES]); - field_mul(prod,pk,sum); - field_add(sum,pk,sum); -#endif - - msucc &= barrett_deserialize(sk,my_privkey->opaque,&curve_prime_order); - -#if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS - if (pre) { - tw_extensible_a_t tw; - succ &= scalarmul_fixed_base(tw, sk, GOLDI_SCALAR_BITS, &pre->table); - untwist_and_double_and_serialize(pk, tw); - } else { - succ &= montgomery_ladder(pk,pk,sk,GOLDI_SCALAR_BITS,1); - } -#else - (void)pre; - succ &= montgomery_ladder(pk,pk,sk,GOLDI_SCALAR_BITS,1); -#endif - - - field_serialize(gxy,pk); - - /* obliterate records of our failure by adjusting with obliteration key */ - sha512_ctx_a_t ctx; - sha512_init(ctx); - -#ifdef EXPERIMENT_ECDH_OBLITERATE_CT - uint8_t oblit[GOLDI_DIVERSIFY_BYTES + GOLDI_SYMKEY_BYTES]; - unsigned i; - for (i=0; iopaque[2*GOLDI_FIELD_BYTES+i] & ~(succ&msucc); - } - sha512_update(ctx, oblit, sizeof(oblit)); -#endif - -#ifdef EXPERIMENT_ECDH_STIR_IN_PUBKEYS - /* stir in the sum and product of the pubkeys. */ - uint8_t a_pk[GOLDI_FIELD_BYTES]; - field_serialize(a_pk, sum); - sha512_update(ctx, a_pk, GOLDI_FIELD_BYTES); - field_serialize(a_pk, prod); - sha512_update(ctx, a_pk, GOLDI_FIELD_BYTES); -#endif - - /* stir in the shared key and finish */ - sha512_update(ctx, gxy, GOLDI_FIELD_BYTES); - sha512_final(ctx, shared); - - return (GOLDI_ECORRUPT & ~msucc) - | (GOLDI_EINVAL & msucc &~ succ) - | (GOLDI_EOK & msucc & succ); -} - -int -goldilocks_shared_secret ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_public_key_t *your_pubkey -) { - return goldilocks_shared_secret_core( - shared, - my_privkey, - your_pubkey, - NULL - ); -} - -#if GOLDI_IMPLEMENT_SIGNATURES -static void -goldilocks_derive_challenge( - word_t challenge[GOLDI_FIELD_WORDS], - const unsigned char pubkey[GOLDI_FIELD_BYTES], - const unsigned char gnonce[GOLDI_FIELD_BYTES], - const unsigned char *message, - uint64_t message_len -) { - /* challenge = H(pk, [nonceG], message). */ - unsigned char sha_out[FIELD_HASH_BYTES]; - sha512_ctx_a_t ctx; - sha512_init(ctx); - sha512_update(ctx, pubkey, GOLDI_FIELD_BYTES); - sha512_update(ctx, gnonce, GOLDI_FIELD_BYTES); - sha512_update(ctx, message, message_len); - field_hash_final(ctx, sha_out); - barrett_deserialize_and_reduce(challenge, sha_out, sizeof(sha_out), &curve_prime_order); -} - -int -goldilocks_sign ( - uint8_t signature_out[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_private_key_t *privkey -) { - if (!goldilocks_check_init()) { - return GOLDI_EUNINIT; - } - - /* challenge = H(pk, [nonceG], message). */ - word_t skw[GOLDI_FIELD_WORDS]; - mask_t succ = barrett_deserialize(skw,privkey->opaque,&curve_prime_order); - if (!succ) { - really_memset(skw,0,sizeof(skw)); - return GOLDI_ECORRUPT; - } - - /* Derive a nonce. TODO: use HMAC. FUTURE: factor. */ - unsigned char sha_out[FIELD_HASH_BYTES]; - word_t tk[GOLDI_FIELD_WORDS]; - sha512_ctx_a_t ctx; - sha512_init(ctx); - sha512_update(ctx, (const unsigned char *)"signonce", 8); - sha512_update(ctx, &privkey->opaque[2*GOLDI_FIELD_BYTES], GOLDI_SYMKEY_BYTES); - sha512_update(ctx, message, message_len); - sha512_update(ctx, &privkey->opaque[2*GOLDI_FIELD_BYTES], GOLDI_SYMKEY_BYTES); - field_hash_final(ctx, sha_out); - barrett_deserialize_and_reduce(tk, sha_out, sizeof(sha_out), &curve_prime_order); - - /* 4[nonce]G */ - uint8_t signature_tmp[GOLDI_FIELD_BYTES]; - tw_extensible_a_t exta; - field_a_t gsk; - scalarmul_fixed_base(exta, tk, GOLDI_SCALAR_BITS, &goldilocks_global.fixed_base); - double_tw_extensible(exta); - untwist_and_double_and_serialize(gsk, exta); - field_serialize(signature_tmp, gsk); - - word_t challenge[GOLDI_FIELD_WORDS]; - goldilocks_derive_challenge ( - challenge, - &privkey->opaque[GOLDI_FIELD_BYTES], - signature_tmp, - message, - message_len - ); - - /* reduce challenge and sub. */ - barrett_negate(challenge,GOLDI_FIELD_WORDS,&curve_prime_order); - - barrett_mac( - tk,GOLDI_FIELD_WORDS, - challenge,GOLDI_FIELD_WORDS, - skw,GOLDI_FIELD_WORDS, - &curve_prime_order - ); - - word_t carry = add_nr_ext_packed(tk,tk,GOLDI_FIELD_WORDS,tk,GOLDI_FIELD_WORDS,-1); - barrett_reduce(tk,GOLDI_FIELD_WORDS,carry,&curve_prime_order); - - memcpy(signature_out, signature_tmp, GOLDI_FIELD_BYTES); - barrett_serialize(signature_out+GOLDI_FIELD_BYTES, tk, GOLDI_FIELD_BYTES); - really_memset((unsigned char *)tk,0,sizeof(tk)); - really_memset((unsigned char *)skw,0,sizeof(skw)); - really_memset((unsigned char *)challenge,0,sizeof(challenge)); - - /* response = 2(nonce_secret - sk*challenge) - * Nonce = 8[nonce_secret]*G - * PK = 2[sk]*G, except doubled (TODO) - * so [2] ( [response]G + 2[challenge]PK ) = Nonce - */ - - return 0; -} - -int -goldilocks_verify ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_public_key_t *pubkey -) { - if (!goldilocks_check_init()) { - return GOLDI_EUNINIT; - } - - field_a_t pk; - word_t s[GOLDI_FIELD_WORDS]; - - mask_t succ = field_deserialize(pk,pubkey->opaque); - if (!succ) return GOLDI_EINVAL; - - succ = barrett_deserialize(s, &signature[GOLDI_FIELD_BYTES], &curve_prime_order); - if (!succ) return GOLDI_EINVAL; - - word_t challenge[GOLDI_FIELD_WORDS]; - goldilocks_derive_challenge(challenge, pubkey->opaque, signature, message, message_len); - - field_a_t eph; - tw_extensible_a_t pk_text; - - /* deserialize [nonce]G */ - succ = field_deserialize(eph, signature); - if (!succ) return GOLDI_EINVAL; - - succ = deserialize_and_twist_approx(pk_text, pk); - if (!succ) return GOLDI_EINVAL; - - linear_combo_var_fixed_vt( pk_text, - challenge, GOLDI_SCALAR_BITS, - s, GOLDI_SCALAR_BITS, - (const tw_niels_a_t*)goldilocks_global.wnafs, WNAF_PRECMP_BITS ); - - untwist_and_double_and_serialize( pk, pk_text ); - - succ = field_eq(eph, pk); - return succ ? 0 : GOLDI_EINVAL; -} -#endif - -#if GOLDI_IMPLEMENT_PRECOMPUTED_KEYS - -struct goldilocks_precomputed_public_key_t * -goldilocks_precompute_public_key ( - const struct goldilocks_public_key_t *pub -) { - struct goldilocks_precomputed_public_key_t *precom; - precom = (struct goldilocks_precomputed_public_key_t *) - malloc(sizeof(*precom)); - - if (!precom) return NULL; - - tw_extensible_a_t pk_text; - - field_a_t pk; - mask_t succ = field_deserialize(pk, pub->opaque); - if (!succ) { - free(precom); - return NULL; - } - - succ = deserialize_and_twist_approx(pk_text, pk); - if (!succ) { - free(precom); - return NULL; - } - - succ = precompute_fixed_base(&precom->table, pk_text, - COMB_N, COMB_T, COMB_S, NULL); - if (!succ) { - free(precom); - return NULL; - } - - memcpy(&precom->pub,pub,sizeof(*pub)); - - return precom; -} - -void -goldilocks_destroy_precomputed_public_key ( - struct goldilocks_precomputed_public_key_t *precom -) { - if (!precom) return; - destroy_fixed_base(&precom->table); - really_memset(&precom->pub.opaque, 0, sizeof(precom->pub)); - free(precom); -} - -int -goldilocks_verify_precomputed ( - const uint8_t signature[GOLDI_SIGNATURE_BYTES], - const uint8_t *message, - uint64_t message_len, - const struct goldilocks_precomputed_public_key_t *pubkey -) { - if (!goldilocks_check_init()) { - return GOLDI_EUNINIT; - } - - word_t s[GOLDI_FIELD_WORDS]; - mask_t succ = barrett_deserialize(s, &signature[GOLDI_FIELD_BYTES], &curve_prime_order); - if (!succ) return GOLDI_EINVAL; - - word_t challenge[GOLDI_FIELD_WORDS]; - goldilocks_derive_challenge(challenge, pubkey->pub.opaque, signature, message, message_len); - - field_a_t eph, pk; - tw_extensible_a_t pk_text; - - /* deserialize [nonce]G */ - succ = field_deserialize(eph, signature); - if (!succ) return GOLDI_EINVAL; - - succ = linear_combo_combs_vt ( - pk_text, - challenge, GOLDI_SCALAR_BITS, &pubkey->table, - s, GOLDI_SCALAR_BITS, &goldilocks_global.fixed_base - ); - if (!succ) return GOLDI_EINVAL; - - untwist_and_double_and_serialize( pk, pk_text ); - - succ = field_eq(eph, pk); - return succ ? 0 : GOLDI_EINVAL; -} - -int -goldilocks_shared_secret_precomputed ( - uint8_t shared[GOLDI_SHARED_SECRET_BYTES], - const struct goldilocks_private_key_t *my_privkey, - const struct goldilocks_precomputed_public_key_t *your_pubkey -) { - return goldilocks_shared_secret_core( - shared, - my_privkey, - &your_pubkey->pub, - your_pubkey - ); -} - -#endif /* GOLDI_IMPLEMENT_PRECOMPUTED_KEYS */ - diff --git a/src/include/barrett_field.h b/src/include/barrett_field.h deleted file mode 100644 index 0331f72..0000000 --- a/src/include/barrett_field.h +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ -#ifndef __BARRETT_FIELD_H__ -#define __BARRETT_FIELD_H__ 1 - -/** - * @file barrett_field.h - * @brief Slow routines for generic primes in Barrett form. - * - * @warning These routines are very slow, roughly implemented, and should be made more - * flexible in the future. I might even outright switch to Montgomery form. - */ - -#include "word.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief A Barrett-form prime, 2^k - c. - * @todo Support primes of other forms. - */ -struct barrett_prime_t { - uint32_t nwords_p; /**< The number of bits in p, i.e. ceiling((k-1) / WORD_BITS) */ - uint32_t p_shift; /**< c mod WORD_BITS. */ - uint32_t nwords_lo; /**< The number of nonzero low words. */ - const word_t *p_lo; /**< The low words. */ -}; - -/** - * The Goldilocks prime. I'm not sure this is the right place for it, but oh well. - */ -extern const struct barrett_prime_t curve_prime_order; - -/** - * Reduce a number (with optional high carry word) mod p. - * - * @param [in,out] a The value to be reduced. - * @param [in] nwords_a The number of words in a. - * @param [in] a_carry A high word to be carried into the computation. - * @param [in] prime The Barrett prime. - */ -void -barrett_reduce( - word_t *a, - uint32_t nwords_a, - word_t a_carry, - const struct barrett_prime_t *prime -); - -/** - * out = a+(c&mask), returning a carry. - * - * @param [out] out The output, of length nwords_a. - * @param [in] a The "always" addend. - * @param [in] nwords_a The number of words in a. - * @param [in] c The "sometimes" addend. - * @param [in] nwords_c The number of words in c. - * @param [in] mask A mask of whether to add or not. - * @return A carry word. - */ -word_t -add_nr_ext_packed( - word_t *out, - const word_t *a, - uint32_t nwords_a, - const word_t *c, - uint32_t nwords_c, - word_t mask -); - -/** - * out = a-(c&mask), returning a borrow. - * - * @param [out] out The output, of length nwords_a. - * @param [in] a The "always" minuend. - * @param [in] nwords_a The number of words in a. - * @param [in] c The "sometimes" subtrahend. - * @param [in] nwords_c The number of words in c. - * @param [in] mask A mask of whether to add or not. - * @return A borrow word. - */ -word_t -sub_nr_ext_packed( - word_t *out, - const word_t *a, - uint32_t nwords_a, - const word_t *c, - uint32_t nwords_c, - word_t mask -); - -/** - * a -> reduce(-a) mod p - * - * @param [in] a The value to be reduced and negated. - * @param [in] nwords_a The number of words in a. Must be >= nwords_p. - * @param [in] prime The prime. - */ -void -barrett_negate ( - word_t *a, - uint32_t nwords_a, - const struct barrett_prime_t *prime -); - -/* - * If doMac, accum = accum + a*b mod p. - * Otherwise, accum = a*b mod p. - * - * This function is not __restrict__; you may pass accum, - * a, b, etc all from the same location. - */ -void -barrett_mul_or_mac( - word_t *accum, - uint32_t nwords_accum, - - const word_t *a, - uint32_t nwords_a, - - const word_t *b, - uint32_t nwords_b, - - const struct barrett_prime_t *prime, - - mask_t doMac -); - -static inline void -barrett_mul( - word_t *out, - uint32_t nwords_out, - - const word_t *a, - uint32_t nwords_a, - - const word_t *b, - uint32_t nwords_b, - - const struct barrett_prime_t *prime -) { - barrett_mul_or_mac(out,nwords_out,a,nwords_a,b,nwords_b,prime,0); -} - -static inline void -barrett_mac( - word_t *out, - uint32_t nwords_out, - - const word_t *a, - uint32_t nwords_a, - - const word_t *b, - uint32_t nwords_b, - - const struct barrett_prime_t *prime -) { - barrett_mul_or_mac(out,nwords_out,a,nwords_a,b,nwords_b,prime,-(mask_t)1); -} - -mask_t -barrett_deserialize ( - word_t *x, - const uint8_t *serial, - const struct barrett_prime_t *prime -); - -void -barrett_serialize ( - uint8_t *serial, - const word_t *x, - uint32_t nserial -); - -void -barrett_deserialize_and_reduce ( - word_t *x, - const uint8_t *serial, - uint32_t nserial, - const struct barrett_prime_t *prime -); - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __BARRETT_FIELD_H__ */ diff --git a/src/include/config.h b/src/include/config.h deleted file mode 100644 index bf5e384..0000000 --- a/src/include/config.h +++ /dev/null @@ -1,76 +0,0 @@ -/** - * @file config.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief Goldilocks top-level configuration flags. - */ - -#ifndef __GOLDILOCKS_CONFIG_H__ -#define __GOLDILOCKS_CONFIG_H__ 1 - -/** @brief crandom architecture detection. - * With this flag set to 1, crandom will assume that any flag - * supported by -march and friends (MIGHT_HAVE) will actually - * be available on the target machine (MUST_HAVE), instead of - * trying to detect it. - * - * Without this flag, crandom can detect, eg, that while -mavx - * was passed, the currint machine doesn't support AVX, and can - * fall back to SSE2 or whatever. But the rest of the - * Goldilocks code doesn't support this, so it'll still crash - * with an illegal instruction error. - * - * Setting this flag will make the library smaller. - */ -#define CRANDOM_MIGHT_IS_MUST 1 - -/** - * @brief Causes crandom to refuse to buffer requests bigger - * than this size. Setting 0 disables buffering for all - * requests, which hurts performance. - * - * The advantage is that if a user process forks or is VM- - * snapshotted, the buffer is not adjusted (FUTURE). However, - * with the buffer disabled, the refresh routines will stir - * in entropy from RDTSC and/or RDRAND, making this operation - * mostly-safe. - */ -#define EXPERIMENT_CRANDOM_BUFFER_CUTOFF_BYTES 0 - -/** - * @brief Goldilocks uses libpthread mutexes to provide - * thread-safety. If you disable this flag, it won't link - * libpthread, but it won't be thread-safe either. - */ -#define GOLDILOCKS_USE_PTHREAD 1 - -/** - * @brief Experiment to change the hash inputs for ECDH, - * in a way that obliterates the result -- overwriting it with - * a safe pseudorandom value -- if the public key is invalid. - * That way users who ignore the status result won't be - * exposed to invalid key attacks. - */ -#define EXPERIMENT_ECDH_OBLITERATE_CT 1 - -/** - * @brief Whether or not define the signing functions, which - * currently require SHA-512. - */ -#define GOLDI_IMPLEMENT_SIGNATURES 1 - -/** - * @brief Whether or not to define and implement functions - * working with pre-computed keys. - */ -#define GOLDI_IMPLEMENT_PRECOMPUTED_KEYS 1 - -/** - * @brief ECDH adds public keys into the hash, to prevent - * esoteric attacks. - */ -#define EXPERIMENT_ECDH_STIR_IN_PUBKEYS 1 - -#endif /* __GOLDILOCKS_CONFIG_H__ */ diff --git a/src/include/crandom.h b/src/include/crandom.h deleted file mode 100644 index 06dc583..0000000 --- a/src/include/crandom.h +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (c) 2011 Stanford University. - * Copyright (c) 2014-2015 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -/** - * @file crandom.h - * @author Mike Hamburg - * @brief A miniature version of the (as of yet incomplete) crandom project. - */ - -#ifndef __GOLDI_CRANDOM_H__ -#define __GOLDI_CRANDOM_H__ 1 - -#define _XOPEN_SOURCE 600 -#include /* for uint64_t */ -#include /* for open */ -#include /* for returning errors after open */ -#include /* for abort */ -#include /* for memcpy */ -#include /* for bzero */ -#include /* for read */ - -/** - * @brief The state of a crandom generator. - * - * This object is opaque. It is not protected by a lock, and so must - * not be accessed by multiple threads at the same time. - */ -struct crandom_state_t { - /** @privatesection */ - /* unsigned char seed[32]; */ - /* unsigned char buffer[96]; */ - unsigned char seedBuffer[32+96]; - uint64_t ctr; - uint64_t magic; - unsigned int fill; - int reseed_countdown; - int reseed_interval; - int reseeds_mandatory; - int randomfd; -} __attribute__((aligned(16))) ; -typedef struct crandom_state_t crandom_state_a_t[1]; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Initialize a crandom state from the chosen file. - * - * This function initializes a state from a given state file, or - * from a random device (eg. /dev/random or /dev/urandom). - * - * You must check the return value of this function. - * - * @param [out] state The crandom state variable to initalize. - * @param [in] filename The name of the seed file or random device. - * @param [in] reseed_interval The number of 96-byte blocks which can be - * generated without reseeding. Suggest 10000. - * @param [in] reseeds_mandatory If nonzero, call abort() if a reseed fails. - * Suggest 1. - * - * @retval 0 Success. - * @retval Nonzero An error to be interpreted by strerror(). - */ -int -crandom_init_from_file ( - crandom_state_a_t state, - const char *filename, - int reseed_interval, - int reseeds_mandatory -) __attribute__((warn_unused_result)); - - -/** - * Initialize a crandom state from a buffer, for deterministic operation. - * - * This function is used to initialize a crandom state deterministically, - * mainly for testing purposes. It can also be used to expand a secret - * random value deterministically. - * - * @warning The crandom implementation is not guaranteed to be stable. - * That is, a later release might produce a different random stream from - * the same seed. - * - * @param [out] state The crandom state variable to initalize. - * @param [in] initial_seed The seed value. - */ -void -crandom_init_from_buffer ( - crandom_state_a_t state, - const char initial_seed[32] -); - -/** - * Fill the output buffer with random data. - * - * This function uses the given crandom state to produce pseudorandom data - * in the output buffer. - * - * This function may perform reads from the state's random device if it needs - * to reseed. This could block if that file is a blocking source, such as - * a pipe or /dev/random on Linux. If reseeding fails and the state has - * reseeds_mandatory set, this function will call abort(). Otherwise, it will - * return an error code, but it will still randomize the buffer. - * - * If called on a corrupted, uninitialized or destroyed state, this function - * will abort(). - * - * @warning This function is not thread-safe with respect to the state. Don't - * call it from multiple threads with the same state at the same time. - * - * @param [inout] state The crandom state to use for generation. - * @param [out] output The buffer to fill with random data. - * @param [in] length The length of the buffer. - * - * @retval 0 Success. - * @retval Nonezero A non-mandatory reseed operation failed. - */ -int -crandom_generate ( - crandom_state_a_t state, - unsigned char *output, - unsigned long long length -); - -/** - * Destroy the random state. Further calls to crandom_generate() on that state - * will abort(). - * - * @param [inout] state The state to be destroyed. - */ -void -crandom_destroy ( - crandom_state_a_t state -); - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __GOLDI_CRANDOM_H__ */ diff --git a/src/include/ec_point.h b/src/include/ec_point.h deleted file mode 100644 index 9ad22f7..0000000 --- a/src/include/ec_point.h +++ /dev/null @@ -1,697 +0,0 @@ -/** - * @file ec_point.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * - * This file contains a huge number of different options for EC point arithmetic, - * but only a few of them will be used by any given library. They are here for - * reference and for consistency checks. The Goldilocks library link step strips - * out unused functions. - */ - -#ifndef __CC_INCLUDED_EC_POINT_H__ -#define __CC_INCLUDED_EC_POINT_H__ - -#include "field.h" -#include "constant_time.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * Affine point on an Edwards curve. - */ -typedef struct affine_t { - field_a_t x, y; -} affine_a_t[1]; - -/** - * Affine point on a twisted Edwards curve. - */ -typedef struct tw_affine_t { - field_a_t x, y; -} tw_affine_a_t[1]; - -/** - * Montgomery buffer. - */ -typedef struct montgomery_t { - field_a_t z0, xd, zd, xa, za; -} montgomery_a_t[1]; - -/** - * Montgomery buffer, augmented version. - */ -typedef struct montgomery_aux_t { - field_a_t s0, xd, zd, xa, za, xs, zs; -} montgomery_aux_a_t[1]; - -/** - * Extensible coordinates for Edwards curves, suitable for - * accumulators. - * - * Represents the point (x/z, y/z). The extra coordinates - * t,u satisfy xy = tuz, allowing for conversion to Extended - * form by multiplying t and u. - * - * The idea is that you don't have to do this multiplication - * when doubling the accumulator, because the t-coordinate - * isn't used there. At the same time, as long as you only - * have one point in extensible form, additions don't cost - * extra. - * - * This is essentially a lazier version of Hisil et al's - * lookahead trick. It might be worth considering that trick - * instead. - */ -typedef struct extensible_t { - field_a_t x, y, z, t, u; -} extensible_a_t[1]; - -/** - * Extensible coordinates for twisted Edwards curves, - * suitable for accumulators. - */ -typedef struct tw_extensible_t { - field_a_t x, y, z, t, u; -} tw_extensible_a_t[1]; - -/** - * Extended coordinates for twisted Edwards curves. - * Jack of all trades, master of none. - */ -typedef struct tw_extended_t { - field_a_t x, y, z, t; -} tw_extended_a_t[1]; - -/** - * Niels coordinates for twisted Edwards curves. - * - * Good for mixed readdition; suitable for fixed tables. - */ -typedef struct tw_niels_t { - field_a_t a, b, c; -} tw_niels_a_t[1]; - -/** - * Projective niels coordinates for twisted Edwards curves. - * - * Good for readdition; suitable for temporary tables. - */ -typedef struct tw_pniels_t { - tw_niels_a_t n; - field_a_t z; -} tw_pniels_a_t[1]; - - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_affine ( - affine_a_t a, - const affine_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_tw_affine ( - tw_affine_a_t a, - const tw_affine_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_montgomery ( - montgomery_a_t a, - const montgomery_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_extensible ( - extensible_a_t a, - const extensible_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_tw_extensible ( - tw_extensible_a_t a, - const tw_extensible_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_tw_extended ( - tw_extended_a_t a, - const tw_extended_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_tw_niels ( - tw_niels_a_t a, - const tw_niels_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Auto-generated copy method. - */ -static __inline__ void -copy_tw_pniels ( - tw_pniels_a_t a, - const tw_pniels_a_t ds -) __attribute__((unused,always_inline)); - -/** - * Add two points on a twisted Edwards curve, one in Extensible form - * and the other in half-Niels form. - */ -void -add_tw_niels_to_tw_extensible ( - tw_extensible_a_t d, - const tw_niels_a_t e -); - -/** - * Add two points on a twisted Edwards curve, one in Extensible form - * and the other in half-Niels form. - */ -void -sub_tw_niels_from_tw_extensible ( - tw_extensible_a_t d, - const tw_niels_a_t e -); - -/** - * Add two points on a twisted Edwards curve, one in Extensible form - * and the other in projective Niels form. - */ -void -add_tw_pniels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t a -); - -/** - * Add two points on a twisted Edwards curve, one in Extensible form - * and the other in projective Niels form. - */ -void -sub_tw_pniels_from_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t a -); - -/** - * Double a point on a twisted Edwards curve, in "extensible" coordinates. - */ -void -double_tw_extensible ( - tw_extensible_a_t a -); - -/** - * Double a point on an Edwards curve, in "extensible" coordinates. - */ -void -double_extensible ( - extensible_a_t a -); - -/** - * Double a point, and transfer it to the twisted curve. - * - * That is, apply the 4-isogeny. - */ -void -twist_and_double ( - tw_extensible_a_t b, - const extensible_a_t a -); - -/** - * Double a point, and transfer it to the untwisted curve. - * - * That is, apply the dual isogeny. - */ -void -untwist_and_double ( - extensible_a_t b, - const tw_extensible_a_t a -); - -void -convert_tw_affine_to_tw_pniels ( - tw_pniels_a_t b, - const tw_affine_a_t a -); - -void -convert_tw_affine_to_tw_extensible ( - tw_extensible_a_t b, - const tw_affine_a_t a -); - -void -convert_affine_to_extensible ( - extensible_a_t b, - const affine_a_t a -); - -void -convert_tw_extensible_to_tw_pniels ( - tw_pniels_a_t b, - const tw_extensible_a_t a -); - -void -convert_tw_pniels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_pniels_a_t d -); - -void -convert_tw_niels_to_tw_extensible ( - tw_extensible_a_t e, - const tw_niels_a_t d -); - -void -convert_tw_extensible_to_tw_extended ( - tw_extended_a_t b, - const tw_extensible_a_t a -); - -void -add_tw_extended ( - tw_extended_a_t d, - const tw_extended_a_t e -); - -void -add_sub_tw_extended ( - tw_extended_a_t c, - const tw_extended_a_t d, - const tw_extended_a_t e, - mask_t sub -); - -void -montgomery_step ( - montgomery_a_t a -); - -void -montgomery_aux_step ( - montgomery_aux_a_t a -); - -void -deserialize_montgomery ( - montgomery_a_t a, - const field_a_t sbz -); - -mask_t -serialize_montgomery ( - field_a_t b, - const montgomery_a_t a, - const field_a_t sbz -); - -mask_t -decaf_serialize_montgomery ( - field_a_t b, - const montgomery_aux_a_t a, - mask_t swapped -); - -void -decaf_deserialize_montgomery ( - montgomery_aux_a_t a, - const field_a_t s -); - -/** - * Serialize a point on an Edwards curve. - * - * The serialized form would be sqrt((z-y)/(z+y)) with sign of xz. - * - * It would be on 4y^2/(1-d) = x^3 + 2(1+d)/(1-d) * x^2 + x. - * - * But 4/(1-d) isn't square, so we need to twist it: - * - * -x is on 4y^2/(d-1) = x^3 + 2(d+1)/(d-1) * x^2 + x - */ -void -serialize_extensible ( - field_a_t b, - const extensible_a_t a -); - -/** - * - */ -void -untwist_and_double_and_serialize ( - field_a_t b, - const tw_extensible_a_t a -); - -/** - * Expensive transfer from untwisted to twisted. Roughly equivalent to halve and isogeny. - * Correctly transfers point of order 2. - * - * Can't have x=+1 (it's not even). There is code to fix the exception that would otherwise - * occur at (0,1). - * - * Input point must be even. - */ -void -twist_even ( - tw_extensible_a_t b, - const extensible_a_t a -); - -/** - * Expensive transfer from untwisted to twisted. Roughly equivalent to halve and isogeny. - * - * This function is for testing purposes only, because it can return odd points on the - * twist. This can cause exceptions in the point addition formula. What's more, this - * function should be able to return points of order 4, which are at infinity. - * - * This function probably doesn't properly handle special cases, such as the point at - * infinity (FUTURE). - * - * This function probably isn't a homomorphism, in that it probably doesn't consistently - * handle adjustments by the point of order 2 when the input is odd. (FUTURE) - */ -void -test_only_twist ( - tw_extensible_a_t b, - const extensible_a_t a -); - -mask_t -field_is_square ( - const field_a_t x -); - -mask_t -is_even_pt ( - const extensible_a_t a -); - -mask_t -is_even_tw ( - const tw_extensible_a_t a -); - -/** - * Deserialize a point to an untwisted affine curve. - */ -mask_t -deserialize_affine ( - affine_a_t a, - const field_a_t sz -); - -/** - * Deserialize a point and transfer it to the twist. - * - * Not guaranteed to preserve the 4-torsion component. - * - * Refuses to deserialize +-1, which are the points of order 2. - */ -mask_t -deserialize_and_twist_approx ( - tw_extensible_a_t a, - const field_a_t sz -) -__attribute__((warn_unused_result)); - -mask_t -decaf_deserialize_affine ( - affine_a_t a, - const field_a_t s, - mask_t allow_identity -) -__attribute__((warn_unused_result)); - -void -decaf_serialize_extensible ( - field_a_t b, - const extensible_a_t a -); - - -mask_t -decaf_deserialize_tw_affine ( - tw_affine_a_t a, - const field_a_t s, - mask_t allow_identity -) -__attribute__((warn_unused_result)); - -void -decaf_serialize_tw_extensible ( - field_a_t b, - const tw_extensible_a_t a -); - - -mask_t -decaf_deserialize_tw_extended ( - tw_extended_a_t a, - const field_a_t s, - mask_t allow_identity -) -__attribute__((warn_unused_result)); - -void -decaf_serialize_tw_extended ( - field_a_t b, - const tw_extended_a_t a -); - -void -set_identity_extensible ( - extensible_a_t a -); - -void -set_identity_tw_extensible ( - tw_extensible_a_t a -); - -void -set_identity_tw_extended ( - tw_extended_a_t a -); - -void -set_identity_affine ( - affine_a_t a -); - -mask_t -eq_affine ( - const affine_a_t a, - const affine_a_t b -); - -mask_t -eq_extensible ( - const extensible_a_t a, - const extensible_a_t b -); - -mask_t -eq_tw_extensible ( - const tw_extensible_a_t a, - const tw_extensible_a_t b -); - -void -elligator_2s_inject ( - affine_a_t a, - const field_a_t r -); - -mask_t -validate_affine ( - const affine_a_t a -); - -mask_t -decaf_eq_tw_extensible ( - const tw_extensible_a_t a, - const tw_extensible_a_t b -) -__attribute__((warn_unused_result)); - -mask_t -decaf_eq_tw_extended ( - const tw_extended_a_t a, - const tw_extended_a_t b -) -__attribute__((warn_unused_result)); - -mask_t -decaf_eq_extensible ( - const extensible_a_t a, - const extensible_a_t b -) -__attribute__((warn_unused_result)); - -/** - * Check the invariants for struct tw_extensible_t. - * NOTE: This function was automatically generated - * with no regard for speed. - */ -mask_t -validate_tw_extensible ( - const tw_extensible_a_t ext -); - -/** - * Check the invariants for struct extensible_t. - * NOTE: This function was automatically generated - * with no regard for speed. - */ -mask_t -validate_extensible ( - const extensible_a_t ext -); - -/** - * If doNegate, then negate a twisted niels point. - */ -static __inline__ void -__attribute__((unused)) -cond_negate_tw_niels ( - tw_niels_a_t n, - mask_t doNegate -) { - constant_time_cond_swap(n->a, n->b, sizeof(n->a), doNegate); - field_cond_neg(n->c, doNegate); -} - -/** - * If doNegate, then negate a twisted projective niels point. - */ -static __inline__ void -__attribute__((unused)) -cond_negate_tw_pniels ( - tw_pniels_a_t n, - mask_t doNegate -) { - cond_negate_tw_niels(n->n, doNegate); -} - -void -copy_affine ( - affine_a_t a, - const affine_a_t ds -) { - field_copy ( a->x, ds->x ); - field_copy ( a->y, ds->y ); -} - -void -copy_tw_affine ( - tw_affine_a_t a, - const tw_affine_a_t ds -) { - field_copy ( a->x, ds->x ); - field_copy ( a->y, ds->y ); -} - -void -copy_montgomery ( - montgomery_a_t a, - const montgomery_a_t ds -) { - field_copy ( a->z0, ds->z0 ); - field_copy ( a->xd, ds->xd ); - field_copy ( a->zd, ds->zd ); - field_copy ( a->xa, ds->xa ); - field_copy ( a->za, ds->za ); -} - -void -copy_extensible ( - extensible_a_t a, - const extensible_a_t ds -) { - field_copy ( a->x, ds->x ); - field_copy ( a->y, ds->y ); - field_copy ( a->z, ds->z ); - field_copy ( a->t, ds->t ); - field_copy ( a->u, ds->u ); -} - -void -copy_tw_extensible ( - tw_extensible_a_t a, - const tw_extensible_a_t ds -) { - field_copy ( a->x, ds->x ); - field_copy ( a->y, ds->y ); - field_copy ( a->z, ds->z ); - field_copy ( a->t, ds->t ); - field_copy ( a->u, ds->u ); -} - -void -copy_tw_extended ( - tw_extended_a_t a, - const tw_extended_a_t ds -) { - field_copy ( a->x, ds->x ); - field_copy ( a->y, ds->y ); - field_copy ( a->z, ds->z ); - field_copy ( a->t, ds->t ); -} - -void -copy_tw_niels ( - tw_niels_a_t a, - const tw_niels_a_t ds -) { - field_copy ( a->a, ds->a ); - field_copy ( a->b, ds->b ); - field_copy ( a->c, ds->c ); -} - -void -copy_tw_pniels ( - tw_pniels_a_t a, - const tw_pniels_a_t ds -) { - copy_tw_niels( a->n, ds->n ); - field_copy ( a->z, ds->z ); -} - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __CC_INCLUDED_EC_POINT_H__ */ diff --git a/src/include/intrinsics.h b/src/include/intrinsics.h deleted file mode 100644 index 88e90d0..0000000 --- a/src/include/intrinsics.h +++ /dev/null @@ -1,276 +0,0 @@ -/* Copyright (c) 2011 Stanford University. - * Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -/** @file intrinsics.h - * @brief cRandom intrinsics header. - */ - -#ifndef __CRANDOM_INTRINSICS_H__ -#define __CRANDOM_INTRINSICS_H__ 1 - -#include -#include "config.h" - -#if defined(__i386__) || defined(__x86_64__) -#include -#endif - -/** @brief Macro to make a function static, forcibly inlined and possibly unused. */ -#define INTRINSIC \ - static __inline__ __attribute__((__gnu_inline__, __always_inline__, unused)) - -#define GEN 1 /**< @brief Intrinsics field has been generated. */ -#define SSE2 2 /**< @brief Machine supports SSE2 */ -#define SSSE3 4 /**< @brief Machine supports SSSE3 (for shuffles) */ -#define AESNI 8 /**< @brief Machine supports Intel AES-NI */ -#define XOP 16 /**< @brief Machine supports AMD XOP */ -#define AVX 32 /**< @brief Machine supports Intel AVX (for masking) */ -#define AVX2 64 /**< @brief Machine supports Intel AVX2 (for bignums) */ -#define RDRAND 128 /**< @brief Machine supports Intel RDRAND */ - -/** - * @brief If on x86, read the timestamp counter. Otherwise, return 0. - */ -#ifndef __has_builtin -#define __has_builtin(X) 0 -#endif -#if defined(__clang__) && __has_builtin(__builtin_readcyclecounter) -#define rdtsc __builtin_readcyclecounter -#else -INTRINSIC u_int64_t rdtsc(void) { - u_int64_t out = 0; -# if (defined(__i386__) || defined(__x86_64__)) - __asm__ __volatile__ ("rdtsc" : "=A"(out)); -# endif - return out; -} -#endif - -/** - * Return x unchanged, but confuse the compiler. - * - * This is mainly for use in test scripts, to prevent the value from - * being constant-folded or removed by dead code elimination. - * - * @param x A 64-bit number. - * @return The same number in a register. - */ -INTRINSIC u_int64_t opacify(u_int64_t x) { - __asm__ volatile("mov %0, %0" : "+r"(x)); - return x; -} - - -/** @cond internal */ -#ifdef __AVX2__ -# define MIGHT_HAVE_AVX2 1 -# ifndef MUST_HAVE_AVX2 -# define MUST_HAVE_AVX2 0 -# endif -#else -# define MIGHT_HAVE_AVX2 0 -# define MUST_HAVE_AVX2 0 -#endif - -#ifdef __AVX__ -# define MIGHT_HAVE_AVX 1 -# ifndef MUST_HAVE_AVX -# define MUST_HAVE_AVX MUST_HAVE_AVX2 -# endif -#else -# define MIGHT_HAVE_AVX 0 -# define MUST_HAVE_AVX 0 -#endif - -#ifdef __SSSE3__ -# define MIGHT_HAVE_SSSE3 1 -# ifndef MUST_HAVE_SSSE3 -# define MUST_HAVE_SSSE3 MUST_HAVE_AVX -# endif -#else -# define MIGHT_HAVE_SSSE3 0 -# define MUST_HAVE_SSSE3 0 -#endif - -#ifdef __SSE2__ -# define MIGHT_HAVE_SSE2 1 -# ifndef MUST_HAVE_SSE2 -# define MUST_HAVE_SSE2 MUST_HAVE_SSSE3 -# endif - typedef __m128i ssereg; -# define pslldq _mm_slli_epi32 -# define pshufd _mm_shuffle_epi32 - -#else -# define MIGHT_HAVE_SSE2 0 -# define MUST_HAVE_SSE2 0 -#endif - -#ifdef __AES__ -/* don't include intrinsics file, because not all platforms have it */ -# define MIGHT_HAVE_AESNI 1 -# ifndef MIGHT_HAVE_RDRAND -# define MIGHT_HAVE_RDRAND 1 -# endif -# ifndef MUST_HAVE_RDRAND -# define MUST_HAVE_RDRAND 0 -# endif -# ifndef MUST_HAVE_AESNI -# define MUST_HAVE_AESNI 0 -# endif - -#else -# define MIGHT_HAVE_AESNI 0 -# define MUST_HAVE_AESNI 0 -# define MIGHT_HAVE_RDRAND 0 -# define MUST_HAVE_RDRAND 0 -#endif - -#ifdef __XOP__ -/* don't include intrinsics file, because not all platforms have it */ -# define MIGHT_HAVE_XOP 1 -# ifndef MUST_HAVE_XOP -# define MUST_HAVE_XOP 0 -# endif -#else -# define MIGHT_HAVE_XOP 0 -# define MUST_HAVE_XOP 0 -#endif - -#define MIGHT_MASK \ - ( SSE2 * MIGHT_HAVE_SSE2 \ - | SSSE3 * MIGHT_HAVE_SSSE3 \ - | AESNI * MIGHT_HAVE_AESNI \ - | XOP * MIGHT_HAVE_XOP \ - | AVX * MIGHT_HAVE_AVX \ - | RDRAND * MIGHT_HAVE_RDRAND \ - | AVX2 * MIGHT_HAVE_AVX2) - -#if CRANDOM_MIGHT_IS_MUST -#define MUST_MASK MIGHT_MASK -#else -#define MUST_MASK \ - ( SSE2 * MUST_HAVE_SSE2 \ - | SSSE3 * MUST_HAVE_SSSE3 \ - | AESNI * MUST_HAVE_AESNI \ - | XOP * MUST_HAVE_XOP \ - | AVX * MUST_HAVE_AVX \ - | RDRAND * MUST_HAVE_RDRAND \ - | AVX2 * MUST_HAVE_AVX2 ) -#endif -/** @endcond */ - -#ifdef __SSE2__ -/** Rotate a register by some amount using SSE2. */ -INTRINSIC ssereg sse2_rotate(int r, ssereg a) { - return _mm_slli_epi32(a, r) ^ _mm_srli_epi32(a, 32-r); -} -#endif - -#ifdef __XOP__ -/** Rotate a register by some amount using AMD XOP. */ -INTRINSIC ssereg xop_rotate(int amount, ssereg x) { - ssereg out; - __asm__ ("vprotd %1, %2, %0" : "=x"(out) : "x"(x), "g"(amount)); - return out; -} -#endif - -/** - * @brief Macro which detects that targets might support this feature, - * so that we can include code for it. - */ -#define MIGHT_HAVE(feature) ((MIGHT_MASK & feature) == feature) - -/** - * @brief Macro which detects that targets must support this feature, - * so we can omit fallback code. - */ -#define MUST_HAVE(feature) ((MUST_MASK & feature) == feature) - -/** - * @brief Make a functiona available by C API. - */ -#ifdef __cplusplus -# define extern_c extern "C" -#else -# define extern_c -#endif - -/** @cond internal - * @brief Detect platform features and return them as a flagfield int. - */ -extern_c -unsigned int crandom_detect_features(); -/** @endcond */ - -#ifndef likely -# define likely(x) __builtin_expect((x),1) \ - /**< @brief Tell the compiler that a branch is likely, for optimization. */ -# define unlikely(x) __builtin_expect((x),0) \ - /**< @brief Tell the compiler that a branch is unlikely, for optimization. */ -#endif - -/** - * Atomic compare and swap, return by fetching. - * - * Equivalent to: - * ret = *target; if (*target == old) *target = new; return ret; - * - * @param [inout] target The volatile memory area to be CAS'd - * @param [in] old The expected old value of the target. - * @param [in] new A value to replace the target on success. - */ -INTRINSIC const char * -compare_and_swap ( - const char *volatile* target, - const char *old, - const char *new -) { - return __sync_val_compare_and_swap(target,old,new); -} - -/** - * Atomic compare and swap. Return whether successful. - * - * Equivalent to: - * if (*target == old) { *target = new; return nonzero; } else { return 0; } - * - * @param [inout] target The volatile memory area to be CAS'd - * @param [in] old The expected old value of the target. - * @param [in] new A value to replace the target on success. - */ -INTRINSIC int -bool_compare_and_swap ( - const char *volatile* target, - const char *old, - const char *new -) { - return __sync_bool_compare_and_swap(target,old,new); -} - -/** - * Determine whether the current processor supports the given feature. - * - * This function is designed so that it should only have runtime overhead - * if the feature is not known at compile time -- that is, if - * MIGHT_HAVE(feature) is set, but MUST_HAVE(feature) is not. - */ -extern volatile unsigned int crandom_features; - -/** @brief Determine if a given CPU feature is available. */ -INTRINSIC int HAVE(unsigned int feature); - -int HAVE(unsigned int feature) { - unsigned int features; - if (!MIGHT_HAVE(feature)) return 0; - if (MUST_HAVE(feature)) return 1; - features = crandom_features; - if (unlikely(!features)) - crandom_features = features = crandom_detect_features(); - return likely((features & feature) == feature); -} - -#endif /* __CRANDOM_INTRINSICS_H__ */ diff --git a/src/include/magic.h b/src/include/magic.h deleted file mode 100644 index 1d186f2..0000000 --- a/src/include/magic.h +++ /dev/null @@ -1,95 +0,0 @@ -/** - * @file magic.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief Curve-independent declarations of magic numbers. - */ - -#ifndef __GOLDI_MAGIC_H__ -#define __GOLDI_MAGIC_H__ 1 - -#include "word.h" - -/** - * @brief If true, use wider tables for the precomputed combs. - */ -#ifndef USE_BIG_COMBS -#if defined(__ARM_NEON__) -#define USE_BIG_COMBS 1 -#else -#define USE_BIG_COMBS (WORD_BITS==64) -#endif -#endif - -/* TODO: standardize notation */ - -/** @brief The number of words in the Goldilocks field. */ -#define GOLDI_FIELD_WORDS DIV_CEIL(FIELD_BITS,WORD_BITS) - -/** @brief The number of bits in the Goldilocks curve's cofactor (cofactor=4). */ -#define COFACTOR_BITS 2 - -/** @brief The number of bits in a Goldilocks scalar. */ -#define SCALAR_BITS (FIELD_BITS - COFACTOR_BITS) - -/** @brief The number of bytes in a Goldilocks scalar. */ -#define SCALAR_BYTES (1+(SCALAR_BITS)/8) - -/** @brief The number of words in the Goldilocks field. */ -#define SCALAR_WORDS WORDS_FOR_BITS(SCALAR_BITS) - -#include "f_magic.h" - -/** - * @brief sqrt(d-1), used for point formats and twisting. - */ -extern const field_a_t sqrt_d_minus_1; - -/** - * @brief The base point for Goldilocks. - */ -extern const affine_a_t goldilocks_base_point; - -/** - * @brief The Goldilocks prime subgroup order. - */ -extern const struct barrett_prime_t curve_prime_order; - -/** - * @brief Window size for fixed-window signed binary scalarmul. - * Table size is 2^(this - 1). - */ -#define SCALARMUL_FIXED_WINDOW_SIZE 5 - -/** - * @brief Even/odd adjustments for fixed window with - * ROUNDUP(SCALAR_BITS,SCALARMUL_FIXED_WINDOW_SIZE). - */ -extern const word_t SCALARMUL_FIXED_WINDOW_ADJUSTMENT[2*SCALAR_WORDS]; - -/** - * @brief Table size for wNAF signed binary (variable-time) scalarmul. - * Table size is 2^this. - */ -#define SCALARMUL_WNAF_TABLE_BITS 3 - -/** - * @brief Table size for wNAF signed binary (variable-time) linear combo. - * Table size is 2^this. - */ -#define SCALARMUL_WNAF_COMBO_TABLE_BITS 4 - -/** - * @brief The bit width of the precomputed WNAF tables. Size is 2^this elements. - */ -#define WNAF_PRECMP_BITS 5 - -/** - * @brief crandom magic structure guard constant = "return 4", cf xkcd #221 - */ -#define CRANDOM_MAGIC 0x72657475726e2034ull - - -#endif /* __GOLDI_MAGIC_H__ */ diff --git a/src/include/scalarmul.h b/src/include/scalarmul.h deleted file mode 100644 index 4191bec..0000000 --- a/src/include/scalarmul.h +++ /dev/null @@ -1,373 +0,0 @@ -/** - * @file scalarmul.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - */ - -#ifndef __P448_ALGO_H__ -#define __P448_ALGO_H__ 1 - -#include "ec_point.h" -#include "field.h" -#include "intrinsics.h" -#include "magic.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * A word array containing a scalar - */ -typedef word_t scalar_t[SCALAR_WORDS]; - -/** - * A precomputed table for fixed-base scalar multiplication. - * - * This uses a signed combs format. - */ -struct fixed_base_table_t { - /** Comb tables containing multiples of the base point. */ - tw_niels_a_t *table; - - /** Adjustments to the scalar in even and odd cases, respectively. */ - word_t scalar_adjustments[2*SCALAR_WORDS]; - - /** The number of combs in the table. */ - unsigned int n; - - /** The number of teeth in each comb. */ - unsigned int t; - - /** The spacing between the teeth. */ - unsigned int s; - - /** If nonzero, the table was malloc'd by precompute_for_combs. */ - unsigned int own_table; -}; - -/** - * Full Montgomery ladder in inverse square root format. - * - * Out = [2^n_extra_doubles * scalar] * in, where - * scalar is little-endian and has length $nbits$ bits. - * - * If the scalar is even and/or n_extra_doubles >= 1, - * then this function will reject points which are not - * on the curve by returning MASK_FAILURE. - * - * This function will also reject multiplies which output - * the identity or the point of order 2. It may be worth - * revisiting this decision in the FUTURE. The idea is that - * this can only happen when: the input is the identity or the - * point of order 2; or the input is the point of order 4 on - * the twist; or the scalar is 0 or a multiple of the curve - * order; or the scalar is a multiple of the twist order and - * the input point is on the twist. - * - * This function takes constant time with respect to $*in$ - * and $*scalar$, but not of course with respect to nbits or - * n_extra_doubles. - * - * For security, we recommend setting n_extra_doubles = 1. - * Because the cofactor of Goldilocks is 4 and input points - * are always even (when on the curve), this will cancel the - * cofactor. - * - * @param [out] out The output point. - * @param [in] in The base point. - * @param [in] scalar The scalar's little-endian representation. - * @param [in] nbits The number of bits in the scalar. Note that - * unlike in Curve25519, we do not require the top bit to be set. - * @param [in] n_extra_doubles The number of extra doubles to do at - * the end. - * - * @retval MASK_SUCCESS The operation was successful. - * @retval MASK_FAILURE The input point was invalid, or the output - * would be the identity or the point of order 2. - */ -mask_t -montgomery_ladder ( - field_a_t out, - const field_a_t in, - const word_t *scalar, - unsigned int nbits, - unsigned int n_extra_doubles -) __attribute__((warn_unused_result)); - -/** - * Full Montgomery aux ladder in decaf format. - * - * Out = scalar * in, where - * scalar is little-endian and has length $nbits$ bits. - * - * This function (once it's done; TODO) will always reject points - * on the twist. - * - * This function takes constant time with respect to $*in$ - * and $*scalar$, but not of course with respect to nbits or - * n_extra_doubles. - * - * @param [out] out The output point. - * @param [in] in The base point. - * @param [in] scalar The scalar's little-endian representation. - * @param [in] nbits The number of bits in the scalar. Note that - * unlike in Curve25519, we do not require the top bit to be set. - * - * @retval MASK_SUCCESS The operation was successful. - * @retval MASK_FAILURE The input point was invalid, or the output - * would be the identity or the point of order 2. - */ -mask_t -decaf_montgomery_ladder ( - field_a_t out, - const field_a_t in, - const word_t *scalar, - unsigned int nbits -) __attribute__((warn_unused_result)); - -/** - * Scalar multiply a twisted Edwards-form point. - * - * This function takes constant time. - * - * Currently the scalar is always exactly 448 bits long. - * - * @param [inout] working The point to multply. - * @param [in] scalar The scalar, in little-endian form. - */ -void -scalarmul ( - tw_extensible_a_t working, - const word_t scalar[SCALAR_WORDS] - /* TODO? int nbits */ -); - -/** - * Scalar multiply a twisted Edwards-form point, simply, in extended coordinates. - * - * This function takes constant time. - * - * Currently the scalar is always exactly 448 bits long. - * - * @param [inout] working The point to multply. - * @param [in] scalar The scalar, in little-endian form. - */ -void -scalarmul_ed ( - tw_extended_a_t working, - const word_t scalar[SCALAR_WORDS] - /* TODO? int nbits */ -); - -/** - * Scalar multiply a twisted Edwards-form point. Use the same - * algorithm as scalarmul(), but uses variable array indices. - * - * Currently the scalar is always exactly 448 bits long. - * - * @warning This function uses variable array indices, - * so it is insecure against cache-timing attacks. It is intended - * for microbenchmarking, to see how much constant-time arithmetic - * costs us. - * - * @param [inout] working The point to multply. - * @param [in] scalar The scalar, in little-endian form. - */ -void -scalarmul_vlook ( - tw_extensible_a_t working, - const word_t scalar[SCALAR_WORDS] -); - -/** - * Precompute a table to accelerate fixed-point scalar - * multiplication using the "multiple signed combs" approach. - * - * This function computes $n$ "comb" tables, each containing - * 2^(t-1) points in tw_niels_t format. You must have - * n * t * s >= SCALAR_BITS = 446 for complete coverage. - * - * The scalar multiplication algorithm may adjust the scalar by - * a multiple of q. Therefore, we strongly recommend to use base - * points in the q-torsion group (i.e. doubly even points). - * - * @param [out] out The table to compute. - * @param [in] base The base point. - * @param [in] n The number of combs in the table. - * @param [in] t The number of teeth in each comb. - * @param [in] s The spacing between the teeth. - * @param [out] prealloc An optional preallocated array containing - * space for n<<(t-1) values of type tw_niels_t. - * - * @retval MASK_SUCCESS Success. - * @retval MASK_FAILURE Failure, most likely because we are out - * of memory. - */ -mask_t -precompute_fixed_base ( - struct fixed_base_table_t *out, - const tw_extensible_a_t base, - unsigned int n, - unsigned int t, - unsigned int s, - tw_niels_a_t *prealloc -) __attribute__((warn_unused_result)); - - /** - * Destroy a fixed-base table. Frees any memory that we allocated - * for the combs. - * - * @param [in] table The table to destroy. - */ -void -destroy_fixed_base ( - struct fixed_base_table_t *table -); - -/** - * Scalar multiplication with precomputation. Set working to - * to [scalar] * Base, where Base is the base point passed to - * precompute_for_combs(). - * - * The scalar may be adjusted by a multiple of q, so this routine - * can be wrong by a cofactor if the base has cofactor components. - * - * @param [out] out The output point. - * @param [in] scalar The scalar. - * @param [in] nbits The number of bits in the scalar. Must be <= n*t*s. - * @param [in] table The precomputed table. - * - * @retval MASK_SUCCESS Success. - * @retval MASK_FAILURE Failure, because n*t*s < nbits - */ -mask_t -scalarmul_fixed_base ( - tw_extensible_a_t out, - const word_t *scalar, - unsigned int nbits, - const struct fixed_base_table_t *table -); - -/** - * Variable-time scalar multiplication. - * - * @warning This function takes variable time. It is intended for - * microbenchmarking. - * - * @param [inout] working The input and output point. - * @param [in] scalar The scalar. - * @param [in] nbits The number of bits in the scalar - */ -void -scalarmul_vt ( - tw_extensible_a_t working, - const word_t *scalar, - unsigned int nbits -); - - -/** - * Precompute a table to accelerate fixed-point scalar - * multiplication (and, more importantly, linear combos) - * using the "windowed non-adjacent form" approach. - * - * @param [out] out The output table. Must have room for 1< - -#ifdef __cplusplus -extern "C" { -#endif - -#define SHA512_OUTPUT_BYTES 64 - -/** - * SHA512 hashing context. - * - * This structure is opaque. - */ -typedef struct { - /** @privatesection */ - uint64_t chain[8]; - uint8_t block[128]; - uint64_t nbytes; -} sha512_ctx_a_t[1]; - -void -sha512_init ( - sha512_ctx_a_t ctx -); - -void -sha512_update ( - sha512_ctx_a_t ctx, - const unsigned char *data, - uint64_t bytes -); - -void -sha512_final ( - sha512_ctx_a_t ctx, - uint8_t result[SHA512_OUTPUT_BYTES] -); - -#ifdef __cplusplus -}; /* extern "C" */ -#endif - -#endif /* __GOLDI_SHA512_H__ */ diff --git a/src/p448/arch_x86_64/p448.h b/src/p448/arch_x86_64/p448.h index 20b7597..d91895b 100644 --- a/src/p448/arch_x86_64/p448.h +++ b/src/p448/arch_x86_64/p448.h @@ -75,7 +75,7 @@ mask_t p448_is_zero ( const p448_t *in ); - + static __inline__ void p448_bias ( p448_t *inout, diff --git a/src/p448/f_arithmetic.c b/src/p448/f_arithmetic.c index c9b87e5..12e2b07 100644 --- a/src/p448/f_arithmetic.c +++ b/src/p448/f_arithmetic.c @@ -8,7 +8,7 @@ * @brief Field-specific arithmetic. */ -#include "ec_point.h" +#include "field.h" void field_isr ( diff --git a/src/p448/f_magic.h b/src/p448/f_magic.h deleted file mode 100644 index 681f05e..0000000 --- a/src/p448/f_magic.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file f_magic.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief Goldilocks magic numbers (group orders, coefficients, algo params etc). - */ - -#ifndef __GOLDI_F_MAGIC_H__ -#define __GOLDI_F_MAGIC_H__ 1 - -#include "field.h" -#include "ec_point.h" - -/** - * @brief The Edwards "d" term for this curve. - */ -static const int64_t EDWARDS_D = -39081; - -/** @brief The number of combs to use for signed comb algo */ -#define COMB_N (USE_BIG_COMBS ? 5 : 8) - -/** @brief The number of teeth of the combs for signed comb algo */ -#define COMB_T (USE_BIG_COMBS ? 5 : 4) - -/** @brief The spacing the of combs for signed comb algo */ -#define COMB_S (USE_BIG_COMBS ? 18 : 14) - -#endif /* __GOLDI_F_MAGIC_H__ */ diff --git a/src/p448/magic.c b/src/p448/magic.c deleted file mode 100644 index 74b433c..0000000 --- a/src/p448/magic.c +++ /dev/null @@ -1,81 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "field.h" -#include "magic.h" -#include "barrett_field.h" - -/* FUTURE: automatically generate this file? */ - -const uint8_t FIELD_MODULUS[FIELD_BYTES] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -/*!*/ 0xfe, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -const word_t SCALARMUL_FIXED_WINDOW_ADJUSTMENT[2*SCALAR_WORDS] = { - U64LE(0xebec9967f5d3f5c2), - U64LE(0x0aa09b49b16c9a02), - U64LE(0x7f6126aec172cd8e), - U64LE(0x00000007b027e54d), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x4000000000000000), - - U64LE(0xc873d6d54a7bb0cf), - U64LE(0xe933d8d723a70aad), - U64LE(0xbb124b65129c96fd), - U64LE(0x00000008335dc163), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000) -}; - -const affine_a_t goldilocks_base_point = {{ -#ifdef USE_NEON_PERM - {{{ 0xaed939f,0xc59d070,0xf0de840,0x5f065c3, 0xf4ba0c7,0xdf73324,0xc170033,0x3a6a26a, - 0x4c63d96,0x4609845,0xf3932d9,0x1b4faff, 0x6147eaa,0xa2692ff,0x9cecfa9,0x297ea0e - }}}, -#else - {{{ U56LE(0xf0de840aed939f), U56LE(0xc170033f4ba0c7), - U56LE(0xf3932d94c63d96), U56LE(0x9cecfa96147eaa), - U56LE(0x5f065c3c59d070), U56LE(0x3a6a26adf73324), - U56LE(0x1b4faff4609845), U56LE(0x297ea0ea2692ff) - }}}, -#endif - {{{ 19 }}} -}}; - -static const word_t curve_prime_order_lo[(224+WORD_BITS-1)/WORD_BITS] = { - U64LE(0xdc873d6d54a7bb0d), - U64LE(0xde933d8d723a70aa), - U64LE(0x3bb124b65129c96f), - 0x8335dc16 -}; -const struct barrett_prime_t curve_prime_order = { - GOLDI_FIELD_WORDS, - 62 % WORD_BITS, - sizeof(curve_prime_order_lo)/sizeof(curve_prime_order_lo[0]), - curve_prime_order_lo -}; - -const field_a_t -sqrt_d_minus_1 = {{{ -#ifdef USE_NEON_PERM - 0x6749f46,0x24d9770,0xd2e2183,0xa49f7b4, - 0xb4f0179,0x8c5f656,0x888db42,0xdcac462, - 0xbdeea38,0x748734a,0x5a189aa,0x49443b8, - 0x6f14c06,0x0b25b7a,0x51e65ca,0x12fec0c -#else - U56LE(0xd2e21836749f46), - U56LE(0x888db42b4f0179), - U56LE(0x5a189aabdeea38), - U56LE(0x51e65ca6f14c06), - U56LE(0xa49f7b424d9770), - U56LE(0xdcac4628c5f656), - U56LE(0x49443b8748734a), - U56LE(0x12fec0c0b25b7a) -#endif -}}}; diff --git a/src/p480/f_arithmetic.c b/src/p480/f_arithmetic.c index bc8e657..1166c3c 100644 --- a/src/p480/f_arithmetic.c +++ b/src/p480/f_arithmetic.c @@ -8,7 +8,7 @@ * @brief Field-specific arithmetic. */ -#include "ec_point.h" +#include "field.h" void field_isr ( diff --git a/src/p480/f_magic.h b/src/p480/f_magic.h deleted file mode 100644 index 6942cda..0000000 --- a/src/p480/f_magic.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file f_magic.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief Goldilocks magic numbers (group orders, coefficients, algo params etc). - */ - -#ifndef __GOLDI_F_MAGIC_H__ -#define __GOLDI_F_MAGIC_H__ 1 - -#include "field.h" -#include "ec_point.h" - -/** - * @brief The Edwards "d" term for this curve. - */ -static const int64_t EDWARDS_D = 53825; - -/** @brief The number of combs to use for signed comb algo */ -#define COMB_N (USE_BIG_COMBS ? 6 : 5) - -/** @brief The number of teeth of the combs for signed comb algo */ -#define COMB_T (USE_BIG_COMBS ? 5 : 4) - -/** @brief The spacing the of combs for signed comb algo */ -#define COMB_S (USE_BIG_COMBS ? 16 : 24) - -#endif /* __GOLDI_F_MAGIC_H__ */ diff --git a/src/p480/magic.c b/src/p480/magic.c deleted file mode 100644 index be209b1..0000000 --- a/src/p480/magic.c +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "field.h" -#include "magic.h" -#include "barrett_field.h" - -/* FUTURE: automatically generate this file? */ - -const uint8_t FIELD_MODULUS[FIELD_BYTES] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, -/*!*/ 0xfe, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF -}; - -const word_t SCALARMUL_FIXED_WINDOW_ADJUSTMENT[2*SCALAR_WORDS] = { - U64LE(0x58b51bc56ea8f0c4), - U64LE(0xd361f6a2348b50c9), - U64LE(0x08089c139c0002ae), - U64LE(0x0001d2ac3d9503a0), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - 0x40000000, - - U64LE(0xcb9c25073e36965b), - U64LE(0x6f2d48d8460f1661), - U64LE(0x0ab6256f7aaaae3e), - U64LE(0x00026e3afcc6af80), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - 0x00000000 -}; - -const affine_a_t goldilocks_base_point = {{ - {{{ - U60LE(0x849ff7f845c30d3), - U60LE(0x7dda488553a4c5b), - U60LE(0x1d3a2d9844831ea), - U60LE(0xb33ecf6ade470a2), - U60LE(0x8b3cb95210bd3c3), - U60LE(0xfc955e59aeefa65), - U60LE(0x3ab247cd530013c), - U60LE(0x7ca42af3d564280) - }}}, - {{{ 5 }}} -}}; - -static const word_t curve_prime_order_lo[(240+WORD_BITS-1)/WORD_BITS] = { - U64LE(0x72e70941cf8da597), - U64LE(0x9bcb52361183c598), - U64LE(0x02ad895bdeaaab8f), - U64LE(0x9b8ebf31abe0) -}; -const struct barrett_prime_t curve_prime_order = { - GOLDI_FIELD_WORDS, - 30 % WORD_BITS, - sizeof(curve_prime_order_lo)/sizeof(curve_prime_order_lo[0]), - curve_prime_order_lo -}; - -const field_a_t -sqrt_d_minus_1 = {{{ - 232 /* Whoa, it comes out even. */ -}}}; \ No newline at end of file diff --git a/src/p521/f_arithmetic.c b/src/p521/f_arithmetic.c index 37c0b50..7c36478 100644 --- a/src/p521/f_arithmetic.c +++ b/src/p521/f_arithmetic.c @@ -8,7 +8,7 @@ * @brief Field-specific arithmetic. */ -#include "ec_point.h" +#include "field.h" void field_isr ( diff --git a/src/p521/f_magic.h b/src/p521/f_magic.h deleted file mode 100644 index d805114..0000000 --- a/src/p521/f_magic.h +++ /dev/null @@ -1,30 +0,0 @@ -/** - * @file f_magic.h - * @copyright - * Copyright (c) 2014 Cryptography Research, Inc. \n - * Released under the MIT License. See LICENSE.txt for license information. - * @author Mike Hamburg - * @brief Goldilocks magic numbers (group orders, coefficients, algo params etc). - */ - -#ifndef __GOLDI_F_MAGIC_H__ -#define __GOLDI_F_MAGIC_H__ 1 - -#include "field.h" -#include "ec_point.h" - -/** - * @brief The Edwards "d" term for this curve. - */ -static const int64_t EDWARDS_D = -376014; - -/** @brief The number of combs to use for signed comb algo */ -#define COMB_N (USE_BIG_COMBS ? 4 : 5) - -/** @brief The number of teeth of the combs for signed comb algo */ -#define COMB_T (USE_BIG_COMBS ? 5 : 4) - -/** @brief The spacing the of combs for signed comb algo */ -#define COMB_S (USE_BIG_COMBS ? 26 : 26) - -#endif /* __GOLDI_F_MAGIC_H__ */ diff --git a/src/p521/magic.c b/src/p521/magic.c deleted file mode 100644 index 4613958..0000000 --- a/src/p521/magic.c +++ /dev/null @@ -1,111 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "field.h" -#include "magic.h" -#include "barrett_field.h" - -/* FUTURE: automatically generate this file? */ - -const uint8_t FIELD_MODULUS[FIELD_BYTES] = { - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, - 0xFF, 0x01 -}; - -const word_t SCALARMUL_FIXED_WINDOW_ADJUSTMENT[2*SCALAR_WORDS] = { - U64LE(0xbf15dbca0ae7f294), - U64LE(0x04273ba96570e0ba), - U64LE(0xc94750a1813ac0fb), - U64LE(0xea4939b8b9037a08), - U64LE(0x0000000000000002), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - 0x80, - - U64LE(0x7e2bb79415cfe529), - U64LE(0x084e7752cae1c175), - U64LE(0x928ea143027581f6), - U64LE(0xd49273717206f411), - U64LE(0x0000000000000005), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - U64LE(0x0000000000000000), - 0x0 -}; - -const affine_a_t goldilocks_base_point = {{ - {{{ -#ifdef USE_P521_3x3_TRANSPOSE - U58LE(0x02a940a2f19ba6c), - U58LE(0x3331c90d2c6ba52), - U58LE(0x2878a3bfd9f42fc), - 0, - U58LE(0x03ec4cd920e2a8c), - U58LE(0x0c6203913f6ecc5), - U58LE(0x06277e432c8a5ac), - 0, - U58LE(0x1d568fc99c6059d), - U58LE(0x1b2063b22fcf270), - U58LE(0x0752cb45c48648b), - 0 -#else - U58LE(0x02a940a2f19ba6c), - U58LE(0x03ec4cd920e2a8c), - U58LE(0x1d568fc99c6059d), - U58LE(0x3331c90d2c6ba52), - U58LE(0x0c6203913f6ecc5), - U58LE(0x1b2063b22fcf270), - U58LE(0x2878a3bfd9f42fc), - U58LE(0x06277e432c8a5ac), - U58LE(0x0752cb45c48648b) -#endif - }}}, - {{{ 12 }}} -}}; - -static const word_t curve_prime_order_lo[(261+WORD_BITS-1)/WORD_BITS] = { - U64LE(0xbf15dbca0ae7f295), - U64LE(0x4273ba96570e0ba), - U64LE(0xc94750a1813ac0fb), - U64LE(0xea4939b8b9037a08), - 2 -}; -const struct barrett_prime_t curve_prime_order = { - GOLDI_FIELD_WORDS, - 7 % WORD_BITS, - sizeof(curve_prime_order_lo)/sizeof(curve_prime_order_lo[0]), - curve_prime_order_lo -}; - -const field_a_t -sqrt_d_minus_1 = {{{ -#ifdef USE_P521_3x3_TRANSPOSE - U58LE(0x1e2be72c1c81990), - U58LE(0x207dfc238a33e46), - U58LE(0x2264cfb418c4c30), - 0, - U58LE(0x1135002ad596c69), - U58LE(0x0e30107cd79d1f6), - U58LE(0x0524b9e715937f5), - 0, - U58LE(0x2ab3a257a22666d), - U58LE(0x2d80cc2936a1824), - U58LE(0x0a9ea3ac10d6aed), - 0 -#else - U58LE(0x1e2be72c1c81990), - U58LE(0x1135002ad596c69), - U58LE(0x2ab3a257a22666d), - U58LE(0x207dfc238a33e46), - U58LE(0x0e30107cd79d1f6), - U58LE(0x2d80cc2936a1824), - U58LE(0x2264cfb418c4c30), - U58LE(0x0524b9e715937f5), - U58LE(0x0a9ea3ac10d6aed) -#endif -}}}; diff --git a/src/scalarmul.c b/src/scalarmul.c deleted file mode 100644 index 5445c38..0000000 --- a/src/scalarmul.c +++ /dev/null @@ -1,987 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "word.h" - -#include -#include -#include - -#include "intrinsics.h" -#include "scalarmul.h" -#include "barrett_field.h" -#include "constant_time.h" - -mask_t -montgomery_ladder ( - field_a_t out, - const field_a_t in, - const word_t *scalar, - unsigned int nbits, - unsigned int n_extra_doubles -) { - montgomery_a_t mont; - deserialize_montgomery(mont, in); - - int i,j,n=(nbits-1)%WORD_BITS; - mask_t pflip = 0; - for (j=(nbits+WORD_BITS-1)/WORD_BITS-1; j>=0; j--) { - word_t w = scalar[j]; - for (i=n; i>=0; i--) { - mask_t flip = -((w>>i)&1); - constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),flip^pflip); - constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),flip^pflip); - montgomery_step(mont); - pflip = flip; - } - n = WORD_BITS-1; - } - constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),pflip); - constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),pflip); - - assert(n_extra_doubles < INT_MAX); - for (j=0; j<(int)n_extra_doubles; j++) { - montgomery_step(mont); - } - - return serialize_montgomery(out, mont, in); -} - -mask_t -decaf_montgomery_ladder ( - field_a_t out, - const field_a_t in, - const word_t *scalar, - unsigned int nbits -) { - montgomery_aux_a_t mont; - decaf_deserialize_montgomery(mont, in); - - int i,j,n=(nbits-1)%WORD_BITS; - mask_t pflip = 0; - for (j=(nbits+WORD_BITS-1)/WORD_BITS-1; j>=0; j--) { - word_t w = scalar[j]; - for (i=n; i>=0; i--) { - mask_t flip = -((w>>i)&1); - constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),flip^pflip); - constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),flip^pflip); - montgomery_aux_step(mont); - pflip = flip; - } - n = WORD_BITS-1; - } - constant_time_cond_swap(mont->xa,mont->xd,sizeof(mont->xd),pflip); - constant_time_cond_swap(mont->za,mont->zd,sizeof(mont->xd),pflip); - - return decaf_serialize_montgomery(out, mont, pflip); -} - -static __inline__ void -__attribute__((unused,always_inline)) -constant_time_lookup_tw_pniels ( - tw_pniels_a_t out, - const tw_pniels_a_t *in, - int nin, - int idx -) { - constant_time_lookup(out,in,sizeof(*out),nin,idx); -} - -static __inline__ void -__attribute__((unused,always_inline)) -constant_time_lookup_tw_extended ( - tw_extended_a_t out, - const tw_extended_a_t *in, - int nin, - int idx -) { - constant_time_lookup(out,in,sizeof(*out),nin,idx); -} - -static __inline__ void -__attribute__((unused,always_inline)) -constant_time_lookup_tw_niels ( - tw_niels_a_t out, - const tw_niels_a_t *in, - int nin, - int idx -) { - constant_time_lookup(out,in,sizeof(*out),nin,idx); -} - -static void -convert_to_signed_window_form ( - word_t *out, - const word_t *scalar, - int nwords_scalar, - const word_t *prepared_data, - int nwords_pd -) { - assert(nwords_pd <= nwords_scalar); - mask_t mask = -(scalar[0]&1); - - word_t carry = add_nr_ext_packed(out, scalar, nwords_scalar, prepared_data, nwords_pd, ~mask); - carry += add_nr_ext_packed(out, out, nwords_scalar, prepared_data+nwords_pd, nwords_pd, mask); - - assert(!(out[0]&1)); - - int i; - for (i=0; i>= 1; - if (i> 1, - NTABLE = 1<<(WINDOW-1), - nbits = ROUND_UP(SCALAR_BITS,WINDOW); - - word_t scalar2[SCALAR_WORDS]; - convert_to_signed_window_form ( - scalar2, scalar, SCALAR_WORDS, - SCALARMUL_FIXED_WINDOW_ADJUSTMENT, SCALAR_WORDS - ); - - /* FIXME: tabulator is redundant */ - tw_extensible_a_t tabulator; - copy_tw_extensible(tabulator, working); - double_tw_extensible(tabulator); - - tw_pniels_a_t - pn VECTOR_ALIGNED, - multiples[NTABLE] VECTOR_ALIGNED; - convert_tw_extensible_to_tw_pniels(pn, tabulator); - convert_tw_extensible_to_tw_pniels(multiples[0], working); - - int i,j; - for (i=1; i> (i%WORD_BITS) & WINDOW_MASK, - inv = (bits>>(WINDOW-1))-1; - bits ^= inv; - - constant_time_lookup_tw_pniels(pn, (const tw_pniels_a_t*)multiples, NTABLE, bits & WINDOW_T_MASK); - cond_negate_tw_pniels(pn, inv); - convert_tw_pniels_to_tw_extensible(working, pn); - - - for (i-=WINDOW; i>=0; i-=WINDOW) { - for (j=0; j> (i%WORD_BITS); - - if (i/WORD_BITS < SCALAR_WORDS-1 && i%WORD_BITS >= WORD_BITS-WINDOW) { - bits ^= scalar2[i/WORD_BITS+1] << (WORD_BITS - (i%WORD_BITS)); - } - - bits &= WINDOW_MASK; - inv = (bits>>(WINDOW-1))-1; - bits ^= inv; - - constant_time_lookup_tw_pniels(pn, (const tw_pniels_a_t*)multiples, NTABLE, bits & WINDOW_T_MASK); - cond_negate_tw_pniels(pn, inv); - add_tw_pniels_to_tw_extensible(working, pn); - } -} - -void -scalarmul_ed ( - tw_extended_a_t working, - const word_t scalar[SCALAR_WORDS] -) { - const int WINDOW = SCALARMUL_FIXED_WINDOW_SIZE, - WINDOW_MASK = (1<> 1, - NTABLE = 1<<(WINDOW-1), - nbits = ROUND_UP(SCALAR_BITS,WINDOW); - - word_t scalar2[SCALAR_WORDS]; - convert_to_signed_window_form ( - scalar2, scalar, SCALAR_WORDS, - SCALARMUL_FIXED_WINDOW_ADJUSTMENT, SCALAR_WORDS - ); - - tw_extended_a_t - tmp VECTOR_ALIGNED, - multiples[NTABLE] VECTOR_ALIGNED; - - copy_tw_extended(tmp, working); - add_tw_extended(tmp, tmp); - copy_tw_extended(multiples[0], working); - - int i,j; - for (i=1; i=0; i-=WINDOW) { - if (i != nbits-WINDOW) { - for (j=0; j> (i%WORD_BITS); - - if (i/WORD_BITS < SCALAR_WORDS-1 && i%WORD_BITS >= WORD_BITS-WINDOW) { - bits ^= scalar2[i/WORD_BITS+1] << (WORD_BITS - (i%WORD_BITS)); - } - - bits &= WINDOW_MASK; - inv = (bits>>(WINDOW-1))-1; - bits ^= inv; - - constant_time_lookup_tw_extended(tmp, (const tw_extended_a_t*)multiples, NTABLE, bits & WINDOW_T_MASK); - add_sub_tw_extended(working, working, tmp, inv); - } -} - -void -scalarmul_vlook ( - tw_extensible_a_t working, - const word_t scalar[SCALAR_WORDS] -) { - const int WINDOW = SCALARMUL_FIXED_WINDOW_SIZE, - WINDOW_MASK = (1<> 1, - NTABLE = 1<<(WINDOW-1), - nbits = ROUND_UP(SCALAR_BITS,WINDOW); - - word_t scalar2[SCALAR_WORDS]; - convert_to_signed_window_form( - scalar2, scalar, SCALAR_WORDS, - SCALARMUL_FIXED_WINDOW_ADJUSTMENT, SCALAR_WORDS - ); - - - tw_extensible_a_t tabulator; - copy_tw_extensible(tabulator, working); - double_tw_extensible(tabulator); - - tw_pniels_a_t - pn VECTOR_ALIGNED, - multiples[NTABLE] VECTOR_ALIGNED; - convert_tw_extensible_to_tw_pniels(pn, tabulator); - convert_tw_extensible_to_tw_pniels(multiples[0], working); - - int i,j; - for (i=1; i> (i%WORD_BITS) & WINDOW_MASK, - inv = (bits>>(WINDOW-1))-1; - bits ^= inv; - - copy_tw_pniels(pn, multiples[bits & WINDOW_T_MASK]); - cond_negate_tw_pniels(pn, inv); - convert_tw_pniels_to_tw_extensible(working, pn); - - - for (i-=WINDOW; i>=0; i-=WINDOW) { - for (j=0; j> (i%WORD_BITS); - - if (i/WORD_BITS < SCALAR_WORDS-1 && i%WORD_BITS >= WORD_BITS-WINDOW) { - bits ^= scalar2[i/WORD_BITS+1] << (WORD_BITS - (i%WORD_BITS)); - } - - bits &= WINDOW_MASK; - inv = (bits>>(WINDOW-1))-1; - bits ^= inv; - - copy_tw_pniels(pn, multiples[bits & WINDOW_T_MASK]); - cond_negate_tw_pniels(pn, inv); - add_tw_pniels_to_tw_extensible(working, pn); - } -} - -static mask_t -schedule_scalar_for_combs ( - word_t *scalar2, - const word_t *scalar, - unsigned int nbits, - const struct fixed_base_table_t* table -) { - unsigned int i; - unsigned int n = table->n, t = table->t, s = table->s; - - if (n*t*s < nbits || n < 1 || t < 1 || s < 1) { - return MASK_FAILURE; - } - - unsigned int scalar_words = (nbits + WORD_BITS - 1)/WORD_BITS, - scalar2_words = scalar_words; - if (scalar2_words < SCALAR_WORDS) - scalar2_words = SCALAR_WORDS; - word_t scalar3[scalar2_words]; - - /* Copy scalar to scalar3, but clear its high bits (if there are any) */ - for (i=0; iscalar_adjustments , SCALAR_WORDS - ); - - return MASK_SUCCESS; -} - -mask_t -scalarmul_fixed_base ( - tw_extensible_a_t out, - const word_t scalar[SCALAR_WORDS], - unsigned int nbits, - const struct fixed_base_table_t* table -) { - unsigned int i,j,k; - unsigned int n = table->n, t = table->t, s = table->s; - - unsigned int scalar2_words = (nbits + WORD_BITS - 1)/WORD_BITS; - if (scalar2_words < SCALAR_WORDS) scalar2_words = SCALAR_WORDS; - - word_t scalar2[scalar2_words]; - - mask_t succ = schedule_scalar_for_combs(scalar2, scalar, nbits, table); - if (!succ) return MASK_FAILURE; - -#ifdef __clang_analyzer__ - assert(t >= 1); -#endif - - tw_niels_a_t ni; - - for (i=0; i> (bit%WORD_BITS) & 1) << k; - } - } - - mask_t invert = (tab>>(t-1))-1; - tab ^= invert; - tab &= (1<<(t-1)) - 1; - - constant_time_lookup_tw_niels(ni, (const tw_niels_a_t*)table->table + (j<<(t-1)), 1<<(t-1), tab); - cond_negate_tw_niels(ni, invert); - if (i||j) { - add_tw_niels_to_tw_extensible(out, ni); - } else { - convert_tw_niels_to_tw_extensible(out, ni); - } - } - } - - return MASK_SUCCESS; -} - -mask_t -linear_combo_combs_vt ( - tw_extensible_a_t out, - const word_t scalar1[SCALAR_WORDS], - unsigned int nbits1, - const struct fixed_base_table_t* table1, - const word_t scalar2[SCALAR_WORDS], - unsigned int nbits2, - const struct fixed_base_table_t* table2 -) { - unsigned int i,j,k,sc; - unsigned int s1 = table1->s, s2 = table2->s, smax = (s1 > s2) ? s1 : s2; - - unsigned int scalar1b_words = (nbits1 + WORD_BITS - 1)/WORD_BITS; - if (scalar1b_words < SCALAR_WORDS) scalar1b_words = SCALAR_WORDS; - - unsigned int scalar2b_words = (nbits2 + WORD_BITS - 1)/WORD_BITS; - if (scalar2b_words < SCALAR_WORDS) scalar2b_words = SCALAR_WORDS; - - word_t scalar1b[scalar1b_words], scalar2b[scalar2b_words]; - - /* Schedule the scalars */ - mask_t succ; - succ = schedule_scalar_for_combs(scalar1b, scalar1, nbits1, table1); - if (!succ) return MASK_FAILURE; - - succ = schedule_scalar_for_combs(scalar2b, scalar2, nbits2, table2); - if (!succ) return MASK_FAILURE; - -#ifdef __clang_analyzer__ - assert(table1->t >= 1); - assert(table2->t >= 1); -#endif - - const struct tw_niels_t *ni; - - unsigned int swords[2] = {scalar1b_words, scalar2b_words}; - word_t *scalars[2] = {scalar1b,scalar2b}; - - set_identity_tw_extensible(out); - - for (i=0; is; - if (ii < 0) continue; - assert(ii < (int)table->s); - - for (j=0; jn; j++) { - - int tab = 0; - - for (k=0; kt; k++) { - unsigned int bit = (table->s-1-ii) + k*table->s + j*(table->s*table->t); - if (bit < swords[sc] * WORD_BITS) { - tab |= (scalars[sc][bit/WORD_BITS] >> (bit%WORD_BITS) & 1) << k; - } - } - - mask_t invert = (tab>>(table->t-1))-1; - tab ^= invert; - tab &= (1<<(table->t-1)) - 1; - - ni = table->table[tab + (j<<(table->t-1))]; - - if (invert) sub_tw_niels_from_tw_extensible(out, ni); - else add_tw_niels_to_tw_extensible(out, ni); - } - } - } - - return MASK_SUCCESS; -} - - -mask_t -precompute_fixed_base ( - struct fixed_base_table_t* out, - const tw_extensible_a_t base, - unsigned int n, - unsigned int t, - unsigned int s, - tw_niels_a_t *prealloc -) { - if (s < 1 || t < 1 || n < 1 || n*t*s < SCALAR_BITS) { - really_memset(out, 0, sizeof(*out)); - return 0; - } - - out->n = n; - out->t = t; - out->s = s; - - tw_extensible_a_t working, start; - copy_tw_extensible(working, base); - tw_pniels_a_t pn_tmp; - - tw_pniels_a_t *doubles = (tw_pniels_a_t *) malloc_vector(sizeof(*doubles) * (t-1)); - field_a_t *zs = (field_a_t *) malloc_vector(sizeof(*zs) * (n<<(t-1))); - field_a_t *zis = (field_a_t *) malloc_vector(sizeof(*zis) * (n<<(t-1))); - - tw_niels_a_t *table = prealloc; - if (prealloc) { - out->own_table = 0; - } else { - table = (tw_niels_a_t *) malloc_vector(sizeof(*table) * (n<<(t-1))); - out->own_table = 1; - } - out->table = table; - - if (!doubles || !zs || !zis || !table) { - free(doubles); - free(zs); - free(zis); - really_memset(out, 0, sizeof(*out)); - really_memset(table, 0, sizeof(*table) * (n<<(t-1))); - if (!prealloc) free(table); - return 0; - } - - unsigned int i,j,k; - - /* Compute the scalar adjustments, equal to 2^nbits-1 mod q */ - unsigned int adjustment_size = (n*t*s)/WORD_BITS + 1; - assert(adjustment_size >= SCALAR_WORDS); - word_t adjustment[adjustment_size]; - for (i=0; iscalar_adjustments[(SCALAR_WORDS)*(adjustment[0] & 1)], - *high_adjustment = &out->scalar_adjustments[(SCALAR_WORDS)*((~adjustment[0]) & 1)]; - for (i=0; i>1); - int idx = (((i+1)<<(t-1))-1) ^ gray; - - convert_tw_extensible_to_tw_pniels(pn_tmp, start); - copy_tw_niels(table[idx], pn_tmp->n); - field_copy(zs[idx], pn_tmp->z); - - if (j >= (1u<<(t-1)) - 1) break; - int delta = (j+1) ^ ((j+1)>>1) ^ gray; - - for (k=0; delta>1; k++) - delta >>=1; - - if (gray & (1<a, zis[i]); - field_strong_reduce(product); - field_copy(table[i]->a, product); - - field_mul(product, table[i]->b, zis[i]); - field_strong_reduce(product); - field_copy(table[i]->b, product); - - field_mul(product, table[i]->c, zis[i]); - field_strong_reduce(product); - field_copy(table[i]->c, product); - } - - mask_t ret = ~field_is_zero(zis[0]); - - free(doubles); - free(zs); - free(zis); - - if (unlikely(!ret)) { - really_memset(table, 0, sizeof(*table) * (n<<(t-1))); - if (!prealloc) free(table); - really_memset(out, 0, sizeof(*out)); - return 0; - } - - return ret; -} - -void -destroy_fixed_base ( - struct fixed_base_table_t* table -) { - if (table->table) { - really_memset(table->table,0,sizeof(*table->table)*(table->n<<(table->t-1))); - } - if (table->own_table) { - free(table->table); - } - really_memset(table,0,sizeof(*table)); -} - -mask_t -precompute_fixed_base_wnaf ( - tw_niels_a_t *out, - const tw_extensible_a_t const_base, - unsigned int tbits -) { - int i; - field_a_t *zs = (field_a_t *) malloc_vector(sizeof(*zs)<z); - copy_tw_niels(out[0], tmp->n); - - if (tbits > 0) { - double_tw_extensible(base); - convert_tw_extensible_to_tw_pniels(twop, base); - add_tw_pniels_to_tw_extensible(base, tmp); - - convert_tw_extensible_to_tw_pniels(tmp, base); - field_copy(zs[1], tmp->z); - copy_tw_niels(out[1], tmp->n); - - for (i=2; i < 1<z); - copy_tw_niels(out[i], tmp->n); - } - } - - field_simultaneous_invert(zis, (const field_a_t *)zs, 1<a, zis[i]); - field_strong_reduce(product); - field_copy(out[i]->a, product); - - field_mul(product, out[i]->b, zis[i]); - field_strong_reduce(product); - field_copy(out[i]->b, product); - - field_mul(product, out[i]->c, zis[i]); - field_strong_reduce(product); - field_copy(out[i]->c, product); - } - - free(zs); - free(zis); - - return -1; -} - -/** - * @cond internal - * Control for variable-time scalar multiply algorithms. - */ -struct smvt_control { - int power, addend; -}; - -static int -recode_wnaf( - struct smvt_control *control, /* [nbits/(tableBits+1) + 3] */ - const word_t *scalar, - unsigned int nbits, - unsigned int tableBits) -{ - int current = 0, i, j; - unsigned int position = 0; - - /* PERF: negate scalar if it's large - * PERF: this is a pretty simplistic algorithm. I'm sure there's a faster one... - */ - for (i=nbits-1; i >= 0; i--) { - int bit = (scalar[i/WORD_BITS] >> (i%WORD_BITS)) & 1; - current = 2*current + bit; - - /* - * Sizing: |current| >= 2^(tableBits+1) -> |current| = 2^0 - * So current loses (tableBits+1) bits every time. It otherwise gains - * 1 bit per iteration. The number of iterations is - * (nbits + 2 + tableBits), and an additional control word is added at - * the end. So the total number of control words is at most - * ceil((nbits+1) / (tableBits+1)) + 2 = floor((nbits)/(tableBits+1)) + 2. - * There's also the stopper with power -1, for a total of +3. - */ - if (current >= (2<> 1; /* |delta| < 2^tablebits */ - current = -(current & 1); - - for (j=i; (delta & 1) == 0; j++) { - delta >>= 1; - } - control[position].power = j+1; - control[position].addend = delta; - position++; - assert(position <= nbits/(tableBits+1) + 2); - } - } - - if (current) { - for (j=0; (current & 1) == 0; j++) { - current >>= 1; - } - control[position].power = j; - control[position].addend = current; - position++; - assert(position <= nbits/(tableBits+1) + 2); - } - - - control[position].power = -1; - control[position].addend = 0; - return position; -} - - -static void -prepare_wnaf_table( - tw_pniels_a_t *output, - tw_extensible_a_t working, - unsigned int tbits -) { - int i; - convert_tw_extensible_to_tw_pniels(output[0], working); - - if (tbits == 0) return; - - double_tw_extensible(working); - tw_pniels_a_t twop; - convert_tw_extensible_to_tw_pniels(twop, working); - - add_tw_pniels_to_tw_extensible(working, output[0]); - convert_tw_extensible_to_tw_pniels(output[1], working); - - for (i=2; i < 1< 0) { - assert(control[0].addend > 0); - assert(control[0].power >= 0); - convert_tw_pniels_to_tw_extensible(working, precmp[control[0].addend >> 1]); - } else { - set_identity_tw_extensible(working); - return; - } - - int conti = 1, i; - for (i = control[0].power - 1; i >= 0; i--) { - double_tw_extensible(working); - - if (i == control[conti].power) { - assert(control[conti].addend); - - if (control[conti].addend > 0) { - add_tw_pniels_to_tw_extensible(working, precmp[control[conti].addend >> 1]); - } else { - sub_tw_pniels_from_tw_extensible(working, precmp[(-control[conti].addend) >> 1]); - } - conti++; - assert(conti <= control_bits); - } - } -} - -void -scalarmul_fixed_base_wnaf_vt ( - tw_extensible_a_t working, - const word_t scalar[SCALAR_WORDS], - unsigned int nbits, - const tw_niels_a_t *precmp, - unsigned int table_bits -) { - struct smvt_control control[nbits/(table_bits+1)+3]; - - int control_bits = recode_wnaf(control, scalar, nbits, table_bits); - - if (control_bits > 0) { - assert(control[0].addend > 0); - assert(control[0].power >= 0); - convert_tw_niels_to_tw_extensible(working, precmp[control[0].addend >> 1]); - } else { - set_identity_tw_extensible(working); - return; - } - - int conti = 1, i; - for (; control[conti].power >= 0; conti++) { - assert(conti <= control_bits); - for (i = control[conti-1].power - control[conti].power; i; i--) { - double_tw_extensible(working); - } - - assert(control[conti].addend); - if (control[conti].addend > 0) { - add_tw_niels_to_tw_extensible(working, precmp[control[conti].addend >> 1]); - } else { - sub_tw_niels_from_tw_extensible(working, precmp[(-control[conti].addend) >> 1]); - } - } - - for (i = control[conti-1].power; i; i--) { - double_tw_extensible(working); - } -} - -void -linear_combo_var_fixed_vt( - tw_extensible_a_t working, - const word_t scalar_var[SCALAR_WORDS], - unsigned int nbits_var, - const word_t scalar_pre[SCALAR_WORDS], - unsigned int nbits_pre, - const tw_niels_a_t *precmp, - unsigned int table_bits_pre -) { - const int table_bits_var = SCALARMUL_WNAF_COMBO_TABLE_BITS; - struct smvt_control control_var[nbits_var/(table_bits_var+1)+3]; - struct smvt_control control_pre[nbits_pre/(table_bits_pre+1)+3]; - - int ncb_var = recode_wnaf(control_var, scalar_var, nbits_var, table_bits_var); - int ncb_pre = recode_wnaf(control_pre, scalar_pre, nbits_pre, table_bits_pre); - (void)ncb_var; - (void)ncb_pre; - - tw_pniels_a_t precmp_var[1< control_pre[0].power) { - convert_tw_pniels_to_tw_extensible(working, precmp_var[control_var[0].addend >> 1]); - contv++; - } else if (i == control_pre[0].power && i >=0 ) { - convert_tw_pniels_to_tw_extensible(working, precmp_var[control_var[0].addend >> 1]); - add_tw_niels_to_tw_extensible(working, precmp[control_pre[0].addend >> 1]); - contv++; contp++; - } else { - i = control_pre[0].power; - convert_tw_niels_to_tw_extensible(working, precmp[control_pre[0].addend >> 1]); - contp++; - } - - if (i < 0) { - set_identity_tw_extensible(working); - return; - } - - for (i--; i >= 0; i--) { - double_tw_extensible(working); - - if (i == control_var[contv].power) { - assert(control_var[contv].addend); - - if (control_var[contv].addend > 0) { - add_tw_pniels_to_tw_extensible(working, precmp_var[control_var[contv].addend >> 1]); - } else { - sub_tw_pniels_from_tw_extensible(working, precmp_var[(-control_var[contv].addend) >> 1]); - } - contv++; - } - - if (i == control_pre[contp].power) { - assert(control_pre[contp].addend); - - if (control_pre[contp].addend > 0) { - add_tw_niels_to_tw_extensible(working, precmp[control_pre[contp].addend >> 1]); - } else { - sub_tw_niels_from_tw_extensible(working, precmp[(-control_pre[contp].addend) >> 1]); - } - contp++; - } - } - - assert(contv == ncb_var); - assert(contp == ncb_pre); -} - - - diff --git a/src/sha512.c b/src/sha512.c deleted file mode 100644 index 9a11bd0..0000000 --- a/src/sha512.c +++ /dev/null @@ -1,177 +0,0 @@ -/* Copyright (c) 2011 Stanford University. - * Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ -#include "word.h" -#include "sha512.h" - -#include -#include - -static inline uint64_t -rotate_r ( - uint64_t x, - int d -) { - return (x >> d) | (x << (64-d)); -} - -static const uint64_t -sha512_init_state[8] = { - 0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1, - 0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179 -}; - -static const uint64_t -sha512_k[80] = { - 0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc, - 0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118, - 0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2, - 0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694, - 0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65, - 0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5, - 0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4, - 0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70, - 0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df, - 0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b, - 0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30, - 0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8, - 0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8, - 0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3, - 0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec, - 0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b, - 0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178, - 0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b, - 0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c, - 0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817 -}; - -static inline uint64_t S0 (uint64_t h1) { - return rotate_r(h1, 28) ^ rotate_r(h1, 34) ^ rotate_r(h1, 39); -} - -static inline uint64_t S1 (uint64_t h4) { - return rotate_r(h4,14) ^ rotate_r(h4,18) ^ rotate_r(h4,41); -} - -static inline uint64_t s0 (uint64_t a) { - return rotate_r(a,1) ^ rotate_r(a,8) ^ a>>7; -} - -static inline uint64_t s1 (uint64_t b) { - return rotate_r(b,19) ^ rotate_r(b,61) ^ b>>6; -} - -static inline uint64_t ch (uint64_t h4, uint64_t h5, uint64_t h6) { - return h6^(h4 & (h6^h5)); -} - -static inline uint64_t maj(uint64_t h1, uint64_t h2, uint64_t h3) { - return (h1&h2) ^ (h3&(h1^h2)); -} - -static void -sha512_process_block ( - sha512_ctx_a_t ctx -) { - uint64_t i, tmp, a, b, - *w = (uint64_t *) ctx->block, - *state = ctx->chain, - h0 = state[0], h1 = state[1], h2 = state[2], h3 = state[3], - h4 = state[4], h5 = state[5], h6 = state[6], h7 = state[7]; - - /* Clang doesn't unswitch this automatically */ - for (i=0; i<16; i++) { - /* load up the input word for this round */ - tmp = w[i] = htobe64(w[i]); - tmp = tmp + h7 + S1(h4) + ch(h4,h5,h6) + sha512_k[i]; - - /* shift register */ - h7 = h6; h6 = h5; h5 = h4; - h4 = h3 + tmp; - h3 = h2; h2 = h1; h1 = h0; - h0 = tmp + maj(h1,h2,h3) + S0(h1); - } - - for (; i<80; i++) { - /* load up the input word for this round */ - a = w[(i+1 ) & 15]; - b = w[(i+14) & 15]; - tmp = w[i&15] = s0(a) + s1(b) + w[i&15] + w[(i+9) & 15]; - tmp = tmp + h7 + S1(h4) + ch(h4,h5,h6) + sha512_k[i]; - - /* shift register */ - h7 = h6; h6 = h5; h5 = h4; - h4 = h3 + tmp; - h3 = h2; h2 = h1; h1 = h0; - h0 = tmp + maj(h1,h2,h3) + S0(h1); - } - - state[0] += h0; - state[1] += h1; - state[2] += h2; - state[3] += h3; - state[4] += h4; - state[5] += h5; - state[6] += h6; - state[7] += h7; -} - -void -sha512_init ( - sha512_ctx_a_t ctx -) { - ctx->nbytes = 0; - memcpy(ctx->chain, sha512_init_state, sizeof(sha512_init_state)); - memset(ctx->block, 0, sizeof(ctx->block)); -} - -void -sha512_update ( - sha512_ctx_a_t ctx, - const unsigned char *data, - uint64_t bytes -) { - assert(ctx->nbytes < 1ull<<56); - assert(bytes < 1ull<<56); - - while (bytes) { - uint64_t fill = ctx->nbytes % 128, accept = 128 - fill; - if (accept > bytes) accept = bytes; - ctx->nbytes += accept; - memcpy(ctx->block + fill, data, accept); - - if (fill+accept == 128) - sha512_process_block(ctx); - - bytes -= accept; - data += accept; - } - - assert(ctx->nbytes < 1ull<<56); -} - -void -sha512_final ( - sha512_ctx_a_t ctx, - uint8_t result[64] -) { - uint64_t fill = ctx->nbytes % 128, i; - ctx->block[fill++] = 0x80; - if (fill > 112) { - memset(ctx->block + fill, 0, 128-fill); - sha512_process_block(ctx); - fill = 0; - } - memset(ctx->block + fill, 0, 112-fill); - - uint64_t highCount = 0, lowCount = htobe64((ctx->nbytes * 8)); - memcpy(&ctx->block[112],&highCount,8); - memcpy(&ctx->block[120],&lowCount,8); - sha512_process_block(ctx); - for (i=0; i<8; i++) { - ctx->chain[i] = htobe64(ctx->chain[i]); - } - memcpy(result, ctx->chain, sizeof(ctx->chain)); - sha512_init(ctx); -} diff --git a/test/bench.c b/test/bench.c deleted file mode 100644 index 167dbc0..0000000 --- a/test/bench.c +++ /dev/null @@ -1,780 +0,0 @@ -/* Copyright (c) 2014 Cryptography Research, Inc. - * Released under the MIT License. See LICENSE.txt for license information. - */ - -#include "word.h" - -#include -#include -#include -#include - -#include "field.h" -#include "ec_point.h" -#include "scalarmul.h" -#include "barrett_field.h" -#include "crandom.h" -#include "goldilocks.h" -#include "sha512.h" -#include "decaf.h" -#include "decaf_crypto.h" -#include "shake.h" - -static __inline__ void -ignore_result ( int result ) { - (void)result; -} - -static double now(void) { - struct timeval tv; - gettimeofday(&tv, NULL); - - return tv.tv_sec + tv.tv_usec/1000000.0; -} - -static void field_randomize( struct crandom_state_t *crand, field_a_t a ) { - crandom_generate(crand, (unsigned char *)a, sizeof(*a)); - field_strong_reduce(a); -} - -static void q448_randomize( struct crandom_state_t *crand, word_t sk[SCALAR_WORDS] ) { - crandom_generate(crand, (unsigned char *)sk, SCALAR_BYTES); -} - -static void field_print( const char *descr, const field_a_t a ) { - int j; - unsigned char ser[FIELD_BYTES]; - field_serialize(ser,a); - printf("%s = 0x", descr); - for (j=FIELD_BYTES - 1; j>=0; j--) { - printf("%02x", ser[j]); - } - printf("\n"); -} - -static void __attribute__((unused)) -field_print_full ( - const char *descr, - const field_a_t a -) { - int j; - printf("%s = 0x", descr); - for (j=15; j>=0; j--) { - printf("%02" PRIxWORD "_" PRIxWORD56 " ", - a->limb[j]>>28, a->limb[j]&((1<<28)-1)); - } - printf("\n"); -} - -#ifndef N_TESTS_BASE -#define N_TESTS_BASE 10000 -#endif - -int main(int argc, char **argv) { - (void)argc; - (void)argv; - - struct tw_extensible_t ext; - struct extensible_t exta; - struct tw_niels_t niels; - struct tw_pniels_t pniels; - struct affine_t affine; - struct montgomery_t mb; - struct montgomery_aux_t mba; - field_a_t a,b,c,d; - - double when; - int i; - - int nbase = N_TESTS_BASE; - - /* Bad randomness so we can debug. */ - char initial_seed[32]; - for (i=0; i<32; i++) initial_seed[i] = i; - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, initial_seed); - /* For testing the performance drop from the crandom debuffering change. - ignore_result(crandom_init_from_file(&crand, "/dev/urandom", 10000, 1)); - */ - - word_t sk[SCALAR_WORDS],tk[SCALAR_WORDS]; - q448_randomize(&crand, sk); - - memset(a,0,sizeof(a)); - memset(b,0,sizeof(b)); - memset(c,0,sizeof(c)); - memset(d,0,sizeof(d)); - when = now(); - for (i=0; ia isog: %5.1fns\n", when * 1e9 / i); - - when = now(); - for (i=0; ii isog: %5.1fns\n", when * 1e9 / i); - - memset(&mb,0,sizeof(mb)); - when = now(); - for (i=0; i -#include - -#ifndef LIMBPERM -#define LIMBPERM(x) (x) -#endif - -int failed_tests, n_tests, failed_this_test, running_a_test; - -static void end_test(void) { - if (!failed_this_test) { - printf("[PASS]\n"); - } - n_tests ++; - running_a_test = 0; -} - -static void begin_test(const char *name) { - if (running_a_test) end_test(); - printf("%s...%*s",name,(int)(30-strlen(name)),""); - fflush(stdout); - failed_this_test = 0; - running_a_test = 1; -} - -void youfail(void) { - if (failed_this_test) return; - failed_this_test = 1; - failed_tests ++; - printf("[FAIL]\n"); -} - -static int -hexchar (char c) { - if (c >= '0' && c <= '9') { - return c - '0'; - } else if (c >= 'a' && c <= 'f') { - return 10 + c - 'a'; - } else if (c >= 'A' && c <= 'F') { - return 10 + c - 'A'; - } else { - return -1; - } -} - -int -hexdecode ( - unsigned char *bytes, - const char *hex, - unsigned int nbytes -) { - if (strlen(hex) != nbytes*2) { - return -1; - } - - unsigned int i; - for (i=0; i=0; j--) { - printf("%02x", ser[j]); - } - printf("\n"); -} - -void scalar_print ( - const char *descr, - const word_t *scalar, - int nwords -) { - int j; - printf("%s = 0x", descr); - for (j=nwords-1; j>=0; j--) { - printf(PRIxWORDfull, scalar[j]); - } - printf("\n"); -} - -int main(int argc, char **argv) { - (void) argc; - (void) argv; - - n_tests = running_a_test = failed_tests = 0; - - begin_test("Arithmetic"); - test_arithmetic(); - - begin_test("EC point operations"); - test_pointops(); - - begin_test("Decaf point encoding"); - test_decaf(); - - begin_test("Decaf pathological cases"); - test_decaf_evil(); - - begin_test("Scalarmul compatibility"); - test_scalarmul_compatibility(); - - begin_test("Scalarmul commutativity"); - test_scalarmul_commutativity(); - - begin_test("Linear combo"); - test_linear_combo(); - - begin_test("SHA-512 NIST Monte Carlo"); - test_sha512_monte_carlo(); - - begin_test("Goldilocks complete system"); - test_goldilocks(); - - if (running_a_test) end_test(); - printf("\n"); - if (failed_tests) { - printf("Failed %d / %d tests.\n", failed_tests, n_tests); - } else { - printf("Passed all %d tests.\n", n_tests); - } - - return failed_tests ? 1 : 0; -} diff --git a/test/test.h b/test/test.h deleted file mode 100644 index 0e192e8..0000000 --- a/test/test.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef __GOLDILOCKS_TEST_H__ -#define __GOLDILOCKS_TEST_H__ 1 - -#include "word.h" -#include "field.h" - -int -hexdecode ( - unsigned char *bytes, - const char *hex, - unsigned int nbytes -); - -void -hexprint ( - const char *descr, - const unsigned char *bytes, - unsigned int nbytes -); - -void field_print ( - const char *descr, - const field_a_t a -); - -void scalar_print ( - const char *descr, - const word_t *scalar, - int nwords -); - -void youfail(void); - -int test_sha512_monte_carlo(void); - -int test_linear_combo (void); - -int test_scalarmul_compatibility (void); - -int test_scalarmul_commutativity (void); - -int test_arithmetic (void); - -int test_goldilocks (void); - -int test_pointops (void); - -int test_decaf (void); -int test_decaf_evil (void); - -#endif // __GOLDILOCKS_TEST_H__ diff --git a/test/test_arithmetic.c b/test/test_arithmetic.c deleted file mode 100644 index 20acc49..0000000 --- a/test/test_arithmetic.c +++ /dev/null @@ -1,392 +0,0 @@ -#include "field.h" -#include "test.h" -#include "decaf.h" -#include -#include -#include - -mpz_t mp_field; -mpz_t mp_scalar_field; - -static void decaf_448_scalar_print ( - const char *descr, - const decaf_448_scalar_t scalar -) { - int j; - printf("%s = 0x", descr); - for (j=DECAF_448_SCALAR_LIMBS-1; j>=0; j--) { - printf(PRIxWORDfull, scalar->limb[j]); - } - printf("\n"); -} - -static mask_t mpz_to_field ( - field_a_t out, - const mpz_t in -) { - uint8_t ser[FIELD_BYTES]; - mpz_t modded; - memset(ser,0,sizeof(ser)); - mpz_init(modded); - mpz_mod(modded, in, mp_field); - mpz_export(ser, NULL, -1, 1, -1, 0, modded); - mask_t succ = field_deserialize(out, ser); - return succ; -} - -static mask_t mpz_to_scalar ( - decaf_448_scalar_t out, - const mpz_t in -) { - uint8_t ser[DECAF_448_SCALAR_BYTES]; - mpz_t modded; - memset(ser,0,sizeof(ser)); - mpz_init(modded); - mpz_mod(modded, in, mp_scalar_field); - mpz_export(ser, NULL, -1, 1, -1, 0, modded); - mask_t succ = decaf_448_scalar_decode(out, ser); - return succ; -} - -static mask_t scalar_assert_eq_gmp( - const char *descr, - const decaf_448_scalar_t a, - const decaf_448_scalar_t b, - const decaf_448_scalar_t x, - const mpz_t ma, - const mpz_t mb, - const mpz_t y -) { - uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES]; - mpz_t modded; - - memset(yser,0,sizeof(yser)); - - decaf_448_scalar_encode(xser, x); - - mpz_init(modded); - mpz_mod(modded, y, mp_scalar_field); - mpz_export(yser, NULL, -1, 1, -1, 0, modded); - - if (memcmp(xser,yser,FIELD_BYTES)) { - youfail(); - printf(" Failed arithmetic test %s\n", descr); - decaf_448_scalar_print(" a", a); - decaf_448_scalar_print(" b", b); - decaf_448_scalar_print(" decaf_448", x); - // printf(" gmpa = 0x"); - - int j; - // mpz_export(yser, NULL, -1, 1, -1, 0, ma); - // for (j=FIELD_BYTES-1; j>=0; j--) { - // printf("%02x", yser[j]); - // } - // printf("\n"); - // printf(" gmpb = 0x"); - // - // - // mpz_export(yser, NULL, -1, 1, -1, 0, mb); - // for (j=FIELD_BYTES-1; j>=0; j--) { - // printf("%02x", yser[j]); - // } - // printf("\n"); - (void)ma; (void)mb; - - printf(" gmpy = 0x"); - - mpz_export(yser, NULL, -1, 1, -1, 0, modded); - for (j=FIELD_BYTES-1; j>=0; j--) { - printf("%02x", yser[j]); - } - printf("\n"); - return MASK_FAILURE; - } - - mpz_clear(modded); - return MASK_SUCCESS; -} - -static inline int BRANCH_ON_CONSTANT(int x) { - __asm__ ("" : "+r"(x)); - return x; -} - -static mask_t field_assert_eq_gmp( - const char *descr, - const field_a_t a, - const field_a_t b, - const field_a_t x, - const mpz_t y, - float lowBound, - float highBound -) { - uint8_t xser[FIELD_BYTES], yser[FIELD_BYTES]; - mpz_t modded; - - memset(yser,0,sizeof(yser)); - - field_serialize(xser, x); - - mpz_init(modded); - mpz_mod(modded, y, mp_field); - mpz_export(yser, NULL, -1, 1, -1, 0, modded); - - unsigned int i; - for (i=0; ilimb[0]); i++) { - int radix_bits = 1 + (sizeof(x->limb[0]) * FIELD_BITS - 1) / sizeof(*x); - word_t yardstick; - - if (BRANCH_ON_CONSTANT(FIELD_BITS == 521) && BRANCH_ON_CONSTANT(sizeof(*x)==12*8)) { - radix_bits = 58; - } - - yardstick = (1ull<limb[i] < yardstick * lowBound || x->limb[i] > yardstick * highBound) { - youfail(); - printf(" Limb %d -> " PRIxWORDfull " is out of bounds (%0.2f, %0.2f) for test %s (yardstick = " PRIxWORDfull ")\n", - i, x->limb[i], lowBound, highBound, descr, yardstick); - break; - } - } - - if (memcmp(xser,yser,FIELD_BYTES)) { - youfail(); - printf(" Failed arithmetic test %s\n", descr); - field_print(" a", a); - field_print(" b", b); - field_print(" goldi", x); - printf(" gmp = 0x"); - int j; - for (j=FIELD_BYTES-1; j>=0; j--) { - printf("%02x", yser[j]); - } - printf("\n"); - return MASK_FAILURE; - } - - mpz_clear(modded); - return MASK_SUCCESS; -} - -static mask_t test_add_sub_RAW ( - const mpz_t x, - const mpz_t y, - word_t word -) { - field_a_t xx,yy,tt; - mpz_t t; - mask_t succ = MASK_SUCCESS; - succ = mpz_to_field(xx,x); - succ &= mpz_to_field(yy,y); - mpz_init(t); - - field_add_RAW(tt,xx,yy); - mpz_add(t,x,y); - succ &= field_assert_eq_gmp("add",xx,yy,tt,t,0,2.1); - - field_sub_RAW(tt,xx,yy); - field_bias(tt,2); - mpz_sub(t,x,y); - succ &= field_assert_eq_gmp("sub",xx,yy,tt,t,0,3.1); - - field_copy(tt,xx); - field_addw(tt,word); - mpz_add_ui(t,x,word); - succ &= field_assert_eq_gmp("addw",xx,yy,tt,t,0,2.1); - - field_copy(tt,xx); - field_subw(tt,word); - field_bias(tt,1); - mpz_sub_ui(t,x,word); - succ &= field_assert_eq_gmp("subw",xx,yy,tt,t,0,2.1); - - /* - if (!succ) { - field_print(" x", &xx); - field_print(" y", &yy); - } - */ - - mpz_clear(t); - - return succ; -} - -static mask_t test_scalar ( - const mpz_t x, - const mpz_t y, - int inv -) { - decaf_448_scalar_t xx,yy,tt; - mpz_t t; - mask_t succ = MASK_SUCCESS; - succ = mpz_to_scalar(xx,x); - succ &= mpz_to_scalar(yy,y); - mpz_init(t); - - decaf_448_scalar_add(tt,xx,yy); - mpz_add(t,x,y); - succ &= scalar_assert_eq_gmp("scalar add",xx,yy,tt,x,y,t); - - decaf_448_scalar_sub(tt,xx,yy); - mpz_sub(t,x,y); - succ &= scalar_assert_eq_gmp("scalar sub",xx,yy,tt,x,y,t); - - decaf_448_scalar_mul(tt,xx,yy); - mpz_mul(t,x,y); - succ &= scalar_assert_eq_gmp("scalar mul",xx,yy,tt,x,y,t); - - if (inv) { - decaf_bool_t ret = decaf_448_scalar_invert(tt,xx); - if (!mpz_cmp_ui(x,0)) { - mpz_set_ui(t,0); - succ &= (ret == 0) ? MASK_SUCCESS : MASK_FAILURE; - } else { - mpz_invert(t,x,mp_scalar_field); - succ &= (ret == MASK_SUCCESS) ? MASK_SUCCESS : MASK_FAILURE; - } - succ &= scalar_assert_eq_gmp("scalar inv",xx,yy,tt,x,y,t); - } - - mpz_clear(t); - - return succ; -} - -static mask_t test_mul_sqr ( - const mpz_t x, - const mpz_t y, - word_t word -) { - ANALYZE_THIS_ROUTINE_CAREFULLY; - field_a_t xx,yy,tt,zz; - mpz_t t, z; - mask_t succ = MASK_SUCCESS; - succ = mpz_to_field(xx,x); - succ &= mpz_to_field(yy,y); - mpz_init(t); - mpz_init(z); - - field_mul(tt,xx,yy); - mpz_mul(t,x,y); - succ &= field_assert_eq_gmp("mul",xx,yy,tt,t,0,1.1); - - field_mulw(tt,xx,word); - mpz_mul_ui(t,x,word); - succ &= field_assert_eq_gmp("mulw",xx,yy,tt,t,0,1.1); - - field_sqr(tt,xx); - mpz_mul(t,x,x); - succ &= field_assert_eq_gmp("sqrx",xx,yy,tt,t,0,1.1); - - field_sqr(tt,yy); - mpz_mul(t,y,y); - succ &= field_assert_eq_gmp("sqy",xx,yy,tt,t,0,1.1); - - field_add_nr(zz,xx,xx); - mpz_add(z,x,x); - mpz_mul(t,z,z); - field_mul(tt,zz,zz); - succ &= field_assert_eq_gmp("msr4",xx,yy,tt,t,0,1.1); - field_sqr(tt,zz); - succ &= field_assert_eq_gmp("sqr4",xx,yy,tt,t,0,1.1); - - if (!succ) { - field_print(" x", xx); - field_print(" y", yy); - } - - mpz_clear(t); - mpz_clear(z); - - return succ; -} - -static mask_t test_isr ( - const mpz_t x -) { - field_a_t xx,yy,ss,tt; - mask_t succ = 0; - succ = mpz_to_field(xx,x); - - field_isr(ss,xx); - field_sqr(tt,ss); - field_mul(yy,xx,tt); - - field_addw(tt,1); - succ |= field_is_zero(tt); - - field_subw(tt,2); - field_bias(tt,1); - succ |= field_is_zero(tt); - - field_addw(tt,1); - if (~succ) { - youfail(); - printf("ISR failure.\n"); - field_print(" x", xx); - field_print(" s", ss); - field_print(" t", tt); - } - - return succ; -} - -void dbg_gmp_printf(const mpz_t x); -void dbg_gmp_printf(const mpz_t x) { - gmp_printf("DEBUG: 0x%Zx\n", x); -} - -int test_arithmetic (void) { - int j, ntests = 100000; - - gmp_randstate_t state; - gmp_randinit_mt(state); - mpz_init(mp_field); - mpz_import(mp_field, FIELD_BYTES, -1, 1, -1, 0, FIELD_MODULUS); - - mpz_import(mp_scalar_field, DECAF_448_SCALAR_LIMBS, -1, sizeof(decaf_word_t), -1, 0, decaf_448_scalar_p); - - mpz_t x,y; - mpz_init(x); - mpz_init(y); - - mask_t succ = MASK_SUCCESS; - - int radix_bits = sizeof(word_t) * FIELD_BITS / sizeof(field_a_t); - - for (j=0; j -#include -#include - -int test_goldilocks (void) { - const char *message1 = "hello world"; - const char *message2 = "Jello world"; - - unsigned char signature[GOLDI_SIGNATURE_BYTES]; - - unsigned char - ss12[GOLDI_SHARED_SECRET_BYTES], - ss21[GOLDI_SHARED_SECRET_BYTES], - ss21p[GOLDI_SHARED_SECRET_BYTES], - proto[GOLDI_SYMKEY_BYTES]; - - struct goldilocks_public_key_t pub, pub2; - struct goldilocks_private_key_t priv, priv2; - struct goldilocks_precomputed_public_key_t *pre = NULL; - - int i, ret, good = 1; - - ret = goldilocks_init(); - if (ret) { - youfail(); - printf(" Failed init.\n"); - } - - for (i=0; i<1000 && good; i++) { - - ret = goldilocks_keygen(&priv, &pub); - if (ret) { - youfail(); - printf(" Failed keygen trial %d.\n", i); - good = 0; - } - - goldilocks_destroy_precomputed_public_key( pre ); - pre = goldilocks_precompute_public_key ( &pub ); - if (!pre) { - youfail(); - printf(" Failed precomp-public trial %d.\n", i); - return -1; - } - - ret = goldilocks_sign( - signature, - (const unsigned char *)message1, - strlen(message1), - &priv - ); - if (ret) { - youfail(); - printf(" Failed sign trial %d.\n", i); - good = 0; - } - - ret = goldilocks_verify( - signature, - (const unsigned char *)message1, - strlen(message1), - &pub - ); - if (ret) { - youfail(); - printf(" Failed verify trial %d.\n", i); - good = 0; - } - - ret = goldilocks_verify_precomputed ( - signature, - (const unsigned char *)message1, - strlen(message1), - pre - ); - if (ret) { - youfail(); - printf(" Failed verify-pre trial %d.\n", i); - good = 0; - } - - /* terrible negative test */ - ret = goldilocks_verify( - signature, - (const unsigned char *)message2, - strlen(message1), - &pub - ); - if (ret != GOLDI_EINVAL) { - youfail(); - printf(" Failed nega-verify trial %d.\n", i); - good = 0; - } - ret = goldilocks_verify_precomputed( - signature, - (const unsigned char *)message2, - strlen(message1), - pre - ); - if (ret != GOLDI_EINVAL) { - youfail(); - printf(" Failed nega-verify-pre trial %d.\n", i); - good = 0; - } - - /* honestly a slightly better negative test */ - memset(signature,0,sizeof(signature)); - ret = goldilocks_verify( - signature, - (const unsigned char *)message1, - strlen(message1), - &pub - ); - if (ret != GOLDI_EINVAL) { - youfail(); - printf(" Failed nega-verify-0 trial %d.\n", i); - good = 0; - } - ret = goldilocks_verify_precomputed( - signature, - (const unsigned char *)message1, - strlen(message1), - pre - ); - if (ret != GOLDI_EINVAL) { - youfail(); - printf(" Failed nega-verify-pre-0 trial %d.\n", i); - good = 0; - } - - /* ecdh */ - ret = goldilocks_keygen(&priv2, &pub2); - if (ret) { - youfail(); - printf(" Failed keygen2 trial %d.\n", i); - good = 0; - } - - ret = goldilocks_shared_secret ( ss12, &priv, &pub2 ); - if (ret) { - youfail(); - printf(" Failed ss12 trial %d.\n", i); - good = 0; - } - - ret = goldilocks_shared_secret ( ss21, &priv2, &pub ); - if (ret) { - youfail(); - printf(" Failed ss21 trial %d.\n", i); - good = 0; - } - - ret = goldilocks_shared_secret_precomputed ( ss21p, &priv2, pre ); - if (ret) { - youfail(); - printf(" Failed ss21p trial %d.\n", i); - good = 0; - } - - if (memcmp(ss12,ss21,sizeof(ss12))) { - youfail(); - printf(" Failed shared-secret trial %d.\n", i); - good = 0; - } - - if (memcmp(ss21,ss21p,sizeof(ss21))) { - youfail(); - printf(" Failed shared-secret precomp trial %d.\n", i); - good = 0; - } - - /* test derive / underive / priv to pub */ - goldilocks_underive_private_key ( proto, &priv ); - ret = goldilocks_derive_private_key ( &priv2, proto ); - if (ret || memcmp(&priv,&priv2,sizeof(priv))) { - youfail(); - printf(" Failed derive round-trip trial %d.\n", i); - good = 0; - } - - ret = goldilocks_private_to_public ( &pub2, &priv ); - if (ret || memcmp(&pub,&pub2,sizeof(pub))) { - youfail(); - printf(" Failed private-to-public trial %d.\n", i); - good = 0; - } - - } - - goldilocks_destroy_precomputed_public_key( pre ); - - return good ? 0 : -1; -} diff --git a/test/test_pointops.c b/test/test_pointops.c deleted file mode 100644 index 9d79cb1..0000000 --- a/test/test_pointops.c +++ /dev/null @@ -1,648 +0,0 @@ -#include "test.h" - -#include - -#include "ec_point.h" -#include "decaf.h" -#include "scalarmul.h" -#include "magic.h" -#include "field.h" -#include "crandom.h" - - -static void -failprint_ext ( - const struct extensible_t *a -) { - field_a_t zi, scaled; - field_print(" x", a->x); - field_print(" y", a->y); - field_print(" z", a->z); - field_inverse(zi, a->z); - field_mul(scaled, zi, a->x); - field_print(" X", scaled); - field_mul(scaled, zi, a->y); - field_print(" Y", scaled); - printf("\n"); -} - -static void -failprint_tw_ext ( - const struct tw_extensible_t *a -) { - failprint_ext((const struct extensible_t *)a); -} - -static mask_t -fail_if_different ( - const struct extensible_t *a, - const struct extensible_t *b, - const char *faildescr, - const char *adescr, - const char *bdescr -) { - mask_t succ = eq_extensible(a, b); - - if (!succ) { - youfail(); - printf(" %s\n", faildescr); - - printf("\n %s:\n", adescr); - failprint_ext(a); - - printf("\n %s:\n", bdescr); - failprint_ext(b); - } - - return succ; -} - -static mask_t -validate_ext( - const struct extensible_t *ext, - int evenness, - const char *description -) { - mask_t succ = validate_extensible(ext), succ2; - const char *error = "Point isn't on the curve."; - if (evenness > 0) { - succ2 = is_even_pt(ext); - if (succ &~ succ2) error = "Point isn't even."; - succ &= succ2; - } else if (evenness < 0) { - succ2 = is_even_pt(ext); - if (succ &~ succ2) error = "Point is even but shouldn't be."; - succ &= succ2; - } /* FUTURE: quadness */ - - if (~succ) { - youfail(); - printf(" %s\n", error); - printf(" %s\n", description); - failprint_ext(ext); - } - - return succ; -} - -static mask_t -validate_tw_ext( - const struct tw_extensible_t *ext, - int evenness, - const char *description -) { - mask_t succ = validate_tw_extensible(ext), succ2; - const char *error = "Point isn't on the twisted curve."; - if (evenness > 0) { - succ2 = is_even_tw(ext); - if (succ &~ succ2) error = "Point isn't even."; - succ &= succ2; - } else if (evenness < 0) { - succ2 = is_even_tw(ext); - if (succ &~ succ2) error = "Point is even but shouldn't be."; - succ &= succ2; - } /* FUTURE: quadness */ - - if (~succ) { - youfail(); - printf(" %s\n", error); - printf(" %s\n", description); - failprint_tw_ext(ext); - } - - return succ; -} - -static mask_t -fail_if_different_tw ( - const struct tw_extensible_t *a, - const struct tw_extensible_t *b, - const char *faildescr, - const char *adescr, - const char *bdescr -) { - return fail_if_different( - (const struct extensible_t *)a, (const struct extensible_t *)b, - faildescr,adescr,bdescr - ); -} - -static int -add_double_test ( - const struct affine_t *base1, - const struct affine_t *base2 -) { - mask_t succ = MASK_SUCCESS; - struct extensible_t exb; - struct tw_extensible_t text1, text2, texta, textb; - struct tw_extended_t ted1, ted2; - struct tw_pniels_t pn; - - /* Convert to ext */ - convert_affine_to_extensible(&exb, base1); - succ &= validate_ext(&exb,0,"base1"); - twist_and_double(&text1, &exb); - succ &= validate_tw_ext(&text1,2,"iso1"); - convert_affine_to_extensible(&exb, base2); - succ &= validate_ext(&exb,0,"base2"); - twist_and_double(&text2, &exb); - succ &= validate_tw_ext(&text2,2,"iso2"); - - /* a + b == b + a? */ - convert_tw_extensible_to_tw_pniels(&pn, &text1); - copy_tw_extensible(&texta, &text2); - add_tw_pniels_to_tw_extensible(&texta, &pn); - - convert_tw_extensible_to_tw_pniels(&pn, &text2); - copy_tw_extensible(&textb, &text1); - add_tw_pniels_to_tw_extensible(&textb, &pn); - - decaf_448_point_t ted3; - convert_tw_extensible_to_tw_extended(&ted1, &text1); - convert_tw_extensible_to_tw_extended(&ted2, &text2); - decaf_448_point_add(ted3, (struct decaf_448_point_s*)&ted1, (struct decaf_448_point_s*)&ted2); - add_tw_extended(&ted1, &ted2); - convert_tw_extensible_to_tw_extended(&ted2, &textb); - - if (~decaf_eq_tw_extended(&ted1, &ted2) | ~decaf_448_point_eq((struct decaf_448_point_s*)&ted1, ted3)) { - youfail(); - succ = 0; - printf(" Tw extended simple compat:\n"); - field_print(" x1",ted1.x); - field_print(" y1",ted1.y); - field_print(" z1",ted1.z); - field_print(" t1",ted1.t); - field_print(" x2",ted2.x); - field_print(" y2",ted2.y); - field_print(" z2",ted2.z); - field_print(" t2",ted2.t); - struct tw_extended_t *t3 = (struct tw_extended_t *)&ted3; - field_print(" x3",t3->x); - field_print(" y3",t3->y); - field_print(" z3",t3->z); - field_print(" t3",t3->t); - - } - - succ &= fail_if_different_tw(&texta,&textb,"Addition commutativity","a+b","b+a"); - - copy_tw_extensible(&textb, &text2); - add_tw_pniels_to_tw_extensible(&textb, &pn); - copy_tw_extensible(&texta, &text2); - double_tw_extensible(&texta); - - succ &= fail_if_different_tw(&texta,&textb,"Doubling test","2b","b+b"); - - if (~succ) { - printf(" Bases were:\n"); - field_print(" x1", base1->x); - field_print(" y1", base1->y); - field_print(" x2", base2->x); - field_print(" y2", base2->y); - } - - return succ ? 0 : -1; -} - -static int -single_twisting_test ( - const struct affine_t *base -) { - struct extensible_t exb, ext, tmpext; - struct tw_extensible_t text, text2; - mask_t succ = MASK_SUCCESS; - - convert_affine_to_extensible(&exb, base); - succ &= validate_ext(&exb,0,"base"); - - /* check: dual . iso = 4 */ - twist_and_double(&text, &exb); - succ &= validate_tw_ext(&text,2,"iso"); - untwist_and_double(&ext, &text); - succ &= validate_ext(&ext,2,"dual.iso"); - - copy_extensible(&tmpext,&exb); - double_extensible(&tmpext); - succ &= validate_ext(&tmpext,1,"2*base"); - - double_extensible(&tmpext); - succ &= validate_ext(&tmpext,2,"4*base"); - - succ &= fail_if_different(&ext,&tmpext,"Isogeny and dual","Dual . iso","4*base"); - - /* check: twist and serialize */ - test_only_twist(&text, &exb); - succ &= validate_tw_ext(&text,0,"tot"); - mask_t evt = is_even_tw(&text), evb = is_even_pt(&exb); - if (evt != evb) { - youfail(); - printf(" Different evenness from twist base: %d, twist: %d\n", (int)-evt, (int)-evb); - - succ = 0; - } /* FUTURE: quadness */ - - field_a_t sera,serb; - untwist_and_double_and_serialize(sera,&text); - copy_extensible(&tmpext,&exb); - double_extensible(&tmpext); - serialize_extensible(serb,&tmpext); - - /* check that their (doubled; FUTURE?) serializations are equal */ - if (~field_eq(sera,serb)) { - youfail(); - printf(" Different serialization from twist + double ()\n"); - field_print(" t", sera); - field_print(" b", serb); - succ = 0; - } - - untwist_and_double(&ext, &text); - succ &= validate_ext(&tmpext,1,"dual.tot"); - - twist_and_double(&text2, &ext); - succ &= validate_tw_ext(&text2,2,"iso.dual.tot"); - - double_tw_extensible(&text); - succ &= validate_tw_ext(&text,1,"2*tot"); - - double_tw_extensible(&text); - succ &= validate_tw_ext(&text,2,"4*tot"); - - succ &= fail_if_different_tw(&text,&text2,"Dual and isogeny","4*tot","iso.dual.tot"); - - if (~succ) { - printf(" Base was:\n"); - field_print(" x", base->x); - field_print(" y", base->y); - } - - - return succ ? 0 : -1; -} - -int test_decaf_evil (void) { - -#if FIELD_BITS != 448 - printf(" [ UNIMP ] "); - return 0; -#else - -#if WORD_BITS==64 -#define SC_WORD(x) x##ull -#elif WORD_BITS==32 -#define SC_WORD(x) (uint32_t)(x##ull), (x##ull)>>32 -#endif - - word_t evil_scalars[5][448/WORD_BITS] = { - {0}, - {SC_WORD(0x2378c292ab5844f3),SC_WORD(0x216cc2728dc58f55),SC_WORD(0xc44edb49aed63690),SC_WORD(0xffffffff7cca23e9), - SC_WORD(0xffffffffffffffff),SC_WORD(0xffffffffffffffff),SC_WORD(0x3fffffffffffffff)}, /* q */ - {SC_WORD(0xdc873d6d54a7bb0d),SC_WORD(0xde933d8d723a70aa),SC_WORD(0x3bb124b65129c96f), - SC_WORD(0x335dc16),SC_WORD(0x0),SC_WORD(0x0),SC_WORD(0x4000000000000000)}, /* qtwist */ - {SC_WORD(0x46f1852556b089e6),SC_WORD(0x42d984e51b8b1eaa),SC_WORD(0x889db6935dac6d20),SC_WORD(0xfffffffef99447d3), - SC_WORD(0xffffffffffffffff),SC_WORD(0xffffffffffffffff),SC_WORD(0x7fffffffffffffff)}, /* 2q */ - {SC_WORD(0xb90e7adaa94f761a),SC_WORD(0xbd267b1ae474e155),SC_WORD(0x7762496ca25392df),SC_WORD(0x66bb82c), - SC_WORD(0x0),SC_WORD(0x0),SC_WORD(0x8000000000000000)} /* 2*qtwist */ - }; - word_t random_scalar[448/WORD_BITS]; - - unsigned char evil_inputs[3][56]; - memset(evil_inputs[0],0,56); - memset(evil_inputs[1],0,56); - memset(evil_inputs[2],0xff,56); - evil_inputs[1][0] = 1; - evil_inputs[2][0] = evil_inputs[2][28] = 0xFE; - - unsigned char random_input[56]; - - - crandom_state_a_t crand; - crandom_init_from_buffer(crand, "my evil_decaf random initializer"); - - int i,j,fails=0; - int ret = 0; - for (i=0; i<100; i++) { - - crandom_generate(crand, (unsigned char *)random_scalar, sizeof(random_scalar)); - if (i<15) { - memcpy(random_scalar, evil_scalars[i%5], sizeof(random_scalar)); - if (i%3 == 1) random_scalar[0] ++; - if (i%3 == 2) random_scalar[0] --; - } - - for (j=0; j<100; j++) { - crandom_generate(crand, random_input, sizeof(random_input)); - mask_t should = 0, care_should = 0; - if (j<3) { - memcpy(random_input, evil_inputs[j], sizeof(random_input)); - care_should = -1; - should = (j==0) ? -1 : 0; - } else { - random_input[55] &= 0x7F; - } - - field_a_t base, out_m, out_e, out_ed; - mask_t s_base = field_deserialize(base,random_input); - - affine_a_t pt_e; - tw_affine_a_t pt_te; - tw_extended_a_t pt_ed; - // TODO: test don't allow identity - mask_t s_e = decaf_deserialize_affine(pt_e,base,-1); - mask_t s_te = decaf_deserialize_tw_affine(pt_te,base,-1); - mask_t s_ed = decaf_deserialize_tw_extended(pt_ed,base,-1); - mask_t s_m = decaf_montgomery_ladder(out_m, base, random_scalar, 448); - - uint8_t ser_di[56]; - mask_t s_di = decaf_448_direct_scalarmul(ser_di,random_input,(struct decaf_448_scalar_s *)random_scalar,-1,-1); - - tw_extensible_a_t work; - convert_tw_affine_to_tw_extensible(work,pt_te); - scalarmul(work, random_scalar); - decaf_serialize_tw_extensible(out_e, work); - - scalarmul_ed(pt_ed, random_scalar); - decaf_serialize_tw_extended(out_ed, pt_ed); - - uint8_t ser_de[56], ser_ed[56]; - decaf_448_point_t pt_dec, pt_dec2; - memcpy(pt_dec, pt_ed, sizeof(pt_dec)); - decaf_448_point_encode(ser_de, pt_dec); - mask_t succ_dec = decaf_448_point_decode(pt_dec2, ser_de, -1); - field_serialize(ser_ed, out_ed); - - decaf_448_point_t p,q,m; - uint8_t oo_base_ser[56], n_base_ser[56]; - field_a_t oo_base,tmp,tmp2; - field_isr(tmp,base); - field_sqr(tmp2,tmp); // 1/+-s_base - field_sqr(tmp,tmp2); // = 1/s_base^2 - field_mul(oo_base,tmp,base); // = 1/s_base - field_serialize(oo_base_ser,oo_base); - field_neg(tmp,base); - field_serialize(n_base_ser,tmp); // = -base - decaf_448_point_from_hash_nonuniform (p,random_input); - decaf_448_point_from_hash_nonuniform (q,oo_base_ser); - decaf_448_point_from_hash_nonuniform (m,n_base_ser); - mask_t succ_nur = decaf_448_point_valid(p); - succ_nur &= decaf_448_point_valid(q); - succ_nur &= decaf_448_point_valid(m); - - mask_t eq_neg, eq_pos; - eq_neg = decaf_448_point_eq(m,p); - decaf_448_point_add(m,p,q); - eq_pos = decaf_448_point_eq(m,decaf_448_point_identity); - - if ((care_should && should != s_m) - || ~s_base || s_e != s_te || s_m != s_te || s_ed != s_te || s_di != s_te - || (s_te && ~field_eq(out_e,out_m)) - || (s_ed && ~field_eq(out_e,out_ed)) - || memcmp(ser_de, ser_ed, 56) - || (s_te && memcmp(ser_di, ser_ed, 56)) - || (s_e & ~succ_dec) - || (s_e & ~decaf_448_point_eq(pt_dec, pt_dec2) - || (s_e & ~decaf_448_point_valid(pt_dec)) - || (succ_dec & ~decaf_448_point_valid(pt_dec2)) - || ~succ_nur - || ~eq_neg - || ~eq_pos) - ) { - youfail(); - field_print(" base", base); - scalar_print(" scal", random_scalar, (448+WORD_BITS-1)/WORD_BITS); - field_print(" oute", out_e); - field_print(" outE", out_ed); - field_print(" outm", out_m); - printf(" succ: m=%d, e=%d, t=%d, di=%d, b=%d, T=%d, D=%d, nur=%d, e+=%d, e-=%d, should=%d[%d]\n", - -(int)s_m,-(int)s_e,-(int)s_te,-(int)s_di,-(int)s_base,-(int)s_ed,-(int)succ_dec, - -(int)succ_nur, -(int)eq_neg, -(int)eq_pos, - -(int)should,-(int)care_should - ); - ret = -1; - fails++; - } - } - } - if (fails) { - printf(" Failed %d trials\n", fails); - } - return ret; -#endif -} - -int test_decaf (void) { - struct affine_t base; - struct tw_affine_t tw_base; - field_a_t serf; - - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, "my test_decaf random initializer"); - - int i, hits = 0, fails = 0; - - if (~decaf_448_point_valid(decaf_448_point_base)) { - youfail(); - printf(" Decaf base point invalid\n"); - fails++; - } - - if (~decaf_448_point_valid(decaf_448_point_identity)) { - youfail(); - printf(" Decaf identity point invalid\n"); - fails++; - } - - - for (i=0; i<1000; i++) { - uint8_t ser[FIELD_BYTES]; - - int j; - - mask_t succ = 0; - for (j=0; j<128 && !succ; j++) { - crandom_generate(&crand, ser, sizeof(ser)); - ser[FIELD_BYTES-1] &= (1<<((FIELD_BITS-1)%8)) - 1; - - succ = field_deserialize(serf, ser); - if (!succ) { - youfail(); - printf(" Unlikely: fail at field_deserialize\n"); - return -1; - } - - succ &= decaf_deserialize_affine(&base, serf, 0); - } - if (!succ) { - youfail(); - printf("Unlikely: fail 128 desers\n"); - return -1; - } - - hits++; - field_a_t serf2; - struct extensible_t ext; - convert_affine_to_extensible(&ext, &base); - decaf_serialize_extensible(serf2, &ext); - - if (~validate_affine(&base)) { - youfail(); - printf("Invalid decaf deser:\n"); - field_print(" s", serf); - field_print(" x", base.x); - field_print(" y", base.y); - fails ++; - } else if (~field_eq(serf, serf2)) { - youfail(); - printf("Fail round-trip through decaf ser:\n"); - field_print(" s", serf); - field_print(" x", base.x); - field_print(" y", base.y); - printf(" deser is %s\n", validate_affine(&base) ? "valid" : "invalid"); - field_print(" S", serf2); - fails ++; - } else if (~is_even_pt(&ext)) { - youfail(); - printf("Decaf deser isn't even:\n"); - field_print(" s", serf); - field_print(" x", base.x); - field_print(" y", base.y); - fails ++; - } - - succ = decaf_deserialize_tw_affine(&tw_base, serf, 0); - struct tw_extensible_t tw_ext, tw_ext2; - convert_tw_affine_to_tw_extensible(&tw_ext, &tw_base); - decaf_serialize_tw_extensible(serf2, &tw_ext); - - twist_even(&tw_ext2, &ext); - - if (~succ | ~validate_tw_extensible(&tw_ext)) { - youfail(); - printf("Invalid decaf tw deser:\n"); - field_print(" s", serf); - field_print(" x", tw_base.x); - field_print(" y", tw_base.y); - fails ++; - } else if (~field_eq(serf, serf2)) { - youfail(); - printf("Fail round-trip through decaf ser:\n"); - field_print(" s", serf); - field_print(" x", tw_base.x); - field_print(" y", tw_base.y); - printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid"); - field_print(" S", serf2); - fails ++; - } else if (~is_even_tw(&tw_ext)) { - youfail(); - printf("Decaf tw deser isn't even:\n"); - field_print(" s", serf); - field_print(" x", tw_base.x); - field_print(" y", tw_base.y); - fails ++; - } else if (~decaf_eq_tw_extensible(&tw_ext,&tw_ext2)) { - youfail(); - printf("Decaf tw doesn't equal ext:\n"); - field_print(" s", serf); - field_print(" x1", base.x); - field_print(" y1", base.y); - field_print(" x2", tw_base.x); - field_print(" y2", tw_base.y); - field_print(" X2", tw_ext2.x); - field_print(" Y2", tw_ext2.y); - fails ++; - } - - tw_extended_a_t ed; - succ = decaf_deserialize_tw_extended(ed, serf, 0); - decaf_serialize_tw_extended(serf2, ed); - - if (~succ) { - youfail(); - printf("Invalid decaf ed deser:\n"); - field_print(" s", serf); - fails ++; - } else if (~field_eq(serf, serf2)) { - youfail(); - printf("Fail round-trip through decaf ser:\n"); - field_print(" s", serf); - field_print(" x", ed->x); - field_print(" y", ed->y); - field_print(" z", ed->z); - field_print(" t", ed->t); - printf(" tw deser is %s\n", validate_tw_extensible(&tw_ext) ? "valid" : "invalid"); - field_print(" S", serf2); - fails ++; - } - - word_t scalar = 1; - mask_t res = decaf_montgomery_ladder(serf2,serf,&scalar,1+(i%31)); - if (~res | ~field_eq(serf2,serf)) { - youfail(); - printf("Decaf Montgomery ladder i=%d res=%d\n", 1+(i%31), (int)res); - field_print(" s", serf); - field_print(" o", serf2); - printf("\n"); - } - } - if (hits < 1000) { - youfail(); - printf(" Fail: only %d successes in decaf_deser\n", hits); - return -1; - } else if (fails) { - printf(" %d fails\n", fails); - return -1; - } else { - return 0; - } -} - -int test_pointops (void) { - struct affine_t base, pbase; - field_a_t serf; - - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, "test_pointops random initializer"); - - struct extensible_t ext_base; - if (!validate_affine(goldilocks_base_point)) { - youfail(); - printf(" Base point isn't on the curve.\n"); - return -1; - } - convert_affine_to_extensible(&ext_base, goldilocks_base_point); - if (!validate_ext(&ext_base, 2, "base")) return -1; - - int i, ret; - for (i=0; i<1000; i++) { - uint8_t ser[FIELD_BYTES]; - crandom_generate(&crand, ser, sizeof(ser)); - - - #if (FIELD_BITS % 8) - ser[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1; - #endif - - /* TODO: we need a field generate, which can return random or pathological. */ - mask_t succ = field_deserialize(serf, ser); - if (!succ) { - youfail(); - printf(" Unlikely: fail at field_deserialize\n"); - return -1; - } - - if (i) { - copy_affine(&pbase, &base); - } - elligator_2s_inject(&base, serf); - - if (i) { - ret = add_double_test(&base, &pbase); - if (ret) return ret; - } - - ret = single_twisting_test(&base); - if (ret) return ret; - } - - return 0; -} diff --git a/test/test_scalarmul.c b/test/test_scalarmul.c deleted file mode 100644 index 9e5070f..0000000 --- a/test/test_scalarmul.c +++ /dev/null @@ -1,480 +0,0 @@ -#include "test.h" - -#include - -#include "scalarmul.h" -#include "decaf.h" -#include "ec_point.h" -#include "field.h" -#include "crandom.h" - -#define STRIDE 7 - -/* 0 = succeed, 1 = inval, -1 = fail */ -static int -single_scalarmul_compatibility_test ( - const field_a_t base, - const word_t *scalar, - int nbits -) { - struct tw_extensible_t text, work; - field_a_t mont, ct, vl, vt, sced, decaf_s, decaf_m, decaf_te; - - int ret = 0, i; - mask_t succ, succm; - - succ = deserialize_and_twist_approx(&text, base); - - succm = montgomery_ladder(mont,base,scalar,nbits,1); - - if (succ != succm) { - youfail(); - printf(" Deserialize_and_twist_approx succ=%d, montgomery_ladder succ=%d\n", - (int)-succ, (int)-succm); - printf(" nbits = %d\n", nbits); - field_print(" base", base); - scalar_print(" scal", scalar, (nbits+WORD_BITS-1)/WORD_BITS); - return -1; - } - - if (!succ) { - return 1; - } - -#if FIELD_BITS == 448 - struct { int n,t,s; } params[] = {{5,5,18},{3,5,30},{4,4,28},{1,2,224}}; -#elif FIELD_BITS == 480 - struct { int n,t,s; } params[] = {{5,6,16},{6,5,16},{4,5,24},{4,4,30},{1,2,240}}; -#elif FIELD_BITS == 521 - struct { int n,t,s; } params[] = {{5,8,13},{4,5,26},{1,2,(SCALAR_BITS+1)/2}}; -#else - struct { int n,t,s; } params[] = {{5,5,(SCALAR_BITS+24)/25},{1,2,(SCALAR_BITS+1)/2}}; -#endif - const int nparams = sizeof(params)/sizeof(params[0]); - struct fixed_base_table_t fbt; - const int nsizes = 6; - field_a_t fbout[nparams], wout[nsizes]; - memset(&fbt, 0, sizeof(fbt)); - memset(&fbout, 0, sizeof(fbout)); - memset(&wout, 0, sizeof(wout)); - - /* compute using combs */ - for (i=0; ix); - field_copy(work.y, ed->y); - field_copy(work.z, ed->z); - field_copy(work.t, ed->t); - field_set_ui(work.u, 1); - untwist_and_double_and_serialize(sced, &work); - - uint8_t ser1[DECAF_448_SER_BYTES], ser2[DECAF_448_SER_BYTES], - ser3[DECAF_448_SER_BYTES]; - decaf_448_point_encode(ser1, (struct decaf_448_point_s *)ed); - decaf_448_point_encode(ser2, ed2); - decaf_448_point_encode(ser3, ed3); - consistent &= decaf_448_direct_scalarmul(ser4, ser4, (struct decaf_448_scalar_s *)scalar, -1, -1); - - /* check consistency mont vs window */ - consistent &= field_eq(mont, ct); - consistent &= field_eq(mont, vl); - consistent &= field_eq(mont, vt); - consistent &= field_eq(mont, sced); - consistent &= memcmp(ser1,ser2,sizeof(ser1)) ? 0 : -1; - consistent &= memcmp(ser1,ser3,sizeof(ser1)) ? 0 : -1; - consistent &= memcmp(ser1,ser4,sizeof(ser1)) ? 0 : -1; - } - - /* check consistency mont vs combs */ - for (i=0; i= FIELD_BYTES) { - scalar[FIELD_BYTES-1] &= (1<<(FIELD_BITS%8)) - 1; - } -#endif -} - -int test_scalarmul_commutativity (void) { - int i,j,k,got; - - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, "scalarmul_commutativity_test RNG"); - - for (i=0; i<=FIELD_BITS; i+=STRIDE) { - for (j=0; j<=FIELD_BITS; j+=STRIDE) { - got = 0; - - for (k=0; k<128 && !got; k++) { - uint8_t ser[FIELD_BYTES]; - word_t scalar1[SCALAR_WORDS], scalar2[SCALAR_WORDS]; - crandom_generate_f(&crand, ser, sizeof(ser)); - crandom_generate(&crand, (uint8_t *)scalar1, sizeof(scalar1)); - crandom_generate(&crand, (uint8_t *)scalar2, sizeof(scalar2)); - - field_t base; - mask_t succ = field_deserialize(&base, ser); - if (!succ) continue; - - int ret = single_scalarmul_commutativity_test (&base, scalar1, i, i%3, scalar2, j, j%3); - got = !ret; - if (ret == -1) return -1; - } - - if (!got) { - youfail(); - printf(" Unlikely: rejected 128 scalars in a row.\n"); - return -1; - } - - } - } - - return 0; -} - -int test_linear_combo (void) { - int i,j,k,got; - - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, "scalarmul_linear_combos_test RNG"); - - for (i=0; i<=FIELD_BITS; i+=STRIDE) { - for (j=0; j<=FIELD_BITS; j+=STRIDE) { - got = 0; - - for (k=0; k<128 && !got; k++) { - uint8_t ser[FIELD_BYTES]; - word_t scalar1[SCALAR_WORDS], scalar2[SCALAR_WORDS]; - crandom_generate(&crand, (uint8_t *)scalar1, sizeof(scalar1)); - crandom_generate(&crand, (uint8_t *)scalar2, sizeof(scalar2)); - - field_t base1; - crandom_generate_f(&crand, ser, sizeof(ser)); - mask_t succ = field_deserialize(&base1, ser); - if (!succ) continue; - - field_t base2; - crandom_generate(&crand, ser, sizeof(ser)); - succ = field_deserialize(&base2, ser); - if (!succ) continue; - - int ret = single_linear_combo_test (&base1, scalar1, i, &base2, scalar2, j); - got = !ret; - if (ret == -1) return -1; - } - - if (!got) { - youfail(); - printf(" Unlikely: rejected 128 scalars in a row.\n"); - return -1; - } - - } - } - - return 0; -} - -int test_scalarmul_compatibility (void) { - int i,j,k,got; - - struct crandom_state_t crand; - crandom_init_from_buffer(&crand, "scalarmul_compatibility_test RNG"); - - for (i=0; i<=FIELD_BITS; i+=STRIDE) { - for (j=0; j<=20; j++) { - got = 0; - - for (k=0; k<128 && !got; k++) { - uint8_t ser[FIELD_BYTES]; - word_t scalar[SCALAR_WORDS]; - crandom_generate_f(&crand, ser, sizeof(ser)); - crandom_generate(&crand, (uint8_t *)scalar, sizeof(scalar)); - - field_t base; - mask_t succ = field_deserialize(&base, ser); - if (!succ) continue; - - int ret = single_scalarmul_compatibility_test (&base, scalar, i); - got = !ret; - if (ret == -1) return -1; - } - - if (!got) { - youfail(); - printf(" Unlikely: rejected 128 scalars in a row.\n"); - return -1; - } - - } - } - - return 0; -} diff --git a/test/test_sha512.c b/test/test_sha512.c deleted file mode 100644 index 815bb5f..0000000 --- a/test/test_sha512.c +++ /dev/null @@ -1,270 +0,0 @@ -#include "test.h" - -#include -#include - -#include "sha512.h" - - - -static int sha512_monte_carlo_core ( - const char *seed, - const char *checks[100] -) { - sha512_ctx_a_t sha; - sha512_init(sha); - - unsigned char md0[64],md1[64],md2[64]; - - int ret = hexdecode(md0,seed,64); - if (ret) { - youfail(); - printf(" SHA-512 NIST Monte Carlo validation seed hex decode failure.\n"); - return -1; - } - - int i,j; - - memcpy(md1,md0,sizeof(md1)); - memcpy(md2,md0,sizeof(md1)); - - for (j=0; j<100; j++) { - - for (i=3; i<1003; i++) { - sha512_update(sha,md0,sizeof(md0)); - sha512_update(sha,md1,sizeof(md1)); - sha512_update(sha,md2,sizeof(md2)); - memcpy(md0,md1,sizeof(md1)); - memcpy(md1,md2,sizeof(md1)); - sha512_final(sha,md2); - } - - ret = hexdecode(md0,checks[j],64); - if (ret) { - youfail(); - printf(" SHA-512 NIST Monte Carlo validation hex decode failure at iteration %d\n", j); - return -1; - } else if (memcmp(md0,md2,sizeof(md2))) { - youfail(); - printf(" SHA-512 NIST Monte Carlo validation failure at iteration %d\n", j); - hexprint(" Expected", md0, 64); - hexprint(" But got ", md2, 64); - return j+1; - } - - memcpy(md0,md2,sizeof(md1)); - memcpy(md1,md2,sizeof(md1)); - } - - return 0; -} - -int test_sha512_monte_carlo(void) { - const char *seed = - "5c337de5caf35d18ed90b5cddfce001ca1b8ee8602f367e7c24ccca6f893802f" - "b1aca7a3dae32dcd60800a59959bc540d63237876b799229ae71a2526fbc52cd"; - const char *checks[100] = { - "ada69add0071b794463c8806a177326735fa624b68ab7bcab2388b9276c036e4" - "eaaff87333e83c81c0bca0359d4aeebcbcfd314c0630e0c2af68c1fb19cc470e", - "ef219b37c24ae507a2b2b26d1add51b31fb5327eb8c3b19b882fe38049433dbe" - "ccd63b3d5b99ba2398920bcefb8aca98cd28a1ee5d2aaf139ce58a15d71b06b4", - "c3d5087a62db0e5c6f5755c417f69037308cbce0e54519ea5be8171496cc6d18" - "023ba15768153cfd74c7e7dc103227e9eed4b0f82233362b2a7b1a2cbcda9daf", - "bb3a58f71148116e377505461d65d6c89906481fedfbcfe481b7aa8ceb977d25" - "2b3fe21bfff6e7fbf7575ceecf5936bd635e1cf52698c36ef6908ddbd5b6ae05", - "b68f0cd2d63566b3934a50666dec6d62ca1db98e49d7733084c1f86d91a8a08c" - "756fa7ece815e20930dd7cb66351bad8c087c2f94e8757cb98e7f4b86b21a8a8", - "937d7856a82a84c163c79417d0540c47daaf9ffe662c843737dbbcbe5f865bf6" - "f47a9d2bd10129a4f498073094653c324a2519a1c71ac1279b1623ff7d24647a", - "f8fbc058c2b9f84131c9decfa543a35ade41581f670398efd61b3abfced9c1cf" - "cb5324f2370487f9c59a65bc668ea596c8d22ce8a33014dfad28357fa7d05f04", - "4ab0c9484ff5c30fa64ae6e81510c5fea566eafb88f175f8bc19109f40fe8001" - "4c8b77fff10b8750778429bf3c5497e4cb92d9b30014f4cb975dff2a45244c28", - "685179397554d276513d630234a03419808c698abf2600d7490aabb8e455c6ab" - "6ea412c7729dc140a79dff66533c6946cbe90f9da9ed16e2e629db1651bea870", - "335e6e941ab7dadfecdb74ea6cb4e8584b6e3408841a33a6cf7fd6a63294b193" - "0a60983240311672acac3840a90e64cc366ce75081b2252627e9c31197ebad03", - "e3217f6af6e279e9445dc3738cbf9ba0e9edba0455844a73648139777afdea2c" - "4d8032e214f541bf92675fb23f24df8e4fe98e0003aadfb6d8f9cc2cd799bbf7", - "ee2fdfb3ae630613b7d890977cf2515deac272a37f27e4a01961ecf103d4ff5b" - "45cc8aef53b635dd75aa51aabf71c0642555ccd3281e0388f8ca09d83258cf30", - "6a30d97cc98af6a25b673dce7aeab8d762bf2e55ea0c6dc899179281f84dd02a" - "2896f77e9c106b472f55f7adbef7b1157be567ee1236ebdac2a3c5d8cb133eb5", - "ac1176abdc5f71170183d92ae55856221b0d95590af11d9d72ba605ec026bbec" - "52d6974bc43a1efb125ff2b161fbdc616fda00f04193a0bc26aacdfa052a5741", - "59fa909480620ecc08d34531a6da1b55158b74fc93ddf68e1d242615b6f3843a" - "7952e63e798c6445cde1b07e0be09d0d711cb7b42a0e7760a593b08acfceb63d", - "9eb253319efa61b864f27bd334d7dd78b38d3265fb544e0c8edee950a547e1d8" - "db921a285774ab94d66beae933298d20f2a5aa87c62fe1e383cc3b18e7af18ac", - "81735324005671f7bdad9e685ee8257f5e0622b9fcb5d38dbdfb2df27258c3e1" - "d46d76e24c0c92c744e1b50a2b4b0d31525b3af83cc80a75722d921bdeef59c4", - "17498cdff4323bb8021e44eca6559e05d8ff9a0ef2ee9d4ba0ac6e73f83972a0" - "dfbb6d47728fa70311d7c82e154966e1b7678263b0f65133e9116969193d429b", - "228c4574d7c45eb9ba9240722133fce74abe00c7328ab30b4bde373dc79afdd6" - "e0569d36268cd5eaa2f27205fc00512577bcbb6699e1d66ed85eafaba7548afb", - "3d40ccd9cc445bbecca9227c67fe455d89e0b7c1c858d32f30e2b544ca9a5a60" - "6535aea2e59fec6ec4d1ba898cc4338c6eadef9c0884bcf56aca2f481a2d7d3e", - "e1e577aeac92e3a2b7f8a262bf2ac9c037d2274ca6618fbe4cc21db7c699e994" - "6b6671ae45ea433a1e392a5bc9eec96fd641ba8f4a047f022a04a337227004df", - "5e4424c0bcb2f0f7a2428821a9d5840a82401f4440ae6bed25c53cd9e71cf9d3" - "9904d6a375bd721f4332ab0202529c91feb9c094c3e6d34ca4f66649ee6fa212", - "56b199d63ca37189d5ca0d40006ac7bcb9f39cbdc00ef7b8a5697caa7d81d05b" - "645a146995b1151d01958f1589337e14afc6e7dd10a815170e527a398e6ce8c3", - "d2d498ff93fb03013a64f295b5bc68e57d2fb5600da578aa011d43ff432eae3e" - "0c800f9e2a53155e56fdbf5e068fe2b4beb3e42b2585531b8b16c4d8ca3356c6", - "3d3875489903710f17cf4247b5842ace6f017b1a3b99e9ee5fbc04fc7898e78b" - "12693879878028ca40c63cd0f6925fb7d0ca0412e4f06619e3ace223690f03b8", - "a013e21cd1234483c95c2ea2757be949bc79401ba39b09c316a1612d594642be" - "65ca106e12695ac3808c57c6f2980e895fd1fe188946562afc238414e1e43649", - "c5f6367d7195489e16242f912fbe0d8002e947de3a7e9c53f77b1e5e90e05bd7" - "ca395e787e34cb5f500c02da59c9d83de35601de7ae80dae74a0d6b4a292d43b", - "7c28c44c6aaba83c122f24d68273e28a5afd65b4071d02b7ea3300478d511897" - "1e1356ae57cbc70d2a177ea464a1c2c50d4297b933e789c63b1481797ae8f08c", - "af7cb42b1c70a85ac1ae1c2991b25b657c19f4fcf83af7f7dc0ae1028c1452a6" - "a17dc98929634fe6ed3855b70b96bc2caa93d82037b94ebeddc77e4c1a7cc563", - "bd56ad4c0cbd162706053da929d667253aadcf417affb483fff4f2699bf406d1" - "28cfdf5196dfbb05bb89ccbf04c5147bd2ebb3156b0bc1768ca6faa171c91c01", - "004d7b0fff9bcddf4b3913ae190a76728705a3d23874d92a8b7ff246c8fcad46" - "623cb04723c8aded0cba4968d1a8cc1375b99005786c1bcb7ae4bf13325c3ae0", - "8299a5bf5ed64f525c4eebbeca969fc1b91a81adb58c584bdd2d7676386a31fa" - "546643a3cf505007584f02fb712d708cab645bf078a1b9339f5a76aee985d017", - "ce7100f3455db1a9776a9f40d562ea998afca1f9fee7e0d81c8db34cf68ad23a" - "8bfa6fc04774703e1e56d5196b66966158fcf2a8335a58c6ba7ba1af756ba1dc", - "90aaabcb655ee921b8350229efe6064a60051cf0cac858fa3d43afd5b97cc823" - "01bd1b8cc1f874022e5af948185638783a13ca1bbd5049ace7fbf4f6d90c201f", - "3cf0a25b33ded3e0806dfe603b9987f1d6f2b3fdcb1ec7f8566828c00e17e8f5" - "9e38b3bca302396c7525ca194e6cc8501369059e2e34ae21e3141215876847c4", - "bdc5266aee339a1ff13fcf5229773cd3d14b47101e83076927c160bb71bf7445" - "590525a2012d52af008e118e16df1b6bfcaf8f22b4e45f9e749f3c20625a2bc8", - "ef8d2ba885381ab97756d59dbbbf53a1ea35d152b2d8f82c3518430aa34e7083" - "59194ea43950d032e151f576d343a5c3cfe6b71d4ed0ead9d3a107402589bad0", - "194ea5324c4179998dd7057755f255fdea04dadf533f7851e3e9718b610948e3" - "2fd28323077d9421142ac808978adfa325b668c8599a2e01c757a5a14ed2dd37", - "106984d2f0087e621dae760552bc6279072267883c204079481af6034354f1a2" - "b77c17e6c039a1063e479342aa3ccd90330dd3fb5a7d5e976619497e2d3326cd", - "a1347216f1a6db47b90c4ded3c5c75440f54c22c87d538314d1340f86f88acba" - "01378acb933ddad0adc6b75d55bfb7e8efc9c4a531b2a410610b7515b6dac66a", - "b76e4db147e0eaa4f04880654088b9d0fce518c8c377d92c846345604dc6b2b1" - "8d377fdb8e30f06d9bcfe6d7dacc07d6adff73d98d49f8f132b80f3084390830", - "acd4e527763dfd4513f0def0b1edf8ea12dc78d336b7b796f3dcc32e10687254" - "43a2f55ab4f666b27d6bf2ab39669c98293f0a9108051fd3144d31a1ed171ddd", - "10128c15494bc87a87374f676ef9fe2df20b36ffcca41a80bd40b216637b3de7" - "10efd070e277827820a7bba3cceb7b21f8fe7f9775d6c4df4d3da5349434ec49", - "2632dd5c188c6ed3a4610405fdda704add752f5424d9de65a51400fe478e26cd" - "0412e5f91ca4b744c34f4954f40a3a4254431d21954623208b527b7b4daa687e", - "45707f5b6fc5ccd1f78d77f177d10fb8b462c74cc821518cd5cfa4b5d6b40b41" - "8044900693c37abbb82367d340fec67f800d74072935da1706b4d90ae26099c7", - "56c37f31220b5b3040373d91b2c5e42fe9e601a12f7f8dc4534459bf28e484b8" - "713db243c5782c031e674003a3c14c42fd152e7188789065e82795e10f87d54b", - "5da94c899d48bd8299fee3d81662f8d6c5f8f8bc54d18cb0368b13cebaee7ad7" - "1e74ea80f34974ad166f04f9a0602809166fe4085a475a8ca86cade12b6754c4", - "0664363f97ba910760b0922e31ca880ca97469506cb007e3108c36c3ce3ce180" - "1fb4197609479339e8820632b6a38bffffee05a9adc11cc544b9aa6f5b95cc6f", - "732c41a1edaa727c04f627ff158aaff67c18efd667216132b99ab84d108996a1" - "0bb008b5d803b22ed1aa78bb0d10f8a762fd34777d7dccce8e84827ba88d4193", - "fc9c21d67e393a2b05a23a17d8db630cbaebaa3def211181749f1bcad1815606" - "27fb60ee20fae2e5980cbf50fce0a19dce807e7fb75c4da0ef008bc75d413a65", - "0453b765afc1edffa595efe345177f5805ed3abc1297ceab757ae7161723a614" - "4cb543299f418049276d16b7896662631634fab9549127c10f27505b7dee8665", - "3853f3bf024e0668e8d1ea53733a97537f97d9307c5f3a19864ab4eeb1654710" - "693bb961a344dec8a758f5e64b26fcb6dd423419c4a114fa749211a9de06c281", - "240137f0dd57beb3f7fc283bb3ead423c67883fd46f4e27471d7be57ad469a49" - "bad03a3658418bd55614678f3a463bceff85291314b90ef43ccbcb028f0a7a07", - "f9050a5271edbe4cfdb9520ec05bbdc3cbcb9bce36fd212338d3e7028a39b9ab" - "30793e561d75a2e424193264c7f0775e65599ef0c94e0ad24dbfe18252364267", - "47caa7a5862fad837aaa409a4a9df2575e645528c35159115911b7c4e2f08ae4" - "9d68de97249b31b83ce2c163f649cad4559dc6e6a7191f2922d79a5fd6af167b", - "13f5825c41fa49edf6104e3e35c9c224eba93e37374f730004c39c54e7391e4a" - "847fd61865235a3fe32224c96fbe86f7e14c3d5df496e83ec989a71b4f293a44", - "e5b55e05efe1ca6b9a96a57e3a1523d610d70f837e93b31fa98c2736d3e114d2" - "38d46ec6b6e3d19e774b253f6b0c7a2ebe69b7e60fc0874444806b2a2278df45", - "f14a586ac30f0af255f597a9aef9abba5e99c04d17b01f24427c4ee2c196b52a" - "cb1ceefc9b15cb822b3ecffdc2f7c49e11d3fc0769acee33361537d379c62e0c", - "7e2d3398807195c48e6ec52d20710bbf8b21ea8de4d1abc197897ccc58aeff40" - "259edc67270cdae0edcc686c0d0dccc5760c1495ab1cf48482dc2000ae2d42ad", - "2f3d5c5f990bf615d5e8b396ccbd0337da39fad09b059f955a431db76a9dc720" - "dffc4e02c0be397c7e0463799cd75fd6ab7c52bec66c8df5ef0d47e14a4c5927", - "483a1764d308cc494a2b543d29ba616483aefdf91c7769fd084eedaac1add189" - "1df95d317a47430b2bf73e4081f86597020e28afe2d34a22b77ea62b6112d09a", - "bfa88691ec951511651c6f14af100eeb26d87729e18ac3ef49a80d73ffeaeea5" - "3e97c4a7277a7ee9f2fba070b1c9720d6cdba407dd82267019e3f0f5662b2f2b", - "4c17c8e2e7132dbf82afebc40efc77926d16f4d2c082d846dac28733aa767e28" - "40ebf04f2563df75933466a36e11968d342e4157827605d04d9627ce9b5216c8", - "70bbfc29a2a765220af84e7bb10d759a3152ad4b5643ef6b89966950ec7ef950" - "3d57bc0a28c4ee789a60bf9dcac59139e15241d73b990410cf92eff213da9eca", - "8d1d56f37fc19b84984a6fa33aa9c2dbdbf79a29c04ad0b4cf20333e6bec9434" - "47be2416242f8cd2f9732e79bb925cc5a61a80c5fc9c079961243fd1c1f5900e", - "492fd0171f4dcd5d20ea6c0d34b5576c8894664ae5955e6737f5e3b711c2804d" - "99ccca065b7ec18c82da98b18a3029b765c51ebc7c433b36492e0ed6b8511bb6", - "7f49e8e54db7e5b4323cae2db71f3e8b8eba172dcad3602e9b7b058007a55893" - "58732d5afffa56072a46e89b1ea27ef8d556deb86b569c635d394f15d99d8a15", - "56884a6a9210d5f371e25823efb2511a9c410c26a441e07c1bdffe8605084267" - "d49c315baf6a692d7d97844b2714b4930877a5d7f52cf6fa151700fcb6980546", - "6aaef8284eef221ecb17ea3c9596f075b5155fe7b925d737ed3c6543c761c28c" - "7cd9d9d4b5e2a37b2f183a2a367bbd34b633497bc7a1737d61c8c1f3ef295062", - "38ef178f5688e59d47c375252db7b39f40c0c84169878ee7ba5086e4b25fea81" - "076b9c37847e9e6bf24ae0b343689c265ec5ca7469e619acd61b0276721efb1b", - "e3fe1aabad120777cf24eaae289b486632ca46ceb89afae73dbae5fa87c76787" - "9369355a9cc5c21ca604ed91d0f2f58c466573f3e6d88e52c62c0d3cb188e141", - "82f5bd920457bb2763a0da031a7fed47b236951b1ea420c20fd2b6de1dbfbb9c" - "4600ea7092788493e2d4be6ee24b6dba04e57af3e8f2f14d9837295420ac7631", - "6d0b26208ba9b1615067bb3ff97b292fe67e4c02d240d649c32370e0a4cd22d0" - "3bdf864be4d24a3f5f51aeccfd1afd5191e590edeb5f7bec323b0506c3104b89", - "d081083158054d08371ec84f4d3aa5aa761734ac6091a30330a861fda056f835" - "c750bf4f7981af1693ff28545366bd05cec47bccd77a7d237befb0135c534138", - "6ba8b52780b8a07a2a2015dd8f0c5e7437b8e024c4ee428f7ba91dfea118cb72" - "a939872550983317132b841b7cbc29a22b8f1cfea0c55203cafc69b55ed6244a", - "312692b0a51f002b7f06d05b39d15a5637dbddd2f4f1a73e6c88a4c841cdba5c" - "d8e69c0939ab39bb1a9c54fa35402143c97edb9704a0e9e1a98701710f6a5dad", - "aaee960de201a8dcccff95b834fccf0dafc03fe6cffc0429162bf4aff01165ab" - "07a0c9435e9cb412121b7ba010657ccc3152118602b665072136317d92fd4262", - "21fdff552e08c86c07f080cefacaaaf31846eb893bfe2e4f88c3c3cd8cbf592a" - "84500942695a5e5ae971ab343ce2695dd1baeb1f94dd4b53d678e14265e421ae", - "ca8f1a5b2172f6adb474da53b35e3f73ffd88263d3eecde72e48b16e1a065801" - "5b555ee319005a1d82802e91431ee777610f9b1028d819921e1044ad426b0270", - "ce5ab25eff9c1ddc569a1eaaa66b689109ee269db7066e0b02d39b3564fd14ca" - "6249987b7791e203d3d7c2ebf18558d2f23f94c03dd1d03aa63849e4d2889a76", - "a6f8b0561000dd4ae8b828c5f676e8c1a6474c4a042a645f1815bd52e9ff53c9" - "7dc36d5d8997f8ce332185feead76267f5b2e63f597fb3345ca0046e58fc0f24", - "fec86794bad4106c5ad1c1a2d9a1b7aae480396ec231eb5cac21c4077d17a0b6" - "52da0037363399a5a1dababa4a40e4c54b9124167580dee9108c4dbb24c57512", - "594f5dd3f4c87bdc0d81309386e9163a9718e34c7b0dcb4613f8487aa786f9d2" - "11cfb61bb247fa9f5ecef042e710f192850f5571807294bfd8a54397850e5773", - "d81ad866f25ef6a0a6431d267114da564513e5ebdcf48db7e95db8cf32a89f0a" - "b107874d796035db97420ffcf1db5f04dc1a52ddbbb960fc63b7f3f835cc8be6", - "431d537e098e9949f6a68108d55d20952e3bfcdeb7273bac3917e37790a84fa5" - "db04c33a79c113a06cf333e831d7702a00853a93fd0aa5146d934f4f71242a6a", - "4ed95636c6885ae4e63d042e82f4da830c702dbf3b9746d64770a64dd666b332" - "08315f3a947c4dff790771ef283788a9c74da83e22b97f750286a820ee46698c", - "a9bcb60b4d7724cdddddbc232b4ac70b94d0d7e9f0724b1222d918930cbb9bdb" - "b04b3ad43e3c8caf3bf8b004ee4aec6bd527ff8eb6189b44827f7ba7057f6a90", - "d6d5e44d5bb07fc4144ab6ab309f048968f73f7992beb326047e9e2cd7af6240" - "bc8abf46703c32fdb58fb2a8672594a660ef855be74f24cec09d4fb00219de82", - "dfda9ac0c7147530da97715ccf47814182255f2f2cf40287db97a4c63b43fcd3" - "9e6d41e560921492badb253a7dea0aba863c7c33b912bb59d1ff4de03a4f03bb", - "0395faaaf2e907f27779d6f1cc9c9db68ec390a38fbb0702c6475b46f7a39949" - "8d46fd8014f834b131e1e83abba0359b1f16d8fc0a393580615def2ad0caba73", - "41cb98f09029abe85d24a0f131f116c7f69f54f7e91c250642606512bf3da4ca" - "89ba70a4714a5f66d9ae81ff09317dadaff12a02057074c970f0f02a52bfafd2", - "8e8f161d48e306c5533ed614b8ef3a1979df6db7e13d0780a73c4a3980ddf0a9" - "5f93941d412c93683e39915a660c3fbec0dbb1bb6beea2e2099cd968011535c0", - "789593f0b8fb83ef9b3ec50ab8f6e1e47344f763d4f7ceab5600989e7b6fd5fe" - "f6ee5e487975f64474af6cd71ae4d9ecce8f009edea0227c7ebe73080b8f961b", - "f37e1449e0b313d9537a6177f7a31158d353e5b79c781facf02526ec94e0c6cf" - "da37105bac67098b194ea82efb307c2929a9ab8aca0e76c53e829e3f901cd245", - "2e74e745caaf2d449ab3b031dd214b48616853a512cf2e95c40cb8e7594fe5e4" - "879ac8a26d02eb35b3b96a5c9e7dcae3e15fd050a0bcc1fb3b9cb9c4df0fad3e", - "6eac7069c26082e52574ca6a58abb9b1b9faf452e8cca9f1c7023679ce192ca5" - "54892f30e38104d39088a24df35612444a0fc90084af7535fd9344fa51dded84", - "ada6caf30c4f6e3644d952366e01519af6771b406e2c447552f0c597b8dd10e9" - "e9b4e699c9a835de03f422be8980538d9786172dfd2fe511db272a1543d5aa35", - "4d4b0086b2cb05d713f2805caa7e6605c8f7dbbb2e0f92aa159aebdcd6306030" - "5f47b748f1bca6e0b6e11cf8f9697fcccb6584b878c4b54a699290728a40aa1b", - "97420b8a0ad102aeb92139da2c052d2748dd7d2dbb93a9ea79dc15b520d0ca7c" - "ab8cb7a00f5b5aebcb49d7e7f52a27180935ce617aeecdecba04064c668edd37", - "4aa7dad74eb51d09a6ae7735c4b795b078f51c314f14f42a0d63071e13bdc5fd" - "9f51612e77b36d44567502a3b5eb66c609ec017e51d8df93e58d1a44f3c1e375" - }; - - return sha512_monte_carlo_core(seed, checks); -}