Skip to content

Commit

Permalink
Use an initialization flag, and use two different init functions.
Browse files Browse the repository at this point in the history
  • Loading branch information
Zane Beckwith committed Sep 21, 2017
1 parent 974586b commit 848bbc2
Show file tree
Hide file tree
Showing 10 changed files with 165 additions and 81 deletions.
13 changes: 7 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ 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(USE_LIBSODIUM_RNG_SEED_FUNCTION
"Use the default Libsodium-based seed function"
ON)
option(DISABLE_LIBSODIUM_RNG_SEED_FUNCTION
"Disable the default Libsodium-based seed function"
OFF)

project(ecdaa
LANGUAGES C
Expand All @@ -42,10 +42,11 @@ 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(USE_LIBSODIUM_RNG_SEED_FUNCTION)
if(NOT DISABLE_LIBSODIUM_RNG_SEED_FUNCTION)
SET(ECDAA_SEED_LINK_LIBRARY sodium)
SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_LIBSODIUM_RNG_SEED_FUNCTION")
endif(USE_LIBSODIUM_RNG_SEED_FUNCTION)
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/)
Expand Down
48 changes: 41 additions & 7 deletions include/ecdaa/prng.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,37 +28,71 @@ extern "C" {

#include <stddef.h>

#define AMCL_SEED_SIZE 128 // As recommended in AMCL's "rand.c"

enum ecdaa_prng_initialized {
ECDAA_PRNG_INITIALIZED_YES,
ECDAA_PRNG_INITIALIZED_NO
};

/*
* 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` before first use.
* via a call to `ecdaa_prng_init`
* of `ecdaa_prng_init_custom` before first use.
*/
struct ecdaa_prng {
enum ecdaa_prng_initialized initialized;
csprng impl;
};

#ifndef DISABLE_LIBSODIUM_RNG_SEED_FUNCTION

/*
* Properly-seed a `ecdaa_prng`.
* Properly seed 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
*/
void ecdaa_prng_init(struct ecdaa_prng *prng_in);
int ecdaa_prng_init(struct ecdaa_prng *prng_in);

#endif // DISABLE_LIBSODIUM_RNG_SEED_FUNCTION

/*
* Type of function used to obtain a cryptographically-secure seed.
*
* Must be able to provide AMCL_SEED_SIZE crpytographically-strong bytes in a single call.
*
* Returns:
* 0 on success
* non-zero on failure
*/
typedef void (*ecdaa_prng_seed_function_type)(void * const buf, const size_t size);
typedef int (*ecdaa_prng_custom_seed_function_type)(void * const buf, const size_t size);

/*
* Override the default function used to obtain a cryptographically-secure seed.
* Properly seed a `ecdaa_prng`.
*
* MUST be called on a `ecdaa_prng` before first use.
*
* No dynamic memory allocation is performed.
*
* NOTE: This is NOT thread-safe.
* Returns:
* 0 on success
* return value of `custom_func`, if non-zero
*/
void ecdaa_prng_set_seed_function(ecdaa_prng_seed_function_type new_function);
int ecdaa_prng_init_custom(struct ecdaa_prng *prng_in, ecdaa_prng_custom_seed_function_type custom_func);

#ifdef __cplusplus
}
Expand Down
4 changes: 4 additions & 0 deletions src/amcl-extensions/big_256_56.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <amcl/ecp_BN254.h>

#include <assert.h>
#include <stdlib.h>

static void convert_hash_to_big(BIG_256_56 *big_out, hash256 *hash);

