summaryrefslogtreecommitdiffstats
path: root/crypto/rand/rand_lib.c
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/rand_lib.c
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/rand_lib.c')
-rw-r--r--crypto/rand/rand_lib.c97
1 files changed, 97 insertions, 0 deletions
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