Przeglądaj źródła

add some cms support

Ugochukwu Mmaduekwe 8 godzin temu
rodzic
commit
0cd0885da6

+ 5 - 0
CryptoLib.Tests/Delphi.Tests/CryptoLib.Tests.dpr

@@ -493,6 +493,11 @@ uses
   ClpX962NamedCurves in '..\..\CryptoLib\src\Asn1\X9\ClpX962NamedCurves.pas',
   ClpX509NameBuilder in '..\..\CryptoLib\src\X509\ClpX509NameBuilder.pas',
   ClpIX509NameBuilder in '..\..\CryptoLib\src\Interfaces\X509\ClpIX509NameBuilder.pas',
+  ClpCmsAsn1Objects in '..\..\CryptoLib\src\Asn1\Cms\ClpCmsAsn1Objects.pas',
+  ClpCmsObjectIdentifiers in '..\..\CryptoLib\src\Asn1\Cms\ClpCmsObjectIdentifiers.pas',
+  ClpCmsParsers in '..\..\CryptoLib\src\Asn1\Cms\ClpCmsParsers.pas',
+  ClpICmsAsn1Objects in '..\..\CryptoLib\src\Interfaces\Asn1\Cms\ClpICmsAsn1Objects.pas',
+  ClpICmsParsers in '..\..\CryptoLib\src\Interfaces\Asn1\Cms\ClpICmsParsers.pas',
   ClpFixedSecureRandom in '..\src\Utils\ClpFixedSecureRandom.pas',
   ClpShortenedDigest in '..\src\Utils\ClpShortenedDigest.pas',
   BlowfishTestVectors in '..\src\Crypto\BlowfishTestVectors.pas',

+ 12 - 15
CryptoLib.Tests/src/Others/CertTests.pas

@@ -75,9 +75,9 @@ uses
   ClpAsn1Comparers,
   ClpIX509NameBuilder,
   ClpX509NameBuilder,
-  ClpPkcsObjectIdentifiers,
-  ClpPkcsAsn1Objects,
-  ClpIPkcsAsn1Objects,
+  ClpCmsObjectIdentifiers,
+  ClpCmsAsn1Objects,
+  ClpICmsAsn1Objects,
   ClpX509Extension,
   ClpEncoders,
   ClpX9ObjectIdentifiers,
@@ -1762,9 +1762,8 @@ end;
 procedure TCertTest.Pkcs7Test;
 var
   LRootCertBin, LRootCrlBin, LAttrCert: TCryptoLibByteArray;
-  LDataOid: IDerObjectIdentifier;
-  LContentInfo: IContentInfo;
-  LSigData: IPkcsSignedData;
+  LContentInfo: ICmsContentInfo;
+  LSigData: ICmsSignedData;
   LCertSet, LCrlSet: IAsn1Set;
   LTaggedAttr: IAsn1Encodable;
   LInfoEnc: TCryptoLibByteArray;
@@ -2114,21 +2113,19 @@ begin
   LRootCrlBin := DecodeBase64(RootCrlB64);
   LAttrCert := DecodeBase64(AttrCertB64);
 
-  LDataOid := TPkcsObjectIdentifiers.Data;
-  LContentInfo := TContentInfo.Create(LDataOid, nil);
+  LContentInfo := TCmsContentInfo.Create(TCmsObjectIdentifiers.Data, nil);
   LRootCertObj := TAsn1Object.FromByteArray(LRootCertBin) as IAsn1Encodable;
   LTaggedAttr := TDerTaggedObject.Create(False, 2, TAsn1Object.FromByteArray(LAttrCert) as IAsn1Encodable);
   LCertSet := TDerSet.Create([LRootCertObj, LTaggedAttr]);
   LRootCrlObj := TAsn1Object.FromByteArray(LRootCrlBin) as IAsn1Encodable;
   LCrlSet := TDerSet.Create(LRootCrlObj);
