aboutsummaryrefslogtreecommitdiffstats
path: root/src/libstrongswan/plugins
diff options
context:
space:
mode:
authorMartin Willi <martin@revosec.ch>2013-01-04 16:07:31 +0100
committerMartin Willi <martin@revosec.ch>2013-01-11 10:45:14 +0100
commitb9148ea232f24d2f751588aa3045a6bc98bff1f8 (patch)
treebaf4968a6a7dc3f157b67a6d7b09d7328229f8e0 /src/libstrongswan/plugins
parent9fe24b004d6d1a64d0e2f106d39cf7a8fbd3179d (diff)
downloadstrongswan-b9148ea232f24d2f751588aa3045a6bc98bff1f8.tar.bz2
strongswan-b9148ea232f24d2f751588aa3045a6bc98bff1f8.tar.xz
Provide RNG_STRONG quality in rdrand by forcing PRNG reseed after every sample
Diffstat (limited to 'src/libstrongswan/plugins')
-rw-r--r--src/libstrongswan/plugins/rdrand/rdrand_plugin.c1
-rw-r--r--src/libstrongswan/plugins/rdrand/rdrand_rng.c69
2 files changed, 69 insertions, 1 deletions
diff --git a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
index fc9c6202d..4462c5e0e 100644
--- a/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
+++ b/src/libstrongswan/plugins/rdrand/rdrand_plugin.c
@@ -97,6 +97,7 @@ METHOD(plugin_t, get_features, int,
static plugin_feature_t f[] = {
PLUGIN_REGISTER(RNG, rdrand_rng_create),
PLUGIN_PROVIDE(RNG, RNG_WEAK),
+ PLUGIN_PROVIDE(RNG, RNG_STRONG),
};
*features = f;
return countof(f);
diff --git a/src/libstrongswan/plugins/rdrand/rdrand_rng.c b/src/libstrongswan/plugins/rdrand/rdrand_rng.c
index 64ce12509..6ad0da29c 100644
--- a/src/libstrongswan/plugins/rdrand/rdrand_rng.c
+++ b/src/libstrongswan/plugins/rdrand/rdrand_rng.c
@@ -39,6 +39,12 @@ struct private_rdrand_rng_t {
#define MAX_TRIES 16
/**
+ * After how many bytes should we reseed for RNG_STRONG
+ * (must be a power of two >= 8)
+ */
+#define FORCE_RESEED 16
+
+/**
* Get a two byte word using RDRAND
*/
static bool rdrand16(u_int16_t *out)
@@ -121,6 +127,37 @@ static bool rdrand8(u_int8_t *out)
return TRUE;
}
+/**
+ * Enforce a DRNG reseed by reading 511 128-bit samples
+ */
+static bool reseed()
+{
+ int i;
+
+#ifdef __x86_64__
+ u_int64_t tmp;
+
+ for (i = 0; i < 511 * 16 / sizeof(u_int64_t); i++)
+ {
+ if (!rdrand64(&tmp))
+ {
+ return FALSE;
+ }
+ }
+#else /* __i386__ */
+ u_int32_t tmp;
+
+ for (i = 0; i < 511 * 16 / sizeof(u_int32_t); i++)
+ {
+ if (!rdrand32(&tmp))
+ {
+ return FALSE;
+ }
+ }
+#endif /* __x86_64__ / __i386__ */
+ return TRUE;
+}
+
METHOD(rng_t, get_bytes, bool,
private_rdrand_rng_t *this, size_t bytes, u_int8_t *buffer)
{
@@ -128,6 +165,14 @@ METHOD(rng_t, get_bytes, bool,
chunk = chunk_create(buffer, bytes);
+ if (this->quality == RNG_STRONG)
+ {
+ if (!reseed())
+ {
+ return FALSE;
+ }
+ }
+
/* align to 2 byte */
if (chunk.len >= sizeof(u_int8_t))
{
@@ -172,6 +217,13 @@ METHOD(rng_t, get_bytes, bool,
/* fill with 8 byte words */
while (chunk.len >= sizeof(u_int64_t))
{
+ if (this->quality == RNG_STRONG && chunk.len % FORCE_RESEED)
+ {
+ if (!reseed())
+ {
+ return FALSE;
+ }
+ }
if (!rdrand64((u_int64_t*)chunk.ptr))
{
return FALSE;
@@ -194,6 +246,13 @@ METHOD(rng_t, get_bytes, bool,
/* fill with 4 byte words */
while (chunk.len >= sizeof(u_int32_t))
{
+ if (this->quality == RNG_STRONG && chunk.len % FORCE_RESEED)
+ {
+ if (!reseed())
+ {
+ return FALSE;
+ }
+ }
if (!rdrand32((u_int32_t*)chunk.ptr))
{
return FALSE;
@@ -203,6 +262,14 @@ METHOD(rng_t, get_bytes, bool,
#endif /* __x86_64__ / __i386__ */
+ if (this->quality == RNG_STRONG)
+ {
+ if (!reseed())
+ {
+ return FALSE;
+ }
+ }
+
/* append 2 byte word */
if (chunk.len >= sizeof(u_int16_t))
{
@@ -254,8 +321,8 @@ rdrand_rng_t *rdrand_rng_create(rng_quality_t quality)
switch (quality)
{
case RNG_WEAK:
- break;
case RNG_STRONG:
+ break;
case RNG_TRUE:
default:
/* not yet */