summaryrefslogtreecommitdiffstats
path: root/crypto
diff options
context:
space:
mode:
authorKurt Roeckx <kurt@roeckx.be>2017-11-17 15:00:35 +0100
committerDr. Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com>2018-01-29 12:42:06 +0100
commit20928ff635772182fe8696d618a19f9101a5370f (patch)
tree26305c173b7eddf05cbace4a2f4aa750d930c968 /crypto
parent1af66bb7241268f96554136387126d280efab75d (diff)
Add RAND_DRBG_bytes
Reviewed-by: Paul Dale <paul.dale@oracle.com> Reviewed-by: Matthias St. Pierre <Matthias.St.Pierre@ncp-e.com> (Merged from https://github.com/openssl/openssl/pull/4752)
Diffstat (limited to 'crypto')
-rw-r--r--crypto/rand/drbg_lib.c22
-rw-r--r--crypto/rand/rand_lcl.h1
-rw-r--r--crypto/rand/rand_lib.c74
3 files changed, 97 insertions, 0 deletions
diff --git a/crypto/rand/drbg_lib.c b/crypto/rand/drbg_lib.c
index 5d3d0f2fd7..5e6bdceb1e 100644
--- a/crypto/rand/drbg_lib.c
+++ b/crypto/rand/drbg_lib.c
@@ -535,6 +535,28 @@ int RAND_DRBG_generate(RAND_DRBG *drbg, unsigned char *out, size_t outlen,
}
/*
+ * Generates |outlen| random bytes and stores them in |out|. It will
+ * using the given |drbg| to generate the bytes.
+ *
+ * Requires that drbg->lock is already locked for write, if non-null.
+ *
+ * Returns 1 on success 0 on failure.
+ */
+int RAND_DRBG_bytes(RAND_DRBG *drbg, unsigned char *out, size_t outlen)
+{
+ unsigned char *additional = NULL;
+ size_t additional_len;
+ size_t ret;
+
+ additional_len = rand_drbg_get_additional_data(&additional, drbg->max_adinlen);
+ ret = RAND_DRBG_generate(drbg, out, outlen, 0, additional, additional_len);
+ if (additional_len != 0)
+ OPENSSL_secure_clear_free(additional, additional_len);
+
+ return ret;
+}
+
+/*
* Set the RAND_DRBG callbacks for obtaining entropy and nonce.
*
* In the following, the signature and the semantics of the
diff --git a/crypto/rand/rand_lcl.h b/crypto/rand/rand_lcl.h
index 5f859d5376..e3c0b76cde 100644
--- a/crypto/rand/rand_lcl.h
+++ b/crypto/rand/rand_lcl.h
@@ -215,6 +215,7 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
int entropy, size_t min_len, size_t max_len);
void rand_drbg_cleanup_entropy(RAND_DRBG *drbg,
unsigned char *out, size_t outlen);
+size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len);
/* DRBG helpers */
int rand_drbg_restart(RAND_DRBG *drbg,
diff --git a/crypto/rand/rand_lib.c b/crypto/rand/rand_lib.c
index 07f54276d3..3824d93317 100644
--- a/crypto/rand/rand_lib.c
+++ b/crypto/rand/rand_lib.c
@@ -15,6 +15,12 @@
#include <openssl/engine.h>
#include "internal/thread_once.h"
#include "rand_lcl.h"
+#ifdef OPENSSL_SYS_UNIX
+# include <sys/types.h>
+# include <unistd.h>
+# include <sys/time.h>
+#endif
+#include "e_os.h"
#ifndef OPENSSL_NO_ENGINE
/* non-NULL if default_RAND_meth is ENGINE-provided */
@@ -187,6 +193,74 @@ size_t rand_drbg_get_entropy(RAND_DRBG *drbg,
return ret;
}
+/*
+ * Generate additional data that can be used for the drbg. The data does
+ * not need to contain entropy, but it's useful if it contains at least
+ * some bits that are unpredictable.
+ *
+ * Returns 0 on failure.
+ *
+ * On success it allocates a buffer at |*pout| and returns the length of
+ * the data. The buffer should get freed using OPENSSL_secure_clear_free().
+ */
+size_t rand_drbg_get_additional_data(unsigned char **pout, size_t max_len)
+{
+ RAND_POOL *pool;
+ CRYPTO_THREAD_ID thread_id;
+ size_t len;
+#ifdef OPENSSL_SYS_UNIX
+ pid_t pid;
+ struct timespec ts;
+#elif defined(OPENSSL_SYS_WIN32)
+ DWORD pid;
+ FILETIME ft;
+ LARGE_INTEGER pc;
+#endif
+ uint32_t tsc = 0;
+
+ pool = RAND_POOL_new(0, 0, max_len);
+ if (pool == NULL)
+ return 0;
+
+#ifdef OPENSSL_SYS_UNIX
+ pid = getpid();
+ RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0);
+#elif defined(OPENSSL_SYS_WIN32)
+ pid = GetCurrentProcessId();
+ RAND_POOL_add(pool, (unsigned char *)&pid, sizeof(pid), 0);
+#endif
+
+ thread_id = CRYPTO_THREAD_get_current_id();
+ if (thread_id != 0)
+ RAND_POOL_add(pool, (unsigned char *)&thread_id, sizeof(thread_id), 0);
+
+#ifdef OPENSSL_CPUID_OBJ
+ tsc = OPENSSL_rdtsc();
+ if (tsc != 0)
+ RAND_POOL_add(pool, (unsigned char *)&tsc, sizeof(tsc), 0);
+#endif
+
+#ifdef OPENSSL_SYS_UNIX
+ if (tsc == 0 && clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
+ RAND_POOL_add(pool, (unsigned char *)&ts, sizeof(ts), 0);
+ if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
+ RAND_POOL_add(pool, (unsigned char *)&ts, sizeof(ts), 0);
+#elif defined(OPENSSL_SYS_WIN32)
+ if (tsc == 0 && QueryPerformanceCounter(&pc) != 0)
+ RAND_POOL_add(pool, (unsigned char *)&pc, sizeof(pc), 0);
+ GetSystemTimeAsFileTime(&ft);
+ RAND_POOL_add(pool, (unsigned char *)&ft, sizeof(ft), 0);
+#endif
+
+ /* TODO: Use RDSEED? */
+
+ len = RAND_POOL_length(pool);
+ if (len != 0)
+ *pout = RAND_POOL_detach(pool);
+ RAND_POOL_free(pool);
+
+ return len;
+}
/*
* Implements the cleanup_entropy() callback (see RAND_DRBG_set_callbacks())