Hi Peter,

On Aug 12 15:29, Peter Rosin wrote:
> On 2014-08-09 16:37, Corinna Vinschen wrote:
> > I just uploaded rng-tools-5-1.
> > 
> > The Cygwin release only comes with the rngtest tool for now.
> > 
> > The rngd daemon requires porting assembler code to COFF and the
> > Microsoft calling convention.  Any help porting this code would
> > be greatly appreciated.
> 
> Ok, I took a stab at it. The problems I identified in the assembly
> are ELF debug info, different register use for the x86-64 calls and
> a missing underscore prefix for the i686 symbols.
> 
> I'm unsure if used registers (and which) have to be saved in the
> MS x86-64 ABI, but that shouldn't be too hard to fix if that's the
> case.
> 
> I also moved up the AC_SEARCH_LIBS hunk in configure.ac since
> the existing AC_CHECK_LIB is buried inside some other construct
> (AC_CHECK_HEADER is possibly the culprit) which causes this:
> 
> checking for library containing argp_parse... 
> /usr/src/rng-tools-5-1.src/rng-tools-5-1.i686/src/rng-tools-5/configure: line 
> 4335: ac_fn_c_try_link: command not found
> /usr/src/rng-tools-5-1.src/rng-tools-5-1.i686/src/rng-tools-5/configure: line 
> 4335: ac_fn_c_try_link: command not found
> no
> 
> Anyway, with the attached patch instead of the one included in the
> src package, it builds for both arches, but my cpu appears to lack
> the rdrand instruction, so I have a hard time taking this any
> further.   Bummer.

Thanks for your efforts!  Over the weekend I tried my own port.  I opted
for creating a new file, rdrand_win_asm.S (attached for reference) to
keep the code a bit cleaner.

I have a machine which supports the rdrand call, but you need at least
an Ivy Bridge CPU,  For rdseed you need at least Haswell.

Ultimately I gave up on rngd for now, for four reasons:

- rngd uses poll(2) on /dev/random to wait until /dev/random becomes
  writable.  /dev/random on Cygwin is always writable (we're not
  controlling the entropy pool, the OS does, and the RtlGenRandom call
  never blocks).  This results in 100% CPU usage.

- Even then, using rngd on /dev/random gave *worse* results when
  testing /dev/random with rngtest :-P   I'm not sure why.

- Cygwin does not support any of the other three hardware entropy
  sources /dev/hwrng or /dev/tpm0.  For Intel/AMD hwrng you'd need
  access to the PCI bus and certain chipsets.  For tpm0 you'd
  need a TPM chip and a description how to access the chip for
  producing random numbers.  The chip is supposedly available as
  cryptographic provider under Windows, but on the only machine 
  in our home with a TPM chip *and* a functional Windows driver,
  there was no matching cryptographic provider returned by the call
  to CryptEnumProviders.

- Given that, and given the hardware constraints for the rdrand and
  rdseed calls, I decided that it's not worth to follow through with
  this stuff.

Still, thanks a lot for working on that.  I appreciate it.  If you
have any idea how Cygwin could provide /dev/hwrng or /dev/tpm0 to
have at least two HW entropy sources, please feel free to discuss 
this on the cygwin-developer's list.


Thanks,
Corinna

-- 
Corinna Vinschen                  Please, send mails regarding Cygwin to
Cygwin Maintainer                 cygwin AT cygwin DOT com
Red Hat
/*
 * Copyright (c) 2011-2014, Intel Corporation
 * Authors: Fenghua Yu <fenghua...@intel.com>,
 *          H. Peter Anvin <h...@linux.intel.com>
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

/*
 * This is the Windows version of the file.  It's equivalent to the original
 * code from Intel, just replacing ELF with COFF pseudo code expressions
 * where necessary and using Windows ABI rather than System V ABI on x86_64.
 * Additionally it utilizes the fact that recent versions of gas know the
 * rdrand, rdseed, and aes opcodes to avoid opaque .byte expression.
 */

#if defined(__i386__) || defined(__x86_64__)

#ifdef __x86_64__
#define LBL(x)  x
#else
#define LBL(x)  _##x
#endif

#define ENTRY(x)          \
        .align  8       ; \
        .globl  LBL(x)  ; \
        .def    LBL(x)  ; \
        .scl    2       ; \
        .type   32      ; \
        .endef          ; \
