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.
|
;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
|
||||||
;; Copyright assigned to the Crypto++ project.
|
;; Copyright assigned to the Crypto++ project.
|
||||||
|
|
||||||
;; This ASM file exists for one reason only - to emit the RDRAND instruction for Microsoft platforms.
|
;; This ASM file provides RDRAND and RDSEED to downlevel Microsoft tool chains.
|
||||||
;; We can't call RDRAND directly on some versions of the toolchain (prior to CL 17.00/VS2012).
|
;; Everything "just works" under Visual Studio. Other platforms will have to
|
||||||
;; Additionally, Microsoft/Intel penalizes AMD CPUs with the feature. To avoid these troubles, we
|
;; run MASM/MASM-64 and then link to the object files.
|
||||||
;; provide the ASM and emit the opcodes for RDRAND by hand.
|
|
||||||
|
|
||||||
;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
|
;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh
|
||||||
;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi
|
;; 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
|
SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains
|
||||||
|
|
||||||
PUBLIC MSC_RRA_GenerateBlock
|
PUBLIC MASM_RRA_GenerateBlock
|
||||||
PUBLIC MSC_RSA_GenerateBlock
|
PUBLIC MASM_RSA_GenerateBlock
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|
@ -26,6 +25,7 @@ PUBLIC MSC_RSA_GenerateBlock
|
||||||
;; Naming convention used in rdrand.{h|cpp|asm}
|
;; Naming convention used in rdrand.{h|cpp|asm}
|
||||||
;; MSC = Microsoft Compiler (and compatibles)
|
;; MSC = Microsoft Compiler (and compatibles)
|
||||||
;; GCC = GNU Compiler (and compatibles)
|
;; GCC = GNU Compiler (and compatibles)
|
||||||
|
;; ALL = MSC and GCC (and compatibles)
|
||||||
;; RRA = RDRAND, Assembly
|
;; RRA = RDRAND, Assembly
|
||||||
;; RSA = RDSEED, Assembly
|
;; RSA = RDSEED, Assembly
|
||||||
;; RRI = RDRAND, Intrinsic
|
;; RRI = RDRAND, Intrinsic
|
||||||
|
|
@ -39,9 +39,9 @@ PUBLIC MSC_RSA_GenerateBlock
|
||||||
|
|
||||||
;; C/C++ Function prototypes
|
;; C/C++ Function prototypes
|
||||||
;; X86:
|
;; 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:
|
;; 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
|
;; Base relative (in): arg3, unsigned int safety
|
||||||
;; EAX (out): success (1), failure (0)
|
;; EAX (out): success (1), failure (0)
|
||||||
|
|
||||||
;; MSC_RRA_GenerateBlock PROC USES ecx edx edi arg1:DWORD,arg2:DWORD,arg3:DWORD
|
MASM_RRA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||||
MSC_RRA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
|
||||||
|
|
||||||
MWSIZE EQU 04h ;; machine word size
|
MWSIZE EQU 04h ;; machine word size
|
||||||
buffer EQU edi
|
buffer EQU edi
|
||||||
|
|
@ -108,7 +107,7 @@ GenerateBlock_Top:
|
||||||
Call_RDRAND_EAX:
|
Call_RDRAND_EAX:
|
||||||
;; RDRAND is not available prior to VS2012. Just emit
|
;; RDRAND is not available prior to VS2012. Just emit
|
||||||
;; the byte codes using DB. This is `rdrand eax`.
|
;; 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=1, the number returned by RDRAND is valid.
|
||||||
;; If CF=0, a random number was not available.
|
;; 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 bit 0 to see if size is at least 1
|
||||||
test bsize, 1
|
test bsize, 1
|
||||||
;; jz Bit_0_Not_Set
|
|
||||||
jz GenerateBlock_Success
|
jz GenerateBlock_Success
|
||||||
|
|
||||||
mov BYTE PTR [buffer], al
|
mov BYTE PTR [buffer], al
|
||||||
|
|
||||||
Bit_0_Not_Set:
|
Bit_0_Not_Set:
|
||||||
|
|
||||||
;; We've hit all the bits, set size to 0
|
;; We've hit all the bits
|
||||||
;; mov bsize, 0
|
|
||||||
jmp GenerateBlock_Success
|
jmp GenerateBlock_Success
|
||||||
|
|
||||||
GenerateBlock_PreRet:
|
GenerateBlock_PreRet:
|
||||||
|
|
@ -171,18 +168,17 @@ GenerateBlock_PreRet:
|
||||||
|
|
||||||
GenerateBlock_Failure:
|
GenerateBlock_Failure:
|
||||||
|
|
||||||
mov eax, RDRAND_FAILURE
|
xor eax, eax
|
||||||
jmp GenerateBlock_Ret
|
mov al, RDRAND_FAILURE
|
||||||
|
ret
|
||||||
|
|
||||||
GenerateBlock_Success:
|
GenerateBlock_Success:
|
||||||
|
|
||||||
mov eax, RDRAND_SUCCESS
|
xor eax, eax
|
||||||
|
mov al, RDRAND_SUCCESS
|
||||||
GenerateBlock_Ret:
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
MSC_RRA_GenerateBlock ENDP
|
MASM_RRA_GenerateBlock ENDP
|
||||||
|
|
||||||
ENDIF ;; _M_X86
|
ENDIF ;; _M_X86
|
||||||
|
|
||||||
|
|
@ -201,8 +197,7 @@ OPTION EPILOGUE:NONE
|
||||||
;; R8d (in): arg3, unsigned int safety
|
;; R8d (in): arg3, unsigned int safety
|
||||||
;; RAX (out): success (1), failure (0)
|
;; RAX (out): success (1), failure (0)
|
||||||
|
|
||||||
;; MSC_RRA_GenerateBlock PROC USES RCX ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
MASM_RRA_GenerateBlock PROC
|
||||||
MSC_RRA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
|
||||||
|
|
||||||
MWSIZE EQU 08h ;; machine word size
|
MWSIZE EQU 08h ;; machine word size
|
||||||
buffer EQU rcx
|
buffer EQU rcx
|
||||||
|
|
@ -227,7 +222,7 @@ GenerateBlock_Top:
|
||||||
Call_RDRAND_RAX:
|
Call_RDRAND_RAX:
|
||||||
;; RDRAND is not available prior to VS2012. Just emit
|
;; RDRAND is not available prior to VS2012. Just emit
|
||||||
;; the byte codes using DB. This is `rdrand rax`.
|
;; 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=1, the number returned by RDRAND is valid.
|
||||||
;; If CF=0, a random number was not available.
|
;; 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 bit 0 to see if size is at least 1
|
||||||
test bsize, 1
|
test bsize, 1
|
||||||
;; jz Bit_0_Not_Set
|
|
||||||
jz GenerateBlock_Success
|
jz GenerateBlock_Success
|
||||||
|
|
||||||
mov BYTE PTR [buffer], al
|
mov BYTE PTR [buffer], al
|
||||||
|
|
||||||
Bit_0_Not_Set:
|
Bit_0_Not_Set:
|
||||||
|
|
||||||
;; We've hit all the bits, set size to 0
|
;; We've hit all the bits
|
||||||
;; mov bsize, 0
|
|
||||||
jmp GenerateBlock_Success
|
jmp GenerateBlock_Success
|
||||||
|
|
||||||
GenerateBlock_PreRet:
|
GenerateBlock_PreRet:
|
||||||
|
|
@ -300,18 +293,17 @@ GenerateBlock_PreRet:
|
||||||
|
|
||||||
GenerateBlock_Failure:
|
GenerateBlock_Failure:
|
||||||
|
|
||||||
mov rax, RDRAND_FAILURE
|
xor rax, rax
|
||||||
jmp GenerateBlock_Ret
|
mov al, RDRAND_FAILURE
|
||||||
|
ret
|
||||||
|
|
||||||
GenerateBlock_Success:
|
GenerateBlock_Success:
|
||||||
|
|
||||||
mov rax, RDRAND_SUCCESS
|
xor rax, rax
|
||||||
|
mov al, RDRAND_SUCCESS
|
||||||
GenerateBlock_Ret:
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
MSC_RRA_GenerateBlock ENDP
|
MASM_RRA_GenerateBlock ENDP
|
||||||
|
|
||||||
ENDIF ;; _M_X64
|
ENDIF ;; _M_X64
|
||||||
|
|
||||||
|
|
@ -331,8 +323,7 @@ OPTION EPILOGUE:NONE
|
||||||
;; Base relative (in): arg3, unsigned int safety
|
;; Base relative (in): arg3, unsigned int safety
|
||||||
;; EAX (out): success (1), failure (0)
|
;; EAX (out): success (1), failure (0)
|
||||||
|
|
||||||
;; MSC_RSA_GenerateBlock PROC USES ecx edx edi arg1:DWORD,arg2:DWORD,arg3:DWORD
|
MASM_RSA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
||||||
MSC_RSA_GenerateBlock PROC arg1:DWORD,arg2:DWORD,arg3:DWORD
|
|
||||||
|
|
||||||
MWSIZE EQU 04h ;; machine word size
|
MWSIZE EQU 04h ;; machine word size
|
||||||
buffer EQU edi
|
buffer EQU edi
|
||||||
|
|
@ -347,20 +338,20 @@ Load_Arguments:
|
||||||
|
|
||||||
Validate_Pointer:
|
Validate_Pointer:
|
||||||
|
|
||||||
cmp buffer, 0
|
cmp buffer, 0
|
||||||
je GenerateBlock_PreRet
|
je GenerateBlock_PreRet
|
||||||
|
|
||||||
;; Top of While loop
|
;; Top of While loop
|
||||||
GenerateBlock_Top:
|
GenerateBlock_Top:
|
||||||
|
|
||||||
;; Check remaining size
|
;; Check remaining size
|
||||||
cmp bsize, 0
|
cmp bsize, 0
|
||||||
je GenerateBlock_Success
|
je GenerateBlock_Success
|
||||||
|
|
||||||
Call_RDSEED_EAX:
|
Call_RDSEED_EAX:
|
||||||
;; RDSEED is not available prior to VS2012. Just emit
|
;; RDSEED is not available prior to VS2012. Just emit
|
||||||
;; the byte codes using DB. This is `rdseed eax`.
|
;; 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=1, the number returned by RDSEED is valid.
|
||||||
;; If CF=0, a random number was not available.
|
;; 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 bit 0 to see if size is at least 1
|
||||||
test bsize, 1
|
test bsize, 1
|
||||||
;; jz Bit_0_Not_Set
|
|
||||||
jz GenerateBlock_Success
|
jz GenerateBlock_Success
|
||||||
|
|
||||||
mov BYTE PTR [buffer], al
|
mov BYTE PTR [buffer], al
|
||||||
|
|
||||||
Bit_0_Not_Set:
|
Bit_0_Not_Set:
|
||||||
|
|
||||||
;; We've hit all the bits, set size to 0
|
;; We've hit all the bits
|
||||||
;; mov bsize, 0
|
|
||||||
jmp GenerateBlock_Success
|
jmp GenerateBlock_Success
|
||||||
|
|
||||||
GenerateBlock_PreRet:
|
GenerateBlock_PreRet:
|
||||||
|
|
@ -423,18 +412,17 @@ GenerateBlock_PreRet:
|
||||||
|
|
||||||
GenerateBlock_Failure:
|
GenerateBlock_Failure:
|
||||||
|
|
||||||
mov eax, RDSEED_FAILURE
|
xor eax, eax
|
||||||
jmp GenerateBlock_Ret
|
mov al, RDSEED_FAILURE
|
||||||
|
ret
|
||||||
|
|
||||||
GenerateBlock_Success:
|
GenerateBlock_Success:
|
||||||
|
|
||||||
mov eax, RDSEED_SUCCESS
|
xor eax, eax
|
||||||
|
mov al, RDSEED_SUCCESS
|
||||||
GenerateBlock_Ret:
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
MSC_RSA_GenerateBlock ENDP
|
MASM_RSA_GenerateBlock ENDP
|
||||||
|
|
||||||
ENDIF ;; _M_X86
|
ENDIF ;; _M_X86
|
||||||
|
|
||||||
|
|
@ -453,8 +441,7 @@ OPTION EPILOGUE:NONE
|
||||||
;; R8d (in): arg3, unsigned int safety
|
;; R8d (in): arg3, unsigned int safety
|
||||||
;; RAX (out): success (1), failure (0)
|
;; RAX (out): success (1), failure (0)
|
||||||
|
|
||||||
;; MSC_RSA_GenerateBlock PROC USES RCX ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
MASM_RSA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
||||||
MSC_RSA_GenerateBlock PROC ;; arg1:QWORD,arg2:QWORD,arg3:DWORD
|
|
||||||
|
|
||||||
MWSIZE EQU 08h ;; machine word size
|
MWSIZE EQU 08h ;; machine word size
|
||||||
buffer EQU rcx
|
buffer EQU rcx
|
||||||
|
|
@ -533,15 +520,13 @@ Bit_1_Not_Set:
|
||||||
|
|
||||||
;; Test bit 0 to see if size is at least 1
|
;; Test bit 0 to see if size is at least 1
|
||||||
test bsize, 1
|
test bsize, 1
|
||||||
;; jz Bit_0_Not_Set
|
|
||||||
jz GenerateBlock_Success
|
jz GenerateBlock_Success
|
||||||
|
|
||||||
mov BYTE PTR [buffer], al
|
mov BYTE PTR [buffer], al
|
||||||
|
|
||||||
Bit_0_Not_Set:
|
Bit_0_Not_Set:
|
||||||
|
|
||||||
;; We've hit all the bits, set size to 0
|
;; We've hit all the bits
|
||||||
;; mov bsize, 0
|
|
||||||
jmp GenerateBlock_Success
|
jmp GenerateBlock_Success
|
||||||
|
|
||||||
GenerateBlock_PreRet:
|
GenerateBlock_PreRet:
|
||||||
|
|
@ -552,18 +537,17 @@ GenerateBlock_PreRet:
|
||||||
|
|
||||||
GenerateBlock_Failure:
|
GenerateBlock_Failure:
|
||||||
|
|
||||||
mov rax, RDSEED_FAILURE
|
xor rax, rax
|
||||||
jmp GenerateBlock_Ret
|
mov al, RDSEED_FAILURE
|
||||||
|
ret
|
||||||
|
|
||||||
GenerateBlock_Success:
|
GenerateBlock_Success:
|
||||||
|
|
||||||
mov rax, RDSEED_SUCCESS
|
xor rax, rax
|
||||||
|
mov al, RDSEED_SUCCESS
|
||||||
GenerateBlock_Ret:
|
|
||||||
|
|
||||||
ret
|
ret
|
||||||
|
|
||||||
MSC_RSA_GenerateBlock ENDP
|
MASM_RSA_GenerateBlock ENDP
|
||||||
|
|
||||||
ENDIF ;; _M_X64
|
ENDIF ;; _M_X64
|
||||||
|
|
||||||
|
|
|
||||||
646
rdrand.cpp
646
rdrand.cpp
|
|
@ -20,225 +20,163 @@
|
||||||
// available. A lazy throw strategy is used in case the CPU does not support
|
// 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.
|
// 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....
|
// Here's the naming convention for the functions....
|
||||||
// MSC = Microsoft Compiler (and compatibles)
|
// MSC = Microsoft Compiler (and compatibles)
|
||||||
// GCC = GNU Compiler (and compatibles)
|
// GCC = GNU Compiler (and compatibles)
|
||||||
|
// ALL = MSC and GCC (and compatibles)
|
||||||
// RRA = RDRAND, Assembly
|
// RRA = RDRAND, Assembly
|
||||||
// RSA = RDSEED, Assembly
|
// RSA = RDSEED, Assembly
|
||||||
// RRI = RDRAND, Intrinsic
|
// RRI = RDRAND, Intrinsic
|
||||||
// RSA = RDSEED, 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
|
// For Linux, install NASM, run rdrand-nasm.asm, add the apppropriate
|
||||||
#if __GNUC__
|
// object file to the Makefile's LIBOBJS (rdrand-x{86|32|64}.o). After
|
||||||
# define GCC_RDSEED_INTRINSIC_AVAILABLE 0
|
// 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
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Microsoft uses Intel's intrinsics, and it excludes AMD's CPUs. You should
|
// According to Wei, CRYPTOPP_DISABLE_ASM is a failsafe due to the assembler.
|
||||||
// "#define MSC_RDRAND_INTRINSIC_AVAILABLE 0" and
|
// We sidestep it because it does not limit us. The assembler does not limit
|
||||||
// "#define MSC_RDSEED_INTRINSIC_AVAILABLE 0", if possible. The downside is
|
// us because we emit out own byte codes as needed. To diasble RDRAND or
|
||||||
// you must assemble the object files rdrand-x86.obj and rdrand-x86.obj and
|
// RDSEED, set CRYPTOPP_BOOL_RDRAND_ASM or CRYPTOPP_BOOL_RDSEED_ASM to 0.
|
||||||
// then build the rdrand-x86.lib and rdrand-x86.lib libraries. To build the
|
#ifndef CRYPTOPP_CPUID_AVAILABLE
|
||||||
// libraries run "make-rdrand.cmd" from a developer prompt.
|
# if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||||
|
# define CRYPTOPP_CPUID_AVAILABLE
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
// 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
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fallback to MSC_RDRAND_INTRINSIC_AVAILABLE on Windows. The compiler must support it.
|
#if defined(CRYPTOPP_CPUID_AVAILABLE) && !defined(CRYPTOPP_BOOL_RDRAND_ASM)
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && MSC_RDRAND_COMPILER
|
# define CRYPTOPP_BOOL_RDRAND_ASM 1
|
||||||
# if !defined(MSC_RDRAND_INTRINSIC_AVAILABLE) && !(MSC_RDRAND_ASM_AVAILABLE > 0)
|
#else
|
||||||
# define MSC_RDRAND_INTRINSIC_AVAILABLE 1
|
# define CRYPTOPP_BOOL_RDRAND_ASM 0
|
||||||
# define MSC_RDRAND_ASM_AVAILABLE 0
|
#endif
|
||||||
# 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
|
#endif
|
||||||
|
|
||||||
// GCC Compatible on Unix/Linux/Apple. Set GCC_RDRAND_INTRINSIC_AVAILABLE if
|
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
||||||
// it (and ASM) are not set. The requirements are __RDRND__ preprocessor.
|
# define MSC_INTRIN_COMPILER ((CRYPTOPP_MSC_VERSION >= 1700) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && GCC_RDRAND_COMPILER && (__RDRND__ >= 1)
|
# define GCC_INTRIN_COMPILER ((CRYPTOPP_GCC_VERSION >= 40600) || (CRYPTOPP_CLANG_VERSION >= 30200) || (_INTEL_COMPILER >= 1210))
|
||||||
# if !defined(GCC_RDRAND_INTRINSIC_AVAILABLE) && !(defined(GCC_RDRAND_ASM_AVAILABLE) && (GCC_RDRAND_ASM_AVAILABLE > 0))
|
#else
|
||||||
# define GCC_RDRAND_INTRINSIC_AVAILABLE 1
|
# define MSC_INTRIN_COMPILER 0
|
||||||
# define GCC_RDRAND_ASM_AVAILABLE 0
|
# define GCC_INTRIN_COMPILER 0
|
||||||
# endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fallback to MSC_ASM_INTRINSIC_AVAILABLE on Unix/Linux/Apple
|
// In general, the library's ASM code is best on Windows, and Intrinsics is
|
||||||
#if defined(CRYPTOPP_UNIX_AVAILABLE) && IA32_ASM && GCC_RDRAND_COMPILER
|
// the best code under GCC and compatibles. We favor them accordingly.
|
||||||
# if !defined(GCC_RDRAND_INTRINSIC_AVAILABLE) && !(defined(GCCC_RDRAND_ASM_AVAILABLE) && (GCCC_RDRAND_ASM_AVAILABLE > 0))
|
// The NASM code is optimized well on Linux, but its not easy to cut-in.
|
||||||
# define GCC_RDRAND_ASM_AVAILABLE 1
|
#if defined(CRYPTOPP_CPUID_AVAILABLE) && (CRYPTOPP_MSC_VERSION >= 1200)
|
||||||
# define GCC_RDRAND_INTRINSIC_AVAILABLE 0
|
# if CRYPTOPP_BOOL_RDRAND_ASM
|
||||||
# endif
|
# 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
|
#endif
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// MSC Compatible on Windows. Set MSC_RDRAND_ASM_AVAILABLE if it (and Intrinsics)
|
#if (ALL_RDRAND_INTRIN_AVAILABLE || ALL_RDSEED_INTRIN_AVAILABLE)
|
||||||
// are not set. The requirement is rdrand.asm assembled with MASM/MAS64. We use
|
# include <immintrin.h> // rdrand, MSC, ICC, and GCC
|
||||||
// CRYTPOPP_MSC_VERSION as a proxy for MASM/MAS64 availability.
|
# if defined(__has_include)
|
||||||
#if defined(CRYPTOPP_WIN32_AVAILABLE) && IA32_ASM && defined(CRYTPOPP_MSC_VERSION)
|
# if __has_include(<x86intrin.h>)
|
||||||
# if !defined(MSC_RDSEED_ASM_AVAILABLE) && !(MSC_RDSEED_INTRINSIC_AVAILABLE > 0)
|
# include <x86intrin.h> // rdseed for some compilers, like GCC
|
||||||
# define MSC_RDSEED_ASM_AVAILABLE 1
|
# endif
|
||||||
# define MSC_RDSEED_INTRINSIC_AVAILABLE 0
|
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Fallback to MSC_RDSEED_INTRINSIC_AVAILABLE on Windows. The compiler must support it.
|
#if MASM_RDRAND_ASM_AVAILABLE
|
||||||
#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
|
|
||||||
# ifdef _M_X64
|
# 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")
|
// # pragma comment(lib, "rdrand-x64.lib")
|
||||||
# else
|
# 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")
|
// # pragma comment(lib, "rdrand-x86.lib")
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if MSC_RDSEED_ASM_AVAILABLE
|
#if MASM_RDSEED_ASM_AVAILABLE
|
||||||
# ifdef _M_X64
|
# 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")
|
// # pragma comment(lib, "rdrand-x64.lib")
|
||||||
# else
|
# 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")
|
// # pragma comment(lib, "rdrand-x86.lib")
|
||||||
# endif
|
# endif
|
||||||
#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)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////
|
#if ALL_RDRAND_INTRIN_AVAILABLE
|
||||||
/////////////////////////////////////////////////////////////////////
|
static int ALL_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
#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])
|
|
||||||
{
|
{
|
||||||
// This is the "GenuineIntel" string
|
assert((output && size) || !(output || size));
|
||||||
return (output[1] /*EBX*/ == 0x756e6547) &&
|
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||||
(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
|
|
||||||
word64 val;
|
word64 val;
|
||||||
#else
|
#else
|
||||||
word32 val;
|
word32 val;
|
||||||
|
|
@ -246,7 +184,7 @@ static int MSC_RRI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
while (size >= sizeof(val))
|
while (size >= sizeof(val))
|
||||||
{
|
{
|
||||||
#if CRYPTOPP_BOOL_X64
|
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||||
if (_rdrand64_step((word64*)output))
|
if (_rdrand64_step((word64*)output))
|
||||||
#else
|
#else
|
||||||
if (_rdrand32_step((word32*)output))
|
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 (size)
|
||||||
{
|
{
|
||||||
#if CRYPTOPP_BOOL_X64
|
#if CRYPTOPP_BOOL_X64 || CRYTPOPP_BOOL_X32
|
||||||
if (_rdrand64_step(&val))
|
if (_rdrand64_step(&val))
|
||||||
#else
|
#else
|
||||||
if (_rdrand32_step(&val))
|
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;
|
*((volatile word64*)&val) = 0;
|
||||||
#else
|
#else
|
||||||
*((volatile word32*)&val) = 0;
|
*((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);
|
return int(size == 0);
|
||||||
}
|
}
|
||||||
|
#endif // ALL_RDRAND_INTRINSIC_AVAILABLE
|
||||||
#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
|
|
||||||
|
|
||||||
#if GCC_RDRAND_ASM_AVAILABLE
|
#if GCC_RDRAND_ASM_AVAILABLE
|
||||||
static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
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
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
word64 val;
|
word64 val;
|
||||||
#else
|
#else
|
||||||
|
|
@ -359,9 +241,13 @@ static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
__asm__ volatile(
|
__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; "
|
"setc %1; "
|
||||||
: "=r" (val), "=qm" (rc)
|
: "=a" (val), "=qm" (rc)
|
||||||
:
|
:
|
||||||
: "cc"
|
: "cc"
|
||||||
);
|
);
|
||||||
|
|
@ -404,103 +290,39 @@ static int GCC_RRA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
#endif // GCC_RDRAND_ASM_AVAILABLE
|
#endif // GCC_RDRAND_ASM_AVAILABLE
|
||||||
|
|
||||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||||
|
|
||||||
//! generate random array of bytes
|
|
||||||
void RDRAND::GenerateBlock(byte *output, size_t size)
|
void RDRAND::GenerateBlock(byte *output, size_t size)
|
||||||
{
|
{
|
||||||
assert((output == NULL && size == 0) || (output != NULL && size != 0));
|
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||||
assert(Available());
|
assert((output && size) || !(output || size));
|
||||||
|
|
||||||
// We could (should?) test Ready, but Available conveys more useful information.
|
if(!HasRDRAND())
|
||||||
if(!Available())
|
|
||||||
throw NotImplemented("RDRAND: rdrand is not available on this platform");
|
throw NotImplemented("RDRAND: rdrand is not available on this platform");
|
||||||
|
|
||||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
|
||||||
int rc; CRYPTOPP_UNUSED(rc);
|
int rc; CRYPTOPP_UNUSED(rc);
|
||||||
#if MSC_RDRAND_ASM_AVAILABLE
|
#if MASM_RDRAND_ASM_AVAILABLE
|
||||||
rc = MSC_RRA_GenerateBlock(output, size, m_retries);
|
rc = MASM_RRA_GenerateBlock(output, size, m_retries);
|
||||||
if (!rc) { throw RDRAND_Err("MSC_RRA_GenerateBlock"); }
|
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
|
#elif GCC_RDRAND_ASM_AVAILABLE
|
||||||
rc = GCC_RRA_GenerateBlock(output, size, m_retries);
|
rc = GCC_RRA_GenerateBlock(output, size, m_retries);
|
||||||
if (!rc) { throw RDRAND_Err("GCC_RRA_GenerateBlock"); }
|
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
|
#else
|
||||||
// RDRAND not detected at compile time, and no suitable compiler found
|
// RDRAND not detected at compile time, and no suitable compiler found
|
||||||
throw NotImplemented("RDRAND: failed to find a suitable implementation???");
|
throw NotImplemented("RDRAND: failed to find a suitable implementation???");
|
||||||
#endif
|
#endif // CRYPTOPP_CPUID_AVAILABLE
|
||||||
|
|
||||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//! 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)
|
void RDRAND::DiscardBytes(size_t n)
|
||||||
{
|
{
|
||||||
// RoundUpToMultipleOf is used because a full word is read, and its cheaper
|
// 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.
|
// to discard full words. There's no sense in dealing with tail bytes.
|
||||||
assert(Ready());
|
assert(HasRDRAND());
|
||||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
FixedSizeSecBlock<word64, 16> discard;
|
FixedSizeSecBlock<word64, 16> discard;
|
||||||
n = RoundUpToMultipleOf(n, sizeof(word64));
|
n = RoundUpToMultipleOf(n, sizeof(word64));
|
||||||
|
|
@ -517,41 +339,16 @@ void RDRAND::DiscardBytes(size_t n)
|
||||||
count = STDMIN(n, discard.SizeInBytes());
|
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)
|
assert((output && size) || !(output || size));
|
||||||
bool rdseed = false; word32 output[4];
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
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
|
|
||||||
word64 val;
|
word64 val;
|
||||||
#else
|
#else
|
||||||
word32 val;
|
word32 val;
|
||||||
|
|
@ -559,7 +356,7 @@ static int MSC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
while (size >= sizeof(val))
|
while (size >= sizeof(val))
|
||||||
{
|
{
|
||||||
#if CRYPTOPP_BOOL_X64
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
if (_rdseed64_step((word64*)output))
|
if (_rdseed64_step((word64*)output))
|
||||||
#else
|
#else
|
||||||
if (_rdseed32_step((word32*)output))
|
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 (size)
|
||||||
{
|
{
|
||||||
#if CRYPTOPP_BOOL_X64
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
if (_rdseed64_step(&val))
|
if (_rdseed64_step(&val))
|
||||||
#else
|
#else
|
||||||
if (_rdseed32_step(&val))
|
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
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
*((volatile word64*)&val) = 0;
|
*((volatile word64*)&val) = 0;
|
||||||
#else
|
#else
|
||||||
|
|
@ -657,12 +398,12 @@ static int GCC_RSI_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
return int(size == 0);
|
return int(size == 0);
|
||||||
}
|
}
|
||||||
|
#endif // ALL_RDSEED_INTRIN_AVAILABLE
|
||||||
#endif // GCC_RDSEED_INTRINSIC_AVAILABLE
|
|
||||||
|
|
||||||
#if GCC_RDSEED_ASM_AVAILABLE
|
#if GCC_RDSEED_ASM_AVAILABLE
|
||||||
static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
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
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
word64 val;
|
word64 val;
|
||||||
#else
|
#else
|
||||||
|
|
@ -672,9 +413,13 @@ static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
while (size)
|
while (size)
|
||||||
{
|
{
|
||||||
__asm__ volatile(
|
__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; "
|
"setc %1; "
|
||||||
: "=r" (val), "=qm" (rc)
|
: "=a" (val), "=qm" (rc)
|
||||||
:
|
:
|
||||||
: "cc"
|
: "cc"
|
||||||
);
|
);
|
||||||
|
|
@ -714,107 +459,41 @@ static int GCC_RSA_GenerateBlock(byte *output, size_t size, unsigned int safety)
|
||||||
|
|
||||||
return int(size == 0);
|
return int(size == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // GCC_RDSEED_ASM_AVAILABLE
|
#endif // GCC_RDSEED_ASM_AVAILABLE
|
||||||
|
|
||||||
#endif // CRYPTOPP_CPUID_AVAILABLE (CRYPTOPP_BOOL_{X86|X32|X64})
|
#if (CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64)
|
||||||
|
|
||||||
//! generate random array of bytes
|
|
||||||
void RDSEED::GenerateBlock(byte *output, size_t size)
|
void RDSEED::GenerateBlock(byte *output, size_t size)
|
||||||
{
|
{
|
||||||
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
CRYPTOPP_UNUSED(output), CRYPTOPP_UNUSED(size);
|
||||||
assert((output == NULL && size == 0) || (output != NULL && size != 0));
|
assert((output && size) || !(output || size));
|
||||||
assert(Available());
|
|
||||||
|
|
||||||
// We could (should?) test Ready, but Available conveys more useful information.
|
if(!HasRDSEED())
|
||||||
if(!Available())
|
|
||||||
throw NotImplemented("RDSEED: rdseed is not available on this platform");
|
throw NotImplemented("RDSEED: rdseed is not available on this platform");
|
||||||
|
|
||||||
#if defined(CRYPTOPP_CPUID_AVAILABLE)
|
|
||||||
int rc; CRYPTOPP_UNUSED(rc);
|
int rc; CRYPTOPP_UNUSED(rc);
|
||||||
#if MSC_RDSEED_ASM_AVAILABLE
|
#if MASM_RDSEED_ASM_AVAILABLE
|
||||||
rc = MSC_RSA_GenerateBlock(output, size, m_retries);
|
rc = MASM_RSA_GenerateBlock(output, size, m_retries);
|
||||||
if (!rc) { throw RDSEED_Err("MSC_RSA_GenerateBlock"); }
|
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
|
#elif GCC_RDSEED_ASM_AVAILABLE
|
||||||
rc = GCC_RSA_GenerateBlock(output, size, m_retries);
|
rc = GCC_RSA_GenerateBlock(output, size, m_retries);
|
||||||
if (!rc) { throw RDSEED_Err("GCC_RSA_GenerateBlock"); }
|
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
|
#else
|
||||||
// RDSEED not detected at compile time, and no suitable compiler found
|
// RDSEED not detected at compile time, and no suitable compiler found
|
||||||
throw NotImplemented("RDSEED: failed to find a suitable implementation???");
|
throw NotImplemented("RDSEED: failed to find a suitable implementation???");
|
||||||
#endif
|
#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)
|
void RDSEED::DiscardBytes(size_t n)
|
||||||
{
|
{
|
||||||
// RoundUpToMultipleOf is used because a full word is read, and its cheaper
|
// 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.
|
// to discard full words. There's no sense in dealing with tail bytes.
|
||||||
assert(Ready());
|
assert(HasRDSEED());
|
||||||
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
#if CRYPTOPP_BOOL_X64 || CRYPTOPP_BOOL_X32
|
||||||
FixedSizeSecBlock<word64, 16> discard;
|
FixedSizeSecBlock<word64, 16> discard;
|
||||||
n = RoundUpToMultipleOf(n, sizeof(word64));
|
n = RoundUpToMultipleOf(n, sizeof(word64));
|
||||||
|
|
@ -831,5 +510,6 @@ void RDSEED::DiscardBytes(size_t n)
|
||||||
count = STDMIN(n, discard.SizeInBytes());
|
count = STDMIN(n, discard.SizeInBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // CRYPTOPP_BOOL_X86 || CRYPTOPP_BOOL_X32 || CRYPTOPP_BOOL_X64
|
||||||
|
|
||||||
NAMESPACE_END
|
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.
|
// rdrand.h - written and placed in public domain by Jeffrey Walton and Uri Blumenthal.
|
||||||
// Copyright assigned to Crypto++ project.
|
// Copyright assigned to Crypto++ project.
|
||||||
|
|
||||||
|
//! \file
|
||||||
|
//! \headerfile rdrand.h
|
||||||
|
//! \brief Classes for RDRAND and RDSEED
|
||||||
|
|
||||||
#ifndef CRYPTOPP_RDRAND_H
|
#ifndef CRYPTOPP_RDRAND_H
|
||||||
#define CRYPTOPP_RDRAND_H
|
#define CRYPTOPP_RDRAND_H
|
||||||
|
|
||||||
#include "cryptlib.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.
|
// 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.
|
// 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)
|
NAMESPACE_BEGIN(CryptoPP)
|
||||||
|
|
||||||
|
//! \brief Exception thrown when a RDRAND generator encounters
|
||||||
|
//! a generator related error.
|
||||||
class RDRAND_Err : public Exception
|
class RDRAND_Err : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -23,61 +32,65 @@ public:
|
||||||
: Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
|
: Exception(OTHER_ERROR, "RDRAND: " + operation + " operation failed") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief Read hardware generated random numbers.
|
//! \brief Hardware generated random numbers using RDRAND instruction
|
||||||
|
//! \sa MaurerRandomnessTest() for random bit generators
|
||||||
//! This file (and friends) provides both RDRAND and RDSEED, but its somewhat
|
class RDRAND : public RandomNumberGenerator
|
||||||
//! 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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string AlgorithmName() const {return "RDRAND";}
|
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) {}
|
RDRAND(unsigned int retries = 8) : m_retries(retries) {}
|
||||||
|
|
||||||
virtual ~RDRAND() {}
|
virtual ~RDRAND() {}
|
||||||
|
|
||||||
//! returns true if RDRAND is present or available according to CPUID, false otherwise
|
//! \brief Retrieve the number of retries used by the generator
|
||||||
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;
|
|
||||||
|
|
||||||
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
||||||
unsigned int GetRetries() const
|
unsigned int GetRetries() const
|
||||||
{
|
{
|
||||||
return m_retries;
|
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)
|
void SetRetries(unsigned int retries)
|
||||||
{
|
{
|
||||||
m_retries = retries;
|
m_retries = retries;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! generate random array of bytes
|
//! \brief Generate random array of bytes
|
||||||
//! \param output the byte buffer
|
//! \param output the byte buffer
|
||||||
//! \param size the length of the buffer, in bytes
|
//! \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);
|
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.
|
//! \brief Generate and discard n bytes
|
||||||
//! \param n the number of bytes to discard
|
//! \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);
|
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 input unused
|
||||||
//! \param length unused
|
//! \param length unused
|
||||||
|
//! \details The operation is a nop for this generator.
|
||||||
virtual void IncorporateEntropy(const byte *input, size_t length)
|
virtual void IncorporateEntropy(const byte *input, size_t length)
|
||||||
{
|
{
|
||||||
// Override to avoid the base class' throw.
|
// Override to avoid the base class' throw.
|
||||||
|
|
@ -89,6 +102,8 @@ private:
|
||||||
unsigned int m_retries;
|
unsigned int m_retries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \brief Exception thrown when a RDSEED generator encounters
|
||||||
|
//! a generator related error.
|
||||||
class RDSEED_Err : public Exception
|
class RDSEED_Err : public Exception
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
@ -96,61 +111,65 @@ public:
|
||||||
: Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
|
: Exception(OTHER_ERROR, "RDSEED: " + operation + " operation failed") {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief Read hardware generated random numbers.
|
//! \brief Hardware generated random numbers using RDSEED instruction
|
||||||
|
//! \sa MaurerRandomnessTest() for random bit generators
|
||||||
//! This file (and friends) provides both RDRAND and RDSEED, but its somewhat
|
class RDSEED : public RandomNumberGenerator
|
||||||
//! 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
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::string AlgorithmName() const {return "RDSEED";}
|
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) {}
|
RDSEED(unsigned int retries = 8) : m_retries(retries) {}
|
||||||
|
|
||||||
virtual ~RDSEED() {}
|
virtual ~RDSEED() {}
|
||||||
|
|
||||||
//! returns true if RDSEED is present or available according to CPUID, false otherwise
|
//! \brief Retrieve the number of retries used by the generator
|
||||||
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;
|
|
||||||
|
|
||||||
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
//! returns the number of times GenerateBlock will attempt to recover from a failed generation
|
||||||
unsigned int GetRetries() const
|
unsigned int GetRetries() const
|
||||||
{
|
{
|
||||||
return m_retries;
|
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)
|
void SetRetries(unsigned int retries)
|
||||||
{
|
{
|
||||||
m_retries = retries;
|
m_retries = retries;
|
||||||
}
|
}
|
||||||
|
|
||||||
//! generate random array of bytes
|
//! \brief Generate random array of bytes
|
||||||
//! \param output the byte buffer
|
//! \param output the byte buffer
|
||||||
//! \param size the length of the buffer, in bytes
|
//! \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);
|
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.
|
//! \brief Generate and discard n bytes
|
||||||
//! \param n the number of bytes to discard
|
//! \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);
|
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 input unused
|
||||||
//! \param length unused
|
//! \param length unused
|
||||||
|
//! \details The operation is a nop for this generator.
|
||||||
virtual void IncorporateEntropy(const byte *input, size_t length)
|
virtual void IncorporateEntropy(const byte *input, size_t length)
|
||||||
{
|
{
|
||||||
// Override to avoid the base class' throw.
|
// Override to avoid the base class' throw.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue