diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr index dc9d03c7..575fd462 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dpr @@ -819,6 +819,7 @@ uses Asn1IntegerTests in '..\src\Asn1\Asn1IntegerTests.pas', Asn1GeneratorTests in '..\src\Asn1\Asn1GeneratorTests.pas', Asn1SequenceParserTests in '..\src\Asn1\Asn1SequenceParserTests.pas', + Asn1SequenceCursorTests in '..\src\Asn1\Asn1SequenceCursorTests.pas', Asn1TimeFormatTests in '..\src\Asn1\Asn1TimeFormatTests.pas', BitStringTests in '..\src\Asn1\BitStringTests.pas', DerUtf8StringTests in '..\src\Asn1\DerUtf8StringTests.pas', @@ -864,6 +865,7 @@ uses CtrDrbgTests in '..\src\Rngs\Drbg\CtrDrbgTests.pas', //FixedPointTests in '..\src\Math\EC\FixedPointTests.pas', AESTests in '..\src\Crypto\AESTests.pas', + BlockCipherTestBase in '..\src\Crypto\BlockCipherTestBase.pas', AesBlockCipherTestBase in '..\src\Crypto\AesBlockCipherTestBase.pas', AesLightTests in '..\src\Crypto\AesLightTests.pas', FusedExternalRegistrationTests in '..\src\Crypto\FusedExternalRegistrationTests.pas', diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj index 0993ce34..f0c8319e 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.Mobile.dproj @@ -1162,6 +1162,7 @@ + @@ -1203,6 +1204,7 @@ + diff --git a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr index 9080b797..261747d0 100644 --- a/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr +++ b/CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr @@ -838,6 +838,7 @@ uses Asn1IntegerTests in '..\src\Asn1\Asn1IntegerTests.pas', Asn1GeneratorTests in '..\src\Asn1\Asn1GeneratorTests.pas', Asn1SequenceParserTests in '..\src\Asn1\Asn1SequenceParserTests.pas', + Asn1SequenceCursorTests in '..\src\Asn1\Asn1SequenceCursorTests.pas', Asn1TimeFormatTests in '..\src\Asn1\Asn1TimeFormatTests.pas', BitStringTests in '..\src\Asn1\BitStringTests.pas', DerUtf8StringTests in '..\src\Asn1\DerUtf8StringTests.pas', @@ -883,6 +884,7 @@ uses DigestRandomNumberTests in '..\src\Crypto\DigestRandomNumberTests.pas', FixedPointTests in '..\src\Math\EC\FixedPointTests.pas', AESTests in '..\src\Crypto\AESTests.pas', + BlockCipherTestBase in '..\src\Crypto\BlockCipherTestBase.pas', AesBlockCipherTestBase in '..\src\Crypto\AesBlockCipherTestBase.pas', AesLightTests in '..\src\Crypto\AesLightTests.pas', FusedExternalRegistrationTests in '..\src\Crypto\FusedExternalRegistrationTests.pas', diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi index aebb8170..4ec355e6 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.Tests.lpi @@ -79,7 +79,7 @@ - + @@ -837,6 +837,14 @@ + + + + + + + + diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr index 19438c72..cf4d0936 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLib.lpr @@ -4,6 +4,7 @@ uses Interfaces, Forms, GuiTestRunner, Asn1GeneratorTests, Asn1SequenceParserTests, + Asn1SequenceCursorTests, Asn1TimeFormatTests, EqualsAndHashCodeTests, OIDTests, EnumeratedTests, ExternalTests, ParsingTests, ParseTests, StringTests, TagTests, BigIntegerTests, ECAlgorithmsTests, ECPointTests, BinPolyTests, @@ -12,7 +13,8 @@ DigestRandomNumberTests, FixedPointTests, AESTests, AesLightTests, FusedExternalRegistrationTests, AesHardwareEngineTests, AESSICTests, SicBulkParityTests, EcbBulkParityTests, CbcBulkParityTests, - GcmSivBulkParityTests, SpeckBlockCipherTestBase, SpeckLegacyTests, SpeckTests, + GcmSivBulkParityTests, BlockCipherTestBase, SpeckBlockCipherTestBase, + SpeckLegacyTests, SpeckTests, IESCipherTests, HMacTests, Pkcs5Tests, HkdfGeneratorTests, ECIESTests, PascalCoinECIESTests, ECNRTests, PrimesTests, ECEncodingTests, GF256AesTests, PaddingTests, DSATests, DeterministicDsaTests, Salsa20Tests, XSalsa20Tests, diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi index d2d1e7eb..ce438b02 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpi @@ -39,7 +39,7 @@ - + @@ -796,6 +796,14 @@ + + + + + + + + diff --git a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr index f4dc5434..059fb17a 100644 --- a/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr +++ b/CryptoLib.Tests/FreePascal.Tests/CryptoLibConsole.lpr @@ -5,6 +5,7 @@ uses {$IFDEF UNIX}cwstring,{$ENDIF} consoletestrunner, Asn1GeneratorTests, Asn1SequenceParserTests, + Asn1SequenceCursorTests, Asn1TimeFormatTests, EqualsAndHashCodeTests, OIDTests, EnumeratedTests, ExternalTests, ParsingTests, ParseTests, StringTests, TagTests, BigIntegerTests, ECAlgorithmsTests, ECPointTests, BinPolyTests, @@ -13,7 +14,8 @@ DigestRandomNumberTests, FixedPointTests, AESTests, AesLightTests, FusedExternalRegistrationTests, AesHardwareEngineTests, AESSICTests, SicBulkParityTests, EcbBulkParityTests, CbcBulkParityTests, - GcmSivBulkParityTests, SpeckBlockCipherTestBase, SpeckLegacyTests, SpeckTests, + GcmSivBulkParityTests, BlockCipherTestBase, SpeckBlockCipherTestBase, + SpeckLegacyTests, SpeckTests, IESCipherTests, HMacTests, Pkcs5Tests, HkdfGeneratorTests, ECIESTests, PascalCoinECIESTests, ECNRTests, PrimesTests, ECEncodingTests, GF256AesTests, PaddingTests, DSATests, DeterministicDsaTests, Salsa20Tests, XSalsa20Tests, diff --git a/CryptoLib.Tests/src/Asn1/Asn1SequenceCursorTests.pas b/CryptoLib.Tests/src/Asn1/Asn1SequenceCursorTests.pas new file mode 100644 index 00000000..82957d28 --- /dev/null +++ b/CryptoLib.Tests/src/Asn1/Asn1SequenceCursorTests.pas @@ -0,0 +1,232 @@ +{ *********************************************************************************** } +{ * CryptoLib Library * } +{ * Author - Ugochukwu Mmaduekwe * } +{ * Github Repository * } +{ * * } +{ * Distributed under the MIT software license, see the accompanying file LICENSE * } +{ * or visit http://www.opensource.org/licenses/mit-license.php. * } +{ * * } +{ * Acknowledgements: * } +{ * * } +{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } +{ * the development of this library * } +{ * ******************************************************************************* * } + +(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) + +unit Asn1SequenceCursorTests; + +interface + +{$IFDEF FPC} +{$MODE DELPHI} +{$ENDIF FPC} + +uses + Classes, + SysUtils, +{$IFDEF FPC} + fpcunit, + testregistry, +{$ELSE} + TestFramework, +{$ENDIF FPC} + ClpAsn1Objects, + ClpIAsn1Objects, + ClpIAsn1Core, + ClpAsn1Utilities, + ClpCryptoLibTypes, + CryptoLibTestBase; + +type + + /// + /// Direct edge-case tests for the TAsn1Utilities sequence cursor helpers + /// (Read / ReadOptional / ReadContextTagged / CheckSequenceSize / RequireEndOfSequence). + /// + TTestAsn1SequenceCursor = class(TCryptoLibAlgorithmTestCase) + private + function IntSeq(const AValues: array of Int32): IAsn1Sequence; + published + procedure TestReadMandatoryAndRequireEnd; + procedure TestCheckSequenceSizeRejectsWrongSize; + procedure TestCheckSequenceSizeRejectsNil; + procedure TestReadRejectsPrematureEnd; + procedure TestRequireEndRejectsTrailing; + procedure TestReadEncodableReturnsRawElement; + procedure TestReadOptionalPresentAdvances; + procedure TestReadOptionalAbsentDoesNotAdvance; + procedure TestReadContextTaggedExplicit; + end; + +implementation + +function TTestAsn1SequenceCursor.IntSeq(const AValues: array of Int32): IAsn1Sequence; +var + LElements: TCryptoLibGenericArray; + LI: Int32; +begin + LElements := nil; + System.SetLength(LElements, System.Length(AValues)); + for LI := 0 to System.Length(AValues) - 1 do + LElements[LI] := TDerInteger.ValueOf(AValues[LI]); + Result := TDerSequence.FromElements(LElements); +end; + +procedure TTestAsn1SequenceCursor.TestReadMandatoryAndRequireEnd; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LA, LB: IDerInteger; +begin + LSeq := IntSeq([7, 11]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(LSeq, 2, 2); + LA := TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + LB := TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(LSeq, LPos); + CheckTrue(LA.HasValue(7), 'first element'); + CheckTrue(LB.HasValue(11), 'second element'); + CheckEquals(2, LPos, 'position after two reads'); +end; + +procedure TTestAsn1SequenceCursor.TestCheckSequenceSizeRejectsWrongSize; +var + LRaised: Boolean; +begin + LRaised := False; + try + TAsn1Utilities.CheckSequenceSize(IntSeq([1, 2, 3]), 2, 2); + except + on E: EArgumentCryptoLibException do + LRaised := True; + end; + CheckTrue(LRaised, 'expected bad-sequence-size exception'); +end; + +procedure TTestAsn1SequenceCursor.TestCheckSequenceSizeRejectsNil; +var + LSeq: IAsn1Sequence; + LRaised: Boolean; +begin + LSeq := nil; + LRaised := False; + try + TAsn1Utilities.CheckSequenceSize(LSeq, 0, 3); + except + on E: EArgumentNilCryptoLibException do + LRaised := True; + end; + CheckTrue(LRaised, 'expected nil-sequence exception'); +end; + +procedure TTestAsn1SequenceCursor.TestReadRejectsPrematureEnd; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LRaised: Boolean; +begin + LSeq := IntSeq([1]); + LPos := 0; + TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + LRaised := False; + try + TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + except + on E: EArgumentCryptoLibException do + LRaised := True; + end; + CheckTrue(LRaised, 'expected premature-end exception'); +end; + +procedure TTestAsn1SequenceCursor.TestRequireEndRejectsTrailing; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LRaised: Boolean; +begin + LSeq := IntSeq([1, 2]); + LPos := 0; + TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + LRaised := False; + try + TAsn1Utilities.RequireEndOfSequence(LSeq, LPos); + except + on E: EArgumentCryptoLibException do + LRaised := True; + end; + CheckTrue(LRaised, 'expected unexpected-elements exception'); +end; + +procedure TTestAsn1SequenceCursor.TestReadEncodableReturnsRawElement; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LElement: IAsn1Encodable; +begin + LSeq := IntSeq([42]); + LPos := 0; + LElement := TAsn1Utilities.ReadEncodable(LSeq, LPos); + CheckNotNull(LElement, 'raw element'); + CheckEquals(1, LPos, 'position advanced'); + CheckTrue(TDerInteger.GetInstance(LElement).HasValue(42), 'element value'); +end; + +procedure TTestAsn1SequenceCursor.TestReadOptionalPresentAdvances; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LValue: IDerInteger; +begin + LSeq := IntSeq([9]); + LPos := 0; + LValue := TAsn1Utilities.ReadOptional(LSeq, LPos, TDerInteger.GetOptional); + CheckNotNull(LValue, 'optional present'); + CheckTrue(LValue.HasValue(9), 'optional value'); + CheckEquals(1, LPos, 'position advanced'); +end; + +procedure TTestAsn1SequenceCursor.TestReadOptionalAbsentDoesNotAdvance; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LBits: IDerBitString; + LInt: IDerInteger; +begin + // sequence holds a DerInteger; an optional DerBitString read must not consume it + LSeq := IntSeq([5]); + LPos := 0; + LBits := TAsn1Utilities.ReadOptional(LSeq, LPos, TDerBitString.GetOptional); + CheckNull(LBits, 'optional absent'); + CheckEquals(0, LPos, 'position not advanced'); + LInt := TAsn1Utilities.Read(LSeq, LPos, TDerInteger.GetInstance); + CheckTrue(LInt.HasValue(5), 'element still readable'); + CheckEquals(1, LPos, 'position advanced after mandatory read'); +end; + +procedure TTestAsn1SequenceCursor.TestReadContextTaggedExplicit; +var + LSeq: IAsn1Sequence; + LPos: Int32; + LValue: IDerInteger; +begin + LSeq := TDerSequence.FromElement(TDerTaggedObject.Create(True, 0, TDerInteger.ValueOf(5)) as IDerTaggedObject); + LPos := 0; + LValue := TAsn1Utilities.ReadContextTagged(LSeq, LPos, 0, True, TDerInteger.GetTagged); + TAsn1Utilities.RequireEndOfSequence(LSeq, LPos); + CheckNotNull(LValue, 'context-tagged value'); + CheckTrue(LValue.HasValue(5), 'context-tagged value content'); + CheckEquals(1, LPos, 'position advanced'); +end; + +initialization + +// Register any test cases with the test runner + +{$IFDEF FPC} + RegisterTest(TTestAsn1SequenceCursor); +{$ELSE} + RegisterTest(TTestAsn1SequenceCursor.Suite); +{$ENDIF FPC} + +end. diff --git a/CryptoLib.Tests/src/Asn1/Asn1StreamReadTests.pas b/CryptoLib.Tests/src/Asn1/Asn1StreamReadTests.pas index b1a961b9..483feae6 100644 --- a/CryptoLib.Tests/src/Asn1/Asn1StreamReadTests.pas +++ b/CryptoLib.Tests/src/Asn1/Asn1StreamReadTests.pas @@ -282,7 +282,7 @@ function TAsn1StreamReadTest.BuildBerIndefiniteConstructedBitString procedure TAsn1StreamReadTest.TestConstructedOctetReadAllRoundTrip; var - LPayload, LEncoding, LActual: TCryptoLibByteArray; + LPayload, LEncoding: TCryptoLibByteArray; LParser: IAsn1StreamParser; LOctets: IBerOctetString; LI: Int32; diff --git a/CryptoLib.Tests/src/Crypto/AESTests.pas b/CryptoLib.Tests/src/Crypto/AESTests.pas index af58be07..5378d03a 100644 --- a/CryptoLib.Tests/src/Crypto/AESTests.pas +++ b/CryptoLib.Tests/src/Crypto/AESTests.pas @@ -57,6 +57,7 @@ interface FixedSecureRandom, ClpCryptoLibTypes, CryptoLibTestBase, + BlockCipherTestBase, AesBlockCipherTestBase, SymmetricBlockVectors; @@ -107,11 +108,10 @@ TTestAES = class(TAesBlockCipherTestBase) protected procedure SetUp; override; procedure TearDown; override; + function GetEngineFactory: TBlockCipherFactory; override; + function EngineLabel: String; override; published - procedure TestBlockCipherVector; - procedure TestMonteCarloAES; - procedure TestBadParameters; procedure TestOids; procedure TestCiphers; procedure TestAES_CBC_PKCS7PADDING_WITH_IV; @@ -449,19 +449,14 @@ procedure TTestAES.TearDown; inherited; end; -procedure TTestAES.TestBlockCipherVector; +function TTestAES.GetEngineFactory: TBlockCipherFactory; begin - RunBlockCipherVectorTests(@CreateAesEngine, 'TAesEngine'); + Result := @CreateAesEngine; end; -procedure TTestAES.TestMonteCarloAES; +function TTestAES.EngineLabel: String; begin - RunBlockCipherMonteCarloTests(@CreateAesEngine, 'TAesEngine'); -end; - -procedure TTestAES.TestBadParameters; -begin - AssertEngineRejectsBadParameters(@CreateAesEngine, 'TAesEngine'); + Result := 'TAesEngine'; end; procedure TTestAES.TestCiphers; diff --git a/CryptoLib.Tests/src/Crypto/AesBlockCipherTestBase.pas b/CryptoLib.Tests/src/Crypto/AesBlockCipherTestBase.pas index 30c43618..392b199d 100644 --- a/CryptoLib.Tests/src/Crypto/AesBlockCipherTestBase.pas +++ b/CryptoLib.Tests/src/Crypto/AesBlockCipherTestBase.pas @@ -34,16 +34,14 @@ interface ClpIKeyParameter, ClpKeyParameter, ClpICipherParameters, - ClpIParametersWithIV, - ClpParametersWithIV, ClpIBufferedBlockCipher, ClpBufferedBlockCipher, ClpCryptoLibTypes, - CryptoLibTestBase; + CryptoLibTestBase, + BlockCipherTestBase; type - - TAesBlockCipherTestBase = class abstract(TCryptoLibAlgorithmTestCase) + TAesBlockCipherTestBase = class abstract(TBlockCipherTestBase) strict private class var FBlockCipherVectorKeys, FBlockCipherVectorInputs, @@ -53,26 +51,23 @@ TAesBlockCipherTestBase = class abstract(TCryptoLibAlgorithmTestCase) class constructor CreateBlockCipherTestData; - procedure DoBlockCipherVectorTest(const AEngine: IBlockCipher; - const AParam: ICipherParameters; const AInput, AOutput: String; - const APreface: String = ''); - procedure DoBlockCipherMonteCarloTest(const AIteration: String; const AEngine: IBlockCipher; const AParam: ICipherParameters; const AInput, AOutput: String; const APreface: String = ''); strict protected - procedure RunBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); + // engine hooks supplied by the concrete suite + function GetEngineFactory: TBlockCipherFactory; virtual; abstract; + function EngineLabel: String; virtual; abstract; + // default: always run; hardware suites override with a real capability check + function EngineSupported: Boolean; virtual; procedure RunBlockCipherMonteCarloTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); - - procedure AssertEngineRejectsBadParameters(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); - - procedure RunCipherEngineChecks(const AEngine: IBlockCipher; - const AValidKey: IKeyParameter; const AContext: String); + : TBlockCipherFactory; const AEngineLabel: String); + published + procedure TestBlockCipherVector; + procedure TestMonteCarloAES; + procedure TestBadParameters; end; implementation @@ -147,53 +142,6 @@ implementation 'E58B82BFBA53C0040DC610C642121168'); end; -procedure TAesBlockCipherTestBase.DoBlockCipherVectorTest(const AEngine: IBlockCipher; - const AParam: ICipherParameters; const AInput, AOutput: String; - const APreface: String); -var - LCipher: IBufferedBlockCipher; - LLen1, LLen2: Int32; - LInput, LOutput, LOutBytes: TBytes; - LPrefix: String; -begin - LInput := DecodeHex(AInput); - LOutput := DecodeHex(AOutput); - - if APreface <> '' then - LPrefix := '[' + APreface + '] ' - else - LPrefix := ''; - - LCipher := TBufferedBlockCipher.Create(AEngine); - - LCipher.Init(True, AParam); - - System.SetLength(LOutBytes, System.Length(LInput)); - - LLen1 := LCipher.ProcessBytes(LInput, 0, System.Length(LInput), LOutBytes, 0); - - LCipher.DoFinal(LOutBytes, LLen1); - - if (not AreEqual(LOutBytes, LOutput)) then - begin - Fail(LPrefix + Format('Encryption Failed - Expected %s but got %s', - [EncodeHex(LOutput), EncodeHex(LOutBytes)])); - end; - - LCipher.Init(False, AParam); - - LLen2 := LCipher.ProcessBytes(LOutput, 0, System.Length(LOutput), - LOutBytes, 0); - - LCipher.DoFinal(LOutBytes, LLen2); - - if (not AreEqual(LInput, LOutBytes)) then - begin - Fail(LPrefix + Format('Decryption Failed - Expected %s but got %s', - [EncodeHex(LInput), EncodeHex(LOutBytes)])); - end; -end; - procedure TAesBlockCipherTestBase.DoBlockCipherMonteCarloTest(const AIteration: String; const AEngine: IBlockCipher; const AParam: ICipherParameters; const AInput, AOutput: String; const APreface: String); @@ -256,25 +204,35 @@ procedure TAesBlockCipherTestBase.DoBlockCipherMonteCarloTest(const AIteration: end; end; -procedure TAesBlockCipherTestBase.RunBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); -var - LI: Int32; - LPreface: String; +function TAesBlockCipherTestBase.EngineSupported: Boolean; begin - for LI := System.Low(FBlockCipherVectorKeys) - to System.High(FBlockCipherVectorKeys) do - begin - LPreface := Format('%s block vector index %d', [AEngineLabel, LI]); - DoBlockCipherVectorTest(ACreateEngine(), - TKeyParameter.Create(DecodeHex(FBlockCipherVectorKeys[LI])) - as IKeyParameter, FBlockCipherVectorInputs[LI], - FBlockCipherVectorOutputs[LI], LPreface); - end; + Result := True; +end; + +procedure TAesBlockCipherTestBase.TestBlockCipherVector; +begin + if not EngineSupported then + Exit; + RunBlockCipherVectorTests(GetEngineFactory(), EngineLabel, + FBlockCipherVectorKeys, FBlockCipherVectorInputs, FBlockCipherVectorOutputs); +end; + +procedure TAesBlockCipherTestBase.TestMonteCarloAES; +begin + if not EngineSupported then + Exit; + RunBlockCipherMonteCarloTests(GetEngineFactory(), EngineLabel); +end; + +procedure TAesBlockCipherTestBase.TestBadParameters; +begin + if not EngineSupported then + Exit; + AssertEngineRejectsBadParameters(GetEngineFactory(), EngineLabel); end; procedure TAesBlockCipherTestBase.RunBlockCipherMonteCarloTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); + : TBlockCipherFactory; const AEngineLabel: String); var LI: Int32; LPreface: String; @@ -291,102 +249,4 @@ procedure TAesBlockCipherTestBase.RunBlockCipherMonteCarloTests(const ACreateEng end; end; -procedure TAesBlockCipherTestBase.AssertEngineRejectsBadParameters(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String); -var - LDudKey, LIV: TBytes; - LEngine: IBlockCipher; -begin - LEngine := ACreateEngine(); - - try - System.SetLength(LDudKey, 6); - LEngine.Init(True, TKeyParameter.Create(LDudKey) as IKeyParameter); - Fail(Format('[%s] failed key length check', [AEngineLabel])); - except - on e: EArgumentCryptoLibException do - begin - // expected - end; - end; - - LEngine := ACreateEngine(); - - try - System.SetLength(LIV, 16); - LEngine.Init(True, TParametersWithIV.Create(nil, LIV) as IParametersWithIV); - Fail(Format('[%s] failed parameter check', [AEngineLabel])); - except - on e: EArgumentCryptoLibException do - begin - // expected - end; - end; -end; - -procedure TAesBlockCipherTestBase.RunCipherEngineChecks(const AEngine: IBlockCipher; - const AValidKey: IKeyParameter; const AContext: String); -var - LCorrectBuf, LShortBuf: TBytes; - LBlockSize: Int32; -begin - LBlockSize := AEngine.GetBlockSize(); - System.SetLength(LCorrectBuf, LBlockSize); - System.SetLength(LShortBuf, LBlockSize div 2); - - try - AEngine.ProcessBlock(LCorrectBuf, 0, LCorrectBuf, 0); - Fail(Format('[%s] failed initialisation check', [AContext])); - except - on E: EInvalidOperationCryptoLibException do - begin - // expected - end; - end; - - AEngine.Init(True, AValidKey as ICipherParameters); - - try - AEngine.ProcessBlock(LShortBuf, 0, LCorrectBuf, 0); - Fail(Format('[%s] failed short input check (encrypt)', [AContext])); - except - on E: EDataLengthCryptoLibException do - begin - // expected (includes EOutputLengthCryptoLibException) - end; - end; - - try - AEngine.ProcessBlock(LCorrectBuf, 0, LShortBuf, 0); - Fail(Format('[%s] failed short output check (encrypt)', [AContext])); - except - on E: EDataLengthCryptoLibException do - begin - // expected - end; - end; - - AEngine.Init(False, AValidKey as ICipherParameters); - - try - AEngine.ProcessBlock(LShortBuf, 0, LCorrectBuf, 0); - Fail(Format('[%s] failed short input check (decrypt)', [AContext])); - except - on E: EDataLengthCryptoLibException do - begin - // expected - end; - end; - - try - AEngine.ProcessBlock(LCorrectBuf, 0, LShortBuf, 0); - Fail(Format('[%s] failed short output check (decrypt)', [AContext])); - except - on E: EDataLengthCryptoLibException do - begin - // expected - end; - end; -end; - end. diff --git a/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas b/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas index 5930f3c4..f2a0b90e 100644 --- a/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas +++ b/CryptoLib.Tests/src/Crypto/AesHardwareEngineTests.pas @@ -37,10 +37,10 @@ interface {$IFDEF CRYPTOLIB_X86_SIMD} ClpAesEngineX86, {$ENDIF CRYPTOLIB_X86_SIMD} + BlockCipherTestBase, AesBlockCipherTestBase; type - TEngineFactory = function: IBlockCipher; /// /// Engine-agnostic test suite for hardware-accelerated AES engines. All the /// vector / Monte-Carlo / engine-check coverage plus the SIMD batch (4-/8-wide) @@ -53,10 +53,9 @@ interface TAesHardwareEngineTestBase = class abstract(TAesBlockCipherTestBase) strict protected // ---- architecture hooks (implemented by the concrete per-arch suite) ---- + // GetEngineFactory / EngineLabel / EngineSupported are inherited from + // TAesBlockCipherTestBase; only CreateHwEngine is hardware-specific. function CreateHwEngine: IAesHardwareEngine; virtual; abstract; - function EngineSupported: Boolean; virtual; abstract; - function EngineLabel: String; virtual; abstract; - function GetEngineFactory: TEngineFactory; virtual; abstract; // ---- shared SIMD test logic ---- procedure ImplTestFourBlocks(AForEncryption: Boolean; AKeySizeBytes: Int32); @@ -66,8 +65,8 @@ TAesHardwareEngineTestBase = class abstract(TAesBlockCipherTestBase) procedure ImplTestProcessFourBlocksMemoryLayouts(AKeySizeBytes: Int32); procedure ImplTestProcessEightBlocksMemoryLayouts(AKeySizeBytes: Int32); published - procedure TestBlockCipherVectors; - procedure TestMonteCarloAES; + // TestBlockCipherVector / TestMonteCarloAES / TestBadParameters are + // inherited from TAesBlockCipherTestBase (guarded by EngineSupported). procedure TestEngineChecks128; procedure TestEngineChecks192; procedure TestEngineChecks256; @@ -108,7 +107,7 @@ TTestAesX86 = class(TAesHardwareEngineTestBase) function CreateHwEngine: IAesHardwareEngine; override; function EngineSupported: Boolean; override; function EngineLabel: String; override; - function GetEngineFactory: TEngineFactory; override; + function GetEngineFactory: TBlockCipherFactory; override; end; {$ENDIF CRYPTOLIB_X86_SIMD} @@ -540,20 +539,6 @@ procedure TAesHardwareEngineTestBase.ImplTestProcessEightBlocksMemoryLayouts(AKe end; end; -procedure TAesHardwareEngineTestBase.TestBlockCipherVectors; -begin - if not EngineSupported then - Exit; - RunBlockCipherVectorTests(GetEngineFactory(), EngineLabel); -end; - -procedure TAesHardwareEngineTestBase.TestMonteCarloAES; -begin - if not EngineSupported then - Exit; - RunBlockCipherMonteCarloTests(GetEngineFactory(), EngineLabel); -end; - procedure TAesHardwareEngineTestBase.TestEngineChecks128; var LKey: TBytes; @@ -788,7 +773,7 @@ function TTestAesX86.EngineLabel: String; Result := 'TAesEngineX86'; end; -function TTestAesX86.GetEngineFactory: TEngineFactory; +function TTestAesX86.GetEngineFactory: TBlockCipherFactory; begin Result := @CreateAesX86Engine; end; diff --git a/CryptoLib.Tests/src/Crypto/AesLightTests.pas b/CryptoLib.Tests/src/Crypto/AesLightTests.pas index 070d3db1..477e2415 100644 --- a/CryptoLib.Tests/src/Crypto/AesLightTests.pas +++ b/CryptoLib.Tests/src/Crypto/AesLightTests.pas @@ -31,15 +31,15 @@ interface {$ENDIF FPC} ClpAesLightEngine, ClpIBlockCipher, + BlockCipherTestBase, AesBlockCipherTestBase; type TTestAesLight = class(TAesBlockCipherTestBase) - published - procedure TestBlockCipherVector; - procedure TestMonteCarloAES; - procedure TestBadParameters; + strict protected + function GetEngineFactory: TBlockCipherFactory; override; + function EngineLabel: String; override; end; implementation @@ -51,19 +51,14 @@ function CreateAesLightEngine: IBlockCipher; { TTestAesLight } -procedure TTestAesLight.TestBlockCipherVector; +function TTestAesLight.GetEngineFactory: TBlockCipherFactory; begin - RunBlockCipherVectorTests(@CreateAesLightEngine, 'TAesLightEngine'); + Result := @CreateAesLightEngine; end; -procedure TTestAesLight.TestMonteCarloAES; +function TTestAesLight.EngineLabel: String; begin - RunBlockCipherMonteCarloTests(@CreateAesLightEngine, 'TAesLightEngine'); -end; - -procedure TTestAesLight.TestBadParameters; -begin - AssertEngineRejectsBadParameters(@CreateAesLightEngine, 'TAesLightEngine'); + Result := 'TAesLightEngine'; end; initialization diff --git a/CryptoLib.Tests/src/Crypto/BlockCipherTestBase.pas b/CryptoLib.Tests/src/Crypto/BlockCipherTestBase.pas new file mode 100644 index 00000000..03aabd4b --- /dev/null +++ b/CryptoLib.Tests/src/Crypto/BlockCipherTestBase.pas @@ -0,0 +1,231 @@ +{ *********************************************************************************** } +{ * CryptoLib Library * } +{ * Author - Ugochukwu Mmaduekwe * } +{ * Github Repository * } +{ * * } +{ * Distributed under the MIT software license, see the accompanying file LICENSE * } +{ * or visit http://www.opensource.org/licenses/mit-license.php. * } +{ * * } +{ * Acknowledgements: * } +{ * * } +{ * Thanks to Sphere 10 Software (http://www.sphere10.com/) for sponsoring * } +{ * the development of this library * } +{ * ******************************************************************************* * } + +(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *) + +unit BlockCipherTestBase; + +interface + +{$IFDEF FPC} +{$MODE DELPHI} +{$ENDIF FPC} + +uses + SysUtils, + ClpIBlockCipher, + ClpICipherParameters, + ClpIKeyParameter, + ClpKeyParameter, + ClpIParametersWithIV, + ClpParametersWithIV, + ClpIBufferedBlockCipher, + ClpBufferedBlockCipher, + ClpCryptoLibTypes, + CryptoLibTestBase; + +type + // shared factory shape for every block-cipher test suite + TBlockCipherFactory = function: IBlockCipher; + + /// + /// Common scaffolding for block-cipher known-answer test suites: a single + /// encrypt/decrypt round-trip primitive and a data-driven runner over + /// parallel key/input/output vectors. Family-specific bases (AES, Speck) + /// inherit from this. + /// + TBlockCipherTestBase = class abstract(TCryptoLibAlgorithmTestCase) + strict protected + procedure DoBlockCipherVectorTest(const AEngine: IBlockCipher; + const AParam: ICipherParameters; const AInput, AOutput: String; + const APreface: String = ''); + + procedure RunBlockCipherVectorTests(const ACreateEngine: TBlockCipherFactory; + const AEngineLabel: String; + const AKeys, AInputs, AOutputs: TCryptoLibStringArray); + + // engine-agnostic IBlockCipher contract checks + procedure AssertEngineRejectsBadParameters(const ACreateEngine + : TBlockCipherFactory; const AEngineLabel: String); + + procedure RunCipherEngineChecks(const AEngine: IBlockCipher; + const AValidKey: IKeyParameter; const AContext: String); + end; + +implementation + +{ TBlockCipherTestBase } + +procedure TBlockCipherTestBase.DoBlockCipherVectorTest(const AEngine: IBlockCipher; + const AParam: ICipherParameters; const AInput, AOutput: String; + const APreface: String); +var + LCipher: IBufferedBlockCipher; + LLen1, LLen2: Int32; + LInput, LOutput, LOutBytes: TBytes; + LPrefix: String; +begin + LInput := DecodeHex(AInput); + LOutput := DecodeHex(AOutput); + + if APreface <> '' then + LPrefix := '[' + APreface + '] ' + else + LPrefix := ''; + + LCipher := TBufferedBlockCipher.Create(AEngine); + + LCipher.Init(True, AParam); + + System.SetLength(LOutBytes, System.Length(LInput)); + + LLen1 := LCipher.ProcessBytes(LInput, 0, System.Length(LInput), LOutBytes, 0); + + LCipher.DoFinal(LOutBytes, LLen1); + + if (not AreEqual(LOutBytes, LOutput)) then + begin + Fail(LPrefix + Format('Encryption Failed - Expected %s but got %s', + [EncodeHex(LOutput), EncodeHex(LOutBytes)])); + end; + + LCipher.Init(False, AParam); + + LLen2 := LCipher.ProcessBytes(LOutput, 0, System.Length(LOutput), + LOutBytes, 0); + + LCipher.DoFinal(LOutBytes, LLen2); + + if (not AreEqual(LInput, LOutBytes)) then + begin + Fail(LPrefix + Format('Decryption Failed - Expected %s but got %s', + [EncodeHex(LInput), EncodeHex(LOutBytes)])); + end; +end; + +procedure TBlockCipherTestBase.RunBlockCipherVectorTests(const ACreateEngine + : TBlockCipherFactory; const AEngineLabel: String; + const AKeys, AInputs, AOutputs: TCryptoLibStringArray); +var + LI: Int32; + LPreface: String; +begin + for LI := System.Low(AKeys) to System.High(AKeys) do + begin + LPreface := Format('%s block vector index %d', [AEngineLabel, LI]); + DoBlockCipherVectorTest(ACreateEngine(), + TKeyParameter.Create(DecodeHex(AKeys[LI])) as IKeyParameter, + AInputs[LI], AOutputs[LI], LPreface); + end; +end; + +procedure TBlockCipherTestBase.AssertEngineRejectsBadParameters(const ACreateEngine + : TBlockCipherFactory; const AEngineLabel: String); +var + LDudKey, LIV: TBytes; + LEngine: IBlockCipher; +begin + LEngine := ACreateEngine(); + + try + System.SetLength(LDudKey, 6); + LEngine.Init(True, TKeyParameter.Create(LDudKey) as IKeyParameter); + Fail(Format('[%s] failed key length check', [AEngineLabel])); + except + on e: EArgumentCryptoLibException do + begin + // expected + end; + end; + + LEngine := ACreateEngine(); + + try + System.SetLength(LIV, 16); + LEngine.Init(True, TParametersWithIV.Create(nil, LIV) as IParametersWithIV); + Fail(Format('[%s] failed parameter check', [AEngineLabel])); + except + on e: EArgumentCryptoLibException do + begin + // expected + end; + end; +end; + +procedure TBlockCipherTestBase.RunCipherEngineChecks(const AEngine: IBlockCipher; + const AValidKey: IKeyParameter; const AContext: String); +var + LCorrectBuf, LShortBuf: TBytes; + LBlockSize: Int32; +begin + LBlockSize := AEngine.GetBlockSize(); + System.SetLength(LCorrectBuf, LBlockSize); + System.SetLength(LShortBuf, LBlockSize div 2); + + try + AEngine.ProcessBlock(LCorrectBuf, 0, LCorrectBuf, 0); + Fail(Format('[%s] failed initialisation check', [AContext])); + except + on E: EInvalidOperationCryptoLibException do + begin + // expected + end; + end; + + AEngine.Init(True, AValidKey as ICipherParameters); + + try + AEngine.ProcessBlock(LShortBuf, 0, LCorrectBuf, 0); + Fail(Format('[%s] failed short input check (encrypt)', [AContext])); + except + on E: EDataLengthCryptoLibException do + begin + // expected (includes EOutputLengthCryptoLibException) + end; + end; + + try + AEngine.ProcessBlock(LCorrectBuf, 0, LShortBuf, 0); + Fail(Format('[%s] failed short output check (encrypt)', [AContext])); + except + on E: EDataLengthCryptoLibException do + begin + // expected + end; + end; + + AEngine.Init(False, AValidKey as ICipherParameters); + + try + AEngine.ProcessBlock(LShortBuf, 0, LCorrectBuf, 0); + Fail(Format('[%s] failed short input check (decrypt)', [AContext])); + except + on E: EDataLengthCryptoLibException do + begin + // expected + end; + end; + + try + AEngine.ProcessBlock(LCorrectBuf, 0, LShortBuf, 0); + Fail(Format('[%s] failed short output check (decrypt)', [AContext])); + except + on E: EDataLengthCryptoLibException do + begin + // expected + end; + end; +end; + +end. diff --git a/CryptoLib.Tests/src/Crypto/CbcBulkParityTests.pas b/CryptoLib.Tests/src/Crypto/CbcBulkParityTests.pas index 92ea1768..d3a075ae 100644 --- a/CryptoLib.Tests/src/Crypto/CbcBulkParityTests.pas +++ b/CryptoLib.Tests/src/Crypto/CbcBulkParityTests.pas @@ -44,7 +44,8 @@ interface ClpSecureRandom, ClpISecureRandom, ClpCryptoLibTypes, - CryptoLibTestBase; + CryptoLibTestBase, + BlockCipherTestBase; type /// @@ -61,10 +62,7 @@ interface /// TTestCbcBulkParity = class(TCryptoLibAlgorithmTestCase) strict private - type - TEngineFactory = function: IBlockCipher; - - procedure RunParityForEngine(AEngineFactory: TEngineFactory; + procedure RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, ABlockSize: Int32; const ALabel: String); published {$IFDEF CRYPTOLIB_X86_SIMD} @@ -95,7 +93,7 @@ function CreateBlowfishEngine: IBlockCipher; { TTestCbcBulkParity } -procedure TTestCbcBulkParity.RunParityForEngine(AEngineFactory: TEngineFactory; +procedure TTestCbcBulkParity.RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, ABlockSize: Int32; const ALabel: String); const BlockCounts: array [0 .. 15] of Int32 = (1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 15, diff --git a/CryptoLib.Tests/src/Crypto/EcbBulkParityTests.pas b/CryptoLib.Tests/src/Crypto/EcbBulkParityTests.pas index 16068669..b94ec8c6 100644 --- a/CryptoLib.Tests/src/Crypto/EcbBulkParityTests.pas +++ b/CryptoLib.Tests/src/Crypto/EcbBulkParityTests.pas @@ -43,7 +43,8 @@ interface ClpSecureRandom, ClpISecureRandom, ClpCryptoLibTypes, - CryptoLibTestBase; + CryptoLibTestBase, + BlockCipherTestBase; type /// @@ -57,10 +58,7 @@ interface /// TTestEcbBulkParity = class(TCryptoLibAlgorithmTestCase) strict private - type - TEngineFactory = function: IBlockCipher; - - procedure RunParityForEngine(AEngineFactory: TEngineFactory; + procedure RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, ABlockSize: Int32; const ALabel: String); published {$IFDEF CRYPTOLIB_X86_SIMD} @@ -91,7 +89,7 @@ function CreateBlowfishEngine: IBlockCipher; { TTestEcbBulkParity } -procedure TTestEcbBulkParity.RunParityForEngine(AEngineFactory: TEngineFactory; +procedure TTestEcbBulkParity.RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, ABlockSize: Int32; const ALabel: String); const BlockCounts: array [0 .. 15] of Int32 = (1, 2, 3, 4, 5, 7, 8, 9, 11, 12, 15, diff --git a/CryptoLib.Tests/src/Crypto/SicBulkParityTests.pas b/CryptoLib.Tests/src/Crypto/SicBulkParityTests.pas index d24d64cf..dea329c8 100644 --- a/CryptoLib.Tests/src/Crypto/SicBulkParityTests.pas +++ b/CryptoLib.Tests/src/Crypto/SicBulkParityTests.pas @@ -44,7 +44,8 @@ interface ClpSecureRandom, ClpISecureRandom, ClpCryptoLibTypes, - CryptoLibTestBase; + CryptoLibTestBase, + BlockCipherTestBase; type /// @@ -59,10 +60,7 @@ interface /// TTestSicBulkParity = class(TCryptoLibAlgorithmTestCase) strict private - type - TEngineFactory = function: IBlockCipher; - - procedure RunParityForEngine(AEngineFactory: TEngineFactory; + procedure RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, AIvLen, ABlockSize: Int32; const ALabel: String); published {$IFDEF CRYPTOLIB_X86_SIMD} @@ -97,7 +95,7 @@ function CreateBlowfishEngine: IBlockCipher; { TTestSicBulkParity } -procedure TTestSicBulkParity.RunParityForEngine(AEngineFactory: TEngineFactory; +procedure TTestSicBulkParity.RunParityForEngine(AEngineFactory: TBlockCipherFactory; AKeyLen, AIvLen, ABlockSize: Int32; const ALabel: String); const // Chosen to stress every branch of the bulk dispatch: diff --git a/CryptoLib.Tests/src/Crypto/SpeckBlockCipherTestBase.pas b/CryptoLib.Tests/src/Crypto/SpeckBlockCipherTestBase.pas index a4c08a35..be096482 100644 --- a/CryptoLib.Tests/src/Crypto/SpeckBlockCipherTestBase.pas +++ b/CryptoLib.Tests/src/Crypto/SpeckBlockCipherTestBase.pas @@ -38,35 +38,22 @@ interface ClpSicBlockCipher, ClpISicBlockCipher, ClpSpeckEngine, - ClpISpeckEngine, - ClpISpeckLegacyEngine, ClpCryptoLibTypes, CryptoLibTestBase, + BlockCipherTestBase, SymmetricBlockVectors; type - TSpeckBlockCipherTestBase = class abstract(TCryptoLibAlgorithmTestCase) + TSpeckBlockCipherTestBase = class abstract(TBlockCipherTestBase) strict private - procedure DoBlockCipherVectorTest(const AEngine: IBlockCipher; - const AParam: ICipherParameters; const AInput, AOutput: String; - const APreface: String = ''); - procedure DoSPECKTest(const ACipher: IBufferedCipher; const AParam: ICipherParameters; const AInput, AOutput: String; AWithPadding: Boolean = False); strict protected - procedure RunSpeckBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String; - const AKeys, AInputs, AOutputs: TCryptoLibStringArray); - - procedure RunSpeckLegacyBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String; - const AKeys, AInputs, AOutputs: TCryptoLibStringArray); - procedure RunCryptoPPSpeckModeTests(const AMode: string; AWithIV: Boolean; - ACreateEngine: TCryptoLibFunc); + ACreateEngine: TBlockCipherFactory); procedure RunCryptoPPSpeck64EcbTests; procedure RunCryptoPPSpeck128EcbTests; @@ -78,66 +65,18 @@ TSpeckBlockCipherTestBase = class abstract(TCryptoLibAlgorithmTestCase) implementation -function CreateSpeck64EngineForCryptoPP: ISpeckEngine; +function CreateSpeck64EngineForCryptoPP: IBlockCipher; begin Result := TSpeck64Engine.Create(); end; -function CreateSpeck128EngineForCryptoPP: ISpeckEngine; +function CreateSpeck128EngineForCryptoPP: IBlockCipher; begin Result := TSpeck128Engine.Create(); end; { TSpeckBlockCipherTestBase } -procedure TSpeckBlockCipherTestBase.DoBlockCipherVectorTest(const AEngine: IBlockCipher; - const AParam: ICipherParameters; const AInput, AOutput: String; - const APreface: String); -var - LCipher: IBufferedBlockCipher; - LLen1, LLen2: Int32; - LInput, LOutput, LOutBytes: TBytes; - LPrefix: String; -begin - LInput := DecodeHex(AInput); - LOutput := DecodeHex(AOutput); - - if APreface <> '' then - LPrefix := '[' + APreface + '] ' - else - LPrefix := ''; - - LCipher := TBufferedBlockCipher.Create(AEngine); - - LCipher.Init(True, AParam); - - System.SetLength(LOutBytes, System.Length(LInput)); - - LLen1 := LCipher.ProcessBytes(LInput, 0, System.Length(LInput), - LOutBytes, 0); - - LCipher.DoFinal(LOutBytes, LLen1); - - if (not AreEqual(LOutBytes, LOutput)) then - begin - Fail(LPrefix + Format('Encryption Failed - Expected %s but got %s', - [EncodeHex(LOutput), EncodeHex(LOutBytes)])); - end; - - LCipher.Init(False, AParam); - - LLen2 := LCipher.ProcessBytes(LOutput, 0, System.Length(LOutput), - LOutBytes, 0); - - LCipher.DoFinal(LOutBytes, LLen2); - - if (not AreEqual(LInput, LOutBytes)) then - begin - Fail(LPrefix + Format('Decryption Failed - Expected %s but got %s', - [EncodeHex(LInput), EncodeHex(LOutBytes)])); - end; -end; - procedure TSpeckBlockCipherTestBase.DoSPECKTest(const ACipher: IBufferedCipher; const AParam: ICipherParameters; const AInput, AOutput: String; AWithPadding: Boolean); @@ -171,40 +110,8 @@ procedure TSpeckBlockCipherTestBase.DoSPECKTest(const ACipher: IBufferedCipher; end; end; -procedure TSpeckBlockCipherTestBase.RunSpeckBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String; - const AKeys, AInputs, AOutputs: TCryptoLibStringArray); -var - LI: Int32; - LPreface: String; -begin - for LI := System.Low(AKeys) to System.High(AKeys) do - begin - LPreface := Format('%s block vector index %d', [AEngineLabel, LI]); - DoBlockCipherVectorTest(ACreateEngine(), - TKeyParameter.Create(DecodeHex(AKeys[LI])) as IKeyParameter, - AInputs[LI], AOutputs[LI], LPreface); - end; -end; - -procedure TSpeckBlockCipherTestBase.RunSpeckLegacyBlockCipherVectorTests(const ACreateEngine - : TCryptoLibFunc; const AEngineLabel: String; - const AKeys, AInputs, AOutputs: TCryptoLibStringArray); -var - LI: Int32; - LPreface: String; -begin - for LI := System.Low(AKeys) to System.High(AKeys) do - begin - LPreface := Format('%s block vector index %d', [AEngineLabel, LI]); - DoBlockCipherVectorTest(ACreateEngine(), - TKeyParameter.Create(DecodeHex(AKeys[LI])) as IKeyParameter, - AInputs[LI], AOutputs[LI], LPreface); - end; -end; - procedure TSpeckBlockCipherTestBase.RunCryptoPPSpeckModeTests(const AMode: string; - AWithIV: Boolean; ACreateEngine: TCryptoLibFunc); + AWithIV: Boolean; ACreateEngine: TBlockCipherFactory); var LRows: TCryptoLibGenericArray; LKeyParametersWithIV: IParametersWithIV; @@ -212,7 +119,7 @@ procedure TSpeckBlockCipherTestBase.RunCryptoPPSpeckModeTests(const AMode: strin LKeyBytes, LIVBytes: TBytes; LCipher: IBufferedCipher; LI: Int32; - LEngine: ISpeckEngine; + LEngine: IBlockCipher; LBlockCipher: IBlockCipher; LCbcBlockCipher: ICbcBlockCipher; LSicBlockCipher: ISicBlockCipher; diff --git a/CryptoLib.Tests/src/Crypto/SpeckLegacyTests.pas b/CryptoLib.Tests/src/Crypto/SpeckLegacyTests.pas index 0d7c8c57..818ee668 100644 --- a/CryptoLib.Tests/src/Crypto/SpeckLegacyTests.pas +++ b/CryptoLib.Tests/src/Crypto/SpeckLegacyTests.pas @@ -30,7 +30,7 @@ interface TestFramework, {$ENDIF FPC} ClpSpeckLegacyEngine, - ClpISpeckLegacyEngine, + ClpIBlockCipher, ClpCryptoLibTypes, SpeckBlockCipherTestBase; @@ -74,27 +74,27 @@ TTestSpeckLegacy = class(TSpeckBlockCipherTestBase) implementation -function CreateSpeck32LegacyEngine: ISpeckLegacyEngine; +function CreateSpeck32LegacyEngine: IBlockCipher; begin Result := TSpeck32LegacyEngine.Create(); end; -function CreateSpeck48LegacyEngine: ISpeckLegacyEngine; +function CreateSpeck48LegacyEngine: IBlockCipher; begin Result := TSpeck48LegacyEngine.Create(); end; -function CreateSpeck64LegacyEngine: ISpeckLegacyEngine; +function CreateSpeck64LegacyEngine: IBlockCipher; begin Result := TSpeck64LegacyEngine.Create(); end; -function CreateSpeck96LegacyEngine: ISpeckLegacyEngine; +function CreateSpeck96LegacyEngine: IBlockCipher; begin Result := TSpeck96LegacyEngine.Create(); end; -function CreateSpeck128LegacyEngine: ISpeckLegacyEngine; +function CreateSpeck128LegacyEngine: IBlockCipher; begin Result := TSpeck128LegacyEngine.Create(); end; @@ -165,7 +165,7 @@ procedure TTestSpeckLegacy.TearDown; procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck32; begin - RunSpeckLegacyBlockCipherVectorTests(@CreateSpeck32LegacyEngine, + RunBlockCipherVectorTests(@CreateSpeck32LegacyEngine, 'TSpeck32LegacyEngine', FSpeck32LegacyBlockCipherVectorKeys, FSpeck32LegacyBlockCipherVectorInputs, FSpeck32LegacyBlockCipherVectorOutputs); @@ -173,7 +173,7 @@ procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck32; procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck48; begin - RunSpeckLegacyBlockCipherVectorTests(@CreateSpeck48LegacyEngine, + RunBlockCipherVectorTests(@CreateSpeck48LegacyEngine, 'TSpeck48LegacyEngine', FSpeck48LegacyBlockCipherVectorKeys, FSpeck48LegacyBlockCipherVectorInputs, FSpeck48LegacyBlockCipherVectorOutputs); @@ -181,7 +181,7 @@ procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck48; procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck64; begin - RunSpeckLegacyBlockCipherVectorTests(@CreateSpeck64LegacyEngine, + RunBlockCipherVectorTests(@CreateSpeck64LegacyEngine, 'TSpeck64LegacyEngine', FSpeck64LegacyBlockCipherVectorKeys, FSpeck64LegacyBlockCipherVectorInputs, FSpeck64LegacyBlockCipherVectorOutputs); @@ -189,7 +189,7 @@ procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck64; procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck96; begin - RunSpeckLegacyBlockCipherVectorTests(@CreateSpeck96LegacyEngine, + RunBlockCipherVectorTests(@CreateSpeck96LegacyEngine, 'TSpeck96LegacyEngine', FSpeck96LegacyBlockCipherVectorKeys, FSpeck96LegacyBlockCipherVectorInputs, FSpeck96LegacyBlockCipherVectorOutputs); @@ -197,7 +197,7 @@ procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck96; procedure TTestSpeckLegacy.TestBlockCipherVectorSpeck128; begin - RunSpeckLegacyBlockCipherVectorTests(@CreateSpeck128LegacyEngine, + RunBlockCipherVectorTests(@CreateSpeck128LegacyEngine, 'TSpeck128LegacyEngine', FSpeck128LegacyBlockCipherVectorKeys, FSpeck128LegacyBlockCipherVectorInputs, FSpeck128LegacyBlockCipherVectorOutputs); diff --git a/CryptoLib.Tests/src/Crypto/SpeckTests.pas b/CryptoLib.Tests/src/Crypto/SpeckTests.pas index c4b88215..7650b5ac 100644 --- a/CryptoLib.Tests/src/Crypto/SpeckTests.pas +++ b/CryptoLib.Tests/src/Crypto/SpeckTests.pas @@ -30,7 +30,7 @@ interface TestFramework, {$ENDIF FPC} ClpSpeckEngine, - ClpISpeckEngine, + ClpIBlockCipher, ClpCryptoLibTypes, SpeckBlockCipherTestBase; @@ -75,27 +75,27 @@ TTestSpeck = class(TSpeckBlockCipherTestBase) implementation -function CreateSpeck32Engine: ISpeckEngine; +function CreateSpeck32Engine: IBlockCipher; begin Result := TSpeck32Engine.Create(); end; -function CreateSpeck48Engine: ISpeckEngine; +function CreateSpeck48Engine: IBlockCipher; begin Result := TSpeck48Engine.Create(); end; -function CreateSpeck64Engine: ISpeckEngine; +function CreateSpeck64Engine: IBlockCipher; begin Result := TSpeck64Engine.Create(); end; -function CreateSpeck96Engine: ISpeckEngine; +function CreateSpeck96Engine: IBlockCipher; begin Result := TSpeck96Engine.Create(); end; -function CreateSpeck128Engine: ISpeckEngine; +function CreateSpeck128Engine: IBlockCipher; begin Result := TSpeck128Engine.Create(); end; @@ -164,35 +164,35 @@ procedure TTestSpeck.TearDown; procedure TTestSpeck.TestBlockCipherVectorSpeck32; begin - RunSpeckBlockCipherVectorTests(@CreateSpeck32Engine, 'TSpeck32Engine', + RunBlockCipherVectorTests(@CreateSpeck32Engine, 'TSpeck32Engine', FSpeck32BlockCipherVectorKeys, FSpeck32BlockCipherVectorInputs, FSpeck32BlockCipherVectorOutputs); end; procedure TTestSpeck.TestBlockCipherVectorSpeck48; begin - RunSpeckBlockCipherVectorTests(@CreateSpeck48Engine, 'TSpeck48Engine', + RunBlockCipherVectorTests(@CreateSpeck48Engine, 'TSpeck48Engine', FSpeck48BlockCipherVectorKeys, FSpeck48BlockCipherVectorInputs, FSpeck48BlockCipherVectorOutputs); end; procedure TTestSpeck.TestBlockCipherVectorSpeck64; begin - RunSpeckBlockCipherVectorTests(@CreateSpeck64Engine, 'TSpeck64Engine', + RunBlockCipherVectorTests(@CreateSpeck64Engine, 'TSpeck64Engine', FSpeck64BlockCipherVectorKeys, FSpeck64BlockCipherVectorInputs, FSpeck64BlockCipherVectorOutputs); end; procedure TTestSpeck.TestBlockCipherVectorSpeck96; begin - RunSpeckBlockCipherVectorTests(@CreateSpeck96Engine, 'TSpeck96Engine', + RunBlockCipherVectorTests(@CreateSpeck96Engine, 'TSpeck96Engine', FSpeck96BlockCipherVectorKeys, FSpeck96BlockCipherVectorInputs, FSpeck96BlockCipherVectorOutputs); end; procedure TTestSpeck.TestBlockCipherVectorSpeck128; begin - RunSpeckBlockCipherVectorTests(@CreateSpeck128Engine, 'TSpeck128Engine', + RunBlockCipherVectorTests(@CreateSpeck128Engine, 'TSpeck128Engine', FSpeck128BlockCipherVectorKeys, FSpeck128BlockCipherVectorInputs, FSpeck128BlockCipherVectorOutputs); end; diff --git a/CryptoLib/src/Asn1/ClpAsn1Utilities.pas b/CryptoLib/src/Asn1/ClpAsn1Utilities.pas index 996d1996..8cb231c2 100644 --- a/CryptoLib/src/Asn1/ClpAsn1Utilities.pas +++ b/CryptoLib/src/Asn1/ClpAsn1Utilities.pas @@ -36,8 +36,17 @@ interface SExpectedTagButFound = 'expected %s tag but found %s'; SFailedToConstructFromByte = 'failed to construct %s from byte array: %s'; SInvalidObject = 'invalid object: %s'; + SSequenceNil = 'sequence cannot be nil'; + SBadSequenceSize = 'bad sequence size: %d'; + SPrematureEndOfSequence = 'premature end of sequence'; + SUnexpectedElementsInSequence = 'unexpected elements in sequence'; type + // sequence-cursor constructor callbacks + TAsn1Constructor = function(const AElement: TInput): TResult; + TAsn1TaggedConstructor = function(const ATagged: IAsn1TaggedObject; + ADeclaredExplicit: Boolean): TResult; + /// /// Utility class for ASN.1 operations. /// @@ -81,6 +90,15 @@ TAsn1Utilities = class sealed(TObject) class function GetTaggedChoice(const ATaggedObject: IAsn1TaggedObject; ADeclaredExplicit: Boolean; const AConstructor: TCryptoLibFunc): TChoice; static; + // Cursor callback: [n] EXPLICIT base object + class function GetTaggedExplicitBaseObject(const ATaggedObject: IAsn1TaggedObject; + ADeclaredExplicit: Boolean): IAsn1Encodable; static; + // Cursor callback: the tagged object itself + class function GetTaggedObjectIdentity(const ATaggedObject: IAsn1TaggedObject; + ADeclaredExplicit: Boolean): IAsn1TaggedObject; static; + // Cursor callback: the element itself (optional ANY reads) + class function GetEncodableIdentity(const AElement: IAsn1Encodable): IAsn1Encodable; static; + // Explicit base object methods class function GetExplicitBaseObject(const ATaggedObject: IAsn1TaggedObject; ATagClass: Int32): IAsn1Encodable; overload; static; @@ -201,28 +219,35 @@ TAsn1Utilities = class sealed(TObject) class function TryParseExplicitContextBaseObject(const ATaggedObjectParser: IAsn1TaggedObjectParser; ATagNo: Int32; out ABaseObject: IAsn1Convertible): Boolean; overload; static; - // Sequence cursor methods - class function ReadContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; static; - class function ReadTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; static; - class function ReadOptional(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; - const AConstructor: TCryptoLibFunc): TResult; static; - class function ReadOptionalContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; static; - class function ReadOptionalTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; static; - class function TryReadOptionalContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; out AResult: TResult; - const AConstructor: TCryptoLibFunc): Boolean; static; - class function TryReadOptionalTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; out AResult: TResult; - const AConstructor: TCryptoLibFunc): Boolean; static; + // Sequence cursor methods (sequence + position) + class procedure CheckSequenceSize(const ASequence: IAsn1Sequence; + AMinCount, AMaxCount: Int32); static; + class procedure RequireEndOfSequence(const ASequence: IAsn1Sequence; + ASequencePosition: Int32); static; + class function ReadEncodable(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32): IAsn1Encodable; static; + class function Read(const ASequence: IAsn1Sequence; var ASequencePosition: Int32; + const AConstructor: TAsn1Constructor): TResult; static; + class function ReadOptional(const ASequence: IAsn1Sequence; var ASequencePosition: Int32; + const AConstructor: TAsn1Constructor): TResult; static; + class function ReadTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; static; + class function ReadContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; static; + class function ReadOptionalContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; static; + class function ReadOptionalTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; static; + class function TryReadOptionalContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; out AResult: TResult; + const AConstructor: TAsn1TaggedConstructor): Boolean; static; + class function TryReadOptionalTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; out AResult: TResult; + const AConstructor: TAsn1TaggedConstructor): Boolean; static; end; implementation @@ -489,6 +514,23 @@ class function TAsn1Utilities.GetTaggedChoice(const ATaggedObject: IAsn Result := AConstructor(ATaggedObject.GetExplicitBaseObject()); end; +class function TAsn1Utilities.GetTaggedExplicitBaseObject(const ATaggedObject: IAsn1TaggedObject; + ADeclaredExplicit: Boolean): IAsn1Encodable; +begin + Result := ATaggedObject.GetExplicitBaseObject(); +end; + +class function TAsn1Utilities.GetTaggedObjectIdentity(const ATaggedObject: IAsn1TaggedObject; + ADeclaredExplicit: Boolean): IAsn1TaggedObject; +begin + Result := ATaggedObject; +end; + +class function TAsn1Utilities.GetEncodableIdentity(const AElement: IAsn1Encodable): IAsn1Encodable; +begin + Result := AElement; +end; + // Explicit base object methods class function TAsn1Utilities.GetExplicitBaseObject(const ATaggedObject: IAsn1TaggedObject; @@ -865,46 +907,48 @@ class function TAsn1Utilities.TryParseExplicitContextBaseObject(const ATaggedObj // Sequence cursor methods -class function TAsn1Utilities.ReadContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; +class procedure TAsn1Utilities.CheckSequenceSize(const ASequence: IAsn1Sequence; + AMinCount, AMaxCount: Int32); begin - Result := ReadTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, ATagNo, AState, AConstructor); + if ASequence = nil then + raise EArgumentNilCryptoLibException.CreateRes(@SSequenceNil); + if (ASequence.Count < AMinCount) or (ASequence.Count > AMaxCount) then + raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [ASequence.Count]); end; -class function TAsn1Utilities.ReadTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; -var - LTagged: IAsn1TaggedObject; - LElement: IAsn1Encodable; - LObj: IAsn1Object; +class procedure TAsn1Utilities.RequireEndOfSequence(const ASequence: IAsn1Sequence; + ASequencePosition: Int32); begin - // TODO: We might want to check the position and throw a better exception, but current ASN.1 types aren't - // doing that, so leave it until it can be consistent. - LElement := ASequence.Items[ASequencePosition]; + if ASequencePosition <> ASequence.Count then + raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); +end; + +class function TAsn1Utilities.ReadEncodable(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32): IAsn1Encodable; +begin + if ASequencePosition < 0 then + raise EArgumentOutOfRangeCryptoLibException.CreateRes(@SPrematureEndOfSequence); + if ASequencePosition >= ASequence.Count then + raise EArgumentCryptoLibException.CreateRes(@SPrematureEndOfSequence); + Result := ASequence.Items[ASequencePosition]; System.Inc(ASequencePosition); - if LElement = nil then - raise EArgumentNilCryptoLibException.CreateRes(@SElementNil); - LObj := LElement.ToAsn1Object(); - LTagged := TAsn1TaggedObject.GetInstance(LObj, ATagClass, ATagNo); - Result := AConstructor(LTagged, AState); end; -class function TAsn1Utilities.ReadOptional(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; - const AConstructor: TCryptoLibFunc): TResult; +class function TAsn1Utilities.Read(const ASequence: IAsn1Sequence; var ASequencePosition: Int32; + const AConstructor: TAsn1Constructor): TResult; +begin + Result := AConstructor(ReadEncodable(ASequence, ASequencePosition)); +end; + +class function TAsn1Utilities.ReadOptional(const ASequence: IAsn1Sequence; var ASequencePosition: Int32; + const AConstructor: TAsn1Constructor): TResult; var LResult: TResult; - LResultPtr: Pointer; begin if ASequencePosition < ASequence.Count then begin LResult := AConstructor(ASequence.Items[ASequencePosition]); - // Check if result is not nil (for reference types) - // Since we know TResult will always be a reference type, we check the pointer value - LResultPtr := PPointer(@LResult)^; - if LResultPtr <> nil then + if PPointer(@LResult)^ <> nil then begin System.Inc(ASequencePosition); Result := LResult; @@ -914,49 +958,72 @@ class function TAsn1Utilities.ReadOptional(const ASequence: IAsn1Sequen Result := Default(TResult); end; -class function TAsn1Utilities.ReadOptionalContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; +class function TAsn1Utilities.ReadTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; +var + LTagged: IAsn1TaggedObject; begin - Result := ReadOptionalTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, ATagNo, AState, AConstructor); + LTagged := TAsn1TaggedObject.GetInstance(ReadEncodable(ASequence, ASequencePosition).ToAsn1Object(), + ATagClass, ATagNo); + Result := AConstructor(LTagged, ADeclaredExplicit); end; -class function TAsn1Utilities.ReadOptionalTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; - const AConstructor: TCryptoLibFunc): TResult; +class function TAsn1Utilities.ReadContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; +begin + Result := ReadTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, ATagNo, + ADeclaredExplicit, AConstructor); +end; + +class function TAsn1Utilities.TryReadOptionalTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; out AResult: TResult; + const AConstructor: TAsn1TaggedConstructor): Boolean; var - LResult: TResult; + LTagged: IAsn1TaggedObject; begin - if (ASequencePosition < ASequence.Count) and - (TryGetOptionalTagged(ASequence.Items[ASequencePosition], ATagClass, ATagNo, AState, LResult, AConstructor)) then + if ASequencePosition < ASequence.Count then begin - System.Inc(ASequencePosition); - Result := LResult; - Exit; + LTagged := TAsn1TaggedObject.GetOptional(ASequence.Items[ASequencePosition], ATagClass, ATagNo); + if LTagged <> nil then + begin + AResult := AConstructor(LTagged, ADeclaredExplicit); + System.Inc(ASequencePosition); + Result := True; + Exit; + end; end; - Result := Default(TResult); + AResult := Default(TResult); + Result := False; end; -class function TAsn1Utilities.TryReadOptionalContextTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; const AState: TState; out AResult: TResult; - const AConstructor: TCryptoLibFunc): Boolean; +class function TAsn1Utilities.TryReadOptionalContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; out AResult: TResult; + const AConstructor: TAsn1TaggedConstructor): Boolean; begin - Result := TryReadOptionalTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, ATagNo, AState, AResult, AConstructor); + Result := TryReadOptionalTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, + ATagNo, ADeclaredExplicit, AResult, AConstructor); end; -class function TAsn1Utilities.TryReadOptionalTagged(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagClass, ATagNo: Int32; const AState: TState; out AResult: TResult; - const AConstructor: TCryptoLibFunc): Boolean; +class function TAsn1Utilities.ReadOptionalTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagClass, ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; +var + LFound: Boolean; begin - if (ASequencePosition < ASequence.Count) and - (TryGetOptionalTagged(ASequence.Items[ASequencePosition], ATagClass, ATagNo, AState, AResult, AConstructor)) then - begin - System.Inc(ASequencePosition); - Result := True; - Exit; - end; - AResult := Default(TResult); - Result := False; + LFound := TryReadOptionalTagged(ASequence, ASequencePosition, ATagClass, ATagNo, ADeclaredExplicit, + Result, AConstructor); + if not LFound then + Result := Default(TResult); +end; + +class function TAsn1Utilities.ReadOptionalContextTagged(const ASequence: IAsn1Sequence; + var ASequencePosition: Int32; ATagNo: Int32; ADeclaredExplicit: Boolean; + const AConstructor: TAsn1TaggedConstructor): TResult; +begin + Result := ReadOptionalTagged(ASequence, ASequencePosition, TAsn1Tags.ContextSpecific, + ATagNo, ADeclaredExplicit, AConstructor); end; end. diff --git a/CryptoLib/src/Asn1/Cms/ClpCmsAsn1Objects.pas b/CryptoLib/src/Asn1/Cms/ClpCmsAsn1Objects.pas index 24a5828c..51a14377 100644 --- a/CryptoLib/src/Asn1/Cms/ClpCmsAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Cms/ClpCmsAsn1Objects.pas @@ -37,8 +37,6 @@ interface ClpCryptoLibTypes; resourcestring - SCmsBadSequenceSize = 'bad sequence size: %d'; - SCmsUnexpectedElementsInSequence = 'unexpected elements in sequence'; SCmsContentTypeNil = 'CMS content type cannot be nil'; SCmsAsn1ElementNil = 'ASN.1 encodable element cannot be nil'; SCmsIssuerNil = 'CMS issuer name cannot be nil'; @@ -118,6 +116,7 @@ TCmsContentInfo = class(TAsn1Encodable, ICmsContentInfo) class function GetInstance(const AEncoded: TCryptoLibByteArray): ICmsContentInfo; overload; static; class function GetInstance(const AObj: IAsn1TaggedObject; AExplicitly: Boolean): ICmsContentInfo; overload; static; + class function GetOptional(const AElement: IAsn1Encodable): ICmsContentInfo; static; class function GetTagged(const ATaggedObject: IAsn1TaggedObject; ADeclaredExplicit: Boolean): ICmsContentInfo; static; @@ -144,7 +143,6 @@ TCcmParameters = class(TAsn1Encodable, ICcmParameters) FNonce: IAsn1OctetString; FIcvLen: Int32; - class function ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; static; class function ValidateIcvLen(AIcvLen: Int32): Int32; static; strict protected @@ -181,7 +179,6 @@ TGcmParameters = class(TAsn1Encodable, IGcmParameters) FNonce: IAsn1OctetString; FIcvLen: Int32; - class function ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; static; class function ValidateIcvLen(AIcvLen: Int32): Int32; static; strict protected @@ -285,8 +282,6 @@ TCmsSignerInfo = class(TAsn1Encodable, ICmsSignerInfo) FSignature: IAsn1OctetString; FUnsignedAttrs: IAsn1Set; - class function GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; static; - strict protected function GetVersion: IDerInteger; function GetSignerID: ICmsSignerIdentifier; @@ -339,8 +334,8 @@ TCmsSignedData = class(TAsn1Encodable, ICmsSignedData) FSigsBer: Boolean; strict private - class function ReadOptionalTaggedSet(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; out AIsBer: Boolean): IAsn1Set; static; + class procedure ReadOptionalTaggedSet(const ASeq: IAsn1Sequence; var APos: Int32; + ATagNo: Int32; out ASet: IAsn1Set; out AIsBer: Boolean); static; class function CalculateVersionField(const AContentOid: IDerObjectIdentifier; const ACerts, ACrls, ASignerInfs: IAsn1Set): IDerInteger; static; class function HasV3SignerInfos(const ASignerInfs: IAsn1Set): Boolean; static; @@ -565,26 +560,34 @@ function TCmsContentInfo.IsDLContent(const AContent: IAsn1Encodable): Boolean; Result := IsDLOctetString(LObj) or IsDLSequenceObj(LObj); end; -constructor TCmsContentInfo.Create(const ASeq: IAsn1Sequence); +class function TCmsContentInfo.GetOptional(const AElement: IAsn1Encodable): ICmsContentInfo; var - LCount: Int32; - LTagged: IAsn1TaggedObject; + LSeq: IAsn1Sequence; begin - Inherited Create(); - LCount := ASeq.Count; - if (LCount < 1) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); - - FContentType := TDerObjectIdentifier.GetInstance(ASeq[0]); - - if ASeq.Count > 1 then + if AElement = nil then + raise EArgumentNilCryptoLibException.CreateRes(@SCmsAsn1ElementNil); + if Supports(AElement, ICmsContentInfo, Result) then + Exit; + LSeq := TAsn1Sequence.GetOptional(AElement); + if LSeq <> nil then begin - LTagged := TAsn1TaggedObject.GetContextInstance(ASeq[1], 0); - FContent := LTagged.GetExplicitBaseObject(); - end - else - FContent := nil; + Result := TCmsContentInfo.Create(LSeq); + Exit; + end; + Result := nil; +end; +constructor TCmsContentInfo.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; +begin + Inherited Create(); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FContentType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FContent := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAsn1Utilities.GetTaggedExplicitBaseObject); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FIsDefiniteLength := IsDLSequence(ASeq); end; @@ -689,14 +692,14 @@ class function TCmsIssuerAndSerialNumber.GetTagged(const ATaggedObject: IAsn1Tag constructor TCmsIssuerAndSerialNumber.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin Inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); - FIssuer := TX509Name.GetInstance(ASeq[0]); - FSerialNumber := TDerInteger.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FIssuer := TAsn1Utilities.Read(ASeq, LPos, TX509Name.GetInstance); + FSerialNumber := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TCmsIssuerAndSerialNumber.Create(const AIssuer: IX509Name; const ASerialNumber: IDerInteger); @@ -873,34 +876,19 @@ class function TCmsSignerInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TCmsSignerInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin Inherited Create(); - LCount := ASeq.Count; - if (LCount < 5) or (LCount > 7) then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); LPos := 0; - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSignerID := TCmsSignerIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FDigestAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSignedAttrs := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedAsn1Set); - FSignatureAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSignature := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FUnsignedAttrs := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedAsn1Set); - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SCmsUnexpectedElementsInSequence); -end; - -class function TCmsSignerInfo.GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; -begin - Result := TAsn1Set.GetTagged(ATagged, AState); + TAsn1Utilities.CheckSequenceSize(ASeq, 5, 7); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FSignerID := TAsn1Utilities.Read(ASeq, LPos, TCmsSignerIdentifier.GetInstance); + FDigestAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSignedAttrs := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, TAsn1Set.GetTagged); + FSignatureAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSignature := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FUnsignedAttrs := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, TAsn1Set.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TCmsSignerInfo.Create(const ASignerID: ICmsSignerIdentifier; @@ -979,24 +967,24 @@ function TCmsSignerInfo.ToAsn1Object: IAsn1Object; { TCmsSignedData } -class function TCmsSignedData.ReadOptionalTaggedSet(const ASequence: IAsn1Sequence; - var ASequencePosition: Int32; ATagNo: Int32; out AIsBer: Boolean): IAsn1Set; +class procedure TCmsSignedData.ReadOptionalTaggedSet(const ASeq: IAsn1Sequence; var APos: Int32; + ATagNo: Int32; out ASet: IAsn1Set; out AIsBer: Boolean); var - LElement: IAsn1Encodable; LTagged: IAsn1TaggedObject; + LFound: Boolean; begin - Result := nil; - AIsBer := False; - if ASequencePosition >= ASequence.Count then - Exit; - LElement := ASequence.Items[ASequencePosition]; - if not Supports(LElement, IAsn1TaggedObject, LTagged) then - Exit; - if not LTagged.HasContextTag(ATagNo) then - Exit; - Result := TAsn1Set.GetTagged(LTagged, False); - AIsBer := Supports(LElement, IBerTaggedObject); - System.Inc(ASequencePosition); + LFound := TAsn1Utilities.TryReadOptionalContextTagged(ASeq, APos, ATagNo, False, + LTagged, TAsn1Utilities.GetTaggedObjectIdentity); + if LFound then + begin + ASet := TAsn1Set.GetTagged(LTagged, False); + AIsBer := Supports(LTagged, IBerTaggedObject); + end + else + begin + ASet := nil; + AIsBer := False; + end; end; class function TCmsSignedData.CalculateVersionField(const AContentOid: IDerObjectIdentifier; @@ -1162,27 +1150,18 @@ class function TCmsSignedData.FromContentInfo(const AInfo: ICmsContentInfo): ICm constructor TCmsSignedData.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin Inherited Create(); - LCount := ASeq.Count; - if (LCount < 4) or (LCount > 6) then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); - LPos := 0; - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FDigestAlgorithms := TAsn1Set.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FEncapContentInfo := TCmsContentInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FCertificates := ReadOptionalTaggedSet(ASeq, LPos, 0, FCertsBer); - FCrls := ReadOptionalTaggedSet(ASeq, LPos, 1, FCrlsBer); - FSignerInfos := TAsn1Set.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SCmsUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 4, 6); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FDigestAlgorithms := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + FEncapContentInfo := TAsn1Utilities.Read(ASeq, LPos, TCmsContentInfo.GetInstance); + ReadOptionalTaggedSet(ASeq, LPos, 0, FCertificates, FCertsBer); + ReadOptionalTaggedSet(ASeq, LPos, 1, FCrls, FCrlsBer); + FSignerInfos := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FDigsBer := Supports(FDigestAlgorithms, IBerSet); FSigsBer := Supports(FSignerInfos, IBerSet); @@ -1276,11 +1255,6 @@ function TCmsSignedData.ToAsn1Object: IAsn1Object; { TCcmParameters } -class function TCcmParameters.ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AEnc); -end; - class function TCcmParameters.ValidateIcvLen(AIcvLen: Int32): Int32; begin if (AIcvLen < 4) or (AIcvLen > 16) or ((AIcvLen and 1) <> 0) then @@ -1326,20 +1300,15 @@ class function TCcmParameters.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TCcmParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LIcvLen: IDerInteger; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 1) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); - - FNonce := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - LIcvLen := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SCmsUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FNonce := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + LIcvLen := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); if LIcvLen = nil then FIcvLen := ValidateIcvLen(DefaultIcvLen) @@ -1375,11 +1344,6 @@ function TCcmParameters.ToAsn1Object: IAsn1Object; { TGcmParameters } -class function TGcmParameters.ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AEnc); -end; - class function TGcmParameters.ValidateIcvLen(AIcvLen: Int32): Int32; begin if (AIcvLen < 12) or (AIcvLen > 16) then @@ -1425,20 +1389,15 @@ class function TGcmParameters.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TGcmParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LIcvLen: IDerInteger; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 1) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSequenceSize, [LCount]); - - FNonce := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - LIcvLen := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SCmsUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FNonce := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + LIcvLen := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); if LIcvLen = nil then FIcvLen := ValidateIcvLen(DefaultIcvLen) diff --git a/CryptoLib/src/Asn1/Cms/ClpCmsECAsn1Objects.pas b/CryptoLib/src/Asn1/Cms/ClpCmsECAsn1Objects.pas index 232a79a6..74f7e006 100644 --- a/CryptoLib/src/Asn1/Cms/ClpCmsECAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Cms/ClpCmsECAsn1Objects.pas @@ -50,7 +50,6 @@ TEccCmsSharedInfo = class(TAsn1Encodable, IEccCmsSharedInfo) FEntityUInfo: IAsn1OctetString; FSuppPubInfo: IAsn1OctetString; - class function GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; static; strict protected function GetKeyInfo: IAlgorithmIdentifier; @@ -129,32 +128,19 @@ class function TEccCmsSharedInfo.GetTagged(const ATaggedObject: IAsn1TaggedObjec Result := TEccCmsSharedInfo.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TEccCmsSharedInfo.GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; -begin - Result := TAsn1OctetString.GetTagged(ATagged, AState); -end; - constructor TEccCmsSharedInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SEccCmsBadSequenceSize, [LCount]); - - FKeyInfo := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FEntityUInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedAsn1OctetString); - - FSuppPubInfo := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 2, True, - GetTaggedAsn1OctetString); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SEccCmsUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FKeyInfo := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FEntityUInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAsn1OctetString.GetTagged); + FSuppPubInfo := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 2, True, + TAsn1OctetString.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TEccCmsSharedInfo.Create(const AKeyInfo: IAlgorithmIdentifier; const ASuppPubInfo: IAsn1OctetString); diff --git a/CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas b/CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas index fac761f4..79bb2f27 100644 --- a/CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Pkcs/ClpPkcsAsn1Objects.pas @@ -40,7 +40,6 @@ interface resourcestring SAttrTypeNil = 'attribute type cannot be nil'; SAttrValuesNil = 'attribute values cannot be nil'; - SWrongNumberOfElements = 'wrong number of elements in sequence'; SRequestInfoNil = 'request info cannot be nil'; SAlgorithmNil = 'algorithm identifier cannot be nil'; SSignatureNil = 'signature cannot be nil'; @@ -122,8 +121,6 @@ TPkcsSignedData = class(TAsn1Encodable, IPkcsSignedData) FCrls: IAsn1Set; FSignerInfos: IAsn1Set; - class function GetTaggedAsn1SetFromSeq(ATagged: IAsn1TaggedObject; AState: IAsn1Sequence): IAsn1Set; static; - strict protected function GetVersion: IDerInteger; function GetDigestAlgorithms: IAsn1Set; @@ -203,8 +200,6 @@ TCertificationRequestInfo = class(TAsn1Encodable, ICertificationRequestInfo) FSubjectPKInfo: ISubjectPublicKeyInfo; FAttributes: IAsn1Set; - class function GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; static; - strict protected function GetVersion: IDerInteger; function GetSubject: IX509Name; @@ -288,9 +283,6 @@ TPrivateKeyInfo = class(TAsn1Encodable, IPrivateKeyInfo) FAttributes: IAsn1Set; FPublicKey: IDerBitString; - class function GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; static; - class function GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; static; - strict protected function GetVersion: IDerInteger; function GetPrivateKeyAlgorithm: IAlgorithmIdentifier; @@ -478,8 +470,6 @@ TPbkdf2Params = class(TAsn1Encodable, IPbkdf2Params) FDefaultPrf: IAlgorithmIdentifier; class constructor Create(); overload; - class function ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; static; - class function ReadOptionalAlgorithmIdentifier(AEnc: IAsn1Encodable): IAlgorithmIdentifier; static; strict protected function GetSalt: IAsn1OctetString; @@ -562,8 +552,6 @@ TMacData = class(TAsn1Encodable, IMacData) FMacSalt: IAsn1OctetString; FIterations: IDerInteger; - class function ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; static; - strict protected function GetMac: IDigestInfo; function GetSalt: TCryptoLibByteArray; @@ -577,6 +565,7 @@ TMacData = class(TAsn1Encodable, IMacData) class function GetInstance(const AEncoded: TCryptoLibByteArray): IMacData; overload; static; class function GetInstance(const AObj: IAsn1TaggedObject; AExplicitly: Boolean): IMacData; overload; static; + class function GetOptional(const AElement: IAsn1Encodable): IMacData; static; class function GetTagged(const ATaggedObject: IAsn1TaggedObject; ADeclaredExplicit: Boolean): IMacData; static; @@ -604,7 +593,6 @@ TSafeBag = class(TAsn1Encodable, ISafeBag) FBagValue: IAsn1Encodable; FBagAttributes: IAsn1Set; - class function ReadOptionalAsn1Set(AElement: IAsn1Encodable): IAsn1Set; static; strict protected function GetBagID: IDerObjectIdentifier; @@ -824,18 +812,14 @@ class function TAttributePkcs.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TAttributePkcs.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - end; - - FAttrType := TDerObjectIdentifier.GetInstance(ASeq[0]); - FAttrValues := TAsn1Set.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAttrType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FAttrValues := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAttributePkcs.Create(const AAttrType: IDerObjectIdentifier; @@ -922,41 +906,21 @@ class function TCertificationRequestInfo.GetTagged(const ATaggedObject: IAsn1Tag constructor TCertificationRequestInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 4) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - end; - - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSubject := TX509Name.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSubjectPKInfo := TSubjectPublicKeyInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 4); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FSubject := TAsn1Utilities.Read(ASeq, LPos, TX509Name.GetInstance); + FSubjectPKInfo := TAsn1Utilities.Read(ASeq, LPos, TSubjectPublicKeyInfo.GetInstance); // NOTE: some CertificationRequestInfo objects seem to treat this field as optional. - FAttributes := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedAsn1Set); - - if LPos <> LCount then - begin - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - end; - + FAttributes := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TAsn1Set.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); ValidateAttributes(FAttributes); end; -class function TCertificationRequestInfo.GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; -begin - Result := TAsn1Set.GetTagged(ATagged, AState); -end; - constructor TCertificationRequestInfo.Create(const ASubject: IX509Name; const APkInfo: ISubjectPublicKeyInfo; const AAttributes: IAsn1Set); begin @@ -1085,19 +1049,15 @@ constructor TCertificationRequest.Create; constructor TCertificationRequest.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 3 then - begin - raise EArgumentCryptoLibException.CreateRes(@SWrongNumberOfElements); - end; - - FReqInfo := TCertificationRequestInfo.GetInstance(ASeq[0]); - FSigAlgId := TAlgorithmIdentifier.GetInstance(ASeq[1]); - FSigBits := TDerBitString.GetInstance(ASeq[2]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 3); + FReqInfo := TAsn1Utilities.Read(ASeq, LPos, TCertificationRequestInfo.GetInstance); + FSigAlgId := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSigBits := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TCertificationRequest.Create(const ARequestInfo: ICertificationRequestInfo; @@ -1214,50 +1174,24 @@ class function TPrivateKeyInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TPrivateKeyInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos, LVersionValue: Int32; + LPos: Int32; + LVersionValue: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 5) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - end; - - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FPrivateKeyAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FPrivateKey := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FAttributes := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedAsn1Set); - - FPublicKey := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedDerBitString); - - if LPos <> LCount then - begin - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - end; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 5); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FPrivateKeyAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FPrivateKey := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FAttributes := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TAsn1Set.GetTagged); + FPublicKey := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TDerBitString.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); LVersionValue := FVersion.IntValueExact; if (FPublicKey <> nil) and (LVersionValue < 1) then - begin raise EArgumentCryptoLibException.CreateRes(@SPublicKeyRequiresVersionV21OrLater); - end; -end; - -class function TPrivateKeyInfo.GetTaggedAsn1Set(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set; -begin - Result := TAsn1Set.GetTagged(ATagged, AState); -end; - -class function TPrivateKeyInfo.GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; -begin - Result := TDerBitString.GetTagged(ATagged, AState); end; constructor TPrivateKeyInfo.Create(const APrivateKeyAlgorithm: IAlgorithmIdentifier; @@ -1414,16 +1348,14 @@ class function TEncryptedPrivateKeyInfo.GetTagged(const ATaggedObject: IAsn1Tagg constructor TEncryptedPrivateKeyInfo.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FEncryptionAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[0]); - FEncryptedData := TAsn1OctetString.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FEncryptionAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FEncryptedData := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TEncryptedPrivateKeyInfo.Create(const AAlgId: IAlgorithmIdentifier; @@ -1550,8 +1482,17 @@ constructor TEncryptionScheme.Create(const AObjectID: IDerObjectIdentifier; end; constructor TEncryptionScheme.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; + LObjectID: IDerObjectIdentifier; + LParameters: IAsn1Encodable; begin - Create(TDerObjectIdentifier.GetInstance(ASeq[0]), ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + LObjectID := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + LParameters := TAsn1Utilities.ReadEncodable(ASeq, LPos); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); + Create(LObjectID, LParameters); end; function TEncryptionScheme.GetParametersAsn1Object: IAsn1Object; @@ -1612,14 +1553,14 @@ class function TPbeParameter.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TPbeParameter.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - FSalt := TAsn1OctetString.GetInstance(ASeq[0]); - FIterationCount := TDerInteger.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FSalt := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FIterationCount := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPbeParameter.Create(const ASalt: TCryptoLibByteArray; AIterationCount: Int32); @@ -1699,16 +1640,16 @@ class function TPbeS2Parameters.GetTagged(const ATaggedObject: IAsn1TaggedObject constructor TPbeS2Parameters.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; LFunc: IAlgorithmIdentifier; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - LFunc := TAlgorithmIdentifier.GetInstance(ASeq[0]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + LFunc := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); FKeyDerivationFunc := TKeyDerivationFunc.Create(LFunc.Algorithm, LFunc.Parameters); - FEncryptionScheme := TEncryptionScheme.GetEncryptionSchemeInstance(ASeq[1]); + FEncryptionScheme := TEncryptionScheme.GetEncryptionSchemeInstance(TAsn1Utilities.ReadEncodable(ASeq, LPos)); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPbeS2Parameters.Create(const AKeyDerivationFunc: IKeyDerivationFunc; @@ -1788,33 +1729,18 @@ class function TPbkdf2Params.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TPbkdf2Params.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 4) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - FOctStr := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIterationCount := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FKeyLength := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); - FPrf := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalAlgorithmIdentifier); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 4); + FOctStr := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FIterationCount := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FKeyLength := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + FPrf := TAsn1Utilities.ReadOptional(ASeq, LPos, TAlgorithmIdentifier.GetOptional); if FPrf = nil then FPrf := DefaultPrf; - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TPbkdf2Params.ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AEnc); -end; - -class function TPbkdf2Params.ReadOptionalAlgorithmIdentifier(AEnc: IAsn1Encodable): IAlgorithmIdentifier; -begin - Result := TAlgorithmIdentifier.GetOptional(AEnc); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPbkdf2Params.Create(const ASalt: TCryptoLibByteArray; AIterationCount: Int32); @@ -1959,14 +1885,14 @@ class function TPkcs12PbeParams.GetTagged(const ATaggedObject: IAsn1TaggedObject constructor TPkcs12PbeParams.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - FIV := TAsn1OctetString.GetInstance(ASeq[0]); - FIterations := TDerInteger.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FIV := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FIterations := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPkcs12PbeParams.Create(const ASalt: TCryptoLibByteArray; AIterations: Int32); @@ -2056,25 +1982,15 @@ class function TPkcsContentInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject constructor TPkcsContentInfo.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; - LTagged: IAsn1TaggedObject; + LPos: Int32; begin Inherited Create(); - LCount := ASeq.Count; - if (LCount < 1) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FContentType := TDerObjectIdentifier.GetInstance(ASeq[0]); - - if ASeq.Count > 1 then - begin - LTagged := TAsn1TaggedObject.GetContextInstance(ASeq[1], 0); - FContent := LTagged.GetExplicitBaseObject(); - end - else - begin - FContent := nil; - end; + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FContentType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FContent := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAsn1Utilities.GetTaggedExplicitBaseObject); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPkcsContentInfo.Create(const AContentType: IDerObjectIdentifier; @@ -2165,36 +2081,20 @@ class function TPkcsSignedData.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TPkcsSignedData.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin Inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 4) or (LCount > 6) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FDigestAlgorithms := TAsn1Set.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FContentInfo := TPkcsContentInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FCertificates := TAsn1Utilities.ReadOptionalContextTagged( - ASeq, LPos, 0, ASeq, - GetTaggedAsn1SetFromSeq); - FCrls := TAsn1Utilities.ReadOptionalContextTagged( - ASeq, LPos, 1, ASeq, - GetTaggedAsn1SetFromSeq); - FSignerInfos := TAsn1Set.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TPkcsSignedData.GetTaggedAsn1SetFromSeq(ATagged: IAsn1TaggedObject; AState: IAsn1Sequence): IAsn1Set; -begin - Result := TAsn1Set.GetTagged(ATagged, False); + TAsn1Utilities.CheckSequenceSize(ASeq, 4, 6); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FDigestAlgorithms := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + FContentInfo := TAsn1Utilities.Read(ASeq, LPos, TPkcsContentInfo.GetInstance); + FCertificates := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TAsn1Set.GetTagged); + FCrls := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TAsn1Set.GetTagged); + FSignerInfos := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPkcsSignedData.Create(const AVersion: IDerInteger; @@ -2264,6 +2164,21 @@ function TPkcsSignedData.ToAsn1Object: IAsn1Object; { TMacData } +class function TMacData.GetOptional(const AElement: IAsn1Encodable): IMacData; +var + LSequence: IAsn1Sequence; +begin + if AElement = nil then + raise EArgumentNilCryptoLibException.CreateRes(@SAsn1EncodableElementNil); + if Supports(AElement, IMacData, Result) then + Exit; + LSequence := TAsn1Sequence.GetOptional(AElement); + if LSequence <> nil then + Result := TMacData.Create(LSequence) + else + Result := nil; +end; + class function TMacData.GetInstance(AObj: TObject): IMacData; begin if AObj = nil then @@ -2317,31 +2232,19 @@ class function TMacData.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TMacData.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FMac := TDigestInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FMacSalt := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIterations := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FMac := TAsn1Utilities.Read(ASeq, LPos, TDigestInfo.GetInstance); + FMacSalt := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FIterations := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); if FIterations = nil then FIterations := TDerInteger.One; - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; -class function TMacData.ReadOptionalDerInteger(AEnc: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AEnc); -end; constructor TMacData.Create(const ADigInfo: IDigestInfo; const ASalt: TCryptoLibByteArray; AIterationCount: Int32); @@ -2461,25 +2364,18 @@ class function TPfx.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TPfx.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; LVersion: IDerInteger; begin inherited Create(); - - LCount := ASeq.Count; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - LVersion := TDerInteger.GetInstance(ASeq[0]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + LVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); if not LVersion.HasValue(3) then raise EArgumentCryptoLibException.CreateRes(@SWrongVersionForPfxPdu); - - FContentInfo := TPkcsContentInfo.GetInstance(ASeq[1]); - - if LCount <= 2 then - FMacData := nil - else - FMacData := TMacData.GetInstance(ASeq[2]); + FContentInfo := TAsn1Utilities.Read(ASeq, LPos, TPkcsContentInfo.GetInstance); + FMacData := TAsn1Utilities.ReadOptional(ASeq, LPos, TMacData.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPfx.Create(const AContentInfo: IPkcsContentInfo; @@ -2567,33 +2463,18 @@ class function TSafeBag.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TSafeBag.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; - LTagged: IAsn1TaggedObject; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FBagID := TDerObjectIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - LTagged := TAsn1TaggedObject.GetContextInstance(ASeq[LPos], 0); - FBagValue := LTagged.GetExplicitBaseObject(); - System.Inc(LPos); - - FBagAttributes := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalAsn1Set); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FBagID := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FBagValue := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 0, True, + TAsn1Utilities.GetTaggedExplicitBaseObject); + FBagAttributes := TAsn1Utilities.ReadOptional(ASeq, LPos, TAsn1Set.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; -class function TSafeBag.ReadOptionalAsn1Set(AElement: IAsn1Encodable): IAsn1Set; -begin - Result := TAsn1Set.GetOptional(AElement); -end; constructor TSafeBag.Create(const ABagID: IDerObjectIdentifier; const ABagValue: IAsn1Encodable); @@ -2702,18 +2583,15 @@ class function TCertBag.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TCertBag.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; - LTagged: IAsn1TaggedObject; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - FCertID := TDerObjectIdentifier.GetInstance(ASeq[0]); - LTagged := TAsn1TaggedObject.GetContextInstance(ASeq[1], 0); - FCertValue := LTagged.GetExplicitBaseObject(); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FCertID := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FCertValue := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 0, True, + TAsn1Utilities.GetTaggedExplicitBaseObject); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TCertBag.Create(const ACertID: IDerObjectIdentifier; @@ -2899,20 +2777,17 @@ class function TPkcsEncryptedData.GetTagged(const ATaggedObject: IAsn1TaggedObje constructor TPkcsEncryptedData.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; LVersion: IDerInteger; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SPkcsBadSequenceSize, [LCount]); - - LVersion := TDerInteger.GetInstance(ASeq[0]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + LVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); if not LVersion.HasValue(0) then raise EArgumentCryptoLibException.CreateRes(@SEncryptedDataVersionNotZero); - - FData := TAsn1Sequence.GetInstance(ASeq[1]); + FData := TAsn1Utilities.Read(ASeq, LPos, TAsn1Sequence.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPkcsEncryptedData.Create(const AContentType: IDerObjectIdentifier; diff --git a/CryptoLib/src/Asn1/Pkcs/ClpPkcsDHAsn1Objects.pas b/CryptoLib/src/Asn1/Pkcs/ClpPkcsDHAsn1Objects.pas index 2c06299f..be8a1202 100644 --- a/CryptoLib/src/Asn1/Pkcs/ClpPkcsDHAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Pkcs/ClpPkcsDHAsn1Objects.pas @@ -28,7 +28,8 @@ interface ClpIAsn1Core, ClpIPkcsDHAsn1Objects, ClpBigInteger, - ClpCryptoLibTypes; + ClpCryptoLibTypes, + ClpAsn1Utilities; resourcestring SBadSequenceSize = 'bad sequence size: %d'; @@ -73,18 +74,15 @@ implementation constructor TDHParameter.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - FP := TDerInteger.GetInstance(ASeq[0]); - FG := TDerInteger.GetInstance(ASeq[1]); - if LCount > 2 then - FL := TDerInteger.GetInstance(ASeq[2]) - else - FL := nil; + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FP := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FG := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FL := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDHParameter.Create(const AP, AG: TBigInteger; AL: Int32); diff --git a/CryptoLib/src/Asn1/Pkcs/ClpPkcsRsaAsn1Objects.pas b/CryptoLib/src/Asn1/Pkcs/ClpPkcsRsaAsn1Objects.pas index 07476802..7315e08d 100644 --- a/CryptoLib/src/Asn1/Pkcs/ClpPkcsRsaAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Pkcs/ClpPkcsRsaAsn1Objects.pas @@ -121,8 +121,6 @@ TRsassaPssParameters = class(TAsn1Encodable, IRsassaPssParameters) FDefaultHashAlgorithm, FDefaultMaskGenAlgorithm: IAlgorithmIdentifier; FDefaultSaltLength, FDefaultTrailerField: IDerInteger; class constructor Create; - class function GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; static; - class function GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; static; var FHashAlgorithm: IAlgorithmIdentifier; @@ -181,7 +179,6 @@ TRsaesOaepParameters = class(TAsn1Encodable, IRsaesOaepParameters) FDefaultHashAlgorithm, FDefaultMaskGenAlgorithm, FDefaultPSourceAlgorithm: IAlgorithmIdentifier; class constructor Create; - class function GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; static; var FHashAlgorithm: IAlgorithmIdentifier; @@ -278,26 +275,22 @@ class function TRsaPrivateKeyStructure.GetTagged(const ATaggedObject: IAsn1Tagge constructor TRsaPrivateKeyStructure.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; LVersion: IDerInteger; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 9 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - LVersion := TDerInteger.GetInstance(ASeq[0]); - FModulus := TDerInteger.GetInstance(ASeq[1]).Value; - FPublicExponent := TDerInteger.GetInstance(ASeq[2]).Value; - FPrivateExponent := TDerInteger.GetInstance(ASeq[3]).Value; - FPrime1 := TDerInteger.GetInstance(ASeq[4]).Value; - FPrime2 := TDerInteger.GetInstance(ASeq[5]).Value; - FExponent1 := TDerInteger.GetInstance(ASeq[6]).Value; - FExponent2 := TDerInteger.GetInstance(ASeq[7]).Value; - FCoefficient := TDerInteger.GetInstance(ASeq[8]).Value; + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 9, 9); + LVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FModulus := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FPublicExponent := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FPrivateExponent := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FPrime1 := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FPrime2 := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FExponent1 := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FExponent2 := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + FCoefficient := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); if not LVersion.HasValue(0) then raise EArgumentCryptoLibException.CreateRes(@SWrongVersionForRsaPrivateKey); @@ -454,48 +447,34 @@ class function TRsassaPssParameters.GetTagged(const ATaggedObject: IAsn1TaggedOb Result := TRsassaPssParameters.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TRsassaPssParameters.GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; -begin - Result := TAlgorithmIdentifier.GetTagged(ATagged, AState); -end; - -class function TRsassaPssParameters.GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; -begin - Result := TDerInteger.GetTagged(ATagged, AState); -end; - constructor TRsassaPssParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 4) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FHashAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedAlgorithmIdentifier); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 4); + FHashAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAlgorithmIdentifier.GetTagged); if FHashAlgorithm = nil then FHashAlgorithm := DefaultHashAlgorithm; - FMaskGenAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, - GetTaggedAlgorithmIdentifier); + FMaskGenAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, + TAlgorithmIdentifier.GetTagged); if FMaskGenAlgorithm = nil then FMaskGenAlgorithm := DefaultMaskGenAlgorithm; - FSaltLength := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, - GetTaggedDerInteger); + FSaltLength := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, + TDerInteger.GetTagged); if FSaltLength = nil then FSaltLength := DefaultSaltLength; - FTrailerField := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, - GetTaggedDerInteger); + FTrailerField := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, + TDerInteger.GetTagged); if FTrailerField = nil then FTrailerField := DefaultTrailerField; - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TRsassaPssParameters.Create; @@ -641,38 +620,29 @@ class function TRsaesOaepParameters.GetTagged(const ATaggedObject: IAsn1TaggedOb Result := TRsaesOaepParameters.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TRsaesOaepParameters.GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; -begin - Result := TAlgorithmIdentifier.GetTagged(ATagged, AState); -end; - constructor TRsaesOaepParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FHashAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedAlgorithmIdentifier); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 3); + FHashAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAlgorithmIdentifier.GetTagged); if FHashAlgorithm = nil then FHashAlgorithm := DefaultHashAlgorithm; - FMaskGenAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, - GetTaggedAlgorithmIdentifier); + FMaskGenAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, + TAlgorithmIdentifier.GetTagged); if FMaskGenAlgorithm = nil then FMaskGenAlgorithm := DefaultMaskGenAlgorithm; - FPSourceAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, - GetTaggedAlgorithmIdentifier); + FPSourceAlgorithm := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, + TAlgorithmIdentifier.GetTagged); if FPSourceAlgorithm = nil then FPSourceAlgorithm := DefaultPSourceAlgorithm; - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TRsaesOaepParameters.Create; diff --git a/CryptoLib/src/Asn1/Sec/ClpSecECAsn1Objects.pas b/CryptoLib/src/Asn1/Sec/ClpSecECAsn1Objects.pas index 3d2ee44d..35d59e66 100644 --- a/CryptoLib/src/Asn1/Sec/ClpSecECAsn1Objects.pas +++ b/CryptoLib/src/Asn1/Sec/ClpSecECAsn1Objects.pas @@ -33,10 +33,8 @@ interface ClpAsn1Utilities; resourcestring - SBadSequenceSize = 'bad sequence size: %d'; SKeyNil = 'key cannot be nil'; SOrderBitLengthTooSmall = 'order must be at least the key bit length'; - SUnexpectedElementsInSequence = 'unexpected elements in sequence'; SPrivateKeyNil = 'private key cannot be nil'; @@ -53,9 +51,6 @@ TECPrivateKeyStructure = class(TAsn1Encodable, IECPrivateKeyStructure) FParameters: IAsn1Encodable; FPublicKey: IDerBitString; - class function GetTaggedExplicitBaseObject(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Encodable; static; - class function GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; static; - strict protected function GetVersion: IDerInteger; function GetPrivateKey: IAsn1OctetString; @@ -146,41 +141,20 @@ class function TECPrivateKeyStructure.GetTagged(const ATaggedObject: IAsn1Tagged Result := TECPrivateKeyStructure.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TECPrivateKeyStructure.GetTaggedExplicitBaseObject(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Encodable; -begin - Result := ATagged.GetExplicitBaseObject(); -end; - -class function TECPrivateKeyStructure.GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; -begin - Result := TDerBitString.GetTagged(ATagged, AState); -end; - constructor TECPrivateKeyStructure.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - - if (LCount < 2) or (LCount > 4) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FPrivateKey := TAsn1OctetString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FParameters := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedExplicitBaseObject); - - FPublicKey := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, - GetTaggedDerBitString); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 4); + FVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FPrivateKey := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + FParameters := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAsn1Utilities.GetTaggedExplicitBaseObject); + FPublicKey := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, + TDerBitString.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TECPrivateKeyStructure.Create(AOrderBitLength: Int32; const AKey: TBigInteger); diff --git a/CryptoLib/src/Asn1/X500/ClpX500Asn1Objects.pas b/CryptoLib/src/Asn1/X500/ClpX500Asn1Objects.pas index 7b57f50c..eab6e48b 100644 --- a/CryptoLib/src/Asn1/X500/ClpX500Asn1Objects.pas +++ b/CryptoLib/src/Asn1/X500/ClpX500Asn1Objects.pas @@ -230,16 +230,14 @@ class function TAttributeTypeAndValue.GetTagged(const ATaggedObject: IAsn1Tagged constructor TAttributeTypeAndValue.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FAttrType := TDerObjectIdentifier.GetInstance(ASeq[0]); - FValue := ASeq[1]; + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAttrType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FValue := TAsn1Utilities.ReadEncodable(ASeq, LPos); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAttributeTypeAndValue.Create(const AAttrType: IDerObjectIdentifier; diff --git a/CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas b/CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas index 468ca9f4..5979a6e4 100644 --- a/CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas +++ b/CryptoLib/src/Asn1/X509/ClpX509Asn1Objects.pas @@ -257,10 +257,6 @@ TDeltaCertificateDescriptor = class(TAsn1Encodable, IAsn1Encodable, strict private procedure ImplCreate(const ASeq: IAsn1Sequence); - class function GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; static; - class function GetTaggedX509Name(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Name; static; - class function GetTaggedValidity(ATagged: IAsn1TaggedObject; AState: Boolean): IValidity; static; - class function GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; static; strict protected function GetSerialNumber: IDerInteger; @@ -462,9 +458,6 @@ TAuthorityKeyIdentifier = class(TAsn1Encodable, IAuthorityKeyIdentifier) FAuthorityCertSerialNumber: IDerInteger; class procedure CheckIssuerAndSerial(const ACertIssuer: IGeneralNames; const ACertSerial: IDerInteger); static; - class function GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; static; - class function GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; static; - class function GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; static; strict protected function GetKeyIdentifier: IAsn1OctetString; @@ -1193,7 +1186,6 @@ TCrlEntry = class(TAsn1Encodable, ICrlEntry) FRevocationDate: ITime; FCrlEntryExtensions: IX509Extensions; - class function ReadOptionalX509Extensions(AElement: IAsn1Encodable): IX509Extensions; static; strict protected function GetUserCertificate: IDerInteger; @@ -1330,8 +1322,6 @@ TBasicConstraints = class(TAsn1Encodable, IBasicConstraints) FCA: IDerBoolean; FPathLenConstraint: IDerInteger; - class function ReadOptionalDerBoolean(AElement: IAsn1Encodable): IDerBoolean; static; - class function ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; static; strict protected function IsCA: Boolean; @@ -1463,9 +1453,6 @@ TTbsCertificateStructure = class(TAsn1Encodable, ITbsCertificateStructure) FExtensions: IX509Extensions; FSeq: IAsn1Sequence; - class function GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; static; - class function GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; static; - class function GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; static; strict protected function GetVersion: Int32; @@ -1602,7 +1589,6 @@ TCertificatePair = class(TAsn1Encodable, ICertificatePair) FReverse: IX509CertificateStructure; procedure Validate; - class function GetTaggedX509CertificateStructure(ATagged: IAsn1TaggedObject; AState: Boolean): IX509CertificateStructure; static; strict protected function GetForward: IX509CertificateStructure; @@ -1752,7 +1738,6 @@ TIssuerSerial = class(TAsn1Encodable, IIssuerSerial) FSerial: IDerInteger; FIssuerUid: IDerBitString; - class function ReadOptionalDerBitString(AElement: IAsn1Encodable): IDerBitString; static; strict protected function GetIssuer: IGeneralNames; @@ -1797,9 +1782,6 @@ TV2Form = class(TAsn1Encodable, IV2Form) FBaseCertificateID: IIssuerSerial; FObjectDigestInfo: IObjectDigestInfo; - class function ReadOptionalGeneralNames(AElement: IAsn1Encodable): IGeneralNames; static; - class function GetTaggedIssuerSerial(ATagged: IAsn1TaggedObject; AState: Boolean): IIssuerSerial; static; - class function GetTaggedObjectDigestInfo(ATagged: IAsn1TaggedObject; AState: Boolean): IObjectDigestInfo; static; strict protected function GetIssuerName: IGeneralNames; @@ -1846,7 +1828,6 @@ TObjectDigestInfo = class(TAsn1Encodable, IObjectDigestInfo) FDigestAlgorithm: IAlgorithmIdentifier; FObjectDigest: IDerBitString; - class function ReadOptionalDerObjectIdentifier(AElement: IAsn1Encodable): IDerObjectIdentifier; static; public const @@ -2028,10 +2009,6 @@ TTbsCertificateList = class(TAsn1Encodable, ITbsCertificateList) FRevokedCertificates: IAsn1Sequence; FCrlExtensions: IX509Extensions; - class function ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; static; - class function ReadOptionalTime(AElement: IAsn1Encodable): ITime; static; - class function ReadOptionalAsn1Sequence(AElement: IAsn1Encodable): IAsn1Sequence; static; - class function GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; static; class function ElementToCrlEntry(AElement: IAsn1Encodable): ICrlEntry; static; strict protected @@ -2078,9 +2055,7 @@ TDistributionPoint = class(TAsn1Encodable, IDistributionPoint) FReasons: IReasonFlags; FCrlIssuer: IGeneralNames; - class function GetTaggedDistributionPointName(ATagged: IAsn1TaggedObject; AState: Boolean): IDistributionPointName; static; - class function GetTaggedReasonFlags(ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; static; - class function GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; static; + class function GetTaggedReasonFlags(const ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; static; strict protected function GetDistributionPointName: IDistributionPointName; @@ -2137,9 +2112,7 @@ TIssuingDistributionPoint = class(TAsn1Encodable, IIssuingDistributionPoint) FOnlyContainsAttributeCerts: IDerBoolean; FSeq: IAsn1Sequence; - class function GetTaggedDistributionPointName(ATagged: IAsn1TaggedObject; AState: Boolean): IDistributionPointName; static; - class function GetTaggedDerBoolean(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBoolean; static; - class function GetTaggedReasonFlags(ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; static; + class function GetTaggedReasonFlags(const ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; static; strict protected function GetDistributionPoint: IDistributionPointName; @@ -2302,9 +2275,6 @@ THolder = class(TAsn1Encodable, IHolder) FObjectDigestInfo: IObjectDigestInfo; FVersion: Int32; - class function GetTaggedIssuerSerial(ATagged: IAsn1TaggedObject; AState: Boolean): IIssuerSerial; static; - class function GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; static; - class function GetTaggedObjectDigestInfo(ATagged: IAsn1TaggedObject; AState: Boolean): IObjectDigestInfo; static; strict protected function GetVersion: Int32; @@ -2399,9 +2369,6 @@ TAttributeCertificateInfo = class(TAsn1Encodable, IAttributeCertificateInfo) FIssuerUniqueID: IDerBitString; FExtensions: IX509Extensions; - class function ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; static; - class function ReadOptionalDerBitString(AElement: IAsn1Encodable): IDerBitString; static; - class function ReadOptionalX509Extensions(AElement: IAsn1Encodable): IX509Extensions; static; strict protected function GetVersion: IDerInteger; @@ -2546,21 +2513,14 @@ class function TAlgorithmIdentifier.GetTagged(const ATaggedObject: IAsn1TaggedOb constructor TAlgorithmIdentifier.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if (LCount < 1) or (LCount > 2) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FAlgorithm := TDerObjectIdentifier.GetInstance(ASeq[0]); - if LCount < 2 then - FParameters := nil - else - FParameters := ASeq[1]; + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FParameters := TAsn1Utilities.ReadOptional(ASeq, LPos, TAsn1Utilities.GetEncodableIdentity); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAlgorithmIdentifier.Create(const AAlgorithm: IDerObjectIdentifier); @@ -2655,18 +2615,14 @@ class function TDigestInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TDigestInfo.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FDigestAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[0]); - FDigest := TAsn1OctetString.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FDigestAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FDigest := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDigestInfo.Create(const AAlgId: IAlgorithmIdentifier; @@ -2724,62 +2680,26 @@ function TDigestInfo.ToAsn1Object: IAsn1Object; { TDeltaCertificateDescriptor } -class function TDeltaCertificateDescriptor.GetTaggedAlgorithmIdentifier(ATagged: IAsn1TaggedObject; AState: Boolean): IAlgorithmIdentifier; -begin - Result := TAlgorithmIdentifier.GetTagged(ATagged, AState); -end; - -class function TDeltaCertificateDescriptor.GetTaggedX509Name(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Name; -begin - Result := TX509Name.GetTagged(ATagged, AState); -end; - -class function TDeltaCertificateDescriptor.GetTaggedValidity(ATagged: IAsn1TaggedObject; AState: Boolean): IValidity; -begin - Result := TValidity.GetTagged(ATagged, AState); -end; - -class function TDeltaCertificateDescriptor.GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; -begin - Result := TX509Extensions.GetTagged(ATagged, AState); -end; - procedure TDeltaCertificateDescriptor.ImplCreate(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 8) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FSerialNumber := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FSignature := TAsn1Utilities.ReadOptionalContextTagged( - ASeq, LPos, 0, True, - GetTaggedAlgorithmIdentifier); - - FIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, - GetTaggedX509Name); - - FValidity := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, - GetTaggedValidity); - - FSubject := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, - GetTaggedX509Name); - - FSubjectPublicKeyInfo := TSubjectPublicKeyInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 4, True, - GetTaggedX509Extensions); - - FSignatureValue := TDerBitString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 8); + FSerialNumber := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FSignature := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAlgorithmIdentifier.GetTagged); + FIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, + TX509Name.GetTagged); + FValidity := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, True, + TValidity.GetTagged); + FSubject := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, + TX509Name.GetTagged); + FSubjectPublicKeyInfo := TAsn1Utilities.Read(ASeq, LPos, TSubjectPublicKeyInfo.GetInstance); + FExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 4, True, + TX509Extensions.GetTagged); + FSignatureValue := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDeltaCertificateDescriptor.Create(const ASeq: IAsn1Sequence); @@ -3170,18 +3090,14 @@ class function TValidity.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TValidity.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FNotBefore := TTime.GetInstance(ASeq[0]); - FNotAfter := TTime.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FNotBefore := TAsn1Utilities.Read(ASeq, LPos, TTime.GetInstance); + FNotAfter := TAsn1Utilities.Read(ASeq, LPos, TTime.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TValidity.Create(const ANotBefore, ANotAfter: ITime); @@ -3270,32 +3186,17 @@ class function TCrlEntry.GetTagged(const ATaggedObject: IAsn1TaggedObject; Result := TCrlEntry.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TCrlEntry.ReadOptionalX509Extensions(AElement: IAsn1Encodable): IX509Extensions; -begin - Result := TX509Extensions.GetOptional(AElement); -end; - constructor TCrlEntry.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FUserCertificate := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FRevocationDate := TTime.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FCrlEntryExtensions := TAsn1Utilities.ReadOptional(ASeq, LPos, - ReadOptionalX509Extensions); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FUserCertificate := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FRevocationDate := TAsn1Utilities.Read(ASeq, LPos, TTime.GetInstance); + FCrlEntryExtensions := TAsn1Utilities.ReadOptional(ASeq, LPos, TX509Extensions.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FSeq := ASeq; end; @@ -3631,39 +3532,18 @@ class function TBasicConstraints.GetTagged(const ATaggedObject: IAsn1TaggedObjec Result := TBasicConstraints.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TBasicConstraints.ReadOptionalDerBoolean(AElement: IAsn1Encodable): IDerBoolean; -begin - Result := TDerBoolean.GetOptional(AElement); -end; - -class function TBasicConstraints.ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AElement); -end; - constructor TBasicConstraints.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 2) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FCA := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerBoolean); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 2); + FCA := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerBoolean.GetOptional); if FCA = nil then FCA := TDerBoolean.False; - - FPathLenConstraint := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); - - if LPos <> LCount then - begin - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - end; + FPathLenConstraint := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TBasicConstraints.Create(ACA: Boolean); @@ -3789,18 +3669,14 @@ class function TSubjectPublicKeyInfo.GetTagged(const ATaggedObject: IAsn1TaggedO constructor TSubjectPublicKeyInfo.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[0]); - FPublicKey := TDerBitString.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FPublicKey := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TSubjectPublicKeyInfo.Create(const AAlgID: IAlgorithmIdentifier; @@ -3904,18 +3780,14 @@ class function TSubjectAltPublicKeyInfo.FromExtensions(const AExtensions: IX509E constructor TSubjectAltPublicKeyInfo.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - - FAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[0]); - FSubjectAltPublicKey := TDerBitString.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSubjectAltPublicKey := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TSubjectAltPublicKeyInfo.Create(const AAlgorithm: IAlgorithmIdentifier; @@ -4005,88 +3877,48 @@ class function TTbsCertificateStructure.GetTagged(const ATaggedObject: IAsn1Tagg Result := TTbsCertificateStructure.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TTbsCertificateStructure.GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; -begin - Result := TDerInteger.GetTagged(ATagged, AState); -end; - -class function TTbsCertificateStructure.GetTaggedDerBitString(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBitString; -begin - Result := TDerBitString.GetTagged(ATagged, AState); -end; - -class function TTbsCertificateStructure.GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; -begin - Result := TX509Extensions.GetTagged(ATagged, AState); -end; - constructor TTbsCertificateStructure.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LIsV1, LIsV2: Boolean; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 6) or (LCount > 10) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; + TAsn1Utilities.CheckSequenceSize(ASeq, 6, 10); - FVersion := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedDerInteger); + FVersion := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TDerInteger.GetTagged); if FVersion = nil then FVersion := TDerInteger.Zero; LIsV1 := False; LIsV2 := False; if FVersion.HasValue(0) then - begin - LIsV1 := True; - end + LIsV1 := True else if FVersion.HasValue(1) then - begin - LIsV2 := True; - end + LIsV2 := True else if not FVersion.HasValue(2) then - begin raise EArgumentCryptoLibException.CreateRes(@SVersionNumberNotRecognized); - end; - FSerialNumber := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSignature := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIssuer := TX509Name.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FValidity := TValidity.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSubject := TX509Name.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSubjectPublicKeyInfo := TSubjectPublicKeyInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); + FSerialNumber := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FSignature := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FIssuer := TAsn1Utilities.Read(ASeq, LPos, TX509Name.GetInstance); + FValidity := TAsn1Utilities.Read(ASeq, LPos, TValidity.GetInstance); + FSubject := TAsn1Utilities.Read(ASeq, LPos, TX509Name.GetInstance); + FSubjectPublicKeyInfo := TAsn1Utilities.Read(ASeq, LPos, TSubjectPublicKeyInfo.GetInstance); if not LIsV1 then begin - FIssuerUniqueID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedDerBitString); - - FSubjectUniqueID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, - GetTaggedDerBitString); - + FIssuerUniqueID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TDerBitString.GetTagged); + FSubjectUniqueID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, + TDerBitString.GetTagged); if not LIsV2 then - begin - FExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, - GetTaggedX509Extensions); - end; - end; - - if LPos <> LCount then - begin - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + FExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, True, + TX509Extensions.GetTagged); end; + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FSeq := ASeq; end; @@ -4308,20 +4140,16 @@ class function TX509CertificateStructure.GetTagged(const ATaggedObject: IAsn1Tag constructor TX509CertificateStructure.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 3 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 3); // correct x509 certificate - FTbsCertificate := TTbsCertificateStructure.GetInstance(ASeq[0]); - FSignatureAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[1]); - FSignature := TDerBitString.GetInstance(ASeq[2]); + FTbsCertificate := TAsn1Utilities.Read(ASeq, LPos, TTbsCertificateStructure.GetInstance); + FSignatureAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSignature := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TX509CertificateStructure.Create(const ATbsCert: ITbsCertificateStructure; @@ -4474,33 +4302,18 @@ class function TCertificatePair.GetTagged(const ATaggedObject: IAsn1TaggedObject Result := TCertificatePair.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TCertificatePair.GetTaggedX509CertificateStructure(ATagged: IAsn1TaggedObject; AState: Boolean): IX509CertificateStructure; -begin - Result := TX509CertificateStructure.GetTagged(ATagged, AState); -end; - constructor TCertificatePair.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FForward := TAsn1Utilities.ReadOptionalContextTagged( - ASeq, LPos, 0, True, - GetTaggedX509CertificateStructure); - - FReverse := TAsn1Utilities.ReadOptionalContextTagged( - ASeq, LPos, 1, True, - GetTaggedX509CertificateStructure); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 2); + FForward := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TX509CertificateStructure.GetTagged); + FReverse := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, True, + TX509CertificateStructure.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); Validate(); end; @@ -5308,28 +5121,21 @@ class function TAuthorityKeyIdentifier.FromExtensions(const AExtensions: IX509Ex constructor TAuthorityKeyIdentifier.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LKeyIdentifier: IAsn1OctetString; LAuthorityCertIssuer: IGeneralNames; LAuthorityCertSerialNumber: IDerInteger; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - LKeyIdentifier := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedAsn1OctetString); - - LAuthorityCertIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedGeneralNames); - - LAuthorityCertSerialNumber := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, - GetTaggedDerInteger); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 3); + LKeyIdentifier := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TAsn1OctetString.GetTagged); + LAuthorityCertIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TGeneralNames.GetTagged); + LAuthorityCertSerialNumber := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, + TDerInteger.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); CheckIssuerAndSerial(LAuthorityCertIssuer, LAuthorityCertSerialNumber); FKeyIdentifier := LKeyIdentifier; @@ -5337,21 +5143,6 @@ constructor TAuthorityKeyIdentifier.Create(const ASeq: IAsn1Sequence); FAuthorityCertSerialNumber := LAuthorityCertSerialNumber; end; -class function TAuthorityKeyIdentifier.GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; -begin - Result := TAsn1OctetString.GetTagged(ATagged, AState); -end; - -class function TAuthorityKeyIdentifier.GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; -begin - Result := TGeneralNames.GetTagged(ATagged, AState); -end; - -class function TAuthorityKeyIdentifier.GetTaggedDerInteger(ATagged: IAsn1TaggedObject; AState: Boolean): IDerInteger; -begin - Result := TDerInteger.GetTagged(ATagged, AState); -end; - constructor TAuthorityKeyIdentifier.Create(const AKeyIdentifier: TCryptoLibByteArray); begin Create(AKeyIdentifier, nil, TBigInteger.GetDefault); @@ -5635,26 +5426,18 @@ class function TExtension.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TExtension.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FExtnID := TDerObjectIdentifier.GetInstance(ASeq[0]); - - if LCount = 3 then - begin - FCritical := TDerBoolean.GetInstance(ASeq[1]); - FExtnValue := TAsn1OctetString.GetInstance(ASeq[2]); - end + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FExtnID := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + if ASeq.Count = 3 then + FCritical := TAsn1Utilities.Read(ASeq, LPos, TDerBoolean.GetInstance) else - begin FCritical := TDerBoolean.False; - FExtnValue := TAsn1OctetString.GetInstance(ASeq[1]); - end; + FExtnValue := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TExtension.Create(const AExtnID: IDerObjectIdentifier; const ACritical: IDerBoolean; @@ -7831,15 +7614,14 @@ class function TAttributeX509.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TAttributeX509.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FAttrType := TDerObjectIdentifier.GetInstance(ASeq[0]); - FAttrValues := TAsn1Set.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAttrType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FAttrValues := TAsn1Utilities.Read(ASeq, LPos, TAsn1Set.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAttributeX509.Create(const AAttrType: IDerObjectIdentifier; const AAttrValues: IAsn1Set); @@ -7922,15 +7704,14 @@ class function TAttCertValidityPeriod.GetTagged(const ATaggedObject: IAsn1Tagged constructor TAttCertValidityPeriod.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FNotBeforeTime := TAsn1GeneralizedTime.GetInstance(ASeq[0]); - FNotAfterTime := TAsn1GeneralizedTime.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FNotBeforeTime := TAsn1Utilities.Read(ASeq, LPos, TAsn1GeneralizedTime.GetInstance); + FNotAfterTime := TAsn1Utilities.Read(ASeq, LPos, TAsn1GeneralizedTime.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAttCertValidityPeriod.Create(const ANotBeforeTime, ANotAfterTime: IAsn1GeneralizedTime); @@ -8008,18 +7789,14 @@ class function TPolicyInformation.GetTagged(const ATaggedObject: IAsn1TaggedObje constructor TPolicyInformation.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if (LCount < 1) or (LCount > 2) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FPolicyIdentifier := TDerObjectIdentifier.GetInstance(ASeq[0]); - if LCount < 2 then - FPolicyQualifiers := nil - else - FPolicyQualifiers := TAsn1Sequence.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 1, 2); + FPolicyIdentifier := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FPolicyQualifiers := TAsn1Utilities.ReadOptional(ASeq, LPos, TAsn1Sequence.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TPolicyInformation.Create(const APolicyIdentifier: IDerObjectIdentifier); @@ -8124,27 +7901,15 @@ class function TIssuerSerial.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TIssuerSerial.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FIssuer := TGeneralNames.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSerial := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIssuerUid := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerBitString); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TIssuerSerial.ReadOptionalDerBitString(AElement: IAsn1Encodable): IDerBitString; -begin - Result := TDerBitString.GetOptional(AElement); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FIssuer := TAsn1Utilities.Read(ASeq, LPos, TGeneralNames.GetInstance); + FSerial := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FIssuerUid := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerBitString.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TIssuerSerial.Create(const AIssuer: IX509Name; const ASerial: IDerInteger); @@ -8262,37 +8027,17 @@ class function TV2Form.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TV2Form.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FIssuerName := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalGeneralNames); - FBaseCertificateID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedIssuerSerial); - FObjectDigestInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedObjectDigestInfo); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TV2Form.ReadOptionalGeneralNames(AElement: IAsn1Encodable): IGeneralNames; -begin - Result := TGeneralNames.GetOptional(AElement); -end; - -class function TV2Form.GetTaggedIssuerSerial(ATagged: IAsn1TaggedObject; AState: Boolean): IIssuerSerial; -begin - Result := TIssuerSerial.GetTagged(ATagged, AState); -end; - -class function TV2Form.GetTaggedObjectDigestInfo(ATagged: IAsn1TaggedObject; AState: Boolean): IObjectDigestInfo; -begin - Result := TObjectDigestInfo.GetTagged(ATagged, AState); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 3); + FIssuerName := TAsn1Utilities.ReadOptional(ASeq, LPos, TGeneralNames.GetOptional); + FBaseCertificateID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TIssuerSerial.GetTagged); + FObjectDigestInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TObjectDigestInfo.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TV2Form.Create(const AIssuerName: IGeneralNames); @@ -8394,29 +8139,16 @@ class function TObjectDigestInfo.GetTagged(const ATaggedObject: IAsn1TaggedObjec constructor TObjectDigestInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 4) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FDigestedObjectType := TDerEnumerated.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FOtherObjectTypeID := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerObjectIdentifier); - FDigestAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FObjectDigest := TDerBitString.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TObjectDigestInfo.ReadOptionalDerObjectIdentifier(AElement: IAsn1Encodable): IDerObjectIdentifier; -begin - Result := TDerObjectIdentifier.GetOptional(AElement); + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 4); + FDigestedObjectType := TAsn1Utilities.Read(ASeq, LPos, TDerEnumerated.GetInstance); + FOtherObjectTypeID := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerObjectIdentifier.GetOptional); + FDigestAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FObjectDigest := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TObjectDigestInfo.Create(ADigestedObjectType: Int32; const AOtherObjectTypeID: String; @@ -8511,40 +8243,25 @@ class function TDistributionPoint.GetTagged(const ATaggedObject: IAsn1TaggedObje constructor TDistributionPoint.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FDistributionPointName := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedDistributionPointName); - FReasons := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 3); + FDistributionPointName := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TDistributionPointName.GetTagged); + FReasons := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, GetTaggedReasonFlags); - FCrlIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, - GetTaggedGeneralNames); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TDistributionPoint.GetTaggedDistributionPointName(ATagged: IAsn1TaggedObject; AState: Boolean): IDistributionPointName; -begin - Result := TDistributionPointName.GetTagged(ATagged, AState); + FCrlIssuer := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, + TGeneralNames.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; -class function TDistributionPoint.GetTaggedReasonFlags(ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; +class function TDistributionPoint.GetTaggedReasonFlags(const ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; begin Result := TReasonFlags.Create(TDerBitString.GetTagged(ATagged, AState)); end; -class function TDistributionPoint.GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; -begin - Result := TGeneralNames.GetTagged(ATagged, AState); -end; - constructor TDistributionPoint.Create(const ADistributionPointName: IDistributionPointName; const AReasons: IReasonFlags; const ACrlIssuer: IGeneralNames); begin @@ -8712,71 +8429,56 @@ constructor TIssuingDistributionPoint.Create(const ADistributionPoint: IDistribu constructor TIssuingDistributionPoint.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LOnlyContainsUserCerts, LOnlyContainsCACerts, LIndirectCRL, LOnlyContainsAttributeCerts: IDerBoolean; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 6) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 6); - FDistributionPoint := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedDistributionPointName); + FDistributionPoint := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TDistributionPointName.GetTagged); - LOnlyContainsUserCerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedDerBoolean); + LOnlyContainsUserCerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TDerBoolean.GetTagged); if LOnlyContainsUserCerts <> nil then FOnlyContainsUserCerts := LOnlyContainsUserCerts else FOnlyContainsUserCerts := TDerBoolean.False; - LOnlyContainsCACerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, - GetTaggedDerBoolean); + LOnlyContainsCACerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, + TDerBoolean.GetTagged); if LOnlyContainsCACerts <> nil then FOnlyContainsCACerts := LOnlyContainsCACerts else FOnlyContainsCACerts := TDerBoolean.False; - FOnlySomeReasons := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, False, + FOnlySomeReasons := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 3, False, GetTaggedReasonFlags); - LIndirectCRL := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 4, False, - GetTaggedDerBoolean); + LIndirectCRL := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 4, False, + TDerBoolean.GetTagged); if LIndirectCRL <> nil then FIndirectCRL := LIndirectCRL else FIndirectCRL := TDerBoolean.False; - LOnlyContainsAttributeCerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 5, False, - GetTaggedDerBoolean); + LOnlyContainsAttributeCerts := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 5, False, + TDerBoolean.GetTagged); if LOnlyContainsAttributeCerts <> nil then FOnlyContainsAttributeCerts := LOnlyContainsAttributeCerts else FOnlyContainsAttributeCerts := TDerBoolean.False; - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FSeq := ASeq; end; -class function TIssuingDistributionPoint.GetTaggedDistributionPointName(ATagged: IAsn1TaggedObject; AState: Boolean): IDistributionPointName; -begin - Result := TDistributionPointName.GetTagged(ATagged, AState); -end; - -class function TIssuingDistributionPoint.GetTaggedDerBoolean(ATagged: IAsn1TaggedObject; AState: Boolean): IDerBoolean; -begin - Result := TDerBoolean.GetTagged(ATagged, AState); -end; - -class function TIssuingDistributionPoint.GetTaggedReasonFlags(ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; +class function TIssuingDistributionPoint.GetTaggedReasonFlags(const ATagged: IAsn1TaggedObject; AState: Boolean): IReasonFlags; begin Result := TReasonFlags.Create(TDerBitString.GetTagged(ATagged, AState)); end; @@ -8922,17 +8624,15 @@ class function TCertificateList.GetTagged(const ATaggedObject: IAsn1TaggedObject constructor TCertificateList.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 3 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FTbsCertList := TTbsCertificateList.GetInstance(ASeq[0]); - FSignatureAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[1]); - FSignatureValue := TDerBitString.GetInstance(ASeq[2]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 3); + FTbsCertList := TAsn1Utilities.Read(ASeq, LPos, TTbsCertificateList.GetInstance); + FSignatureAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSignatureValue := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; function TCertificateList.GetTbsCertList: ITbsCertificateList; @@ -9236,36 +8936,27 @@ class function TTbsCertificateList.GetTagged(const ATaggedObject: IAsn1TaggedObj constructor TTbsCertificateList.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LVersion: IDerInteger; begin inherited Create(); - - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 7) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - LVersion := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 7); + LVersion := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); if LVersion <> nil then FVersion := LVersion else FVersion := TDerInteger.Zero; - FSignature := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIssuer := TX509Name.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FThisUpdate := TTime.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FNextUpdate := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalTime); - FRevokedCertificates := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalAsn1Sequence); - FCrlExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedX509Extensions); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + FSignature := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FIssuer := TAsn1Utilities.Read(ASeq, LPos, TX509Name.GetInstance); + FThisUpdate := TAsn1Utilities.Read(ASeq, LPos, TTime.GetInstance); + FNextUpdate := TAsn1Utilities.ReadOptional(ASeq, LPos, TTime.GetOptional); + FRevokedCertificates := TAsn1Utilities.ReadOptional(ASeq, LPos, TAsn1Sequence.GetOptional); + FCrlExtensions := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TX509Extensions.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FSeq := ASeq; end; @@ -9312,26 +9003,6 @@ function TTbsCertificateList.GetRevokedCertificates: TCryptoLibGenericArray(LElements, ElementToCrlEntry); end; -class function TTbsCertificateList.ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AElement); -end; - -class function TTbsCertificateList.ReadOptionalTime(AElement: IAsn1Encodable): ITime; -begin - Result := TTime.GetOptional(AElement); -end; - -class function TTbsCertificateList.ReadOptionalAsn1Sequence(AElement: IAsn1Encodable): IAsn1Sequence; -begin - Result := TAsn1Sequence.GetOptional(AElement); -end; - -class function TTbsCertificateList.GetTaggedX509Extensions(ATagged: IAsn1TaggedObject; AState: Boolean): IX509Extensions; -begin - Result := TX509Extensions.GetTagged(ATagged, AState); -end; - class function TTbsCertificateList.ElementToCrlEntry(AElement: IAsn1Encodable): ICrlEntry; begin Result := TCrlEntry.GetInstance(AElement); @@ -9524,42 +9195,21 @@ constructor THolder.Create(const ATagObj: IAsn1TaggedObject); constructor THolder.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 0) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FBaseCertificateID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, - GetTaggedIssuerSerial); - FEntityName := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, - GetTaggedGeneralNames); - FObjectDigestInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, - GetTaggedObjectDigestInfo); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); - + TAsn1Utilities.CheckSequenceSize(ASeq, 0, 3); + FBaseCertificateID := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, False, + TIssuerSerial.GetTagged); + FEntityName := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 1, False, + TGeneralNames.GetTagged); + FObjectDigestInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 2, False, + TObjectDigestInfo.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); FVersion := 1; end; -class function THolder.GetTaggedIssuerSerial(ATagged: IAsn1TaggedObject; AState: Boolean): IIssuerSerial; -begin - Result := TIssuerSerial.GetTagged(ATagged, AState); -end; - -class function THolder.GetTaggedGeneralNames(ATagged: IAsn1TaggedObject; AState: Boolean): IGeneralNames; -begin - Result := TGeneralNames.GetTagged(ATagged, AState); -end; - -class function THolder.GetTaggedObjectDigestInfo(ATagged: IAsn1TaggedObject; AState: Boolean): IObjectDigestInfo; -begin - Result := TObjectDigestInfo.GetTagged(ATagged, AState); -end; - constructor THolder.Create(const ABaseCertificateID: IIssuerSerial); begin Create(ABaseCertificateID, 1); @@ -9681,16 +9331,15 @@ class function TAttributeCertificate.GetTagged(const ATaggedObject: IAsn1TaggedO constructor TAttributeCertificate.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 3 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FACInfo := TAttributeCertificateInfo.GetInstance(ASeq[0]); - FSignatureAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[1]); - FSignatureValue := TDerBitString.GetInstance(ASeq[2]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 3); + FACInfo := TAsn1Utilities.Read(ASeq, LPos, TAttributeCertificateInfo.GetInstance); + FSignatureAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSignatureValue := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TAttributeCertificate.Create(const AACInfo: IAttributeCertificateInfo; @@ -9782,49 +9431,23 @@ class function TAttributeCertificateInfo.GetTagged(const ATaggedObject: IAsn1Tag constructor TAttributeCertificateInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 6) or (LCount > 9) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FVersion := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerInteger); + TAsn1Utilities.CheckSequenceSize(ASeq, 6, 9); + FVersion := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); if FVersion = nil then FVersion := TDerInteger.Zero; - FHolder := THolder.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIssuer := TAttCertIssuer.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSignature := TAlgorithmIdentifier.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FSerialNumber := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FAttrCertValidityPeriod := TAttCertValidityPeriod.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FAttributes := TAsn1Sequence.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FIssuerUniqueID := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalDerBitString); - FExtensions := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalX509Extensions); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); -end; - -class function TAttributeCertificateInfo.ReadOptionalDerInteger(AElement: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AElement); -end; - -class function TAttributeCertificateInfo.ReadOptionalDerBitString(AElement: IAsn1Encodable): IDerBitString; -begin - Result := TDerBitString.GetOptional(AElement); -end; - -class function TAttributeCertificateInfo.ReadOptionalX509Extensions(AElement: IAsn1Encodable): IX509Extensions; -begin - Result := TX509Extensions.GetOptional(AElement); + FHolder := TAsn1Utilities.Read(ASeq, LPos, THolder.GetInstance); + FIssuer := TAsn1Utilities.Read(ASeq, LPos, TAttCertIssuer.GetInstance); + FSignature := TAsn1Utilities.Read(ASeq, LPos, TAlgorithmIdentifier.GetInstance); + FSerialNumber := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FAttrCertValidityPeriod := TAsn1Utilities.Read(ASeq, LPos, TAttCertValidityPeriod.GetInstance); + FAttributes := TAsn1Utilities.Read(ASeq, LPos, TAsn1Sequence.GetInstance); + FIssuerUniqueID := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerBitString.GetOptional); + FExtensions := TAsn1Utilities.ReadOptional(ASeq, LPos, TX509Extensions.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; function TAttributeCertificateInfo.GetVersion: IDerInteger; diff --git a/CryptoLib/src/Asn1/X509/ClpX509DsaAsn1Objects.pas b/CryptoLib/src/Asn1/X509/ClpX509DsaAsn1Objects.pas index 32123208..10b740ca 100644 --- a/CryptoLib/src/Asn1/X509/ClpX509DsaAsn1Objects.pas +++ b/CryptoLib/src/Asn1/X509/ClpX509DsaAsn1Objects.pas @@ -28,7 +28,8 @@ interface ClpAsn1Core, ClpIAsn1Core, ClpIX509DsaAsn1Objects, - ClpCryptoLibTypes; + ClpCryptoLibTypes, + ClpAsn1Utilities; resourcestring SBadSequenceSize = 'bad sequence size: %d'; @@ -106,17 +107,16 @@ function TDsaParameter.ToAsn1Object: IAsn1Object; end; constructor TDsaParameter.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; begin Inherited Create(); - if (ASeq.Count <> 3) then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, - [ASeq.Count]); - end; - - FP := TDerInteger.GetInstance(ASeq[0]); - FQ := TDerInteger.GetInstance(ASeq[1]); - FG := TDerInteger.GetInstance(ASeq[2]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 3); + FP := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FQ := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FG := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDsaParameter.Create(const AP, AQ, AG: TBigInteger); diff --git a/CryptoLib/src/Asn1/X509/ClpX509RsaAsn1Objects.pas b/CryptoLib/src/Asn1/X509/ClpX509RsaAsn1Objects.pas index b4a72369..c119a800 100644 --- a/CryptoLib/src/Asn1/X509/ClpX509RsaAsn1Objects.pas +++ b/CryptoLib/src/Asn1/X509/ClpX509RsaAsn1Objects.pas @@ -28,7 +28,8 @@ interface ClpAsn1Core, ClpIAsn1Core, ClpIX509RsaAsn1Objects, - ClpCryptoLibTypes; + ClpCryptoLibTypes, + ClpAsn1Utilities; resourcestring SBadSequenceSize = 'bad sequence size: %d'; @@ -125,19 +126,15 @@ class function TRsaPublicKeyStructure.GetTagged(const ATaggedObject: IAsn1Tagged constructor TRsaPublicKeyStructure.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - - LCount := ASeq.Count; - if LCount <> 2 then - begin - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - end; - + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); // Note: we are accepting technically incorrect (i.e. negative) values here - FModulus := TDerInteger.GetInstance(ASeq[0]).PositiveValue; - FPublicExponent := TDerInteger.GetInstance(ASeq[1]).PositiveValue; + FModulus := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).PositiveValue; + FPublicExponent := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).PositiveValue; + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TRsaPublicKeyStructure.Create(const AModulus, APublicExponent: TBigInteger); diff --git a/CryptoLib/src/Asn1/X9/ClpX9DHAsn1Objects.pas b/CryptoLib/src/Asn1/X9/ClpX9DHAsn1Objects.pas index cf7dc0d1..3b00c3b3 100644 --- a/CryptoLib/src/Asn1/X9/ClpX9DHAsn1Objects.pas +++ b/CryptoLib/src/Asn1/X9/ClpX9DHAsn1Objects.pas @@ -32,8 +32,6 @@ interface resourcestring SInvalidParameters = 'invalid parameters'; - SBadSequenceSize = 'bad sequence size: %d'; - SUnexpectedElementsInSequence = 'unexpected elements in sequence'; SSeedNil = 'seed cannot be nil'; SPGenCounterNil = 'PGenCounter cannot be nil'; SInvalidDHValidationParms = 'invalid DHValidationParms: %s'; @@ -127,8 +125,6 @@ TDomainParameters = class sealed(TAsn1Encodable, IDomainParameters) FP, FG, FQ, FJ: IDerInteger; FValidationParams: IValidationParams; - class function ReadOptionalSubgroupFactor(AElement: IAsn1Encodable): IDerInteger; static; - class function ReadOptionalValidationParams(AElement: IAsn1Encodable): IValidationParams; static; strict protected function GetP: IDerInteger; @@ -226,8 +222,6 @@ TDHDomainParameters = class(TAsn1Encodable, IDHDomainParameters) FP, FG, FQ, FJ: IDerInteger; FValidationParams: IValidationParams; - class function ReadOptionalSubgroupFactor(AElement: IAsn1Encodable): IDerInteger; static; - class function ReadOptionalValidationParams(AElement: IAsn1Encodable): IValidationParams; static; strict protected function GetP: IDerInteger; @@ -325,7 +319,6 @@ TOtherInfo = class(TAsn1Encodable, IOtherInfo) FPartyAInfo: IAsn1OctetString; FSuppPubInfo: IAsn1OctetString; - class function GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; static; strict protected function GetKeyInfo: IKeySpecificInfo; @@ -486,13 +479,15 @@ class function TValidationParams.GetTagged(const ATaggedObject: IAsn1TaggedObjec end; constructor TValidationParams.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; begin inherited Create(); - if ASeq.Count <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [ASeq.Count]); - - FSeed := TDerBitString.GetInstance(ASeq[0]); - FPgenCounter := TDerInteger.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FSeed := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + FPgenCounter := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TValidationParams.Create(const ASeed: IDerBitString; @@ -589,42 +584,19 @@ class function TDomainParameters.GetTagged(const ATaggedObject: IAsn1TaggedObjec Result := TDomainParameters.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TDomainParameters.ReadOptionalSubgroupFactor(AElement: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AElement); -end; - -class function TDomainParameters.ReadOptionalValidationParams(AElement: IAsn1Encodable): IValidationParams; -begin - Result := TValidationParams.GetOptional(AElement); -end; - constructor TDomainParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 5) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FP := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FG := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FQ := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FJ := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalSubgroupFactor); - - FValidationParams := TAsn1Utilities.ReadOptional(ASeq, LPos, - ReadOptionalValidationParams); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 5); + FP := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FG := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FQ := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FJ := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + FValidationParams := TAsn1Utilities.ReadOptional(ASeq, LPos, TValidationParams.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDomainParameters.Create(const AP, AG, AQ, AJ: IDerInteger; @@ -750,13 +722,15 @@ class function TDHValidationParms.GetTagged(const ATaggedObject: IAsn1TaggedObje end; constructor TDHValidationParms.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; begin inherited Create(); - if ASeq.Count <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [ASeq.Count]); - - FSeed := TDerBitString.GetInstance(ASeq[0]); - FPGenCounter := TDerInteger.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FSeed := TAsn1Utilities.Read(ASeq, LPos, TDerBitString.GetInstance); + FPGenCounter := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDHValidationParms.Create(const ASeed: IDerBitString; @@ -836,42 +810,19 @@ class function TDHDomainParameters.GetTagged(const ATaggedObject: IAsn1TaggedObj Result := TDHDomainParameters.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TDHDomainParameters.ReadOptionalSubgroupFactor(AElement: IAsn1Encodable): IDerInteger; -begin - Result := TDerInteger.GetOptional(AElement); -end; - -class function TDHDomainParameters.ReadOptionalValidationParams(AElement: IAsn1Encodable): IValidationParams; -begin - Result := TValidationParams.GetOptional(AElement); -end; - constructor TDHDomainParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 3) or (LCount > 5) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FP := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FG := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FQ := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FJ := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalSubgroupFactor); - - FValidationParams := TAsn1Utilities.ReadOptional(ASeq, LPos, - ReadOptionalValidationParams); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 3, 5); + FP := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FG := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FQ := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FJ := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerInteger.GetOptional); + FValidationParams := TAsn1Utilities.ReadOptional(ASeq, LPos, TValidationParams.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TDHDomainParameters.Create(const AP, AG, AQ, AJ: IDerInteger; @@ -1002,13 +953,15 @@ class function TKeySpecificInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject end; constructor TKeySpecificInfo.Create(const ASeq: IAsn1Sequence); +var + LPos: Int32; begin inherited Create(); - if ASeq.Count <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [ASeq.Count]); - - FAlgorithm := TDerObjectIdentifier.GetInstance(ASeq[0]); - FCounter := TAsn1OctetString.GetInstance(ASeq[1]); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FAlgorithm := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FCounter := TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TKeySpecificInfo.Create(const AAlgorithm: IDerObjectIdentifier; @@ -1088,32 +1041,19 @@ class function TOtherInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject; Result := TOtherInfo.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TOtherInfo.GetTaggedAsn1OctetString(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1OctetString; -begin - Result := TAsn1OctetString.GetTagged(ATagged, AState); -end; - constructor TOtherInfo.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 2) or (LCount > 3) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FKeyInfo := TKeySpecificInfo.GetInstance(ASeq[LPos]); - System.Inc(LPos); - - FPartyAInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, - GetTaggedAsn1OctetString); - - FSuppPubInfo := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 2, True, - GetTaggedAsn1OctetString); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); + FKeyInfo := TAsn1Utilities.Read(ASeq, LPos, TKeySpecificInfo.GetInstance); + FPartyAInfo := TAsn1Utilities.ReadOptionalContextTagged(ASeq, LPos, 0, True, + TAsn1OctetString.GetTagged); + FSuppPubInfo := TAsn1Utilities.ReadContextTagged(ASeq, LPos, 2, True, + TAsn1OctetString.GetTagged); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TOtherInfo.Create(const AKeyInfo: IKeySpecificInfo; diff --git a/CryptoLib/src/Asn1/X9/ClpX9ECAsn1Objects.pas b/CryptoLib/src/Asn1/X9/ClpX9ECAsn1Objects.pas index 8a8d3759..f92e3322 100644 --- a/CryptoLib/src/Asn1/X9/ClpX9ECAsn1Objects.pas +++ b/CryptoLib/src/Asn1/X9/ClpX9ECAsn1Objects.pas @@ -29,6 +29,7 @@ interface ClpIAsn1Core, ClpIX9ECAsn1Objects, ClpBigInteger, + ClpBigIntegerUtilities, ClpIECCommon, ClpIECFieldElement, ClpECAlgorithms, @@ -41,11 +42,8 @@ interface ClpECCurve; resourcestring - SBadSequenceSize = 'bad sequence size: %d'; - SUnexpectedElementsInSequence = 'unexpected elements in sequence'; SBadVersion = 'bad version in X9ECParameters'; SFieldIDNil = 'field ID cannot be nil'; - SSeqNil = 'sequence cannot be nil'; SCurveNil = 'curve cannot be nil'; SFieldElementNil = 'field element cannot be nil'; SCurveNotImplemented = 'this type of ECCurve is not implemented'; @@ -281,7 +279,7 @@ TX9ECParameters = class(TAsn1Encodable, IX9ECParameters) FN: TBigInteger; FH: TBigInteger; - class function ReadOptionalCofactor(AElement: IAsn1Encodable): TBigInteger; static; + class function ReadOptionalCofactor(const AElement: IAsn1Encodable): TBigInteger; static; strict protected function GetCurve: IECCurve; @@ -411,15 +409,14 @@ class function TX9FieldID.GetTagged(const ATaggedObject: IAsn1TaggedObject; constructor TX9FieldID.Create(const ASeq: IAsn1Sequence); var - LCount: Int32; + LPos: Int32; begin inherited Create(); - LCount := ASeq.Count; - if LCount <> 2 then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - FFieldType := TDerObjectIdentifier.GetInstance(ASeq[0]); - FParameters := ASeq[1].ToAsn1Object(); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 2); + FFieldType := TAsn1Utilities.Read(ASeq, LPos, TDerObjectIdentifier.GetInstance); + FParameters := TAsn1Utilities.ReadEncodable(ASeq, LPos).ToAsn1Object(); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; constructor TX9FieldID.Create(const APrimeP: TBigInteger); @@ -543,6 +540,7 @@ constructor TX9Curve.Create(const ACurve: IECCurve; const ASeed: IDerBitString); constructor TX9Curve.Create(const AFieldID: IX9FieldID; const AOrder, ACofactor: TBigInteger; const ASeq: IAsn1Sequence); var + LPos: Int32; LP: TBigInteger; LA, LB: TBigInteger; LParameters: IAsn1Sequence; @@ -554,16 +552,16 @@ constructor TX9Curve.Create(const AFieldID: IX9FieldID; const AOrder, ACofactor: inherited Create(); if AFieldID = nil then raise EArgumentNilCryptoLibException.CreateRes(@SFieldIDNil); - if ASeq = nil then - raise EArgumentNilCryptoLibException.CreateRes(@SSeqNil); + LPos := 0; + TAsn1Utilities.CheckSequenceSize(ASeq, 2, 3); FFieldType := AFieldID.FieldType; if TX9ObjectIdentifiers.PrimeField.Equals(FFieldType) then begin LP := TDerInteger.GetInstance(AFieldID.Parameters).Value; - LA := TBigInteger.Create(1, TAsn1OctetString.GetInstance(ASeq[0]).GetOctets()); - LB := TBigInteger.Create(1, TAsn1OctetString.GetInstance(ASeq[1]).GetOctets()); + LA := TBigIntegerUtilities.FromUnsignedByteArray(TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance).GetOctets()); + LB := TBigIntegerUtilities.FromUnsignedByteArray(TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance).GetOctets()); FCurve := TFpCurve.Create(LP, LA, LB, AOrder, ACofactor); end else if TX9ObjectIdentifiers.CharacteristicTwoField.Equals(FFieldType) then @@ -593,8 +591,8 @@ constructor TX9Curve.Create(const AFieldID: IX9FieldID; const AOrder, ACofactor: raise EArgumentCryptoLibException.CreateRes(@SCharacteristicTwoFieldNotImplemented); end; - LA := TBigInteger.Create(1, TAsn1OctetString.GetInstance(ASeq[0]).GetOctets()); - LB := TBigInteger.Create(1, TAsn1OctetString.GetInstance(ASeq[1]).GetOctets()); + LA := TBigIntegerUtilities.FromUnsignedByteArray(TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance).GetOctets()); + LB := TBigIntegerUtilities.FromUnsignedByteArray(TAsn1Utilities.Read(ASeq, LPos, TAsn1OctetString.GetInstance).GetOctets()); FCurve := TF2mCurve.Create(LM, LK1, LK2, LK3, LA, LB, AOrder, ACofactor); end else @@ -602,10 +600,8 @@ constructor TX9Curve.Create(const AFieldID: IX9FieldID; const AOrder, ACofactor: raise EArgumentCryptoLibException.CreateRes(@SCurveNotImplemented); end; - if ASeq.Count = 3 then - begin - FSeed := TDerBitString.GetInstance(ASeq[2]); - end; + FSeed := TAsn1Utilities.ReadOptional(ASeq, LPos, TDerBitString.GetOptional); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); end; function TX9Curve.GetCurve: IECCurve; @@ -775,7 +771,7 @@ class function TX9ECParameters.GetTagged(const ATaggedObject: IAsn1TaggedObject; Result := FromSequence(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit)); end; -class function TX9ECParameters.ReadOptionalCofactor(AElement: IAsn1Encodable): TBigInteger; +class function TX9ECParameters.ReadOptionalCofactor(const AElement: IAsn1Encodable): TBigInteger; var LDerInt: IDerInteger; begin @@ -793,32 +789,22 @@ class function TX9ECParameters.FromSequence(const ASeq: IAsn1Sequence): IX9ECPar constructor TX9ECParameters.Create(const ASeq: IAsn1Sequence); var - LCount, LPos: Int32; + LPos: Int32; LVersion: IDerInteger; LX9CurveSequence: IAsn1Sequence; LP: IAsn1Encodable; LX9ECPoint: IX9ECPoint; begin inherited Create(); - LCount := ASeq.Count; LPos := 0; - if (LCount < 5) or (LCount > 6) then - raise EArgumentCryptoLibException.CreateResFmt(@SBadSequenceSize, [LCount]); - - LVersion := TDerInteger.GetInstance(ASeq[LPos]); - System.Inc(LPos); - FFieldID := TX9FieldID.GetInstance(ASeq[LPos]); - System.Inc(LPos); - LX9CurveSequence := TAsn1Sequence.GetInstance(ASeq[LPos]); - System.Inc(LPos); - LP := ASeq[LPos]; - System.Inc(LPos); - FN := (TDerInteger.GetInstance(ASeq[LPos]) as IDerInteger).Value; - System.Inc(LPos); + TAsn1Utilities.CheckSequenceSize(ASeq, 5, 6); + LVersion := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance); + FFieldID := TAsn1Utilities.Read(ASeq, LPos, TX9FieldID.GetInstance); + LX9CurveSequence := TAsn1Utilities.Read(ASeq, LPos, TAsn1Sequence.GetInstance); + LP := TAsn1Utilities.ReadEncodable(ASeq, LPos); + FN := TAsn1Utilities.Read(ASeq, LPos, TDerInteger.GetInstance).Value; FH := TAsn1Utilities.ReadOptional(ASeq, LPos, ReadOptionalCofactor); - - if LPos <> LCount then - raise EArgumentCryptoLibException.CreateRes(@SUnexpectedElementsInSequence); + TAsn1Utilities.RequireEndOfSequence(ASeq, LPos); if not LVersion.HasValue(1) then raise EArgumentCryptoLibException.CreateRes(@SBadVersion);