]> git.ipfire.org Git - thirdparty/rng-tools.git/commitdiff
rdrand: Simplify by changing x86_rdrand_nlong to x86_rdrand_bytes
authorH. Peter Anvin <hpa@linux.intel.com>
Tue, 4 Mar 2014 22:55:38 +0000 (14:55 -0800)
committerH. Peter Anvin <hpa@linux.intel.com>
Tue, 4 Mar 2014 22:55:38 +0000 (14:55 -0800)
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>
rdrand_asm.S
rngd_rdrand.c

index 4b8fdc5eccf3aa533b13b2ec5db4df24f3ace04d..913b923b445b4efb16ed8bd8bd2771629ef43497 100644 (file)
@@ -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
index 064702f9ba69a4bc782a334c21af6b13c39c3353..cb6736984953c9105753953d82683f829734c50e 100644 (file)
@@ -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))