LBL(x):

#define ENDPROC(x)

#define RDRAND_RETRY_LIMIT      10

#ifdef __x86_64__

ENTRY(x86_rdrand_bytes)
        mov     %edx, %eax
1:
        mov     $RDRAND_RETRY_LIMIT, %r9d
2:
        rdrand  %r10
        jnc     3f
        mov     %r10, (%rcx)
        add     $8, %rcx
        sub     $8, %edx
        ja      1b
4:
        sub     %edx, %eax
        ret
3:
        dec     %r9d
        rep;nop
        jnz     2b
        jmp     4b
ENDPROC(x86_rdrand_bytes)

ENTRY(x86_rdseed_or_rdrand_bytes)
        push    %r12
        push    %r13
        mov     (%rdx), %r12d           /* RDSEED count */
        mov     (%r9), %r13d            /* RDRAND count */
1:
        mov     $RDRAND_RETRY_LIMIT, %r10d
2:
        rdrand  %rax
        jnc     3f
        mov     %rax, (%rcx)
        add     $8, %rcx
        sub     $8, %r12d
        ja      1b
4:
        sub     %r12d, (%rdx)
        sub     %r13d, (%r9)
        pop     %r13
        pop     %r12
        ret
3:
        rdrand  %rax
        jnc     5f
        mov     %rax, (%r8)
        add     $8, %r8
        sub     $8, %r13d
        ja      1b
        jmp     4b
5:
        dec     %r10d
        rep;nop
        jnz     2b
        jmp     4b
ENDPROC(x86_rdseed_or_rdrand_bytes)

#define SETPTR(var,ptr) leaq var(%rip),ptr
#define PTR0    %rcx
#define PTR1    %rdx
#define PTR2    %r9
#define CTR3    %eax
#define NPTR2   1       /* %rcx = %r1, only 0-7 valid here */

#elif defined(__i386__)

ENTRY(x86_rdrand_bytes)
        push    %ebp
        mov     %esp, %ebp
        push    %edi
        push    %esi
        movl    8(%ebp), %edi
        movl    12(%ebp), %esi

        mov     %esi, %eax
1:
        mov     $RDRAND_RETRY_LIMIT, %ecx
2:
        rdrand  %edx
        jnc     3f
        mov     %edx, (%edi)
        add     $4, %edi
        sub     $4, %esi
        ja      1b
4:
        sub     %esi, %eax
        pop     %esi
        pop     %edi
        pop     %ebp
        ret
3:
        dec     %ecx
        rep;nop
        jnz     2b
        jmp     4b
ENDPROC(x86_rdrand_bytes)


ENTRY(x86_rdseed_or_rdrand_bytes)
        push    %ebp
        mov     %esp, %ebp
        push    %edi
        push    %esi
        push    %ebx

        mov     12(%ebp), %ebx
        mov     20(%ebp), %esi
        mov     8(%ebp), %edi           /* RDSEED pointer */
        mov     16(%ebp), %edx          /* RDRAND pointer */
        mov     (%ebx), %ebx            /* RDSEED count */
        mov     (%esi), %esi            /* RDRAND count */
1:
        mov     $RDRAND_RETRY_LIMIT, %ecx
2:
        rdseed  %eax
        jnc     3f
        mov     %eax, (%edi)
        add     $4, %edi
        sub     $4, %ebx
        ja      1b
4:
        mov     12(%ebp), %edx
        mov     20(%ebp), %eax
        sub     %ebx, (%edx)            /* RDSEED count */
        sub     %esi, (%eax)            /* RDRAND count */

        pop     %ebx
        pop     %esi
        pop     %edi
        pop     %ebp
        ret
3:
        rdrand  %eax
        jnc     5f
        mov     %eax, (%edx)
        add     $4, %edx
        sub     $4, %esi
        jnz     1b
        ja      4b
5:
        dec     %ecx
        rep;nop
        jnz     2b
        jmp     4b
ENDPROC(x86_rdseed_or_rdrand_bytes)

#define SETPTR(var,ptr) movl $(var),ptr
#define PTR0    %eax
#define PTR1    %edx
#define PTR2    %ecx
#define CTR3    %esi
#define NPTR2   1       /* %rcx = %r1 */

#endif

