diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-04 14:55:38 -0800 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2014-03-04 14:55:38 -0800 |
commit | 3164d3ebb3d8feb27ca59d98c53306ab93f476b2 (patch) | |
tree | e5083e514b471a76d092b7690c8f6d24a3684beb | |
parent | 0ad21ad0a4d02faf48b5ff94db0ffb7cb43773c2 (diff) | |
download | rng-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.S | 49 | ||||
-rw-r--r-- | rngd_rdrand.c | 20 |
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)) |