Browse Source

add Solaris support (untested)

Ugochukwu Mmaduekwe 6 years ago
parent
commit
ab6898578d
3 changed files with 139 additions and 35 deletions
  1. 4 0
      CryptoLib/src/Include/CryptoLib.inc
  2. 133 35
      CryptoLib/src/Utils/Randoms/ClpOSRandom.pas
  3. 2 0
      README.md

+ 4 - 0
CryptoLib/src/Include/CryptoLib.inc

@@ -49,6 +49,7 @@
    {$DEFINE CRYPTOLIB_UNIX}
    {$IF DEFINED(BSD)}
       {$IF DEFINED(DARWIN)}
+         {$UNDEF CRYPTOLIB_UNIX}
          {$DEFINE CRYPTOLIB_APPLE}
          {$IF DEFINED(CRYPTOLIB_ARM) OR DEFINED(CRYPTOLIB_AARCH64)}
             {$DEFINE CRYPTOLIB_IOS}
@@ -56,10 +57,13 @@
             {$DEFINE CRYPTOLIB_MACOS}
          {$IFEND}
       {$ELSEIF DEFINED(FREEBSD) OR DEFINED(NETBSD) OR DEFINED(OPENBSD) OR DEFINED(DRAGONFLY)}
+         {$UNDEF CRYPTOLIB_UNIX}
          {$DEFINE CRYPTOLIB_GENERIC_BSD}
       {$IFEND}
   {$ELSEIF DEFINED(LINUX)}
      {$DEFINE CRYPTOLIB_LINUX}
+  {$ELSEIF DEFINED(SOLARIS)}
+     {$DEFINE CRYPTOLIB_SOLARIS}
   {$ELSE}
      {$DEFINE CRYPTOLIB_UNDEFINED_UNIX_VARIANTS}
   {$IFEND}

+ 133 - 35
CryptoLib/src/Utils/Randoms/ClpOSRandom.pas

@@ -40,7 +40,8 @@ uses
 {$IFEND} // ENDIF CRYPTOLIB_MACOS
 {$ENDIF}  // ENDIF FPC
 {$ENDIF}   // ENDIF CRYPTOLIB_APPLE
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_UNIX}
+  Classes,
 {$IFDEF FPC}
   BaseUnix,
   dl,
@@ -48,13 +49,10 @@ uses
   Posix.Errno,
   Posix.Dlfcn,
 {$ENDIF}
-{$ENDIF}  // ENDIF CRYPTOLIB_LINUX
+{$ENDIF}  // ENDIF CRYPTOLIB_UNIX
 {$IFDEF CRYPTOLIB_PUREBSD}
   // PureBSD (NetBSD, FreeBSD, OpenBSD)
 {$ENDIF}  // ENDIF CRYPTOLIB_PUREBSD
-{$IFDEF CRYPTOLIB_UNIX}
-  Classes,
-{$ENDIF}  // ENDIF CRYPTOLIB_UNIX
 {$IF DEFINED(CRYPTOLIB_MSWINDOWS) OR DEFINED(CRYPTOLIB_UNIX)}
   SysUtils,
 {$IFEND}  // ENDIF CRYPTOLIB_MSWINDOWS OR CRYPTOLIB_UNIX
