|
@@ -40,7 +40,8 @@ uses
|
|
|
{$IFEND} // ENDIF CRYPTOLIB_MACOS
|
|
{$IFEND} // ENDIF CRYPTOLIB_MACOS
|
|
|
{$ENDIF} // ENDIF FPC
|
|
{$ENDIF} // ENDIF FPC
|
|
|
{$ENDIF} // ENDIF CRYPTOLIB_APPLE
|
|
{$ENDIF} // ENDIF CRYPTOLIB_APPLE
|
|
|
-{$IFDEF CRYPTOLIB_LINUX}
|
|
|
|
|
|
|
+{$IFDEF CRYPTOLIB_UNIX}
|
|
|
|
|
+ Classes,
|
|
|
{$IFDEF FPC}
|
|
{$IFDEF FPC}
|
|
|
BaseUnix,
|
|
BaseUnix,
|
|
|
dl,
|
|
dl,
|
|
@@ -48,13 +49,10 @@ uses
|
|
|
Posix.Errno,
|
|
Posix.Errno,
|
|
|
Posix.Dlfcn,
|
|
Posix.Dlfcn,
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
-{$ENDIF} // ENDIF CRYPTOLIB_LINUX
|
|
|
|
|
|
|
+{$ENDIF} // ENDIF CRYPTOLIB_UNIX
|
|
|
{$IFDEF CRYPTOLIB_PUREBSD}
|
|
{$IFDEF CRYPTOLIB_PUREBSD}
|
|
|
// PureBSD (NetBSD, FreeBSD, OpenBSD)
|
|
// PureBSD (NetBSD, FreeBSD, OpenBSD)
|
|
|
{$ENDIF} // ENDIF CRYPTOLIB_PUREBSD
|
|
{$ENDIF} // ENDIF CRYPTOLIB_PUREBSD
|
|
|
-{$IFDEF CRYPTOLIB_UNIX}
|
|
|
|
|
- Classes,
|
|
|
|
|
-{$ENDIF} // ENDIF CRYPTOLIB_UNIX
|
|
|
|
|
{$IF DEFINED(CRYPTOLIB_MSWINDOWS) OR DEFINED(CRYPTOLIB_UNIX)}
|
|
{$IF DEFINED(CRYPTOLIB_MSWINDOWS) OR DEFINED(CRYPTOLIB_UNIX)}
|
|
|
SysUtils,
|
|
SysUtils,
|
|
|
{$IFEND} // ENDIF CRYPTOLIB_MSWINDOWS OR CRYPTOLIB_UNIX
|
|
{$IFEND} // ENDIF CRYPTOLIB_MSWINDOWS OR CRYPTOLIB_UNIX
|
|
@@ -73,14 +71,18 @@ resourcestring
|
|
|
SLinuxGetRandomError =
|
|
SLinuxGetRandomError =
|
|
|
'An Error Occured while generating random data using getRandom API';
|
|
'An Error Occured while generating random data using getRandom API';
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
|
|
+{$IFDEF CRYPTOLIB_SOLARIS}
|
|
|
|
|
+ SSolarisGetRandomError =
|
|
|
|
|
+ 'An Error Occured while generating random data using getRandom API';
|
|
|
|
|
+{$ENDIF}
|
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
|
SArc4RandomBufGenerationError =
|
|
SArc4RandomBufGenerationError =
|
|
|
'An Error Occured while generating random data using arc4random_buf API.';
|
|
'An Error Occured while generating random data using arc4random_buf API.';
|
|
|
{$ENDIF}
|
|
{$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
|
|
type
|
|
|
|
|
|
|
@@ -107,6 +109,13 @@ type
|
|
|
/// available)</description>
|
|
/// available)</description>
|
|
|
/// </item>
|
|
/// </item>
|
|
|
/// <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>
|
|
/// <term>Windows</term>
|
|
|
/// <description><see href="https://docs.microsoft.com/en-us/windows/desktop/api/wincrypt/nf-wincrypt-cryptgenrandom">
|
|
/// <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">
|
|
/// 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}
|
|
{$IFDEF CRYPTOLIB_LINUX}
|
|
|
|
|
+ LIBC_SO = 'libc.so.6';
|
|
|
|
|
+{$ENDIF}
|
|
|
|
|
+{$IFDEF CRYPTOLIB_SOLARIS}
|
|
|
|
|
+ LIBC_SO = 'libc.so.1';
|
|
|
|
|
+{$ENDIF}
|
|
|
|
|
+
|
|
|
type
|
|
type
|
|
|
TGetRandom = function(pbBuffer: PByte; buflen: LongWord; flags: UInt32)
|
|
TGetRandom = function(pbBuffer: PByte; buflen: LongWord; flags: UInt32)
|
|
|
: Int32; cdecl;
|
|
: Int32; cdecl;
|
|
@@ -208,6 +228,11 @@ type
|
|
|
class function GenRandomBytesLinux(len: Int32; data: PByte): Int32; static;
|
|
class function GenRandomBytesLinux(len: Int32; data: PByte): Int32; static;
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
// ================================================================//
|
|
// ================================================================//
|
|
|
|
|
+{$IFDEF CRYPTOLIB_SOLARIS}
|
|
|
|
|
+ class function GenRandomBytesSolaris(len: Int32; data: PByte)
|
|
|
|
|
+ : Int32; static;
|
|
|
|
|
+{$ENDIF}
|
|
|
|
|
+ // ================================================================//
|
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
|
class function GenRandomBytesGenericBSD(len: Int32; data: PByte)
|
|
class function GenRandomBytesGenericBSD(len: Int32; data: PByte)
|
|
|
: Int32; static;
|
|
: Int32; static;
|
|
@@ -303,7 +328,7 @@ begin
|
|
|
{$IFDEF CRYPTOLIB_MSWINDOWS}
|
|
{$IFDEF CRYPTOLIB_MSWINDOWS}
|
|
|
FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
|
|
FIsCngBCryptGenRandomSupportedOnOS := IsCngBCryptGenRandomAvailable();
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
-{$IFDEF CRYPTOLIB_LINUX}
|
|
|
|
|
|
|
+{$IFDEF CRYPTOLIB_UNIX}
|
|
|
FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
|
|
FIsGetRandomSupportedOnOS := IsGetRandomAvailable();
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
end;
|
|
end;
|
|
@@ -436,11 +461,20 @@ class function TOSRandom.dev_random_device_read(len: Int32; data: PByte): Int32;
|
|
|
var
|
|
var
|
|
|
LStream: TFileStream;
|
|
LStream: TFileStream;
|
|
|
RandGen: String;
|
|
RandGen: String;
|
|
|
|
|
+ got, MaxChunkSize: Int32;
|
|
|
begin
|
|
begin
|
|
|
|
|
+ MaxChunkSize := len;
|
|
|
RandGen := '/dev/urandom';
|
|
RandGen := '/dev/urandom';
|
|
|
|
|
+{$IFDEF CRYPTOLIB_SOLARIS}
|
|
|
|
|
+ MaxChunkSize := 128 * 1040; // 128 * 1040 bytes
|
|
|
|
|
+{$ENDIF}
|
|
|
if not FileExists(RandGen) then
|
|
if not FileExists(RandGen) then
|
|
|
begin
|
|
begin
|
|
|
|
|
+{$IFDEF CRYPTOLIB_SOLARIS}
|
|
|
|
|
+ MaxChunkSize := 1040; // 1040 bytes
|
|
|
|
|
+{$ENDIF}
|
|
|
RandGen := '/dev/random';
|
|
RandGen := '/dev/random';
|
|
|
|
|
+
|
|
|
if not FileExists(RandGen) then
|
|
if not FileExists(RandGen) then
|
|
|
begin
|
|
begin
|
|
|
result := -1;
|
|
result := -1;
|
|
@@ -451,18 +485,36 @@ begin
|
|
|
LStream := TFileStream.Create(RandGen, fmOpenRead);
|
|
LStream := TFileStream.Create(RandGen, fmOpenRead);
|
|
|
|
|
|
|
|
try
|
|
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;
|
|
end;
|
|
|
|
|
+ result := 0;
|
|
|
finally
|
|
finally
|
|
|
LStream.Free;
|
|
LStream.Free;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
|
{$ENDIF}
|
|
{$ENDIF}
|
|
|
-{$IFDEF CRYPTOLIB_LINUX}
|
|
|
|
|
|
|
+{$IFDEF CRYPTOLIB_UNIX}
|
|
|
|
|
|
|
|
class function TOSRandom.ErrorNo: Int32;
|
|
class function TOSRandom.ErrorNo: Int32;
|
|
|
begin
|
|
begin
|
|
@@ -475,13 +527,11 @@ begin
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
class function TOSRandom.IsGetRandomAvailable(): Boolean;
|
|
class function TOSRandom.IsGetRandomAvailable(): Boolean;
|
|
|
-const
|
|
|
|
|
- LIBC_SO_6 = 'libc.so.6';
|
|
|
|
|
var
|
|
var
|
|
|
Lib: {$IFDEF FPC} PtrInt {$ELSE} NativeUInt {$ENDIF};
|
|
Lib: {$IFDEF FPC} PtrInt {$ELSE} NativeUInt {$ENDIF};
|
|
|
begin
|
|
begin
|
|
|
FGetRandom := Nil;
|
|
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
|
|
if Lib <> 0 then
|
|
|
begin
|
|
begin
|
|
|
FGetRandom := dlsym(Lib, 'getrandom');
|
|
FGetRandom := dlsym(Lib, 'getrandom');
|
|
@@ -490,29 +540,32 @@ begin
|
|
|
result := System.Assigned(FGetRandom);
|
|
result := System.Assigned(FGetRandom);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+{$ENDIF}
|
|
|
|
|
+{$IFDEF CRYPTOLIB_LINUX}
|
|
|
|
|
+
|
|
|
class function TOSRandom.GenRandomBytesLinux(len: Int32; data: PByte): Int32;
|
|
class function TOSRandom.GenRandomBytesLinux(len: Int32; data: PByte): Int32;
|
|
|
-const
|
|
|
|
|
- GRND_DEFAULT: Int32 = $0000;
|
|
|
|
|
- EINTR = {$IFDEF FPC}ESysEINTR {$ELSE}Posix.Errno.EINTR{$ENDIF};
|
|
|
|
|
var
|
|
var
|
|
|
- n: Int64;
|
|
|
|
|
|
|
+ got: Int32;
|
|
|
begin
|
|
begin
|
|
|
|
|
+
|
|
|
if IsGetRandomSupportedOnOS then
|
|
if IsGetRandomSupportedOnOS then
|
|
|
begin
|
|
begin
|
|
|
while (len > 0) do
|
|
while (len > 0) do
|
|
|
begin
|
|
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
|
|
begin
|
|
|
|
|
+ if ErrorNo = EINTR then
|
|
|
|
|
+ begin
|
|
|
|
|
+ continue;
|
|
|
|
|
+ end;
|
|
|
result := -1;
|
|
result := -1;
|
|
|
Exit;
|
|
Exit;
|
|
|
end;
|
|
end;
|
|
|
- System.Inc(data, n);
|
|
|
|
|
- System.Dec(len, n);
|
|
|
|
|
|
|
+ System.Inc(data, got);
|
|
|
|
|
+ System.Dec(len, got);
|
|
|
end;
|
|
end;
|
|
|
result := 0;
|
|
result := 0;
|
|
|
end
|
|
end
|
|
@@ -522,7 +575,46 @@ begin
|
|
|
result := dev_random_device_read(len, data);
|
|
result := dev_random_device_read(len, data);
|
|
|
end;
|
|
end;
|
|
|
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}
|
|
{$ENDIF}
|
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
{$IFDEF CRYPTOLIB_GENERIC_BSD}
|
|
|
|
|
|
|
@@ -566,17 +658,23 @@ begin
|
|
|
raise EOSRandomCryptoLibException.CreateRes(@SLinuxGetRandomError);
|
|
raise EOSRandomCryptoLibException.CreateRes(@SLinuxGetRandomError);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+{$ELSEIF DEFINED(CRYPTOLIB_SOLARIS)}
|
|
|
|
|
+ if GenRandomBytesSolaris(count, PByte(data)) <> 0 then
|
|
|
|
|
+ begin
|
|
|
|
|
+ raise EOSRandomCryptoLibException.CreateRes(@SSolarisGetRandomError);
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
{$ELSEIF DEFINED(CRYPTOLIB_GENERIC_BSD)}
|
|
{$ELSEIF DEFINED(CRYPTOLIB_GENERIC_BSD)}
|
|
|
if GenRandomBytesGenericBSD(count, PByte(data)) <> 0 then
|
|
if GenRandomBytesGenericBSD(count, PByte(data)) <> 0 then
|
|
|
begin
|
|
begin
|
|
|
raise EOSRandomCryptoLibException.CreateRes(@SArc4RandomBufGenerationError);
|
|
raise EOSRandomCryptoLibException.CreateRes(@SArc4RandomBufGenerationError);
|
|
|
end;
|
|
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}
|
|
{$ELSE}
|
|
|
{$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
|
|
{$MESSAGE ERROR 'UNSUPPORTED TARGET.'}
|
|
|
{$IFEND}
|
|
{$IFEND}
|