Cleared issues 11,12,13 (Clang integrated assembler), 58 (RC rollup), 66 (Coverity rollup)
parent
1993a8b7b9
commit
d2fda9bd42
|
|
@ -0,0 +1,393 @@
|
|||
3way.cpp
|
||||
3way.h
|
||||
adhoc.cpp.proto
|
||||
adler32.cpp
|
||||
adler32.h
|
||||
aes.h
|
||||
algebra.cpp
|
||||
algebra.h
|
||||
algparam.cpp
|
||||
algparam.h
|
||||
arc4.cpp
|
||||
arc4.h
|
||||
argnames.h
|
||||
asn.cpp
|
||||
asn.h
|
||||
authenc.cpp
|
||||
authenc.h
|
||||
base32.cpp
|
||||
base32.h
|
||||
base64.cpp
|
||||
base64.h
|
||||
basecode.cpp
|
||||
basecode.h
|
||||
bench.cpp
|
||||
bench.h
|
||||
bench2.cpp
|
||||
bfinit.cpp
|
||||
blowfish.cpp
|
||||
blowfish.h
|
||||
blumshub.cpp
|
||||
blumshub.h
|
||||
camellia.cpp
|
||||
camellia.h
|
||||
cast.cpp
|
||||
cast.h
|
||||
casts.cpp
|
||||
cbcmac.cpp
|
||||
cbcmac.h
|
||||
ccm.cpp
|
||||
ccm.h
|
||||
channels.cpp
|
||||
channels.h
|
||||
cmac.cpp
|
||||
cmac.h
|
||||
config.h
|
||||
config.recommend
|
||||
cpu.cpp
|
||||
cpu.h
|
||||
crc.cpp
|
||||
crc.h
|
||||
cryptdll.dsp
|
||||
cryptdll.vcproj
|
||||
cryptest.dsp
|
||||
cryptest.dsw
|
||||
cryptest.sh
|
||||
cryptest.sln
|
||||
cryptest.vcproj
|
||||
cryptest_bds.bdsgroup
|
||||
cryptest_bds.bdsproj
|
||||
cryptest_bds.bpf
|
||||
cryptlib.cpp
|
||||
cryptlib.dsp
|
||||
cryptlib.h
|
||||
cryptlib.vcproj
|
||||
cryptlib_bds.bdsproj
|
||||
cryptlib_bds.cpp
|
||||
cryptopp.rc
|
||||
cryptopp563.diff
|
||||
datatest.cpp
|
||||
default.cpp
|
||||
default.h
|
||||
des.cpp
|
||||
des.h
|
||||
dessp.cpp
|
||||
dh.cpp
|
||||
dh.h
|
||||
dh2.cpp
|
||||
dh2.h
|
||||
dll.cpp
|
||||
dll.h
|
||||
dlltest.cpp
|
||||
dlltest.dsp
|
||||
dlltest.vcproj
|
||||
dmac.h
|
||||
dsa.cpp
|
||||
dsa.h
|
||||
eax.cpp
|
||||
eax.h
|
||||
ec2n.cpp
|
||||
ec2n.h
|
||||
eccrypto.cpp
|
||||
eccrypto.h
|
||||
ecp.cpp
|
||||
ecp.h
|
||||
elgamal.cpp
|
||||
elgamal.h
|
||||
emsa2.cpp
|
||||
emsa2.h
|
||||
eprecomp.cpp
|
||||
eprecomp.h
|
||||
esign.cpp
|
||||
esign.h
|
||||
factory.h
|
||||
files.cpp
|
||||
files.h
|
||||
filters.cpp
|
||||
filters.h
|
||||
fips140.cpp
|
||||
fips140.h
|
||||
fipsalgt.cpp
|
||||
fipstest.cpp
|
||||
fltrimpl.h
|
||||
gcm.cpp
|
||||
gcm.h
|
||||
gf256.cpp
|
||||
gf256.h
|
||||
gf2_32.cpp
|
||||
gf2_32.h
|
||||
gf2n.cpp
|
||||
gf2n.h
|
||||
gfpcrypt.cpp
|
||||
gfpcrypt.h
|
||||
gost.cpp
|
||||
gost.h
|
||||
gzip.cpp
|
||||
gzip.h
|
||||
hex.cpp
|
||||
hex.h
|
||||
hkdf.h
|
||||
hmac.cpp
|
||||
hmac.h
|
||||
hrtimer.cpp
|
||||
hrtimer.h
|
||||
ida.cpp
|
||||
ida.h
|
||||
idea.cpp
|
||||
idea.h
|
||||
integer.cpp
|
||||
integer.h
|
||||
iterhash.cpp
|
||||
iterhash.h
|
||||
lubyrack.h
|
||||
luc.cpp
|
||||
luc.h
|
||||
mars.cpp
|
||||
mars.h
|
||||
marss.cpp
|
||||
md2.cpp
|
||||
md2.h
|
||||
md4.cpp
|
||||
md4.h
|
||||
md5.cpp
|
||||
md5.h
|
||||
mdc.h
|
||||
mersenne.h
|
||||
misc.cpp
|
||||
misc.h
|
||||
modarith.h
|
||||
modes.cpp
|
||||
modes.h
|
||||
modexppc.h
|
||||
mqueue.cpp
|
||||
mqueue.h
|
||||
mqv.cpp
|
||||
mqv.h
|
||||
nbtheory.cpp
|
||||
nbtheory.h
|
||||
network.cpp
|
||||
network.h
|
||||
nr.h
|
||||
oaep.cpp
|
||||
oaep.h
|
||||
oids.h
|
||||
osrng.cpp
|
||||
osrng.h
|
||||
panama.cpp
|
||||
panama.h
|
||||
pch.cpp
|
||||
pch.h
|
||||
pkcspad.cpp
|
||||
pkcspad.h
|
||||
polynomi.cpp
|
||||
polynomi.h
|
||||
pssr.cpp
|
||||
pssr.h
|
||||
pubkey.cpp
|
||||
pubkey.h
|
||||
pwdbased.h
|
||||
queue.cpp
|
||||
queue.h
|
||||
rabin.cpp
|
||||
rabin.h
|
||||
randpool.cpp
|
||||
randpool.h
|
||||
rc2.cpp
|
||||
rc2.h
|
||||
rc5.cpp
|
||||
rc5.h
|
||||
rc6.cpp
|
||||
rc6.h
|
||||
rdrand-masm.cmd
|
||||
rdrand-nasm.sh
|
||||
rdrand.S
|
||||
rdrand.asm
|
||||
rdrand.cpp
|
||||
rdrand.h
|
||||
rdtables.cpp
|
||||
regtest.cpp
|
||||
resource.h
|
||||
rijndael.cpp
|
||||
rijndael.h
|
||||
ripemd.cpp
|
||||
ripemd.h
|
||||
rng.cpp
|
||||
rng.h
|
||||
rsa.cpp
|
||||
rsa.h
|
||||
rw.cpp
|
||||
rw.h
|
||||
safer.cpp
|
||||
safer.h
|
||||
salsa.cpp
|
||||
salsa.h
|
||||
seal.cpp
|
||||
seal.h
|
||||
secblock.h
|
||||
seckey.h
|
||||
seed.cpp
|
||||
seed.h
|
||||
serpent.cpp
|
||||
serpent.h
|
||||
serpentp.h
|
||||
sha.cpp
|
||||
sha.h
|
||||
sha3.cpp
|
||||
sha3.h
|
||||
shacal2.cpp
|
||||
shacal2.h
|
||||
shark.cpp
|
||||
shark.h
|
||||
sharkbox.cpp
|
||||
simple.cpp
|
||||
simple.h
|
||||
skipjack.cpp
|
||||
skipjack.h
|
||||
smartptr.h
|
||||
socketft.cpp
|
||||
socketft.h
|
||||
sosemanuk.cpp
|
||||
sosemanuk.h
|
||||
square.cpp
|
||||
square.h
|
||||
squaretb.cpp
|
||||
stdcpp.h
|
||||
strciphr.cpp
|
||||
strciphr.h
|
||||
tea.cpp
|
||||
tea.h
|
||||
test.cpp
|
||||
tftables.cpp
|
||||
tiger.cpp
|
||||
tiger.h
|
||||
tigertab.cpp
|
||||
trdlocal.cpp
|
||||
trdlocal.h
|
||||
trunhash.h
|
||||
ttmac.cpp
|
||||
ttmac.h
|
||||
twofish.cpp
|
||||
twofish.h
|
||||
validat1.cpp
|
||||
validat2.cpp
|
||||
validat3.cpp
|
||||
validate.h
|
||||
vmac.cpp
|
||||
vmac.h
|
||||
vs2010.zip
|
||||
wait.cpp
|
||||
wait.h
|
||||
wake.cpp
|
||||
wake.h
|
||||
whrlpool.cpp
|
||||
whrlpool.h
|
||||
winpipes.cpp
|
||||
winpipes.h
|
||||
words.h
|
||||
x64dll.asm
|
||||
x64masm.asm
|
||||
xtr.cpp
|
||||
xtr.h
|
||||
xtrcrypt.cpp
|
||||
xtrcrypt.h
|
||||
zdeflate.cpp
|
||||
zdeflate.h
|
||||
zinflate.cpp
|
||||
zinflate.h
|
||||
zlib.cpp
|
||||
zlib.h
|
||||
Doxyfile
|
||||
GNUmakefile
|
||||
GNUmakefile-cross
|
||||
License.txt
|
||||
Readme.txt
|
||||
Install.txt
|
||||
Filelist.txt
|
||||
TestData/3desval.dat
|
||||
TestData/3wayval.dat
|
||||
TestData/camellia.dat
|
||||
TestData/cast128v.dat
|
||||
TestData/cast256v.dat
|
||||
TestData/descert.dat
|
||||
TestData/dh1024.dat
|
||||
TestData/dh2048.dat
|
||||
TestData/dlie1024.dat
|
||||
TestData/dlie2048.dat
|
||||
TestData/dsa1024.dat
|
||||
TestData/dsa1024b.dat
|
||||
TestData/dsa512.dat
|
||||
TestData/elgc1024.dat
|
||||
TestData/esig1023.dat
|
||||
TestData/esig1536.dat
|
||||
TestData/esig2046.dat
|
||||
TestData/gostval.dat
|
||||
TestData/ideaval.dat
|
||||
TestData/luc1024.dat
|
||||
TestData/luc2048.dat
|
||||
TestData/lucc1024.dat
|
||||
TestData/lucc512.dat
|
||||
TestData/lucd1024.dat
|
||||
TestData/lucd512.dat
|
||||
TestData/lucs1024.dat
|
||||
TestData/lucs512.dat
|
||||
TestData/marsval.dat
|
||||
TestData/mqv1024.dat
|
||||
TestData/mqv2048.dat
|
||||
TestData/nr1024.dat
|
||||
TestData/nr2048.dat
|
||||
TestData/rabi1024.dat
|
||||
TestData/rabi2048.dat
|
||||
TestData/rc2val.dat
|
||||
TestData/rc5val.dat
|
||||
TestData/rc6val.dat
|
||||
TestData/rijndael.dat
|
||||
TestData/rsa1024.dat
|
||||
TestData/rsa2048.dat
|
||||
TestData/rsa400pb.dat
|
||||
TestData/rsa400pv.dat
|
||||
TestData/rsa512a.dat
|
||||
TestData/rw1024.dat
|
||||
TestData/rw2048.dat
|
||||
TestData/saferval.dat
|
||||
TestData/serpentv.dat
|
||||
TestData/shacal2v.dat
|
||||
TestData/sharkval.dat
|
||||
TestData/skipjack.dat
|
||||
TestData/squareva.dat
|
||||
TestData/twofishv.dat
|
||||
TestData/usage.dat
|
||||
TestData/xtrdh171.dat
|
||||
TestData/xtrdh342.dat
|
||||
TestVectors/Readme.txt
|
||||
TestVectors/aes.txt
|
||||
TestVectors/all.txt
|
||||
TestVectors/camellia.txt
|
||||
TestVectors/ccm.txt
|
||||
TestVectors/cmac.txt
|
||||
TestVectors/dlies.txt
|
||||
TestVectors/dsa.txt
|
||||
TestVectors/dsa_1363.txt
|
||||
TestVectors/eax.txt
|
||||
TestVectors/esign.txt
|
||||
TestVectors/gcm.txt
|
||||
TestVectors/hkdf.txt
|
||||
TestVectors/hmac.txt
|
||||
TestVectors/mars.txt
|
||||
TestVectors/nr.txt
|
||||
TestVectors/panama.txt
|
||||
TestVectors/rsa_oaep.txt
|
||||
TestVectors/rsa_pkcs1_1_5.txt
|
||||
TestVectors/rsa_pss.txt
|
||||
TestVectors/rw.txt
|
||||
TestVectors/salsa.txt
|
||||
TestVectors/seal.txt
|
||||
TestVectors/seed.txt
|
||||
TestVectors/sha.txt
|
||||
TestVectors/sha3.txt
|
||||
TestVectors/shacal2.txt
|
||||
TestVectors/sosemanuk.txt
|
||||
TestVectors/tea.txt
|
||||
TestVectors/ttmac.txt
|
||||
TestVectors/vmac.txt
|
||||
TestVectors/wake.txt
|
||||
TestVectors/whrlpool.txt
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
REM make-rdrand
|
||||
@echo OFF
|
||||
|
||||
@cls
|
||||
|
||||
@del rdrand.obj rdrand-x86.obj rdrand-x64.obj rdrand-x86.lib rdrand-x64.lib /Q > nul
|
||||
|
||||
REM Visual Studio 2005
|
||||
REM @set TOOLS32=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin
|
||||
REM @set TOOLS64=C:\Program Files (x86)\Microsoft Visual Studio 8\VC\bin\amd64
|
||||
|
||||
REM Visual Studio 2010
|
||||
REM @set TOOLS32=C:\Program Files (x86)\Microsoft Visual Studio 10\VC\bin
|
||||
REM @set TOOLS64=C:\Program Files (x86)\Microsoft Visual Studio 10\VC\bin\amd64
|
||||
|
||||
REM Visual Studio 2012
|
||||
REM @set TOOLS32=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin
|
||||
REM @set TOOLS64=C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64
|
||||
|
||||
REM Visual Studio 2013
|
||||
@set TOOLS32=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin
|
||||
@set TOOLS64=C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\bin\amd64
|
||||
|
||||
@set MASM="%TOOLS32%\ml.exe"
|
||||
@set MASM64="%TOOLS64%\ml64.exe"
|
||||
@set DUMPBIN="%TOOLS32%\dumpbin.exe"
|
||||
@set LIBTOOL="%TOOLS32%\lib.exe"
|
||||
|
||||
REM /W3 - Warning level
|
||||
REM /Cx - Preserve case in external symbols
|
||||
REM /Zi - Porgram Database information
|
||||
@set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
|
||||
@set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
|
||||
@set LIBFLAGS=/nologo /SUBSYSTEM:CONSOLE
|
||||
|
||||
REM Use _M_X86 and _M_X64 becuase cl.exe uses them. It keeps preprocessor defines consistent.
|
||||
echo ****************************************
|
||||
echo Assembling rdrand.asm into rdrand-x86.obj
|
||||
call %MASM% %ASFLAGS% /Fo rdrand-x86.obj /c rdrand.asm > nul
|
||||
@IF NOT %ERRORLEVEL% EQU 0 (echo Failed to assemble rdrand.asm with X86 && goto SCRIPT_FAILED)
|
||||
echo Done...
|
||||
|
||||
echo ****************************************
|
||||
echo Assembling rdrand.asm into rdrand-x64.obj
|
||||
call %MASM64% %ASFLAGS64% /Fo rdrand-x64.obj /c rdrand.asm > nul
|
||||
@IF NOT %ERRORLEVEL% EQU 0 (echo Failed to assemble rdrand.asm with X64 && goto SCRIPT_FAILED)
|
||||
echo Done...
|
||||
|
||||
echo ****************************************
|
||||
echo Creating static library rdrand-x86.lib
|
||||
call %LIBTOOL% %LIBFLAGS% /MACHINE:X86 /OUT:rdrand-x86.lib rdrand-x86.obj > nul
|
||||
@IF NOT %ERRORLEVEL% EQU 0 (echo Failed to create rdrand-x86.lib && goto SCRIPT_FAILED)
|
||||
echo Done...
|
||||
|
||||
echo ****************************************
|
||||
echo Creating static library rdrand-x64.lib
|
||||
call %LIBTOOL% %LIBFLAGS% /MACHINE:X64 /OUT:rdrand-x64.lib rdrand-x64.obj > nul
|
||||
@IF NOT %ERRORLEVEL% EQU 0 (echo Failed to create rdrand-x64.lib && goto SCRIPT_FAILED)
|
||||
echo Done...
|
||||
|
||||
goto SKIP_SYMBOL_DUMP_OBJ
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping symbols for rdrand-x86.obj
|
||||
echo.
|
||||
call %DUMPBIN% /SYMBOLS rdrand-x86.obj
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping symbols for rdrand-x64.obj
|
||||
echo.
|
||||
call %DUMPBIN% /SYMBOLS rdrand-x64.obj
|
||||
|
||||
:SKIP_SYMBOL_DUMP_OBJ
|
||||
|
||||
goto SKIP_SYMBOL_DUMP_LIB
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping symbols for rdrand-x86.lib
|
||||
echo.
|
||||
call %DUMPBIN% /SYMBOLS rdrand-x86.lib
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping symbols for rdrand-x64.lib
|
||||
echo.
|
||||
call %DUMPBIN% /SYMBOLS rdrand-x64.lib
|
||||
|
||||
:SKIP_SYMBOL_DUMP_LIB
|
||||
|
||||
goto SKIP_EXPORT_DUMP
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping exports for rdrand-x86.lib
|
||||
echo.
|
||||
call %DUMPBIN% /EXPORTS rdrand-x86.lib
|
||||
|
||||
echo ****************************************
|
||||
echo Dumping exports for rdrand-x64.lib
|
||||
echo.
|
||||
call %DUMPBIN% /EXPORTS rdrand-x64.lib
|
||||
|
||||
:SKIP_EXPORT_DUMP
|
||||
|
||||
REM goto SKIP_DISASSEMBLY
|
||||
|
||||
echo ****************************************
|
||||
echo Disassembling rdrand-x64.obj
|
||||
echo.
|
||||
call %DUMPBIN% /DISASM:NOBYTES rdrand-x64.obj
|
||||
|
||||
echo ****************************************
|
||||
echo Disassembling rdrand-x86.obj
|
||||
echo.
|
||||
call %DUMPBIN% /DISASM:NOBYTES rdrand-x86.obj
|
||||
|
||||
:SKIP_DISASSEMBLY
|
||||
|
||||
:SCRIPT_FAILED
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/sh
|
||||
|
||||
reset
|
||||
|
||||
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
|
||||
|
||||
echo "**************************************"
|
||||
echo "**************************************"
|
||||
|
||||
objdump --disassemble rdrand-x86.o
|
||||
|
||||
echo
|
||||
echo "**************************************"
|
||||
echo "**************************************"
|
||||
|
||||
objdump --disassemble rdrand-x32.o
|
||||
|
||||
echo
|
||||
echo "**************************************"
|
||||
echo "**************************************"
|
||||
|
||||
objdump --disassemble rdrand-x64.o
|
||||
|
|
@ -0,0 +1,599 @@
|
|||
;; 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
|
||||
|
||||
;; Caller/Callee Saved Registers
|
||||
;; https://msdn.microsoft.com/en-us/library/6t169e9c.aspx
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
;; 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
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
110
rdrand.asm
110
rdrand.asm
|
|
@ -1,10 +1,9 @@
|
|||
;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
|
||||
;; Copyright assigned to the Crypto++ project.
|
||||
|
||||
;; This ASM file exists for one reason only - to emit the RDRAND instruction for Microsoft platforms.
|
||||
;; We can't call RDRAND directly on some versions of the toolchain (prior to CL 17.00/VS2012).
|
||||
;; Additionally, Microsoft/Intel penalizes AMD CPUs with the feature. To avoid these troubles, we
|
||||
;; provide the ASM and emit the opcodes for RDRAND by hand.
|
||||
;; This ASM file provides RDRAND and RDSEED to downlevel Microsoft tool chains.
|
||||
;; Everything "just works" under Visual Studio. Other platforms will have to
|
||||
;; run MASM/MASM-64 and then link to the object files.
|
||||
|
||||
;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
|
||||
;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
|
||||
|
|
@ -14,11 +13,11 @@
|
|||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
||||
TITLE MSC_RRA_GenerateBlock and MSC_RSA_GenerateBlock
|
||||
TITLE MASM_RRA_GenerateBlock and MASM_RSA_GenerateBlock
|
||||
SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains
|
||||
|
||||
PUBLIC MSC_RRA_GenerateBlock
|
||||
PUBLIC MSC_RSA_GenerateBlock
|
||||
PUBLIC MASM_RRA_GenerateBlock
|
||||
PUBLIC MASM_RSA_GenerateBlock
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
@ -26,6 +25,7 @@ PUBLIC MSC_RSA_GenerateBlock
|
|||
;; Naming convention used in rdrand.{h|cpp|asm}
|
||||
;; 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
|
||||
|
|
@ -39,9 +39,9 @@ PUBLIC MSC_RSA_GenerateBlock
|
|||
|
||||
;; C/C++ Function prototypes
|
||||
;; X86:
|
||||
;; extern "C" int MSC_RRA_GenerateBlock(byte* ptr, size_t size, unsigned int safety);
|
||||
;; extern "C" int MASM_RRA_GenerateBlock(byte* ptr, size_t size, unsigned int safety);
|
||||
;; X64:
|
||||
;; extern "C" int __fastcall MSC_RRA_GenerateBlock(byte* ptr, size_t size, unsigned int safety);
|
||||
;; extern "C" int __fastcall MASM_RRA_GenerateBlock(byte* ptr, size_t size, unsigned int safety);
|
||||
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||
|
|
@ -79,8 +79,7 @@ OPTION EPILOGUE:NONE
|
|||
;; Base relative (in): arg3, unsigned int safety
|
||||
;; EAX (out): success (1), failure (0)
|
||||
|
||||
;; MSC_RRA_GenerateBlock PROC USES ecx edx edi arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
MSC_RRA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
MASM_RRA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
|
||||
MWSIZE EQU 04h ;; machine word size
|
||||
buffer EQU edi
|
||||
|
|
@ -108,7 +107,7 @@ GenerateBlock_Top:
|
|||
Call_RDRAND_EAX:
|
||||
;; RDRAND is not available prior to VS2012. Just emit
|
||||
;; the byte codes using DB. This is `rdrand eax`.
|
||||
DB 0Fh, 0C7h, 0F0h
|
||||
DB 0Fh, 0C7h, 0F0h
|
||||
|
||||
;; If CF=1, the number returned by RDRAND is valid.
|
||||
;; If CF=0, a random number was not available.
|
||||
|
|
@ -152,15 +151,13 @@ Bit_1_Not_Set:
|
|||
|
||||
;; Test bit 0 to see if size is at least 1
|
||||
test bsize, 1
|
||||
;; jz Bit_0_Not_Set
|
||||
jz GenerateBlock_Success
|
||||
|
||||
mov BYTE PTR [buffer], al
|
||||
|
||||
Bit_0_Not_Set:
|
||||
|
||||
;; We've hit all the bits, set size to 0
|
||||
;; mov bsize, 0
|
||||
;; We've hit all the bits
|
||||
jmp GenerateBlock_Success
|
||||
|
||||
GenerateBlock_PreRet:
|
||||
|
|
@ -171,18 +168,17 @@ GenerateBlock_PreRet:
|
|||
|
||||
GenerateBlock_Failure:
|
||||
|
||||
mov eax, RDRAND_FAILURE
|
||||
jmp GenerateBlock_Ret
|
||||
xor eax, eax
|
||||
mov al, RDRAND_FAILURE
|
||||
ret
|
||||
|
||||
GenerateBlock_Success:
|
||||
|
||||
mov eax, RDRAND_SUCCESS
|
||||
|
||||
GenerateBlock_Ret:
|
||||
|
||||
xor eax, eax
|
||||
mov al, RDRAND_SUCCESS
|
||||
ret
|
||||
|
||||
MSC_RRA_GenerateBlock ENDP
|
||||
MASM_RRA_GenerateBlock ENDP
|
||||
|
||||
ENDIF ;; _M_X86
|
||||
|
||||
|
|
@ -201,8 +197,7 @@ OPTION EPILOGUE:NONE
|
|||
;; R8d (in): arg3, unsigned int safety
|
||||
;; RAX (out): success (1), failure (0)
|
||||
|
||||
;; MSC_RRA_GenerateBlock PROC USES RCX ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||
MSC_RRA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||
MASM_RRA_GenerateBlock PROC
|
||||
|
||||
MWSIZE EQU 08h ;; machine word size
|
||||
buffer EQU rcx
|
||||
|
|
@ -227,7 +222,7 @@ GenerateBlock_Top:
|
|||
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
|
||||
DB 048h, 0Fh, 0C7h, 0F0h
|
||||
|
||||
;; If CF=1, the number returned by RDRAND is valid.
|
||||
;; If CF=0, a random number was not available.
|
||||
|
|
@ -281,15 +276,13 @@ Bit_1_Not_Set:
|
|||
|
||||
;; Test bit 0 to see if size is at least 1
|
||||
test bsize, 1
|
||||
;; jz Bit_0_Not_Set
|
||||
jz GenerateBlock_Success
|
||||
|
||||
mov BYTE PTR [buffer], al
|
||||
|
||||
Bit_0_Not_Set:
|
||||
|
||||
;; We've hit all the bits, set size to 0
|
||||
;; mov bsize, 0
|
||||
;; We've hit all the bits
|
||||
jmp GenerateBlock_Success
|
||||
|
||||
GenerateBlock_PreRet:
|
||||
|
|
@ -300,18 +293,17 @@ GenerateBlock_PreRet:
|
|||
|
||||
GenerateBlock_Failure:
|
||||
|
||||
mov rax, RDRAND_FAILURE
|
||||
jmp GenerateBlock_Ret
|
||||
xor rax, rax
|
||||
mov al, RDRAND_FAILURE
|
||||
ret
|
||||
|
||||
GenerateBlock_Success:
|
||||
|
||||
mov rax, RDRAND_SUCCESS
|
||||
|
||||
GenerateBlock_Ret:
|
||||
|
||||
xor rax, rax
|
||||
mov al, RDRAND_SUCCESS
|
||||
ret
|
||||
|
||||
MSC_RRA_GenerateBlock ENDP
|
||||
MASM_RRA_GenerateBlock ENDP
|
||||
|
||||
ENDIF ;; _M_X64
|
||||
|
||||
|
|
@ -331,8 +323,7 @@ OPTION EPILOGUE:NONE
|
|||
;; Base relative (in): arg3, unsigned int safety
|
||||
;; EAX (out): success (1), failure (0)
|
||||
|
||||
;; MSC_RSA_GenerateBlock PROC USES ecx edx edi arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
MSC_RSA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
MASM_RSA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||
|
||||
MWSIZE EQU 04h ;; machine word size
|
||||
buffer EQU edi
|
||||
|
|
@ -347,20 +338,20 @@ Load_Arguments:
|
|||
|
||||
Validate_Pointer:
|
||||
|
||||
cmp buffer, 0
|
||||
je GenerateBlock_PreRet
|
||||
cmp buffer, 0
|
||||
je GenerateBlock_PreRet
|
||||
|
||||
;; Top of While loop
|
||||
GenerateBlock_Top:
|
||||
|
||||
;; Check remaining size
|
||||
cmp bsize, 0
|
||||
cmp bsize, 0
|
||||
je GenerateBlock_Success
|
||||
|
||||
Call_RDSEED_EAX:
|
||||
;; RDSEED is not available prior to VS2012. Just emit
|
||||
;; the byte codes using DB. This is `rdseed eax`.
|
||||
DB 0Fh, 0C7h, 0F8h
|
||||
DB 0Fh, 0C7h, 0F8h
|
||||
|
||||
;; If CF=1, the number returned by RDSEED is valid.
|
||||
;; If CF=0, a random number was not available.
|
||||
|
|
@ -404,15 +395,13 @@ Bit_1_Not_Set:
|
|||
|
||||
;; Test bit 0 to see if size is at least 1
|
||||
test bsize, 1
|
||||
;; jz Bit_0_Not_Set
|
||||
jz GenerateBlock_Success
|
||||
|
||||
mov BYTE PTR [buffer], al
|
||||
|
||||
Bit_0_Not_Set:
|
||||
|
||||
;; We've hit all the bits, set size to 0
|
||||
;; mov bsize, 0
|
||||
;; We've hit all the bits
|
||||
jmp GenerateBlock_Success
|
||||
|
||||
GenerateBlock_PreRet:
|
||||
|
|
@ -423,18 +412,17 @@ GenerateBlock_PreRet:
|
|||
|
||||
GenerateBlock_Failure:
|
||||
|
||||
mov eax, RDSEED_FAILURE
|
||||
jmp GenerateBlock_Ret
|
||||
xor eax, eax
|
||||
mov al, RDSEED_FAILURE
|
||||
ret
|
||||
|
||||
GenerateBlock_Success:
|
||||
|
||||
mov eax, RDSEED_SUCCESS
|
||||
|
||||
GenerateBlock_Ret:
|
||||
|
||||
xor eax, eax
|
||||
mov al, RDSEED_SUCCESS
|
||||
ret
|
||||
|
||||
MSC_RSA_GenerateBlock ENDP
|
||||
MASM_RSA_GenerateBlock ENDP
|
||||
|
||||
ENDIF ;; _M_X86
|
||||
|
||||
|
|
@ -453,8 +441,7 @@ OPTION EPILOGUE:NONE
|
|||
;; R8d (in): arg3, unsigned int safety
|
||||
;; RAX (out): success (1), failure (0)
|
||||
|
||||
;; MSC_RSA_GenerateBlock PROC USES RCX ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||
MSC_RSA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||
MASM_RSA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||
|
||||
MWSIZE EQU 08h ;; machine word size
|
||||
buffer EQU rcx
|
||||
|
|
@ -533,15 +520,13 @@ Bit_1_Not_Set:
|
|||
|
||||
;; Test bit 0 to see if size is at least 1
|
||||
test bsize, 1
|
||||
;; jz Bit_0_Not_Set
|
||||
jz GenerateBlock_Success
|
||||
|
||||
mov BYTE PTR [buffer], al
|
||||
|
||||
Bit_0_Not_Set:
|
||||
|
||||
;; We've hit all the bits, set size to 0
|
||||
;; mov bsize, 0
|
||||
;; We've hit all the bits
|
||||
jmp GenerateBlock_Success
|
||||
|
||||
GenerateBlock_PreRet:
|
||||
|
|
@ -552,18 +537,17 @@ GenerateBlock_PreRet:
|
|||
|
||||
GenerateBlock_Failure:
|
||||
|
||||
mov rax, RDSEED_FAILURE
|
||||
jmp GenerateBlock_Ret
|
||||
xor rax, rax
|
||||
mov al, RDSEED_FAILURE
|
||||
ret
|
||||
|
||||
GenerateBlock_Success:
|
||||
|
||||
mov rax, RDSEED_SUCCESS
|
||||
|
||||
GenerateBlock_Ret:
|
||||
|
||||
xor rax, rax
|
||||
mov al, RDSEED_SUCCESS
|
||||
ret
|
||||
|
||||
MSC_RSA_GenerateBlock ENDP
|
||||
MASM_RSA_GenerateBlock ENDP
|
||||
|
||||
ENDIF ;; _M_X64
|
||||
|
||||
|
|
|
|||
650
rdrand.cpp
650
rdrand.cpp
|
|
@ -20,225 +20,163 @@
|
|||
// available. A lazy throw strategy is used in case the CPU does not support
|
||||
// the instruction. I.e., the throw is deferred until GenerateBlock is called.
|
||||
|
||||
// For GCC/ICC/Clang on Unix/Linux/Apple, you can use `-mrdrnd` to force the
|
||||
// option. If you use `-mrdrnd`, then __RDRND__ is defined and intrinsics
|
||||
// are used. If you omit the otion, then assembly language routines are
|
||||
// used if the compiler supports RDRAND. The same applies to -mrdseed and
|
||||
// __RDSEED__ (but they did not skimp on the extra vowel). Also see
|
||||
// http://gcc.gnu.org/onlinedocs/gcc/x86-Built-in-Functions.html#x86-Built-in-Functions
|
||||
|
||||
// Here's the naming convention for the functions....
|
||||
// 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
|
||||
|
||||
// Helper macros. IA32_ASM captuers the architecture. MSC_RDRAND_COMPILER means
|
||||
// MSC_RDSEED_COMPILER; GCC_RDRAND_COMPILER means GCC_RDSEED_COMPILER.
|
||||
#define IA32_ASM (!defined(CRYPTOPP_DISABLE_ASM) && (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64))
|
||||
#define MSC_RDRAND_COMPILER ((CRYPTOPP_MSC_VERSION >= 1700) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||
#define GCC_RDRAND_COMPILER ((CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||
#define MSC_RDSEED_COMPILER MSC_RDRAND_COMPILER
|
||||
#define GCC_RDSEED_COMPILER GCC_RDRAND_COMPILER
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GCC cannot compile programs with __builtin_ia32_rdseed{16|32|64}_step
|
||||
#if __GNUC__
|
||||
# define GCC_RDSEED_INTRINSIC_AVAILABLE 0
|
||||
// For Linux, install NASM, run rdrand-nasm.asm, add the apppropriate
|
||||
// object file to the Makefile's LIBOBJS (rdrand-x{86|32|64}.o). After
|
||||
// that, define these. They are not enabled by default because they
|
||||
// are not easy to cut-in in the Makefile.
|
||||
|
||||
#if 0
|
||||
#define NASM_RDRAND_ASM_AVAILABLE 1
|
||||
#define NASM_RDSEED_ASM_AVAILABLE 1
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Microsoft uses Intel's intrinsics, and it excludes AMD's CPUs. You should
|
||||
// "#define MSC_RDRAND_INTRINSIC_AVAILABLE 0" and
|
||||
// "#define MSC_RDSEED_INTRINSIC_AVAILABLE 0", if possible. The downside is
|
||||
// you must assemble the object files rdrand-x86.obj and rdrand-x86.obj and
|
||||
// then build the rdrand-x86.lib and rdrand-x86.lib libraries. To build the
|
||||
// libraries run "make-rdrand.cmd" from a developer prompt.
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// MSC Compatible on Windows. Set MSC_RDRAND_ASM_AVAILABLE if it (and Intrinsics)
|
||||
// are not set. The requirement is rdrand.asm assembled with MASM/MAS64. We use
|
||||
// CRYTPOPP_MSC_VERSION as a proxy for MASM/MAS64 availability.
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && IA32_ASM && defined(CRYTPOPP_MSC_VERSION)
|
||||
# if !defined(MSC_RDRAND_ASM_AVAILABLE) && !(MSC_RDRAND_INTRINSIC_AVAILABLE > 0)
|
||||
# define MSC_RDRAND_ASM_AVAILABLE 1
|
||||
# define MSC_RDRAND_INTRINSIC_AVAILABLE 0
|
||||
// According to Wei, CRYPTOPP_DISABLE_ASM is a failsafe due to the assembler.
|
||||
// We sidestep it because it does not limit us. The assembler does not limit
|
||||
// us because we emit out own byte codes as needed. To diasble RDRAND or
|
||||
// RDSEED, set CRYPTOPP_BOOL_RDRAND_ASM or CRYPTOPP_BOOL_RDSEED_ASM to 0.
|
||||
#ifndef CRYPTOPP_CPUID_AVAILABLE
|
||||
# if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
# define CRYPTOPP_CPUID_AVAILABLE
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Fallback to MSC_RDRAND_INTRINSIC_AVAILABLE on Windows. The compiler must support it.
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && MSC_RDRAND_COMPILER
|
||||
# if !defined(MSC_RDRAND_INTRINSIC_AVAILABLE) && !(MSC_RDRAND_ASM_AVAILABLE > 0)
|
||||
# define MSC_RDRAND_INTRINSIC_AVAILABLE 1
|
||||
# define MSC_RDRAND_ASM_AVAILABLE 0
|
||||
# endif
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_BOOL_RDRAND_ASM)
|
||||
# define CRYPTOPP_BOOL_RDRAND_ASM 1
|
||||
#else
|
||||
# define CRYPTOPP_BOOL_RDRAND_ASM 0
|
||||
#endif
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_BOOL_RDSEED_ASM)
|
||||
# define CRYPTOPP_BOOL_RDSEED_ASM 1
|
||||
#else
|
||||
# define CRYPTOPP_BOOL_RDSEED_ASM 0
|
||||
#endif
|
||||
|
||||
// GCC Compatible on Unix/Linux/Apple. Set GCC_RDRAND_INTRINSIC_AVAILABLE if
|
||||
// it (and ASM) are not set. The requirements are __RDRND__ preprocessor.
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && GCC_RDRAND_COMPILER && (__RDRND__ >= 1)
|
||||
# if !defined(GCC_RDRAND_INTRINSIC_AVAILABLE) && !(defined(GCC_RDRAND_ASM_AVAILABLE) && (GCC_RDRAND_ASM_AVAILABLE > 0))
|
||||
# define GCC_RDRAND_INTRINSIC_AVAILABLE 1
|
||||
# define GCC_RDRAND_ASM_AVAILABLE 0
|
||||
# endif
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
# define MSC_INTRIN_COMPILER ((CRYPTOPP_MSC_VERSION >= 1700) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||
# define GCC_INTRIN_COMPILER ((CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||
#else
|
||||
# define MSC_INTRIN_COMPILER 0
|
||||
# define GCC_INTRIN_COMPILER 0
|
||||
#endif
|
||||
|
||||
// Fallback to MSC_ASM_INTRINSIC_AVAILABLE on Unix/Linux/Apple
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && IA32_ASM && GCC_RDRAND_COMPILER
|
||||
# if !defined(GCC_RDRAND_INTRINSIC_AVAILABLE) && !(defined(GCCC_RDRAND_ASM_AVAILABLE) && (GCCC_RDRAND_ASM_AVAILABLE > 0))
|
||||
# define GCC_RDRAND_ASM_AVAILABLE 1
|
||||
# define GCC_RDRAND_INTRINSIC_AVAILABLE 0
|
||||
# endif
|
||||
// In general, the library's ASM code is best on Windows, and Intrinsics is
|
||||
// the best code under GCC and compatibles. We favor them accordingly.
|
||||
// The NASM code is optimized well on Linux, but its not easy to cut-in.
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE) && (CRYPTOPP_MSC_VERSION >= 1200)
|
||||
# if CRYPTOPP_BOOL_RDRAND_ASM
|
||||
# define MASM_RDRAND_ASM_AVAILABLE 1
|
||||
# elif MSC_INTRIN_COMPILER
|
||||
# define ALL_RDRAND_INTRIN_AVAILABLE 1
|
||||
# endif
|
||||
# if CRYPTOPP_BOOL_RDSEED_ASM
|
||||
# define MASM_RDSEED_ASM_AVAILABLE 1
|
||||
# elif MSC_INTRIN_COMPILER
|
||||
# define ALL_RDSEED_INTRIN_AVAILABLE 1
|
||||
# endif
|
||||
#elif defined(CRYPTOPP_CPUID_AVAILABLE) && (CRYPTOPP_GCC_VERSION >= 30200)
|
||||
# if GCC_INTRIN_COMPILER && defined(__RDRND__)
|
||||
# define ALL_RDRAND_INTRIN_AVAILABLE 1
|
||||
# elif CRYPTOPP_BOOL_RDRAND_ASM
|
||||
# define GCC_RDRAND_ASM_AVAILABLE 1
|
||||
# endif
|
||||
# if GCC_INTRIN_COMPILER && defined(__RDSEED__)
|
||||
# define ALL_RDSEED_INTRIN_AVAILABLE 1
|
||||
# elif CRYPTOPP_BOOL_RDSEED_ASM
|
||||
# define GCC_RDSEED_ASM_AVAILABLE 1
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Debug diagnostics
|
||||
#if !defined(NDEBUG)
|
||||
# if MASM_RDRAND_ASM_AVAILABLE
|
||||
# pragma message ("MASM_RDRAND_ASM_AVAILABLE is 1")
|
||||
# elif NASM_RDRAND_ASM_AVAILABLE
|
||||
# pragma message ("NASM_RDRAND_ASM_AVAILABLE is 1")
|
||||
# elif GCC_RDRAND_ASM_AVAILABLE
|
||||
# pragma message ("GCC_RDRAND_ASM_AVAILABLE is 1")
|
||||
# elif ALL_RDRAND_INTRIN_AVAILABLE
|
||||
# pragma message ("ALL_RDRAND_INTRIN_AVAILABLE is 1")
|
||||
# else
|
||||
# pragma message ("RDRAND is not available")
|
||||
# endif
|
||||
# if MASM_RDSEED_ASM_AVAILABLE
|
||||
# pragma message ("MASM_RDSEED_ASM_AVAILABLE is 1")
|
||||
# elif NASM_RDSEED_ASM_AVAILABLE
|
||||
# pragma message ("NASM_RDSEED_ASM_AVAILABLE is 1")
|
||||
# elif GCC_RDSEED_ASM_AVAILABLE
|
||||
# pragma message ("GCC_RDSEED_ASM_AVAILABLE is 1")
|
||||
# elif ALL_RDSEED_INTRIN_AVAILABLE
|
||||
# pragma message ("ALL_RDSEED_INTRIN_AVAILABLE is 1")
|
||||
# else
|
||||
# pragma message ("RDSEED is not available")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// MSC Compatible on Windows. Set MSC_RDRAND_ASM_AVAILABLE if it (and Intrinsics)
|
||||
// are not set. The requirement is rdrand.asm assembled with MASM/MAS64. We use
|
||||
// CRYTPOPP_MSC_VERSION as a proxy for MASM/MAS64 availability.
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && IA32_ASM && defined(CRYTPOPP_MSC_VERSION)
|
||||
# if !defined(MSC_RDSEED_ASM_AVAILABLE) && !(MSC_RDSEED_INTRINSIC_AVAILABLE > 0)
|
||||
# define MSC_RDSEED_ASM_AVAILABLE 1
|
||||
# define MSC_RDSEED_INTRINSIC_AVAILABLE 0
|
||||
#if (ALL_RDRAND_INTRIN_AVAILABLE || ALL_RDSEED_INTRIN_AVAILABLE)
|
||||
# include <immintrin.h> // rdrand, MSC, ICC, and GCC
|
||||
# if defined(__has_include)
|
||||
# if __has_include(<x86intrin.h>)
|
||||
# include <x86intrin.h> // rdseed for some compilers, like GCC
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Fallback to MSC_RDSEED_INTRINSIC_AVAILABLE on Windows. The compiler must support it.
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && MSC_RDSEED_COMPILER
|
||||
# if !defined(MSC_RDSEED_INTRINSIC_AVAILABLE) && !(MSC_RDSEED_ASM_AVAILABLE > 0)
|
||||
# define MSC_RDSEED_INTRINSIC_AVAILABLE 1
|
||||
# define MSC_RDSEED_ASM_AVAILABLE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// GCC Compatible on Unix/Linux/Apple. Set GCC_RDSEED_INTRINSIC_AVAILABLE if
|
||||
// it (and ASM) are not set. The requirements are __RDSEED__ preprocessor.
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && GCC_RDSEED_COMPILER && (__RDSEED__ >= 1)
|
||||
# if !defined(GCC_RDSEED_INTRINSIC_AVAILABLE) && !(defined(GCC_RDSEED_ASM_AVAILABLE) && (GCC_RDSEED_ASM_AVAILABLE > 0))
|
||||
# define GCC_RDSEED_INTRINSIC_AVAILABLE 1
|
||||
# define GCC_RDSEED_ASM_AVAILABLE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// Fallback to MSC_ASM_INTRINSIC_AVAILABLE on Unix/Linux/Apple
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && IA32_ASM && GCC_RDSEED_COMPILER
|
||||
# if !defined(GCC_RDSEED_INTRINSIC_AVAILABLE) && !(defined(GCCC_RDSEED_ASM_AVAILABLE) && (GCCC_RDSEED_ASM_AVAILABLE > 0))
|
||||
# define GCC_RDSEED_ASM_AVAILABLE 1
|
||||
# define GCC_RDSEED_INTRINSIC_AVAILABLE 0
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if MSC_RDRAND_ASM_AVAILABLE
|
||||
#if MASM_RDRAND_ASM_AVAILABLE
|
||||
# ifdef _M_X64
|
||||
extern "C" int CRYPTOPP_FASTCALL MSC_RRA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
extern "C" int CRYPTOPP_FASTCALL MASM_RRA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
// # pragma comment(lib, "rdrand-x64.lib")
|
||||
# else
|
||||
extern "C" int MSC_RRA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
extern "C" int MASM_RRA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
// # pragma comment(lib, "rdrand-x86.lib")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if MSC_RDSEED_ASM_AVAILABLE
|
||||
#if MASM_RDSEED_ASM_AVAILABLE
|
||||
# ifdef _M_X64
|
||||
extern "C" int CRYPTOPP_FASTCALL MSC_RSA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
extern "C" int CRYPTOPP_FASTCALL MASM_RSA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
// # pragma comment(lib, "rdrand-x64.lib")
|
||||
# else
|
||||
extern "C" int MSC_RSA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
extern "C" int MASM_RSA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
// # pragma comment(lib, "rdrand-x86.lib")
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#if NASM_RDRAND_ASM_AVAILABLE
|
||||
extern "C" int NASM_RRA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
#endif
|
||||
|
||||
#if NASM_RDSEED_ASM_AVAILABLE
|
||||
extern "C" int NASM_RSA_GenerateBlock(byte*, size_t, unsigned int);
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if MSC_RDRAND_INTRINSIC_AVAILABLE || MSC_RDSEED_INTRINSIC_AVAILABLE
|
||||
# include <immintrin.h>
|
||||
#elif GCC_RDRAND_INTRINSIC_AVAILABLE || GCC_RDSEED_INTRINSIC_AVAILABLE
|
||||
# include <emmintrin.h>
|
||||
#endif
|
||||
|
||||
// Define ERROR_DEV_NOT_EXIST for this TU if not already defined
|
||||
#ifndef ERROR_DEV_NOT_EXIST
|
||||
# define ERROR_DEV_NOT_EXIST 0x37
|
||||
#endif
|
||||
|
||||
#if defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
# include <errno.h>
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
extern CRYPTOPP_DLL bool CpuId(word32 input, word32 *output);
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Intel and AMD provide RDRAND, only Intel provides RDSEED. To call these
|
||||
// functions, use the word32 array returned from CpuId(0, output[]).
|
||||
|
||||
static bool IsIntel(const word32 output[4])
|
||||
#if ALL_RDRAND_INTRIN_AVAILABLE
|
||||
static int ALL_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
// This is the "GenuineIntel" string
|
||||
return (output[1] /*EBX*/ == 0x756e6547) &&
|
||||
(output[2] /*ECX*/ == 0x6c65746e) &&
|
||||
(output[3] /*EDX*/ == 0x49656e69);
|
||||
}
|
||||
|
||||
static bool IsAMD(const word32 output[4])
|
||||
{
|
||||
// This is the "AuthenticAMD" string
|
||||
return (output[1] /*EBX*/ == 0x68747541) &&
|
||||
(output[2] /*ECX*/ == 0x69746E65) &&
|
||||
(output[3] /*EDX*/ == 0x444D4163);
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool RDRAND_Runtime_Helper()
|
||||
{
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
bool rdrand = false; word32 output[4];
|
||||
if (CpuId(0, output))
|
||||
{
|
||||
if (IsIntel(output) || IsAMD(output))
|
||||
{
|
||||
if (output[0] /*EAX*/ >= 1 && CpuId(1, output))
|
||||
{
|
||||
static const unsigned int RDRAND_FLAG = (1 << 30);
|
||||
rdrand = !!(output[2] /*ECX*/ & RDRAND_FLAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rdrand;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This will be moved to CPU.h/CPU.cpp eventually
|
||||
static bool hasRDRAND = RDRAND_Runtime_Helper();
|
||||
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
|
||||
#if MSC_RDRAND_INTRINSIC_AVAILABLE
|
||||
static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
assert((output && size) || !(output || size));
|
||||
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else
|
||||
word32 val;
|
||||
|
|
@ -246,7 +184,7 @@ static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
while (size >= sizeof(val))
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||
if (_rdrand64_step((word64*)output))
|
||||
#else
|
||||
if (_rdrand32_step((word32*)output))
|
||||
|
|
@ -264,7 +202,7 @@ static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
if (size)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||
if (_rdrand64_step(&val))
|
||||
#else
|
||||
if (_rdrand32_step(&val))
|
||||
|
|
@ -280,7 +218,7 @@ static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
}
|
||||
}
|
||||
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||
*((volatile word64*)&val) = 0;
|
||||
#else
|
||||
*((volatile word32*)&val) = 0;
|
||||
|
|
@ -288,68 +226,12 @@ static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
return int(size == 0);
|
||||
}
|
||||
|
||||
#endif // MSC_RDRAND_INTRINSIC_AVAILABLE
|
||||
|
||||
#if GCC_RDRAND_INTRINSIC_AVAILABLE
|
||||
static int GCC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else // CRYPTOPP_BOOL_X86
|
||||
word32 val;
|
||||
#endif
|
||||
|
||||
while (size >= sizeof(val))
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (__builtin_ia32_rdrand64_step((word64*)output))
|
||||
#else
|
||||
if (__builtin_ia32_rdrand32_step((word32*)output))
|
||||
#endif
|
||||
{
|
||||
output += sizeof(val);
|
||||
size -= sizeof(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!safety--)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (__builtin_ia32_rdrand64_step(&val))
|
||||
#else
|
||||
if (__builtin_ia32_rdrand32_step(&val))
|
||||
#endif
|
||||
{
|
||||
memcpy(output, &val, size);
|
||||
size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!safety--)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
*((volatile word64*)&val) = 0;
|
||||
#else
|
||||
*((volatile word32*)&val) = 0;
|
||||
#endif
|
||||
|
||||
return int(size == 0);
|
||||
}
|
||||
|
||||
#endif // GCC_RDRAND_INTRINSIC_AVAILABLE
|
||||
#endif // ALL_RDRAND_INTRINSIC_AVAILABLE
|
||||
|
||||
#if GCC_RDRAND_ASM_AVAILABLE
|
||||
static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
assert((output && size) || !(output || size));
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else
|
||||
|
|
@ -359,9 +241,13 @@ static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
while (size)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"rdrand %0; "
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
".byte 0x48, 0x0f, 0xc7, 0xf0;\n" // rdrand rax
|
||||
#else
|
||||
".byte 0x0f, 0xc7, 0xf0;\n" // rdrand eax
|
||||
#endif
|
||||
"setc %1; "
|
||||
: "=r" (val), "=qm" (rc)
|
||||
: "=a" (val), "=qm" (rc)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -404,103 +290,39 @@ static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
#endif // GCC_RDRAND_ASM_AVAILABLE
|
||||
|
||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
||||
|
||||
//! generate random array of bytes
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
void RDRAND::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
assert((output == NULL && size == 0) || (output != NULL && size != 0));
|
||||
assert(Available());
|
||||
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||
assert((output && size) || !(output || size));
|
||||
|
||||
// We could (should?) test Ready, but Available conveys more useful information.
|
||||
if(!Available())
|
||||
if(!HasRDRAND())
|
||||
throw NotImplemented("RDRAND: rdrand is not available on this platform");
|
||||
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
int rc; CRYPTOPP_UNUSED(rc);
|
||||
#if MSC_RDRAND_ASM_AVAILABLE
|
||||
rc = MSC_RRA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("MSC_RRA_GenerateBlock"); }
|
||||
#if MASM_RDRAND_ASM_AVAILABLE
|
||||
rc = MASM_RRA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("MASM_RRA_GenerateBlock"); }
|
||||
#elif NASM_RDRAND_ASM_AVAILABLE
|
||||
rc = NASM_RRA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("NASM_RRA_GenerateBlock"); }
|
||||
#elif ALL_RDRAND_INTRIN_AVAILABLE
|
||||
rc = ALL_RRI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("ALL_RRI_GenerateBlock"); }
|
||||
#elif GCC_RDRAND_ASM_AVAILABLE
|
||||
rc = GCC_RRA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("GCC_RRA_GenerateBlock"); }
|
||||
#elif MSC_RDRAND_INTRINSIC_AVAILABLE
|
||||
rc = MSC_RRI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("MSC_RRI_GenerateBlock"); }
|
||||
#elif GCC_RDRAND_INTRINSIC_AVAILABLE
|
||||
rc = GCC_RRI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("GCC_RRI_GenerateBlock"); }
|
||||
#elif (__RDRND__ >= 1)
|
||||
// RDRAND detected at compile time, GCC Compatible compiler, but no suitable implementations
|
||||
# error "Please report on the Crypto++ user group"
|
||||
#else
|
||||
// RDRAND not detected at compile time, and no suitable compiler found
|
||||
throw NotImplemented("RDRAND: failed to find a suitable implementation???");
|
||||
#endif
|
||||
|
||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
||||
#endif // CRYPTOPP_CPUID_AVAILABLE
|
||||
}
|
||||
|
||||
//! returns true if RDRAND is present or available according to CPUID, false otherwise
|
||||
bool RDRAND::Available() const
|
||||
{
|
||||
word64 unused;
|
||||
return Available(unused);
|
||||
}
|
||||
|
||||
//! returns true if RDRAND is present or available according to CPUID, false otherwise. There is no exended information available.
|
||||
bool RDRAND::Available(word64& extendedInfo) const
|
||||
{
|
||||
if (hasRDRAND)
|
||||
{
|
||||
extendedInfo = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
extendedInfo = ERROR_DEV_NOT_EXIST; // 0x00000037
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
extendedInfo = ENODEV; // 19
|
||||
#else
|
||||
extendedInfo = word64(-1);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! returns true if RDRAND is online/ready to produce random numbers, false otherwise
|
||||
bool RDRAND::Ready() const
|
||||
{
|
||||
word64 unused;
|
||||
return Ready(unused);
|
||||
}
|
||||
|
||||
//! returns true if RDRAND is online/ready to produce random numbers, false otherwise. There is no exended information available.
|
||||
bool RDRAND::Ready(word64& extendedInfo) const
|
||||
{
|
||||
if (hasRDRAND)
|
||||
{
|
||||
extendedInfo = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
extendedInfo = ERROR_DEV_NOT_EXIST; // 0x00000037
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
extendedInfo = ENODEV; // 19
|
||||
#else
|
||||
extendedInfo = word64(-1);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! generate and discard n bytes.
|
||||
void RDRAND::DiscardBytes(size_t n)
|
||||
{
|
||||
{
|
||||
// RoundUpToMultipleOf is used because a full word is read, and its cheaper
|
||||
// to discard full words. There's no sense in dealing with tail bytes.
|
||||
assert(Ready());
|
||||
assert(HasRDRAND());
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
FixedSizeSecBlock<word64, 16> discard;
|
||||
n = RoundUpToMultipleOf(n, sizeof(word64));
|
||||
|
|
@ -517,41 +339,16 @@ void RDRAND::DiscardBytes(size_t n)
|
|||
count = STDMIN(n, discard.SizeInBytes());
|
||||
}
|
||||
}
|
||||
#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
|
||||
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
|
||||
static bool RDSEED_Runtime_Helper()
|
||||
#if ALL_RDSEED_INTRIN_AVAILABLE
|
||||
static int ALL_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
bool rdseed = false; word32 output[4];
|
||||
if (CpuId(0, output))
|
||||
{
|
||||
// Only Intel supports RDSEED at the moment.
|
||||
if (IsIntel(output))
|
||||
{
|
||||
if (output[0] /*EAX*/ >= 7 && CpuId(7, output))
|
||||
{
|
||||
static const unsigned int RDSEED_FLAG = (1 << 18);
|
||||
rdseed = !!(output[1] /*EBX*/ & RDSEED_FLAG);
|
||||
}
|
||||
}
|
||||
}
|
||||
return rdseed;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// This will be moved to CPU.h/CPU.cpp eventually
|
||||
static bool hasRDSEED = RDSEED_Runtime_Helper();
|
||||
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
|
||||
#if MSC_RDSEED_INTRINSIC_AVAILABLE
|
||||
static int MSC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
assert((output && size) || !(output || size));
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else
|
||||
word32 val;
|
||||
|
|
@ -559,7 +356,7 @@ static int MSC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
while (size >= sizeof(val))
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (_rdseed64_step((word64*)output))
|
||||
#else
|
||||
if (_rdseed32_step((word32*)output))
|
||||
|
|
@ -577,7 +374,7 @@ static int MSC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
if (size)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (_rdseed64_step(&val))
|
||||
#else
|
||||
if (_rdseed32_step(&val))
|
||||
|
|
@ -593,62 +390,6 @@ static int MSC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
}
|
||||
}
|
||||
|
||||
#if CRYPTOPP_BOOL_X64
|
||||
*((volatile word64*)&val) = 0;
|
||||
#else
|
||||
*((volatile word32*)&val) = 0;
|
||||
#endif
|
||||
|
||||
return int(size == 0);
|
||||
}
|
||||
|
||||
#endif // MSC_RDSEED_INTRINSIC_AVAILABLE
|
||||
|
||||
#if GCC_RDSEED_INTRINSIC_AVAILABLE
|
||||
static int GCC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else // CRYPTOPP_BOOL_X86
|
||||
word32 val;
|
||||
#endif
|
||||
|
||||
while (size >= sizeof(val))
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (__builtin_ia32_rdseed64_step((word64*)output))
|
||||
#else
|
||||
if (__builtin_ia32_rdseed32_step((word32*)output))
|
||||
#endif
|
||||
{
|
||||
output += sizeof(val);
|
||||
size -= sizeof(val);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!safety--)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (size)
|
||||
{
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
if (__builtin_ia32_rdseed64_step(&val))
|
||||
#else
|
||||
if (__builtin_ia32_rdseed32_step(&val))
|
||||
#endif
|
||||
{
|
||||
memcpy(output, &val, size);
|
||||
size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!safety--)
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
*((volatile word64*)&val) = 0;
|
||||
#else
|
||||
|
|
@ -657,12 +398,12 @@ static int GCC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
return int(size == 0);
|
||||
}
|
||||
|
||||
#endif // GCC_RDSEED_INTRINSIC_AVAILABLE
|
||||
#endif // ALL_RDSEED_INTRIN_AVAILABLE
|
||||
|
||||
#if GCC_RDSEED_ASM_AVAILABLE
|
||||
static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||
{
|
||||
assert((output && size) || !(output || size));
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
word64 val;
|
||||
#else
|
||||
|
|
@ -672,9 +413,13 @@ static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
while (size)
|
||||
{
|
||||
__asm__ volatile(
|
||||
"rdseed %0; "
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
".byte 0x48, 0x0f, 0xc7, 0xf8;\n" // rdseed rax
|
||||
#else
|
||||
".byte 0x0f, 0xc7, 0xf8;\n" // rdseed eax
|
||||
#endif
|
||||
"setc %1; "
|
||||
: "=r" (val), "=qm" (rc)
|
||||
: "=a" (val), "=qm" (rc)
|
||||
:
|
||||
: "cc"
|
||||
);
|
||||
|
|
@ -714,107 +459,41 @@ static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
|||
|
||||
return int(size == 0);
|
||||
}
|
||||
|
||||
#endif // GCC_RDSEED_ASM_AVAILABLE
|
||||
|
||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
||||
|
||||
//! generate random array of bytes
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
void RDSEED::GenerateBlock(byte *output, size_t size)
|
||||
{
|
||||
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||
assert((output == NULL && size == 0) || (output != NULL && size != 0));
|
||||
assert(Available());
|
||||
assert((output && size) || !(output || size));
|
||||
|
||||
// We could (should?) test Ready, but Available conveys more useful information.
|
||||
if(!Available())
|
||||
if(!HasRDSEED())
|
||||
throw NotImplemented("RDSEED: rdseed is not available on this platform");
|
||||
|
||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||
int rc; CRYPTOPP_UNUSED(rc);
|
||||
#if MSC_RDSEED_ASM_AVAILABLE
|
||||
rc = MSC_RSA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("MSC_RSA_GenerateBlock"); }
|
||||
#if MASM_RDSEED_ASM_AVAILABLE
|
||||
rc = MASM_RSA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("MASM_RSA_GenerateBlock"); }
|
||||
#elif NASM_RDSEED_ASM_AVAILABLE
|
||||
rc = NASM_RSA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDRAND_Err("NASM_RSA_GenerateBlock"); }
|
||||
#elif ALL_RDSEED_INTRIN_AVAILABLE
|
||||
rc = ALL_RSI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("ALL_RSI_GenerateBlock"); }
|
||||
#elif GCC_RDSEED_ASM_AVAILABLE
|
||||
rc = GCC_RSA_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("GCC_RSA_GenerateBlock"); }
|
||||
#elif MSC_RDSEED_INTRINSIC_AVAILABLE
|
||||
rc = MSC_RSI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("MSC_RSI_GenerateBlock"); }
|
||||
#elif GCC_RDSEED_INTRINSIC_AVAILABLE
|
||||
rc = GCC_RSI_GenerateBlock(output, size, m_retries);
|
||||
if (!rc) { throw RDSEED_Err("GCC_RSI_GenerateBlock"); }
|
||||
#elif (__RDSEED__ >= 1)
|
||||
// RDSEED detected at compile time, GCC Compatible compiler, but no suitable implementations
|
||||
# error "Please report on the Crypto++ user group"
|
||||
#else
|
||||
// RDSEED not detected at compile time, and no suitable compiler found
|
||||
throw NotImplemented("RDSEED: failed to find a suitable implementation???");
|
||||
#endif
|
||||
|
||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
||||
}
|
||||
|
||||
//! returns true if RDSEED is present or available according to CPUID, false otherwise
|
||||
bool RDSEED::Available() const
|
||||
{
|
||||
word64 unused;
|
||||
return Available(unused);
|
||||
}
|
||||
|
||||
//! returns true if RDSEED is present or available according to CPUID, false otherwise. There is no exended information available.
|
||||
bool RDSEED::Available(word64& extendedInfo) const
|
||||
{
|
||||
if (hasRDSEED)
|
||||
{
|
||||
extendedInfo = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
extendedInfo = ERROR_DEV_NOT_EXIST; // 0x00000037
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
extendedInfo = ENODEV; // 19
|
||||
#else
|
||||
extendedInfo = word64(-1);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! returns true if RDSEED is online/ready to produce random numbers, false otherwise
|
||||
bool RDSEED::Ready() const
|
||||
{
|
||||
word64 unused;
|
||||
return Ready(unused);
|
||||
}
|
||||
|
||||
//! returns true if RDSEED is online/ready to produce random numbers, false otherwise. There is no exended information available.
|
||||
bool RDSEED::Ready(word64& extendedInfo) const
|
||||
{
|
||||
if (hasRDSEED)
|
||||
{
|
||||
extendedInfo = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(CRYPTOPP_WIN32_AVAILABLE)
|
||||
extendedInfo = ERROR_DEV_NOT_EXIST; // 0x00000037
|
||||
#elif defined(CRYPTOPP_UNIX_AVAILABLE)
|
||||
extendedInfo = ENODEV; // 19
|
||||
#else
|
||||
extendedInfo = word64(-1);
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
//! generate and discard n bytes.
|
||||
void RDSEED::DiscardBytes(size_t n)
|
||||
{
|
||||
{
|
||||
// RoundUpToMultipleOf is used because a full word is read, and its cheaper
|
||||
// to discard full words. There's no sense in dealing with tail bytes.
|
||||
assert(Ready());
|
||||
assert(HasRDSEED());
|
||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||
FixedSizeSecBlock<word64, 16> discard;
|
||||
n = RoundUpToMultipleOf(n, sizeof(word64));
|
||||
|
|
@ -831,5 +510,6 @@ void RDSEED::DiscardBytes(size_t n)
|
|||
count = STDMIN(n, discard.SizeInBytes());
|
||||
}
|
||||
}
|
||||
#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
|
||||
|
||||
NAMESPACE_END
|
||||
|
|
|
|||
141
rdrand.h
141
rdrand.h
|
|
@ -1,21 +1,30 @@
|
|||
// rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
|
||||
// Copyright assigned to Crypto++ project.
|
||||
|
||||
//! \file
|
||||
//! \headerfile rdrand.h
|
||||
//! \brief Classes for RDRAND and RDSEED
|
||||
|
||||
#ifndef CRYPTOPP_RDRAND_H
|
||||
#define CRYPTOPP_RDRAND_H
|
||||
|
||||
#include "cryptlib.h"
|
||||
|
||||
// This file (and friends) provides both RDRAND and RDSEED, but its somewhat
|
||||
// experimental. They were added at Crypto++ 5.6.3. At compile time, it
|
||||
// indirectly uses CRYPTOPP_BOOL_{X86|X32|X64} (via CRYPTOPP_CPUID_AVAILABLE)
|
||||
// to select an implementation or "throw NotImplemented". At runtime, the
|
||||
// class uses the result of CPUID to determine if RDRAND or RDSEED are
|
||||
// available. A lazy throw strategy is used in case the CPU does not support
|
||||
// the instruction. I.e., the throw is deferred until GenerateBlock is called.
|
||||
|
||||
// Microsoft added RDRAND in August 2012, VS2012. GCC added RDRAND in December 2010, GCC 4.6.
|
||||
// Clang added RDRAND in July 2012, Clang 3.2. Intel added RDRAND in September 2011, ICC 12.1.
|
||||
|
||||
// Visual Studio 2015 (CL version 1900) is missing _rdseed{16|32|64}_step
|
||||
#if (CRYPTOPP_MSC_VERSION <= 1900)
|
||||
# define MSC_RDSEED_INTRINSIC_AVAILABLE 0
|
||||
#endif
|
||||
|
||||
NAMESPACE_BEGIN(CryptoPP)
|
||||
|
||||
//! \brief Exception thrown when a RDRAND generator encounters
|
||||
//! a generator related error.
|
||||
class RDRAND_Err : public Exception
|
||||
{
|
||||
public:
|
||||
|
|
@ -23,61 +32,65 @@ public:
|
|||
: Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
|
||||
};
|
||||
|
||||
//! \brief Read hardware generated random numbers.
|
||||
|
||||
//! This file (and friends) provides both RDRAND and RDSEED, but its somewhat
|
||||
//! experimental. They were added at Crypto++ 5.6.3. At compile time, it
|
||||
//! indirectly uses CRYPTOPP_BOOL_{X86|X32|X64} (via CRYPTOPP_CPUID_AVAILABLE)
|
||||
//! to select an implementation or "throw NotImplemented". At runtime, the
|
||||
//! class uses the result of CPUID to determine if RDRAND or RDSEED are
|
||||
//! available. A lazy throw strategy is used in case the CPU does not support
|
||||
//! the instruction. I.e., the throw is deferred until GenerateBlock is called.
|
||||
class RDRAND : public RandomNumberGenerator, public DeviceState
|
||||
//! \brief Hardware generated random numbers using RDRAND instruction
|
||||
//! \sa MaurerRandomnessTest() for random bit generators
|
||||
class RDRAND : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "RDRAND";}
|
||||
|
||||
//! construct a RDRAND generator with a maximum number of retires for failed generation attempts
|
||||
//! \brief Construct a RDRAND generator
|
||||
//! \param retries the number of retries for failed calls to the hardware
|
||||
//! \details RDRAND() constructs a generator with a maximum number of retires
|
||||
//! for failed generation attempts.
|
||||
RDRAND(unsigned int retries = 8) : m_retries(retries) {}
|
||||
|
||||
virtual ~RDRAND() {}
|
||||
|
||||
//! returns true if RDRAND is present or available according to CPUID, false otherwise
|
||||
bool Available() const;
|
||||
|
||||
//! returns true if RDRAND is present or available according to CPUID, false otherwise. There is no exended information available.
|
||||
bool Available(word64& extendedInfo) const;
|
||||
|
||||
//! returns true if RDRAND is online/ready to produce random numbers, false otherwise
|
||||
bool Ready() const;
|
||||
|
||||
//! returns true if RDRAND is online/ready to produce random numbers, false otherwise. There is no exended information available.
|
||||
bool Ready(word64& extendedInfo) const;
|
||||
|
||||
//! \brief Retrieve the number of retries used by the generator
|
||||
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
unsigned int GetRetries() const
|
||||
{
|
||||
return m_retries;
|
||||
}
|
||||
|
||||
//! sets the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
//! \brief Set the number of retries used by the generator
|
||||
//! \param the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
void SetRetries(unsigned int retries)
|
||||
{
|
||||
m_retries = retries;
|
||||
}
|
||||
|
||||
//! generate random array of bytes
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
virtual void GenerateBlock(byte *output, size_t size);
|
||||
#else
|
||||
virtual void GenerateBlock(byte *output, size_t size) {
|
||||
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||
throw NotImplemented("RDRAND: rdrand is not available on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
//! generate and discard n bytes.
|
||||
//! \param n the number of bytes to discard
|
||||
//! \brief Generate and discard n bytes
|
||||
//! \param n the number of bytes to generate and discard
|
||||
//! \details the RDSEED generator discards words, not bytes. If n is
|
||||
//! not a multiple of a machine word, then it is rounded up to
|
||||
//! that size.
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
virtual void DiscardBytes(size_t n);
|
||||
#else
|
||||
virtual void DiscardBytes(size_t n) {
|
||||
CRYPTOPP_UNUSED(n);
|
||||
throw NotImplemented("RDRAND: rdrand is not available on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
//! update RNG state with additional unpredictable values. The operation is a nop for this generator.
|
||||
//! Update RNG state with additional unpredictable values
|
||||
//! \param input unused
|
||||
//! \param length unused
|
||||
//! \details The operation is a nop for this generator.
|
||||
virtual void IncorporateEntropy(const byte *input, size_t length)
|
||||
{
|
||||
// Override to avoid the base class' throw.
|
||||
|
|
@ -89,6 +102,8 @@ private:
|
|||
unsigned int m_retries;
|
||||
};
|
||||
|
||||
//! \brief Exception thrown when a RDSEED generator encounters
|
||||
//! a generator related error.
|
||||
class RDSEED_Err : public Exception
|
||||
{
|
||||
public:
|
||||
|
|
@ -96,61 +111,65 @@ public:
|
|||
: Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
|
||||
};
|
||||
|
||||
//! \brief Read hardware generated random numbers.
|
||||
|
||||
//! This file (and friends) provides both RDRAND and RDSEED, but its somewhat
|
||||
//! experimental. They were added at Crypto++ 5.6.3. At compile time, it
|
||||
//! indirectly uses CRYPTOPP_BOOL_{X86|X32|X64} (via CRYPTOPP_CPUID_AVAILABLE)
|
||||
//! to select an implementation or "throw NotImplemented". At runtime, the
|
||||
//! class uses the result of CPUID to determine if RDRAND or RDSEED are
|
||||
//! available. A lazy throw strategy is used in case the CPU does not support
|
||||
//! the instruction. I.e., the throw is deferred until GenerateBlock is called.
|
||||
class RDSEED : public RandomNumberGenerator, public DeviceState
|
||||
//! \brief Hardware generated random numbers using RDSEED instruction
|
||||
//! \sa MaurerRandomnessTest() for random bit generators
|
||||
class RDSEED : public RandomNumberGenerator
|
||||
{
|
||||
public:
|
||||
std::string AlgorithmName() const {return "RDSEED";}
|
||||
|
||||
//! construct a RDSEED generator with a maximum number of retires for failed generation attempts
|
||||
//! \brief Construct a RDSEED generator
|
||||
//! \param retries the number of retries for failed calls to the hardware
|
||||
//! \details RDSEED() constructs a generator with a maximum number of retires
|
||||
//! for failed generation attempts.
|
||||
RDSEED(unsigned int retries = 8) : m_retries(retries) {}
|
||||
|
||||
virtual ~RDSEED() {}
|
||||
|
||||
//! returns true if RDSEED is present or available according to CPUID, false otherwise
|
||||
bool Available() const;
|
||||
|
||||
//! returns true if RDSEED is present or available according to CPUID, false otherwise. There is no exended information available.
|
||||
bool Available(word64& extendedInfo) const;
|
||||
|
||||
//! returns true if RDSEED is online/ready to produce random numbers, false otherwise
|
||||
bool Ready() const;
|
||||
|
||||
//! returns true if RDSEED is online/ready to produce random numbers, false otherwise. There is no exended information available.
|
||||
bool Ready(word64& extendedInfo) const;
|
||||
|
||||
//! \brief Retrieve the number of retries used by the generator
|
||||
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
unsigned int GetRetries() const
|
||||
{
|
||||
return m_retries;
|
||||
}
|
||||
|
||||
//! sets the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
//! \brief Set the number of retries used by the generator
|
||||
//! \param the number of times GenerateBlock will attempt to recover from a failed generation
|
||||
void SetRetries(unsigned int retries)
|
||||
{
|
||||
m_retries = retries;
|
||||
}
|
||||
|
||||
//! generate random array of bytes
|
||||
//! \brief Generate random array of bytes
|
||||
//! \param output the byte buffer
|
||||
//! \param size the length of the buffer, in bytes
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
virtual void GenerateBlock(byte *output, size_t size);
|
||||
#else
|
||||
virtual void GenerateBlock(byte *output, size_t size) {
|
||||
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||
throw NotImplemented("RDSEED: rdseed is not available on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
//! generate and discard n bytes.
|
||||
//! \param n the number of bytes to discard
|
||||
//! \brief Generate and discard n bytes
|
||||
//! \param n the number of bytes to generate and discard
|
||||
//! \details the RDSEED generator discards words, not bytes. If n is
|
||||
//! not a multiple of a machine word, then it is rounded up to
|
||||
//! that size.
|
||||
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||
virtual void DiscardBytes(size_t n);
|
||||
#else
|
||||
virtual void DiscardBytes(size_t n) {
|
||||
CRYPTOPP_UNUSED(n);
|
||||
throw NotImplemented("RDSEED: rdseed is not available on this platform");
|
||||
}
|
||||
#endif
|
||||
|
||||
//! update RNG state with additional unpredictable values. The operation is a nop for this generator.
|
||||
//! Update RNG state with additional unpredictable values
|
||||
//! \param input unused
|
||||
//! \param length unused
|
||||
//! \details The operation is a nop for this generator.
|
||||
virtual void IncorporateEntropy(const byte *input, size_t length)
|
||||
{
|
||||
// Override to avoid the base class' throw.
|
||||
|
|
|
|||
Loading…
Reference in New Issue