2
0
Ugochukwu Mmaduekwe 6 жил өмнө
parent
commit
d8670eb912

+ 4 - 0
CryptoLib/src/Math/EC/Rfc8032/ClpEd25519.pas

@@ -1661,9 +1661,13 @@ begin
   // Recode the scalar into signed-digit form, then group comb bits in each block
 
   c1 := TNat.CAdd(ScalarUints, not(Int32(n[0])) and 1, n, FL, n);
+{$IFOPT C+}
   System.Assert(c1 = 0);
+{$ENDIF}
   c2 := TNat.ShiftDownBit(ScalarUints, n, UInt32(1));
+{$IFOPT C+}
   System.Assert(c2 = (UInt32(1) shl 31));
+{$ENDIF}
   for i := 0 to System.Pred(ScalarUints) do
   begin
     n[i] := TInterleave.Shuffle2(n[i]);

+ 107 - 56
CryptoLib/src/Utils/Randoms/ClpOSRandom.pas

@@ -125,9 +125,10 @@ type
   /// </item>
   /// <item>
   /// <term>Windows</term>
-  /// <description><see href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom">
-  /// CryptGenRandom</see> for <b>XP</b>, <see href="https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/nf-bcrypt-bcryptgenrandom">
-  /// BCryptGenRandom</see> for <b>Vista</b> Upwards</description>
+  /// <description>Checks availability in this order, <see href="https://docs.microsoft.com/en-us/windows/win32/api/ntsecapi/nf-ntsecapi-rtlgenrandom">
+  /// RtlGenRandom</see> =&gt; <see href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom">
+  /// CryptGenRandom</see> =&gt; <see href="https://docs.microsoft.com/en-us/windows/desktop/api/bcrypt/nf-bcrypt-bcryptgenrandom">
+  /// BCryptGenRandom</see></description>
   /// </item>
   /// <item>
   /// <term>Mac OS X</term>
@@ -212,6 +213,10 @@ type
 
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 
+  const
+    BCRYPT = 'bcrypt.dll';
+    ADVAPI32 = 'advapi32.dll';
+
   type
     BCRYPT_ALG_HANDLE = THandle;
     NTStatus = HRESULT;
@@ -236,25 +241,56 @@ type
       static; inline;
 
     class function IsCngBCryptGenRandomAvailable(): Boolean; static;
-    class function GenRandomBytesWindows(len: Int32; data: PByte)
-      : Int32; static;
+
     class property IsCngBCryptGenRandomSupportedOnOS: Boolean
       read GetIsCngBCryptGenRandomSupportedOnOS;
 
   type
-    TRtlGenRandom = function(RandomBuffer: PVOID; RandomBufferLength: ULONG): Boolean; stdcall;
+
+    TCryptGenRandom = function(hProv: THandle; dwLen: DWORD; pbBuffer: PByte)
+      : BOOL; stdcall;
+
+    TCryptAcquireContextW = function(phProv: Pointer; pszContainer: LPCWSTR;
+      pszProvider: LPCWSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;
+
+    TCryptReleaseContext = function(hProv: THandle; dwFlags: DWORD)
+      : BOOL; stdcall;
+
+  class var
+
+    FIsCryptGenRandomSupportedOnOS: Boolean;
+    FCryptGenRandom: TCryptGenRandom;
+    FCryptAcquireContextW: TCryptAcquireContextW;
+    FCryptReleaseContext: TCryptReleaseContext;
+
+    class function GetIsCryptGenRandomSupportedOnOS(): Boolean; static; inline;
+
+    class function IsCryptGenRandomAvailable(): Boolean; static;
+
+    class property IsCryptGenRandomSupportedOnOS: Boolean
+      read GetIsCryptGenRandomSupportedOnOS;
+
+  type
+    TRtlGenRandom = function(RandomBuffer: PVOID; RandomBufferLength: ULONG)
+      : Boolean; stdcall;
 
   class var
     FIsRtlGenRandomSupportedOnOS: Boolean;
     FRtlGenRandom: TRtlGenRandom;
 
-    class function GetIsRtlGenRandomSupportedOnOS(): Boolean;
-      static; inline;
+    class function GetIsRtlGenRandomSupportedOnOS(): Boolean; static; inline;
 
     class function IsRtlGenRandomAvailable(): Boolean; static;
 
     class property IsRtlGenRandomSupportedOnOS: Boolean
       read GetIsRtlGenRandomSupportedOnOS;
+
+    class function GetProcedureAddress(ModuleHandle: THandle;
+      const AProcedureName: String; var AFunctionFound: Boolean)
+      : Pointer; static;
+
+    class function GenRandomBytesWindows(len: Int32; data: PByte)
+      : Int32; static;
 {$ENDIF}
 
     // ================================================================//
@@ -292,23 +328,6 @@ type
   end;
 
   // ************************************************************************//
-
-{$IFDEF CRYPTOLIB_MSWINDOWS}
-
-const
-  ADVAPI32 = 'advapi32.dll';
-
-function CryptAcquireContextW(phProv: Pointer; pszContainer: LPCWSTR;
-  pszProvider: LPCWSTR; dwProvType: DWORD; dwFlags: DWORD): BOOL; stdcall;
-  external ADVAPI32 Name 'CryptAcquireContextW';
-
-function CryptGenRandom(hProv: THandle; dwLen: DWORD; pbBuffer: PByte): BOOL;
-  stdcall; external ADVAPI32 Name 'CryptGenRandom';
-
-function CryptReleaseContext(hProv: THandle; dwFlags: DWORD): BOOL; stdcall;
-  external ADVAPI32 Name 'CryptReleaseContext';
-{$ENDIF}
-// ************************************************************************//
 {$IFDEF CRYPTOLIB_APPLE}
 {$IFDEF FPC}
 
@@ -351,8 +370,9 @@ implementation
 class procedure TOSRandom.Boot;
 begin
 {$IFDEF CRYPTOLIB_MSWINDOWS}
-  FIsRtlGenRandomSupportedOnOS := IsRtlGenRandomAvailable();
   FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
+  FIsCryptGenRandomSupportedOnOS := IsCryptGenRandomAvailable();
+  FIsRtlGenRandomSupportedOnOS := IsRtlGenRandomAvailable();
 {$ENDIF}
 {$IFDEF CRYPTOLIB_HAS_GETRANDOM}
   FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
@@ -366,27 +386,50 @@ end;
 
 {$IFDEF CRYPTOLIB_MSWINDOWS}
 
+class function TOSRandom.GetProcedureAddress(ModuleHandle: THandle;
+  const AProcedureName: String; var AFunctionFound: Boolean): Pointer;
+begin
+  result := GetProcAddress(ModuleHandle, PChar(AProcedureName));
+  if result = Nil then
+  begin
+    AFunctionFound := False;
+  end;
+end;
+
 class function TOSRandom.GetIsCngBCryptGenRandomSupportedOnOS(): Boolean;
 begin
   result := FIsCngBCryptGenRandomSupportedOnOS;
 end;
 
+class function TOSRandom.GetIsCryptGenRandomSupportedOnOS(): Boolean;
+begin
+  result := FIsCryptGenRandomSupportedOnOS;
+end;
+
 class function TOSRandom.GetIsRtlGenRandomSupportedOnOS(): Boolean;
 begin
   result := FIsRtlGenRandomSupportedOnOS;
 end;
 
-function GetProcedureAddress(ModuleHandle: THandle; const AProcedureName: String;
-  var AFunctionFound: Boolean): Pointer;
+class function TOSRandom.IsCngBCryptGenRandomAvailable(): Boolean;
+var
+  ModuleHandle: THandle;
 begin
-  result := GetProcAddress(ModuleHandle, PChar(AProcedureName));
-  if result = Nil then
+  result := False;
+  ModuleHandle := SafeLoadLibrary(BCRYPT, SEM_FAILCRITICALERRORS);
+  if ModuleHandle <> 0 then
   begin
-    AFunctionFound := False;
+    result := True;
+    FBCryptOpenAlgorithmProvider := GetProcedureAddress(ModuleHandle,
+      'BCryptOpenAlgorithmProvider', result);
+    FBCryptCloseAlgorithmProvider := GetProcedureAddress(ModuleHandle,
+      'BCryptCloseAlgorithmProvider', result);
+    FBCryptGenRandom := GetProcedureAddress(ModuleHandle,
+      'BCryptGenRandom', result);
   end;
 end;
 
-class function TOSRandom.IsRtlGenRandomAvailable(): Boolean;
+class function TOSRandom.IsCryptGenRandomAvailable(): Boolean;
 var
   ModuleHandle: THandle;
 begin
@@ -395,26 +438,26 @@ begin
   if ModuleHandle <> 0 then
   begin
     result := True;
-    FRtlGenRandom := GetProcedureAddress(ModuleHandle, 'SystemFunction036', result);
+    FCryptAcquireContextW := GetProcedureAddress(ModuleHandle,
+      'CryptAcquireContextW', result);
+    FCryptReleaseContext := GetProcedureAddress(ModuleHandle,
+      'CryptReleaseContext', result);
+    FCryptGenRandom := GetProcedureAddress(ModuleHandle,
+      'CryptGenRandom', result);
   end;
 end;
 
-class function TOSRandom.IsCngBCryptGenRandomAvailable(): Boolean;
-const
-  BCRYPT = 'bcrypt.dll';
+class function TOSRandom.IsRtlGenRandomAvailable(): Boolean;
 var
   ModuleHandle: THandle;
 begin
   result := False;
-  ModuleHandle := SafeLoadLibrary(PChar(BCRYPT), SEM_FAILCRITICALERRORS);
+  ModuleHandle := SafeLoadLibrary(ADVAPI32, SEM_FAILCRITICALERRORS);
   if ModuleHandle <> 0 then
   begin
     result := True;
-    FBCryptOpenAlgorithmProvider :=
-      GetProcedureAddress(ModuleHandle, 'BCryptOpenAlgorithmProvider', result);
-    FBCryptCloseAlgorithmProvider :=
-      GetProcedureAddress(ModuleHandle, 'BCryptCloseAlgorithmProvider', result);
-    FBCryptGenRandom := GetProcedureAddress(ModuleHandle, 'BCryptGenRandom', result);
+    FRtlGenRandom := GetProcedureAddress(ModuleHandle,
+      'SystemFunction036', result);
   end;
 end;
 
@@ -435,55 +478,63 @@ const
   BCRYPT_RNG_ALGORITHM: WideString = 'RNG';
 
 begin
+  // first check if RtlGenRandom is available to avoid the memory overhead
+  // of pulling in 'CryptoAPI'
   if IsRtlGenRandomSupportedOnOS then
   begin
-    // Windows XP / Server 2003 and Above
+    // Availability: Windows XP / Server 2003 and Above
     if not FRtlGenRandom(data, ULONG(len)) then
     begin
       result := HResultFromWin32(GetLastError);
       Exit;
     end;
   end
-  else if IsCngBCryptGenRandomSupportedOnOS then
+  else if IsCryptGenRandomSupportedOnOS then
   begin
-    // Windows Vista and Above
-    if (not BCRYPT_SUCCESS(FBCryptOpenAlgorithmProvider(@hProv,
-      PWideChar(BCRYPT_RNG_ALGORITHM), nil, 0))) then
+    // Availability: Windows XP / Server 2003 and Above
+    if not FCryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
+      CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
     begin
       result := HResultFromWin32(GetLastError);
       Exit;
     end;
 
     try
-      if (not BCRYPT_SUCCESS(FBCryptGenRandom(hProv, PUCHAR(data),
-        ULONG(len), 0))) then
+      if not FCryptGenRandom(hProv, DWORD(len), data) then
       begin
         result := HResultFromWin32(GetLastError);
         Exit;
       end;
     finally
-      FBCryptCloseAlgorithmProvider(hProv, 0);
+      FCryptReleaseContext(hProv, 0);
     end;
   end
-  else
+  else if IsCngBCryptGenRandomSupportedOnOS then
   begin
-    // Below Windows Vista
-    if not CryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
-      CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
+    // Availability: Windows Vista / Server 2008 and Above
+    if (not BCRYPT_SUCCESS(FBCryptOpenAlgorithmProvider(@hProv,
+      PWideChar(BCRYPT_RNG_ALGORITHM), nil, 0))) then
     begin
       result := HResultFromWin32(GetLastError);
       Exit;
     end;
 
     try
-      if not CryptGenRandom(hProv, DWORD(len), data) then
+      if (not BCRYPT_SUCCESS(FBCryptGenRandom(hProv, PUCHAR(data),
+        ULONG(len), 0))) then
       begin
         result := HResultFromWin32(GetLastError);
         Exit;
       end;
     finally
-      CryptReleaseContext(hProv, 0);
+      FBCryptCloseAlgorithmProvider(hProv, 0);
     end;
+  end
+  else
+  begin
+    // should never happen but who knows :)
+    result := S_FALSE;
+    Exit;
   end;
   result := S_OK;
 end;