This patch, while retaining PolarSSL 1.0 support, introduces the PolarSSL 1.1
DRBG. This RNG adds a number of features, including support for personalisation
strings and multiple entropy sources.
Personalisation strings have been implemented, based on PID, program name,
place within memory, and a hash of the user's certificate.
The entropy sources used are the platform default ones. Which ones these are
depends on how PolarSSL was built, but usually this includes:
- /dev/urandom or the Windows CryptoAPI RNG
- the HAVEGE RNG
- the output of PolarSSL's hardclock() call (usually RDTSC)
Finally, this patch moves to only one instance of the RNG per OpenVPN
instance, instead of one per keystate
Signed-off-by: Adriaan de Jong
Signed-off-by: Eelse-jan Stutvoet
---
crypto_polarssl.c | 84 ++--
crypto_polarssl.h | 25
ssl.c |5 +++
ssl_backend.h | 10 ++
ssl_polarssl.c| 44 +--
ssl_polarssl.h|2 -
6 files changed, 148 insertions(+), 22 deletions(-)
diff --git a/crypto_polarssl.c b/crypto_polarssl.c
index e7470d5..8eb47db 100644
--- a/crypto_polarssl.c
+++ b/crypto_polarssl.c
@@ -36,12 +36,18 @@
#include "buffer.h"
#include "integer.h"
#include "crypto_backend.h"
+#include "otime.h"
+#include "misc.h"
#include
#include
#include
#include
+#if (POLARSSL_VERSION_NUMBER >= 0x0101)
+#include
+#endif
+
/*
*
* Hardware engine support. Allows loading/unloading of engines.
@@ -143,7 +149,6 @@ show_available_engines ()
"available\n");
}
-
/*
*
* Random number functions, used in cases where we want
@@ -153,29 +158,88 @@ show_available_engines ()
*
*/
-int
-rand_bytes (uint8_t *output, int len)
+/*
+ * Initialise the given ctr_drbg context, using a personalisation string and an
+ * entropy gathering function.
+ */
+#if (POLARSSL_VERSION_NUMBER >= 0x0101)
+ctr_drbg_context * rand_ctx_get()
+{
+ static entropy_context ec = {0};
+ static ctr_drbg_context cd_ctx = {0};
+ static bool rand_initialised = false;
+
+ if (!rand_initialised)
+{
+ struct gc_arena gc = gc_new();
+ struct buffer pers_string = alloc_buf_gc(100, );
+
+ /*
+ * Personalisation string, should be as unique as possible (see NIST
+ * 800-90 section 8.7.1). We have very little information at this stage.
+ * Include Program Name, memory address of the context and PID.
+ */
+ buf_printf(_string, "OpenVPN %0u %p %s", openvpn_getpid(), _ctx,
time_string(0, 0, 0, ));
+
+ /* Initialise PolarSSL RNG, and built-in entropy sources */
+ entropy_init();
+
+ if (0 != ctr_drbg_init(_ctx, entropy_func, , BPTR(_string),
BLEN(_string)))
+msg (M_FATAL, "Failed to initialize random generator");
+
+ gc_free();
+ rand_initialised = true;
+ }
+
+ return _ctx;
+}
+
+#else /* (POLARSSL_VERSION_NUMBER < 0x0101) */
+
+havege_state * rand_ctx_get()
{
static havege_state hs = {0};
- static bool hs_initialised = false;
- const int int_size = sizeof(int);
+ static bool rand_initialised = false;
- if (!hs_initialised)
+ if (!rand_initialised)
{
/* Initialise PolarSSL RNG */
havege_init();
- hs_initialised = true;
+ rand_initialised = true;
}
+ return
+}
+
+#endif /* (POLARSSL_VERSION_NUMBER >= 0x0101) */
+
+int
+rand_bytes (uint8_t *output, int len)
+{
+#if (POLARSSL_VERSION_NUMBER >= 0x0101)
+ ctr_drbg_context *rng_ctx = rand_ctx_get();
+#else /* (POLARSSL_VERSION_NUMBER >= 0x0101) */
+ havege_state *rng_ctx = rand_ctx_get();
+#endif /* (POLARSSL_VERSION_NUMBER >= 0x0101) */
+
while (len > 0)
{
- const int blen = min_int (len, int_size);
- const int rand_int = havege_rand();
-
+#if (POLARSSL_VERSION_NUMBER >= 0x0101)
+ const size_t blen = min_int (len, CTR_DRBG_MAX_REQUEST);
+ if (0 != ctr_drbg_random(rng_ctx, output, blen))
+ return 0;
+
+#else /* (POLARSSL_VERSION_NUMBER >= 0x0101) */
+ const size_t blen = min_int (len, sizeof(int));
+ const int rand_int = havege_rand(rng_ctx);
memcpy (output, _int, blen);
+
+#endif /* (POLARSSL_VERSION_NUMBER >= 0x0101) */
+
output += blen;
len -= blen;
}
+
return 1;
}
diff --git a/crypto_polarssl.h b/crypto_polarssl.h
index 358483a..2f303db 100644
--- a/crypto_polarssl.h
+++ b/crypto_polarssl.h
@@ -30,9 +30,16 @@
#ifndef CRYPTO_POLARSSL_H_
#define CRYPTO_POLARSSL_H_
+#include
#include
#include
+#if (POLARSSL_VERSION_NUMBER >= 0x0101)
+# include
+#else
+# include
+#endif
+
/** Generic cipher key type %context. */
typedef cipher_info_t cipher_kt_t;
@@ -71,4 +78,22 @@ typedef md_context_t hmac_ctx_t;
#define SHA_DIGEST_LENGTH 20
#define DES_KEY_LENGTH 8
+/**
+ * Returns a singleton instance of the PolarSSL random number generator.
+ *
+ * For PolarSSL