@@ -73,14 +71,18 @@ resourcestring
   SLinuxGetRandomError =
     'An Error Occured while generating random data using getRandom API';
 {$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+  SSolarisGetRandomError =
+    'An Error Occured while generating random data using getRandom API';
+{$ENDIF}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
   SArc4RandomBufGenerationError =
     'An Error Occured while generating random data using arc4random_buf API.';
 {$ENDIF}
-{$IFDEF CRYPTOLIB_UNIX}
-  SRandomDeviceReadError =
-    'An Error Occured while reading random data from random device (file)';
-{$ENDIF}
+  // {$IFDEF CRYPTOLIB_UNIX}
+  // SRandomDeviceReadError =
+  // 'An Error Occured while reading random data from random device (file)';
+  // {$ENDIF}
 
 type
 
@@ -107,6 +109,13 @@ type
   /// available)</description>
   /// </item>
   /// <item>
+  /// <term>Solaris</term>
+  /// <description><see href="https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html">
+  /// getrandom</see> system call if available, otherwise ( <see href="https://docs.oracle.com/cd/E86824_01/html/E54777/random-7d.html">
+  /// /dev/urandom or /dev/random</see>) (which ever is
+  /// available)</description>
+  /// </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">
@@ -145,7 +154,18 @@ type
 
     // ================================================================//
 
+{$IFDEF CRYPTOLIB_UNIX}
+  const
+    GRND_DEFAULT: Int32 = $0000;
+    EINTR = {$IFDEF FPC}ESysEINTR {$ELSE}Posix.Errno.EINTR{$ENDIF};
+
 {$IFDEF CRYPTOLIB_LINUX}
+    LIBC_SO = 'libc.so.6';
+{$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+    LIBC_SO = 'libc.so.1';
+{$ENDIF}
+
   type
     TGetRandom = function(pbBuffer: PByte; buflen: LongWord; flags: UInt32)
       : Int32; cdecl;
@@ -208,6 +228,11 @@ type
     class function GenRandomBytesLinux(len: Int32; data: PByte): Int32; static;
 {$ENDIF}
     // ================================================================//
+{$IFDEF CRYPTOLIB_SOLARIS}
+    class function GenRandomBytesSolaris(len: Int32; data: PByte)
+      : Int32; static;
+{$ENDIF}
+    // ================================================================//
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
     class function GenRandomBytesGenericBSD(len: Int32; data: PByte)
       : Int32; static;
@@ -303,7 +328,7 @@ begin
 {$IFDEF CRYPTOLIB_MSWINDOWS}
   FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
 {$ENDIF}
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_UNIX}
   FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
 {$ENDIF}
 end;
@@ -436,11 +461,20 @@ class function TOSRandom.dev_random_device_read(len: Int32; data: PByte): Int32;
 var
   LStream: TFileStream;
   RandGen: String;
+  got, MaxChunkSize: Int32;
 begin
+  MaxChunkSize := len;
   RandGen := '/dev/urandom';
+{$IFDEF CRYPTOLIB_SOLARIS}
+  MaxChunkSize := 128 * 1040; // 128 * 1040 bytes
+{$ENDIF}
   if not FileExists(RandGen) then
   begin
+{$IFDEF CRYPTOLIB_SOLARIS}
+    MaxChunkSize := 1040; // 1040 bytes
+{$ENDIF}
     RandGen := '/dev/random';
+
     if not FileExists(RandGen) then
     begin
       result := -1;
@@ -451,18 +485,36 @@ begin
   LStream := TFileStream.Create(RandGen, fmOpenRead);
 
   try
-    try
-      LStream.ReadBuffer(data[0], len);
-      result := 0;
-    except
-      result := -1;
+    while (len > 0) do
+    begin
+      if len <= MaxChunkSize then
+      begin
+        MaxChunkSize := len;
+      end;
+
+      got := LStream.Read(data^, MaxChunkSize);
+
+      if (got = 0) then
+      begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
+
+        result := -1;
+        Exit;
+      end;
+
+      System.Inc(data, got);
+      System.Dec(len, got);
     end;
+    result := 0;
   finally
     LStream.Free;
   end;
 end;
 {$ENDIF}
-{$IFDEF CRYPTOLIB_LINUX}
+{$IFDEF CRYPTOLIB_UNIX}
 
 class function TOSRandom.ErrorNo: Int32;
 begin
@@ -475,13 +527,11 @@ begin
 end;
 
 class function TOSRandom.IsGetRandomAvailable(): Boolean;
-const
-  LIBC_SO_6 = 'libc.so.6';
 var
   Lib: {$IFDEF FPC} PtrInt {$ELSE} NativeUInt {$ENDIF};
 begin
   FGetRandom := Nil;
-  Lib := {$IFDEF FPC}PtrInt{$ENDIF}(dlopen(LIBC_SO_6, RTLD_NOW));
+  Lib := {$IFDEF FPC}PtrInt{$ENDIF}(dlopen(LIBC_SO, RTLD_NOW));
   if Lib <> 0 then
   begin
     FGetRandom := dlsym(Lib, 'getrandom');
@@ -490,29 +540,32 @@ begin
   result := System.Assigned(FGetRandom);
 end;
 
+{$ENDIF}
+{$IFDEF CRYPTOLIB_LINUX}
+
 class function TOSRandom.GenRandomBytesLinux(len: Int32; data: PByte): Int32;
-const
-  GRND_DEFAULT: Int32 = $0000;
-  EINTR = {$IFDEF FPC}ESysEINTR {$ELSE}Posix.Errno.EINTR{$ENDIF};
 var
-  n: Int64;
+  got: Int32;
 begin
+
   if IsGetRandomSupportedOnOS then
   begin
     while (len > 0) do
     begin
 
-      repeat
-        n := FGetRandom(data, LongWord(len), GRND_DEFAULT);
-      until ((n > 0) and (ErrorNo <> EINTR));
+      got := FGetRandom(data, LongWord(len), GRND_DEFAULT);
 
-      if (n <= 0) then
+      if (got < 0) then
       begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
         result := -1;
         Exit;
       end;
-      System.Inc(data, n);
-      System.Dec(len, n);
+      System.Inc(data, got);
+      System.Dec(len, got);
     end;
     result := 0;
   end
@@ -522,7 +575,46 @@ begin
     result := dev_random_device_read(len, data);
   end;
 end;
+{$ENDIF}
+{$IFDEF CRYPTOLIB_SOLARIS}
+
+class function TOSRandom.GenRandomBytesSolaris(len: Int32; data: PByte): Int32;
+var
+  got, MaxChunkSize: Int32;
+begin
+  MaxChunkSize := 256; // 256 bytes
+
+  if IsGetRandomSupportedOnOS then
+  begin
+    while (len > 0) do
+    begin
+      if len <= MaxChunkSize then
+      begin
+        MaxChunkSize := len;
+      end;
+
+      got := FGetRandom(data, LongWord(MaxChunkSize), GRND_DEFAULT);
 
+      if (got = 0) then
+      begin
+        if ErrorNo = EINTR then
+        begin
+          continue;
+        end;
+        result := -1;
+        Exit;
+      end;
+      System.Inc(data, got);
+      System.Dec(len, got);
+    end;
+    result := 0;
+  end
+  else
+  begin
+    // fallback for when getrandom API is not available
+    result := dev_random_device_read(len, data);
+  end;
+end;
 {$ENDIF}
 {$IFDEF CRYPTOLIB_GENERIC_BSD}
 
@@ -566,17 +658,23 @@ begin
     raise EOSRandomCryptoLibException.CreateRes(@SLinuxGetRandomError);
   end;
 
+{$ELSEIF DEFINED(CRYPTOLIB_SOLARIS)}
+  if GenRandomBytesSolaris(count, PByte(data)) <> 0 then
+  begin
+    raise EOSRandomCryptoLibException.CreateRes(@SSolarisGetRandomError);
+  end;
+
 {$ELSEIF DEFINED(CRYPTOLIB_GENERIC_BSD)}
   if GenRandomBytesGenericBSD(count, PByte(data)) <> 0 then
   begin
     raise EOSRandomCryptoLibException.CreateRes(@SArc4RandomBufGenerationError);
   end;
-{$ELSEIF DEFINED(CRYPTOLIB_UNDEFINED_UNIX_VARIANTS)}
-  // fallback option for other Undefined Unix OSes
-  if dev_random_device_read(count, PByte(data)) <> 0 then
-  begin
-    raise EOSRandomCryptoLibException.CreateRes(@SRandomDeviceReadError);
-  end;
+  // {$ELSEIF DEFINED(CRYPTOLIB_UNDEFINED_UNIX_VARIANTS)}
+  // // fallback option for other Undefined Unix OSes
+  // if dev_random_device_read(count, PByte(data)) <> 0 then
+  // begin
+  // raise EOSRandomCryptoLibException.CreateRes(@SRandomDeviceReadError);
+  // end;
 {$ELSE}
 {$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
 {$IFEND}

+ 2 - 0
README.md

@@ -186,6 +186,8 @@ Available Algorithms
 
 * `FreeBSD, NetBSD, OpenBSD and DragonBSD`
 
+* `Solaris (Untested)`
+
 ### Acknowledgements
 ----------------------------------------