From 8f3e1165a1ec88bafb7e3ba887fe71d485f5fa2f Mon Sep 17 00:00:00 2001 From: Chris Conlon Date: Thu, 5 May 2016 15:31:25 -0600 Subject: [PATCH] add Whitewood netRandom client library support --- configure.ac | 44 ++++++++++ examples/client/client.c | 26 +++++- examples/echoclient/echoclient.c | 11 +++ examples/echoserver/echoserver.c | 11 +++ examples/server/server.c | 28 +++++- tests/unit.c | 10 +++ testsuite/testsuite.c | 13 +++ wolfcrypt/benchmark/benchmark.c | 18 ++++ wolfcrypt/src/random.c | 141 ++++++++++++++++++++++++++++++- wolfcrypt/test/test.c | 16 ++++ wolfssl/test.h | 8 ++ wolfssl/wolfcrypt/random.h | 10 +++ 12 files changed, 329 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 9a63d5a6c..a46fcc17b 100644 --- a/configure.ac +++ b/configure.ac @@ -1646,6 +1646,49 @@ AC_ARG_WITH([ntru], AM_CONDITIONAL([BUILD_NTRU], [test "x$ENABLED_NTRU" = "xyes"]) +# Whitewood netRandom client library +ENABLED_WNR="no" +trywnrdir="" +AC_ARG_WITH([wnr], + [AS_HELP_STRING([--with-wnr=PATH],[Path to Whitewood netRandom install (default /usr/local)])], + [ + AC_MSG_CHECKING([for Whitewood netRandom]) + CPPFLAGS="$CPPFLAGS -DHAVE_WNR" + LIBS="$LIBS -lwnr" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ wnr_setup(0, 0); ]])], [ wnr_linked=yes ],[ wnr_linked=no ]) + + if test "x$wnr_linked" == "xno" ; then + if test "x$withval" != "xno" ; then + trywnrdir=$withval + fi + if test "x$withval" == "xyes" ; then + trywnrdir="/usr/local" + fi + + LDFLAGS="$AM_LDFLAGS $LDFLAGS -L$trywnrdir/lib" + CPPFLAGS="$CPPFLAGS -I$trywnrdir/include" + + AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include ]], [[ wnr_setup(0, 0); ]])], [ wnr_linked=yes ],[ wnr_linked=no ]) + + if test "x$wnr_linked" == "xno" ; then + AC_MSG_ERROR([Whitewood netRandom isn't found. + If it's already installed, specify its path using --with-wnr=/dir/]) + fi + AC_MSG_RESULT([yes]) + AM_LDFLAGS="$AM_LDFLAGS -L$trywnrdir/lib" + else + AC_MSG_RESULT([yes]) + fi + + AM_CFLAGS="$AM_CFLAGS -DHAVE_WNR" + ENABLED_WNR="yes" + ] +) + +AM_CONDITIONAL([BUILD_WNR], [test "x$ENABLED_WNR" = "xyes"]) + + # SNI AC_ARG_ENABLE([sni], [ --enable-sni Enable SNI (default: disabled)], @@ -2872,6 +2915,7 @@ echo " * Persistent cert cache: $ENABLED_SAVECERT" echo " * Atomic User Record Layer: $ENABLED_ATOMICUSER" echo " * Public Key Callbacks: $ENABLED_PKCALLBACKS" echo " * NTRU: $ENABLED_NTRU" +echo " * Whitewood netRandom: $ENABLED_WNR" echo " * Server Name Indication: $ENABLED_SNI" echo " * ALPN: $ENABLED_ALPN" echo " * Maximum Fragment Length: $ENABLED_MAX_FRAGMENT" diff --git a/examples/client/client.c b/examples/client/client.c index 46b08304f..4a8e15d44 100644 --- a/examples/client/client.c +++ b/examples/client/client.c @@ -502,6 +502,9 @@ static void Usage(void) #ifdef WOLFSSL_TRUST_PEER_CERT printf("-E Path to load trusted peer cert\n"); #endif +#ifdef HAVE_WNR + printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif } THREAD_RETURN WOLFSSL_THREAD client_test(void* args) @@ -588,6 +591,10 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) char* ocspUrl = NULL; #endif +#ifdef HAVE_WNR + const char* wnrConfigFile = wnrConfig; +#endif + int argc = ((func_args*)args)->argc; char** argv = ((func_args*)args)->argv; @@ -620,7 +627,7 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifndef WOLFSSL_VXWORKS while ((ch = mygetopt(argc, argv, - "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:")) + "?gdeDusmNrwRitfxXUPCVh:p:v:l:A:c:k:Z:b:zS:F:L:ToO:aB:W:E:M:q:")) != -1) { switch (ch) { case '?' : @@ -873,6 +880,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) break; + case 'q' : + #ifdef HAVE_WNR + wnrConfigFile = myoptarg; + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -972,6 +985,11 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) InitMemoryTracker(); #endif +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) + err_sys("can't load whitewood net random config file"); +#endif + switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 @@ -1628,6 +1646,12 @@ THREAD_RETURN WOLFSSL_THREAD client_test(void* args) #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } diff --git a/examples/echoclient/echoclient.c b/examples/echoclient/echoclient.c index 6492169be..132b0260c 100644 --- a/examples/echoclient/echoclient.c +++ b/examples/echoclient/echoclient.c @@ -272,6 +272,11 @@ void echoclient_test(void* args) err_sys("Cavium OpenNitroxDevice failed"); #endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif + StartTCP(); args.argc = argc; @@ -291,6 +296,12 @@ void echoclient_test(void* args) #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index fb982af3f..e3937615d 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -411,6 +411,11 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) err_sys("Cavium OpenNitroxDevice failed"); #endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif + StartTCP(); args.argc = argc; @@ -427,6 +432,12 @@ THREAD_RETURN CYASSL_THREAD echoserver_test(void* args) #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } diff --git a/examples/server/server.c b/examples/server/server.c index 890df118a..f6e1006c7 100644 --- a/examples/server/server.c +++ b/examples/server/server.c @@ -242,6 +242,9 @@ static void Usage(void) #ifdef WOLFSSL_TRUST_PEER_CERT printf("-E Path to load trusted peer cert\n"); #endif +#ifdef HAVE_WNR + printf("-q Whitewood config file, default %s\n", wnrConfig); +#endif } THREAD_RETURN CYASSL_THREAD server_test(void* args) @@ -312,6 +315,10 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) char* ocspUrl = NULL; #endif +#ifdef HAVE_WNR + const char* wnrConfigFile = wnrConfig; +#endif + ((func_args*)args)->return_code = -1; /* error state */ #ifdef NO_RSA @@ -343,8 +350,8 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef WOLFSSL_VXWORKS useAnyAddr = 1; #else - while ((ch = mygetopt(argc, argv, "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:")) - != -1) { + while ((ch = mygetopt(argc, argv, + "?jdbstnNufrawPIR:p:v:l:A:c:k:Z:S:oO:D:L:ieB:E:q:")) != -1) { switch (ch) { case '?' : Usage(); @@ -522,6 +529,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) break; #endif + case 'q' : + #ifdef HAVE_WNR + wnrConfigFile = myoptarg; + #endif + break; + default: Usage(); exit(MY_EX_USAGE); @@ -552,6 +565,11 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) InitMemoryTracker(); #endif +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) + err_sys("can't load whitewood net random config file"); +#endif + switch (version) { #ifndef NO_OLD_TLS #ifdef WOLFSSL_ALLOW_SSLV3 @@ -1047,6 +1065,12 @@ THREAD_RETURN CYASSL_THREAD server_test(void* args) #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return args.return_code; } diff --git a/tests/unit.c b/tests/unit.c index 924510792..4b64d1082 100644 --- a/tests/unit.c +++ b/tests/unit.c @@ -60,6 +60,11 @@ int unit_test(int argc, char** argv) err_sys("Cavium OpenNitroxDevice failed"); #endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) + err_sys("Whitewood netRandom global config failed"); +#endif /* HAVE_WNR */ + #ifndef WOLFSSL_TIRTOS ChangeToWolfRoot(); #endif @@ -84,6 +89,11 @@ int unit_test(int argc, char** argv) CspShutdown(CAVIUM_DEV_ID); #endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + return 0; } diff --git a/testsuite/testsuite.c b/testsuite/testsuite.c index e2054ea5a..c342609fa 100644 --- a/testsuite/testsuite.c +++ b/testsuite/testsuite.c @@ -90,6 +90,13 @@ int testsuite_test(int argc, char** argv) err_sys("Cavium OpenNitroxDevice failed"); #endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfig, NULL, 5000) != 0) { + err_sys("Whitewood netRandom global config failed"); + return -1237; + } +#endif /* HAVE_WNR */ + StartTCP(); server_args.argc = argc; @@ -200,6 +207,12 @@ int testsuite_test(int argc, char** argv) #ifdef HAVE_CAVIUM CspShutdown(CAVIUM_DEV_ID); #endif + +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context"); +#endif /* HAVE_WNR */ + printf("\nAll tests passed!\n"); return EXIT_SUCCESS; } diff --git a/wolfcrypt/benchmark/benchmark.c b/wolfcrypt/benchmark/benchmark.c index 7c29588a9..62c8eac43 100644 --- a/wolfcrypt/benchmark/benchmark.c +++ b/wolfcrypt/benchmark/benchmark.c @@ -86,6 +86,10 @@ #endif #include +#ifdef HAVE_WNR + const char* wnrConfigFile = "wnr-example.conf"; +#endif + #if defined(WOLFSSL_MDK_ARM) extern FILE * wolfSSL_fopen(const char *fname, const char *mode) ; #define fopen wolfSSL_fopen @@ -282,6 +286,13 @@ int benchmark_test(void *args) } #endif /* HAVE_CAVIUM */ + #ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { + printf("Whitewood netRandom config init failed\n"); + exit(-1); + } + #endif /* HAVE_WNR */ + #if defined(HAVE_LOCAL_RNG) { int rngRet = wc_InitRng(&rng); @@ -404,6 +415,13 @@ int benchmark_test(void *args) wc_FreeRng(&rng); #endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) { + printf("Failed to free netRandom context\n"); + exit(-1); + } +#endif + #if defined(USE_WOLFSSL_MEMORY) && defined(WOLFSSL_TRACK_MEMORY) ShowMemoryTracker(); #endif diff --git a/wolfcrypt/src/random.c b/wolfcrypt/src/random.c index 015fcea4f..86ce4357e 100644 --- a/wolfcrypt/src/random.c +++ b/wolfcrypt/src/random.c @@ -143,10 +143,17 @@ int wc_FreeRng(WC_RNG* rng) #include #include #else - #if !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ - !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ - !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ - !defined(WOLFSSL_EMBOS) + #ifdef HAVE_WNR + #include + #include + wolfSSL_Mutex wnr_mutex; /* global netRandom mutex */ + int wnr_timeout = 0; /* entropy timeout, mililseconds */ + int wnr_mutex_init = 0; /* flag for mutex init */ + wnr_context* wnr_ctx; /* global netRandom context */ + #elif !defined(NO_DEV_RANDOM) && !defined(CUSTOM_RAND_GENERATE) && \ + !defined(WOLFSSL_GENSEED_FORTEST) && !defined(WOLFSSL_MDK_ARM) && \ + !defined(WOLFSSL_IAR_ARM) && !defined(WOLFSSL_ROWLEY_ARM) && \ + !defined(WOLFSSL_EMBOS) #include #ifndef EBSNET #include @@ -909,6 +916,104 @@ static void CaviumRNG_GenerateBlock(WC_RNG* rng, byte* output, word32 sz) #endif /* HAVE_HASHDRBG || NO_RC4 */ +#ifdef HAVE_WNR + +/* + * Init global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_InitNetRandom(const char* configFile, wnr_hmac_key hmac_cb, int timeout) +{ + if (configFile == NULL || timeout < 0) + return BAD_FUNC_ARG; + + if (wnr_mutex_init > 0) { + WOLFSSL_MSG("netRandom context already created, skipping"); + return 0; + } + + if (InitMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Init Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + wnr_mutex_init = 1; + + if (LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + + /* store entropy timeout */ + wnr_timeout = timeout; + + /* create global wnr_context struct */ + if (wnr_create(&wnr_ctx) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error creating global netRandom context"); + return RNG_FAILURE_E; + } + + /* load config file */ + if (wnr_config_loadf(wnr_ctx, (char*)configFile) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error loading config file into netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* create/init polling mechanism */ + if (wnr_poll_create() != WNR_ERROR_NONE) { + printf("ERROR: wnr_poll_create() failed\n"); + WOLFSSL_MSG("Error initializing netRandom polling mechanism"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + return RNG_FAILURE_E; + } + + /* validate config, set HMAC callback (optional) */ + if (wnr_setup(wnr_ctx, hmac_cb) != WNR_ERROR_NONE) { + WOLFSSL_MSG("Error setting up netRandom context"); + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + wnr_poll_destroy(); + return RNG_FAILURE_E; + } + + UnLockMutex(&wnr_mutex); + + return 0; +} + +/* + * Free global Whitewood netRandom context + * Returns 0 on success, negative on error + */ +int wc_FreeNetRandom(void) +{ + if (wnr_mutex_init > 0) { + + if (LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex"); + return BAD_MUTEX_E; + } + + if (wnr_ctx != NULL) { + wnr_destroy(wnr_ctx); + wnr_ctx = NULL; + } + wnr_poll_destroy(); + + UnLockMutex(&wnr_mutex); + + FreeMutex(&wnr_mutex); + wnr_mutex_init = 0; + } + + return 0; +} + +#endif /* HAVE_WNR */ + + #if defined(HAVE_INTEL_RDGEN) #ifndef _MSC_VER @@ -1457,6 +1562,34 @@ int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) return (err_code == NRF_SUCCESS) ? 0 : -1; } +#elif defined(HAVE_WNR) + + int wc_GenerateSeed(OS_Seed* os, byte* output, word32 sz) + { + if (os == NULL || output == NULL || wnr_ctx == NULL || + wnr_timeout < 0) { + return BAD_FUNC_ARG; + } + + if (wnr_mutex_init == 0) { + WOLFSSL_MSG("netRandom context must be created before use"); + return RNG_FAILURE_E; + } + + if (LockMutex(&wnr_mutex) != 0) { + WOLFSSL_MSG("Bad Lock Mutex wnr_mutex\n"); + return BAD_MUTEX_E; + } + + if (wnr_get_entropy(wnr_ctx, wnr_timeout, output, sz, sz) != + WNR_ERROR_NONE) + return RNG_FAILURE_E; + + UnLockMutex(&wnr_mutex); + + return 0; + } + #elif defined(CUSTOM_RAND_GENERATE) /* Implement your own random generation function diff --git a/wolfcrypt/test/test.c b/wolfcrypt/test/test.c index b776a47aa..32da38dc7 100644 --- a/wolfcrypt/test/test.c +++ b/wolfcrypt/test/test.c @@ -146,6 +146,10 @@ #include "wolfssl/wolfcrypt/mem_track.h" #endif +#ifdef HAVE_WNR + const char* wnrConfigFile = "wnr-example.conf"; +#endif + typedef struct testVector { const char* input; @@ -646,6 +650,13 @@ static int OpenNitroxDevice(int dma_mode,int dev_id) } #endif /* HAVE_CAVIUM */ +#ifdef HAVE_WNR + if (wc_InitNetRandom(wnrConfigFile, NULL, 5000) != 0) { + err_sys("Whitewood netRandom global config failed", -1237); + return -1237; + } +#endif + args.argc = argc; args.argv = argv; @@ -655,6 +666,11 @@ static int OpenNitroxDevice(int dma_mode,int dev_id) CspShutdown(CAVIUM_DEV_ID); #endif +#ifdef HAVE_WNR + if (wc_FreeNetRandom() < 0) + err_sys("Failed to free netRandom context", -1238); +#endif /* HAVE_WNR */ + return args.return_code; } diff --git a/wolfssl/test.h b/wolfssl/test.h index f8dc9d18f..2382db453 100644 --- a/wolfssl/test.h +++ b/wolfssl/test.h @@ -257,6 +257,10 @@ #define cliEccKey "certs/ecc-client-key.pem" #define cliEccCert "certs/client-ecc-cert.pem" #define crlPemDir "certs/crl" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "wnr-example.conf" +#endif #else #define caCert "./certs/ca-cert.pem" #define eccCert "./certs/server-ecc.pem" @@ -271,6 +275,10 @@ #define cliEccKey "./certs/ecc-client-key.pem" #define cliEccCert "./certs/client-ecc-cert.pem" #define crlPemDir "./certs/crl" +#ifdef HAVE_WNR + /* Whitewood netRandom default config file */ + #define wnrConfig "./wnr-example.conf" +#endif #endif typedef struct tcp_ready { diff --git a/wolfssl/wolfcrypt/random.h b/wolfssl/wolfcrypt/random.h index 421203dd9..f047b07f2 100644 --- a/wolfssl/wolfcrypt/random.h +++ b/wolfssl/wolfcrypt/random.h @@ -52,6 +52,10 @@ #include #endif /* HAVE_HASHDRBG || NO_RC4 */ +#ifdef HAVE_WNR + #include +#endif + #if defined(USE_WINDOWS_API) #if defined(_WIN64) typedef unsigned __int64 ProviderHandle; @@ -129,6 +133,12 @@ int wc_GenerateSeed(OS_Seed* os, byte* seed, word32 sz); #endif /* HAVE_HASH_DRBG || NO_RC4 */ +#ifdef HAVE_WNR + /* Whitewood netRandom client library */ + WOLFSSL_API int wc_InitNetRandom(const char*, wnr_hmac_key, int); + WOLFSSL_API int wc_FreeNetRandom(void); +#endif /* HAVE_WNR */ + WOLFSSL_API int wc_InitRng(WC_RNG*); WOLFSSL_API int wc_RNG_GenerateBlock(WC_RNG*, byte*, word32 sz);