summaryrefslogtreecommitdiff
path: root/main/openssl/crypto/rand
diff options
context:
space:
mode:
Diffstat (limited to 'main/openssl/crypto/rand')
-rw-r--r--main/openssl/crypto/rand/md_rand.c55
-rw-r--r--main/openssl/crypto/rand/rand.h10
-rw-r--r--main/openssl/crypto/rand/rand_err.c7
-rw-r--r--main/openssl/crypto/rand/rand_lib.c130
-rw-r--r--main/openssl/crypto/rand/rand_unix.c108
-rw-r--r--main/openssl/crypto/rand/randfile.c4
6 files changed, 256 insertions, 58 deletions
diff --git a/main/openssl/crypto/rand/md_rand.c b/main/openssl/crypto/rand/md_rand.c
index b2f04ff1..dd291637 100644
--- a/main/openssl/crypto/rand/md_rand.c
+++ b/main/openssl/crypto/rand/md_rand.c
@@ -109,6 +109,8 @@
*
*/
+#define OPENSSL_FIPSEVP
+
#ifdef MD_RAND_DEBUG
# ifndef NDEBUG
# define NDEBUG
@@ -121,10 +123,10 @@
#include "e_os.h"
+#include <openssl/crypto.h>
#include <openssl/rand.h>
#include "rand_lcl.h"
-#include <openssl/crypto.h>
#include <openssl/err.h>
#ifdef BN_DEBUG
@@ -157,13 +159,14 @@ const char RAND_version[]="RAND" OPENSSL_VERSION_PTEXT;
static void ssleay_rand_cleanup(void);
static void ssleay_rand_seed(const void *buf, int num);
static void ssleay_rand_add(const void *buf, int num, double add_entropy);
-static int ssleay_rand_bytes(unsigned char *buf, int num);
+static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo);
+static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num);
static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num);
static int ssleay_rand_status(void);
RAND_METHOD rand_ssleay_meth={
ssleay_rand_seed,
- ssleay_rand_bytes,
+ ssleay_rand_nopseudo_bytes,
ssleay_rand_cleanup,
ssleay_rand_add,
ssleay_rand_pseudo_bytes,
@@ -328,7 +331,7 @@ static void ssleay_rand_seed(const void *buf, int num)
ssleay_rand_add(buf, num, (double)num);
}
-static int ssleay_rand_bytes(unsigned char *buf, int num)
+static int ssleay_rand_bytes(unsigned char *buf, int num, int pseudo)
{
static volatile int stirred_pool = 0;
int i,j,k,st_num,st_idx;
@@ -377,8 +380,11 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
* are fed into the hash function and the results are kept in the
* global 'md'.
*/
-
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+ /* NB: in FIPS mode we are already under a lock */
+ if (!FIPS_mode())
+#endif
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
/* prevent ssleay_rand_bytes() from trying to obtain the lock again */
CRYPTO_w_lock(CRYPTO_LOCK_RAND2);
@@ -457,7 +463,10 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
/* before unlocking, we must clear 'crypto_lock_rand' */
crypto_lock_rand = 0;
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+ if (!FIPS_mode())
+#endif
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
while (num > 0)
{
@@ -509,15 +518,23 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
MD_Init(&m);
MD_Update(&m,(unsigned char *)&(md_c[0]),sizeof(md_c));
MD_Update(&m,local_md,MD_DIGEST_LENGTH);
- CRYPTO_w_lock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+ if (!FIPS_mode())
+#endif
+ CRYPTO_w_lock(CRYPTO_LOCK_RAND);
MD_Update(&m,md,MD_DIGEST_LENGTH);
MD_Final(&m,md);
- CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
+#ifdef OPENSSL_FIPS
+ if (!FIPS_mode())
+#endif
+ CRYPTO_w_unlock(CRYPTO_LOCK_RAND);
EVP_MD_CTX_cleanup(&m);
if (ok)
return(1);
- else
+ else if (pseudo)
+ return 0;
+ else
{
RANDerr(RAND_F_SSLEAY_RAND_BYTES,RAND_R_PRNG_NOT_SEEDED);
ERR_add_error_data(1, "You need to read the OpenSSL FAQ, "
@@ -526,22 +543,16 @@ static int ssleay_rand_bytes(unsigned char *buf, int num)
}
}
+static int ssleay_rand_nopseudo_bytes(unsigned char *buf, int num)
+ {
+ return ssleay_rand_bytes(buf, num, 0);
+ }
+
/* pseudo-random bytes that are guaranteed to be unique but not
unpredictable */
static int ssleay_rand_pseudo_bytes(unsigned char *buf, int num)
{
- int ret;
- unsigned long err;
-
- ret = RAND_bytes(buf, num);
- if (ret == 0)
- {
- err = ERR_peek_error();
- if (ERR_GET_LIB(err) == ERR_LIB_RAND &&
- ERR_GET_REASON(err) == RAND_R_PRNG_NOT_SEEDED)
- ERR_clear_error();
- }
- return (ret);
+ return ssleay_rand_bytes(buf, num, 1);
}
static int ssleay_rand_status(void)
diff --git a/main/openssl/crypto/rand/rand.h b/main/openssl/crypto/rand/rand.h
index ac6c0217..bb5520e8 100644
--- a/main/openssl/crypto/rand/rand.h
+++ b/main/openssl/crypto/rand/rand.h
@@ -119,6 +119,11 @@ int RAND_event(UINT, WPARAM, LPARAM);
#endif
+#ifdef OPENSSL_FIPS
+void RAND_set_fips_drbg_type(int type, int flags);
+int RAND_init_fips(void);
+#endif
+
/* BEGIN ERROR CODES */
/* The following lines are auto generated by the script mkerr.pl. Any changes
* made after this point may be overwritten when the script is next run.
@@ -129,9 +134,14 @@ void ERR_load_RAND_strings(void);
/* Function codes. */
#define RAND_F_RAND_GET_RAND_METHOD 101
+#define RAND_F_RAND_INIT_FIPS 102
#define RAND_F_SSLEAY_RAND_BYTES 100
/* Reason codes. */
+#define RAND_R_DUAL_EC_DRBG_DISABLED 104
+#define RAND_R_ERROR_INITIALISING_DRBG 102
+#define RAND_R_ERROR_INSTANTIATING_DRBG 103
+#define RAND_R_NO_FIPS_RANDOM_METHOD_SET 101
#define RAND_R_PRNG_NOT_SEEDED 100
#ifdef __cplusplus
diff --git a/main/openssl/crypto/rand/rand_err.c b/main/openssl/crypto/rand/rand_err.c
index 03cda4dd..c4c80fc8 100644
--- a/main/openssl/crypto/rand/rand_err.c
+++ b/main/openssl/crypto/rand/rand_err.c
@@ -1,6 +1,6 @@
/* crypto/rand/rand_err.c */
/* ====================================================================
- * Copyright (c) 1999-2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2011 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -71,12 +71,17 @@
static ERR_STRING_DATA RAND_str_functs[]=
{
{ERR_FUNC(RAND_F_RAND_GET_RAND_METHOD), "RAND_get_rand_method"},
+{ERR_FUNC(RAND_F_RAND_INIT_FIPS), "RAND_init_fips"},
{ERR_FUNC(RAND_F_SSLEAY_RAND_BYTES), "SSLEAY_RAND_BYTES"},
{0,NULL}
};
static ERR_STRING_DATA RAND_str_reasons[]=
{
+{ERR_REASON(RAND_R_DUAL_EC_DRBG_DISABLED),"dual ec drbg disabled"},
+{ERR_REASON(RAND_R_ERROR_INITIALISING_DRBG),"error initialising drbg"},
+{ERR_REASON(RAND_R_ERROR_INSTANTIATING_DRBG),"error instantiating drbg"},
+{ERR_REASON(RAND_R_NO_FIPS_RANDOM_METHOD_SET),"no fips random method set"},
{ERR_REASON(RAND_R_PRNG_NOT_SEEDED) ,"PRNG not seeded"},
{0,NULL}
};
diff --git a/main/openssl/crypto/rand/rand_lib.c b/main/openssl/crypto/rand/rand_lib.c
index 513e3389..5ac0e14c 100644
--- a/main/openssl/crypto/rand/rand_lib.c
+++ b/main/openssl/crypto/rand/rand_lib.c
@@ -60,10 +60,16 @@
#include <time.h>
#include "cryptlib.h"
#include <openssl/rand.h>
+
#ifndef OPENSSL_NO_ENGINE
#include <openssl/engine.h>
#endif
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#include <openssl/fips_rand.h>
+#endif
+
#ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
static ENGINE *funct_ref =NULL;
@@ -174,3 +180,127 @@ int RAND_status(void)
return meth->status();
return 0;
}
+
+#ifdef OPENSSL_FIPS
+
+/* FIPS DRBG initialisation code. This sets up the DRBG for use by the
+ * rest of OpenSSL.
+ */
+
+/* Entropy gatherer: use standard OpenSSL PRNG to seed (this will gather
+ * entropy internally through RAND_poll().
+ */
+
+static size_t drbg_get_entropy(DRBG_CTX *ctx, unsigned char **pout,
+ int entropy, size_t min_len, size_t max_len)
+ {
+ /* Round up request to multiple of block size */
+ min_len = ((min_len + 19) / 20) * 20;
+ *pout = OPENSSL_malloc(min_len);
+ if (!*pout)
+ return 0;
+ if (RAND_SSLeay()->bytes(*pout, min_len) <= 0)
+ {
+ OPENSSL_free(*pout);
+ *pout = NULL;
+ return 0;
+ }
+ return min_len;
+ }
+
+static void drbg_free_entropy(DRBG_CTX *ctx, unsigned char *out, size_t olen)
+ {
+ if (out)
+ {
+ OPENSSL_cleanse(out, olen);
+ OPENSSL_free(out);
+ }
+ }
+
+/* Set "additional input" when generating random data. This uses the
+ * current PID, a time value and a counter.
+ */
+
+static size_t drbg_get_adin(DRBG_CTX *ctx, unsigned char **pout)
+ {
+ /* Use of static variables is OK as this happens under a lock */
+ static unsigned char buf[16];
+ static unsigned long counter;
+ FIPS_get_timevec(buf, &counter);
+ *pout = buf;
+ return sizeof(buf);
+ }
+
+/* RAND_add() and RAND_seed() pass through to OpenSSL PRNG so it is
+ * correctly seeded by RAND_poll().
+ */
+
+static int drbg_rand_add(DRBG_CTX *ctx, const void *in, int inlen,
+ double entropy)
+ {
+ RAND_SSLeay()->add(in, inlen, entropy);
+ return 1;
+ }
+
+static int drbg_rand_seed(DRBG_CTX *ctx, const void *in, int inlen)
+ {
+ RAND_SSLeay()->seed(in, inlen);
+ return 1;
+ }
+
+#ifndef OPENSSL_DRBG_DEFAULT_TYPE
+#define OPENSSL_DRBG_DEFAULT_TYPE NID_aes_256_ctr
+#endif
+#ifndef OPENSSL_DRBG_DEFAULT_FLAGS
+#define OPENSSL_DRBG_DEFAULT_FLAGS DRBG_FLAG_CTR_USE_DF
+#endif
+
+static int fips_drbg_type = OPENSSL_DRBG_DEFAULT_TYPE;
+static int fips_drbg_flags = OPENSSL_DRBG_DEFAULT_FLAGS;
+
+void RAND_set_fips_drbg_type(int type, int flags)
+ {
+ fips_drbg_type = type;
+ fips_drbg_flags = flags;
+ }
+
+int RAND_init_fips(void)
+ {
+ DRBG_CTX *dctx;
+ size_t plen;
+ unsigned char pers[32], *p;
+#ifndef OPENSSL_ALLOW_DUAL_EC_DRBG
+ if (fips_drbg_type >> 16)
+ {
+ RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_DUAL_EC_DRBG_DISABLED);
+ return 0;
+ }
+#endif
+
+ dctx = FIPS_get_default_drbg();
+ if (FIPS_drbg_init(dctx, fips_drbg_type, fips_drbg_flags) <= 0)
+ {
+ RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_ERROR_INITIALISING_DRBG);
+ return 0;
+ }
+
+ FIPS_drbg_set_callbacks(dctx,
+ drbg_get_entropy, drbg_free_entropy, 20,
+ drbg_get_entropy, drbg_free_entropy);
+ FIPS_drbg_set_rand_callbacks(dctx, drbg_get_adin, 0,
+ drbg_rand_seed, drbg_rand_add);
+ /* Personalisation string: a string followed by date time vector */
+ strcpy((char *)pers, "OpenSSL DRBG2.0");
+ plen = drbg_get_adin(dctx, &p);
+ memcpy(pers + 16, p, plen);
+
+ if (FIPS_drbg_instantiate(dctx, pers, sizeof(pers)) <= 0)
+ {
+ RANDerr(RAND_F_RAND_INIT_FIPS, RAND_R_ERROR_INSTANTIATING_DRBG);
+ return 0;
+ }
+ FIPS_rand_set_method(FIPS_drbg_method());
+ return 1;
+ }
+
+#endif
diff --git a/main/openssl/crypto/rand/rand_unix.c b/main/openssl/crypto/rand/rand_unix.c
index e9ead3a5..e3a65571 100644
--- a/main/openssl/crypto/rand/rand_unix.c
+++ b/main/openssl/crypto/rand/rand_unix.c
@@ -133,47 +133,87 @@
# define FD_SETSIZE (8*sizeof(fd_set))
#endif
-#ifdef __VOS__
+#if defined(OPENSSL_SYS_VOS)
+
+/* The following algorithm repeatedly samples the real-time clock
+ (RTC) to generate a sequence of unpredictable data. The algorithm
+ relies upon the uneven execution speed of the code (due to factors
+ such as cache misses, interrupts, bus activity, and scheduling) and
+ upon the rather large relative difference between the speed of the
+ clock and the rate at which it can be read.
+
+ If this code is ported to an environment where execution speed is
+ more constant or where the RTC ticks at a much slower rate, or the
+ clock can be read with fewer instructions, it is likely that the
+ results would be far more predictable.
+
+ As a precaution, we generate 4 times the minimum required amount of
+ seed data. */
+
int RAND_poll(void)
{
- unsigned char buf[ENTROPY_NEEDED];
+ short int code;
+ gid_t curr_gid;
pid_t curr_pid;
uid_t curr_uid;
- static int first=1;
- int i;
- long rnd = 0;
+ int i, k;
struct timespec ts;
- unsigned seed;
-
-/* The VOS random() function starts from a static seed so its
- initial value is predictable. If random() returns the
- initial value, reseed it with dynamic data. The VOS
- real-time clock has a granularity of 1 nsec so it should be
- reasonably difficult to predict its exact value. Do not
- gratuitously reseed the PRNG because other code in this
- process or thread may be using it. */
-
- if (first) {
- first = 0;
- rnd = random ();
- if (rnd == 1804289383) {
- clock_gettime (CLOCK_REALTIME, &ts);
- curr_pid = getpid();
- curr_uid = getuid();
- seed = ts.tv_sec ^ ts.tv_nsec ^ curr_pid ^ curr_uid;
- srandom (seed);
- }
- }
+ unsigned char v;
- for (i = 0; i < sizeof(buf); i++) {
- if (i % 4 == 0)
- rnd = random();
- buf[i] = rnd;
- rnd >>= 8;
- }
- RAND_add(buf, sizeof(buf), ENTROPY_NEEDED);
- memset(buf, 0, sizeof(buf));
+#ifdef OPENSSL_SYS_VOS_HPPA
+ long duration;
+ extern void s$sleep (long *_duration, short int *_code);
+#else
+#ifdef OPENSSL_SYS_VOS_IA32
+ long long duration;
+ extern void s$sleep2 (long long *_duration, short int *_code);
+#else
+#error "Unsupported Platform."
+#endif /* OPENSSL_SYS_VOS_IA32 */
+#endif /* OPENSSL_SYS_VOS_HPPA */
+
+ /* Seed with the gid, pid, and uid, to ensure *some*
+ variation between different processes. */
+
+ curr_gid = getgid();
+ RAND_add (&curr_gid, sizeof curr_gid, 1);
+ curr_gid = 0;
+
+ curr_pid = getpid();
+ RAND_add (&curr_pid, sizeof curr_pid, 1);
+ curr_pid = 0;
+
+ curr_uid = getuid();
+ RAND_add (&curr_uid, sizeof curr_uid, 1);
+ curr_uid = 0;
+ for (i=0; i<(ENTROPY_NEEDED*4); i++)
+ {
+ /* burn some cpu; hope for interrupts, cache
+ collisions, bus interference, etc. */
+ for (k=0; k<99; k++)
+ ts.tv_nsec = random ();
+
+#ifdef OPENSSL_SYS_VOS_HPPA
+ /* sleep for 1/1024 of a second (976 us). */
+ duration = 1;
+ s$sleep (&duration, &code);
+#else
+#ifdef OPENSSL_SYS_VOS_IA32
+ /* sleep for 1/65536 of a second (15 us). */
+ duration = 1;
+ s$sleep2 (&duration, &code);
+#endif /* OPENSSL_SYS_VOS_IA32 */
+#endif /* OPENSSL_SYS_VOS_HPPA */
+
+ /* get wall clock time. */
+ clock_gettime (CLOCK_REALTIME, &ts);
+
+ /* take 8 bits */
+ v = (unsigned char) (ts.tv_nsec % 256);
+ RAND_add (&v, sizeof v, 1);
+ v = 0;
+ }
return 1;
}
#elif defined __OpenBSD__
diff --git a/main/openssl/crypto/rand/randfile.c b/main/openssl/crypto/rand/randfile.c
index bc7d9c58..7f142807 100644
--- a/main/openssl/crypto/rand/randfile.c
+++ b/main/openssl/crypto/rand/randfile.c
@@ -57,7 +57,9 @@
*/
/* We need to define this to get macros like S_IFBLK and S_IFCHR */
+#if !defined(OPENSSL_SYS_VXWORKS)
#define _XOPEN_SOURCE 500
+#endif
#include <errno.h>
#include <stdio.h>
@@ -137,7 +139,7 @@ int RAND_load_file(const char *file, long bytes)
in=fopen(file,"rb");
#endif
if (in == NULL) goto err;
-#if defined(S_IFBLK) && defined(S_IFCHR) && !defined(OPNESSL_NO_POSIX_IO)
+#if defined(S_IFBLK) && defined(S_IFCHR) && !defined(OPENSSL_NO_POSIX_IO)
if (sb.st_mode & (S_IFBLK | S_IFCHR)) {
/* this file is a device. we don't want read an infinite number
* of bytes from a random device, nor do we want to use buffered