Expand Down Expand Up @@ -88,6 +89,9 @@ void big_256_56_mod_mul_and_add(BIG_256_56 *big_out,
void big_256_56_random_mod_order(BIG_256_56 *big_out,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

BIG_256_56 curve_order;
BIG_256_56_rcopy(curve_order, CURVE_Order_BN254);

Expand Down
5 changes: 5 additions & 0 deletions src/credential_BN254.c
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
#include <ecdaa/group_public_key_BN254.h>
#include <ecdaa/prng.h>

#include <stdlib.h>

size_t ecdaa_credential_BN254_length(void)
{
return ECDAA_CREDENTIAL_BN254_LENGTH;
Expand All @@ -46,6 +48,9 @@ int ecdaa_credential_BN254_generate(struct ecdaa_credential_BN254 *cred,
struct ecdaa_member_public_key_BN254 *member_pk,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

int ret = 0;

BIG_256_56 curve_order;
Expand Down
13 changes: 13 additions & 0 deletions src/internal/schnorr.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,15 @@
#include <amcl/amcl.h>

#include <assert.h>
#include <stdlib.h>

void schnorr_keygen(ECP_BN254 *public_out,
BIG_256_56 *private_out,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

big_256_56_random_mod_order(private_out, prng);

ecp_BN254_set_to_generator(public_out);
Expand All @@ -50,6 +54,9 @@ int schnorr_sign(BIG_256_56 *c_out,
BIG_256_56 private_key,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// 1) (Commit 1) Verify basepoint belongs to group
if (0 != ecp_BN254_check_membership(basepoint))
return -1;
Expand Down Expand Up @@ -140,6 +147,9 @@ int credential_schnorr_sign(BIG_256_56 *c_out,
BIG_256_56 credential_random,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// 1) Set generator
ECP_BN254 generator;
ecp_BN254_set_to_generator(&generator);
Expand Down Expand Up @@ -259,6 +269,9 @@ int issuer_schnorr_sign(BIG_256_56 *c_out,
BIG_256_56 issuer_private_key_y,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// 1) Set generator_2
ECP2_BN254 generator_2;
ecp2_BN254_set_to_generator(&generator_2);
Expand Down
5 changes: 5 additions & 0 deletions src/issuer_keypair_BN254.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

#include <ecdaa/group_public_key_BN254.h>

#include <stdlib.h>

size_t ecdaa_issuer_public_key_BN254_length(void) {
return ECDAA_ISSUER_PUBLIC_KEY_BN254_LENGTH;
}
Expand All @@ -38,6 +40,9 @@ int ecdaa_issuer_key_pair_BN254_generate(struct ecdaa_issuer_public_key_BN254 *p
struct ecdaa_issuer_secret_key_BN254 *sk,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// Secret key is
// two random Bignums.
big_256_56_random_mod_order(&sk->x, prng);
Expand Down
4 changes: 4 additions & 0 deletions src/member_keypair_BN254.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "./internal/schnorr.h"

#include <assert.h>
#include <stdlib.h>

size_t ecdaa_member_public_key_BN254_length(void)
{
Expand All @@ -41,6 +42,9 @@ int ecdaa_member_key_pair_BN254_generate(struct ecdaa_member_public_key_BN254 *p
uint32_t nonce_length,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// 1) Generate Schnorr-type keypair,
schnorr_keygen(&pk->Q, &sk->sk, prng);

Expand Down
101 changes: 49 additions & 52 deletions src/prng.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,78 +18,75 @@

#include <ecdaa/prng.h>

#ifdef USE_LIBSODIUM_RNG_SEED_FUNCTION
#ifndef DISABLE_LIBSODIUM_RNG_SEED_FUNCTION

#include <sodium.h>

#include <sodium/randombytes.h>
#include <stdio.h>
#include <stdlib.h>
#if defined(__linux__)
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/random.h>
#include <stdio.h>
#include <stdlib.h>
#endif // defined(__linux__)

static ecdaa_prng_seed_function_type seed_func = &randombytes_buf;
static int sodium_initialized = 0;

static void sodium_init_if_needed(void);
int ecdaa_prng_init(struct ecdaa_prng *prng_in)
{
int ret = 0;

#else // USE_LIBSODIUM_RNG_SEED_FUNCTION
prng_in->initialized = ECDAA_PRNG_INITIALIZED_NO;

static ecdaa_prng_seed_function_type seed_func;
do {
// 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;
}
#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);
if (0 != ret)
break;
}
#endif

#endif // USE_LIBSODIUM_RNG_SEED_FUNCTION
RAND_clean(&prng_in->impl);

void ecdaa_prng_init(struct ecdaa_prng *prng_in)
{
#ifdef USE_LIBSODIUM_RNG_SEED_FUNCTION
sodium_init_if_needed();
#endif
char seed[AMCL_SEED_SIZE];

RAND_clean(&prng_in->impl);
randombytes_buf(seed, AMCL_SEED_SIZE);

char seed[128]; // 128 as recommended in AMCL's "rand.c"
RAND_seed(&prng_in->impl, AMCL_SEED_SIZE, seed);
} while(0);

seed_func(seed, sizeof(seed));
if (0 == ret)
prng_in->initialized = ECDAA_PRNG_INITIALIZED_YES;

RAND_seed(&prng_in->impl, sizeof(seed), seed);
return ret;
}

void ecdaa_prng_set_seed_function(ecdaa_prng_seed_function_type new_function)
{
seed_func = new_function;
}
#endif // DISABLE_LIBSODIUM_RNG_SEED_FUNCTION

#ifdef USE_LIBSODIUM_RNG_SEED_FUNCTION
void sodium_init_if_needed(void)
int ecdaa_prng_init_custom(struct ecdaa_prng *prng_in, ecdaa_prng_custom_seed_function_type custom_func)
{
// 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_initialized) {
if (-1 == sodium_init()) {
fputs("Unable to initialize libsodium random seed source. Aborting", stderr);
abort();
}
#if defined(__linux__) && defined(RNDGETENTCNT)
int fd;
int c;
prng_in->initialized = ECDAA_PRNG_INITIALIZED_NO;

if ((fd = open("/dev/random", O_RDONLY)) != -1) {
if (ioctl(fd, RNDGETENTCNT, &c) == 0 && c < 160) {
fputs("This system doesn't provide enough entropy to quickly generate high-quality random numbers.\n"
"Installing the rng-utils/rng-tools, jitterentropy or haveged packages may help.\n"
"On virtualized Linux environments, also consider using virtio-rng.\n"
"The service will not start until enough entropy has been collected.\n", stderr);
abort();
}
(void) close(fd);
}
#endif // defined(__linux__) && defined(RNDGETENTCNT)
RAND_clean(&prng_in->impl);

char seed[AMCL_SEED_SIZE];

int ret = custom_func(seed, AMCL_SEED_SIZE);
if (0 != ret)
return ret;

RAND_seed(&prng_in->impl, AMCL_SEED_SIZE, seed);

prng_in->initialized = ECDAA_PRNG_INITIALIZED_YES;

sodium_initialized = 1;
}
return 0;
}
#endif // USE_LIBSODIUM_RNG_SEED_FUNCTION
5 changes: 5 additions & 0 deletions src/signature_BN254.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
#include <amcl/pair_BN254.h>
#include <amcl/fp12_BN254.h>

#include <stdlib.h>

size_t ecdaa_signature_BN254_length(void)
{
return ECDAA_SIGNATURE_BN254_LENGTH;
Expand All @@ -45,6 +47,9 @@ int ecdaa_signature_BN254_sign(struct ecdaa_signature_BN254 *signature_out,
struct ecdaa_credential_BN254 *cred,
struct ecdaa_prng *prng)
{
if (ECDAA_PRNG_INITIALIZED_YES != prng->initialized)
abort();

// 1) Choose random l <- Z_p
BIG_256_56 l;
big_256_56_random_mod_order(&l, prng);
Expand Down
Loading

0 comments on commit 848bbc2

Please sign in to comment.