#ifdef __x86_64__
-ENTRY(x86_rdrand_nlong)
+ENTRY(x86_rdrand_bytes)
+ mov %esi, %eax
1:
- mov $RDRAND_RETRY_LIMIT, %eax
+ mov $RDRAND_RETRY_LIMIT, %ecx
2:
.byte 0x48,0x0f,0xc7,0xf2 /* rdrand %rdx */
jnc 3f
mov %rdx, (%rdi)
add $8, %rdi
- sub $1, %esi
- jnz 1b
+ sub $8, %esi
+ ja 1b
+4:
+ sub %esi, %eax
ret
3:
- sub $1, %eax
+ dec %ecx
rep;nop
jnz 2b
- ret
-ENDPROC(x86_rdrand_nlong)
+ jmp 4b
+ENDPROC(x86_rdrand_bytes)
#define SETPTR(var,ptr) leaq var(%rip),ptr
#define PTR0 %rdi
#elif defined(__i386__)
-ENTRY(x86_rdrand_nlong)
+ENTRY(x86_rdrand_bytes)
push %ebp
mov %esp, %ebp
push %edi
- movl 8(%ebp), %ecx
- movl 12(%ebp), %edx
+ push %esi
+ movl 8(%ebp), %edi
+ movl 12(%ebp), %esi
+
+ mov %esi, %eax
1:
- mov $RDRAND_RETRY_LIMIT, %eax
+ mov $RDRAND_RETRY_LIMIT, %ecx
2:
- .byte 0x0f,0xc7,0xf7 /* rdrand %edi */
+ .byte 0x0f,0xc7,0xf2 /* rdrand %edx */
jnc 3f
- mov %edi, (%ecx)
- add $4, %ecx
- sub $1, %edx
- jnz 2b
+ mov %edx, (%edi)
+ add $4, %edi
+ sub $4, %esi
+ ja 1b
+4:
+ sub %esi, %eax
+ pop %esi
pop %edi
pop %ebp
ret
3:
- sub $1, %eax
+ dec %ecx
rep;nop
jnz 2b
- pop %edi
- pop %ebp
- ret
-ENDPROC(x86_rdrand_nlong)
+ jmp 4b
+ENDPROC(x86_rdrand_bytes)
#define SETPTR(var,ptr) movl $(var),ptr
#define PTR0 %eax
uint32_t eax, ecx, edx, ebx;
};
-/* Get data from RDRAND */
-extern int x86_rdrand_nlong(void *ptr, size_t count);
-/* Conditioning RDRAND for seed-grade entropy */
+/*
+ * Get data from RDRAND. The count is in bytes, but the function can
+ * round *up* the count to the nearest 4- or 8-byte boundary. The caller
+ * needs to take that into account.
+ *
+ * The function returns the number of bytes actually written.
+ */
+extern unsigned int x86_rdrand_bytes(void *ptr, unsigned int count);
+
+/* Condition 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);
while (size) {
for (i = 0; i < rdrand_round_count; i++) {
- if (!x86_rdrand_nlong(tmp, CHUNK_SIZE/sizeof(unative_t))) {
+ if (x86_rdrand_bytes(tmp, CHUNK_SIZE) != CHUNK_SIZE) {
message(LOG_DAEMON|LOG_ERR, "read error\n");
return -1;
}
have_aesni = !!(info.ecx & features_ecx1_aesni);
/* Randomize the AES data reduction key the best we can */
- if (!x86_rdrand_nlong(xkey, sizeof xkey/sizeof(unative_t)))
+ if (x86_rdrand_bytes(xkey, sizeof xkey) != sizeof xkey)
return 1;
fd = open("/dev/urandom", O_RDONLY);
key[i] ^= xkey[i];
/* Initialize the IV buffer */
- if (!x86_rdrand_nlong(iv_buf, CHUNK_SIZE/sizeof(unative_t)))
+ if (x86_rdrand_bytes(iv_buf, CHUNK_SIZE) != CHUNK_SIZE)
return 1;
if (init_aesni(key) && init_gcrypt(key))