Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 63 additions & 19 deletions CryptoLib/src/Asn1/ClpAsn1Objects.pas
Original file line number Diff line number Diff line change
Expand Up @@ -2578,8 +2578,12 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
/// </summary>
function GetValue(): TBigInteger;
/// <summary>
/// Get the positive BigInteger value.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// NB: The BigInteger constructor tolerates any redundant sign bytes (per 'AllowUnsafeInteger').
/// </remarks>
function GetPositiveValue(): TBigInteger;
/// <summary>
/// Check if this integer has a specific Int32 value.
Expand All @@ -2598,26 +2602,50 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
/// </summary>
function GetIntValueExact(): Int32;
/// <summary>
/// Get positive Int32 value, throwing if out of range.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function GetIntPositiveValueExact(): Int32;
/// <summary>
/// Get Int64 value, throwing if out of range.
/// </summary>
function GetLongValueExact(): Int64;
/// <summary>
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function GetLongPositiveValueExact(): Int64;
/// <summary>
/// Try to get Int32 value, returning false if out of range.
/// </summary>
function TryGetIntValueExact(out AValue: Int32): Boolean;
/// <summary>
/// Try to get positive Int32 value, returning false if out of range.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
/// <summary>
/// Try to get Int64 value, returning false if out of range.
/// </summary>
function TryGetLongValueExact(out AValue: Int64): Boolean;
/// <summary>
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
/// <summary>
/// Whether the first significant encoding byte has the sign bit set.
/// </summary>
function GetIsNegative(): Boolean;
/// <summary>
/// Check if bytes are malformed (invalid INTEGER encoding).
/// </summary>
class function IsMalformed(const ABytes: TCryptoLibByteArray): Boolean; static;
Expand All @@ -2642,6 +2670,8 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
property IntValueExact: Int32 read GetIntValueExact;
property IntPositiveValueExact: Int32 read GetIntPositiveValueExact;
property LongValueExact: Int64 read GetLongValueExact;
property LongPositiveValueExact: Int64 read GetLongPositiveValueExact;
property IsNegative: Boolean read GetIsNegative;
end;

/// <summary>
Expand Down Expand Up @@ -12659,33 +12689,27 @@ function TDerInteger.HasValue(const AX: TBigInteger): Boolean;
end;

function TDerInteger.GetIntValueExact(): Int32;
var
LCount: Int32;
begin
LCount := System.Length(FBytes) - FStart;
if LCount > 4 then
if not TryGetIntValueExact(Result) then
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of int range');
Result := TDerInteger.IntValue(FBytes, FStart, SignExtSigned);
end;

function TDerInteger.GetIntPositiveValueExact(): Int32;
var
LCount: Int32;
begin
LCount := System.Length(FBytes) - FStart;
if (LCount > 4) or ((LCount = 4) and ((FBytes[FStart] and $80) <> 0)) then
if not TryGetIntPositiveValueExact(Result) then
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of positive int range');
Result := TDerInteger.IntValue(FBytes, FStart, SignExtUnsigned);
end;

function TDerInteger.GetLongValueExact(): Int64;
var
LCount: Int32;
begin
LCount := System.Length(FBytes) - FStart;
if LCount > 8 then
if not TryGetLongValueExact(Result) then
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of long range');
Result := TDerInteger.LongValue(FBytes, FStart, SignExtSigned);
end;

function TDerInteger.GetLongPositiveValueExact(): Int64;
begin
if not TryGetLongPositiveValueExact(Result) then
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of positive long range');
end;

function TDerInteger.TryGetIntValueExact(out AValue: Int32): Boolean;
Expand All @@ -12708,7 +12732,7 @@ function TDerInteger.TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
LCount: Int32;
begin
LCount := System.Length(FBytes) - FStart;
if (LCount > 4) or ((LCount = 4) and ((FBytes[FStart] and $80) <> 0)) then
if (LCount > 4) or ((LCount = 4) and IsNegative) then
begin
AValue := 0;
Result := False;
Expand All @@ -12718,6 +12742,21 @@ function TDerInteger.TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
Result := True;
end;

function TDerInteger.TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
var
LCount: Int32;
begin
LCount := System.Length(FBytes) - FStart;
if (LCount > 8) or ((LCount = 8) and IsNegative) then
begin
AValue := 0;
Result := False;
Exit;
end;
AValue := TDerInteger.LongValue(FBytes, FStart, SignExtSigned);
Result := True;
end;

function TDerInteger.TryGetLongValueExact(out AValue: Int64): Boolean;
var
LCount: Int32;
Expand All @@ -12733,6 +12772,11 @@ function TDerInteger.TryGetLongValueExact(out AValue: Int64): Boolean;
Result := True;
end;

function TDerInteger.GetIsNegative(): Boolean;
begin
Result := (FBytes[FStart] and $80) <> 0;
end;

function TDerInteger.GetEncoding(AEncoding: Int32): IAsn1Encoding;
begin
Result := TPrimitiveEncoding.Create(TAsn1Tags.Universal, TAsn1Tags.Integer, FBytes);
Expand Down
36 changes: 33 additions & 3 deletions CryptoLib/src/Interfaces/Asn1/ClpIAsn1Objects.pas
Original file line number Diff line number Diff line change
Expand Up @@ -506,8 +506,12 @@ interface
/// </summary>
function GetValue(): TBigInteger;
/// <summary>
/// Get the positive BigInteger value.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// NB: The BigInteger constructor tolerates any redundant sign bytes (per 'AllowUnsafeInteger').
/// </remarks>
function GetPositiveValue(): TBigInteger;
/// <summary>
/// Check if this integer has a specific Int32 value.
Expand All @@ -526,31 +530,57 @@ interface
/// </summary>
function GetIntValueExact(): Int32;
/// <summary>
/// Get positive Int32 value, throwing if out of range.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function GetIntPositiveValueExact(): Int32;
/// <summary>
/// Get Int64 value, throwing if out of range.
/// </summary>
function GetLongValueExact(): Int64;
/// <summary>
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function GetLongPositiveValueExact(): Int64;
/// <summary>
/// Try to get Int32 value, returning false if out of range.
/// </summary>
function TryGetIntValueExact(out AValue: Int32): Boolean;
/// <summary>
/// Try to get positive Int32 value, returning false if out of range.
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
/// <summary>
/// Try to get Int64 value, returning false if out of range.
/// </summary>
function TryGetLongValueExact(out AValue: Int64): Boolean;
/// <summary>
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
/// </summary>
/// <remarks>
/// In some cases positive values get crammed into a space that's not quite big enough...
/// </remarks>
function TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
/// <summary>
/// Whether the first significant encoding byte has the sign bit set.
/// </summary>
function GetIsNegative(): Boolean;
property Bytes: TCryptoLibByteArray read GetBytes;
property Value: TBigInteger read GetValue;
property PositiveValue: TBigInteger read GetPositiveValue;
property IntValueExact: Int32 read GetIntValueExact;
property IntPositiveValueExact: Int32 read GetIntPositiveValueExact;
property LongValueExact: Int64 read GetLongValueExact;
property LongPositiveValueExact: Int64 read GetLongPositiveValueExact;
property IsNegative: Boolean read GetIsNegative;
end;

/// <summary>
Expand Down
Loading