提交 da8fc25a 编写于 作者: R Rich Salz

Start to overhaul RAND API

Remove unused rand_hw_xor, MD/EVP indirection
Make rand_pseudo same as rand.
Cleanup formatting and ifdef control
Rename some things:
    - rand_meth to openssl_rand_meth; make it global
    - source file
    - lock/init functions, start per-thread state
    - ossl_meth_init to ossl_rand_init
Put state into RAND_STATE structure
And put OSSL_RAND_STATE into ossl_typ.h
Use "randomness" instead of "entropy"
Reviewed-by: NBen Kaduk <kaduk@mit.edu>
(Merged from https://github.com/openssl/openssl/pull/3758)
上级 71d57be5
LIBS=../../libcrypto
SOURCE[../../libcrypto]=\
md_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c \
ossl_rand.c randfile.c rand_lib.c rand_err.c rand_egd.c \
rand_win.c rand_unix.c rand_vms.c
......@@ -10,37 +10,15 @@
#ifndef HEADER_RAND_LCL_H
# define HEADER_RAND_LCL_H
# define ENTROPY_NEEDED 32 /* require 256 bits = 32 bytes of randomness */
# if !defined(USE_MD5_RAND) && !defined(USE_SHA1_RAND) && !defined(USE_MDC2_RAND) && !defined(USE_MD2_RAND)
# define USE_SHA1_RAND
# endif
/* we require 256 bits of randomness */
# define RANDOMNESS_NEEDED (256 / 8)
# include <openssl/evp.h>
# define MD_Update(a,b,c) EVP_DigestUpdate(a,b,c)
# define MD_Final(a,b) EVP_DigestFinal_ex(a,b,NULL)
# if defined(USE_MD5_RAND)
# include <openssl/md5.h>
# define MD_DIGEST_LENGTH MD5_DIGEST_LENGTH
# define MD_Init(a) EVP_DigestInit_ex(a,EVP_md5(), NULL)
# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_md5(), NULL)
# elif defined(USE_SHA1_RAND)
# include <openssl/sha.h>
# define MD_DIGEST_LENGTH SHA_DIGEST_LENGTH
# define MD_Init(a) EVP_DigestInit_ex(a,EVP_sha1(), NULL)
# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_sha1(), NULL)
# elif defined(USE_MDC2_RAND)
# include <openssl/mdc2.h>
# define MD_DIGEST_LENGTH MDC2_DIGEST_LENGTH
# define MD_Init(a) EVP_DigestInit_ex(a,EVP_mdc2(), NULL)
# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_mdc2(), NULL)
# elif defined(USE_MD2_RAND)
# include <openssl/md2.h>
# define MD_DIGEST_LENGTH MD2_DIGEST_LENGTH
# define MD_Init(a) EVP_DigestInit_ex(a,EVP_md2(), NULL)
# define MD(a,b,c) EVP_Digest(a,b,c,NULL,EVP_md2(), NULL)
# endif
# include <openssl/sha.h>
# define RAND_DIGEST EVP_sha1()
# define RAND_DIGEST_LENGTH SHA_DIGEST_LENGTH
void rand_hw_xor(unsigned char *buf, size_t num);
extern RAND_METHOD openssl_rand_meth;
#endif
......@@ -14,17 +14,19 @@
#include "internal/rand.h"
#include <openssl/engine.h>
#include "internal/thread_once.h"
#include "rand_lcl.h"
#ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref = NULL;
static CRYPTO_RWLOCK *rand_engine_lock = NULL;
static ENGINE *funct_ref;
static CRYPTO_RWLOCK *rand_engine_lock;
#endif
static const RAND_METHOD *default_RAND_meth = NULL;
static CRYPTO_RWLOCK *rand_meth_lock = NULL;
static CRYPTO_ONCE rand_lock_init = CRYPTO_ONCE_STATIC_INIT;
static CRYPTO_RWLOCK *rand_meth_lock;
static const RAND_METHOD *default_RAND_meth;
static CRYPTO_ONCE rand_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_rand_lock_init)
DEFINE_RUN_ONCE_STATIC(do_rand_init)
{
int ret = 1;
#ifndef OPENSSL_NO_ENGINE
......@@ -36,9 +38,22 @@ DEFINE_RUN_ONCE_STATIC(do_rand_lock_init)
return ret;
}
void rand_cleanup_int(void)
{
const RAND_METHOD *meth = default_RAND_meth;
if (meth != NULL && meth->cleanup != NULL)
meth->cleanup();
RAND_set_rand_method(NULL);
#ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
#endif
CRYPTO_THREAD_lock_free(rand_meth_lock);
}
int RAND_set_rand_method(const RAND_METHOD *meth)
{
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
CRYPTO_THREAD_write_lock(rand_meth_lock);
......@@ -55,25 +70,26 @@ const RAND_METHOD *RAND_get_rand_method(void)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
if (!RUN_ONCE(&rand_init, do_rand_init))
return NULL;
CRYPTO_THREAD_write_lock(rand_meth_lock);
if (!default_RAND_meth) {
if (default_RAND_meth == NULL) {
#ifndef OPENSSL_NO_ENGINE
ENGINE *e = ENGINE_get_default_RAND();
if (e) {
default_RAND_meth = ENGINE_get_RAND(e);
if (default_RAND_meth == NULL) {
ENGINE_finish(e);
e = NULL;
}
}
if (e)
ENGINE *e;
/* If we have an engine that can do RAND, use it. */
if ((e = ENGINE_get_default_RAND()) != NULL
&& (tmp_meth = ENGINE_get_RAND(e)) != NULL) {
funct_ref = e;
else
default_RAND_meth = tmp_meth;
} else {
ENGINE_finish(e);
default_RAND_meth = &openssl_rand_meth;
}
#else
default_RAND_meth = &openssl_rand_meth;
#endif
default_RAND_meth = RAND_OpenSSL();
}
tmp_meth = default_RAND_meth;
CRYPTO_THREAD_unlock(rand_meth_lock);
......@@ -85,10 +101,10 @@ int RAND_set_rand_engine(ENGINE *engine)
{
const RAND_METHOD *tmp_meth = NULL;
if (!RUN_ONCE(&rand_lock_init, do_rand_lock_init))
if (!RUN_ONCE(&rand_init, do_rand_init))
return 0;
if (engine) {
if (engine != NULL) {
if (!ENGINE_init(engine))
return 0;
tmp_meth = ENGINE_get_RAND(engine);
......@@ -106,55 +122,48 @@ int RAND_set_rand_engine(ENGINE *engine)
}
#endif
void rand_cleanup_int(void)
{
const RAND_METHOD *meth = default_RAND_meth;
if (meth && meth->cleanup)
meth->cleanup();
RAND_set_rand_method(NULL);
CRYPTO_THREAD_lock_free(rand_meth_lock);
#ifndef OPENSSL_NO_ENGINE
CRYPTO_THREAD_lock_free(rand_engine_lock);
#endif
}
void RAND_seed(const void *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth && meth->seed)
if (meth->seed != NULL)
meth->seed(buf, num);
}
void RAND_add(const void *buf, int num, double entropy)
void RAND_add(const void *buf, int num, double randomness)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth && meth->add)
meth->add(buf, num, entropy);
if (meth->add != NULL)
meth->add(buf, num, randomness);
}
int RAND_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth && meth->bytes)
if (meth->bytes != NULL)
return meth->bytes(buf, num);
RANDerr(RAND_F_RAND_BYTES, RAND_R_FUNC_NOT_IMPLEMENTED);
return (-1);
return -1;
}
#if OPENSSL_API_COMPAT < 0x10100000L
int RAND_pseudo_bytes(unsigned char *buf, int num)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth && meth->pseudorand)
if (meth->pseudorand != NULL)
return meth->pseudorand(buf, num);
return (-1);
return -1;
}
#endif
int RAND_status(void)
{
const RAND_METHOD *meth = RAND_get_rand_method();
if (meth && meth->status)
if (meth->status != NULL)
return meth->status();
return 0;
}
......@@ -91,7 +91,7 @@ int RAND_poll(void)
RAND_add(&curr_uid, sizeof curr_uid, 1);
curr_uid = 0;
for (i = 0; i < (ENTROPY_NEEDED * 4); i++) {
for (i = 0; i < (RANDOMNESS_NEEDED * 4); i++) {
/*
* burn some cpu; hope for interrupts, cache collisions, bus
* interference, etc.
......@@ -127,7 +127,7 @@ int RAND_poll(void)
unsigned long l;
pid_t curr_pid = getpid();
# if defined(DEVRANDOM) || (!defined(OPENSS_NO_EGD) && defined(DEVRANDOM_EGD))
unsigned char tmpbuf[ENTROPY_NEEDED];
unsigned char tmpbuf[RANDOMNESS_NEEDED];
int n = 0;
# endif
# ifdef DEVRANDOM
......@@ -144,12 +144,12 @@ int RAND_poll(void)
# ifdef DEVRANDOM
memset(randomstats, 0, sizeof(randomstats));
/*
* Use a random entropy pool device. Linux, FreeBSD and OpenBSD have
* Use a randomness device. Linux, FreeBSD and OpenBSD have
* this. Use /dev/urandom if you can as /dev/random may block if it runs
* out of random entries.
*/
for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < ENTROPY_NEEDED); i++) {
for (i = 0; (i < OSSL_NELEM(randomfiles)) && (n < RANDOMNESS_NEEDED); i++) {
if ((fd = open(randomfiles[i], O_RDONLY
# ifdef O_NONBLOCK
| O_NONBLOCK
......@@ -229,7 +229,7 @@ int RAND_poll(void)
if (try_read) {
r = read(fd, (unsigned char *)tmpbuf + n,
ENTROPY_NEEDED - n);
RANDOMNESS_NEEDED - n);
if (r > 0)
n += r;
} else
......@@ -246,7 +246,7 @@ int RAND_poll(void)
}
while ((r > 0 ||
(errno == EINTR || errno == EAGAIN)) && usec != 0
&& n < ENTROPY_NEEDED);
&& n < RANDOMNESS_NEEDED);
close(fd);
}
......@@ -255,16 +255,15 @@ int RAND_poll(void)
# if !defined(OPENSSL_NO_EGD) && defined(DEVRANDOM_EGD)
/*
* Use an EGD socket to read entropy from an EGD or PRNGD entropy
* collecting daemon.
* Use an EGD socket to read randomness from the daemon.
*/
for (egdsocket = egdsockets; *egdsocket && n < ENTROPY_NEEDED;
for (egdsocket = egdsockets; *egdsocket && n < RANDOMNESS_NEEDED;
egdsocket++) {
int r;
r = RAND_query_egd_bytes(*egdsocket, (unsigned char *)tmpbuf + n,
ENTROPY_NEEDED - n);
RANDOMNESS_NEEDED - n);
if (r > 0)
n += r;
}
......
......@@ -7,16 +7,11 @@
* https://www.openssl.org/source/license.html
*/
/*
* Modified by VMS Software, Inc (2016)
* Eliminate looping through all processes (performance)
* Add additional randomizations using rand() function
*/
#include <openssl/rand.h>
#include "rand_lcl.h"
#include "e_os.h"
#if defined(OPENSSL_SYS_VMS)
# include <openssl/rand.h>
# include "rand_lcl.h"
# include <descrip.h>
# include <jpidef.h>
# include <ssdef.h>
......@@ -34,9 +29,9 @@
# define PTR_T __void_ptr64
# pragma pointer_size save
# pragma pointer_size 32
# else /* __INITIAL_POINTER_SIZE == 64 */
# else
# define PTR_T void *
# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
# endif
static struct items_data_st {
short length, code; /* length is number of bytes */
......@@ -52,27 +47,22 @@ static struct items_data_st {
{4, JPI$_PPGCNT},
{4, JPI$_WSPEAK},
{4, JPI$_FINALEXC},
{0, 0} /* zero terminated */
{0, 0}
};
int RAND_poll(void)
{
/* determine the number of items in the JPI array */
struct items_data_st item_entry;
int item_entry_count = sizeof(items_data)/sizeof(item_entry);
int item_entry_count = OSSL_NELEM(items_data);
/* Create the JPI itemlist array to hold item_data content */
struct {
short length, code;
int *buffer;
int *retlen;
} item[item_entry_count], *pitem; /* number of entries in items_data */
} item[item_entry_count], *pitem;
struct items_data_st *pitems_data;
int data_buffer[(item_entry_count*2)+4]; /* 8 bytes per entry max */
int data_buffer[(item_entry_count * 2) + 4]; /* 8 bytes per entry max */
int iosb[2];
int sys_time[2];
int *ptr;
......@@ -80,53 +70,46 @@ int RAND_poll(void)
int tmp_length = 0;
int total_length = 0;
pitems_data = items_data;
pitem = item;
/* Setup itemlist for GETJPI */
while (pitems_data->length) {
pitems_data = items_data;
for (pitem = item; pitems_data->length != 0; pitem++) {
pitem->length = pitems_data->length;
pitem->code = pitems_data->code;
pitem->buffer = &data_buffer[total_length];
pitem->retlen = 0;
/* total_length is in longwords */
total_length += pitems_data->length/4;
total_length += pitems_data->length / 4;
pitems_data++;
pitem ++;
}
pitem->length = pitem->code = 0;
/* Fill data_buffer with various info bits from this process */
/* and twist that data to seed the SSL random number init */
if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) != SS$_NORMAL)
return 0;
if (sys$getjpiw(EFN$C_ENF, NULL, NULL, item, &iosb, 0, 0) == SS$_NORMAL) {
for (i = 0; i < total_length; i++) {
sys$gettim((struct _generic_64 *)&sys_time[0]);
srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i);
/* Now twist that data to seed the SSL random number init */
for (i = 0; i < total_length; i++) {
sys$gettim((struct _generic_64 *)&sys_time[0]);
srand(sys_time[0] * data_buffer[0] * data_buffer[1] + i);
if (i == (total_length - 1)) { /* for JPI$_FINALEXC */
ptr = &data_buffer[i];
for (j = 0; j < 4; j++) {
data_buffer[i + j] = ptr[j];
/* OK to use rand() just to scramble the seed */
data_buffer[i + j] ^= (sys_time[0] ^ rand());
tmp_length++;
}
} else {
if (i == (total_length - 1)) { /* for JPI$_FINALEXC */
ptr = &data_buffer[i];
for (j = 0; j < 4; j++) {
data_buffer[i + j] = ptr[j];
/* OK to use rand() just to scramble the seed */
data_buffer[i] ^= (sys_time[0] ^ rand());
data_buffer[i + j] ^= (sys_time[0] ^ rand());
tmp_length++;
}
} else {
/* OK to use rand() just to scramble the seed */
data_buffer[i] ^= (sys_time[0] ^ rand());
}
total_length += (tmp_length - 1);
/* size of seed is total_length*4 bytes (64bytes) */
RAND_add((PTR_T) data_buffer, total_length*4, total_length * 2);
} else {
return 0;
}
total_length += (tmp_length - 1);
/* size of seed is total_length*4 bytes (64bytes) */
RAND_add((PTR_T)data_buffer, total_length * 4, total_length * 2);
return 1;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册