Skip to content

Commit 5078cf4

Browse files
committed
DerInteger enhancements
1 parent 521a2ef commit 5078cf4

2 files changed

Lines changed: 96 additions & 22 deletions

File tree

CryptoLib/src/Asn1/ClpAsn1Objects.pas

Lines changed: 63 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2578,8 +2578,12 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
25782578
/// </summary>
25792579
function GetValue(): TBigInteger;
25802580
/// <summary>
2581-
/// Get the positive BigInteger value.
2581+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
25822582
/// </summary>
2583+
/// <remarks>
2584+
/// In some cases positive values get crammed into a space that's not quite big enough...
2585+
/// NB: The BigInteger constructor tolerates any redundant sign bytes (per 'AllowUnsafeInteger').
2586+
/// </remarks>
25832587
function GetPositiveValue(): TBigInteger;
25842588
/// <summary>
25852589
/// Check if this integer has a specific Int32 value.
@@ -2598,26 +2602,50 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
25982602
/// </summary>
25992603
function GetIntValueExact(): Int32;
26002604
/// <summary>
2601-
/// Get positive Int32 value, throwing if out of range.
2605+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
26022606
/// </summary>
2607+
/// <remarks>
2608+
/// In some cases positive values get crammed into a space that's not quite big enough...
2609+
/// </remarks>
26032610
function GetIntPositiveValueExact(): Int32;
26042611
/// <summary>
26052612
/// Get Int64 value, throwing if out of range.
26062613
/// </summary>
26072614
function GetLongValueExact(): Int64;
26082615
/// <summary>
2616+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
2617+
/// </summary>
2618+
/// <remarks>
2619+
/// In some cases positive values get crammed into a space that's not quite big enough...
2620+
/// </remarks>
2621+
function GetLongPositiveValueExact(): Int64;
2622+
/// <summary>
26092623
/// Try to get Int32 value, returning false if out of range.
26102624
/// </summary>
26112625
function TryGetIntValueExact(out AValue: Int32): Boolean;
26122626
/// <summary>
2613-
/// Try to get positive Int32 value, returning false if out of range.
2627+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
26142628
/// </summary>
2629+
/// <remarks>
2630+
/// In some cases positive values get crammed into a space that's not quite big enough...
2631+
/// </remarks>
26152632
function TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
26162633
/// <summary>
26172634
/// Try to get Int64 value, returning false if out of range.
26182635
/// </summary>
26192636
function TryGetLongValueExact(out AValue: Int64): Boolean;
26202637
/// <summary>
2638+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
2639+
/// </summary>
2640+
/// <remarks>
2641+
/// In some cases positive values get crammed into a space that's not quite big enough...
2642+
/// </remarks>
2643+
function TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
2644+
/// <summary>
2645+
/// Whether the first significant encoding byte has the sign bit set.
2646+
/// </summary>
2647+
function GetIsNegative(): Boolean;
2648+
/// <summary>
26212649
/// Check if bytes are malformed (invalid INTEGER encoding).
26222650
/// </summary>
26232651
class function IsMalformed(const ABytes: TCryptoLibByteArray): Boolean; static;
@@ -2642,6 +2670,8 @@ Meta = class sealed(TAsn1UniversalType, IAsn1UniversalType)
26422670
property IntValueExact: Int32 read GetIntValueExact;
26432671
property IntPositiveValueExact: Int32 read GetIntPositiveValueExact;
26442672
property LongValueExact: Int64 read GetLongValueExact;
2673+
property LongPositiveValueExact: Int64 read GetLongPositiveValueExact;
2674+
property IsNegative: Boolean read GetIsNegative;
26452675
end;
26462676

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

1266112691
function TDerInteger.GetIntValueExact(): Int32;
12662-
var
12663-
LCount: Int32;
1266412692
begin
12665-
LCount := System.Length(FBytes) - FStart;
12666-
if LCount > 4 then
12693+
if not TryGetIntValueExact(Result) then
1266712694
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of int range');
12668-
Result := TDerInteger.IntValue(FBytes, FStart, SignExtSigned);
1266912695
end;
1267012696

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

1268112703
function TDerInteger.GetLongValueExact(): Int64;
12682-
var
12683-
LCount: Int32;
1268412704
begin
12685-
LCount := System.Length(FBytes) - FStart;
12686-
if LCount > 8 then
12705+
if not TryGetLongValueExact(Result) then
1268712706
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of long range');
12688-
Result := TDerInteger.LongValue(FBytes, FStart, SignExtSigned);
12707+
end;
12708+
12709+
function TDerInteger.GetLongPositiveValueExact(): Int64;
12710+
begin
12711+
if not TryGetLongPositiveValueExact(Result) then
12712+
raise EArithmeticCryptoLibException.Create('ASN.1 Integer out of positive long range');
1268912713
end;
1269012714

