/*
- * 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>
*
#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 */
/*
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)
}
return 0;
#else
+ (void)tmp;
return -1;
#endif
}
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))) {
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)) {
}
return 0;
#else
+ (void)key;
return 1;
#endif
}
/* 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 */
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);