aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2014-02-24 14:01:49 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2014-02-26 00:12:32 -0800
commit94f03c9a2c479bd59913e6556620c2432e43b6ee (patch)
treea10dff0ada1ac56133587d52c4f028f7b95b42a9
parent62dec321e2f6cc5de249d1396aec579729d0cf13 (diff)
downloadrng-tools-94f03c9a2c479bd59913e6556620c2432e43b6ee.tar.gz
rngd_rdrand: Don't use a fixed AES key for data reduction
If we're going to run the data through AES anyway, there is no point in using the same key every time. Grab a key from /dev/urandom, although of course it is unknown how much entropy actually *is* in /dev/urandom at this point, it is presumably better than nothing, which is what we have now and XOR with rdrand output. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--rdrand_asm.S87
-rw-r--r--rngd_rdrand.c44
2 files changed, 98 insertions, 33 deletions
diff --git a/rdrand_asm.S b/rdrand_asm.S
index 3bd99ae..32e7328 100644
--- a/rdrand_asm.S
+++ b/rdrand_asm.S
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011, Intel Corporation
+ * Copyright (c) 2011-2014, Intel Corporation
* Authors: Fenghua Yu <fenghua.yu@intel.com>,
* H. Peter Anvin <hpa@linux.intel.com>
*
@@ -166,32 +166,69 @@ ENTRY(x86_aes_mangle)
#endif
ret
ENDPROC(x86_aes_mangle)
- /*
- * AES round keys for an arbitrary key:
- * 00102030405060708090A0B0C0D0E0F0
- */
- .section ".rodata","a"
- .balign 16
-aes_round_keys:
- .long 0x30201000, 0x70605040, 0xB0A09080, 0xF0E0D0C0
- .long 0x8AACF171, 0xFACCA131, 0x4A6C31B1, 0xBA8CE171
- .long 0x2958958B, 0xD39434BA, 0x99F8050B, 0x2374E47A
- .long 0xF37E07E6, 0x20EA335C, 0xB9123657, 0x9A66D22D
- .long 0x2BC6345B, 0x0B2C0707, 0xB23E3150, 0x2858E37D
- .long 0xD4F25E5A, 0xDFDE595D, 0x6DE0680D, 0x45B88B70
- .long 0x859C3247, 0x5A426B1A, 0x37A20317, 0x721A8867
- .long 0x00DC90C3, 0x5A9EFBD9, 0x6D3CF8CE, 0x1F2670A9
- .long 0xD31C6712, 0x89829CCB, 0xE4BE6405, 0xFB9814AC
- .long 0x421321F3, 0xCB91BD38, 0x2F2FD93D, 0xD4B7CD91
- .long 0xC35B8878, 0x08CA3540, 0x27E5EC7D, 0xF35221EC
- .size aes_round_keys, .-aes_round_keys
- .bss
- .balign 16
-aes_fwd_state:
- .space 16
- .size aes_fwd_state, .-aes_fwd_state
+/* aeskeygenassist $imm,%xmm0,%xmm1 */
+#define AESKEYGENASSIST(imm) .byte 0x66,0x0f,0x3a,0xdf,0xc8,imm
+
+ENTRY(x86_aes_expand_key)
+#if defined(__i386__)
+ push %ebp
+ mov %esp, %ebp
+ movl 8(%ebp), %eax
+#endif
+
+ SETPTR(aes_round_keys, PTR1)
+ movdqu (PTR0), %xmm0
+ movdqa %xmm0, (PTR1) /* First slot = the plain key */
+ add $16, PTR1
+
+ AESKEYGENASSIST(0x01)
+ call 1f
+ AESKEYGENASSIST(0x02)
+ call 1f
+ AESKEYGENASSIST(0x04)
+ call 1f
+ AESKEYGENASSIST(0x08)
+ call 1f
+ AESKEYGENASSIST(0x10)
+ call 1f
+ AESKEYGENASSIST(0x20)
+ call 1f
+ AESKEYGENASSIST(0x40)
+ call 1f
+ AESKEYGENASSIST(0x80)
+ call 1f
+ AESKEYGENASSIST(0x1b)
+ call 1f
+ AESKEYGENASSIST(0x36)
+ call 1f
+
+#if defined(__i386__)
+ pop %ebp
+#endif
+ ret
+1:
+ pshufd $0xff, %xmm1, %xmm1
+ movdqa %xmm0, %xmm2
+ pslldq $4, %xmm2
+ pxor %xmm2, %xmm0
+ pslldq $4, %xmm2
+ pxor %xmm2, %xmm0
+ pslldq $4, %xmm2
+ pxor %xmm2, %xmm0
+ pxor %xmm1, %xmm0
+ movdqa %xmm0, (PTR1)
+ add $16, PTR1
+ ret
+
+ENDPROC(x86_aes_expand_key)
+
+ .bss
+ .balign 64
+aes_round_keys:
+ .space 11*16
+ .size aes_round_keys, .-aes_round_keys
#endif /* i386 or x86_64 */
/*
diff --git a/rngd_rdrand.c b/rngd_rdrand.c
index 9a20d7d..d50993d 100644
--- a/rngd_rdrand.c
+++ b/rngd_rdrand.c
@@ -57,6 +57,8 @@ struct cpuid {
extern int x86_rdrand_nlong(void *ptr, size_t count);
/* Conditioning RDRAND for seed-grade entropy */
extern void x86_aes_mangle(void *data, void *state);
+/* Expand an AES key for future use */
+extern void x86_aes_expand_key(const void *key);
/* Checking eflags to confirm cpuid instruction available */
static inline int x86_has_eflag(unsigned long flag)
@@ -141,6 +143,7 @@ static inline int gcrypt_mangle(unsigned char *tmp)
}
return 0;
#else
+ (void)tmp;
return -1;
#endif
}
@@ -153,6 +156,8 @@ int xread_drng(void *buf, size_t size, struct rng *ent_src)
unsigned char tmp[CHUNK_SIZE] __attribute__((aligned(128)));
int i;
+ (void)ent_src;
+
while (size) {
for (i = 0; i < rdrand_round_count; i++) {
if (!x86_rdrand_nlong(tmp, CHUNK_SIZE/sizeof(long))) {
@@ -178,14 +183,18 @@ int xread_drng(void *buf, size_t size, struct rng *ent_src)
return 0;
}
-static int init_gcrypt(void)
+static int init_aesni(const void *key)
+{
+ if (!have_aesni)
+ return 1;
+
+ x86_aes_expand_key(key);
+ return 0;
+}
+
+static int init_gcrypt(const void *key)
{
#ifdef HAVE_LIBGCRYPT
- /* Arbitrary 128-bit AES key 0x00102030405060708090A0B0C0D0E0F0 */
- static const unsigned char key[16] = {
- 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70,
- 0x80, 0x90, 0xA0, 0xB0, 0xC0, 0xD0, 0xE0, 0xF0
- };
gcry_error_t gcry_error;
if (!gcry_check_version(MIN_GCRYPT_VERSION)) {
@@ -218,6 +227,7 @@ static int init_gcrypt(void)
}
return 0;
#else
+ (void)key;
return 1;
#endif
}
@@ -231,6 +241,13 @@ int init_drng_entropy_source(struct rng *ent_src)
/* We need RDRAND, but AESni is optional */
const uint32_t features_ecx1_rdrand = 1 << 30;
const uint32_t features_ecx1_aesni = 1 << 25;
+ static unsigned char key[16] = {
+ 0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70,
+ 0x80,0x90,0xa0,0xb0,0xc0,0xd0,0xe0,0xf0
+ }; /* AES data reduction key */
+ unsigned char xkey[16]; /* Material to XOR into the key */
+ int fd;
+ int i;
if (!x86_has_cpuid())
return 1; /* No CPUID instruction */
@@ -244,13 +261,24 @@ int init_drng_entropy_source(struct rng *ent_src)
have_aesni = !!(info.ecx & features_ecx1_aesni);
- /* Initialize the AES key */
+ /* Randomize the AES data reduction key the best we can */
+ if (!x86_rdrand_nlong(xkey, sizeof xkey/sizeof(long)))
+ return 1;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ if (fd >= 0) {
+ read(fd, key, sizeof key);
+ close(fd);
+ }
+
+ for (i = 0; i < sizeof key; i++)
+ key[i] ^= xkey[i];
/* Initialize the IV buffer */
if (!x86_rdrand_nlong(iv_buf, CHUNK_SIZE/sizeof(long)))
return 1;
- if (!have_aesni && init_gcrypt())
+ if (init_aesni(key) && init_gcrypt(key))
return 1; /* We need one crypto or the other... */
src_list_add(ent_src);