ENTRY(x86_aes_mangle)
#ifdef __i386__
        push    %ebp
        mov     %esp, %ebp
        movl    8(%ebp), %eax
        movl    12(%ebp), %edx
        push    %esi
#endif
        movl    $512, CTR3      /* Number of rounds */
        
        movdqa  (0*16)(PTR1), %xmm0
        movdqa  (1*16)(PTR1), %xmm1
        movdqa  (2*16)(PTR1), %xmm2
        movdqa  (3*16)(PTR1), %xmm3
        movdqa  (4*16)(PTR1), %xmm4
        movdqa  (5*16)(PTR1), %xmm5
        movdqa  (6*16)(PTR1), %xmm6
        movdqa  (7*16)(PTR1), %xmm7

#ifdef __x86_64__
        SETPTR(aes_round_keys, PTR2)
1:
#else
1:
        SETPTR(aes_round_keys, PTR2)
#endif

        /* 8192 = 512 (rounds) * 16 (bytes) */
        pxor    (0*8192)(PTR0), %xmm0
        pxor    (1*8192)(PTR0), %xmm1
        pxor    (2*8192)(PTR0), %xmm2
        pxor    (3*8192)(PTR0), %xmm3
        pxor    (4*8192)(PTR0), %xmm4
        pxor    (5*8192)(PTR0), %xmm5
        pxor    (6*8192)(PTR0), %xmm6
        pxor    (7*8192)(PTR0), %xmm7
        add     $16, PTR0

offset = 0
        .rept 10
#ifdef __x86_64__
        movdqa  offset(PTR2), %xmm8
offset = offset + 16
        aesenc %xmm8, %xmm0
        aesenc %xmm8, %xmm1
        aesenc %xmm8, %xmm2
        aesenc %xmm8, %xmm3
        aesenc %xmm8, %xmm4
        aesenc %xmm8, %xmm5
        aesenc %xmm8, %xmm6
        aesenc %xmm8, %xmm7
#else
        aesenc (PTR2), %xmm0
        aesenc (PTR2), %xmm1
        aesenc (PTR2), %xmm2
        aesenc (PTR2), %xmm3
        aesenc (PTR2), %xmm4
        aesenc (PTR2), %xmm5
        aesenc (PTR2), %xmm6
        aesenc (PTR2), %xmm7
        add     $16, PTR2
#endif
        .endr

#ifdef __x86_64__
        movdqa  offset(PTR2), %xmm8
        aesenclast %xmm8, %xmm0
        aesenclast %xmm8, %xmm1
        aesenclast %xmm8, %xmm2
        aesenclast %xmm8, %xmm3
        aesenclast %xmm8, %xmm4
        aesenclast %xmm8, %xmm5
        aesenclast %xmm8, %xmm6
        aesenclast %xmm8, %xmm7
#else
        aesenclast (PTR2), %xmm0
        aesenclast (PTR2), %xmm1
        aesenclast (PTR2), %xmm2
        aesenclast (PTR2), %xmm3
        aesenclast (PTR2), %xmm4
        aesenclast (PTR2), %xmm5
        aesenclast (PTR2), %xmm6
        aesenclast (PTR2), %xmm7
#endif
        sub     $1, CTR3
        jnz     1b
        
        movdqa  %xmm0, (0*16)(PTR1)
        movdqa  %xmm1, (1*16)(PTR1)
        movdqa  %xmm2, (2*16)(PTR1)
        movdqa  %xmm3, (3*16)(PTR1)
        movdqa  %xmm4, (4*16)(PTR1)
        movdqa  %xmm5, (5*16)(PTR1)
        movdqa  %xmm6, (6*16)(PTR1)
        movdqa  %xmm7, (7*16)(PTR1)

#ifdef __i386__
        pop     %esi
        pop     %ebp
#endif
        ret
ENDPROC(x86_aes_mangle)

ENTRY(x86_aes_expand_key)
#ifdef __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,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x02,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x04,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x08,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x10,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x20,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x40,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x80,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x1b,%xmm0,%xmm1
        call    1f
        aeskeygenassist $0x36,%xmm0,%xmm1
        call    1f

#ifdef __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

#endif /* i386 or x86_64 */

Attachment: pgp_wvCNjoe2E.pgp
Description: PGP signature

Reply via email to