diff options
author | Martin Willi <martin@revosec.ch> | 2013-01-04 16:07:31 +0100 |
---|---|---|
committer | Martin Willi <martin@revosec.ch> | 2013-01-11 10:45:14 +0100 |
commit | b9148ea232f24d2f751588aa3045a6bc98bff1f8 (patch) | |
tree | baf4968a6a7dc3f157b67a6d7b09d7328229f8e0 /src/libstrongswan/plugins | |
parent | 9fe24b004d6d1a64d0e2f106d39cf7a8fbd3179d (diff) | |
download | strongswan-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.c | 1 | ||||
-rw-r--r-- | src/libstrongswan/plugins/rdrand/rdrand_rng.c | 69 |
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 */ |