From a8a7dc124c06b5e3d565192c743fd1d61dbfbe57 Mon Sep 17 00:00:00 2001 From: Zane Beckwith Date: Tue, 19 Sep 2017 16:31:27 -0500 Subject: [PATCH 1/3] Add a wrapper for AMCL's csprng, and always seed it. --- CMakeLists.txt | 15 +++- README.md | 29 +++---- include/ecdaa.h | 1 + include/ecdaa/credential_BN254.h | 4 +- include/ecdaa/issuer_keypair_BN254.h | 5 +- include/ecdaa/member_keypair_BN254.h | 4 +- include/ecdaa/prng.h | 111 ++++++++++++++++++++++++ include/ecdaa/signature_BN254.h | 3 +- src/credential_BN254.c | 7 +- src/internal/schnorr.c | 20 +++-- src/internal/schnorr.h | 11 +-- src/issuer_keypair_BN254.c | 10 ++- src/member_keypair_BN254.c | 8 +- src/prng.c | 112 ++++++++++++++++++++++++ src/signature_BN254.c | 7 +- test/CMakeLists.txt | 1 + test/benchmarks.c | 32 +++---- test/big_256_56-tests.c | 10 ++- test/credential-tests.c | 19 ++-- test/ecdaa-test-utils.c | 45 ---------- test/ecdaa-test-utils.h | 9 -- test/issuer_keypair-tests.c | 13 ++- test/member_keypair-tests.c | 23 ++--- test/prng-tests.c | 81 +++++++++++++++++ test/schnorr-tests.c | 125 ++++++++++++++------------- test/sign-and-verify-tests.c | 21 ++--- 26 files changed, 502 insertions(+), 224 deletions(-) create mode 100644 include/ecdaa/prng.h create mode 100644 src/prng.c delete mode 100644 test/ecdaa-test-utils.c create mode 100644 test/prng-tests.c diff --git a/CMakeLists.txt b/CMakeLists.txt index 83563c8..98d3a43 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -17,6 +17,10 @@ cmake_minimum_required(VERSION 3.0 FATAL_ERROR) list(APPEND CMAKE_MODULE_PATH CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}/cmake) find_package(AMCL REQUIRED QUIET) +option(DISABLE_LIBSODIUM_RNG_SEED_FUNCTION + "Disable the default Libsodium-based seed function" + OFF) + project(ecdaa LANGUAGES C VERSION "0.1.1") @@ -38,6 +42,12 @@ find_program(MEMORYCHECK_COMMAND NAMES valgrind) set(MEMORYCHECK_COMMAND_OPTIONS "--error-exitcode=5 --leak-check=full -v --track-origins=yes --partial-loads-ok=no") +if(NOT DISABLE_LIBSODIUM_RNG_SEED_FUNCTION) + SET(ECDAA_SEED_LINK_LIBRARY sodium) +else(NOT DISABLE_LIBSODIUM_RNG_SEED_FUNCTION) + SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DDISABLE_LIBSODIUM_RNG_SEED_FUNCTION") +endif(NOT DISABLE_LIBSODIUM_RNG_SEED_FUNCTION) + set(ECDAA_SRC_DIR src) set(ECDAA_INTERNAL_SRC_DIR ${ECDAA_SRC_DIR}/internal/) set(ECDAA_AMCL_EXTENSIONS_SRC_DIR ${ECDAA_SRC_DIR}/amcl-extensions/) @@ -47,6 +57,7 @@ set(ECDAA_SRCS ${ECDAA_SRC_DIR}/group_public_key_BN254.c ${ECDAA_SRC_DIR}/issuer_keypair_BN254.c ${ECDAA_SRC_DIR}/member_keypair_BN254.c + ${ECDAA_SRC_DIR}/prng.c ${ECDAA_SRC_DIR}/signature_BN254.c ${ECDAA_INTERNAL_SRC_DIR}/explicit_bzero.c ${ECDAA_INTERNAL_SRC_DIR}/schnorr.c @@ -54,7 +65,6 @@ set(ECDAA_SRCS ${ECDAA_AMCL_EXTENSIONS_SRC_DIR}/ecp_BN254.c ${ECDAA_AMCL_EXTENSIONS_SRC_DIR}/ecp2_BN254.c ${ECDAA_AMCL_EXTENSIONS_SRC_DIR}/pairing_BN254.c - ${ECDAA_TEST_DIR}/ecdaa-test-utils.c ) add_library(ecdaa ${ECDAA_SRCS}) @@ -66,7 +76,8 @@ target_include_directories(ecdaa PUBLIC ${AMCL_INCLUDE_DIRS}) target_link_libraries(ecdaa - PUBLIC ${AMCL_LIBRARIES}) + PRIVATE ${AMCL_LIBRARIES} + ${ECDAA_SEED_LINK_LIBRARY}) enable_testing() add_subdirectory(${ECDAA_TEST_DIR}) diff --git a/README.md b/README.md index 3113d70..8f2753d 100644 --- a/README.md +++ b/README.md @@ -39,23 +39,18 @@ ctest -V Many of the functions provided by this library (particularly, those used by an Issuer or a Member) require a pointer to a pseudo-random number generator (type `csprng`). The security of these algorithms depends critically on the proper seeding of this prng. - -Before using these functions, create and seed the `csprng`: - -```c -#include -#include -csprng rng; -char seed[SEED_LEN]; -/* Get cryptographically-secure random bytes of length SEED_LEN into seed */ -octet seed_as_octet = {.len=SEED_LEN, .max=SEED_LEN, .val=seed}; -CREATE_CSPRNG(rng, &seed_as_octet); -``` - -The random seed `seed` MUST be generated in a cryptographically-secure manner, -and should be at least 128 bytes long. -Depending on the platform, this seed can be generated, for example, via calls to -`/dev/urandom` (or `getrandom()`), or a hardware random number generator. +This means that the first use of any `ecdaa_prng` MUST be preceeded by a call to +`ecdaa_prng_init` on the prng. + +The seed for the `ecdaa_prng` is generated using code adapted from Libsodium's +`randombytes_buf`. +A discussion on how this function works and any caveats can be found at Libsodium's webpage. +Specifically, the procedure for using a non-standard random number generator +(e.g. in environments where `/dev/urandom` isn't available but a hardware rng is) +may be useful. + +When an `ecdaa_prng` is no longer needed, `ecdaa_prng_free` should be called on it +to securely erase its sensitive memory. ## Naming Convention in API diff --git a/include/ecdaa.h b/include/ecdaa.h index e89bfe0..d59f6c2 100644 --- a/include/ecdaa.h +++ b/include/ecdaa.h @@ -24,6 +24,7 @@ #include "ecdaa/group_public_key_BN254.h" #include "ecdaa/issuer_keypair_BN254.h" #include "ecdaa/member_keypair_BN254.h" +#include "ecdaa/prng.h" #include "ecdaa/revocation_list_BN254.h" #include "ecdaa/signature_BN254.h" diff --git a/include/ecdaa/credential_BN254.h b/include/ecdaa/credential_BN254.h index 2c46c1d..4257ab7 100644 --- a/include/ecdaa/credential_BN254.h +++ b/include/ecdaa/credential_BN254.h @@ -27,10 +27,10 @@ extern "C" { struct ecdaa_member_public_key_BN254; struct ecdaa_issuer_secret_key_BN254; struct ecdaa_group_public_key_BN254; +struct ecdaa_prng; #include #include -#include #include @@ -68,7 +68,7 @@ int ecdaa_credential_BN254_generate(struct ecdaa_credential_BN254 *cred_out, struct ecdaa_credential_BN254_signature *cred_sig_out, struct ecdaa_issuer_secret_key_BN254 *isk, struct ecdaa_member_public_key_BN254 *member_pk, - csprng *rng); + struct ecdaa_prng *prng); /* * Validate a credential and its signature. diff --git a/include/ecdaa/issuer_keypair_BN254.h b/include/ecdaa/issuer_keypair_BN254.h index c9b9737..0c77f12 100644 --- a/include/ecdaa/issuer_keypair_BN254.h +++ b/include/ecdaa/issuer_keypair_BN254.h @@ -27,7 +27,8 @@ extern "C" { #include #include -#include + +struct ecdaa_prng; /* * Issuer's public key. @@ -62,7 +63,7 @@ size_t ecdaa_issuer_secret_key_BN254_length(void); */ int ecdaa_issuer_key_pair_BN254_generate(struct ecdaa_issuer_public_key_BN254 *pk_out, struct ecdaa_issuer_secret_key_BN254 *sk_out, - csprng *rng); + struct ecdaa_prng *prng); /* * Check the signature on an `ecdaa_issuer_public_key_BN254`. diff --git a/include/ecdaa/member_keypair_BN254.h b/include/ecdaa/member_keypair_BN254.h index 8d250b0..04a9832 100644 --- a/include/ecdaa/member_keypair_BN254.h +++ b/include/ecdaa/member_keypair_BN254.h @@ -24,6 +24,8 @@ extern "C" { #endif +struct ecdaa_prng; + #include #include @@ -62,7 +64,7 @@ int ecdaa_member_key_pair_BN254_generate(struct ecdaa_member_public_key_BN254 *p struct ecdaa_member_secret_key_BN254 *sk_out, uint8_t *nonce, uint32_t nonce_length, - csprng *rng); + struct ecdaa_prng *prng); /* * Check the signature on an `ecdaa_member_public_key_BN254`. diff --git a/include/ecdaa/prng.h b/include/ecdaa/prng.h new file mode 100644 index 0000000..cec125b --- /dev/null +++ b/include/ecdaa/prng.h @@ -0,0 +1,111 @@ +/****************************************************************************** + * + * Copyright 2017 Xaptum, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + *****************************************************************************/ + +#ifndef ECDAA_PRNG_H +#define ECDAA_PRNG_H +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#include + +#define AMCL_SEED_SIZE 128 // As recommended in AMCL's "rand.c" + +enum ecdaa_prng_initialized { + ECDAA_PRNG_INITIALIZED_NO = 0, + ECDAA_PRNG_INITIALIZED_YES +}; + +/* + * Wrapper around AMCL's pseudo-random-number-generator. + * + * For the safe operation of this library, + * all `ecdaa_prng`s MUST first be properly seeded + * via a call to `ecdaa_prng_init` + * or `ecdaa_prng_init_custom` before first use. + */ +struct ecdaa_prng { + enum ecdaa_prng_initialized initialized; + csprng impl; +}; + +/* + * Accessor for the underlying AMCL csprng in a `ecdaa_prng`. + * + * Checks that `ecdaa_prng` was initialized before returning. + * If not, calls `abort()`. + */ +csprng *get_csprng(struct ecdaa_prng *prng); + +/* + * Securely-clears memory used by a `ecdaa_prng`. + * + * To be used when finished with a `ecdaa_prng`. + * + * Does not do any heap deallocation. + */ +void ecdaa_prng_free(struct ecdaa_prng *prng); + +#ifndef DISABLE_LIBSODIUM_RNG_SEED_FUNCTION + +/* + * Properly seeds a `ecdaa_prng`. + * + * MUST be called on a `ecdaa_prng` before first use. + * + * No dynamic memory allocation is performed. + * + * Uses Libsodium's `randombytes_buf` as the source of + * a cryptographically-strong random seed. + * Requires the CMake option `DISABLE_LIBSODIUM_RNG_SEED_FUNCTION=OFF`. + * + * Returns: + * 0 on success + * -1 if unable to obtain seed + * -2 if entropy is insufficient + */ +int ecdaa_prng_init(struct ecdaa_prng *prng_in); + +#endif // DISABLE_LIBSODIUM_RNG_SEED_FUNCTION + +/* + * Properly seed a `ecdaa_prng`, with a custom cryptographically-strong random seed. + * + * MUST be called on a `ecdaa_prng` before first use, + * unless using `ecdaa_prng_init` instead. + * + * No dynamic memory allocation is performed. + * + * `seed_size` MUST be at least AMCL_SEED_SIZE. + * + * Returns: + * 0 on success + * -1 if seed_size < AMCL_SEED_SIZE + */ +int ecdaa_prng_init_custom(struct ecdaa_prng *prng_in, char *seed, size_t seed_size); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/include/ecdaa/signature_BN254.h b/include/ecdaa/signature_BN254.h index 5590765..182ff09 100644 --- a/include/ecdaa/signature_BN254.h +++ b/include/ecdaa/signature_BN254.h @@ -31,6 +31,7 @@ struct ecdaa_credential_BN254; struct ecdaa_member_secret_key_BN254; struct ecdaa_revocation_list_BN254; struct ecdaa_group_public_key_BN254; +struct ecdaa_prng; /* * ECDAA signature. @@ -58,7 +59,7 @@ int ecdaa_signature_BN254_sign(struct ecdaa_signature_BN254 *signature_out, uint32_t message_len, struct ecdaa_member_secret_key_BN254 *sk, struct ecdaa_credential_BN254 *cred, - csprng *rng); + struct ecdaa_prng *prng); /* * Verify an ECDAA signature. diff --git a/src/credential_BN254.c b/src/credential_BN254.c index 1d4bdeb..f4f35aa 100644 --- a/src/credential_BN254.c +++ b/src/credential_BN254.c @@ -28,6 +28,7 @@ #include #include #include +#include size_t ecdaa_credential_BN254_length(void) { @@ -43,7 +44,7 @@ int ecdaa_credential_BN254_generate(struct ecdaa_credential_BN254 *cred, struct ecdaa_credential_BN254_signature *cred_sig_out, struct ecdaa_issuer_secret_key_BN254 *isk, struct ecdaa_member_public_key_BN254 *member_pk, - csprng *rng) + struct ecdaa_prng *prng) { int ret = 0; @@ -52,7 +53,7 @@ int ecdaa_credential_BN254_generate(struct ecdaa_credential_BN254 *cred, // 1) Choose random l <- Z_p BIG_256_56 l; - big_256_56_random_mod_order(&l, rng); + big_256_56_random_mod_order(&l, get_csprng(prng)); // 2) Multiply generator by l and save to cred->A (A = l*P) ecp_BN254_set_to_generator(&cred->A); @@ -97,7 +98,7 @@ int ecdaa_credential_BN254_generate(struct ecdaa_credential_BN254 *cred, &cred->D, isk->y, l, - rng); + prng); if (0 != schnorr_ret) ret = -1; diff --git a/src/internal/schnorr.c b/src/internal/schnorr.c index 5c40c4c..95143aa 100644 --- a/src/internal/schnorr.c +++ b/src/internal/schnorr.c @@ -23,6 +23,8 @@ #include "../amcl-extensions/ecp_BN254.h" #include "../amcl-extensions/ecp2_BN254.h" +#include + #include #include @@ -30,9 +32,9 @@ void schnorr_keygen(ECP_BN254 *public_out, BIG_256_56 *private_out, - csprng *rng) + struct ecdaa_prng *prng) { - big_256_56_random_mod_order(private_out, rng); + big_256_56_random_mod_order(private_out, get_csprng(prng)); ecp_BN254_set_to_generator(public_out); @@ -46,7 +48,7 @@ int schnorr_sign(BIG_256_56 *c_out, ECP_BN254 *basepoint, ECP_BN254 *public_key, BIG_256_56 private_key, - csprng *rng) + struct ecdaa_prng *prng) { // 1) (Commit 1) Verify basepoint belongs to group if (0 != ecp_BN254_check_membership(basepoint)) @@ -54,7 +56,7 @@ int schnorr_sign(BIG_256_56 *c_out, // 2) (Commit 2) Choose random k <- Z_n BIG_256_56 k; - big_256_56_random_mod_order(&k, rng); + big_256_56_random_mod_order(&k, get_csprng(prng)); // 3) (Commit 3) Multiply basepoint by k: R = k*basepoint ECP_BN254 R; @@ -136,7 +138,7 @@ int credential_schnorr_sign(BIG_256_56 *c_out, ECP_BN254 *D, BIG_256_56 issuer_private_key_y, BIG_256_56 credential_random, - csprng *rng) + struct ecdaa_prng *prng) { // 1) Set generator ECP_BN254 generator; @@ -144,7 +146,7 @@ int credential_schnorr_sign(BIG_256_56 *c_out, // 2) Choose random r <- Z_n BIG_256_56 r; - big_256_56_random_mod_order(&r, rng); + big_256_56_random_mod_order(&r, get_csprng(prng)); // 3) Multiply generator by r: U = r*generator ECP_BN254 U; @@ -255,7 +257,7 @@ int issuer_schnorr_sign(BIG_256_56 *c_out, ECP2_BN254 *Y, BIG_256_56 issuer_private_key_x, BIG_256_56 issuer_private_key_y, - csprng *rng) + struct ecdaa_prng *prng) { // 1) Set generator_2 ECP2_BN254 generator_2; @@ -263,8 +265,8 @@ int issuer_schnorr_sign(BIG_256_56 *c_out, // 2) Choose random rx, ry <- Z_n BIG_256_56 rx, ry; - big_256_56_random_mod_order(&rx, rng); - big_256_56_random_mod_order(&ry, rng); + big_256_56_random_mod_order(&rx, get_csprng(prng)); + big_256_56_random_mod_order(&ry, get_csprng(prng)); // 3) Multiply generator_2 by rx: Ux = rx*generator_2 ECP2_BN254 Ux; diff --git a/src/internal/schnorr.h b/src/internal/schnorr.h index ca304f8..6e7a7a7 100644 --- a/src/internal/schnorr.h +++ b/src/internal/schnorr.h @@ -24,10 +24,11 @@ extern "C" { #endif +struct ecdaa_prng; + #include #include #include -#include #include @@ -39,7 +40,7 @@ extern "C" { */ void schnorr_keygen(ECP_BN254 *public_out, BIG_256_56 *private_out, - csprng *rng); + struct ecdaa_prng *prng); /* * Perform Schnorr signature of msg_in, allowing for a non-standard basepoint. @@ -62,7 +63,7 @@ int schnorr_sign(BIG_256_56 *c_out, ECP_BN254 *basepoint, ECP_BN254 *public_key, BIG_256_56 private_key, - csprng *rng); + struct ecdaa_prng *prng); /* * Verify that (c, s) is a valid Schnorr signature of msg_in, allowing for a non-standard basepoint. @@ -105,7 +106,7 @@ int credential_schnorr_sign(BIG_256_56 *c_out, ECP_BN254 *D, BIG_256_56 issuer_private_key_y, BIG_256_56 credential_random, - csprng *rng); + struct ecdaa_prng *prng); /* * Verify that (c, s) is a valid 'credential-Schnorr' signature. @@ -150,7 +151,7 @@ int issuer_schnorr_sign(BIG_256_56 *c_out, ECP2_BN254 *Y, BIG_256_56 issuer_private_key_x, BIG_256_56 issuer_private_key_y, - csprng *rng); + struct ecdaa_prng *prng); /* * Verify that (c, sx, sy) is a valid 'issuer-Schnorr' signature. diff --git a/src/issuer_keypair_BN254.c b/src/issuer_keypair_BN254.c index ebe3ad1..2372771 100644 --- a/src/issuer_keypair_BN254.c +++ b/src/issuer_keypair_BN254.c @@ -18,6 +18,8 @@ #include +#include + #include "./amcl-extensions/big_256_56.h" #include "./amcl-extensions/ecp2_BN254.h" #include "./internal/schnorr.h" @@ -34,12 +36,12 @@ size_t ecdaa_issuer_secret_key_BN254_length(void) { int ecdaa_issuer_key_pair_BN254_generate(struct ecdaa_issuer_public_key_BN254 *pk, struct ecdaa_issuer_secret_key_BN254 *sk, - csprng *rng) + struct ecdaa_prng *prng) { // Secret key is // two random Bignums. - big_256_56_random_mod_order(&sk->x, rng); - big_256_56_random_mod_order(&sk->y, rng); + big_256_56_random_mod_order(&sk->x, get_csprng(prng)); + big_256_56_random_mod_order(&sk->y, get_csprng(prng)); // Public key is // 1) G2 generator raised to the two private key random Bignums... @@ -49,7 +51,7 @@ int ecdaa_issuer_key_pair_BN254_generate(struct ecdaa_issuer_public_key_BN254 *p ECP2_BN254_mul(&pk->gpk.Y, sk->y); // 2) and a Schnorr-type signature to prove our knowledge of those two random Bignums. - int sign_ret = issuer_schnorr_sign(&pk->c, &pk->sx, &pk->sy, &pk->gpk.X, &pk->gpk.Y, sk->x, sk->y, rng); + int sign_ret = issuer_schnorr_sign(&pk->c, &pk->sx, &pk->sy, &pk->gpk.X, &pk->gpk.Y, sk->x, sk->y, prng); if (0 != sign_ret) return -1; diff --git a/src/member_keypair_BN254.c b/src/member_keypair_BN254.c index 95eecfd..66d7be6 100644 --- a/src/member_keypair_BN254.c +++ b/src/member_keypair_BN254.c @@ -18,6 +18,8 @@ #include +#include + #include "./amcl-extensions/ecp_BN254.h" #include "./internal/schnorr.h" @@ -37,10 +39,10 @@ int ecdaa_member_key_pair_BN254_generate(struct ecdaa_member_public_key_BN254 *p struct ecdaa_member_secret_key_BN254 *sk, uint8_t *nonce, uint32_t nonce_length, - csprng *rng) + struct ecdaa_prng *prng) { // 1) Generate Schnorr-type keypair, - schnorr_keygen(&pk->Q, &sk->sk, rng); + schnorr_keygen(&pk->Q, &sk->sk, prng); // 2) and a Schnorr-type signature on the Schnorr-type public_key itself concatenated with the nonce. ECP_BN254 basepoint; @@ -52,7 +54,7 @@ int ecdaa_member_key_pair_BN254_generate(struct ecdaa_member_public_key_BN254 *p &basepoint, &pk->Q, sk->sk, - rng); + prng); return sign_ret; } diff --git a/src/prng.c b/src/prng.c new file mode 100644 index 0000000..0277f73 --- /dev/null +++ b/src/prng.c @@ -0,0 +1,112 @@ +/****************************************************************************** + * + * Copyright 2017 Xaptum, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + *****************************************************************************/ + +#include + +#include "internal/explicit_bzero.h" + +#ifndef DISABLE_LIBSODIUM_RNG_SEED_FUNCTION + +#include + +#if defined(__linux__) +#include +#include +#include +#include +#endif + +static int check_entropy() +{ + int ret = 0; +#if defined(__linux__) && defined(RNDGETENTCNT) + int fd; + if ((fd = open("/dev/random", O_RDONLY)) != -1) { + int c; + if (ioctl(fd, RNDGETENTCNT, &c) == 0 && c < 160) { + ret = -2; + } + (void) close(fd); + } +#endif + + return ret; +} + +int ecdaa_prng_init(struct ecdaa_prng *prng_in) +{ + int ret = 0; + + prng_in->initialized = ECDAA_PRNG_INITIALIZED_NO; + + do { + ret = check_entropy(); + if (0 != ret) + break; + + // Note: We don't have to worry about the race-condition here. + // `sodium_init` can be called multiple times, and from multiple threads. + if (-1 == sodium_init()) { + ret = -1; + break; + } + + char seed[AMCL_SEED_SIZE]; + randombytes_buf(seed, sizeof(seed)); + + ret = ecdaa_prng_init_custom(prng_in, seed, sizeof(seed)); + if (0 != ret) + break; + } while(0); + + if (0 == ret) + prng_in->initialized = ECDAA_PRNG_INITIALIZED_YES; + + return ret; +} + +#endif // DISABLE_LIBSODIUM_RNG_SEED_FUNCTION + +csprng *get_csprng(struct ecdaa_prng *prng) +{ + if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized) + abort(); + + return &prng->impl; +} + +void ecdaa_prng_free(struct ecdaa_prng *prng) +{ + explicit_bzero(prng, sizeof(struct ecdaa_prng)); + + prng->initialized = ECDAA_PRNG_INITIALIZED_NO; +} + +int ecdaa_prng_init_custom(struct ecdaa_prng *prng_in, char *seed, size_t seed_size) +{ + prng_in->initialized = ECDAA_PRNG_INITIALIZED_NO; + + if (AMCL_SEED_SIZE > seed_size) + return -1; + + RAND_seed(&prng_in->impl, seed_size, seed); + + prng_in->initialized = ECDAA_PRNG_INITIALIZED_YES; + + return 0; +} diff --git a/src/signature_BN254.c b/src/signature_BN254.c index bb5a9ec..a3eae12 100644 --- a/src/signature_BN254.c +++ b/src/signature_BN254.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "./internal/schnorr.h" #include "./amcl-extensions/big_256_56.h" @@ -42,11 +43,11 @@ int ecdaa_signature_BN254_sign(struct ecdaa_signature_BN254 *signature_out, uint32_t message_len, struct ecdaa_member_secret_key_BN254 *sk, struct ecdaa_credential_BN254 *cred, - csprng *rng) + struct ecdaa_prng *prng) { // 1) Choose random l <- Z_p BIG_256_56 l; - big_256_56_random_mod_order(&l, rng); + big_256_56_random_mod_order(&l, get_csprng(prng)); // 2) Multiply the four points in the credential by l, // and save to the four points in the signature @@ -76,7 +77,7 @@ int ecdaa_signature_BN254_sign(struct ecdaa_signature_BN254 *signature_out, &signature_out->S, &signature_out->W, sk->sk, - rng); + prng); // Clear sensitive intermediate memory. BIG_256_56_zero(l); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index c985caa..03fec67 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -26,6 +26,7 @@ set(TEST_SRCS big_256_56-tests.c ecp_BN254-tests.c ecp2_BN254-tests.c + prng-tests.c schnorr-tests.c benchmarks.c ) diff --git a/test/benchmarks.c b/test/benchmarks.c index cfd93dc..175153f 100644 --- a/test/benchmarks.c +++ b/test/benchmarks.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -40,7 +41,7 @@ static void sign_benchmark(); static void verify_benchmark(); typedef struct sign_and_verify_fixture { - csprng rng; + struct ecdaa_prng prng; uint8_t *msg; uint32_t msg_len; struct ecdaa_revocation_list_BN254 sk_rev_list; @@ -64,22 +65,22 @@ int main() static void setup(sign_and_verify_fixture* fixture) { - create_test_rng(&fixture->rng); + TEST_ASSERT(0 == ecdaa_prng_init(&fixture->prng)); - big_256_56_random_mod_order(&fixture->isk.x, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.x, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.X); ECP2_BN254_mul(&fixture->ipk.gpk.X, fixture->isk.x); - big_256_56_random_mod_order(&fixture->isk.y, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.y, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.Y); ECP2_BN254_mul(&fixture->ipk.gpk.Y, fixture->isk.y); ecp_BN254_set_to_generator(&fixture->pk.Q); - big_256_56_random_mod_order(&fixture->sk.sk, &fixture->rng); + big_256_56_random_mod_order(&fixture->sk.sk, get_csprng(&fixture->prng)); ECP_BN254_mul(&fixture->pk.Q, fixture->sk.sk); struct ecdaa_credential_BN254_signature cred_sig; - ecdaa_credential_BN254_generate(&fixture->cred, &cred_sig, &fixture->isk, &fixture->pk, &fixture->rng); + ecdaa_credential_BN254_generate(&fixture->cred, &cred_sig, &fixture->isk, &fixture->pk, &fixture->prng); fixture->msg = (uint8_t*) "Test message"; fixture->msg_len = strlen((char*)fixture->msg); @@ -88,9 +89,9 @@ static void setup(sign_and_verify_fixture* fixture) fixture->sk_rev_list.list=NULL; } -static void teardown(sign_and_verify_fixture *fixture) +static void teardown(sign_and_verify_fixture* fixture) { - destroy_test_rng(&fixture->rng); + ecdaa_prng_free(&fixture->prng); } void schnorr_sign_benchmark() @@ -102,10 +103,10 @@ void schnorr_sign_benchmark() ECP_BN254 public; BIG_256_56 private; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public, &private, &rng); + schnorr_keygen(&public, &private, &prng); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -118,7 +119,7 @@ void schnorr_sign_benchmark() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); for (unsigned i = 0; i < rounds; i++) { - schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng); + schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng); } struct timeval tv2; @@ -130,7 +131,8 @@ void schnorr_sign_benchmark() elapsed, rounds * 1000000ULL / elapsed); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); + } static void sign_benchmark() @@ -148,7 +150,7 @@ static void sign_benchmark() gettimeofday(&tv1, NULL); for (unsigned i = 0; i < rounds; i++) { - TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.rng)); + TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.prng)); } struct timeval tv2; @@ -174,7 +176,7 @@ static void verify_benchmark() struct ecdaa_signature_BN254 sig; - TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.rng)); + TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.prng)); struct timeval tv1; gettimeofday(&tv1, NULL); diff --git a/test/big_256_56-tests.c b/test/big_256_56-tests.c index 7acbb01..20bc5c7 100644 --- a/test/big_256_56-tests.c +++ b/test/big_256_56-tests.c @@ -20,6 +20,8 @@ #include "../src/amcl-extensions/big_256_56.h" +#include + #include #include @@ -316,12 +318,12 @@ void random_num_mod_order_is_valid() BIG_256_56 curve_order; BIG_256_56_rcopy(curve_order, CURVE_Order_BN254); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); BIG_256_56 num; for (int i = 0; i < 500; ++i) { - big_256_56_random_mod_order(&num, &rng); + big_256_56_random_mod_order(&num, get_csprng(&prng)); TEST_ASSERT(BIG_256_56_iszilch(num) == 0); TEST_ASSERT(BIG_256_56_isunity(num) == 0); @@ -329,7 +331,7 @@ void random_num_mod_order_is_valid() TEST_ASSERT(BIG_256_56_comp(num, curve_order) == -1); } - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } diff --git a/test/credential-tests.c b/test/credential-tests.c index 6a76884..2306dfa 100644 --- a/test/credential-tests.c +++ b/test/credential-tests.c @@ -21,6 +21,7 @@ #include #include #include +#include #include "../src/amcl-extensions/big_256_56.h" #include "../src/amcl-extensions/ecp_BN254.h" @@ -32,7 +33,7 @@ #include typedef struct credential_test_fixture { - csprng rng; + struct ecdaa_prng prng; struct ecdaa_member_public_key_BN254 pk; struct ecdaa_member_secret_key_BN254 sk; @@ -42,7 +43,7 @@ typedef struct credential_test_fixture { } credential_test_fixture; static void setup(credential_test_fixture* fixture); -static void teardown(credential_test_fixture *fixture); +static void teardown(credential_test_fixture* fixture); static void cred_generate_then_validate(); @@ -53,24 +54,24 @@ int main() static void setup(credential_test_fixture* fixture) { - create_test_rng(&fixture->rng); + TEST_ASSERT(0 == ecdaa_prng_init(&fixture->prng)); - big_256_56_random_mod_order(&fixture->isk.x, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.x, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.X); ECP2_BN254_mul(&fixture->ipk.gpk.X, fixture->isk.x); - big_256_56_random_mod_order(&fixture->isk.y, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.y, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.Y); ECP2_BN254_mul(&fixture->ipk.gpk.Y, fixture->isk.y); ecp_BN254_set_to_generator(&fixture->pk.Q); - big_256_56_random_mod_order(&fixture->sk.sk, &fixture->rng); + big_256_56_random_mod_order(&fixture->sk.sk, get_csprng(&fixture->prng)); ECP_BN254_mul(&fixture->pk.Q, fixture->sk.sk); } -static void teardown(credential_test_fixture *fixture) +static void teardown(credential_test_fixture* fixture) { - destroy_test_rng(&fixture->rng); + ecdaa_prng_free(&fixture->prng); } static void cred_generate_then_validate() @@ -82,7 +83,7 @@ static void cred_generate_then_validate() struct ecdaa_credential_BN254 cred; struct ecdaa_credential_BN254_signature cred_sig; - TEST_ASSERT(0 == ecdaa_credential_BN254_generate(&cred, &cred_sig, &fixture.isk, &fixture.pk, &fixture.rng)); + TEST_ASSERT(0 == ecdaa_credential_BN254_generate(&cred, &cred_sig, &fixture.isk, &fixture.pk, &fixture.prng)); TEST_ASSERT(0 == ecdaa_credential_BN254_validate(&cred, &cred_sig, &fixture.pk, &fixture.ipk.gpk)); diff --git a/test/ecdaa-test-utils.c b/test/ecdaa-test-utils.c deleted file mode 100644 index da3177c..0000000 --- a/test/ecdaa-test-utils.c +++ /dev/null @@ -1,45 +0,0 @@ -/****************************************************************************** - * - * Copyright 2017 Xaptum, Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License - * - *****************************************************************************/ - -#include "ecdaa-test-utils.h" - -void get_test_seed(char *out, unsigned out_length) -{ - // Nb. This isn't intended to be secure. - // It's just for testing. - - srand(time(NULL)); - for (unsigned i = 0; i < out_length; ++i) - out[i] = rand(); -} - -void create_test_rng(csprng *rng) -{ - char seed_as_bytes[SEED_LEN]; - - get_test_seed(seed_as_bytes, SEED_LEN); - - octet seed = {.len=SEED_LEN, .max=SEED_LEN, .val=seed_as_bytes}; - - CREATE_CSPRNG(rng, &seed); -} - -void destroy_test_rng(csprng *rng) -{ - KILL_CSPRNG(rng); -} diff --git a/test/ecdaa-test-utils.h b/test/ecdaa-test-utils.h index 9481b5d..d958e74 100644 --- a/test/ecdaa-test-utils.h +++ b/test/ecdaa-test-utils.h @@ -16,13 +16,9 @@ * *****************************************************************************/ -#include - #include #include -#define SEED_LEN 256 - #define TEST_ASSERT(cond) \ do \ { \ @@ -42,8 +38,3 @@ } \ } while(0); -void get_test_seed(char *out, unsigned out_length); - -void create_test_rng(csprng *rng); - -void destroy_test_rng(csprng *rng); diff --git a/test/issuer_keypair-tests.c b/test/issuer_keypair-tests.c index 8fd1434..ba223af 100644 --- a/test/issuer_keypair-tests.c +++ b/test/issuer_keypair-tests.c @@ -19,8 +19,7 @@ #include "ecdaa-test-utils.h" #include - -#include +#include static void issuer_secrets_are_valid(); static void issuer_proof_checks(); @@ -35,12 +34,12 @@ void issuer_secrets_are_valid() { printf("Starting context::issuer_secrets_are_valid...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); struct ecdaa_issuer_secret_key_BN254 sk1; struct ecdaa_issuer_public_key_BN254 pk1; - ecdaa_issuer_key_pair_BN254_generate(&pk1, &sk1, &rng); + ecdaa_issuer_key_pair_BN254_generate(&pk1, &sk1, &prng); TEST_ASSERT(BIG_256_56_comp(sk1.x, sk1.y) != 0); TEST_ASSERT(!pk1.gpk.X.inf); @@ -48,11 +47,11 @@ void issuer_secrets_are_valid() struct ecdaa_issuer_secret_key_BN254 sk2; struct ecdaa_issuer_public_key_BN254 pk2; - ecdaa_issuer_key_pair_BN254_generate(&pk2, &sk2, &rng); + ecdaa_issuer_key_pair_BN254_generate(&pk2, &sk2, &prng); TEST_ASSERT(BIG_256_56_comp(sk1.x, sk2.x) != 0); TEST_ASSERT(BIG_256_56_comp(sk1.y, sk2.y) != 0); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } diff --git a/test/member_keypair-tests.c b/test/member_keypair-tests.c index 976df61..d3319e1 100644 --- a/test/member_keypair-tests.c +++ b/test/member_keypair-tests.c @@ -21,8 +21,7 @@ #include "../src/amcl-extensions/ecp_BN254.h" #include - -#include +#include static void member_secret_is_valid(); static void member_public_is_valid(); @@ -43,21 +42,21 @@ void member_secret_is_valid() struct ecdaa_member_public_key_BN254 pk1; uint8_t nonce[32] = {0}; - csprng rng; - create_test_rng(&rng); - - ecdaa_member_key_pair_BN254_generate(&pk1, &sk1, nonce, sizeof(nonce), &rng); + struct ecdaa_prng prng; + ecdaa_prng_init(&prng); - destroy_test_rng(&rng); + ecdaa_member_key_pair_BN254_generate(&pk1, &sk1, nonce, sizeof(nonce), &prng); TEST_ASSERT(!pk1.Q.inf); struct ecdaa_member_secret_key_BN254 sk2; struct ecdaa_member_public_key_BN254 pk2; - ecdaa_member_key_pair_BN254_generate(&pk2, &sk2, nonce, sizeof(nonce), &rng); + ecdaa_member_key_pair_BN254_generate(&pk2, &sk2, nonce, sizeof(nonce), &prng); TEST_ASSERT(BIG_256_56_comp(sk1.sk, sk2.sk) != 0); + ecdaa_prng_free(&prng); + printf("\tsuccess\n"); } @@ -65,16 +64,18 @@ void member_public_is_valid() { printf("Starting context::member_public_is_valid...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + ecdaa_prng_init(&prng); struct ecdaa_member_secret_key_BN254 sk; struct ecdaa_member_public_key_BN254 pk; uint8_t nonce[32] = {0}; - ecdaa_member_key_pair_BN254_generate(&pk, &sk, nonce, sizeof(nonce), &rng); + ecdaa_member_key_pair_BN254_generate(&pk, &sk, nonce, sizeof(nonce), &prng); TEST_ASSERT(0 == ecp_BN254_check_membership(&pk.Q)); + ecdaa_prng_free(&prng); + printf("\tsuccess\n"); } diff --git a/test/prng-tests.c b/test/prng-tests.c new file mode 100644 index 0000000..0e4cecc --- /dev/null +++ b/test/prng-tests.c @@ -0,0 +1,81 @@ +/****************************************************************************** + * + * Copyright 2017 Xaptum, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License + * + *****************************************************************************/ + +#include "ecdaa-test-utils.h" + +#include + +#include + +static void different_rngs_are_different(); +static void deterministic_seed_makes_same_rngs(); + +int main() +{ + different_rngs_are_different(); + deterministic_seed_makes_same_rngs(); +} + +static void different_rngs_are_different() +{ + struct ecdaa_prng rng1, rng2; + TEST_ASSERT(0 == ecdaa_prng_init(&rng1)); + TEST_ASSERT(0 == ecdaa_prng_init(&rng2)); + + int bytes1[5]; + int bytes2[5]; + for (int i = 0; i < 5; i++) { + bytes1[i] = RAND_byte(&rng1.impl); + bytes2[i] = RAND_byte(&rng2.impl); + } + TEST_ASSERT(bytes1[0] != bytes2[0] + || bytes1[1] != bytes2[1] + || bytes1[2] != bytes2[2] + || bytes1[3] != bytes2[3] + || bytes1[4] != bytes2[4] + ); + + ecdaa_prng_free(&rng1); + ecdaa_prng_free(&rng2); +} + +static void deterministic_seed_makes_same_rngs() +{ + struct ecdaa_prng rng1, rng2; + char seed[AMCL_SEED_SIZE]; + for (size_t i = 0; i < sizeof(seed); i++) + seed[i] = 5; + ecdaa_prng_init_custom(&rng1, seed, sizeof(seed)); + ecdaa_prng_init_custom(&rng2, seed, sizeof(seed)); + + int bytes1[5]; + int bytes2[5]; + for (int i = 0; i < 5; i++) { + bytes1[i] = RAND_byte(&rng1.impl); + bytes2[i] = RAND_byte(&rng2.impl); + } + TEST_ASSERT(bytes1[0] == bytes2[0] + && bytes1[1] == bytes2[1] + && bytes1[2] == bytes2[2] + && bytes1[3] == bytes2[3] + && bytes1[4] == bytes2[4] + ); + + ecdaa_prng_free(&rng1); + ecdaa_prng_free(&rng2); +} diff --git a/test/schnorr-tests.c b/test/schnorr-tests.c index 7f521f9..a1a73dd 100644 --- a/test/schnorr-tests.c +++ b/test/schnorr-tests.c @@ -25,6 +25,7 @@ #include "../src/amcl-extensions/ecp2_BN254.h" #include +#include #include #include @@ -65,11 +66,11 @@ void schnorr_keygen_sane() ECP_BN254 public_one, public_two; BIG_256_56 private_one, private_two; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public_one, &private_one, &rng); - schnorr_keygen(&public_two, &private_two, &rng); + schnorr_keygen(&public_one, &private_one, &prng); + schnorr_keygen(&public_two, &private_two, &prng); TEST_ASSERT(0 != BIG_256_56_comp(private_one, private_two)); TEST_ASSERT(1 != ECP_BN254_equals(&public_one, &public_two)); @@ -77,7 +78,7 @@ void schnorr_keygen_sane() TEST_ASSERT(!public_one.inf); TEST_ASSERT(!public_two.inf); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -86,13 +87,13 @@ void schnorr_sign_sane() { printf("Starting schnorr::schnorr_sign_sane...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); ECP_BN254 public; BIG_256_56 private; - big_256_56_random_mod_order(&private, &rng); + big_256_56_random_mod_order(&private, get_csprng(&prng)); ecp_BN254_set_to_generator(&public); ECP_BN254_mul(&public, private); @@ -104,14 +105,14 @@ void schnorr_sign_sane() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); - TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng)); + TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng)); TEST_ASSERT(0 == BIG_256_56_iszilch(c)); TEST_ASSERT(0 == BIG_256_56_iszilch(s)); TEST_ASSERT(0 == BIG_256_56_isunity(c)); TEST_ASSERT(0 == BIG_256_56_isunity(s)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -123,11 +124,11 @@ void schnorr_verify_wrong_key() ECP_BN254 public, public_wrong; BIG_256_56 private, private_wrong; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public, &private, &rng); - schnorr_keygen(&public_wrong, &private_wrong, &rng); + schnorr_keygen(&public, &private, &prng); + schnorr_keygen(&public_wrong, &private_wrong, &prng); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -136,11 +137,11 @@ void schnorr_verify_wrong_key() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); - TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng)); + TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng)); TEST_ASSERT(-1 == schnorr_verify(c, s, msg, msg_len, &basepoint, &public_wrong)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -152,10 +153,10 @@ void schnorr_verify_wrong_msg() ECP_BN254 public; BIG_256_56 private; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public, &private, &rng); + schnorr_keygen(&public, &private, &prng); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -166,11 +167,11 @@ void schnorr_verify_wrong_msg() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); - TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng)); + TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng)); TEST_ASSERT(-1 == schnorr_verify(c, s, msg_wrong, msg_len_wrong, &basepoint, &public)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -182,10 +183,10 @@ void schnorr_verify_bad_sig() ECP_BN254 public; BIG_256_56 private; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public, &private, &rng); + schnorr_keygen(&public, &private, &prng); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -196,7 +197,7 @@ void schnorr_verify_bad_sig() ecp_BN254_set_to_generator(&basepoint); TEST_ASSERT(-1 == schnorr_verify(c, s, msg, msg_len, &basepoint, &public)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -208,10 +209,10 @@ void schnorr_sign_integration() ECP_BN254 public; BIG_256_56 private; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - schnorr_keygen(&public, &private, &rng); + schnorr_keygen(&public, &private, &prng); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -220,11 +221,11 @@ void schnorr_sign_integration() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); - TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng)); + TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng)); TEST_ASSERT(0 == schnorr_verify(c, s, msg, msg_len, &basepoint, &public)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -233,8 +234,8 @@ void schnorr_sign_integration_other_basepoint() { printf("Starting schnorr::schnorr_sign_integration_other_points...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); uint8_t *msg = (uint8_t*) "Test message"; uint32_t msg_len = strlen((char*)msg); @@ -244,20 +245,20 @@ void schnorr_sign_integration_other_basepoint() ECP_BN254 basepoint; ecp_BN254_set_to_generator(&basepoint); BIG_256_56 rand; - big_256_56_random_mod_order(&rand, &rng); + big_256_56_random_mod_order(&rand, get_csprng(&prng)); ECP_BN254_mul(&basepoint, rand); ECP_BN254 public; BIG_256_56 private; - big_256_56_random_mod_order(&private, &rng); + big_256_56_random_mod_order(&private, get_csprng(&prng)); ECP_BN254_copy(&public, &basepoint); ECP_BN254_mul(&public, private); - TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &rng)); + TEST_ASSERT(0 == schnorr_sign(&c, &s, msg, msg_len, &basepoint, &public, private, &prng)); TEST_ASSERT(0 == schnorr_verify(c, s, msg, msg_len, &basepoint, &public)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -278,25 +279,25 @@ void schnorr_credential_sign_sane() BIG_256_56 c, s; - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); - big_256_56_random_mod_order(&credential_random, &rng); + big_256_56_random_mod_order(&credential_random, get_csprng(&prng)); - big_256_56_random_mod_order(&member_private, &rng); - big_256_56_random_mod_order(&issuer_private, &rng); + big_256_56_random_mod_order(&member_private, get_csprng(&prng)); + big_256_56_random_mod_order(&issuer_private, get_csprng(&prng)); ecp_BN254_set_to_generator(&member_public); ECP_BN254_mul(&member_public, member_private); - TEST_ASSERT(0 == credential_schnorr_sign(&c, &s, &B, &member_public, &D, issuer_private, credential_random, &rng)); - - destroy_test_rng(&rng); + TEST_ASSERT(0 == credential_schnorr_sign(&c, &s, &B, &member_public, &D, issuer_private, credential_random, &prng)); TEST_ASSERT(0 == BIG_256_56_iszilch(c)); TEST_ASSERT(0 == BIG_256_56_iszilch(s)); TEST_ASSERT(0 == BIG_256_56_isunity(c)); TEST_ASSERT(0 == BIG_256_56_isunity(s)); + ecdaa_prng_free(&prng); + printf("\tsuccess\n"); } @@ -304,8 +305,8 @@ void schnorr_credential_sign_integration() { printf("Starting schnorr::schnorr_credential_sign_integration...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); BIG_256_56 member_private = {2718, 0}; ECP_BN254 member_public; @@ -328,11 +329,11 @@ void schnorr_credential_sign_integration() BIG_256_56 c, s; - TEST_ASSERT(0 == credential_schnorr_sign(&c, &s, &B, &member_public, &D, issuer_private_key_y, credential_random, &rng)); + TEST_ASSERT(0 == credential_schnorr_sign(&c, &s, &B, &member_public, &D, issuer_private_key_y, credential_random, &prng)); TEST_ASSERT(0 == credential_schnorr_verify(c, s, &B, &member_public, &D)); - destroy_test_rng(&rng); + ecdaa_prng_free(&prng); printf("\tsuccess\n"); } @@ -341,13 +342,13 @@ void schnorr_issuer_sign_sane() { printf("Starting schnorr::schnorr_issuer_sign_sane...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); BIG_256_56 issuer_private_x; - big_256_56_random_mod_order(&issuer_private_x, &rng); + big_256_56_random_mod_order(&issuer_private_x, get_csprng(&prng)); BIG_256_56 issuer_private_y; - big_256_56_random_mod_order(&issuer_private_y, &rng); + big_256_56_random_mod_order(&issuer_private_y, get_csprng(&prng)); ECP2_BN254 issuer_public_X; ECP2_BN254 issuer_public_Y; ecp2_BN254_set_to_generator(&issuer_public_X); @@ -357,9 +358,7 @@ void schnorr_issuer_sign_sane() BIG_256_56 c, sx, sy; - TEST_ASSERT(0 == issuer_schnorr_sign(&c, &sx, &sy, &issuer_public_X, &issuer_public_Y, issuer_private_x, issuer_private_y, &rng)); - - destroy_test_rng(&rng); + TEST_ASSERT(0 == issuer_schnorr_sign(&c, &sx, &sy, &issuer_public_X, &issuer_public_Y, issuer_private_x, issuer_private_y, &prng)); TEST_ASSERT(0 == BIG_256_56_iszilch(c)); TEST_ASSERT(0 == BIG_256_56_iszilch(sx)); @@ -368,6 +367,8 @@ void schnorr_issuer_sign_sane() TEST_ASSERT(0 == BIG_256_56_isunity(sx)); TEST_ASSERT(0 == BIG_256_56_isunity(sy)); + ecdaa_prng_free(&prng); + printf("\tsuccess\n"); } @@ -375,28 +376,28 @@ void schnorr_issuer_sign_integration() { printf("Starting schnorr::schnorr_issuer_sign_integration...\n"); - csprng rng; - create_test_rng(&rng); + struct ecdaa_prng prng; + TEST_ASSERT(0 == ecdaa_prng_init(&prng)); BIG_256_56 issuer_private_x; - big_256_56_random_mod_order(&issuer_private_x, &rng); + big_256_56_random_mod_order(&issuer_private_x, get_csprng(&prng)); ECP2_BN254 issuer_public_X; ecp2_BN254_set_to_generator(&issuer_public_X); ECP2_BN254_mul(&issuer_public_X, issuer_private_x); BIG_256_56 issuer_private_y; - big_256_56_random_mod_order(&issuer_private_y, &rng); + big_256_56_random_mod_order(&issuer_private_y, get_csprng(&prng)); ECP2_BN254 issuer_public_Y; ecp2_BN254_set_to_generator(&issuer_public_Y); ECP2_BN254_mul(&issuer_public_Y, issuer_private_y); BIG_256_56 c, sx, sy; - TEST_ASSERT(0 == issuer_schnorr_sign(&c, &sx, &sy, &issuer_public_X, &issuer_public_Y, issuer_private_x, issuer_private_y, &rng)); - - destroy_test_rng(&rng); + TEST_ASSERT(0 == issuer_schnorr_sign(&c, &sx, &sy, &issuer_public_X, &issuer_public_Y, issuer_private_x, issuer_private_y, &prng)); TEST_ASSERT(0 == issuer_schnorr_verify(c, sx, sy, &issuer_public_X, &issuer_public_Y)); + ecdaa_prng_free(&prng); + printf("\tsuccess\n"); } diff --git a/test/sign-and-verify-tests.c b/test/sign-and-verify-tests.c index a5511bb..8809906 100644 --- a/test/sign-and-verify-tests.c +++ b/test/sign-and-verify-tests.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -37,7 +38,7 @@ static void sign_then_verify_good(); static void sign_then_verify_on_rev_list(); typedef struct sign_and_verify_fixture { - csprng rng; + struct ecdaa_prng prng; uint8_t *msg; uint32_t msg_len; struct ecdaa_revocation_list_BN254 sk_rev_list; @@ -49,7 +50,7 @@ typedef struct sign_and_verify_fixture { } sign_and_verify_fixture; static void setup(sign_and_verify_fixture* fixture); -static void teardown(sign_and_verify_fixture* fixture); +static void teardown(sign_and_verify_fixture *fixture); int main() { @@ -59,22 +60,22 @@ int main() static void setup(sign_and_verify_fixture* fixture) { - create_test_rng(&fixture->rng); + TEST_ASSERT(0 == ecdaa_prng_init(&fixture->prng)); - big_256_56_random_mod_order(&fixture->isk.x, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.x, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.X); ECP2_BN254_mul(&fixture->ipk.gpk.X, fixture->isk.x); - big_256_56_random_mod_order(&fixture->isk.y, &fixture->rng); + big_256_56_random_mod_order(&fixture->isk.y, get_csprng(&fixture->prng)); ecp2_BN254_set_to_generator(&fixture->ipk.gpk.Y); ECP2_BN254_mul(&fixture->ipk.gpk.Y, fixture->isk.y); ecp_BN254_set_to_generator(&fixture->pk.Q); - big_256_56_random_mod_order(&fixture->sk.sk, &fixture->rng); + big_256_56_random_mod_order(&fixture->sk.sk, get_csprng(&fixture->prng)); ECP_BN254_mul(&fixture->pk.Q, fixture->sk.sk); struct ecdaa_credential_BN254_signature cred_sig; - ecdaa_credential_BN254_generate(&fixture->cred, &cred_sig, &fixture->isk, &fixture->pk, &fixture->rng); + ecdaa_credential_BN254_generate(&fixture->cred, &cred_sig, &fixture->isk, &fixture->pk, &fixture->prng); fixture->msg = (uint8_t*) "Test message"; fixture->msg_len = strlen((char*)fixture->msg); @@ -85,7 +86,7 @@ static void setup(sign_and_verify_fixture* fixture) static void teardown(sign_and_verify_fixture *fixture) { - destroy_test_rng(&fixture->rng); + ecdaa_prng_free(&fixture->prng); } static void sign_then_verify_good() @@ -96,7 +97,7 @@ static void sign_then_verify_good() setup(&fixture); struct ecdaa_signature_BN254 sig; - TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.rng)); + TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.prng)); TEST_ASSERT(0 == ecdaa_signature_BN254_verify(&sig, &fixture.ipk.gpk, &fixture.sk_rev_list, fixture.msg, fixture.msg_len)); @@ -118,7 +119,7 @@ static void sign_then_verify_on_rev_list() struct ecdaa_revocation_list_BN254 sk_rev_list_bad = {.length=1, .list=sk_rev_list_bad_raw}; struct ecdaa_signature_BN254 sig; - TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.rng)); + TEST_ASSERT(0 == ecdaa_signature_BN254_sign(&sig, fixture.msg, fixture.msg_len, &fixture.sk, &fixture.cred, &fixture.prng)); TEST_ASSERT(0 != ecdaa_signature_BN254_verify(&sig, &fixture.ipk.gpk, &sk_rev_list_bad, fixture.msg, fixture.msg_len)); From 208752d2f04ab82d03fa7c30bf5f4b41b4b90a64 Mon Sep 17 00:00:00 2001 From: Zane Beckwith Date: Wed, 20 Sep 2017 14:53:20 -0500 Subject: [PATCH 2/3] Add libsodium package to travis. --- .travis.yml | 22 ++++++++++++++++++---- .travis/install-libsodium.sh | 28 ++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) create mode 100755 .travis/install-libsodium.sh diff --git a/.travis.yml b/.travis.yml index e914d65..c48df39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -16,12 +16,20 @@ language: c compiler: gcc +env: + global: + - LIBSODIUM_DIR=${TRAVIS_BUILD_DIR}/libsodium + - CFLAGS=-I${LIBSODIUM_DIR}/include/ + - LDFLAGS=-L${LIBSODIUM_DIR}/lib/ + - LD_LIBRARY_PATH=${LIBSODIUM_DIR}/lib/ + jobs: include: # Release build, gcc - env: TYPE=RELEASE before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} - cmake . -DCMAKE_BUILD_TYPE=Release script: - cmake --build . -- -j2 @@ -30,17 +38,19 @@ jobs: # Debug build, to get code coverage with gcov - env: TYPE=DEBUG_WITH_COVERAGE before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} - cmake . -DCMAKE_BUILD_TYPE=DebugWithCoverage -DCMAKE_C_OUTPUT_EXTENSION_REPLACE=ON script: - cmake --build . -- -j2 - ctest -VV after_success: - - .travis/upload-gcov-results.sh `pwd` + - .travis/upload-gcov-results.sh ${TRAVIS_BUILD_DIR} # Release build, clang - env: TYPE=RELEASE-WITH-CLANG compiler: clang before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} - cmake . -DCMAKE_BUILD_TYPE=Release script: - cmake --build . -- -j2 @@ -62,22 +72,26 @@ jobs: packages: - valgrind before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} - cmake . -DCMAKE_BUILD_TYPE=RelWithDebInfo script: - cmake --build . -- -j2 - ctest -VV -E benchmarks -T memcheck after_failure: - - .travis/show-memcheck-results.sh `pwd` + - .travis/show-memcheck-results.sh ${TRAVIS_BUILD_DIR} # Scan-build - env: TYPE=SCAN_BUILD + before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} script: - - .travis/run-scanbuild.sh `pwd` `pwd` + - .travis/run-scanbuild.sh ${TRAVIS_BUILD_DIR} ${TRAVIS_BUILD_DIR} # Sanitizers - env: TYPE=SANITIZE compiler: clang before_script: + - .travis/install-libsodium.sh ${LIBSODIUM_DIR} - cmake . -DCMAKE_BUILD_TYPE=RelWithSanitize script: - cmake --build . -- -j2 @@ -94,7 +108,7 @@ jobs: name: "xaptum/ecdaa" description: "A C implementation of elliptic-curve-based Direct Anonymous Attestation signatures" notification_email: ecdaa-coverity-reports@xaptum.com - build_command_prepend: "cmake . -DCMAKE_BUILD_TYPE=Release" + build_command_prepend: ".travis/install-libsodium.sh ${LIBSODIUM_DIR} && cmake . -DCMAKE_BUILD_TYPE=Release" build_command: "cmake --build ." branch_pattern: coverity_scan diff --git a/.travis/install-libsodium.sh b/.travis/install-libsodium.sh new file mode 100755 index 0000000..08f66c1 --- /dev/null +++ b/.travis/install-libsodium.sh @@ -0,0 +1,28 @@ +#!/bin/bash +# Copyright 2017 Xaptum, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License + +if [[ $# -ne 1 ]]; then + echo "usage: $0 " + exit 1 +fi + +version=1.0.13 +install_dir="$1" +wget https://download.libsodium.org/libsodium/releases/libsodium-${version}.tar.gz +tar xvfz libsodium-${version}.tar.gz +cd libsodium-${version} +./configure --prefix=$install_dir +make +make install From 144afb99a437e82688f3e2ea3eaefaa14854da0d Mon Sep 17 00:00:00 2001 From: Zane Beckwith Date: Tue, 19 Sep 2017 16:53:20 -0500 Subject: [PATCH 3/3] Update README to reflect prng struct wrapper. --- README.md | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 8f2753d..4b78c97 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,7 @@ A C implementation of elliptic-curve-based Direct Anonymous Attestation signatur - The CMake build system is used for building. - gcc +- libsodium >= 1.0.11 (optionally, see below) - For building the AMCL dependency: - python3 @@ -37,17 +38,19 @@ ctest -V ## Random number generator Many of the functions provided by this library (particularly, those used by an Issuer or a Member) -require a pointer to a pseudo-random number generator (type `csprng`). +require a pseudo random number generator (type `ecdaa_prng`). The security of these algorithms depends critically on the proper seeding of this prng. This means that the first use of any `ecdaa_prng` MUST be preceeded by a call to -`ecdaa_prng_init` on the prng. +`ecdaa_prng_init` (or `ecdaa_prng_init_custom`, see below) on the prng. -The seed for the `ecdaa_prng` is generated using code adapted from Libsodium's -`randombytes_buf`. +In `ecdaa_prng_init`, the seed for the `ecdaa_prng` is generated from Libsodium's +`randombytes_buf` function. A discussion on how this function works and any caveats can be found at Libsodium's webpage. -Specifically, the procedure for using a non-standard random number generator -(e.g. in environments where `/dev/urandom` isn't available but a hardware rng is) -may be useful. + +To use a different function for obtaining cryptographically-secure random data for a seed, +pass the option `-DDISABLE_LIBSODIUM_RNG_SEED_FUNCTION=ON` to CMake (this will remove the dependency on libsodium) +and use the function `ecdaa_prng_init_custom` rather than `ecdaa_prng_init`, +passing in a buffer of cryptographically-strong random bytes of length at least `AMCL_SEED_SIZE`. When an `ecdaa_prng` is no longer needed, `ecdaa_prng_free` should be called on it to securely erase its sensitive memory.