aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2012-08-01 14:31:36 -0700
committerJeff Garzik <jgarzik@redhat.com>2012-08-02 00:18:52 -0400
commit932e25b20fbf46dbc6d4438bbdd92fdfd1693e7b (patch)
tree6ff01113c1cd703d2ce4375f602ac1cdea245839
parent101309bc070667a39794bf13714d43f950b9bade (diff)
downloadrng-tools-932e25b20fbf46dbc6d4438bbdd92fdfd1693e7b.tar.gz
rngd_rdrand: Actually perform the correct AES data reduction
The pointers were confused in such a way that the AES data reduction wasn't actually being performed. Furthermore, architecturally we need a 512:1 data reduction, rather than 128:1. Finally, initialize the IV to random value during startup and remove some unnecessary buffer shuffling. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--rngd_rdrand.c65
1 files changed, 23 insertions, 42 deletions
diff --git a/rngd_rdrand.c b/rngd_rdrand.c
index d6408a0..f04d2f0 100644
--- a/rngd_rdrand.c
+++ b/rngd_rdrand.c
@@ -44,11 +44,6 @@
#if defined(__i386__) || defined(__x86_64__)
-/* Initialization vector and msg sizes for standard AES usage */
-#define IV_SIZE (16*1)
-#define MSG_SIZE (16*7)
-#define CHUNK_SIZE (16*8)
-
/* Struct for CPUID return values */
struct cpuid {
uint32_t eax, ecx, edx, ebx;
@@ -102,51 +97,33 @@ static void cpuid(unsigned int leaf, unsigned int subleaf, struct cpuid *out)
#endif
}
-/* Read data from the drng
- * in chunks of 128 bytes for AES scrambling */
+/* Read data from the drng in chunks of 128 bytes for AES scrambling */
+#define CHUNK_SIZE (16*8)
+
+static unsigned char iv_buf[CHUNK_SIZE] __attribute__((aligned(128)));
+
int xread_drng(void *buf, size_t size, struct rng *ent_src)
{
- size_t psize = size;
- size_t off = 0;
- ssize_t r = 0;
- int rdrand_round_count = size / 128;
-
- static unsigned char iv_buf[IV_SIZE] __attribute__((aligned(128)));
- static unsigned char m_buf[MSG_SIZE] __attribute__((aligned(128)));
- static unsigned char tmp[CHUNK_SIZE] __attribute__((aligned(128)));
- static unsigned char fwd[CHUNK_SIZE] __attribute__((aligned(128)));
+ char *p = buf;
+ size_t chunk;
+ const int rdrand_round_count = 512;
+ unsigned char tmp[CHUNK_SIZE] __attribute__((aligned(128)));
int i;
- while (size > 0 && size <= psize) {
- for (i = 0; i < rdrand_round_count && size <= psize; i++) {
- if (!x86_rdrand_nlong(iv_buf, sizeof(iv_buf)/sizeof(long))) {
- r = -1;
- break;
- }
- if (!x86_rdrand_nlong(m_buf, sizeof(m_buf)/sizeof(long))) {
- r = -1;
- break;
+ while (size) {
+ for (i = 0; i < rdrand_round_count; i++) {
+ if (!x86_rdrand_nlong(tmp, CHUNK_SIZE/sizeof(long))) {
+ message(LOG_DAEMON|LOG_ERR, "read error\n");
+ return -1;
}
- memcpy(tmp, iv_buf, IV_SIZE);
- memcpy(tmp+IV_SIZE, m_buf, MSG_SIZE);
-
- x86_aes_mangle(tmp, fwd);
- r = (sizeof(tmp) > size)? size : sizeof(tmp);
-
- if (r <= 0)
- break;
- memcpy(buf+off, tmp, r);
- off += r;
- size -= r;
+ x86_aes_mangle(tmp, iv_buf);
}
- if (r <= 0)
- break;
+ chunk = (sizeof(tmp) > size) ? size : sizeof(tmp);
+ memcpy(p, tmp, chunk);
+ p += chunk;
+ size -= chunk;
}
- if (size > 0 && size < psize) {
- message(LOG_DAEMON|LOG_ERR, "read error\n");
- return -1;
- }
return 0;
}
@@ -171,6 +148,10 @@ int init_drng_entropy_source(struct rng *ent_src)
if ((info.ecx & need_features_ecx1) != need_features_ecx1)
return 1;
+ /* Initialize the IV buffer */
+ if (!x86_rdrand_nlong(iv_buf, CHUNK_SIZE/sizeof(long)))
+ return 1;
+
src_list_add(ent_src);
/* Bootstrap FIPS tests */
ent_src->fipsctx = malloc(sizeof(fips_ctx_t));