Skip to content

Harden ASN.1 sequence parsing with cursor helpers; consolidate block-cipher test scaffolding#138

Merged
Xor-el merged 3 commits into
masterfrom
enhancements/cursor-refactorings
Jul 8, 2026
Merged

Harden ASN.1 sequence parsing with cursor helpers; consolidate block-cipher test scaffolding#138
Xor-el merged 3 commits into
masterfrom
enhancements/cursor-refactorings

Conversation

@Xor-el

@Xor-el Xor-el commented Jul 8, 2026

Copy link
Copy Markdown
Owner

ASN.1 sequence parsing

  • Adds bounds-guarded cursor helpers on TAsn1Utilities: CheckSequenceSize, ReadEncodable, Read<T>, ReadOptional<T>, tagged/context-tagged variants, and RequireEndOfSequence
  • Truncated sequences now raise EArgumentCryptoLibException (SPrematureEndOfSequence) instead of raw index errors; trailing elements are rejected (SUnexpectedElementsInSequence)
  • Migrates PKCS, X509, CMS, X9, Sec, and X500 ASN.1 constructors to the cursor pattern, matching upstream Asn1Utilities.Read(seq, ref pos, T.GetInstance)
  • Introduces TAsn1Constructor / TAsn1TaggedConstructor so T.GetInstance, T.GetOptional, and T.GetTagged bind directly — no per-type forwarder wrappers and no @ workarounds
  • Removes 37 dead per-class reader/optional wrappers
  • Adds Asn1SequenceCursorTests (9 edge-case tests)

Block-cipher test consolidation

  • Adds shared BlockCipherTestBase.pas with TBlockCipherFactory and TBlockCipherTestBase
  • Refactors AES and Speck suites (plus CBC/ECB/SIC bulk-parity tests) onto hook-based inheritance, removing duplicated vector/Monte Carlo scaffolding

Xor-el added 3 commits July 8, 2026 11:36
Route every Asn1Sequence element read through cursor helpers on
TAsn1Utilities so short/malformed sequences fail cleanly instead of throwing
raw index errors or silently ignoring trailing elements.

Cursor helpers (TAsn1Utilities, threading `var ASequencePosition`):
- CheckSequenceSize    - nil + min/max size guard (shared SBadSequenceSize)
- ReadEncodable        - bounds-guarded mandatory read (SPrematureEndOfSequence)
- Read<T>              - ReadEncodable + T.GetInstance
- ReadOptional<T>      - peek; advance only if the constructor returns non-nil
- Read/ReadContext/ReadOptional*Tagged, TryReadOptional*Tagged
- RequireEndOfSequence - reject trailing elements (SUnexpectedElementsInSequence)

A truncated sequence now raises EArgumentCryptoLibException instead of a raw
index error, and unexpected trailing elements are rejected.

Add const-first-arg function pointer types TCryptoLibConstFunc<T1,TResult> and
<T1,T2,TResult> in ClpCryptoLibTypes so T.GetInstance / T.GetOptional /
T.GetTagged bind directly, eliminating per-type forwarder wrappers.

Migrate all 13 ASN.1 object units to the cursor helpers and remove 37 now-dead
per-class reader/optional wrappers.

Add Asn1SequenceCursorTests (9 edge-case tests)
Consolidate the AES, Speck, and bulk-parity test suites around a single
engine-factory type and a common base class, removing duplicated scaffolding
and making new engine suites cheap to add.

New CryptoLib.Tests/src/Crypto/BlockCipherTestBase.pas:
- TBlockCipherFactory = function: IBlockCipher — one canonical factory type
  replacing the generic TCryptoLibFunc<...> and three private nested
  TEngineFactory declarations.
- TBlockCipherTestBase: engine-agnostic scaffolding inherited by every
  block-cipher suite — DoBlockCipherVectorTest (previously byte-duplicated in
  the AES and Speck bases), the data-driven RunBlockCipherVectorTests, plus the
  generic IBlockCipher contract checks AssertEngineRejectsBadParameters and
  RunCipherEngineChecks.

TAesBlockCipherTestBase now derives from TBlockCipherTestBase and keeps only
AES-specific pieces: known-answer + Monte-Carlo vectors, DoBlockCipherMonteCarloTest,
and the published contract-test trio (TestBlockCipherVector / TestMonteCarloAES /
TestBadParameters) driven by GetEngineFactory / EngineLabel / EngineSupported
hooks (EngineSupported defaults True).

AesHardwareEngineTests, AESTests, and AesLightTests inherit those published
tests via the hooks instead of hand-writing delegating bodies; the hardware
suite also drops its local TEngineFactory and gains a guarded TestBadParameters.

TSpeckBlockCipherTestBase derives from TBlockCipherTestBase, dropping its
duplicated DoBlockCipherVectorTest and its two byte-identical vector runners
(now a single inherited runner); Speck factory functions return IBlockCipher.

Cbc/Ecb/Sic bulk-parity suites use the shared TBlockCipherFactory.
The sequence-cursor helpers in ClpAsn1Utilities were the only users of the
general-purpose TCryptoLibConstFunc<> family in ClpCryptoLibTypes. Move those
callbacks next to their sole consumer and give them intent-revealing names, so
ClpCryptoLibTypes stays usage-neutral and the helper signatures self-document.

- Remove TCryptoLibConstFunc<T1,TResult> and <T1,T2,TResult> from
  ClpCryptoLibTypes.
- Add to ClpAsn1Utilities:
    TAsn1Constructor<TInput, TResult> = function(const AElement: TInput): TResult;
    TAsn1TaggedConstructor<TResult>   = function(const ATagged: IAsn1TaggedObject;
                                                 ADeclaredExplicit: Boolean): TResult;
  The const first argument still binds the ARC-const T.GetInstance /
  T.GetOptional / T.GetTagged statics directly (no wrappers).

Collapse the vestigial generic state on the tagged cursor helpers: every call
site only ever passed Boolean (the declaredExplicit flag), so drop the <TState>
parameter and take ADeclaredExplicit: Boolean directly. Read/ReadOptional keep
TAsn1Constructor<TInput,TResult>; ReadTagged/ReadContextTagged/
ReadOptional(Context)Tagged/TryReadOptional(Context)Tagged move from
<TState,TResult> to <TResult>. Tagged call sites across the ASN.1 object units
and Asn1SequenceCursorTests shed the now-redundant "Boolean," generic argument
(e.g. ReadOptionalContextTagged<Boolean, IAsn1Set> -> <IAsn1Set>).

Element-level GetOptionalContextTagged / TryGetOptionalContextTagged are
unchanged (they keep TCryptoLibFunc<...,TState,TResult>).
@Xor-el Xor-el merged commit de579f3 into master Jul 8, 2026
24 checks passed
@Xor-el Xor-el deleted the enhancements/cursor-refactorings branch July 8, 2026 12:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant