diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-02-24 14:01:49 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-02-26 00:12:32 -0800 |
commit | 94f03c9a2c479bd59913e6556620c2432e43b6ee (patch) | |
tree | a10dff0ada1ac56133587d52c4f028f7b95b42a9 | |
parent | 62dec321e2f6cc5de249d1396aec579729d0cf13 (diff) | |
download | rng-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.S | 87 | ||||
-rw-r--r-- | rngd_rdrand.c | 44 |
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); |