summaryrefslogtreecommitdiffstats
path: root/crypto/rand
diff options
context:
space:
mode:
authorDr. Stephen Henson <steve@openssl.org>2011-05-26 14:19:19 +0000
committerDr. Stephen Henson <steve@openssl.org>2011-05-26 14:19:19 +0000
commit7207eca1ee06ad4b5b5ab7b16e57f5f4f61606dd (patch)
tree807dd0dc17677e2ba0a464548ac94096a4ca6933 /crypto/rand
parent9c34782478f00faba7bac87bd03a0f4f1ee53747 (diff)
The first of many changes to make OpenSSL 1.0.1 FIPS capable.
Add static build support to openssl utility. Add new "fips" option to Configure. Make use of installed fipsld and fips_standalone_sha1 Initialise FIPS error callbacks, locking and DRBG. Doesn't do anything much yet: no crypto is redirected to the FIPS module. Doesn't completely build either but the openssl utility can enter FIPS mode: which doesn't do anything much either.
Diffstat (limited to 'crypto/rand')
-rw-r--r--crypto/rand/rand.h4
-rw-r--r--crypto/rand/rand_lib.c97
2 files changed, 101 insertions, 0 deletions
diff --git a/crypto/rand/rand.h b/crypto/rand/rand.h
index ac6c021763..24aa7c0cb4 100644
--- a/crypto/rand/rand.h
+++ b/crypto/rand/rand.h
@@ -119,6 +119,10 @@ int RAND_event(UINT, WPARAM, LPARAM);
#endif
+#ifdef OPENSSL_FIPS
+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.
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 3cf9ed5050..655101e0ec 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -70,6 +70,11 @@
#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;
@@ -78,6 +83,10 @@ static const RAND_METHOD *default_RAND_meth = NULL;
int RAND_set_rand_method(const RAND_METHOD *meth)
{
+#ifdef OPENSSL_FIPS
+ if (!FIPS_rand_set_method(meth))
+ return 0;
+#endif
#ifndef OPENSSL_NO_ENGINE
if(funct_ref)
{
@@ -180,3 +189,91 @@ 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)
+ {
+ 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;
+ }
+
+int RAND_init_fips(void)
+ {
+ DRBG_CTX *dctx;
+ size_t plen;
+ unsigned char pers[32], *p;
+ dctx = FIPS_get_default_drbg();
+ FIPS_drbg_init(dctx, NID_aes_256_ctr, DRBG_FLAG_CTR_USE_DF);
+ 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);
+
+ FIPS_drbg_instantiate(dctx, pers, sizeof(pers));
+ FIPS_rand_set_method(FIPS_drbg_method());
+ return 1;
+ }
+
+#endif