1269112715
function TDerInteger.TryGetIntValueExact(out AValue: Int32): Boolean;
@@ -12708,7 +12732,7 @@ function TDerInteger.TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
1270812732
LCount: Int32;
1270912733
begin
1271012734
LCount := System.Length(FBytes) - FStart;
12711-
if (LCount > 4) or ((LCount = 4) and ((FBytes[FStart] and $80) <> 0)) then
12735+
if (LCount > 4) or ((LCount = 4) and IsNegative) then
1271212736
begin
1271312737
AValue := 0;
1271412738
Result := False;
@@ -12718,6 +12742,21 @@ function TDerInteger.TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
1271812742
Result := True;
1271912743
end;
1272012744

12745+
function TDerInteger.TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
12746+
var
12747+
LCount: Int32;
12748+
begin
12749+
LCount := System.Length(FBytes) - FStart;
12750+
if (LCount > 8) or ((LCount = 8) and IsNegative) then
12751+
begin
12752+
AValue := 0;
12753+
Result := False;
12754+
Exit;
12755+
end;
12756+
AValue := TDerInteger.LongValue(FBytes, FStart, SignExtSigned);
12757+
Result := True;
12758+
end;
12759+
1272112760
function TDerInteger.TryGetLongValueExact(out AValue: Int64): Boolean;
1272212761
var
1272312762
LCount: Int32;
@@ -12733,6 +12772,11 @@ function TDerInteger.TryGetLongValueExact(out AValue: Int64): Boolean;
1273312772
Result := True;
1273412773
end;
1273512774

12775+
function TDerInteger.GetIsNegative(): Boolean;
12776+
begin
12777+
Result := (FBytes[FStart] and $80) <> 0;
12778+
end;
12779+
1273612780
function TDerInteger.GetEncoding(AEncoding: Int32): IAsn1Encoding;
1273712781
begin
1273812782
Result := TPrimitiveEncoding.Create(TAsn1Tags.Universal, TAsn1Tags.Integer, FBytes);

CryptoLib/src/Interfaces/Asn1/ClpIAsn1Objects.pas

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -506,8 +506,12 @@ interface
506506
/// </summary>
507507
function GetValue(): TBigInteger;
508508
/// <summary>
509-
/// Get the positive BigInteger value.
509+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
510510
/// </summary>
511+
/// <remarks>
512+
/// In some cases positive values get crammed into a space that's not quite big enough...
513+
/// NB: The BigInteger constructor tolerates any redundant sign bytes (per 'AllowUnsafeInteger').
514+
/// </remarks>
511515
function GetPositiveValue(): TBigInteger;
512516
/// <summary>
513517
/// Check if this integer has a specific Int32 value.
@@ -526,31 +530,57 @@ interface
526530
/// </summary>
527531
function GetIntValueExact(): Int32;
528532
/// <summary>
529-
/// Get positive Int32 value, throwing if out of range.
533+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
530534
/// </summary>
535+
/// <remarks>
536+
/// In some cases positive values get crammed into a space that's not quite big enough...
537+
/// </remarks>
531538
function GetIntPositiveValueExact(): Int32;
532539
/// <summary>
533540
/// Get Int64 value, throwing if out of range.
534541
/// </summary>
535542
function GetLongValueExact(): Int64;
536543
/// <summary>
544+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
545+
/// </summary>
546+
/// <remarks>
547+
/// In some cases positive values get crammed into a space that's not quite big enough...
548+
/// </remarks>
549+
function GetLongPositiveValueExact(): Int64;
550+
/// <summary>
537551
/// Try to get Int32 value, returning false if out of range.
538552
/// </summary>
539553
function TryGetIntValueExact(out AValue: Int32): Boolean;
540554
/// <summary>
541-
/// Try to get positive Int32 value, returning false if out of range.
555+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
542556
/// </summary>
557+
/// <remarks>
558+
/// In some cases positive values get crammed into a space that's not quite big enough...
559+
/// </remarks>
543560
function TryGetIntPositiveValueExact(out AValue: Int32): Boolean;
544561
/// <summary>
545562
/// Try to get Int64 value, returning false if out of range.
546563
/// </summary>
547564
function TryGetLongValueExact(out AValue: Int64): Boolean;
565+
/// <summary>
566+
/// Force the ASN.1 INTEGER encoding to be interpreted as unsigned.
567+
/// </summary>
568+
/// <remarks>
569+
/// In some cases positive values get crammed into a space that's not quite big enough...
570+
/// </remarks>
571+
function TryGetLongPositiveValueExact(out AValue: Int64): Boolean;
572+
/// <summary>
573+
/// Whether the first significant encoding byte has the sign bit set.
574+
/// </summary>
575+
function GetIsNegative(): Boolean;
548576
property Bytes: TCryptoLibByteArray read GetBytes;
549577
property Value: TBigInteger read GetValue;
550578
property PositiveValue: TBigInteger read GetPositiveValue;
551579
property IntValueExact: Int32 read GetIntValueExact;
552580
property IntPositiveValueExact: Int32 read GetIntPositiveValueExact;
553581
property LongValueExact: Int64 read GetLongValueExact;
582+
property LongPositiveValueExact: Int64 read GetLongPositiveValueExact;
583+
property IsNegative: Boolean read GetIsNegative;
554584
end;
555585

556586
/// <summary>

0 commit comments

Comments
 (0)