aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorH. Peter Anvin <hpa@linux.intel.com>2014-03-04 14:55:38 -0800
committerH. Peter Anvin <hpa@linux.intel.com>2014-03-04 14:55:38 -0800
commit3164d3ebb3d8feb27ca59d98c53306ab93f476b2 (patch)
treee5083e514b471a76d092b7690c8f6d24a3684beb
parent0ad21ad0a4d02faf48b5ff94db0ffb7cb43773c2 (diff)
downloadrng-tools-3164d3ebb3d8feb27ca59d98c53306ab93f476b2.tar.gz
rdrand: Simplify by changing x86_rdrand_nlong to x86_rdrand_bytes
Make the code simpler by making x86_rdrand_nlong instead take a count in bytes and return the number of bytes written (the latter will matter for upcoming RDSEED enabling.) The function may still round up the size of the output buffer to a 4- or 8-byte boundary. Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
-rw-r--r--rdrand_asm.S49
-rw-r--r--rngd_rdrand.c20
2 files changed, 42 insertions, 27 deletions
diff --git a/rdrand_asm.S b/rdrand_asm.S
index 4b8fdc5..913b923 100644
--- a/rdrand_asm.S
+++ b/rdrand_asm.S
@@ -33,23 +33,26 @@ x:
#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
@@ -59,32 +62,36 @@ ENDPROC(x86_rdrand_nlong)
#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
diff --git a/rngd_rdrand.c b/rngd_rdrand.c
index 064702f..cb67369 100644
--- a/rngd_rdrand.c
+++ b/rngd_rdrand.c
@@ -53,10 +53,18 @@ struct cpuid {
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);
@@ -166,7 +174,7 @@ int xread_drng(void *buf, size_t size, struct rng *ent_src)
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;
}
@@ -268,7 +276,7 @@ int init_drng_entropy_source(struct rng *ent_src)
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);
@@ -281,7 +289,7 @@ int init_drng_entropy_source(struct rng *ent_src)
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))