-  LSigData := TPkcsSignedData.Create(
-    TDerInteger.One,
+  LSigData := TCmsSignedData.Create(
     TDerSet.Empty,
     LContentInfo,
     LCertSet,
     LCrlSet,
     TDerSet.Empty);
-  LContentInfo := TContentInfo.Create(TPkcsObjectIdentifiers.SignedData, LSigData);
+  LContentInfo := TCmsContentInfo.Create(TCmsObjectIdentifiers.SignedData, LSigData);
   LInfoEnc := LContentInfo.GetEncoded();
 
   LCertParser := TX509CertificateParser.Create;
@@ -2151,8 +2148,8 @@ begin
     Fail('PKCS7 crl collection not right');
 
   { empty certs and crls }
-  LSigData := TPkcsSignedData.Create(TDerInteger.One, TDerSet.Empty, LContentInfo, TDerSet.Empty, TDerSet.Empty, TDerSet.Empty);
-  LContentInfo := TContentInfo.Create(TPkcsObjectIdentifiers.SignedData, LSigData);
+  LSigData := TCmsSignedData.Create(TDerSet.Empty, LContentInfo, TDerSet.Empty, TDerSet.Empty, TDerSet.Empty);
+  LContentInfo := TCmsContentInfo.Create(TCmsObjectIdentifiers.SignedData, LSigData);
   LInfoEnc := LContentInfo.GetEncoded();
   LCert := LCertParser.ReadCertificate(LInfoEnc);
   if LCert <> nil then
@@ -2162,8 +2159,8 @@ begin
     Fail('PKCS7 crl present');
 
   { absent certs and crls - use nil for optional }
-  LSigData := TPkcsSignedData.Create(TDerInteger.One, TDerSet.Empty, TContentInfo.Create(LDataOid, nil), nil, nil, TDerSet.Empty);
-  LContentInfo := TContentInfo.Create(TPkcsObjectIdentifiers.SignedData, LSigData);
+  LSigData := TCmsSignedData.Create(TDerSet.Empty, TCmsContentInfo.Create(TCmsObjectIdentifiers.Data, nil) as ICmsContentInfo, nil, nil, TDerSet.Empty);
+  LContentInfo := TCmsContentInfo.Create(TCmsObjectIdentifiers.SignedData, LSigData);
   LInfoEnc := LContentInfo.GetEncoded();
   LCert := LCertParser.ReadCertificate(LInfoEnc);
   if LCert <> nil then

+ 1029 - 0
CryptoLib/src/Asn1/Cms/ClpCmsAsn1Objects.pas

@@ -0,0 +1,1029 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  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     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpCmsAsn1Objects;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Objects,
+  ClpAsn1Tags,
+  ClpAsn1Core,
+  ClpAsn1Utilities,
+  ClpIAsn1Objects,
+  ClpIAsn1Core,
+  ClpICmsAsn1Objects,
+  ClpCmsObjectIdentifiers,
+  ClpIX509Asn1Objects,
+  ClpX509Asn1Objects,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SCmsBadSequenceSize = 'Bad sequence size: %d';
+  SCmsBadIssuerAndSerialNumberSize = 'Bad sequence size: %d';
+  SCmsBadSignerInfoSequenceSize = 'Bad sequence size: %d';
+  SCmsUnexpectedElementsInSequence = 'Unexpected elements in sequence';
+
+type
+  /// <summary>
+  /// CMS ContentInfo (EncapsulatedContentInfo); supports DL/BER encoding choice.
+  /// </summary>
+  TCmsContentInfo = class(TAsn1Encodable, ICmsContentInfo)
+  strict private
+  var
+    FContentType: IDerObjectIdentifier;
+    FContent: IAsn1Encodable;
+    FIsDefiniteLength: Boolean;
+
+  strict private
+    function IsDLSequence(const ASeq: IAsn1Sequence): Boolean;
+    function IsDLSequenceObj(const AAsn1Object: IAsn1Object): Boolean;
+    function IsDLOctetString(const AAsn1Object: IAsn1Object): Boolean;
+    function IsDLContent(const AContent: IAsn1Encodable): Boolean;
+
+  strict protected
+    function GetContentType: IDerObjectIdentifier;
+    function GetContent: IAsn1Encodable;
+    function GetIsDefiniteLength: Boolean;
+
+  public
+    class function GetInstance(AObj: TObject): ICmsContentInfo; overload; static;
+    class function GetInstance(const AObj: IAsn1Convertible): ICmsContentInfo; overload; static;
+    class function GetInstance(const AEncoded: TCryptoLibByteArray): ICmsContentInfo; overload; static;
+    class function GetInstance(const AObj: IAsn1TaggedObject;
+      AExplicitly: Boolean): ICmsContentInfo; overload; static;
+    class function GetTagged(const ATaggedObject: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsContentInfo; static;
+
+    constructor Create(const ASeq: IAsn1Sequence); overload;
+    constructor Create(const AContentType: IDerObjectIdentifier;
+      const AContent: IAsn1Encodable); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property ContentType: IDerObjectIdentifier read GetContentType;
+    property Content: IAsn1Encodable read GetContent;
+    property IsDefiniteLength: Boolean read GetIsDefiniteLength;
+  end;
+
+  /// <summary>
+  /// CMS IssuerAndSerialNumber (issuer Name + serialNumber).
+  /// </summary>
+  TCmsIssuerAndSerialNumber = class(TAsn1Encodable, ICmsIssuerAndSerialNumber)
+  strict private
+  var
+    FIssuer: IX509Name;
+    FSerialNumber: IDerInteger;
+
+  strict protected
+    function GetIssuer: IX509Name;
+    function GetSerialNumber: IDerInteger;
+
+  public
+    class function GetInstance(AObj: TObject): ICmsIssuerAndSerialNumber; overload; static;
+    class function GetInstance(const AObj: IAsn1Convertible): ICmsIssuerAndSerialNumber; overload; static;
+    class function GetInstance(const AObj: IAsn1TaggedObject;
+      AExplicitly: Boolean): ICmsIssuerAndSerialNumber; overload; static;
+    class function GetOptional(const AElement: IAsn1Encodable): ICmsIssuerAndSerialNumber; static;
+    class function GetTagged(const ATaggedObject: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsIssuerAndSerialNumber; static;
+
+    constructor Create(const ASeq: IAsn1Sequence); overload;
+    constructor Create(const AIssuer: IX509Name; const ASerialNumber: IDerInteger); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property Issuer: IX509Name read GetIssuer;
+    property SerialNumber: IDerInteger read GetSerialNumber;
+  end;
+
+  /// <summary>
+  /// CMS SignerIdentifier (CHOICE: IssuerAndSerialNumber or [0] SubjectKeyIdentifier).
+  /// </summary>
+  TCmsSignerIdentifier = class(TAsn1Encodable, ICmsSignerIdentifier)
+  strict private
+  var
+    FId: IAsn1Encodable;
+
+  strict protected
+    function GetIsTagged: Boolean;
+    function GetID: IAsn1Encodable;
+
+  public
+    class function GetInstance(AObj: TObject): ICmsSignerIdentifier; overload; static;
+    class function GetInstance(const AObj: IAsn1Convertible): ICmsSignerIdentifier; overload; static;
+    class function GetInstance(const AObj: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsSignerIdentifier; overload; static;
+    class function GetOptional(const AElement: IAsn1Encodable): ICmsSignerIdentifier; static;
+    class function GetTagged(const ATaggedObject: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsSignerIdentifier; static;
+
+    constructor Create(const AIssuerAndSerialNumber: ICmsIssuerAndSerialNumber); overload;
+    constructor Create(const ASubjectKeyIdentifier: IAsn1OctetString); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property IsTagged: Boolean read GetIsTagged;
+    property ID: IAsn1Encodable read GetID;
+  end;
+
+  /// <summary>
+  /// CMS SignerInfo (per-signer information in SignedData).
+  /// </summary>
+  TCmsSignerInfo = class(TAsn1Encodable, ICmsSignerInfo)
+  strict private
+  var
+    FVersion: IDerInteger;
+    FSignerID: ICmsSignerIdentifier;
+    FDigestAlgorithm: IAlgorithmIdentifier;
+    FSignedAttrs: IAsn1Set;
+    FSignatureAlgorithm: IAlgorithmIdentifier;
+    FSignature: IAsn1OctetString;
+    FUnsignedAttrs: IAsn1Set;
+
+  strict protected
+    function GetVersion: IDerInteger;
+    function GetSignerID: ICmsSignerIdentifier;
+    function GetDigestAlgorithm: IAlgorithmIdentifier;
+    function GetSignedAttrs: IAsn1Set;
+    function GetSignatureAlgorithm: IAlgorithmIdentifier;
+    function GetSignature: IAsn1OctetString;
+    function GetUnsignedAttrs: IAsn1Set;
+
+  public
+    class function GetInstance(AObj: TObject): ICmsSignerInfo; overload; static;
+    class function GetInstance(const AObj: IAsn1Convertible): ICmsSignerInfo; overload; static;
+    class function GetInstance(const AObj: IAsn1TaggedObject;
+      AExplicitly: Boolean): ICmsSignerInfo; overload; static;
+    class function GetTagged(const ATaggedObject: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsSignerInfo; static;
+
+    constructor Create(const ASeq: IAsn1Sequence); overload;
+    constructor Create(const ASignerID: ICmsSignerIdentifier;
+      const ADigestAlgorithm: IAlgorithmIdentifier; const ASignedAttrs: IAsn1Set;
+      const ASignatureAlgorithm: IAlgorithmIdentifier; const ASignature: IAsn1OctetString;
+      const AUnsignedAttrs: IAsn1Set); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property Version: IDerInteger read GetVersion;
+    property SignerID: ICmsSignerIdentifier read GetSignerID;
+    property DigestAlgorithm: IAlgorithmIdentifier read GetDigestAlgorithm;
+    property SignedAttrs: IAsn1Set read GetSignedAttrs;
+    property SignatureAlgorithm: IAlgorithmIdentifier read GetSignatureAlgorithm;
+    property Signature: IAsn1OctetString read GetSignature;
+    property UnsignedAttrs: IAsn1Set read GetUnsignedAttrs;
+  end;
+
+  /// <summary>
+  /// CMS SignedData (RFC 3852).
+  /// </summary>
+  TCmsSignedData = class(TAsn1Encodable, ICmsSignedData)
+  strict private
+  var
+    FVersion: IDerInteger;
+    FDigestAlgorithms: IAsn1Set;
+    FEncapContentInfo: ICmsContentInfo;
+    FCertificates: IAsn1Set;
+    FCrls: IAsn1Set;
+    FSignerInfos: IAsn1Set;
+    FCertsBer: Boolean;
+    FCrlsBer: Boolean;
+    FDigsBer: Boolean;
+    FSigsBer: Boolean;
+
+  strict private
+    class function ReadOptionalTaggedSet(const ASequence: IAsn1Sequence;
+      var ASequencePosition: Int32; ATagNo: Int32; out AIsBer: Boolean): IAsn1Set; static;
+    class function CalculateVersionField(const AContentOid: IDerObjectIdentifier;
+      const ACerts, ACrls, ASignerInfs: IAsn1Set): IDerInteger; static;
+    class function HasV3SignerInfos(const ASignerInfs: IAsn1Set): Boolean; static;
+
+  strict protected
+    function GetVersion: IDerInteger;
+    function GetDigestAlgorithms: IAsn1Set;
+    function GetEncapContentInfo: ICmsContentInfo;
+    function GetCertificates: IAsn1Set;
+    function GetCrls: IAsn1Set;
+    function GetSignerInfos: IAsn1Set;
+
+  public
+    class function GetInstance(AObj: TObject): ICmsSignedData; overload; static;
+    class function GetInstance(const AObj: IAsn1Convertible): ICmsSignedData; overload; static;
+    class function GetInstance(const AEncoded: TCryptoLibByteArray): ICmsSignedData; overload; static;
+    class function GetInstance(const AObj: IAsn1TaggedObject;
+      AExplicitly: Boolean): ICmsSignedData; overload; static;
+    class function GetTagged(const ATaggedObject: IAsn1TaggedObject;
+      ADeclaredExplicit: Boolean): ICmsSignedData; static;
+
+    constructor Create(const ASeq: IAsn1Sequence); overload;
+    constructor Create(const ADigestAlgorithms: IAsn1Set; const AEncapContentInfo: ICmsContentInfo;
+      const ACertificates, ACrls, ASignerInfos: IAsn1Set); overload;
+
+    function ToAsn1Object: IAsn1Object; override;
+
+    property Version: IDerInteger read GetVersion;
+    property DigestAlgorithms: IAsn1Set read GetDigestAlgorithms;
+    property EncapContentInfo: ICmsContentInfo read GetEncapContentInfo;
+    property Certificates: IAsn1Set read GetCertificates;
+    property Crls: IAsn1Set read GetCrls;
+    property SignerInfos: IAsn1Set read GetSignerInfos;
+  end;
+
+implementation
+
+{ TCmsContentInfo }
+
+class function TCmsContentInfo.GetInstance(AObj: TObject): ICmsContentInfo;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if Supports(AObj, ICmsContentInfo, Result) then
+    Exit;
+
+  Result := TCmsContentInfo.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsContentInfo.GetInstance(const AObj: IAsn1Convertible): ICmsContentInfo;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  if Supports(AObj, ICmsContentInfo, Result) then
+    Exit;
+
+  Result := TCmsContentInfo.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsContentInfo.GetInstance(const AEncoded: TCryptoLibByteArray): ICmsContentInfo;
+begin
+  if AEncoded = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+
+  Result := TCmsContentInfo.Create(TAsn1Sequence.GetInstance(AEncoded));
+end;
+
+class function TCmsContentInfo.GetInstance(const AObj: IAsn1TaggedObject;
+  AExplicitly: Boolean): ICmsContentInfo;
+begin
+  Result := TCmsContentInfo.Create(TAsn1Sequence.GetInstance(AObj, AExplicitly));
+end;
+
+class function TCmsContentInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsContentInfo;
+begin
+  Result := TCmsContentInfo.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit));
+end;
+
+function TCmsContentInfo.IsDLSequence(const ASeq: IAsn1Sequence): Boolean;
+var
+  LObj: IAsn1Object;
+begin
+  if ASeq = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+  LObj := ASeq as IAsn1Object;
+  Result := Supports(LObj, IDLSequence);
+end;
+
+function TCmsContentInfo.IsDLSequenceObj(const AAsn1Object: IAsn1Object): Boolean;
+begin
+  Result := (AAsn1Object <> nil) and Supports(AAsn1Object, IDLSequence);
+end;
+
+function TCmsContentInfo.IsDLOctetString(const AAsn1Object: IAsn1Object): Boolean;
+begin
+  Result := (AAsn1Object <> nil) and Supports(AAsn1Object, IDerOctetString);
+end;
+
+function TCmsContentInfo.IsDLContent(const AContent: IAsn1Encodable): Boolean;
+var
+  LObj: IAsn1Object;
+begin
+  if AContent = nil then
+  begin
+    Result := True;
+    Exit;
+  end;
+  LObj := AContent.ToAsn1Object();
+  Result := IsDLOctetString(LObj) or IsDLSequenceObj(LObj);
+end;
+
+constructor TCmsContentInfo.Create(const ASeq: IAsn1Sequence);
+var
+  LCount: Int32;
+  LTagged: IAsn1TaggedObject;
+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
+  begin
+    LTagged := TAsn1TaggedObject.GetInstance(ASeq[1], TAsn1Tags.ContextSpecific, 0);
+    FContent := LTagged.GetExplicitBaseObject();
+  end
+  else
+    FContent := nil;
+
+  FIsDefiniteLength := IsDLSequence(ASeq);
+end;
+
+constructor TCmsContentInfo.Create(const AContentType: IDerObjectIdentifier;
+  const AContent: IAsn1Encodable);
+begin
+  Inherited Create();
+  if AContentType = nil then
+    raise EArgumentNilCryptoLibException.Create('contentType');
+  FContentType := AContentType;
+  FContent := AContent;
+  FIsDefiniteLength := IsDLContent(AContent);
+end;
+
+function TCmsContentInfo.GetContentType: IDerObjectIdentifier;
+begin
+  Result := FContentType;
+end;
+
+function TCmsContentInfo.GetContent: IAsn1Encodable;
+begin
+  Result := FContent;
+end;
+
+function TCmsContentInfo.GetIsDefiniteLength: Boolean;
+begin
+  Result := FIsDefiniteLength;
+end;
+
+function TCmsContentInfo.ToAsn1Object: IAsn1Object;
+begin
+  if FIsDefiniteLength then
+  begin
+    if FContent = nil then
+      Result := TDLSequence.Create(FContentType)
+    else
+      Result := TDLSequence.Create(FContentType, TDLTaggedObject.Create(0, FContent) as IDLTaggedObject);
+  end
+  else
+  begin
+    if FContent = nil then
+      Result := TBerSequence.Create(FContentType)
+    else
+      Result := TBerSequence.Create(FContentType, TBerTaggedObject.Create(True, 0, FContent) AS IBerTaggedObject);
+  end;
+end;
+
+{ TCmsIssuerAndSerialNumber }
+
+class function TCmsIssuerAndSerialNumber.GetInstance(AObj: TObject): ICmsIssuerAndSerialNumber;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsIssuerAndSerialNumber, Result) then
+    Exit;
+  Result := TCmsIssuerAndSerialNumber.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsIssuerAndSerialNumber.GetInstance(const AObj: IAsn1Convertible): ICmsIssuerAndSerialNumber;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsIssuerAndSerialNumber, Result) then
+    Exit;
+  Result := TCmsIssuerAndSerialNumber.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsIssuerAndSerialNumber.GetInstance(const AObj: IAsn1TaggedObject;
+  AExplicitly: Boolean): ICmsIssuerAndSerialNumber;
+begin
+  Result := TCmsIssuerAndSerialNumber.Create(TAsn1Sequence.GetInstance(AObj, AExplicitly));
+end;
+
+class function TCmsIssuerAndSerialNumber.GetOptional(const AElement: IAsn1Encodable): ICmsIssuerAndSerialNumber;
+var
+  LSeq: IAsn1Sequence;
+begin
+  if AElement = nil then
+    raise EArgumentNilCryptoLibException.Create('element');
+  if Supports(AElement, ICmsIssuerAndSerialNumber, Result) then
+    Exit;
+  LSeq := TAsn1Sequence.GetOptional(AElement);
+  if LSeq <> nil then
+  begin
+    Result := TCmsIssuerAndSerialNumber.Create(LSeq);
+    Exit;
+  end;
+  Result := nil;
+end;
+
+class function TCmsIssuerAndSerialNumber.GetTagged(const ATaggedObject: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsIssuerAndSerialNumber;
+begin
+  Result := TCmsIssuerAndSerialNumber.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit));
+end;
+
+constructor TCmsIssuerAndSerialNumber.Create(const ASeq: IAsn1Sequence);
+var
+  LCount: Int32;
+begin
+  Inherited Create();
+  LCount := ASeq.Count;
+  if LCount <> 2 then
+    raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadIssuerAndSerialNumberSize, [LCount]);
+  FIssuer := TX509Name.GetInstance(ASeq[0]);
+  FSerialNumber := TDerInteger.GetInstance(ASeq[1]);
+end;
+
+constructor TCmsIssuerAndSerialNumber.Create(const AIssuer: IX509Name; const ASerialNumber: IDerInteger);
+begin
+  Inherited Create();
+  if AIssuer = nil then
+    raise EArgumentNilCryptoLibException.Create('issuer');
+  if ASerialNumber = nil then
+    raise EArgumentNilCryptoLibException.Create('serialNumber');
+  FIssuer := AIssuer;
+  FSerialNumber := ASerialNumber;
+end;
+
+function TCmsIssuerAndSerialNumber.GetIssuer: IX509Name;
+begin
+  Result := FIssuer;
+end;
+
+function TCmsIssuerAndSerialNumber.GetSerialNumber: IDerInteger;
+begin
+  Result := FSerialNumber;
+end;
+
+function TCmsIssuerAndSerialNumber.ToAsn1Object: IAsn1Object;
+begin
+  Result := TDerSequence.Create([FIssuer, FSerialNumber]);
+end;
+
+{ TCmsSignerIdentifier }
+
+class function TCmsSignerIdentifier.GetInstance(AObj: TObject): ICmsSignerIdentifier;
+begin
+  Result := TAsn1Utilities.GetInstanceChoice<ICmsSignerIdentifier>(AObj,
+    function(AElement: IAsn1Encodable): ICmsSignerIdentifier
+    begin
+      Result := GetOptional(AElement);
+    end);
+end;
+
+class function TCmsSignerIdentifier.GetInstance(const AObj: IAsn1Convertible): ICmsSignerIdentifier;
+var
+  LObj: IAsn1Object;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  LObj := AObj.ToAsn1Object();
+  Result := TAsn1Utilities.GetInstanceChoice<ICmsSignerIdentifier>(LObj,
+    function(AElement: IAsn1Encodable): ICmsSignerIdentifier
+    begin
+      Result := GetOptional(AElement);
+    end);
+end;
+
+class function TCmsSignerIdentifier.GetInstance(const AObj: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsSignerIdentifier;
+begin
+  Result := TAsn1Utilities.GetInstanceChoice<ICmsSignerIdentifier>(AObj, ADeclaredExplicit,
+    function(AElement: IAsn1Encodable): ICmsSignerIdentifier
+    begin
+      Result := GetOptional(AElement);
+    end);
+end;
+
+class function TCmsSignerIdentifier.GetOptional(const AElement: IAsn1Encodable): ICmsSignerIdentifier;
+var
+  LIssuerAndSerial: ICmsIssuerAndSerialNumber;
+  LTagged: IAsn1TaggedObject;
+begin
+  if AElement = nil then
+    raise EArgumentNilCryptoLibException.Create('element');
+  if Supports(AElement, ICmsSignerIdentifier, Result) then
+    Exit;
+  LIssuerAndSerial := TCmsIssuerAndSerialNumber.GetOptional(AElement);
+  if LIssuerAndSerial <> nil then
+  begin
+    Result := TCmsSignerIdentifier.Create(LIssuerAndSerial);
+    Exit;
+  end;
+  LTagged := TAsn1TaggedObject.GetOptional(AElement);
+  if (LTagged <> nil) and LTagged.HasContextTag(0) then
+  begin
+    Result := TCmsSignerIdentifier.Create(TAsn1OctetString.GetTagged(LTagged, False));
+    Exit;
+  end;
+  Result := nil;
+end;
+
+class function TCmsSignerIdentifier.GetTagged(const ATaggedObject: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsSignerIdentifier;
+begin
+  Result := TAsn1Utilities.GetTaggedChoice<ICmsSignerIdentifier>(ATaggedObject, ADeclaredExplicit,
+    function(AElement: IAsn1Encodable): ICmsSignerIdentifier
+    begin
+      Result := GetInstance(AElement);
+    end);
+end;
+
+constructor TCmsSignerIdentifier.Create(const AIssuerAndSerialNumber: ICmsIssuerAndSerialNumber);
+begin
+  Inherited Create();
+  if AIssuerAndSerialNumber = nil then
+    raise EArgumentNilCryptoLibException.Create('issuerAndSerialNumber');
+  FId := AIssuerAndSerialNumber;
+end;
+
+constructor TCmsSignerIdentifier.Create(const ASubjectKeyIdentifier: IAsn1OctetString);
+begin
+  Inherited Create();
+  if ASubjectKeyIdentifier = nil then
+    raise EArgumentNilCryptoLibException.Create('subjectKeyIdentifier');
+  FId := TDerTaggedObject.Create(False, 0, ASubjectKeyIdentifier) as IAsn1Encodable;
+end;
+
+function TCmsSignerIdentifier.GetIsTagged: Boolean;
+begin
+  Result := Supports(FId, IAsn1TaggedObject);
+end;
+
+function TCmsSignerIdentifier.GetID: IAsn1Encodable;
+var
+  LResult: IAsn1Encodable;
+begin
+  if TAsn1Utilities.TryGetOptionalContextTagged<Boolean, IAsn1Encodable>(FId, 0, False, LResult,
+    function(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Encodable
+    begin
+      Result := TAsn1OctetString.GetTagged(ATagged, AState);
+    end) then
+    Result := LResult
+  else
+    Result := TCmsIssuerAndSerialNumber.GetInstance(FId);
+end;
+
+function TCmsSignerIdentifier.ToAsn1Object: IAsn1Object;
+begin
+  Result := FId.ToAsn1Object();
+end;
+
+{ TCmsSignerInfo }
+
+class function TCmsSignerInfo.GetInstance(AObj: TObject): ICmsSignerInfo;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsSignerInfo, Result) then
+    Exit;
+  Result := TCmsSignerInfo.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsSignerInfo.GetInstance(const AObj: IAsn1Convertible): ICmsSignerInfo;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsSignerInfo, Result) then
+    Exit;
+  Result := TCmsSignerInfo.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsSignerInfo.GetInstance(const AObj: IAsn1TaggedObject;
+  AExplicitly: Boolean): ICmsSignerInfo;
+begin
+  Result := TCmsSignerInfo.Create(TAsn1Sequence.GetInstance(AObj, AExplicitly));
+end;
+
+class function TCmsSignerInfo.GetTagged(const ATaggedObject: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsSignerInfo;
+begin
+  Result := TCmsSignerInfo.Create(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit));
+end;
+
+constructor TCmsSignerInfo.Create(const ASeq: IAsn1Sequence);
+var
+  LCount, LPos: Int32;
+begin
+  Inherited Create();
+  LCount := ASeq.Count;
+  if (LCount < 5) or (LCount > 7) then
+    raise EArgumentCryptoLibException.CreateResFmt(@SCmsBadSignerInfoSequenceSize, [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<Boolean, IAsn1Set>(ASeq, LPos, 0, False,
+    function(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set
+    begin
+      Result := TAsn1Set.GetTagged(ATagged, AState);
+    end);
+  FSignatureAlgorithm := TAlgorithmIdentifier.GetInstance(ASeq[LPos]);
+  System.Inc(LPos);
+  FSignature := TAsn1OctetString.GetInstance(ASeq[LPos]);
+  System.Inc(LPos);
+  FUnsignedAttrs := TAsn1Utilities.ReadOptionalContextTagged<Boolean, IAsn1Set>(ASeq, LPos, 1, False,
+    function(ATagged: IAsn1TaggedObject; AState: Boolean): IAsn1Set
+    begin
+      Result := TAsn1Set.GetTagged(ATagged, AState);
+    end);
+  if LPos <> LCount then
+    raise EArgumentCryptoLibException.Create(SCmsUnexpectedElementsInSequence);
+end;
+
+constructor TCmsSignerInfo.Create(const ASignerID: ICmsSignerIdentifier;
+  const ADigestAlgorithm: IAlgorithmIdentifier; const ASignedAttrs: IAsn1Set;
+  const ASignatureAlgorithm: IAlgorithmIdentifier; const ASignature: IAsn1OctetString;
+  const AUnsignedAttrs: IAsn1Set);
+begin
+  Inherited Create();
+  if ASignerID = nil then
+    raise EArgumentNilCryptoLibException.Create('signerID');
+  if ADigestAlgorithm = nil then
+    raise EArgumentNilCryptoLibException.Create('digestAlgorithm');
+  if ASignatureAlgorithm = nil then
+    raise EArgumentNilCryptoLibException.Create('signatureAlgorithm');
+  if ASignature = nil then
+    raise EArgumentNilCryptoLibException.Create('signature');
+  FSignerID := ASignerID;
+  FDigestAlgorithm := ADigestAlgorithm;
+  FSignedAttrs := ASignedAttrs;
+  FSignatureAlgorithm := ASignatureAlgorithm;
+  FSignature := ASignature;
+  FUnsignedAttrs := AUnsignedAttrs;
+  if ASignerID.IsTagged then
+    FVersion := TDerInteger.Three
+  else
+    FVersion := TDerInteger.One;
+end;
+
+function TCmsSignerInfo.GetVersion: IDerInteger;
+begin
+  Result := FVersion;
+end;
+
+function TCmsSignerInfo.GetSignerID: ICmsSignerIdentifier;
+begin
+  Result := FSignerID;
+end;
+
+function TCmsSignerInfo.GetDigestAlgorithm: IAlgorithmIdentifier;
+begin
+  Result := FDigestAlgorithm;
+end;
+
+function TCmsSignerInfo.GetSignedAttrs: IAsn1Set;
+begin
+  Result := FSignedAttrs;
+end;
+
+function TCmsSignerInfo.GetSignatureAlgorithm: IAlgorithmIdentifier;
+begin
+  Result := FSignatureAlgorithm;
+end;
+
+function TCmsSignerInfo.GetSignature: IAsn1OctetString;
+begin
+  Result := FSignature;
+end;
+
+function TCmsSignerInfo.GetUnsignedAttrs: IAsn1Set;
+begin
+  Result := FUnsignedAttrs;
+end;
+
+function TCmsSignerInfo.ToAsn1Object: IAsn1Object;
+var
+  LV: IAsn1EncodableVector;
+begin
+  LV := TAsn1EncodableVector.Create(7);
+  LV.Add([FVersion, FSignerID, FDigestAlgorithm]);
+  LV.AddOptionalTagged(False, 0, FSignedAttrs);
+  LV.Add(FSignatureAlgorithm);
+  LV.Add(FSignature);
+  LV.AddOptionalTagged(False, 1, FUnsignedAttrs);
+  Result := TDerSequence.Create(LV);
+end;
+
+{ TCmsSignedData }
+
+class function TCmsSignedData.ReadOptionalTaggedSet(const ASequence: IAsn1Sequence;
+  var ASequencePosition: Int32; ATagNo: Int32; out AIsBer: Boolean): IAsn1Set;
+var
+  LElement: IAsn1Encodable;
+  LTagged: IAsn1TaggedObject;
+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);
+end;
+
+class function TCmsSignedData.CalculateVersionField(const AContentOid: IDerObjectIdentifier;
+  const ACerts, ACrls, ASignerInfs: IAsn1Set): IDerInteger;
+var
+  I: Int32;
+  LTagged: IAsn1TaggedObject;
+  LAnyV1AttrCerts, LAnyV2AttrCerts: Boolean;
+  LElement: IAsn1Encodable;
+begin
+  (*
+  * RFC3852, section 5.1:
+  * IF((certificates is present) AND
+  *    (any certificates with a type of other are present)) OR
+  *    ((crls is present) AND
+  *    (any crls with a type of other are present))
+  * THEN version MUST be 5
+  * ELSE
+  *    IF(certificates is present) AND
+  *       (any version 2 attribute certificates are present)
+  *    THEN version MUST be 4
+  *    ELSE
+  *       IF((certificates is present) AND
+  *          (any version 1 attribute certificates are present)) OR
+  *          (any SignerInfo structures are version 3) OR
+  *          (encapContentInfo eContentType is other than id - data)
+  *       THEN version MUST be 3
+  *       ELSE version MUST be 1
+  *)
+
+  if ACrls <> nil then
+  begin
+    for I := 0 to ACrls.Count - 1 do
+    begin
+      LElement := ACrls.Items[I];
+      LTagged := TAsn1TaggedObject.GetOptional(LElement);
+      if LTagged <> nil then
+      begin
+        if LTagged.HasContextTag(1) then
+          Exit(TDerInteger.Five);
+      end;
+    end;
+  end;
+
+  LAnyV1AttrCerts := False;
+  if ACerts <> nil then
+  begin
+    LAnyV2AttrCerts := False;
+    for I := 0 to ACerts.Count - 1 do
+    begin
+      LElement := ACerts.Items[I];
+      LTagged := TAsn1TaggedObject.GetOptional(LElement);
+      if LTagged <> nil then
+      begin
+        if LTagged.HasContextTag(3) then
+          Exit(TDerInteger.Five);
+        LAnyV2AttrCerts := LAnyV2AttrCerts or LTagged.HasContextTag(2);
+        LAnyV1AttrCerts := LAnyV1AttrCerts or LTagged.HasContextTag(1);
+      end;
+    end;
+    if LAnyV2AttrCerts then
+      Exit(TDerInteger.Four);
+  end;
+
+  if LAnyV1AttrCerts or (not TCmsObjectIdentifiers.Data.Equals(AContentOid)) or HasV3SignerInfos(ASignerInfs) then
+    Exit(TDerInteger.Three);
+
+  Result := TDerInteger.One;
+end;
+
+class function TCmsSignedData.HasV3SignerInfos(const ASignerInfs: IAsn1Set): Boolean;
+var
+  I: Int32;
+  LSignerInfo: ICmsSignerInfo;
+  LElement: IAsn1Encodable;
+begin
+  if ASignerInfs = nil then
+  begin
+    Result := False;
+    Exit;
+  end;
+  for I := 0 to ASignerInfs.Count - 1 do
+  begin
+    LElement := ASignerInfs.Items[I];
+    LSignerInfo := TCmsSignerInfo.GetInstance(LElement);
+    if (LSignerInfo <> nil) and LSignerInfo.Version.HasValue(3) then
+      Exit(True);
+  end;
+  Result := False;
+end;
+
+class function TCmsSignedData.GetInstance(AObj: TObject): ICmsSignedData;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsSignedData, Result) then
+    Exit;
+  Result := TCmsSignedData.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsSignedData.GetInstance(const AObj: IAsn1Convertible): ICmsSignedData;
+begin
+  if AObj = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  if Supports(AObj, ICmsSignedData, Result) then
+    Exit;
+  Result := TCmsSignedData.Create(TAsn1Sequence.GetInstance(AObj));
+end;
+
+class function TCmsSignedData.GetInstance(const AEncoded: TCryptoLibByteArray): ICmsSignedData;
+begin
+  if AEncoded = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  Result := TCmsSignedData.Create(TAsn1Sequence.GetInstance(AEncoded));
+end;
+
+class function TCmsSignedData.GetInstance(const AObj: IAsn1TaggedObject;
+  AExplicitly: Boolean): ICmsSignedData;
+begin
+  Result := GetInstance(TAsn1Sequence.GetInstance(AObj, AExplicitly));
+end;
+
+class function TCmsSignedData.GetTagged(const ATaggedObject: IAsn1TaggedObject;
+  ADeclaredExplicit: Boolean): ICmsSignedData;
+begin
+  Result := GetInstance(TAsn1Sequence.GetTagged(ATaggedObject, ADeclaredExplicit));
+end;
+
+constructor TCmsSignedData.Create(const ASeq: IAsn1Sequence);
+var
+  LCount, 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.Create(SCmsUnexpectedElementsInSequence);
+
+  FDigsBer := Supports(FDigestAlgorithms, IBerSet);
+  FSigsBer := Supports(FSignerInfos, IBerSet);
+end;
+
+constructor TCmsSignedData.Create(const ADigestAlgorithms: IAsn1Set; const AEncapContentInfo: ICmsContentInfo;
+  const ACertificates, ACrls, ASignerInfos: IAsn1Set);
+begin
+  Inherited Create();
+  if ADigestAlgorithms = nil then
+    raise EArgumentNilCryptoLibException.Create('digestAlgorithms');
+  if AEncapContentInfo = nil then
+    raise EArgumentNilCryptoLibException.Create('contentInfo');
+  if ASignerInfos = nil then
+    raise EArgumentNilCryptoLibException.Create('signerInfos');
+
+  FDigestAlgorithms := ADigestAlgorithms;
+  FEncapContentInfo := AEncapContentInfo;
+  FCertificates := ACertificates;
+  FCrls := ACrls;
+  FSignerInfos := ASignerInfos;
+  FVersion := CalculateVersionField(AEncapContentInfo.ContentType, ACertificates, ACrls, ASignerInfos);
+  FCertsBer := Supports(FCertificates, IBerSet);
+  FCrlsBer := Supports(FCrls, IBerSet);
+  FDigsBer := Supports(FDigestAlgorithms, IBerSet);
+  FSigsBer := Supports(FSignerInfos, IBerSet);
+end;
+
+function TCmsSignedData.GetVersion: IDerInteger;
+begin
+  Result := FVersion;
+end;
+
+function TCmsSignedData.GetDigestAlgorithms: IAsn1Set;
+begin
+  Result := FDigestAlgorithms;
+end;
+
+function TCmsSignedData.GetEncapContentInfo: ICmsContentInfo;
+begin
+  Result := FEncapContentInfo;
+end;
+
+function TCmsSignedData.GetCertificates: IAsn1Set;
+begin
+  Result := FCertificates;
+end;
+
+function TCmsSignedData.GetCrls: IAsn1Set;
+begin
+  Result := FCrls;
+end;
+
+function TCmsSignedData.GetSignerInfos: IAsn1Set;
+begin
+  Result := FSignerInfos;
+end;
+
+function TCmsSignedData.ToAsn1Object: IAsn1Object;
+var
+  LV: IAsn1EncodableVector;
+begin
+  LV := TAsn1EncodableVector.Create(6);
+  LV.Add([FVersion, FDigestAlgorithms, FEncapContentInfo]);
+
+  if FCertificates <> nil then
+  begin
+    if FCertsBer then
+      LV.Add(TBerTaggedObject.Create(False, 0, FCertificates)
+      as IBerTaggedObject)
+    else
+      LV.Add(TDerTaggedObject.Create(False, 0, FCertificates)
+      as IDerTaggedObject);
+  end;
+
+  if FCrls <> nil then
+  begin
+    if FCrlsBer then
+      LV.Add(TBerTaggedObject.Create(False, 1, FCrls) as IBerTaggedObject)
+    else
+      LV.Add(TDerTaggedObject.Create(False, 1, FCrls) as IDerTaggedObject);
+  end;
+
+  LV.Add(FSignerInfos);
+
+  if (not FEncapContentInfo.IsDefiniteLength) or FCertsBer or FCrlsBer or FDigsBer or FSigsBer then
+    Result := TBerSequence.Create(LV)
+  else
+    Result := TDLSequence.Create(LV);
+end;
+
+end.

+ 264 - 0
CryptoLib/src/Asn1/Cms/ClpCmsObjectIdentifiers.pas

@@ -0,0 +1,264 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  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     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpCmsObjectIdentifiers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpPkcsObjectIdentifiers,
+  ClpX509ObjectIdentifiers,
+  ClpIAsn1Objects;
+
+type
+  /// <summary>
+  /// CMS Object Identifiers (RFC 3852, etc.); delegates to PKCS and X.509 OIDs.
+  /// </summary>
+  TCmsObjectIdentifiers = class sealed(TObject)
+
+  strict private
+    class var
+    FData: IDerObjectIdentifier;
+    FSignedData: IDerObjectIdentifier;
+    FEnvelopedData: IDerObjectIdentifier;
+    FSignedAndEnvelopedData: IDerObjectIdentifier;
+    FDigestedData: IDerObjectIdentifier;
+    FEncryptedData: IDerObjectIdentifier;
+    FAuthenticatedData: IDerObjectIdentifier;
+    FCompressedData: IDerObjectIdentifier;
+    FAuthEnvelopedData: IDerObjectIdentifier;
+    FTimestampedData: IDerObjectIdentifier;
+    FZlibCompress: IDerObjectIdentifier;
+    FIdRi: IDerObjectIdentifier;
+    FIdRiOcspResponse: IDerObjectIdentifier;
+    FIdRiScvp: IDerObjectIdentifier;
+    FIdAlg: IDerObjectIdentifier;
+    FIdRsassaPssShake128: IDerObjectIdentifier;
+    FIdRsassaPssShake256: IDerObjectIdentifier;
+    FIdEcdsaWithShake128: IDerObjectIdentifier;
+    FIdEcdsaWithShake256: IDerObjectIdentifier;
+    FIdOri: IDerObjectIdentifier;
+    FIdOriKem: IDerObjectIdentifier;
+    FIdAlgCekHkdfSha256: IDerObjectIdentifier;
+
+    class function GetData: IDerObjectIdentifier; static; inline;
+    class function GetSignedData: IDerObjectIdentifier; static; inline;
+    class function GetEnvelopedData: IDerObjectIdentifier; static; inline;
+    class function GetSignedAndEnvelopedData: IDerObjectIdentifier; static; inline;
+    class function GetDigestedData: IDerObjectIdentifier; static; inline;
+    class function GetEncryptedData: IDerObjectIdentifier; static; inline;
+    class function GetAuthenticatedData: IDerObjectIdentifier; static; inline;
+    class function GetCompressedData: IDerObjectIdentifier; static; inline;
+    class function GetAuthEnvelopedData: IDerObjectIdentifier; static; inline;
+    class function GetTimestampedData: IDerObjectIdentifier; static; inline;
+    class function GetZlibCompress: IDerObjectIdentifier; static; inline;
+    class function GetIdRi: IDerObjectIdentifier; static; inline;
+    class function GetIdRiOcspResponse: IDerObjectIdentifier; static; inline;
+    class function GetIdRiScvp: IDerObjectIdentifier; static; inline;
+    class function GetIdAlg: IDerObjectIdentifier; static; inline;
+    class function GetIdRsassaPssShake128: IDerObjectIdentifier; static; inline;
+    class function GetIdRsassaPssShake256: IDerObjectIdentifier; static; inline;
+    class function GetIdEcdsaWithShake128: IDerObjectIdentifier; static; inline;
+    class function GetIdEcdsaWithShake256: IDerObjectIdentifier; static; inline;
+    class function GetIdOri: IDerObjectIdentifier; static; inline;
+    class function GetIdOriKem: IDerObjectIdentifier; static; inline;
+    class function GetIdAlgCekHkdfSha256: IDerObjectIdentifier; static; inline;
+
+    class procedure Boot(); static;
+    class constructor CmsObjectIdentifiers();
+
+  public
+    class property Data: IDerObjectIdentifier read GetData;
+    class property SignedData: IDerObjectIdentifier read GetSignedData;
+    class property EnvelopedData: IDerObjectIdentifier read GetEnvelopedData;
+    class property SignedAndEnvelopedData: IDerObjectIdentifier read GetSignedAndEnvelopedData;
+    class property DigestedData: IDerObjectIdentifier read GetDigestedData;
+    class property EncryptedData: IDerObjectIdentifier read GetEncryptedData;
+    class property AuthenticatedData: IDerObjectIdentifier read GetAuthenticatedData;
+    class property CompressedData: IDerObjectIdentifier read GetCompressedData;
+    class property AuthEnvelopedData: IDerObjectIdentifier read GetAuthEnvelopedData;
+    class property TimestampedData: IDerObjectIdentifier read GetTimestampedData;
+    class property ZlibCompress: IDerObjectIdentifier read GetZlibCompress;
+
+    class property IdRi: IDerObjectIdentifier read GetIdRi;
+
+    class property IdRiOcspResponse: IDerObjectIdentifier read GetIdRiOcspResponse;
+    class property IdRiScvp: IDerObjectIdentifier read GetIdRiScvp;
+
+    class property IdAlg: IDerObjectIdentifier read GetIdAlg;
+
+    class property IdRsassaPssShake128: IDerObjectIdentifier read GetIdRsassaPssShake128;
+    class property IdRsassaPssShake256: IDerObjectIdentifier read GetIdRsassaPssShake256;
+    class property IdEcdsaWithShake128: IDerObjectIdentifier read GetIdEcdsaWithShake128;
+    class property IdEcdsaWithShake256: IDerObjectIdentifier read GetIdEcdsaWithShake256;
+
+    class property IdOri: IDerObjectIdentifier read GetIdOri;
+    class property IdOriKem: IDerObjectIdentifier read GetIdOriKem;
+
+    class property IdAlgCekHkdfSha256: IDerObjectIdentifier read GetIdAlgCekHkdfSha256;
+  end;
+
+implementation
+
+class procedure TCmsObjectIdentifiers.Boot;
+begin
+  FData := TPkcsObjectIdentifiers.Data;
+  FSignedData := TPkcsObjectIdentifiers.SignedData;
+  FEnvelopedData := TPkcsObjectIdentifiers.EnvelopedData;
+  FSignedAndEnvelopedData := TPkcsObjectIdentifiers.SignedAndEnvelopedData;
+  FDigestedData := TPkcsObjectIdentifiers.DigestedData;
+  FEncryptedData := TPkcsObjectIdentifiers.EncryptedData;
+  FAuthenticatedData := TPkcsObjectIdentifiers.IdCTAuthData;
+  FCompressedData := TPkcsObjectIdentifiers.IdCTCompressedData;
+  FAuthEnvelopedData := TPkcsObjectIdentifiers.IdCTAuthEnvelopedData;
+  FTimestampedData := TPkcsObjectIdentifiers.IdCTTimestampedData;
+  FZlibCompress := TPkcsObjectIdentifiers.IdAlgZlibCompress;
+
+  FIdRi := TX509ObjectIdentifiers.IdPkix.Branch('16');
+  FIdRiOcspResponse := FIdRi.Branch('2');
+  FIdRiScvp := FIdRi.Branch('4');
+
+  FIdAlg := TX509ObjectIdentifiers.PkixAlgorithms;
+  FIdRsassaPssShake128 := TX509ObjectIdentifiers.IdRsassaPssShake128;
+  FIdRsassaPssShake256 := TX509ObjectIdentifiers.IdRsassaPssShake256;
+  FIdEcdsaWithShake128 := TX509ObjectIdentifiers.IdEcdsaWithShake128;
+  FIdEcdsaWithShake256 := TX509ObjectIdentifiers.IdEcdsaWithShake256;
+
+  FIdOri := TPkcsObjectIdentifiers.IdSmime.Branch('13');
+  FIdOriKem := FIdOri.Branch('3');
+
+  FIdAlgCekHkdfSha256 := TPkcsObjectIdentifiers.SmimeAlg.Branch('31');
+end;
+
+class constructor TCmsObjectIdentifiers.CmsObjectIdentifiers;
+begin
+  TCmsObjectIdentifiers.Boot();
+end;
+
+class function TCmsObjectIdentifiers.GetData: IDerObjectIdentifier;
+begin
+  Result := FData;
+end;
+
+class function TCmsObjectIdentifiers.GetSignedData: IDerObjectIdentifier;
+begin
+  Result := FSignedData;
+end;
+
+class function TCmsObjectIdentifiers.GetEnvelopedData: IDerObjectIdentifier;
+begin
+  Result := FEnvelopedData;
+end;
+
+class function TCmsObjectIdentifiers.GetSignedAndEnvelopedData: IDerObjectIdentifier;
+begin
+  Result := FSignedAndEnvelopedData;
+end;
+
+class function TCmsObjectIdentifiers.GetDigestedData: IDerObjectIdentifier;
+begin
+  Result := FDigestedData;
+end;
+
+class function TCmsObjectIdentifiers.GetEncryptedData: IDerObjectIdentifier;
+begin
+  Result := FEncryptedData;
+end;
+
+class function TCmsObjectIdentifiers.GetAuthenticatedData: IDerObjectIdentifier;
+begin
+  Result := FAuthenticatedData;
+end;
+
+class function TCmsObjectIdentifiers.GetCompressedData: IDerObjectIdentifier;
+begin
+  Result := FCompressedData;
+end;
+
+class function TCmsObjectIdentifiers.GetAuthEnvelopedData: IDerObjectIdentifier;
+begin
+  Result := FAuthEnvelopedData;
+end;
+
+class function TCmsObjectIdentifiers.GetTimestampedData: IDerObjectIdentifier;
+begin
+  Result := FTimestampedData;
+end;
+
+class function TCmsObjectIdentifiers.GetZlibCompress: IDerObjectIdentifier;
+begin
+  Result := FZlibCompress;
+end;
+
+class function TCmsObjectIdentifiers.GetIdRi: IDerObjectIdentifier;
+begin
+  Result := FIdRi;
+end;
+
+class function TCmsObjectIdentifiers.GetIdRiOcspResponse: IDerObjectIdentifier;
+begin
+  Result := FIdRiOcspResponse;
+end;
+
+class function TCmsObjectIdentifiers.GetIdRiScvp: IDerObjectIdentifier;
+begin
+  Result := FIdRiScvp;
+end;
+
+class function TCmsObjectIdentifiers.GetIdAlg: IDerObjectIdentifier;
+begin
+  Result := FIdAlg;
+end;
+
+class function TCmsObjectIdentifiers.GetIdRsassaPssShake128: IDerObjectIdentifier;
+begin
+  Result := FIdRsassaPssShake128;
+end;
+
+class function TCmsObjectIdentifiers.GetIdRsassaPssShake256: IDerObjectIdentifier;
+begin
+  Result := FIdRsassaPssShake256;
+end;
+
+class function TCmsObjectIdentifiers.GetIdEcdsaWithShake128: IDerObjectIdentifier;
+begin
+  Result := FIdEcdsaWithShake128;
+end;
+
+class function TCmsObjectIdentifiers.GetIdEcdsaWithShake256: IDerObjectIdentifier;
+begin
+  Result := FIdEcdsaWithShake256;
+end;
+
+class function TCmsObjectIdentifiers.GetIdOri: IDerObjectIdentifier;
+begin
+  Result := FIdOri;
+end;
+
+class function TCmsObjectIdentifiers.GetIdOriKem: IDerObjectIdentifier;
+begin
+  Result := FIdOriKem;
+end;
+
+class function TCmsObjectIdentifiers.GetIdAlgCekHkdfSha256: IDerObjectIdentifier;
+begin
+  Result := FIdAlgCekHkdfSha256;
+end;
+
+end.

+ 267 - 0
CryptoLib/src/Asn1/Cms/ClpCmsParsers.pas

@@ -0,0 +1,267 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  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     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpCmsParsers;
+
+{$I ..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  SysUtils,
+  ClpAsn1Tags,
+  ClpAsn1Objects,
+  ClpAsn1Utilities,
+  ClpAsn1Parsers,
+  ClpIAsn1Objects,
+  ClpIAsn1Core,
+  ClpIAsn1Parsers,
+  ClpICmsParsers,
+  ClpICmsAsn1Objects,
+  ClpCmsAsn1Objects,
+  ClpPlatformUtilities,
+  ClpCryptoLibTypes;
+
+resourcestring
+  SCmsUnknownObjectEncountered = 'unknown object encountered: %s';
+  SCmsGetCertsNotCalled = 'GetCerts() has not been called.';
+  SCmsGetCertsOrGetCrlsNotCalled = 'GetCerts() and/or GetCrls() has not been called.';
+
+type
+  /// <summary>
+  /// CMS ContentInfo parser.
+  /// </summary>
+  TCmsContentInfoParser = class sealed(TInterfacedObject, ICmsContentInfoParser)
+  strict private
+  var
+    FContentType: IDerObjectIdentifier;
+    FContent: IAsn1TaggedObjectParser;
+
+  strict protected
+    function GetContentType: IDerObjectIdentifier;
+
+  public
+    constructor Create(const ASeq: IAsn1SequenceParser);
+
+    function GetContent(ATag: Int32): IAsn1Convertible;
+
+    property ContentType: IDerObjectIdentifier read GetContentType;
+  end;
+
+  /// <summary>
+  /// CMS SignedData parser.
+  /// </summary>
+  TCmsSignedDataParser = class sealed(TInterfacedObject, ICmsSignedDataParser)
+  strict private
+  var
+    FSeq: IAsn1SequenceParser;
+    FVersion: IDerInteger;
+    FNextObject: IAsn1Convertible;
+    FCertsCalled: Boolean;
+    FCrlsCalled: Boolean;
+
+  strict protected
+    function GetVersion: IDerInteger;
+    function GetDigestAlgorithms: IAsn1SetParser;
+    function GetEncapContentInfo: ICmsContentInfoParser;
+    function GetCertificates: IAsn1SetParser;
+    function GetCrls: IAsn1SetParser;
+    function GetSignerInfos: IAsn1SetParser;
+
+  public
+    class function GetInstance(const AObj: TObject): ICmsSignedDataParser; static;
+
+    constructor Create(const ASeq: IAsn1SequenceParser);
+
+    property Version: IDerInteger read GetVersion;
+  end;
+
+implementation
+
+{ TCmsContentInfoParser }
+
+constructor TCmsContentInfoParser.Create(const ASeq: IAsn1SequenceParser);
+var
+  LObj: IAsn1Convertible;
+  LTagged: IAsn1TaggedObjectParser;
+begin
+  Inherited Create();
+  if ASeq = nil then
+    raise EArgumentNilCryptoLibException.Create('seq');
+
+  LObj := ASeq.ReadObject();
+  if not Supports(LObj, IDerObjectIdentifier, FContentType) then
+    raise EArgumentCryptoLibException.Create('ContentInfoParser: expected DerObjectIdentifier for contentType');
+
+  LObj := ASeq.ReadObject();
+  if Supports(LObj, IAsn1TaggedObjectParser, LTagged) then
+    FContent := LTagged
+  else
+    FContent := nil;
+end;
+
+function TCmsContentInfoParser.GetContentType: IDerObjectIdentifier;
+begin
+  Result := FContentType;
+end;
+
+function TCmsContentInfoParser.GetContent(ATag: Int32): IAsn1Convertible;
+begin
+  if FContent = nil then
+  begin
+    Result := nil;
+    Exit;
+  end;
+  Result := TAsn1Utilities.ParseExplicitContextBaseObject(FContent, 0);
+end;
+
+{ TCmsSignedDataParser }
+
+class function TCmsSignedDataParser.GetInstance(const AObj: TObject): ICmsSignedDataParser;
+var
+  LSeqParser: IAsn1SequenceParser;
+  LSeq: IAsn1Sequence;
+  LObj: IAsn1Convertible;
+begin
+  if AObj = nil then
+    raise EArgumentNilCryptoLibException.Create('AObj');
+
+  if Supports(AObj, IAsn1SequenceParser, LSeqParser) then
+    Exit(TCmsSignedDataParser.Create(LSeqParser));
+
+  if Supports(AObj, IAsn1Sequence, LSeq) then
+    Exit(TCmsSignedDataParser.Create(LSeq.Parser));
+
+  if Supports(AObj, IAsn1Convertible, LObj) then
+  begin
+    LSeq := TAsn1Sequence.GetInstance(LObj);
+    if LSeq <> nil then
+      Exit(TCmsSignedDataParser.Create(LSeq.Parser));
+  end;
+
+  raise EStreamCryptoLibException.CreateResFmt(@SCmsUnknownObjectEncountered,
+    [TPlatformUtilities.GetTypeName(AObj)]);
+end;
+
+constructor TCmsSignedDataParser.Create(const ASeq: IAsn1SequenceParser);
+var
+  LObj: IAsn1Convertible;
+begin
+  Inherited Create();
+  if ASeq = nil then
+    raise EArgumentNilCryptoLibException.Create('seq');
+  FSeq := ASeq;
+  LObj := ASeq.ReadObject();
+  if not Supports(LObj, IDerInteger, FVersion) then
+    raise EArgumentCryptoLibException.Create('SignedDataParser: expected DerInteger for version');
+  FNextObject := nil;
+  FCertsCalled := False;
+  FCrlsCalled := False;
+end;
+
+function TCmsSignedDataParser.GetVersion: IDerInteger;
+begin
+  Result := FVersion;
+end;
+
+function TCmsSignedDataParser.GetDigestAlgorithms: IAsn1SetParser;
+var
+  LObj: IAsn1Convertible;
+  LSetParser: IAsn1SetParser;
+begin
+  LObj := FSeq.ReadObject();
+  if not Supports(LObj, IAsn1SetParser, LSetParser) then
+    raise EArgumentCryptoLibException.Create('SignedDataParser: expected Asn1SetParser for digestAlgorithms');
+  Result := LSetParser;
+end;
+
+function TCmsSignedDataParser.GetEncapContentInfo: ICmsContentInfoParser;
+var
+  LObj: IAsn1Convertible;
+  LSeqParser: IAsn1SequenceParser;
+begin
+  LObj := FSeq.ReadObject();
+  if not Supports(LObj, IAsn1SequenceParser, LSeqParser) then
+    raise EArgumentCryptoLibException.Create('SignedDataParser: expected Asn1SequenceParser for encapContentInfo');
+  Result := TCmsContentInfoParser.Create(LSeqParser);
+end;
+
+function TCmsSignedDataParser.GetCertificates: IAsn1SetParser;
+var
+  LTagged: IAsn1TaggedObjectParser;
+  LSetParser: IAsn1SetParser;
+  LObj: IAsn1Convertible;
+begin
+  FCertsCalled := True;
+  if FNextObject = nil then
+    FNextObject := FSeq.ReadObject();
+
+  if Supports(FNextObject, IAsn1TaggedObjectParser, LTagged) and LTagged.HasContextTag(0) then
+  begin
+    LObj := LTagged.ParseBaseUniversal(False, TAsn1Tags.SetOf);
+    if Supports(LObj, IAsn1SetParser, LSetParser) then
+    begin
+      FNextObject := nil;
+      Result := LSetParser;
+      Exit;
+    end;
+  end;
+  Result := nil;
+end;
+
+function TCmsSignedDataParser.GetCrls: IAsn1SetParser;
+var
+  LTagged: IAsn1TaggedObjectParser;
+  LSetParser: IAsn1SetParser;
+  LObj: IAsn1Convertible;
+begin
+  if not FCertsCalled then
+    raise EStreamCryptoLibException.Create(SCmsGetCertsNotCalled);
+
+  FCrlsCalled := True;
+  if FNextObject = nil then
+    FNextObject := FSeq.ReadObject();
+
+  if Supports(FNextObject, IAsn1TaggedObjectParser, LTagged) and LTagged.HasContextTag(1) then
+  begin
+    LObj := LTagged.ParseBaseUniversal(False, TAsn1Tags.SetOf);
+    if Supports(LObj, IAsn1SetParser, LSetParser) then
+    begin
+      FNextObject := nil;
+      Result := LSetParser;
+      Exit;
+    end;
+  end;
+  Result := nil;
+end;
+
+function TCmsSignedDataParser.GetSignerInfos: IAsn1SetParser;
+var
+  LSetParser: IAsn1SetParser;
+begin
+  if not FCertsCalled or not FCrlsCalled then
+    raise EStreamCryptoLibException.Create(SCmsGetCertsOrGetCrlsNotCalled);
+
+  if FNextObject = nil then
+    FNextObject := FSeq.ReadObject();
+
+  if not Supports(FNextObject, IAsn1SetParser, LSetParser) then
+    raise EArgumentCryptoLibException.Create('SignedDataParser: expected Asn1SetParser for signerInfos');
+  Result := LSetParser;
+end;
+
+end.

+ 125 - 0
CryptoLib/src/Interfaces/Asn1/Cms/ClpICmsAsn1Objects.pas

@@ -0,0 +1,125 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  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     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpICmsAsn1Objects;
+
+{$I ..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1Objects,
+  ClpIAsn1Core,
+  ClpIX509Asn1Objects,
+  ClpCryptoLibTypes;
+
+type
+  // Forward declarations
+  ICmsContentInfo = interface;
+  ICmsIssuerAndSerialNumber = interface;
+  ICmsSignerIdentifier = interface;
+  ICmsSignedData = interface;
+  ICmsSignerInfo = interface;
+
+  /// <summary>
+  /// Interface for CMS ContentInfo (EncapsulatedContentInfo).
+  /// </summary>
+  ICmsContentInfo = interface(IAsn1Encodable)
+    ['{96013FE8-A604-4F2F-9C6C-179EE04F096B}']
+
+    function GetContentType: IDerObjectIdentifier;
+    function GetContent: IAsn1Encodable;
+    function GetIsDefiniteLength: Boolean;
+
+    property ContentType: IDerObjectIdentifier read GetContentType;
+    property Content: IAsn1Encodable read GetContent;
+    property IsDefiniteLength: Boolean read GetIsDefiniteLength;
+  end;
+
+  /// <summary>
+  /// Interface for CMS SignedData (RFC 3852).
+  /// </summary>
+  ICmsSignedData = interface(IAsn1Encodable)
+    ['{A71B2C39-D805-4E10-B8F1-28A1E53C3D4F}']
+
+    function GetVersion: IDerInteger;
+    function GetDigestAlgorithms: IAsn1Set;
+    function GetEncapContentInfo: ICmsContentInfo;
+    function GetCertificates: IAsn1Set;
+    function GetCrls: IAsn1Set;
+    function GetSignerInfos: IAsn1Set;
+
+    property Version: IDerInteger read GetVersion;
+    property DigestAlgorithms: IAsn1Set read GetDigestAlgorithms;
+    property EncapContentInfo: ICmsContentInfo read GetEncapContentInfo;
+    property Certificates: IAsn1Set read GetCertificates;
+    property Crls: IAsn1Set read GetCrls;
+    property SignerInfos: IAsn1Set read GetSignerInfos;
+  end;
+
+  /// <summary>
+  /// Interface for CMS IssuerAndSerialNumber (issuer Name + serialNumber).
+  /// </summary>
+  ICmsIssuerAndSerialNumber = interface(IAsn1Encodable)
+    ['{E1A2B3C4-D5E6-4F78-9012-3456789ABCDE}']
+
+    function GetIssuer: IX509Name;
+    function GetSerialNumber: IDerInteger;
+
+    property Issuer: IX509Name read GetIssuer;
+    property SerialNumber: IDerInteger read GetSerialNumber;
+  end;
+
+  /// <summary>
+  /// Interface for CMS SignerIdentifier (CHOICE: IssuerAndSerialNumber or [0] SubjectKeyIdentifier).
+  /// </summary>
+  ICmsSignerIdentifier = interface(IAsn1Encodable)
+    ['{F2B3C4D5-E6A7-4B89-0123-456789ABCDEF}']
+
+    function GetIsTagged: Boolean;
+    function GetID: IAsn1Encodable;
+
+    property IsTagged: Boolean read GetIsTagged;
+    property ID: IAsn1Encodable read GetID;
+  end;
+
+  /// <summary>
+  /// Interface for CMS SignerInfo (per-signer information in SignedData).
+  /// </summary>
+  ICmsSignerInfo = interface(IAsn1Encodable)
+    ['{B82D4E5A-E916-4F31-9D72-3B0F5C4E6A7D}']
+
+    function GetVersion: IDerInteger;
+    function GetSignerID: ICmsSignerIdentifier;
+    function GetDigestAlgorithm: IAlgorithmIdentifier;
+    function GetSignedAttrs: IAsn1Set;
+    function GetSignatureAlgorithm: IAlgorithmIdentifier;
+    function GetSignature: IAsn1OctetString;
+    function GetUnsignedAttrs: IAsn1Set;
+
+    property Version: IDerInteger read GetVersion;
+    property SignerID: ICmsSignerIdentifier read GetSignerID;
+    property DigestAlgorithm: IAlgorithmIdentifier read GetDigestAlgorithm;
+    property SignedAttrs: IAsn1Set read GetSignedAttrs;
+    property SignatureAlgorithm: IAlgorithmIdentifier read GetSignatureAlgorithm;
+    property Signature: IAsn1OctetString read GetSignature;
+    property UnsignedAttrs: IAsn1Set read GetUnsignedAttrs;
+  end;
+
+implementation
+
+end.

+ 61 - 0
CryptoLib/src/Interfaces/Asn1/Cms/ClpICmsParsers.pas

@@ -0,0 +1,61 @@
+{ *********************************************************************************** }
+{ *                              CryptoLib Library                                  * }
+{ *                Copyright (c) 2018 - 20XX Ugochukwu Mmaduekwe                    * }
+{ *                 Github Repository <https://github.com/Xor-el>                   * }
+
+{ *  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     * }
+{ *                           development of this library                           * }
+
+{ * ******************************************************************************* * }
+
+(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
+
+unit ClpICmsParsers;
+
+{$I ..\..\..\Include\CryptoLib.inc}
+
+interface
+
+uses
+  ClpIAsn1Core,
+  ClpIAsn1Objects,
+  ClpIAsn1Parsers,
+  ClpCryptoLibTypes;
+
+type
+  /// <summary>
+  /// Interface for CMS ContentInfo parser.
+  /// </summary>
+  ICmsContentInfoParser = interface(IInterface)
+    ['{C93E5F6B-0718-4A2E-8C3D-5F1B9E4A7D2C}']
+
+    function GetContentType: IDerObjectIdentifier;
+    function GetContent(ATag: Int32): IAsn1Convertible;
+
+    property ContentType: IDerObjectIdentifier read GetContentType;
+  end;
+
+  /// <summary>
+  /// Interface for CMS SignedData parser.
+  /// </summary>
+  ICmsSignedDataParser = interface(IInterface)
+    ['{D04F6A7C-1829-4B3F-9D4E-6A2C8B1E5F3D}']
+
+    function GetVersion: IDerInteger;
+    function GetDigestAlgorithms: IAsn1SetParser;
+    function GetEncapContentInfo: ICmsContentInfoParser;
+    function GetCertificates: IAsn1SetParser;
+    function GetCrls: IAsn1SetParser;
+    function GetSignerInfos: IAsn1SetParser;
+
+    property Version: IDerInteger read GetVersion;
+  end;
+
+implementation
+
+end.

Plik diff jest za duży
+ 0 - 0
CryptoLib/src/Packages/FPC/CryptoLib4PascalPackage.lpk


Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików