Просмотр исходного кода

improve random provider abstraction

Ugochukwu Mmaduekwe 15 часов назад
Родитель
Сommit
926256a987

+ 1 - 0
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -439,6 +439,7 @@ uses
   ClpIRandomNumberGenerator in '..\..\CryptoLib\src\Interfaces\Rngs\ClpIRandomNumberGenerator.pas',
   ClpAesRandomProvider in '..\..\CryptoLib\src\Rngs\Providers\ClpAesRandomProvider.pas',
   ClpDevRandomReader in '..\..\CryptoLib\src\Rngs\Providers\ClpDevRandomReader.pas',
+  ClpBaseRandomProvider in '..\..\CryptoLib\src\Rngs\Providers\ClpBaseRandomProvider.pas',
   ClpAsn1Parsers in '..\..\CryptoLib\src\Asn1\ClpAsn1Parsers.pas',
   ClpAsn1Core in '..\..\CryptoLib\src\Asn1\ClpAsn1Core.pas',
   ClpIAsn1Parsers in '..\..\CryptoLib\src\Interfaces\Asn1\ClpIAsn1Parsers.pas',

+ 5 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk

@@ -25,7 +25,7 @@
  Acknowledgements: 
 Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the development of this library "/>
     <Version Major="3" Minor="3"/>
-    <Files Count="468">
+    <Files Count="469">
       <Item1>
         <Filename Value="..\..\Asn1\ClpOidTokenizer.pas"/>
         <UnitName Value="ClpOidTokenizer"/>
@@ -1899,6 +1899,10 @@ Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring the devel
         <Filename Value="..\..\Rngs\Providers\ClpDevRandomReader.pas"/>
         <UnitName Value="ClpDevRandomReader"/>
       </Item468>
+      <Item469>
+        <Filename Value="..\..\Rngs\Providers\ClpBaseRandomProvider.pas"/>
+        <UnitName Value="ClpBaseRandomProvider"/>
+      </Item469>
     </Files>
     <CompatibilityMode Value="True"/>
     <RequiredPkgs Count="3">

+ 1 - 1
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.pas

@@ -154,7 +154,7 @@ uses
   ClpX509AttrCertParser, ClpAttributeCertificateIssuer, 
   ClpAttributeCertificateHolder, ClpX509Utilities, ClpX509Generators, 
   ClpDeltaCertificateTool, ClpX509Attribute, ClpX509ExtensionBase, 
-  ClpX509ExtensionUtilities, ClpDevRandomReader;
+  ClpX509ExtensionUtilities, ClpDevRandomReader, ClpBaseRandomProvider;
 
 implementation
 

+ 5 - 22
CryptoLib/src/Rngs/Providers/ClpAesRandomProvider.pas

@@ -33,6 +33,7 @@ uses
   ClpBufferedBlockCipher,
   ClpArrayUtilities,
   ClpOSRandomProvider,
+  ClpBaseRandomProvider,
   ClpIRandomSourceProvider,
   ClpCryptoLibTypes;
 
@@ -45,7 +46,7 @@ type
   /// AES-based random source provider.
   /// Implements counter-based AES PRNG with automatic reseeding.
   /// </summary>
-  TAesRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TAesRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
   const
@@ -82,11 +83,10 @@ type
 
     destructor Destroy; override;
 
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
 
     class property Instance: IRandomSourceProvider read GetInstance;
 
@@ -275,23 +275,6 @@ begin
   end;
 end;
 
-procedure TAesRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TAesRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True; // AES PRNG is always available

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpAppleRandomProvider.pas

@@ -40,7 +40,7 @@ uses
 {$ENDIF}
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SAppleSecRandomError =
@@ -71,7 +71,7 @@ function SecRandomCopyBytes(ARnd: SecRandomRef; ACount: NativeUInt;
   /// Apple OS random source provider.
   /// Implements Apple SecRandomCopyBytes and /dev/urandom fallback
   /// </summary>
-  TAppleRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TAppleRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
   const
@@ -82,10 +82,9 @@ function SecRandomCopyBytes(ARnd: SecRandomRef; ACount: NativeUInt;
   public
     constructor Create();
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -150,23 +149,6 @@ begin
   end;
 end;
 
-procedure TAppleRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TAppleRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True;

+ 72 - 0
CryptoLib/src/Rngs/Providers/ClpBaseRandomProvider.pas

@@ -0,0 +1,72 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  Distributed under the MIT software license, see the accompanying file LICENSE  * }
+{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }
+
+{ *                              Acknowledgements:                                  * }
+{ *                                                                                 * }
+{ *      Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpBaseRandomProvider;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpCryptoLibTypes,
+  ClpIRandomSourceProvider;
+
+type
+  /// <summary>
+  /// Abstract base class for all random source providers.
+  /// Provides a default GetNonZeroBytes implementation that delegates to GetBytes.
+  /// Subclasses must override GetBytes, GetIsAvailable, and GetName.
+  /// </summary>
+  TBaseRandomProvider = class abstract(TInterfacedObject, IRandomSourceProvider)
+
+  public
+    procedure GetBytes(const AData: TCryptoLibByteArray); virtual; abstract;
+
+    /// <summary>
+    /// Fills AData with non-zero random bytes. Calls GetBytes to fill the array,
+    /// then replaces any zero bytes individually. Subclasses may override if a
+    /// platform-specific optimized implementation is available.
+    /// </summary>
+    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray); virtual;
+
+    function GetIsAvailable: Boolean; virtual; abstract;
+    function GetName: String; virtual; abstract;
+
+  end;
+
+implementation
+
+{ TBaseRandomProvider }
+
+procedure TBaseRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
+var
+  LI: Int32;
+  LTmp: TCryptoLibByteArray;
+begin
+  GetBytes(AData);
+  System.SetLength(LTmp, 1);
+  for LI := System.Low(AData) to System.High(AData) do
+  begin
+    while AData[LI] = 0 do
+    begin
+      GetBytes(LTmp);
+      AData[LI] := LTmp[0];
+    end;
+  end;
+end;
+
+end.

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpGenericBSDRandomProvider.pas

@@ -25,7 +25,7 @@ interface
 uses
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SArc4RandomBufGenerationError =
@@ -39,7 +39,7 @@ type
   /// Generic BSD OS random source provider.
   /// Implements BSD variants using arc4random_buf
   /// </summary>
-  TGenericBSDRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TGenericBSDRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
     function GenRandomBytesGenericBSD(ALen: Int32; AData: PByte): Int32;
@@ -47,10 +47,9 @@ type
   public
     constructor Create();
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -91,23 +90,6 @@ begin
   end;
 end;
 
-procedure TGenericBSDRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TGenericBSDRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True;

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpLinuxRandomProvider.pas

@@ -34,7 +34,7 @@ uses
 {$ENDIF}
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SLinuxGetRandomError =
@@ -63,7 +63,7 @@ type
   /// Linux OS random source provider.
   /// Implements Linux getrandom and /dev/urandom fallback
   /// </summary>
-  TLinuxRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TLinuxRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
 {$IFDEF CRYPTOLIB_HAS_GETRANDOM}
@@ -78,10 +78,9 @@ type
   public
     constructor Create();
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -174,23 +173,6 @@ begin
   end;
 end;
 
-procedure TLinuxRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TLinuxRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True;

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpSolarisRandomProvider.pas

@@ -34,7 +34,7 @@ uses
 {$ENDIF}
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SSolarisGetRandomError =
@@ -61,7 +61,7 @@ type
   /// Solaris OS random source provider.
   /// Implements Solaris getrandom and /dev/urandom fallback
   /// </summary>
-  TSolarisRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TSolarisRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
 {$IFDEF CRYPTOLIB_HAS_GETRANDOM}
@@ -76,10 +76,9 @@ type
   public
     constructor Create();
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -181,23 +180,6 @@ begin
   end;
 end;
 
-procedure TSolarisRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TSolarisRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True;

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpUnixRandomProvider.pas

@@ -25,7 +25,7 @@ interface
 uses
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SRandomDeviceReadError =
@@ -36,7 +36,7 @@ type
   /// Unix OS random source provider (fallback for other Unix systems).
   /// Implements /dev/urandom fallback
   /// </summary>
-  TUnixRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TUnixRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
     function GenRandomBytesUnix(ALen: Int32; AData: PByte): Int32;
@@ -44,10 +44,9 @@ type
   public
     constructor Create();
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -89,23 +88,6 @@ begin
   end;
 end;
 
-procedure TUnixRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TUnixRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := True;

+ 5 - 23
CryptoLib/src/Rngs/Providers/ClpWindowsRandomProvider.pas

@@ -26,7 +26,7 @@ uses
   Windows,
   SysUtils,
   ClpCryptoLibTypes,
-  ClpIRandomSourceProvider;
+  ClpBaseRandomProvider;
 
 resourcestring
   SWindowsCryptoApiGenerationError =
@@ -37,7 +37,7 @@ type
   /// Windows OS random source provider.
   /// Implements Windows random APIs in order: BCryptGenRandom -> RtlGenRandom -> CryptGenRandom
   /// </summary>
-  TWindowsRandomProvider = class sealed(TInterfacedObject, IRandomSourceProvider)
+  TWindowsRandomProvider = class sealed(TBaseRandomProvider)
 
   strict private
   const
@@ -93,10 +93,9 @@ type
     constructor Create();
     destructor Destroy; override;
 
-    procedure GetBytes(const AData: TCryptoLibByteArray);
-    procedure GetNonZeroBytes(const AData: TCryptoLibByteArray);
-    function GetIsAvailable: Boolean;
-    function GetName: String;
+    procedure GetBytes(const AData: TCryptoLibByteArray); override;
+    function GetIsAvailable: Boolean; override;
+    function GetName: String; override;
 
   end;
 
@@ -294,23 +293,6 @@ begin
   end;
 end;
 
-procedure TWindowsRandomProvider.GetNonZeroBytes(const AData: TCryptoLibByteArray);
-var
-  LI: Int32;
-  LTmp: TCryptoLibByteArray;
-begin
-  GetBytes(AData);
-  System.SetLength(LTmp, 1);
-  for LI := System.Low(AData) to System.High(AData) do
-  begin
-    while AData[LI] = 0 do
-    begin
-      GetBytes(LTmp);
-      AData[LI] := LTmp[0];
-    end;
-  end;
-end;
-
 function TWindowsRandomProvider.GetIsAvailable: Boolean;
 begin
   Result := FHasBCryptGenRandom or FHasRtlGenRandom or FHasCryptGenRandom;