|
@@ -24,6 +24,12 @@ interface
|
|
|
uses
|
|
uses
|
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
|
Windows,
|
|
Windows,
|
|
|
|
|
+{$ELSEIF DEFINED(IOS)}
|
|
|
|
|
+ // iOS stuffs for Delphi
|
|
|
|
|
+ Macapi.Dispatch,
|
|
|
|
|
+ iOSapi.Foundation,
|
|
|
|
|
+{$ELSEIF DEFINED(DARWIN) AND (DEFINED(ARM) OR DEFINED(AARCH64))}
|
|
|
|
|
+ // iOS stuffs for FreePascal
|
|
|
{$ELSE}
|
|
{$ELSE}
|
|
|
Classes,
|
|
Classes,
|
|
|
SysUtils,
|
|
SysUtils,
|
|
@@ -32,8 +38,13 @@ uses
|
|
|
|
|
|
|
|
resourcestring
|
|
resourcestring
|
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
|
- SMSWIndowsCryptoAPIAvailableGenerationError =
|
|
|
|
|
|
|
+ SMSWIndowsCryptoAPIGenerationError =
|
|
|
'An Error Occured while generating random data using MS WIndows Crypto API.';
|
|
'An Error Occured while generating random data using MS WIndows Crypto API.';
|
|
|
|
|
+{$ELSEIF DEFINED(IOS)}
|
|
|
|
|
+ SIOSSecRandomCopyBytesGenerationError =
|
|
|
|
|
+ 'An Error Occured while generating random data using SecRandomCopyBytes API.';
|
|
|
|
|
+{$ELSEIF DEFINED(DARWIN) AND (DEFINED(ARM) OR DEFINED(AARCH64))}
|
|
|
|
|
+ SNotImplementedError = 'OSRandom has not been implemented for IOS';
|
|
|
{$ELSE}
|
|
{$ELSE}
|
|
|
SUnixRandomReadError =
|
|
SUnixRandomReadError =
|
|
|
'An Error Occured while reading random data from /dev/urandom or /dev/random.';
|
|
'An Error Occured while reading random data from /dev/urandom or /dev/random.';
|
|
@@ -49,9 +60,11 @@ type
|
|
|
/// This class returns random bytes from an OS-specific randomness
|
|
/// This class returns random bytes from an OS-specific randomness
|
|
|
/// source. The returned data should be unpredictable enough for
|
|
/// source. The returned data should be unpredictable enough for
|
|
|
/// cryptographic applications, though its exact quality depends on the
|
|
/// cryptographic applications, though its exact quality depends on the
|
|
|
- /// OS implementation. On a UNIX-like system this will query
|
|
|
|
|
- /// /dev/urandom or /dev/random (if the former is not available) , and
|
|
|
|
|
- /// on MSWINDOWS it will use CryptGenRandom().
|
|
|
|
|
|
|
+ /// OS implementation.
|
|
|
|
|
+ /// On a UNIX-like system this will read directly from /dev/urandom or /dev/random
|
|
|
|
|
+ /// (if the former is not available),
|
|
|
|
|
+ /// on iOS, calls SecRandomCopyBytes as /dev/(u)random is sandboxed,
|
|
|
|
|
+ /// on MSWINDOWS it will call CryptGenRandom().
|
|
|
/// </para>
|
|
/// </para>
|
|
|
/// </summary>
|
|
/// </summary>
|
|
|
|
|
|
|
@@ -64,6 +77,11 @@ type
|
|
|
|
|
|
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
{$IF DEFINED(MSWINDOWS)}
|
|
|
class function GenRandomBytesWindows(len: Int32; const data: PByte): Int32;
|
|
class function GenRandomBytesWindows(len: Int32; const data: PByte): Int32;
|
|
|
|
|
+{$ELSEIF DEFINED(IOS)}
|
|
|
|
|
+ class function GenRandomBytesIOSDelphi(len: Int32;
|
|
|
|
|
+ const data: PByte): Int32;
|
|
|
|
|
+{$ELSEIF DEFINED(DARWIN) AND (DEFINED(ARM) OR DEFINED(AARCH64))}
|
|
|
|
|
+ class function GenRandomBytesIOSFPC(len: Int32; const data: PByte): Int32;
|
|
|
{$ELSE}
|
|
{$ELSE}
|
|
|
class function GenRandomBytesUnix(len: Int32; const data: PByte): Int32;
|
|
class function GenRandomBytesUnix(len: Int32; const data: PByte): Int32;
|
|
|
{$IFEND $MSWINDOWS}
|
|
{$IFEND $MSWINDOWS}
|
|
@@ -89,19 +107,40 @@ function CryptGenRandom(hProv: THandle; dwLen: DWORD; pbBuffer: PByte): BOOL;
|
|
|
function CryptReleaseContext(hProv: THandle; dwFlags: DWORD): BOOL; stdcall;
|
|
function CryptReleaseContext(hProv: THandle; dwFlags: DWORD): BOOL; stdcall;
|
|
|
external ADVAPI32 Name 'CryptReleaseContext';
|
|
external ADVAPI32 Name 'CryptReleaseContext';
|
|
|
{$ENDIF MSWINDOWS}
|
|
{$ENDIF MSWINDOWS}
|
|
|
|
|
+{$IFDEF IOS}
|
|
|
|
|
+
|
|
|
|
|
+type
|
|
|
|
|
+ SecRandomRef = Pointer;
|
|
|
|
|
+
|
|
|
|
|
+const
|
|
|
|
|
+ libSecurity = '/System/Library/Frameworks/Security.framework/Security';
|
|
|
|
|
+
|
|
|
|
|
+function kSecRandomDefault: Pointer;
|
|
|
|
|
+
|
|
|
|
|
+function SecRandomCopyBytes(rnd: SecRandomRef; count: LongWord; bytes: PByte)
|
|
|
|
|
+ : Integer; cdecl; external libSecurity Name _PU + 'SecRandomCopyBytes';
|
|
|
|
|
+{$ENDIF IOS}
|
|
|
|
|
|
|
|
implementation
|
|
implementation
|
|
|
|
|
|
|
|
|
|
+{$IFDEF IOS}
|
|
|
|
|
+
|
|
|
|
|
+function kSecRandomDefault: Pointer;
|
|
|
|
|
+begin
|
|
|
|
|
+ result := CocoaPointerConst(libSecurity, 'kSecRandomDefault');
|
|
|
|
|
+end;
|
|
|
|
|
+{$ENDIF IOS}
|
|
|
|
|
+
|
|
|
class function TOSRandom.NoZeroes(const data: TCryptoLibByteArray): Boolean;
|
|
class function TOSRandom.NoZeroes(const data: TCryptoLibByteArray): Boolean;
|
|
|
var
|
|
var
|
|
|
i: Int32;
|
|
i: Int32;
|
|
|
begin
|
|
begin
|
|
|
- Result := True;
|
|
|
|
|
|
|
+ result := True;
|
|
|
for i := System.Low(data) to System.High(data) do
|
|
for i := System.Low(data) to System.High(data) do
|
|
|
begin
|
|
begin
|
|
|
if data[i] = 0 then
|
|
if data[i] = 0 then
|
|
|
begin
|
|
begin
|
|
|
- Result := False;
|
|
|
|
|
|
|
+ result := False;
|
|
|
Exit;
|
|
Exit;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
@@ -122,23 +161,39 @@ begin
|
|
|
if not CryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
|
|
if not CryptAcquireContextW(@hProv, nil, nil, PROV_RSA_FULL,
|
|
|
CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
|
|
CRYPT_VERIFYCONTEXT or CRYPT_SILENT) then
|
|
|
begin
|
|
begin
|
|
|
- Result := HResultFromWin32(GetLastError);
|
|
|
|
|
|
|
+ result := HResultFromWin32(GetLastError);
|
|
|
Exit;
|
|
Exit;
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
try
|
|
try
|
|
|
if not CryptGenRandom(hProv, len, data) then
|
|
if not CryptGenRandom(hProv, len, data) then
|
|
|
begin
|
|
begin
|
|
|
- Result := HResultFromWin32(GetLastError);
|
|
|
|
|
|
|
+ result := HResultFromWin32(GetLastError);
|
|
|
Exit;
|
|
Exit;
|
|
|
end;
|
|
end;
|
|
|
finally
|
|
finally
|
|
|
CryptReleaseContext(hProv, 0);
|
|
CryptReleaseContext(hProv, 0);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
- Result := S_OK;
|
|
|
|
|
|
|
+ result := S_OK;
|
|
|
|
|
+end;
|
|
|
|
|
+
|
|
|
|
|
+{$ELSEIF DEFINED(IOS)}
|
|
|
|
|
+
|
|
|
|
|
+class function TOSRandom.GenRandomBytesIOSDelphi(len: Int32;
|
|
|
|
|
+ const data: PByte): Int32;
|
|
|
|
|
+begin
|
|
|
|
|
+ // UNTESTED !!!, Please Take Note.
|
|
|
|
|
+ result := SecRandomCopyBytes(kSecRandomDefault, LongWord(len), data);
|
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
+{$ELSEIF DEFINED(DARWIN) AND (DEFINED(ARM) OR DEFINED(AARCH64))}
|
|
|
|
|
+
|
|
|
|
|
+class function TOSRandom.GenRandomBytesIOSFPC(len: Int32;
|
|
|
|
|
+ const data: PByte): Int32;
|
|
|
|
|
+begin
|
|
|
|
|
+ raise ENotImplementedCryptoLibException.CreateRes(@SNotImplementedError);
|
|
|
|
|
+end;
|
|
|
{$ELSE}
|
|
{$ELSE}
|
|
|
|
|
|
|
|
class function TOSRandom.GenRandomBytesUnix(len: Int32;
|
|
class function TOSRandom.GenRandomBytesUnix(len: Int32;
|
|
@@ -153,7 +208,7 @@ begin
|
|
|
RandGen := '/dev/random';
|
|
RandGen := '/dev/random';
|
|
|
if not FileExists(RandGen) then
|
|
if not FileExists(RandGen) then
|
|
|
begin
|
|
begin
|
|
|
- Result := -1;
|
|
|
|
|
|
|
+ result := -1;
|
|
|
Exit;
|
|
Exit;
|
|
|
end;
|
|
end;
|
|
|
end;
|
|
end;
|
|
@@ -163,9 +218,9 @@ begin
|
|
|
try
|
|
try
|
|
|
try
|
|
try
|
|
|
LStream.ReadBuffer(data[0], len);
|
|
LStream.ReadBuffer(data[0], len);
|
|
|
- Result := 0;
|
|
|
|
|
|
|
+ result := 0;
|
|
|
except
|
|
except
|
|
|
- Result := -1;
|
|
|
|
|
|
|
+ result := -1;
|
|
|
end;
|
|
end;
|
|
|
finally
|
|
finally
|
|
|
LStream.Free;
|
|
LStream.Free;
|
|
@@ -183,8 +238,23 @@ begin
|
|
|
if GenRandomBytesWindows(count, PByte(data)) <> 0 then
|
|
if GenRandomBytesWindows(count, PByte(data)) <> 0 then
|
|
|
begin
|
|
begin
|
|
|
raise EAccessCryptoLibException.CreateRes
|
|
raise EAccessCryptoLibException.CreateRes
|
|
|
- (@SMSWIndowsCryptoAPIAvailableGenerationError);
|
|
|
|
|
|
|
+ (@SMSWIndowsCryptoAPIGenerationError);
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
|
|
+{$ELSEIF DEFINED(IOS)}
|
|
|
|
|
+ if GenRandomBytesIOSDelphi(count, PByte(data)) <> 0 then
|
|
|
|
|
+ begin
|
|
|
|
|
+ raise EAccessCryptoLibException.CreateRes
|
|
|
|
|
+ (@SIOSSecRandomCopyBytesGenerationError);
|
|
|
end;
|
|
end;
|
|
|
|
|
+
|
|
|
|
|
+{$ELSEIF DEFINED(DARWIN) AND (DEFINED(ARM) OR DEFINED(AARCH64))}
|
|
|
|
|
+ if GenRandomBytesIOSFPC(count, PByte(data)) <> 0 then
|
|
|
|
|
+ begin
|
|
|
|
|
+ raise EAccessCryptoLibException.CreateRes
|
|
|
|
|
+ (@SIOSSecRandomCopyBytesGenerationError);
|
|
|
|
|
+ end;
|
|
|
|
|
+
|
|
|
{$ELSE}
|
|
{$ELSE}
|
|
|
if GenRandomBytesUnix(count, PByte(data)) <> 0 then
|
|
if GenRandomBytesUnix(count, PByte(data)) <> 0 then
|
|
|
begin
|
|
begin
|