summaryrefslogtreecommitdiff
path: root/external/crypto++-5.6.3/rdrand.S
diff options
context:
space:
mode:
Diffstat (limited to 'external/crypto++-5.6.3/rdrand.S')
-rw-r--r--external/crypto++-5.6.3/rdrand.S596
1 files changed, 596 insertions, 0 deletions
diff --git a/external/crypto++-5.6.3/rdrand.S b/external/crypto++-5.6.3/rdrand.S
new file mode 100644
index 0000000..9a1c4f1
--- /dev/null
+++ b/external/crypto++-5.6.3/rdrand.S
@@ -0,0 +1,596 @@
+;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
+;; Copyright assigned to the Crypto++ project.
+
+;; This ASM file provides RDRAND and RDSEED to downlevel Unix and Linux tool chains.
+;; Additionally, the inline assembly code produced by GCC and Clang is not that
+;; impressive. However, using this code requires NASM and an edit to the GNUmakefile.
+
+;; nasm -f elf32 rdrand.S -DX86 -g -o rdrand-x86.o
+;; nasm -f elfx32 rdrand.S -DX32 -g -o rdrand-x32.o
+;; nasm -f elf64 rdrand.S -DX64 -g -o rdrand-x64.o
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Naming convention used in rdrand.{h|cpp|asm|S}
+;; MSC = Microsoft Compiler (and compatibles)
+;; GCC = GNU Compiler (and compatibles)
+;; ALL = MSC and GCC (and compatibles)
+;; RRA = RDRAND, Assembly
+;; RSA = RDSEED, Assembly
+;; RRI = RDRAND, Intrinsic
+;; RSA = RDSEED, Intrinsic
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; C/C++ Function prototypes
+;; X86, X32 and X64:
+;; extern "C" int NASM_RRA_GenerateBlock(byte* ptr, size_t size, unsigned int safety);
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; Return values
+%define RDRAND_SUCCESS 1
+%define RDRAND_FAILURE 0
+
+%define RDSEED_SUCCESS 1
+%define RDSEED_FAILURE 0
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+%ifdef X86 or X32 ;; Set via the command line
+
+;; Arg1, byte* buffer
+;; Arg2, size_t bsize
+;; Arg3, unsigned int safety
+;; EAX (out): success (1), failure (0)
+
+global NASM_RRA_GenerateBlock
+section .text
+
+%ifdef X86
+align 8
+cpu 486
+%else
+align 16
+%endif
+
+NASM_RRA_GenerateBlock:
+
+%ifdef X86
+%define arg1 [ebp+04h]
+%define arg2 [ebp+08h]
+%define arg3 [ebp+0ch]
+%define MWSIZE 04h ;; machine word size
+%else
+%define MWSIZE 08h ;; machine word size
+%endif
+
+ %define buffer edi
+ %define bsize esi
+ %define safety edx
+
+%ifdef X86
+.Load_Arguments:
+
+ mov buffer, arg1
+ mov bsize, arg2
+ mov safety, arg3
+%endif
+
+.Validate_Pointer:
+
+ cmp buffer, 0
+ je .GenerateBlock_PreRet
+
+ ;; Top of While loop
+.GenerateBlock_Top:
+
+ ;; Check remaining size
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+%ifdef X86
+.Call_RDRAND_EAX:
+%else
+.Call_RDRAND_RAX:
+ DB 48h ;; X32 can use the full register, issue the REX.w prefix
+%endif
+ ;; RDRAND is not available prior to VS2012. Just emit
+ ;; the byte codes using DB. This is `rdrand eax`.
+ DB 0Fh, 07h, F0h
+
+ ;; If CF=1, the number returned by RDRAND is valid.
+ ;; If CF=0, a random number was not available.
+ jc .RDRAND_succeeded
+
+.RDRAND_failed:
+
+ ;; Exit if we've reached the limit
+ cmp safety, 0
+ je .GenerateBlock_Failure
+
+ dec safety
+ jmp .GenerateBlock_Top
+
+.RDRAND_succeeded:
+
+ cmp bsize, MWSIZE
+ jb .Partial_Machine_Word
+
+.Full_Machine_Word:
+
+%ifdef X32
+ mov [buffer+4], eax ;; We can only move 4 at a time
+ DB 048h ;; Combined, these result in
+ shr eax, 32 ;; `shr rax, 32`
+%endif
+
+ mov [buffer], eax
+ add buffer, MWSIZE ;; No need for Intel Core 2 slow word workarounds,
+ sub bsize, MWSIZE ;; like `lea buffer,[buffer+MWSIZE]` for faster adds
+
+ ;; Continue
+ jmp .GenerateBlock_Top
+
+ ;; 1,2,3 bytes remain for X86
+ ;; 1,2,3,4,5,6,7 remain for X32
+.Partial_Machine_Word:
+
+%ifdef X32
+ ;; Test bit 2 to see if size is at least 4
+ test bsize, 4
+ jz .Bit_2_Not_Set
+
+ mov [buffer], eax
+ add buffer, 4
+
+ DB 048h ;; Combined, these result in
+ shr eax, 32 ;; `shr rax, 32`
+
+.Bit_2_Not_Set:
+%endif
+
+ ;; Test bit 1 to see if size is at least 2
+ test bsize, 2
+ jz .Bit_1_Not_Set
+
+ mov [buffer], ax
+ shr eax, 16
+ add buffer, 2
+
+.Bit_1_Not_Set:
+
+ ;; Test bit 0 to see if size is at least 1
+ test bsize, 1
+ jz .GenerateBlock_Success
+
+ mov [buffer], al
+
+.Bit_0_Not_Set:
+
+ ;; We've hit all the bits
+ jmp .GenerateBlock_Success
+
+.GenerateBlock_PreRet:
+
+ ;; Test for success (was the request completely fulfilled?)
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.GenerateBlock_Failure:
+
+ xor eax, eax
+ mov al, RDRAND_FAILURE
+ ret
+
+.GenerateBlock_Success:
+
+ xor eax, eax
+ mov al, RDRAND_SUCCESS
+ ret
+
+%endif ;; X86 and X32
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+%ifdef X64 ;; Set via the command line
+
+global NASM_RRA_GenerateBlock
+section .text
+align 16
+
+;; Arg1, byte* buffer
+;; Arg2, size_t bsize
+;; Arg3, unsigned int safety
+;; RAX (out): success (1), failure (0)
+
+NASM_RRA_GenerateBlock:
+
+%define MWSIZE 08h ;; machine word size
+%define buffer rdi
+%define bsize rsi
+%define safety edx
+
+ ;; No need for Load_Arguments due to fastcall
+
+.Validate_Pointer:
+
+ ;; Validate pointer
+ cmp buffer, 0
+ je .GenerateBlock_PreRet
+
+ ;; Top of While loop
+.GenerateBlock_Top:
+
+ ;; Check remaining size
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.Call_RDRAND_RAX:
+ ;; RDRAND is not available prior to VS2012. Just emit
+ ;; the byte codes using DB. This is `rdrand rax`.
+ DB 048h, 0Fh, 0C7h, 0F0h
+
+ ;; If CF=1, the number returned by RDRAND is valid.
+ ;; If CF=0, a random number was not available.
+ jc .RDRAND_succeeded
+
+.RDRAND_failed:
+
+ ;; Exit if we've reached the limit
+ cmp safety, 0h
+ je .GenerateBlock_Failure
+
+ dec safety
+ jmp .GenerateBlock_Top
+
+.RDRAND_succeeded:
+
+ cmp bsize, MWSIZE
+ jb .Partial_Machine_Word
+
+.Full_Machine_Word:
+
+ mov [buffer], rax
+ add buffer, MWSIZE
+ sub bsize, MWSIZE
+
+ ;; Continue
+ jmp .GenerateBlock_Top
+
+ ;; 1,2,3,4,5,6,7 bytes remain
+.Partial_Machine_Word:
+
+ ;; Test bit 2 to see if size is at least 4
+ test bsize, 4
+ jz .Bit_2_Not_Set
+
+ mov [buffer], eax
+ shr rax, 32
+ add buffer, 4
+
+.Bit_2_Not_Set:
+
+ ;; Test bit 1 to see if size is at least 2
+ test bsize, 2
+ jz .Bit_1_Not_Set
+
+ mov [buffer], ax
+ shr eax, 16
+ add buffer, 2
+
+.Bit_1_Not_Set:
+
+ ;; Test bit 0 to see if size is at least 1
+ test bsize, 1
+ jz .GenerateBlock_Success
+
+ mov [buffer], al
+
+.Bit_0_Not_Set:
+
+ ;; We've hit all the bits
+ jmp .GenerateBlock_Success
+
+.GenerateBlock_PreRet:
+
+ ;; Test for success (was the request completely fulfilled?)
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.GenerateBlock_Failure:
+
+ xor rax, rax
+ mov al, RDRAND_FAILURE
+ ret
+
+.GenerateBlock_Success:
+
+ xor rax, rax
+ mov al, RDRAND_SUCCESS
+ ret
+
+%endif ;; X64
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+%ifdef X86 or X32 ;; Set via the command line
+
+;; Arg1, byte* buffer
+;; Arg2, size_t bsize
+;; Arg3, unsigned int safety
+;; EAX (out): success (1), failure (0)
+
+global NASM_RSA_GenerateBlock
+section .text
+align 8
+
+%ifdef X86
+align 8
+cpu 486
+%else
+align 16
+%endif
+
+NASM_RSA_GenerateBlock:
+
+%ifdef X86
+%define arg1 [ebp+04h]
+%define arg2 [ebp+08h]
+%define arg3 [ebp+0ch]
+%define MWSIZE 04h ;; machine word size
+%else
+%define MWSIZE 08h ;; machine word size
+%endif
+
+ %define buffer edi
+ %define bsize esi
+ %define safety edx
+
+%ifdef X86
+.Load_Arguments:
+
+ mov buffer, arg1
+ mov bsize, arg2
+ mov safety, arg3
+%endif
+
+.Validate_Pointer:
+
+ cmp buffer, 0
+ je .GenerateBlock_PreRet
+
+ ;; Top of While loop
+.GenerateBlock_Top:
+
+ ;; Check remaining size
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+%ifdef X86
+.Call_RDSEED_EAX:
+%else
+.Call_RDSEED_RAX:
+ DB 48h ;; X32 can use the full register, issue the REX.w prefix
+%endif
+ ;; RDSEED is not available prior to VS2012. Just emit
+ ;; the byte codes using DB. This is `rdseed eax`.
+ DB 0Fh, 0C7h, 0F8h
+
+ ;; If CF=1, the number returned by RDSEED is valid.
+ ;; If CF=0, a random number was not available.
+ jc .RDSEED_succeeded
+
+.RDSEED_failed:
+
+ ;; Exit if we've reached the limit
+ cmp safety, 0
+ je .GenerateBlock_Failure
+
+ dec safety
+ jmp .GenerateBlock_Top
+
+.RDSEED_succeeded:
+
+ cmp bsize, MWSIZE
+ jb .Partial_Machine_Word
+
+.Full_Machine_Word:
+
+ mov [buffer], eax
+ add buffer, MWSIZE ;; No need for Intel Core 2 slow word workarounds,
+ sub bsize, MWSIZE ;; like `lea buffer,[buffer+MWSIZE]` for faster adds
+
+ ;; Continue
+ jmp .GenerateBlock_Top
+
+ ;; 1,2,3 bytes remain for X86
+ ;; 1,2,3,4,5,6,7 remain for X32
+.Partial_Machine_Word:
+
+%ifdef X32
+ ;; Test bit 2 to see if size is at least 4
+ test bsize, 4
+ jz .Bit_2_Not_Set
+
+ mov [buffer], eax
+ add buffer, 4
+
+ DB 048h ;; Combined, these result in
+ shr eax, 32 ;; `shr rax, 32`
+
+.Bit_2_Not_Set:
+%endif
+
+ ;; Test bit 1 to see if size is at least 2
+ test bsize, 2
+ jz .Bit_1_Not_Set
+
+ mov [buffer], ax
+ shr eax, 16
+ add buffer, 2
+
+.Bit_1_Not_Set:
+
+ ;; Test bit 0 to see if size is at least 1
+ test bsize, 1
+ jz .GenerateBlock_Success
+
+ mov [buffer], al
+
+.Bit_0_Not_Set:
+
+ ;; We've hit all the bits
+ jmp .GenerateBlock_Success
+
+.GenerateBlock_PreRet:
+
+ ;; Test for success (was the request completely fulfilled?)
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.GenerateBlock_Failure:
+
+ xor eax, eax
+ mov al, RDSEED_FAILURE
+ ret
+
+.GenerateBlock_Success:
+
+ xor eax, eax
+ mov al, RDSEED_SUCCESS
+ ret
+
+%endif ;; X86 and X32
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+%ifdef X64 ;; Set via the command line
+
+global NASM_RSA_GenerateBlock
+section .text
+align 16
+
+;; Arg1, byte* buffer
+;; Arg2, size_t bsize
+;; Arg3, unsigned int safety
+;; RAX (out): success (1), failure (0)
+
+NASM_RSA_GenerateBlock:
+
+%define MWSIZE 08h ;; machine word size
+%define buffer rdi
+%define bsize rsi
+%define safety edx
+
+ ;; No need for Load_Arguments due to fastcall
+
+.Validate_Pointer:
+
+ ;; Validate pointer
+ cmp buffer, 0
+ je .GenerateBlock_PreRet
+
+ ;; Top of While loop
+.GenerateBlock_Top:
+
+ ;; Check remaining size
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.Call_RDSEED_RAX:
+ ;; RDSEED is not available prior to VS2012. Just emit
+ ;; the byte codes using DB. This is `rdseed rax`.
+ DB 048h, 0Fh, 0C7h, 0F8h
+
+ ;; If CF=1, the number returned by RDSEED is valid.
+ ;; If CF=0, a random number was not available.
+ jc .RDSEED_succeeded
+
+.RDSEED_failed:
+
+ ;; Exit if we've reached the limit
+ cmp safety, 0
+ je .GenerateBlock_Failure
+
+ dec safety
+ jmp .GenerateBlock_Top
+
+.RDSEED_succeeded:
+
+ cmp bsize, MWSIZE
+ jb .Partial_Machine_Word
+
+.Full_Machine_Word:
+
+ mov [buffer], rax
+ add buffer, MWSIZE
+ sub bsize, MWSIZE
+
+ ;; Continue
+ jmp .GenerateBlock_Top
+
+ ;; 1,2,3,4,5,6,7 bytes remain
+.Partial_Machine_Word:
+
+ ;; Test bit 2 to see if size is at least 4
+ test bsize, 4
+ jz .Bit_2_Not_Set
+
+ mov [buffer], eax
+ shr rax, 32
+ add buffer, 4
+
+.Bit_2_Not_Set:
+
+ ;; Test bit 1 to see if size is at least 2
+ test bsize, 2
+ jz .Bit_1_Not_Set
+
+ mov [buffer], ax
+ shr eax, 16
+ add buffer, 2
+
+.Bit_1_Not_Set:
+
+ ;; Test bit 0 to see if size is at least 1
+ test bsize, 1
+ jz .GenerateBlock_Success
+
+ mov [buffer], al
+
+.Bit_0_Not_Set:
+
+ ;; We've hit all the bits
+ jmp .GenerateBlock_Success
+
+.GenerateBlock_PreRet:
+
+ ;; Test for success (was the request completely fulfilled?)
+ cmp bsize, 0
+ je .GenerateBlock_Success
+
+.GenerateBlock_Failure:
+
+ xor rax, rax
+ mov al, RDSEED_FAILURE
+ ret
+
+.GenerateBlock_Success:
+
+ xor rax, rax
+ mov al, RDSEED_SUCCESS
+ ret
+
+%endif ;; _M_X64
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+