]> git.ipfire.org Git - thirdparty/rng-tools.git/commitdiff
rngd_rdrand: Don't use a fixed AES key for data reduction
authorH. Peter Anvin <hpa@linux.intel.com>
Mon, 24 Feb 2014 22:01:49 +0000 (14:01 -0800)
committerH. Peter Anvin <hpa@linux.intel.com>
Wed, 26 Feb 2014 08:12:32 +0000 (00:12 -0800)
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>
rdrand_asm.S
rngd_rdrand.c

index 3bd99ae4b43a4c7812e3ad3f5cacd965123ab5a9..32e7328164ce4100387209e4e09c115766789c2f 100644 (file)
@@ -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 */
 
 /*
index 9a20d7db0121fcc21861b36c59619dcf3bd1b0fe..d50993d55112d98b4d5b2923ff6379c74891e0ae 100644 (file)
@@ -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);