mirror of
https://github.com/NLnetLabs/unbound.git
synced 2025-12-20 23:00:56 -05:00
fixes for random number badness (lack of entropy and SIGFPE from RAND_cleanup
too early). git-svn-id: file:///svn/unbound/trunk@907 be551aaa-1e26-0410-a405-d3ace91eadb9
This commit is contained in:
parent
e5196b25ae
commit
c8f2bf0333
15 changed files with 193 additions and 113 deletions
|
|
@ -76,6 +76,9 @@
|
||||||
/* Define to 1 if you have the <openssl/err.h> header file. */
|
/* Define to 1 if you have the <openssl/err.h> header file. */
|
||||||
#undef HAVE_OPENSSL_ERR_H
|
#undef HAVE_OPENSSL_ERR_H
|
||||||
|
|
||||||
|
/* Define to 1 if you have the <openssl/rand.h> header file. */
|
||||||
|
#undef HAVE_OPENSSL_RAND_H
|
||||||
|
|
||||||
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
/* Define to 1 if you have the <openssl/ssl.h> header file. */
|
||||||
#undef HAVE_OPENSSL_SSL_H
|
#undef HAVE_OPENSSL_SSL_H
|
||||||
|
|
||||||
|
|
@ -332,6 +335,10 @@
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL_RAND_H
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ATTR_FORMAT
|
#ifdef HAVE_ATTR_FORMAT
|
||||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||||
|
|
|
||||||
58
configure
vendored
58
configure
vendored
|
|
@ -20887,6 +20887,64 @@ fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
|
for ac_header in openssl/rand.h
|
||||||
|
do
|
||||||
|
as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh`
|
||||||
|
{ echo "$as_me:$LINENO: checking for $ac_header" >&5
|
||||||
|
echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6; }
|
||||||
|
if { as_var=$as_ac_Header; eval "test \"\${$as_var+set}\" = set"; }; then
|
||||||
|
echo $ECHO_N "(cached) $ECHO_C" >&6
|
||||||
|
else
|
||||||
|
cat >conftest.$ac_ext <<_ACEOF
|
||||||
|
/* confdefs.h. */
|
||||||
|
_ACEOF
|
||||||
|
cat confdefs.h >>conftest.$ac_ext
|
||||||
|
cat >>conftest.$ac_ext <<_ACEOF
|
||||||
|
/* end confdefs.h. */
|
||||||
|
$ac_includes_default
|
||||||
|
|
||||||
|
#include <$ac_header>
|
||||||
|
_ACEOF
|
||||||
|
rm -f conftest.$ac_objext
|
||||||
|
if { (ac_try="$ac_compile"
|
||||||
|
case "(($ac_try" in
|
||||||
|
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
|
||||||
|
*) ac_try_echo=$ac_try;;
|
||||||
|
esac
|
||||||
|
eval "echo \"\$as_me:$LINENO: $ac_try_echo\"") >&5
|
||||||
|
(eval "$ac_compile") 2>conftest.er1
|
||||||
|
ac_status=$?
|
||||||
|
grep -v '^ *+' conftest.er1 >conftest.err
|
||||||
|
rm -f conftest.er1
|
||||||
|
cat conftest.err >&5
|
||||||
|
echo "$as_me:$LINENO: \$? = $ac_status" >&5
|
||||||
|
(exit $ac_status); } && {
|
||||||
|
test -z "$ac_c_werror_flag" ||
|
||||||
|
test ! -s conftest.err
|
||||||
|
} && test -s conftest.$ac_objext; then
|
||||||
|
eval "$as_ac_Header=yes"
|
||||||
|
else
|
||||||
|
echo "$as_me: failed program was:" >&5
|
||||||
|
sed 's/^/| /' conftest.$ac_ext >&5
|
||||||
|
|
||||||
|
eval "$as_ac_Header=no"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
|
||||||
|
fi
|
||||||
|
ac_res=`eval echo '${'$as_ac_Header'}'`
|
||||||
|
{ echo "$as_me:$LINENO: result: $ac_res" >&5
|
||||||
|
echo "${ECHO_T}$ac_res" >&6; }
|
||||||
|
if test `eval echo '${'$as_ac_Header'}'` = yes; then
|
||||||
|
cat >>confdefs.h <<_ACEOF
|
||||||
|
#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1
|
||||||
|
_ACEOF
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
done
|
||||||
|
|
||||||
|
|
||||||
# check for thread library.
|
# check for thread library.
|
||||||
|
|
||||||
# Check whether --with-pthreads was given.
|
# Check whether --with-pthreads was given.
|
||||||
|
|
|
||||||
|
|
@ -483,6 +483,7 @@ AC_ARG_WITH(ssl, AC_HELP_STRING([--with-ssl=pathname],
|
||||||
fi
|
fi
|
||||||
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
AC_CHECK_HEADERS([openssl/ssl.h],,, [AC_INCLUDES_DEFAULT])
|
||||||
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
|
AC_CHECK_HEADERS([openssl/err.h],,, [AC_INCLUDES_DEFAULT])
|
||||||
|
AC_CHECK_HEADERS([openssl/rand.h],,, [AC_INCLUDES_DEFAULT])
|
||||||
|
|
||||||
# check for thread library.
|
# check for thread library.
|
||||||
AC_ARG_WITH(pthreads, AC_HELP_STRING([--with-pthreads],
|
AC_ARG_WITH(pthreads, AC_HELP_STRING([--with-pthreads],
|
||||||
|
|
@ -719,6 +720,10 @@ AH_BOTTOM([
|
||||||
#include <openssl/err.h>
|
#include <openssl/err.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef HAVE_OPENSSL_RAND_H
|
||||||
|
#include <openssl/rand.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_ATTR_FORMAT
|
#ifdef HAVE_ATTR_FORMAT
|
||||||
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
# define ATTR_FORMAT(archetype, string_index, first_to_check) \
|
||||||
__attribute__ ((format (archetype, string_index, first_to_check)))
|
__attribute__ ((format (archetype, string_index, first_to_check)))
|
||||||
|
|
|
||||||
|
|
@ -375,5 +375,6 @@ daemon_delete(struct daemon* daemon)
|
||||||
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
|
CRYPTO_cleanup_all_ex_data(); /* safe, no more threads right now */
|
||||||
ERR_remove_state(0);
|
ERR_remove_state(0);
|
||||||
ERR_free_strings();
|
ERR_free_strings();
|
||||||
|
RAND_cleanup();
|
||||||
checklock_stop();
|
checklock_stop();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -906,17 +906,10 @@ worker_init(struct worker* worker, struct config_file *cfg,
|
||||||
} else { /* !do_sigs */
|
} else { /* !do_sigs */
|
||||||
worker->comsig = 0;
|
worker->comsig = 0;
|
||||||
}
|
}
|
||||||
/* init random(), large table size. */
|
|
||||||
if(!(worker->rndstate = (struct ub_randstate*)calloc(1,
|
|
||||||
sizeof(struct ub_randstate)))) {
|
|
||||||
log_err("malloc rndtable failed.");
|
|
||||||
worker_delete(worker);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
||||||
(((unsigned int)worker->thread_num)<<17);
|
(((unsigned int)worker->thread_num)<<17);
|
||||||
/* shift thread_num so it does not match out pid bits */
|
/* shift thread_num so it does not match out pid bits */
|
||||||
if(!ub_initstate(seed, worker->rndstate, RND_STATE_SIZE)) {
|
if(!(worker->rndstate = ub_initstate(seed, NULL))) {
|
||||||
seed = 0;
|
seed = 0;
|
||||||
log_err("could not init random numbers.");
|
log_err("could not init random numbers.");
|
||||||
worker_delete(worker);
|
worker_delete(worker);
|
||||||
|
|
@ -1012,7 +1005,6 @@ worker_delete(struct worker* worker)
|
||||||
comm_point_delete(worker->cmd_com);
|
comm_point_delete(worker->cmd_com);
|
||||||
comm_base_delete(worker->base);
|
comm_base_delete(worker->base);
|
||||||
ub_randfree(worker->rndstate);
|
ub_randfree(worker->rndstate);
|
||||||
free(worker->rndstate);
|
|
||||||
/* close fds after deleting commpoints, to be sure.
|
/* close fds after deleting commpoints, to be sure.
|
||||||
Also epoll does not like closing fd before event_del */
|
Also epoll does not like closing fd before event_del */
|
||||||
if(worker->cmd_send_fd != -1)
|
if(worker->cmd_send_fd != -1)
|
||||||
|
|
|
||||||
|
|
@ -59,9 +59,6 @@ struct listen_port;
|
||||||
struct ub_randstate;
|
struct ub_randstate;
|
||||||
struct regional;
|
struct regional;
|
||||||
|
|
||||||
/** size of table used for random numbers. large to be more secure. */
|
|
||||||
#define RND_STATE_SIZE 256
|
|
||||||
|
|
||||||
/** worker commands */
|
/** worker commands */
|
||||||
enum worker_commands {
|
enum worker_commands {
|
||||||
/** make the worker quit */
|
/** make the worker quit */
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,9 @@
|
||||||
- made openssl entropy warning more silent for library use. Needs
|
- made openssl entropy warning more silent for library use. Needs
|
||||||
verbosity 1 now.
|
verbosity 1 now.
|
||||||
- fixup forgotten locks for rbtree_searches on ctx->query tree.
|
- fixup forgotten locks for rbtree_searches on ctx->query tree.
|
||||||
|
- random generator cleanup - RND_STATE_SIZE removed, and instead
|
||||||
|
a super-rnd can be passed at init to chain init random states.
|
||||||
|
- test also does lock checks if available.
|
||||||
|
|
||||||
25 January 2008: Wouter
|
25 January 2008: Wouter
|
||||||
- added tpkg for asynclook and library use.
|
- added tpkg for asynclook and library use.
|
||||||
|
|
|
||||||
|
|
@ -103,6 +103,8 @@ struct ub_val_ctx {
|
||||||
struct module_stack mods;
|
struct module_stack mods;
|
||||||
/** local authority zones */
|
/** local authority zones */
|
||||||
struct local_zones* local_zones;
|
struct local_zones* local_zones;
|
||||||
|
/** random state used to seed new random state structures */
|
||||||
|
struct ub_randstate* seed_rnd;
|
||||||
|
|
||||||
/** next query number (to try) to use */
|
/** next query number (to try) to use */
|
||||||
int next_querynum;
|
int next_querynum;
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@
|
||||||
#include "util/module.h"
|
#include "util/module.h"
|
||||||
#include "util/regional.h"
|
#include "util/regional.h"
|
||||||
#include "util/log.h"
|
#include "util/log.h"
|
||||||
|
#include "util/random.h"
|
||||||
#include "util/net_help.h"
|
#include "util/net_help.h"
|
||||||
#include "services/modstack.h"
|
#include "services/modstack.h"
|
||||||
#include "services/localzone.h"
|
#include "services/localzone.h"
|
||||||
|
|
@ -62,6 +63,7 @@ struct ub_val_ctx*
|
||||||
ub_val_ctx_create()
|
ub_val_ctx_create()
|
||||||
{
|
{
|
||||||
struct ub_val_ctx* ctx = (struct ub_val_ctx*)calloc(1, sizeof(*ctx));
|
struct ub_val_ctx* ctx = (struct ub_val_ctx*)calloc(1, sizeof(*ctx));
|
||||||
|
unsigned int seed;
|
||||||
if(!ctx) {
|
if(!ctx) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -71,7 +73,17 @@ ub_val_ctx_create()
|
||||||
verbosity = 0; /* errors only */
|
verbosity = 0; /* errors only */
|
||||||
log_init(NULL, 0, NULL); /* logs to stderr */
|
log_init(NULL, 0, NULL); /* logs to stderr */
|
||||||
alloc_init(&ctx->superalloc, NULL, 0);
|
alloc_init(&ctx->superalloc, NULL, 0);
|
||||||
|
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid();
|
||||||
|
if(!(ctx->seed_rnd = ub_initstate(seed, NULL))) {
|
||||||
|
seed = 0;
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
|
free(ctx);
|
||||||
|
errno = ENOMEM;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
seed = 0;
|
||||||
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->qqpipe) == -1) {
|
if(socketpair(AF_UNIX, SOCK_STREAM, 0, ctx->qqpipe) == -1) {
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -79,6 +91,7 @@ ub_val_ctx_create()
|
||||||
int e = errno;
|
int e = errno;
|
||||||
close(ctx->qqpipe[0]);
|
close(ctx->qqpipe[0]);
|
||||||
close(ctx->qqpipe[1]);
|
close(ctx->qqpipe[1]);
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
errno = e;
|
errno = e;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -92,6 +105,7 @@ ub_val_ctx_create()
|
||||||
close(ctx->rrpipe[1]);
|
close(ctx->rrpipe[1]);
|
||||||
close(ctx->qqpipe[0]);
|
close(ctx->qqpipe[0]);
|
||||||
close(ctx->qqpipe[1]);
|
close(ctx->qqpipe[1]);
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
errno = e;
|
errno = e;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -105,6 +119,7 @@ ub_val_ctx_create()
|
||||||
close(ctx->rrpipe[1]);
|
close(ctx->rrpipe[1]);
|
||||||
close(ctx->qqpipe[0]);
|
close(ctx->qqpipe[0]);
|
||||||
close(ctx->qqpipe[1]);
|
close(ctx->qqpipe[1]);
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -116,6 +131,7 @@ ub_val_ctx_create()
|
||||||
close(ctx->qqpipe[0]);
|
close(ctx->qqpipe[0]);
|
||||||
close(ctx->qqpipe[1]);
|
close(ctx->qqpipe[1]);
|
||||||
free(ctx->env);
|
free(ctx->env);
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -210,6 +226,7 @@ ub_val_ctx_delete(struct ub_val_ctx* ctx)
|
||||||
config_delete(ctx->env->cfg);
|
config_delete(ctx->env->cfg);
|
||||||
free(ctx->env);
|
free(ctx->env);
|
||||||
}
|
}
|
||||||
|
ub_randfree(ctx->seed_rnd);
|
||||||
alloc_clear(&ctx->superalloc);
|
alloc_clear(&ctx->superalloc);
|
||||||
traverse_postorder(&ctx->queries, delq, NULL);
|
traverse_postorder(&ctx->queries, delq, NULL);
|
||||||
free(ctx);
|
free(ctx);
|
||||||
|
|
|
||||||
|
|
@ -61,9 +61,6 @@
|
||||||
#include "util/data/msgreply.h"
|
#include "util/data/msgreply.h"
|
||||||
#include "util/data/msgencode.h"
|
#include "util/data/msgencode.h"
|
||||||
|
|
||||||
/** size of table used for random numbers. large to be more secure. */
|
|
||||||
#define RND_STATE_SIZE 256
|
|
||||||
|
|
||||||
/** handle new query command for bg worker */
|
/** handle new query command for bg worker */
|
||||||
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
static void handle_newq(struct libworker* w, uint8_t* buf, uint32_t len);
|
||||||
|
|
||||||
|
|
@ -79,7 +76,6 @@ libworker_delete(struct libworker* w)
|
||||||
ldns_buffer_free(w->env->scratch_buffer);
|
ldns_buffer_free(w->env->scratch_buffer);
|
||||||
regional_destroy(w->env->scratch);
|
regional_destroy(w->env->scratch);
|
||||||
ub_randfree(w->env->rnd);
|
ub_randfree(w->env->rnd);
|
||||||
free(w->env->rnd);
|
|
||||||
free(w->env);
|
free(w->env);
|
||||||
}
|
}
|
||||||
outside_network_delete(w->back);
|
outside_network_delete(w->back);
|
||||||
|
|
@ -118,21 +114,17 @@ libworker_setup(struct ub_val_ctx* ctx, int is_bg)
|
||||||
libworker_delete(w);
|
libworker_delete(w);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
w->env->rnd = (struct ub_randstate*)calloc(1, sizeof(*w->env->rnd));
|
|
||||||
if(!w->env->rnd) {
|
|
||||||
libworker_delete(w);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
w->env->worker = (struct worker*)w;
|
w->env->worker = (struct worker*)w;
|
||||||
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
seed = (unsigned int)time(NULL) ^ (unsigned int)getpid() ^
|
||||||
(((unsigned int)w->thread_num)<<17);
|
(((unsigned int)w->thread_num)<<17);
|
||||||
seed ^= (unsigned int)w->env->alloc->next_id;
|
seed ^= (unsigned int)w->env->alloc->next_id;
|
||||||
if(!w->is_bg || w->is_bg_thread) {
|
if(!w->is_bg || w->is_bg_thread) {
|
||||||
/* put lock around RAND*() */
|
|
||||||
lock_basic_lock(&ctx->cfglock);
|
lock_basic_lock(&ctx->cfglock);
|
||||||
}
|
}
|
||||||
if(!ub_initstate(seed, w->env->rnd, RND_STATE_SIZE)) {
|
if(!(w->env->rnd = ub_initstate(seed, ctx->seed_rnd))) {
|
||||||
|
if(!w->is_bg || w->is_bg_thread) {
|
||||||
lock_basic_unlock(&ctx->cfglock);
|
lock_basic_unlock(&ctx->cfglock);
|
||||||
|
}
|
||||||
seed = 0;
|
seed = 0;
|
||||||
libworker_delete(w);
|
libworker_delete(w);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
||||||
|
|
@ -147,6 +147,9 @@ struct ext_thr_info {
|
||||||
int numq;
|
int numq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** if true, we are testing against 'localhost' and extra checking is done */
|
||||||
|
static int q_is_localhost = 0;
|
||||||
|
|
||||||
/** check result structure for the 'correct' answer */
|
/** check result structure for the 'correct' answer */
|
||||||
static void
|
static void
|
||||||
ext_check_result(const char* desc, int err, struct ub_val_result* result)
|
ext_check_result(const char* desc, int err, struct ub_val_result* result)
|
||||||
|
|
@ -156,7 +159,7 @@ ext_check_result(const char* desc, int err, struct ub_val_result* result)
|
||||||
printf("%s: error result is NULL.\n", desc);
|
printf("%s: error result is NULL.\n", desc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
/* DEBUG */
|
if(q_is_localhost) {
|
||||||
if(strcmp(result->qname, "localhost") != 0) {
|
if(strcmp(result->qname, "localhost") != 0) {
|
||||||
printf("%s: error result has wrong qname.\n", desc);
|
printf("%s: error result has wrong qname.\n", desc);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
@ -190,7 +193,8 @@ ext_check_result(const char* desc, int err, struct ub_val_result* result)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(result->secure || result->bogus) {
|
if(result->secure || result->bogus) {
|
||||||
printf("%s: error result->secure or bogus is set.\n", desc);
|
printf("%s: error result->secure or bogus is set.\n",
|
||||||
|
desc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(result->data[0] == NULL) {
|
if(result->data[0] == NULL) {
|
||||||
|
|
@ -202,10 +206,12 @@ ext_check_result(const char* desc, int err, struct ub_val_result* result)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if(result->len[1] != 0 || result->data[1] != NULL) {
|
if(result->len[1] != 0 || result->data[1] != NULL) {
|
||||||
printf("%s: error result->data[1] or len[1] is wrong.\n", desc);
|
printf("%s: error result->data[1] or len[1] is "
|
||||||
|
"wrong.\n", desc);
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** extended bg result callback, this function is ub_val_callback_t */
|
/** extended bg result callback, this function is ub_val_callback_t */
|
||||||
static void
|
static void
|
||||||
|
|
@ -291,6 +297,8 @@ ext_test(struct ub_val_ctx* ctx, int argc, char** argv)
|
||||||
{
|
{
|
||||||
struct ext_thr_info inf[NUMTHR];
|
struct ext_thr_info inf[NUMTHR];
|
||||||
int i;
|
int i;
|
||||||
|
if(argc == 1 && strcmp(argv[0], "localhost") == 0)
|
||||||
|
q_is_localhost = 1;
|
||||||
printf("extended test start (%d threads)\n", NUMTHR);
|
printf("extended test start (%d threads)\n", NUMTHR);
|
||||||
for(i=0; i<NUMTHR; i++) {
|
for(i=0; i<NUMTHR; i++) {
|
||||||
/* 0 = this, 1 = library bg worker */
|
/* 0 = this, 1 = library bg worker */
|
||||||
|
|
|
||||||
|
|
@ -363,12 +363,12 @@ infra_test()
|
||||||
static void
|
static void
|
||||||
rnd_test()
|
rnd_test()
|
||||||
{
|
{
|
||||||
struct ub_randstate r;
|
struct ub_randstate* r;
|
||||||
int num = 100, i;
|
int num = 100, i;
|
||||||
long int a[100];
|
long int a[100];
|
||||||
unit_assert( ub_initstate((unsigned)time(NULL), &r, 256) );
|
unit_assert( (r = ub_initstate((unsigned)time(NULL), NULL)) );
|
||||||
for(i=0; i<num; i++) {
|
for(i=0; i<num; i++) {
|
||||||
a[i] = ub_random(&r);
|
a[i] = ub_random(r);
|
||||||
unit_assert(a[i] >= 0);
|
unit_assert(a[i] >= 0);
|
||||||
unit_assert((size_t)a[i] <= (size_t)RAND_MAX);
|
unit_assert((size_t)a[i] <= (size_t)RAND_MAX);
|
||||||
if(i > 5)
|
if(i > 5)
|
||||||
|
|
@ -376,7 +376,7 @@ rnd_test()
|
||||||
a[i] != a[i-3] || a[i] != a[i-4] ||
|
a[i] != a[i-3] || a[i] != a[i-4] ||
|
||||||
a[i] != a[i-5] || a[i] != a[i-6]);
|
a[i] != a[i-5] || a[i] != a[i-6]);
|
||||||
}
|
}
|
||||||
ub_randfree(&r);
|
ub_randfree(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
BIN
testdata/05-asynclook.tpkg
vendored
BIN
testdata/05-asynclook.tpkg
vendored
Binary file not shown.
|
|
@ -53,7 +53,7 @@
|
||||||
* Struct with per-thread random state.
|
* Struct with per-thread random state.
|
||||||
* Keeps SSL types away from the header file.
|
* Keeps SSL types away from the header file.
|
||||||
*/
|
*/
|
||||||
struct ub_hiddenstate {
|
struct ub_randstate {
|
||||||
/** key used for arc4random generation */
|
/** key used for arc4random generation */
|
||||||
RC4_KEY rc4;
|
RC4_KEY rc4;
|
||||||
/** keeps track of key usage */
|
/** keeps track of key usage */
|
||||||
|
|
@ -68,17 +68,22 @@ struct ub_hiddenstate {
|
||||||
|
|
||||||
/** reseed random generator */
|
/** reseed random generator */
|
||||||
static void
|
static void
|
||||||
ub_arc4random_stir(struct ub_hiddenstate* s)
|
ub_arc4random_stir(struct ub_randstate* s, struct ub_randstate* from)
|
||||||
{
|
{
|
||||||
unsigned char rand_buf[SEED_SIZE];
|
unsigned char rand_buf[SEED_SIZE];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
memset(&s->rc4, 0, sizeof(s->rc4));
|
memset(&s->rc4, 0, sizeof(s->rc4));
|
||||||
memset(rand_buf, 0xc, sizeof(rand_buf));
|
memset(rand_buf, 0xc, sizeof(rand_buf));
|
||||||
|
if (from) {
|
||||||
|
for(i=0; i<SEED_SIZE; i++)
|
||||||
|
rand_buf[i] = (unsigned char)ub_random(from);
|
||||||
|
} else {
|
||||||
if (RAND_bytes(rand_buf, (int)sizeof(rand_buf)) <= 0)
|
if (RAND_bytes(rand_buf, (int)sizeof(rand_buf)) <= 0)
|
||||||
fatal_exit("Couldn't obtain random bytes (error %ld)",
|
fatal_exit("Couldn't obtain random bytes (error %ld)",
|
||||||
ERR_get_error());
|
ERR_get_error());
|
||||||
RC4_set_key(&s->rc4, (int)sizeof(rand_buf), rand_buf);
|
}
|
||||||
|
RC4_set_key(&s->rc4, SEED_SIZE, rand_buf);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Discard early keystream, as per recommendations in:
|
* Discard early keystream, as per recommendations in:
|
||||||
|
|
@ -92,14 +97,13 @@ ub_arc4random_stir(struct ub_hiddenstate* s)
|
||||||
s->rc4_ready = REKEY_BYTES;
|
s->rc4_ready = REKEY_BYTES;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
struct ub_randstate*
|
||||||
ub_initstate(unsigned int seed, struct ub_randstate* state,
|
ub_initstate(unsigned int seed, struct ub_randstate* from)
|
||||||
unsigned long ATTR_UNUSED(n))
|
|
||||||
{
|
{
|
||||||
state->s = calloc(1, sizeof(*state->s));
|
struct ub_randstate* s = (struct ub_randstate*)calloc(1, sizeof(*s));
|
||||||
if(!state->s) {
|
if(!s) {
|
||||||
log_err("malloc failure in random init");
|
log_err("malloc failure in random init");
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* RAND_ is threadsafe, by the way */
|
/* RAND_ is threadsafe, by the way */
|
||||||
|
|
@ -112,37 +116,36 @@ ub_initstate(unsigned int seed, struct ub_randstate* state,
|
||||||
memmove(buf+i*sizeof(seed), &v, sizeof(seed));
|
memmove(buf+i*sizeof(seed), &v, sizeof(seed));
|
||||||
v = v*seed + (unsigned int)i;
|
v = v*seed + (unsigned int)i;
|
||||||
}
|
}
|
||||||
log_hex("seed with", buf, 256);
|
|
||||||
RAND_seed(buf, 256);
|
RAND_seed(buf, 256);
|
||||||
if(!RAND_status()) {
|
if(!RAND_status()) {
|
||||||
log_err("Random generator has no entropy (error %ld)",
|
log_err("Random generator has no entropy (error %ld)",
|
||||||
ERR_get_error());
|
ERR_get_error());
|
||||||
return 0;
|
return NULL;
|
||||||
}
|
}
|
||||||
verbose(VERB_OPS, "openssl has no entropy, seeding with time");
|
verbose(VERB_OPS, "openssl has no entropy, seeding with time");
|
||||||
}
|
}
|
||||||
ub_arc4random_stir(state->s);
|
ub_arc4random_stir(s, from);
|
||||||
return 1;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
long int
|
long int
|
||||||
ub_random(struct ub_randstate* state)
|
ub_random(struct ub_randstate* s)
|
||||||
{
|
{
|
||||||
unsigned int r = 0;
|
unsigned int r = 0;
|
||||||
if (state->s->rc4_ready <= 0) {
|
if (s->rc4_ready <= 0) {
|
||||||
ub_arc4random_stir(state->s);
|
ub_arc4random_stir(s, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
RC4(&state->s->rc4, sizeof(r),
|
RC4(&s->rc4, sizeof(r),
|
||||||
(unsigned char *)&r, (unsigned char *)&r);
|
(unsigned char *)&r, (unsigned char *)&r);
|
||||||
state->s->rc4_ready -= sizeof(r);
|
s->rc4_ready -= sizeof(r);
|
||||||
return (long int)((r) % (((unsigned)RAND_MAX + 1)));
|
return (long int)((r) % (((unsigned)RAND_MAX + 1)));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ub_randfree(struct ub_randstate* state)
|
ub_randfree(struct ub_randstate* s)
|
||||||
{
|
{
|
||||||
if(state)
|
if(s)
|
||||||
free(state->s);
|
free(s);
|
||||||
RAND_cleanup();
|
/* user app must do RAND_cleanup(); */
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,27 +42,22 @@
|
||||||
* initialisation routine.
|
* initialisation routine.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
struct ub_hiddenstate;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* random state structure.
|
* random state structure.
|
||||||
*/
|
*/
|
||||||
struct ub_randstate {
|
struct ub_randstate;
|
||||||
/** state hidden type. */
|
|
||||||
struct ub_hiddenstate* s;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize a random generator state for use
|
* Initialize a random generator state for use
|
||||||
* @param seed: seed value to create state contents.
|
* @param seed: seed value to create state contents.
|
||||||
* (ignored for arc4random).
|
* (ignored for arc4random).
|
||||||
* @param state: struct allocated by caller.
|
* @param from: if not NULL, the seed is taken from this random structure.
|
||||||
* @param n: size of state->state. 8, 32, 64, 128, or 256 bytes.
|
* can be used to seed random states via a parent-random-state that
|
||||||
* (ignored for arc4random).
|
* is itself seeded with entropy.
|
||||||
* @return false alloc failure.
|
* @return new state or NULL alloc failure.
|
||||||
*/
|
*/
|
||||||
int ub_initstate(unsigned int seed, struct ub_randstate* state,
|
struct ub_randstate* ub_initstate(unsigned int seed,
|
||||||
unsigned long n);
|
struct ub_randstate* from);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate next random number from the state passed along.
|
* Generate next random number from the state passed along.
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue