diff --git a/cryptest.nmake b/cryptest.nmake index 484736f6..40294ac9 100644 --- a/cryptest.nmake +++ b/cryptest.nmake @@ -118,7 +118,7 @@ LIB_OBJS = \ zdeflate.obj zinflate.obj zlib.obj ASM_OBJS = \ - rdrand-x86.obj rdrand-x64.obj x64masm.obj x64dll.obj + rdrand-x86.obj rdrand-x64.obj rdseed-x86.obj rdseed-x64.obj x64masm.obj x64dll.obj TEST_SRCS = \ test.cpp bench1.cpp bench2.cpp bench3.cpp datatest.cpp \ @@ -196,10 +196,12 @@ PLATFORM = x64 # CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP AS = ml.exe ASFLAGS = /nologo /D_M_X86 /W3 /Cx /Zi /safeseh -LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm -LIB_OBJS = $(LIB_OBJS) rdrand-x86.obj +LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm +LIB_OBJS = $(LIB_OBJS) rdrand-x86.obj rdseed-x86.obj LDFLAGS = $(LDFLAGS) /MACHINE:X86 LDLIBS = $(LDLIBS) kernel32.lib +RDRAND_OBJ = rdrand-x86.obj +RDSEED_OBJ = rdseed-x86.obj !ENDIF # May need $(VCINSTALLDIR)\bin\amd64\ml64.exe @@ -209,10 +211,12 @@ LDLIBS = $(LDLIBS) kernel32.lib # CXXFLAGS = $(CXXFLAGS) /DWINAPI_FAMILY=WINAPI_FAMILY_APP AS = ml64.exe ASFLAGS = /nologo /D_M_X64 /W3 /Cx /Zi -LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm -LIB_OBJS = $(LIB_OBJS) rdrand-x64.obj x64masm.obj x64dll.obj +LIB_SRCS = $(LIB_SRCS) rdrand.cpp rdrand.asm rdseed.asm +LIB_OBJS = $(LIB_OBJS) rdrand-x64.obj rdseed-x64.obj x64masm.obj x64dll.obj LDFLAGS = $(LDFLAGS) /MACHINE:X64 LDLIBS = $(LDLIBS) kernel32.lib +RDRAND_OBJ = rdrand-x64.obj +RDSEED_OBJ = rdseed-x64.obj !ENDIF !IF "$(PLATFORM)" == "ARM" || "$(PLATFORM)" == "arm" || "$(PLATFORM)" == "ARM64" || "$(PLATFORM)" == "arm64" @@ -283,21 +287,25 @@ pch.pch: pch.h pch.cpp $(CXX) $(CXXFLAGS) /Yc"pch.h" /Fp"pch.pch" /c pch.cpp # No precompiled headers -iterhash.obj: +iterhash.obj: iterhash.h iterhash.cpp $(CXX) $(CXXFLAGS) /Y- /c iterhash.cpp -dll.obj: +dll.obj: dll.h dll.cpp $(CXX) $(CXXFLAGS) /Y- /c dll.cpp -rdrand.obj: +rdrand.obj: rdrand.h rdrand.cpp $(CXX) $(CXXFLAGS) /c rdrand.cpp # Built for x86/x64 -rdrand-x86.obj: +rdrand-x86.obj: rdrand.asm $(AS) $(ASFLAGS) /Fo rdrand-x86.obj /c rdrand.asm -rdrand-x64.obj: +rdrand-x64.obj: rdrand.asm $(AS) $(ASFLAGS) /Fo rdrand-x64.obj /c rdrand.asm -x64masm.obj: +rdseed-x86.obj: rdseed.asm + $(AS) $(ASFLAGS) /Fo rdseed-x86.obj /c rdseed.asm +rdseed-x64.obj: rdseed.asm + $(AS) $(ASFLAGS) /Fo rdseed-x64.obj /c rdseed.asm +x64masm.obj: x64masm.asm $(AS) $(ASFLAGS) /Fo x64masm.obj /c x64masm.asm -x64dll.obj: +x64dll.obj: x64dll.asm $(AS) $(ASFLAGS) /Fo x64dll.obj /c x64dll.asm # You may need to delete this on early versions of Visual Studio. diff --git a/cryptlib.vcxproj b/cryptlib.vcxproj index 4985c096..fbafa9e8 100644 --- a/cryptlib.vcxproj +++ b/cryptlib.vcxproj @@ -373,6 +373,16 @@ ml64.exe /c /nologo /D_M_X64 /W3 /Cx /Zi /Fo"$(IntDir)rdrand-x64.obj" "%(FullPath)" $(IntDir)\rdrand-x64.obj;%(Outputs) + + Building and assembling rdseed.asm + ml.exe /c /nologo /D_M_X86 /W3 /Cx /Zi /safeseh /Fo"$(IntDir)rdseed-x86.obj" "%(FullPath)" + $(IntDir)\rdseed-x86.obj;%(Outputs) + + + Building and assembling rdseed.asm + ml64.exe /c /nologo /D_M_X64 /W3 /Cx /Zi /Fo"$(IntDir)rdseed-x64.obj" "%(FullPath)" + $(IntDir)\rdseed-x64.obj;%(Outputs) + Building and assembling x64dll.asm ml64.exe /c /nologo /D_M_X64 /W3 /Zi /Fo"$(IntDir)x64dll.obj" "%(FullPath)" diff --git a/cryptlib.vcxproj.filters b/cryptlib.vcxproj.filters index de140e33..9dd9324f 100644 --- a/cryptlib.vcxproj.filters +++ b/cryptlib.vcxproj.filters @@ -1064,6 +1064,9 @@ Source Files + + Source Files + Source Files diff --git a/rdrand.asm b/rdrand.asm index a9434ba8..a1c3421a 100644 --- a/rdrand.asm +++ b/rdrand.asm @@ -1,9 +1,9 @@ ;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. ;; Copyright assigned to the Crypto++ project. -;; This ASM file provides RDRAND and RDSEED to downlevel Microsoft tool chains. -;; Everything "just works" under Visual Studio. Other platforms will have to -;; run MASM/MASM-64 and then link to the object files. +;; This ASM file provides RDRAND to downlevel Microsoft tool chains. +;; Everything "just works" under Visual Studio. Other platforms will +;; have to run MASM/MASM-64 and then link to the object files. ;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh ;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi @@ -13,11 +13,10 @@ ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -TITLE MASM_RDRAND_GenerateBlock and MASM_RDSEED_GenerateBlock -SUBTITLE Microsoft specific ASM code to utilize RDRAND and RDSEED for down level Microsoft toolchains +TITLE MASM_RDRAND_GenerateBlock source file +SUBTITLE Microsoft specific ASM code to utilize RDRAND for down level Microsoft toolchains PUBLIC MASM_RDRAND_GenerateBlock -PUBLIC MASM_RDSEED_GenerateBlock ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -38,7 +37,6 @@ IFDEF _M_X86 ;; Set via the command line ;; Fastcall calling conventions exports ALIAS <@MASM_RDRAND_GenerateBlock@8> = -ALIAS <@MASM_RDSEED_GenerateBlock@8> = ENDIF @@ -125,10 +123,10 @@ RDRAND_GenerateBlock_Return: MASM_RDRAND_GenerateBlock ENDP -ENDIF ;; _M_X86 +;; OPTION PROLOGUE:PrologueDef +;; OPTION EPILOGUE:EpilogueDef -OPTION PROLOGUE:PrologueDef -OPTION EPILOGUE:EpilogueDef +ENDIF ;; _M_X86 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -223,197 +221,11 @@ RDRAND_GenerateBlock_Return: MASM_RDRAND_GenerateBlock ENDP -ENDIF ;; _M_X64 - -OPTION PROLOGUE:PrologueDef -OPTION EPILOGUE:EpilogueDef - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -IFDEF _M_X86 ;; Set via the command line - -.CODE -ALIGN 8 -OPTION PROLOGUE:NONE -OPTION EPILOGUE:NONE - -;; No need for Load_Arguments due to fastcall -;; ECX (in): arg1, byte* buffer -;; EDX (in): arg2, size_t bsize - -MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD - - MWSIZE EQU 04h ;; machine word size - buffer EQU ecx - bsize EQU edx - - ;; Top of While loop -RDSEED_GenerateBlock_Top: - - ;; Check remaining size - cmp bsize, 0 - je RDSEED_GenerateBlock_Return - -RDSEED_Call_EAX: - ;; 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. - - ;; Retry immediately - jnc RDSEED_Call_EAX - -RDSEED_succeeded: - - cmp bsize, MWSIZE - jb RDSEED_Partial_Machine_Word - -RDSEED_Full_Machine_Word: - - mov DWORD PTR [buffer], eax - add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like - sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds - - ;; Continue - jmp RDSEED_GenerateBlock_Top - - ;; 1,2,3 bytes remain -RDSEED_Partial_Machine_Word: - - ;; Test bit 1 to see if size is at least 2 - test bsize, 2 - jz RDSEED_Bit_1_Not_Set - - mov WORD PTR [buffer], ax - shr eax, 16 - add buffer, 2 - -RDSEED_Bit_1_Not_Set: - - ;; Test bit 0 to see if size is at least 1 - test bsize, 1 - jz RDSEED_Bit_0_Not_Set - - mov BYTE PTR [buffer], al - -RDSEED_Bit_0_Not_Set: - - ;; We've hit all the bits - -RDSEED_GenerateBlock_Return: - - ;; Clear artifacts - xor eax, eax - ret - -MASM_RDSEED_GenerateBlock ENDP - -ENDIF ;; _M_X86 - -OPTION PROLOGUE:PrologueDef -OPTION EPILOGUE:EpilogueDef - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -IFDEF _M_X64 ;; Set via the command line - -.CODE -ALIGN 16 -OPTION PROLOGUE:NONE -OPTION EPILOGUE:NONE - -;; No need for Load_Arguments due to fastcall -;; RCX (in): arg1, byte* buffer -;; RDX (in): arg2, size_t bsize - -MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD - - MWSIZE EQU 08h ;; machine word size - buffer EQU rcx - bsize EQU rdx - - ;; Top of While loop -RDSEED_GenerateBlock_Top: - - ;; Check remaining size - cmp bsize, 0 - je RDSEED_GenerateBlock_Return - -RDSEED_Call_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. - - ;; Retry immediately - jnc RDSEED_Call_RAX - -RDSEED_succeeded: - - cmp bsize, MWSIZE - jb RDSEED_Partial_Machine_Word - -RDSEED_Full_Machine_Word: - - mov QWORD PTR [buffer], rax - add buffer, MWSIZE - sub bsize, MWSIZE - - ;; Continue - jmp RDSEED_GenerateBlock_Top - - ;; 1,2,3,4,5,6,7 bytes remain -RDSEED_Partial_Machine_Word: - - ;; Test bit 2 to see if size is at least 4 - test bsize, 4 - jz RDSEED_Bit_2_Not_Set - - mov DWORD PTR [buffer], eax - shr rax, 32 - add buffer, 4 - -RDSEED_Bit_2_Not_Set: - - ;; Test bit 1 to see if size is at least 2 - test bsize, 2 - jz RDSEED_Bit_1_Not_Set - - mov WORD PTR [buffer], ax - shr eax, 16 - add buffer, 2 - -RDSEED_Bit_1_Not_Set: - - ;; Test bit 0 to see if size is at least 1 - test bsize, 1 - jz RDSEED_Bit_0_Not_Set - - mov BYTE PTR [buffer], al - -RDSEED_Bit_0_Not_Set: - - ;; We've hit all the bits - -RDSEED_GenerateBlock_Return: - - ;; Clear artifacts - xor rax, rax - ret - -MASM_RDSEED_GenerateBlock ENDP +;; OPTION PROLOGUE:PrologueDef +;; OPTION EPILOGUE:EpilogueDef ENDIF ;; _M_X64 -OPTION PROLOGUE:PrologueDef -OPTION EPILOGUE:EpilogueDef - ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; diff --git a/rdseed.asm b/rdseed.asm new file mode 100644 index 00000000..48bb2c00 --- /dev/null +++ b/rdseed.asm @@ -0,0 +1,232 @@ +;; rdrand.asm - written and placed in public domain by Jeffrey Walton and Uri Blumenthal. +;; Copyright assigned to the Crypto++ project. + +;; This ASM file provides RDSEED to downlevel Microsoft tool chains. +;; Everything "just works" under Visual Studio. Other platforms will +;; have to run MASM/MASM-64 and then link to the object files. + +;; set ASFLAGS=/nologo /D_M_X86 /W3 /Cx /Zi /safeseh +;; set ASFLAGS64=/nologo /D_M_X64 /W3 /Cx /Zi +;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\ml.exe" %ASFLAGS% /Fo rdrand-x86.obj /c rdrand.asm +;; "C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\amd64\ml64.exe" %ASFLAGS64% /Fo rdrand-x64.obj /c rdrand.asm + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +TITLE MASM_RDSEED_GenerateBlock source file +SUBTITLE Microsoft specific ASM code to utilize RDSEED for down level Microsoft toolchains + +PUBLIC MASM_RDSEED_GenerateBlock + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;; C/C++ Function prototypes (both are fastcall) +;; X86: +;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size); +;; X64: +;; extern "C" void __fastcall MASM_RDSEED_GenerateBlock(byte* ptr, size_t size); + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +IFDEF _M_X86 ;; Set via the command line + +.486 +.MODEL FLAT + +;; Fastcall calling conventions exports +ALIAS <@MASM_RDSEED_GenerateBlock@8> = + +ENDIF + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +IFDEF _M_X86 ;; Set via the command line + +.CODE +ALIGN 8 +OPTION PROLOGUE:NONE +OPTION EPILOGUE:NONE + +;; No need for Load_Arguments due to fastcall +;; ECX (in): arg1, byte* buffer +;; EDX (in): arg2, size_t bsize + +MASM_RDSEED_GenerateBlock PROC ;; arg1:DWORD, arg2:DWORD + + MWSIZE EQU 04h ;; machine word size + buffer EQU ecx + bsize EQU edx + + ;; Top of While loop +RDSEED_GenerateBlock_Top: + + ;; Check remaining size + cmp bsize, 0 + je RDSEED_GenerateBlock_Return + +RDSEED_Call_EAX: + ;; 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. + + ;; Retry immediately + jnc RDSEED_Call_EAX + +RDSEED_succeeded: + + cmp bsize, MWSIZE + jb RDSEED_Partial_Machine_Word + +RDSEED_Full_Machine_Word: + + mov DWORD PTR [buffer], eax + add buffer, MWSIZE ;; No need for Intel Core 2 slow workarounds, like + sub bsize, MWSIZE ;; `lea buffer,[buffer+MWSIZE]` for faster adds + + ;; Continue + jmp RDSEED_GenerateBlock_Top + + ;; 1,2,3 bytes remain +RDSEED_Partial_Machine_Word: + + ;; Test bit 1 to see if size is at least 2 + test bsize, 2 + jz RDSEED_Bit_1_Not_Set + + mov WORD PTR [buffer], ax + shr eax, 16 + add buffer, 2 + +RDSEED_Bit_1_Not_Set: + + ;; Test bit 0 to see if size is at least 1 + test bsize, 1 + jz RDSEED_Bit_0_Not_Set + + mov BYTE PTR [buffer], al + +RDSEED_Bit_0_Not_Set: + + ;; We've hit all the bits + +RDSEED_GenerateBlock_Return: + + ;; Clear artifacts + xor eax, eax + ret + +MASM_RDSEED_GenerateBlock ENDP + +;; OPTION PROLOGUE:PrologueDef +;; OPTION EPILOGUE:EpilogueDef + +ENDIF ;; _M_X86 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +IFDEF _M_X64 ;; Set via the command line + +.CODE +ALIGN 16 +OPTION PROLOGUE:NONE +OPTION EPILOGUE:NONE + +;; No need for Load_Arguments due to fastcall +;; RCX (in): arg1, byte* buffer +;; RDX (in): arg2, size_t bsize + +MASM_RDSEED_GenerateBlock PROC ;; arg1:QWORD, arg2:QWORD + + MWSIZE EQU 08h ;; machine word size + buffer EQU rcx + bsize EQU rdx + + ;; Top of While loop +RDSEED_GenerateBlock_Top: + + ;; Check remaining size + cmp bsize, 0 + je RDSEED_GenerateBlock_Return + +RDSEED_Call_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. + + ;; Retry immediately + jnc RDSEED_Call_RAX + +RDSEED_succeeded: + + cmp bsize, MWSIZE + jb RDSEED_Partial_Machine_Word + +RDSEED_Full_Machine_Word: + + mov QWORD PTR [buffer], rax + add buffer, MWSIZE + sub bsize, MWSIZE + + ;; Continue + jmp RDSEED_GenerateBlock_Top + + ;; 1,2,3,4,5,6,7 bytes remain +RDSEED_Partial_Machine_Word: + + ;; Test bit 2 to see if size is at least 4 + test bsize, 4 + jz RDSEED_Bit_2_Not_Set + + mov DWORD PTR [buffer], eax + shr rax, 32 + add buffer, 4 + +RDSEED_Bit_2_Not_Set: + + ;; Test bit 1 to see if size is at least 2 + test bsize, 2 + jz RDSEED_Bit_1_Not_Set + + mov WORD PTR [buffer], ax + shr eax, 16 + add buffer, 2 + +RDSEED_Bit_1_Not_Set: + + ;; Test bit 0 to see if size is at least 1 + test bsize, 1 + jz RDSEED_Bit_0_Not_Set + + mov BYTE PTR [buffer], al + +RDSEED_Bit_0_Not_Set: + + ;; We've hit all the bits + +RDSEED_GenerateBlock_Return: + + ;; Clear artifacts + xor rax, rax + ret + +MASM_RDSEED_GenerateBlock ENDP + +;; OPTION PROLOGUE:PrologueDef +;; OPTION EPILOGUE:EpilogueDef + +ENDIF ;; _M_X64 + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +END diff --git a/test.cpp b/test.cpp index d1c143bc..7a483f6a 100644 --- a/test.cpp +++ b/test.cpp @@ -176,9 +176,8 @@ int scoped_main(int argc, char *argv[]) // A hint to help locate TestData/ and TestVectors/ after install. SetArgvPathHint(argv[0], g_argvPathHint); - // Set a seed for reproducible results. It can be set on the command line. - // If the seed is short then it is padded with spaces. If the seed is - // missing then time() is used. + // Set a seed for reproducible results. If the seed is too short then + // it is padded with spaces. If the seed is missing then time() is used. // For example: // ./cryptest.exe v seed=abcdefg SetGlobalSeed(argc, argv, s_globalSeed);