From 8119dba914a3aa08cd1ce7b24b757e95269d3aaf Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 18 Jul 2023 18:29:42 +0700 Subject: Asn1.Tsp updates from bc-java --- crypto/src/asn1/DerBitString.cs | 14 -- crypto/src/asn1/cms/Attributes.cs | 44 ++--- crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs | 73 +++----- crypto/src/asn1/tsp/Accuracy.cs | 108 +++++------ crypto/src/asn1/tsp/ArchiveTimeStamp.cs | 176 ++++++++++++++++++ crypto/src/asn1/tsp/ArchiveTimeStampChain.cs | 86 +++++++++ crypto/src/asn1/tsp/ArchiveTimeStampSequence.cs | 93 ++++++++++ crypto/src/asn1/tsp/CryptoInfos.cs | 43 +++++ crypto/src/asn1/tsp/EncryptionInfo.cs | 76 ++++++++ crypto/src/asn1/tsp/EvidenceRecord.cs | 217 +++++++++++++++++++++++ crypto/src/asn1/tsp/MessageImprint.cs | 44 +++-- crypto/src/asn1/tsp/PartialHashtree.cs | 91 ++++++++++ crypto/src/asn1/tsp/TSTInfo.cs | 163 +++++++---------- crypto/src/asn1/tsp/TimeStampReq.cs | 102 +++++------ crypto/src/asn1/tsp/TimeStampResp.cs | 45 +++-- 15 files changed, 1032 insertions(+), 343 deletions(-) create mode 100644 crypto/src/asn1/tsp/ArchiveTimeStamp.cs create mode 100644 crypto/src/asn1/tsp/ArchiveTimeStampChain.cs create mode 100644 crypto/src/asn1/tsp/ArchiveTimeStampSequence.cs create mode 100644 crypto/src/asn1/tsp/CryptoInfos.cs create mode 100644 crypto/src/asn1/tsp/EncryptionInfo.cs create mode 100644 crypto/src/asn1/tsp/EvidenceRecord.cs create mode 100644 crypto/src/asn1/tsp/PartialHashtree.cs diff --git a/crypto/src/asn1/DerBitString.cs b/crypto/src/asn1/DerBitString.cs index caa97933f..f543a968d 100644 --- a/crypto/src/asn1/DerBitString.cs +++ b/crypto/src/asn1/DerBitString.cs @@ -31,11 +31,6 @@ namespace Org.BouncyCastle.Asn1 private static readonly char[] table = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; - /** - * return a Bit string from the passed in object - * - * @exception ArgumentException if the object cannot be converted. - */ public static DerBitString GetInstance(object obj) { if (obj == null) @@ -65,15 +60,6 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj)); } - /** - * return a Bit string from a tagged object. - * - * @param obj the tagged object holding the object we want - * @param explicitly true if the object is meant to be explicitly - * tagged false otherwise. - * @exception ArgumentException if the tagged object cannot - * be converted. - */ public static DerBitString GetInstance(Asn1TaggedObject obj, bool isExplicit) { return (DerBitString)Meta.Instance.GetContextInstance(obj, isExplicit); diff --git a/crypto/src/asn1/cms/Attributes.cs b/crypto/src/asn1/cms/Attributes.cs index 5b6b13034..010684158 100644 --- a/crypto/src/asn1/cms/Attributes.cs +++ b/crypto/src/asn1/cms/Attributes.cs @@ -5,41 +5,34 @@ namespace Org.BouncyCastle.Asn1.Cms public class Attributes : Asn1Encodable { - private readonly Asn1Set attributes; - - private Attributes(Asn1Set attributes) + public static Attributes GetInstance(object obj) { - this.attributes = attributes; + if (obj == null) + return null; + if (obj is Attributes attributes) + return attributes; + return new Attributes(Asn1Set.GetInstance(obj)); } - public Attributes(Asn1EncodableVector v) + public static Attributes GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - attributes = new BerSet(v); + return GetInstance(Asn1Set.GetInstance(taggedObject, declaredExplicit)); } - public static Attributes GetInstance(object obj) - { - if (obj is Attributes) - return (Attributes)obj; + private readonly Asn1Set m_attributes; - if (obj != null) - return new Attributes(Asn1Set.GetInstance(obj)); - - return null; + private Attributes(Asn1Set attributes) + { + m_attributes = attributes; } - public virtual Attribute[] GetAttributes() + public Attributes(Asn1EncodableVector v) { - Attribute[] rv = new Attribute[attributes.Count]; - - for (int i = 0; i != rv.Length; i++) - { - rv[i] = Attribute.GetInstance(attributes[i]); - } - - return rv; + m_attributes = new BerSet(v); } + public virtual Attribute[] GetAttributes() => m_attributes.MapElements(Attribute.GetInstance); + /** *
          * Attributes ::=
@@ -47,9 +40,6 @@ namespace Org.BouncyCastle.Asn1.Cms
          * 
* @return */ - public override Asn1Object ToAsn1Object() - { - return attributes; - } + public override Asn1Object ToAsn1Object() => m_attributes; } } diff --git a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs index 6b4c0488e..12b1f518d 100644 --- a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs +++ b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs @@ -8,6 +8,35 @@ namespace Org.BouncyCastle.Asn1.Cms public class OriginatorIdentifierOrKey : Asn1Encodable, IAsn1Choice { + public static OriginatorIdentifierOrKey GetInstance( + object o) + { + if (o == null) + return null; + + if (o is OriginatorIdentifierOrKey originatorIdentifierOrKey) + return originatorIdentifierOrKey; + + if (o is IssuerAndSerialNumber issuerAndSerialNumber) + return new OriginatorIdentifierOrKey(issuerAndSerialNumber); + + if (o is SubjectKeyIdentifier subjectKeyIdentifier) + return new OriginatorIdentifierOrKey(subjectKeyIdentifier); + + if (o is OriginatorPublicKey originatorPublicKey) + return new OriginatorIdentifierOrKey(originatorPublicKey); + + if (o is Asn1TaggedObject taggedObject) + return new OriginatorIdentifierOrKey(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific)); + + throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + Platform.GetTypeName(o)); + } + + public static OriginatorIdentifierOrKey GetInstance(Asn1TaggedObject o, bool explicitly) + { + return Asn1Utilities.GetInstanceFromChoice(o, explicitly, GetInstance); + } + private readonly Asn1Encodable id; public OriginatorIdentifierOrKey(IssuerAndSerialNumber id) @@ -31,50 +60,6 @@ namespace Org.BouncyCastle.Asn1.Cms this.id = id; } - /** - * return an OriginatorIdentifierOrKey object from a tagged object. - * - * @param o the tagged object holding the object we want. - * @param explicitly true if the object is meant to be explicitly - * tagged false otherwise. - * @exception ArgumentException if the object held by the - * tagged object cannot be converted. - */ - public static OriginatorIdentifierOrKey GetInstance(Asn1TaggedObject o, bool explicitly) - { - return Asn1Utilities.GetInstanceFromChoice(o, explicitly, GetInstance); - } - - /** - * return an OriginatorIdentifierOrKey object from the given object. - * - * @param o the object we want converted. - * @exception ArgumentException if the object cannot be converted. - */ - public static OriginatorIdentifierOrKey GetInstance( - object o) - { - if (o == null) - return null; - - if (o is OriginatorIdentifierOrKey originatorIdentifierOrKey) - return originatorIdentifierOrKey; - - if (o is IssuerAndSerialNumber issuerAndSerialNumber) - return new OriginatorIdentifierOrKey(issuerAndSerialNumber); - - if (o is SubjectKeyIdentifier subjectKeyIdentifier) - return new OriginatorIdentifierOrKey(subjectKeyIdentifier); - - if (o is OriginatorPublicKey originatorPublicKey) - return new OriginatorIdentifierOrKey(originatorPublicKey); - - if (o is Asn1TaggedObject taggedObject) - return new OriginatorIdentifierOrKey(Asn1Utilities.CheckTagClass(taggedObject, Asn1Tags.ContextSpecific)); - - throw new ArgumentException("Invalid OriginatorIdentifierOrKey: " + Platform.GetTypeName(o)); - } - public Asn1Encodable ID { get { return id; } diff --git a/crypto/src/asn1/tsp/Accuracy.cs b/crypto/src/asn1/tsp/Accuracy.cs index f9cd88014..a4fd0443b 100644 --- a/crypto/src/asn1/tsp/Accuracy.cs +++ b/crypto/src/asn1/tsp/Accuracy.cs @@ -7,21 +7,31 @@ namespace Org.BouncyCastle.Asn1.Tsp public class Accuracy : Asn1Encodable { - private readonly DerInteger seconds; - private readonly DerInteger millis; - private readonly DerInteger micros; + protected const int MinMillis = 1; + protected const int MaxMillis = 999; + protected const int MinMicros = 1; + protected const int MaxMicros = 999; - // constants - protected const int MinMillis = 1; - protected const int MaxMillis = 999; - protected const int MinMicros = 1; - protected const int MaxMicros = 999; + public static Accuracy GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is Accuracy accuracy) + return accuracy; + return new Accuracy(Asn1Sequence.GetInstance(obj)); + } - public Accuracy( - DerInteger seconds, - DerInteger millis, - DerInteger micros) - { + public static Accuracy GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new Accuracy(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly DerInteger m_seconds; + private readonly DerInteger m_millis; + private readonly DerInteger m_micros; + + public Accuracy(DerInteger seconds, DerInteger millis, DerInteger micros) + { if (null != millis) { int millisValue = millis.IntValueExact; @@ -35,22 +45,26 @@ namespace Org.BouncyCastle.Asn1.Tsp throw new ArgumentException("Invalid micros field : not in (1..999)"); } - this.seconds = seconds; - this.millis = millis; - this.micros = micros; - } + m_seconds = seconds; + m_millis = millis; + m_micros = micros; + } + + private Accuracy(Asn1Sequence seq) + { + DerInteger seconds = null; + DerInteger millis = null; + DerInteger micros = null; - private Accuracy(Asn1Sequence seq) - { - for (int i = 0; i < seq.Count; ++i) - { - // seconds - if (seq[i] is DerInteger derInteger) - { - seconds = derInteger; - } + for (int i = 0; i < seq.Count; ++i) + { + // seconds + if (seq[i] is DerInteger derInteger) + { + seconds = derInteger; + } else if (seq[i] is Asn1TaggedObject extra) - { + { switch (extra.TagNo) { case 0: @@ -68,35 +82,21 @@ namespace Org.BouncyCastle.Asn1.Tsp default: throw new ArgumentException("Invalid tag number"); } - } - } - } + } + } - public static Accuracy GetInstance(object obj) - { - if (obj is Accuracy) - return (Accuracy)obj; - if (obj == null) - return null; - return new Accuracy(Asn1Sequence.GetInstance(obj)); + m_seconds = seconds; + m_millis = millis; + m_micros = micros; } - public DerInteger Seconds - { - get { return seconds; } - } + public DerInteger Seconds => m_seconds; - public DerInteger Millis - { - get { return millis; } - } + public DerInteger Millis => m_millis; - public DerInteger Micros - { - get { return micros; } - } + public DerInteger Micros => m_micros; - /** + /** *
 		 * Accuracy ::= SEQUENCE {
 		 *             seconds        INTEGER              OPTIONAL,
@@ -108,10 +108,10 @@ namespace Org.BouncyCastle.Asn1.Tsp
         public override Asn1Object ToAsn1Object()
         {
             Asn1EncodableVector v = new Asn1EncodableVector(3);
-            v.AddOptional(seconds);
-            v.AddOptionalTagged(false, 0, millis);
-            v.AddOptionalTagged(false, 1, micros);
+            v.AddOptional(m_seconds);
+            v.AddOptionalTagged(false, 0, m_millis);
+            v.AddOptionalTagged(false, 1, m_micros);
             return new DerSequence(v);
         }
-	}
+    }
 }
diff --git a/crypto/src/asn1/tsp/ArchiveTimeStamp.cs b/crypto/src/asn1/tsp/ArchiveTimeStamp.cs
new file mode 100644
index 000000000..57cc02138
--- /dev/null
+++ b/crypto/src/asn1/tsp/ArchiveTimeStamp.cs
@@ -0,0 +1,176 @@
+using System;
+
+using Org.BouncyCastle.Asn1.Cms;
+using Org.BouncyCastle.Asn1.X509;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+    /**
+     * Implementation of the Archive Timestamp type defined in RFC4998.
+     * @see RFC 4998
+     * 

+ * ASN.1 Archive Timestamp + *

+ * ArchiveTimeStamp ::= SEQUENCE { + * digestAlgorithm [Ø] AlgorithmIdentifier OPTIONAL, + * attributes [1] Attributes OPTIONAL, + * reducedHashtree [2] SEQUENCE OF PartialHashtree OPTIONAL, + * timeStamp ContentInfo} + *

+ * PartialHashtree ::= SEQUENCE OF OCTET STRING + *

+ * Attributes ::= SET SIZE (1..MAX) OF Attribute + */ + public class ArchiveTimeStamp + : Asn1Encodable + { + /** + * Return an ArchiveTimestamp from the given object. + * + * @param obj the object we want converted. + * @return an ArchiveTimestamp instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static ArchiveTimeStamp GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is ArchiveTimeStamp archiveTimeStamp) + return archiveTimeStamp; + return new ArchiveTimeStamp(Asn1Sequence.GetInstance(obj)); + } + + public static ArchiveTimeStamp GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new ArchiveTimeStamp(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly AlgorithmIdentifier m_digestAlgorithm; + private readonly Attributes m_attributes; + private readonly Asn1Sequence m_reducedHashTree; + private readonly ContentInfo m_timeStamp; + + public ArchiveTimeStamp(AlgorithmIdentifier digestAlgorithm, PartialHashtree[] reducedHashTree, + ContentInfo timeStamp) + : this(digestAlgorithm, null, reducedHashTree, timeStamp) + { + } + + public ArchiveTimeStamp(ContentInfo timeStamp) + : this(null, null, null, timeStamp) + { + } + + public ArchiveTimeStamp(AlgorithmIdentifier digestAlgorithm, Attributes attributes, + PartialHashtree[] reducedHashTree, ContentInfo timeStamp) + { + m_digestAlgorithm = digestAlgorithm; + m_attributes = attributes; + if (reducedHashTree != null) + { + m_reducedHashTree = new DerSequence(reducedHashTree); + } + else + { + m_reducedHashTree = null; + } + m_timeStamp = timeStamp; + } + + private ArchiveTimeStamp(Asn1Sequence sequence) + { + if (sequence.Count < 1 || sequence.Count > 4) + throw new ArgumentException("wrong sequence size in constructor: " + sequence.Count, nameof(sequence)); + + AlgorithmIdentifier digAlg = null; + Attributes attrs = null; + Asn1Sequence rHashTree = null; + for (int i = 0; i < sequence.Count - 1; i++) + { + Asn1Encodable obj = sequence[i]; + + if (obj is Asn1TaggedObject taggedObject) + { + switch (taggedObject.TagNo) + { + case 0: + digAlg = AlgorithmIdentifier.GetInstance(taggedObject, false); + break; + case 1: + attrs = Attributes.GetInstance(taggedObject, false); + break; + case 2: + rHashTree = Asn1Sequence.GetInstance(taggedObject, false); + break; + default: + throw new ArgumentException("invalid tag no in constructor: " + taggedObject.TagNo); + } + } + } + + m_digestAlgorithm = digAlg; + m_attributes = attrs; + m_reducedHashTree = rHashTree; + m_timeStamp = ContentInfo.GetInstance(sequence[sequence.Count - 1]); + } + + public virtual AlgorithmIdentifier GetDigestAlgorithmIdentifier() => m_digestAlgorithm + ?? GetTimeStampInfo().MessageImprint.HashAlgorithm; + + public virtual byte[] GetTimeStampDigestValue() => GetTimeStampInfo().MessageImprint.GetHashedMessage(); + + private TstInfo GetTimeStampInfo() + { + if (!CmsObjectIdentifiers.SignedData.Equals(m_timeStamp.ContentType)) + throw new InvalidOperationException("cannot identify algorithm identifier for digest"); + + SignedData tsData = SignedData.GetInstance(m_timeStamp.Content); + var contentInfo = tsData.EncapContentInfo; + + if (!Asn1.Pkcs.PkcsObjectIdentifiers.IdCTTstInfo.Equals(contentInfo.ContentType)) + throw new InvalidOperationException("cannot parse time stamp"); + + return TstInfo.GetInstance(Asn1OctetString.GetInstance(contentInfo.Content).GetOctets()); + } + + /** + * Return the contents of the digestAlgorithm field - null if not set. + * + * @return the contents of the digestAlgorithm field, or null if not set. + */ + public virtual AlgorithmIdentifier DigestAlgorithm() => m_digestAlgorithm; + + /** + * Return the first node in the reduced hash tree which contains the leaf node. + * + * @return the node containing the data hashes, null if no reduced hash tree is present. + */ + public virtual PartialHashtree GetHashTreeLeaf() + { + if (m_reducedHashTree == null) + return null; + + return PartialHashtree.GetInstance(m_reducedHashTree[0]); + } + + public virtual PartialHashtree[] GetReducedHashTree() + { + if (m_reducedHashTree == null) + return null; + + return m_reducedHashTree.MapElements(PartialHashtree.GetInstance); + } + + public virtual ContentInfo TimeStamp => m_timeStamp; + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(4); + v.AddOptionalTagged(false, 0, m_digestAlgorithm); + v.AddOptionalTagged(false, 1, m_attributes); + v.AddOptionalTagged(false, 2, m_reducedHashTree); + v.Add(m_timeStamp); + return new DerSequence(v); + } + } +} diff --git a/crypto/src/asn1/tsp/ArchiveTimeStampChain.cs b/crypto/src/asn1/tsp/ArchiveTimeStampChain.cs new file mode 100644 index 000000000..13138d6f9 --- /dev/null +++ b/crypto/src/asn1/tsp/ArchiveTimeStampChain.cs @@ -0,0 +1,86 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + /** + * Implementation of ArchiveTimeStampChain type, as defined in RFC4998 and RFC6283. + *

+ * An ArchiveTimeStampChain corresponds to a SEQUENCE OF ArchiveTimeStamps, and has the following + * ASN.1 Syntax: + *

+ * ArchiveTimeStampChain ::= SEQUENCE OF ArchiveTimeStamp + */ + public class ArchiveTimeStampChain + : Asn1Encodable + { + /** + * Return an ArchiveTimeStampChain from the given object. + * + * @param obj the object we want converted. + * @return an ArchiveTimeStampChain instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static ArchiveTimeStampChain GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is ArchiveTimeStampChain archiveTimeStampChain) + return archiveTimeStampChain; + return new ArchiveTimeStampChain(Asn1Sequence.GetInstance(obj)); + } + + public static ArchiveTimeStampChain GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new ArchiveTimeStampChain(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly Asn1Sequence m_archiveTimeStamps; + + public ArchiveTimeStampChain(ArchiveTimeStamp archiveTimeStamp) + { + m_archiveTimeStamps = new DerSequence(archiveTimeStamp); + } + + public ArchiveTimeStampChain(ArchiveTimeStamp[] archiveTimeStamps) + { + m_archiveTimeStamps = new DerSequence(archiveTimeStamps); + } + + private ArchiveTimeStampChain(Asn1Sequence sequence) + { + Asn1EncodableVector vector = new Asn1EncodableVector(sequence.Count); + + foreach (var element in sequence) + { + vector.Add(ArchiveTimeStamp.GetInstance(element)); + } + + m_archiveTimeStamps = new DerSequence(vector); + } + + public virtual ArchiveTimeStamp[] GetArchiveTimestamps() => + m_archiveTimeStamps.MapElements(ArchiveTimeStamp.GetInstance); + + /** + * Adds an {@link ArchiveTimeStamp} object to the archive timestamp chain. + * + * @param archiveTimeStamp the {@link ArchiveTimeStamp} to add. + * @return returns the modified chain. + */ + public virtual ArchiveTimeStampChain Append(ArchiveTimeStamp archiveTimeStamp) + { + Asn1EncodableVector v = new Asn1EncodableVector(m_archiveTimeStamps.Count + 1); + + foreach (var element in m_archiveTimeStamps) + { + v.Add(element); + } + + v.Add(archiveTimeStamp); + + return new ArchiveTimeStampChain(new DerSequence(v)); + } + + public override Asn1Object ToAsn1Object() => m_archiveTimeStamps; + } +} diff --git a/crypto/src/asn1/tsp/ArchiveTimeStampSequence.cs b/crypto/src/asn1/tsp/ArchiveTimeStampSequence.cs new file mode 100644 index 000000000..766f6704c --- /dev/null +++ b/crypto/src/asn1/tsp/ArchiveTimeStampSequence.cs @@ -0,0 +1,93 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + /** + * Implementation of ArchiveTimeStampSequence type, as defined in RFC4998. + *

+ * An ArchiveTimeStampSequence corresponds to a SEQUENCE OF ArchiveTimeStampChains and has the + * following ASN.1 Syntax: + *

+ * ArchiveTimeStampSequence ::= SEQUENCE OF ArchiveTimeStampChain + */ + public class ArchiveTimeStampSequence + : Asn1Encodable + { + /** + * Return an ArchiveTimestampSequence from the given object. + * + * @param obj the object we want converted. + * @return an ArchiveTimeStampSequence instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static ArchiveTimeStampSequence GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is ArchiveTimeStampSequence archiveTimeStampSequence) + return archiveTimeStampSequence; + return new ArchiveTimeStampSequence(Asn1Sequence.GetInstance(obj)); + } + + public static ArchiveTimeStampSequence GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new ArchiveTimeStampSequence(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly Asn1Sequence m_archiveTimeStampChains; + + private ArchiveTimeStampSequence(Asn1Sequence sequence) + { + Asn1EncodableVector vector = new Asn1EncodableVector(sequence.Count); + + foreach (var element in sequence) + { + vector.Add(ArchiveTimeStampChain.GetInstance(element)); + } + + m_archiveTimeStampChains = new DerSequence(vector); + } + + public ArchiveTimeStampSequence(ArchiveTimeStampChain archiveTimeStampChain) + { + m_archiveTimeStampChains = new DerSequence(archiveTimeStampChain); + } + + public ArchiveTimeStampSequence(ArchiveTimeStampChain[] archiveTimeStampChains) + { + m_archiveTimeStampChains = new DerSequence(archiveTimeStampChains); + } + + /** + * Returns the sequence of ArchiveTimeStamp chains that compose the ArchiveTimeStamp sequence. + * + * @return the {@link ASN1Sequence} containing the ArchiveTimeStamp chains. + */ + public virtual ArchiveTimeStampChain[] GetArchiveTimeStampChains() => + m_archiveTimeStampChains.MapElements(ArchiveTimeStampChain.GetInstance); + + public virtual int Count => m_archiveTimeStampChains.Count; + + /** + * Adds an {@link ArchiveTimeStampChain} to the ArchiveTimeStamp sequence. + * + * @param chain the {@link ArchiveTimeStampChain} to add + * @return returns the modified sequence. + */ + public virtual ArchiveTimeStampSequence Append(ArchiveTimeStampChain chain) + { + Asn1EncodableVector v = new Asn1EncodableVector(m_archiveTimeStampChains.Count + 1); + + foreach (var element in m_archiveTimeStampChains) + { + v.Add(element); + } + + v.Add(chain); + + return new ArchiveTimeStampSequence(new DerSequence(v)); + } + + public override Asn1Object ToAsn1Object() => m_archiveTimeStampChains; + } +} diff --git a/crypto/src/asn1/tsp/CryptoInfos.cs b/crypto/src/asn1/tsp/CryptoInfos.cs new file mode 100644 index 000000000..b0b84c014 --- /dev/null +++ b/crypto/src/asn1/tsp/CryptoInfos.cs @@ -0,0 +1,43 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + /** + * Implementation of the CryptoInfos element defined in RFC 4998: + *

+ * CryptoInfos ::= SEQUENCE SIZE (1..MAX) OF Attribute + */ + public class CryptoInfos + : Asn1Encodable + { + public static CryptoInfos GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is CryptoInfos cryptoInfos) + return cryptoInfos; + return new CryptoInfos(Asn1Sequence.GetInstance(obj)); + } + + public static CryptoInfos GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new CryptoInfos(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly Asn1Sequence m_attributes; + + private CryptoInfos(Asn1Sequence attributes) + { + m_attributes = attributes; + } + + public CryptoInfos(Asn1.Cms.Attribute[] attrs) + { + m_attributes = new DerSequence(attrs); + } + + public virtual Asn1.Cms.Attribute[] GetAttributes() => m_attributes.MapElements(Asn1.Cms.Attribute.GetInstance); + + public override Asn1Object ToAsn1Object() => m_attributes; + } +} diff --git a/crypto/src/asn1/tsp/EncryptionInfo.cs b/crypto/src/asn1/tsp/EncryptionInfo.cs new file mode 100644 index 000000000..e712c6a00 --- /dev/null +++ b/crypto/src/asn1/tsp/EncryptionInfo.cs @@ -0,0 +1,76 @@ +using System; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + /** + * Implementation of the EncryptionInfo element defined in RFC 4998: + *

+ * 1988 ASN.1 EncryptionInfo + *

+ * EncryptionInfo ::= SEQUENCE { + * encryptionInfoType OBJECT IDENTIFIER, + * encryptionInfoValue ANY DEFINED BY encryptionInfoType + * } + *

+ * 1997-ASN.1 EncryptionInfo + *

+ * EncryptionInfo ::= SEQUENCE { + * encryptionInfoType ENCINFO-TYPE.&id + * ({SupportedEncryptionAlgorithms}), + * encryptionInfoValue ENCINFO-TYPE.&Type + * ({SupportedEncryptionAlgorithms}{@encryptionInfoType}) + * } + *

+ * ENCINFO-TYPE ::= TYPE-IDENTIFIER + *

+ * SupportedEncryptionAlgorithms ENCINFO-TYPE ::= {...} + */ + public class EncryptionInfo + : Asn1Encodable + { + public static EncryptionInfo GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is EncryptionInfo encryptionInfo) + return encryptionInfo; + return new EncryptionInfo(Asn1Sequence.GetInstance(obj)); + } + + public static EncryptionInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new EncryptionInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + /** + * The OID for EncryptionInfo type. + */ + private readonly DerObjectIdentifier m_encryptionInfoType; + + /** + * The value of EncryptionInfo + */ + private readonly Asn1Encodable m_encryptionInfoValue; + + private EncryptionInfo(Asn1Sequence sequence) + { + if (sequence.Count != 2) + throw new ArgumentException("wrong sequence size in constructor: " + sequence.Count, nameof(sequence)); + + m_encryptionInfoType = DerObjectIdentifier.GetInstance(sequence[0]); + m_encryptionInfoValue = sequence[1]; + } + + public EncryptionInfo(DerObjectIdentifier encryptionInfoType, Asn1Encodable encryptionInfoValue) + { + m_encryptionInfoType = encryptionInfoType; + m_encryptionInfoValue = encryptionInfoValue; + } + + public virtual DerObjectIdentifier EncryptionInfoType => m_encryptionInfoType; + + public virtual Asn1Encodable EncryptionInfoValue => m_encryptionInfoValue; + + public override Asn1Object ToAsn1Object() => new DLSequence(m_encryptionInfoType, m_encryptionInfoValue); + } +} diff --git a/crypto/src/asn1/tsp/EvidenceRecord.cs b/crypto/src/asn1/tsp/EvidenceRecord.cs new file mode 100644 index 000000000..42ec4bf16 --- /dev/null +++ b/crypto/src/asn1/tsp/EvidenceRecord.cs @@ -0,0 +1,217 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; +using Org.BouncyCastle.Utilities; + +namespace Org.BouncyCastle.Asn1.Tsp +{ + /** + * RFC 4998: + * Evidence Record Syntax (ERS) + *

+ *

+     * EvidenceRecord ::= SEQUENCE {
+     *   version                   INTEGER { v1(1) } ,
+     *   digestAlgorithms          SEQUENCE OF AlgorithmIdentifier,
+     *   cryptoInfos               [0] CryptoInfos OPTIONAL,
+     *   encryptionInfo            [1] EncryptionInfo OPTIONAL,
+     *   archiveTimeStampSequence  ArchiveTimeStampSequence
+     * }
+     *
+     * CryptoInfos ::= SEQUENCE SIZE (1..MAX) OF Attribute
+     * 
+ */ + public class EvidenceRecord + : Asn1Encodable + { + /** + * ERS {iso(1) identified-organization(3) dod(6) internet(1) security(5) mechanisms(5) ltans(11) + * id-mod(0) id-mod-ers88(2) id-mod-ers88-v1(1) } + */ + private static readonly DerObjectIdentifier Oid = new DerObjectIdentifier("1.3.6.1.5.5.11.0.2.1"); + + /** + * Return an EvidenceRecord from the given object. + * + * @param obj the object we want converted. + * @return an EvidenceRecord instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static EvidenceRecord GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is EvidenceRecord evidenceRecord) + return evidenceRecord; + return new EvidenceRecord(Asn1Sequence.GetInstance(obj)); + } + + public static EvidenceRecord GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new EvidenceRecord(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly DerInteger m_version; + private readonly Asn1Sequence m_digestAlgorithms; + private readonly CryptoInfos m_cryptoInfos; + private readonly EncryptionInfo m_encryptionInfo; + private readonly ArchiveTimeStampSequence m_archiveTimeStampSequence; + + private EvidenceRecord(EvidenceRecord evidenceRecord, ArchiveTimeStampSequence replacementSequence, + ArchiveTimeStamp newChainTimeStamp) + { + m_version = evidenceRecord.m_version; + + // check the list of digest algorithms is correct. + if (newChainTimeStamp != null) + { + AlgorithmIdentifier algID = newChainTimeStamp.GetDigestAlgorithmIdentifier(); + Asn1EncodableVector vector = new Asn1EncodableVector(); + + bool found = false; + + foreach (var element in evidenceRecord.m_digestAlgorithms) + { + AlgorithmIdentifier algorithmIdentifier = AlgorithmIdentifier.GetInstance(element); + vector.Add(algorithmIdentifier); + + if (algorithmIdentifier.Equals(algID)) + { + found = true; + break; + } + } + + if (!found) + { + vector.Add(algID); + m_digestAlgorithms = new DerSequence(vector); + } + else + { + m_digestAlgorithms = evidenceRecord.m_digestAlgorithms; + } + } + else + { + m_digestAlgorithms = evidenceRecord.m_digestAlgorithms; + } + + m_cryptoInfos = evidenceRecord.m_cryptoInfos; + m_encryptionInfo = evidenceRecord.m_encryptionInfo; + m_archiveTimeStampSequence = replacementSequence; + } + + /** + * Build a basic evidence record from an initial + * ArchiveTimeStamp. + * + * @param cryptoInfos + * @param encryptionInfo + * @param archiveTimeStamp + */ + public EvidenceRecord(CryptoInfos cryptoInfos, EncryptionInfo encryptionInfo, ArchiveTimeStamp archiveTimeStamp) + { + m_version = new DerInteger(1); + m_digestAlgorithms = new DerSequence(archiveTimeStamp.GetDigestAlgorithmIdentifier()); + m_cryptoInfos = cryptoInfos; + m_encryptionInfo = encryptionInfo; + m_archiveTimeStampSequence = new ArchiveTimeStampSequence(new ArchiveTimeStampChain(archiveTimeStamp)); + } + + public EvidenceRecord(AlgorithmIdentifier[] digestAlgorithms, CryptoInfos cryptoInfos, + EncryptionInfo encryptionInfo, ArchiveTimeStampSequence archiveTimeStampSequence) + { + m_version = new DerInteger(1); + m_digestAlgorithms = new DerSequence(digestAlgorithms); + m_cryptoInfos = cryptoInfos; + m_encryptionInfo = encryptionInfo; + m_archiveTimeStampSequence = archiveTimeStampSequence; + } + + private EvidenceRecord(Asn1Sequence sequence) + { + if (sequence.Count < 3 && sequence.Count > 5) + throw new ArgumentException("wrong sequence size in constructor: " + sequence.Count, nameof(sequence)); + + DerInteger versionNumber = DerInteger.GetInstance(sequence[0]); + if (!versionNumber.HasValue(1)) + throw new ArgumentException("incompatible version"); + + m_version = versionNumber; + + m_digestAlgorithms = Asn1Sequence.GetInstance(sequence[1]); + for (int i = 2; i != sequence.Count - 1; i++) + { + Asn1Encodable element = sequence[i]; + + if (element is Asn1TaggedObject asn1TaggedObject) + { + switch (asn1TaggedObject.TagNo) + { + case 0: + m_cryptoInfos = CryptoInfos.GetInstance(asn1TaggedObject, false); + break; + case 1: + m_encryptionInfo = EncryptionInfo.GetInstance(asn1TaggedObject, false); + break; + default: + throw new ArgumentException("unknown tag in GetInstance: " + asn1TaggedObject.TagNo); + } + } + else + { + throw new ArgumentException("unknown object in GetInstance: " + Platform.GetTypeName(element)); + } + } + m_archiveTimeStampSequence = ArchiveTimeStampSequence.GetInstance(sequence[sequence.Count - 1]); + } + + public virtual AlgorithmIdentifier[] GetDigestAlgorithms() => + m_digestAlgorithms.MapElements(AlgorithmIdentifier.GetInstance); + + public virtual ArchiveTimeStampSequence ArchiveTimeStampSequence => m_archiveTimeStampSequence; + + /** + * Return a new EvidenceRecord with an added ArchiveTimeStamp + * + * @param ats the archive timestamp to add + * @param newChain states whether this new archive timestamp must be added as part of a + * new sequence (i.e. in the case of hashtree renewal) or not (i.e. in the case of timestamp + * renewal) + * @return the new EvidenceRecord + */ + public virtual EvidenceRecord AddArchiveTimeStamp(ArchiveTimeStamp ats, bool newChain) + { + if (newChain) + { + ArchiveTimeStampChain chain = new ArchiveTimeStampChain(ats); + + return new EvidenceRecord(this, m_archiveTimeStampSequence.Append(chain), ats); + } + else + { + ArchiveTimeStampChain[] chains = m_archiveTimeStampSequence.GetArchiveTimeStampChains(); + + AlgorithmIdentifier digAlg = chains[chains.Length - 1].GetArchiveTimestamps()[0] + .GetDigestAlgorithmIdentifier(); + if (!digAlg.Equals(ats.GetDigestAlgorithmIdentifier())) + throw new ArgumentException("mismatch of digest algorithm in AddArchiveTimeStamp"); + + chains[chains.Length - 1] = chains[chains.Length - 1].Append(ats); + return new EvidenceRecord(this, new ArchiveTimeStampSequence(chains), null); + } + } + + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector vector = new Asn1EncodableVector(5); + vector.Add(m_version); + vector.Add(m_digestAlgorithms); + vector.AddOptionalTagged(false, 0, m_cryptoInfos); + vector.AddOptionalTagged(false, 1, m_encryptionInfo); + vector.Add(m_archiveTimeStampSequence); + return new DerSequence(vector); + } + } +} diff --git a/crypto/src/asn1/tsp/MessageImprint.cs b/crypto/src/asn1/tsp/MessageImprint.cs index cb728629c..0be856048 100644 --- a/crypto/src/asn1/tsp/MessageImprint.cs +++ b/crypto/src/asn1/tsp/MessageImprint.cs @@ -8,46 +8,42 @@ namespace Org.BouncyCastle.Asn1.Tsp public class MessageImprint : Asn1Encodable { - private readonly AlgorithmIdentifier hashAlgorithm; - private readonly byte[] hashedMessage; - public static MessageImprint GetInstance(object obj) { - if (obj is MessageImprint) - return (MessageImprint)obj; if (obj == null) return null; + if (obj is MessageImprint messageImprint) + return messageImprint; return new MessageImprint(Asn1Sequence.GetInstance(obj)); } - private MessageImprint( - Asn1Sequence seq) + public static MessageImprint GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) { - if (seq.Count != 2) - throw new ArgumentException("Wrong number of elements in sequence", "seq"); + return new MessageImprint(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } - this.hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); - this.hashedMessage = Asn1OctetString.GetInstance(seq[1]).GetOctets(); - } + private readonly AlgorithmIdentifier m_hashAlgorithm; + private readonly byte[] m_hashedMessage; - public MessageImprint( - AlgorithmIdentifier hashAlgorithm, - byte[] hashedMessage) + private MessageImprint(Asn1Sequence seq) { - this.hashAlgorithm = hashAlgorithm; - this.hashedMessage = hashedMessage; - } + if (seq.Count != 2) + throw new ArgumentException("Wrong number of elements in sequence", nameof(seq)); - public AlgorithmIdentifier HashAlgorithm - { - get { return hashAlgorithm; } + m_hashAlgorithm = AlgorithmIdentifier.GetInstance(seq[0]); + m_hashedMessage = Asn1OctetString.GetInstance(seq[1]).GetOctets(); } - public byte[] GetHashedMessage() + public MessageImprint(AlgorithmIdentifier hashAlgorithm, byte[] hashedMessage) { - return hashedMessage; + m_hashAlgorithm = hashAlgorithm; + m_hashedMessage = hashedMessage; } + public AlgorithmIdentifier HashAlgorithm => m_hashAlgorithm; + + public byte[] GetHashedMessage() => m_hashedMessage; + /** *
 		 *    MessageImprint ::= SEQUENCE  {
@@ -57,7 +53,7 @@ namespace Org.BouncyCastle.Asn1.Tsp
 		 */
 		public override Asn1Object ToAsn1Object()
 		{
-			return new DerSequence(hashAlgorithm, new DerOctetString(hashedMessage));
+			return new DerSequence(m_hashAlgorithm, new DerOctetString(m_hashedMessage));
 		}
 	}
 }
diff --git a/crypto/src/asn1/tsp/PartialHashtree.cs b/crypto/src/asn1/tsp/PartialHashtree.cs
new file mode 100644
index 000000000..a32a9f18b
--- /dev/null
+++ b/crypto/src/asn1/tsp/PartialHashtree.cs
@@ -0,0 +1,91 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+using Org.BouncyCastle.Utilities.Collections;
+
+namespace Org.BouncyCastle.Asn1.Tsp
+{
+    /**
+     * Implementation of PartialHashtree, as defined in RFC 4998.
+     * 

+ * The ASN.1 notation for a PartialHashTree is: + *

+ * PartialHashtree ::= SEQUENCE OF OCTET STRING + */ + public class PartialHashtree + : Asn1Encodable + { + /** + * Return a PartialHashtree from the given object. + * + * @param obj the object we want converted. + * @return a PartialHashtree instance, or null. + * @throws IllegalArgumentException if the object cannot be converted. + */ + public static PartialHashtree GetInstance(object obj) + { + if (obj == null) + return null; + if (obj is PartialHashtree partialHashtree) + return partialHashtree; + return new PartialHashtree(Asn1Sequence.GetInstance(obj)); + } + + public static PartialHashtree GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new PartialHashtree(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + /** + * Hash values that constitute the hash tree, as ASN.1 Octet Strings. + */ + private readonly Asn1Sequence m_values; + + private PartialHashtree(Asn1Sequence values) + { + for (int i = 0; i != values.Count; i++) + { + if (!(values[i] is Asn1OctetString)) + throw new ArgumentException("unknown object in constructor: " + Platform.GetTypeName(values[i])); + } + m_values = values; + } + + public PartialHashtree(byte[] value) + { + m_values = new DerSequence(new DerOctetString(Arrays.Clone(value))); + } + + public PartialHashtree(byte[][] values) + { + Asn1EncodableVector v = new Asn1EncodableVector(values.Length); + + for (int i = 0; i != values.Length; i++) + { + v.Add(new DerOctetString(Arrays.Clone(values[i]))); + } + + m_values = new DerSequence(v); + } + + public virtual int ValueCount => m_values.Count; + + public virtual byte[][] GetValues() => m_values.MapElements( + element => Arrays.Clone(Asn1OctetString.GetInstance(element).GetOctets())); + + public virtual bool ContainsHash(byte[] hash) + { + foreach (Asn1OctetString octetString in m_values) + { + byte[] currentHash = octetString.GetOctets(); + + if (Arrays.FixedTimeEquals(hash, currentHash)) + return true; + } + + return false; + } + + public override Asn1Object ToAsn1Object() => m_values; + } +} diff --git a/crypto/src/asn1/tsp/TSTInfo.cs b/crypto/src/asn1/tsp/TSTInfo.cs index a8e166cbc..8aefe6159 100644 --- a/crypto/src/asn1/tsp/TSTInfo.cs +++ b/crypto/src/asn1/tsp/TSTInfo.cs @@ -7,25 +7,30 @@ namespace Org.BouncyCastle.Asn1.Tsp public class TstInfo : Asn1Encodable { - private readonly DerInteger version; - private readonly DerObjectIdentifier tsaPolicyId; - private readonly MessageImprint messageImprint; - private readonly DerInteger serialNumber; - private readonly Asn1GeneralizedTime genTime; - private readonly Accuracy accuracy; - private readonly DerBoolean ordering; - private readonly DerInteger nonce; - private readonly GeneralName tsa; - private readonly X509Extensions extensions; - - public static TstInfo GetInstance(object obj) - { - if (obj is TstInfo) - return (TstInfo)obj; + public static TstInfo GetInstance(object obj) + { if (obj == null) return null; + if (obj is TstInfo tstInfo) + return tstInfo; return new TstInfo(Asn1Sequence.GetInstance(obj)); - } + } + + public static TstInfo GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit) + { + return new TstInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); + } + + private readonly DerInteger m_version; + private readonly DerObjectIdentifier m_tsaPolicyID; + private readonly MessageImprint m_messageImprint; + private readonly DerInteger m_serialNumber; + private readonly Asn1GeneralizedTime m_genTime; + private readonly Accuracy m_accuracy; + private readonly DerBoolean m_ordering; + private readonly DerInteger m_nonce; + private readonly GeneralName m_tsa; + private readonly X509Extensions m_extensions; private TstInfo(Asn1Sequence seq) { @@ -33,26 +38,26 @@ namespace Org.BouncyCastle.Asn1.Tsp // version e.MoveNext(); - version = DerInteger.GetInstance(e.Current); + m_version = DerInteger.GetInstance(e.Current); // tsaPolicy e.MoveNext(); - tsaPolicyId = DerObjectIdentifier.GetInstance(e.Current); + m_tsaPolicyID = DerObjectIdentifier.GetInstance(e.Current); // messageImprint e.MoveNext(); - messageImprint = MessageImprint.GetInstance(e.Current); + m_messageImprint = MessageImprint.GetInstance(e.Current); // serialNumber e.MoveNext(); - serialNumber = DerInteger.GetInstance(e.Current); + m_serialNumber = DerInteger.GetInstance(e.Current); // genTime e.MoveNext(); - genTime = Asn1GeneralizedTime.GetInstance(e.Current); + m_genTime = Asn1GeneralizedTime.GetInstance(e.Current); // default for ordering - ordering = DerBoolean.False; + m_ordering = DerBoolean.False; while (e.MoveNext()) { @@ -63,10 +68,10 @@ namespace Org.BouncyCastle.Asn1.Tsp switch (tagged.TagNo) { case 0: - tsa = GeneralName.GetInstance(tagged, true); + m_tsa = GeneralName.GetInstance(tagged, true); break; case 1: - extensions = X509Extensions.GetInstance(tagged, false); + m_extensions = X509Extensions.GetInstance(tagged, false); break; default: throw new ArgumentException("Unknown tag value " + tagged.TagNo); @@ -75,95 +80,58 @@ namespace Org.BouncyCastle.Asn1.Tsp if (o is Asn1Sequence) { - accuracy = Accuracy.GetInstance(o); + m_accuracy = Accuracy.GetInstance(o); } if (o is DerBoolean) { - ordering = DerBoolean.GetInstance(o); + m_ordering = DerBoolean.GetInstance(o); } if (o is DerInteger) { - nonce = DerInteger.GetInstance(o); + m_nonce = DerInteger.GetInstance(o); } } } - public TstInfo( - DerObjectIdentifier tsaPolicyId, - MessageImprint messageImprint, - DerInteger serialNumber, - Asn1GeneralizedTime genTime, - Accuracy accuracy, - DerBoolean ordering, - DerInteger nonce, - GeneralName tsa, - X509Extensions extensions) - { - this.version = new DerInteger(1); - this.tsaPolicyId = tsaPolicyId; - this.messageImprint = messageImprint; - this.serialNumber = serialNumber; - this.genTime = genTime; - this.accuracy = accuracy; - this.ordering = ordering; - this.nonce = nonce; - this.tsa = tsa; - this.extensions = extensions; - } - - public DerInteger Version + public TstInfo(DerObjectIdentifier tsaPolicyId, MessageImprint messageImprint, DerInteger serialNumber, + Asn1GeneralizedTime genTime, Accuracy accuracy, DerBoolean ordering, DerInteger nonce, GeneralName tsa, + X509Extensions extensions) { - get { return version; } + m_version = new DerInteger(1); + m_tsaPolicyID = tsaPolicyId; + m_messageImprint = messageImprint; + m_serialNumber = serialNumber; + m_genTime = genTime; + m_accuracy = accuracy; + m_ordering = ordering; + m_nonce = nonce; + m_tsa = tsa; + m_extensions = extensions; } - public MessageImprint MessageImprint - { - get { return messageImprint; } - } + public DerInteger Version => m_version; - public DerObjectIdentifier Policy - { - get { return tsaPolicyId; } - } + public MessageImprint MessageImprint => m_messageImprint; - public DerInteger SerialNumber - { - get { return serialNumber; } - } + public DerObjectIdentifier Policy => m_tsaPolicyID; - public Accuracy Accuracy - { - get { return accuracy; } - } + public DerInteger SerialNumber => m_serialNumber; - public Asn1GeneralizedTime GenTime - { - get { return genTime; } - } + public Accuracy Accuracy => m_accuracy; - public DerBoolean Ordering - { - get { return ordering; } - } + public Asn1GeneralizedTime GenTime => m_genTime; - public DerInteger Nonce - { - get { return nonce; } - } + public DerBoolean Ordering => m_ordering; - public GeneralName Tsa - { - get { return tsa; } - } + public DerInteger Nonce => m_nonce; - public X509Extensions Extensions - { - get { return extensions; } - } + public GeneralName Tsa => m_tsa; + + public X509Extensions Extensions => m_extensions; - /** + /** *

 		 *
 		 *     TstInfo ::= SEQUENCE  {
@@ -188,18 +156,19 @@ namespace Org.BouncyCastle.Asn1.Tsp
 		 */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, tsaPolicyId, messageImprint, serialNumber, genTime);
-            v.AddOptional(accuracy);
+            Asn1EncodableVector v = new Asn1EncodableVector(10);
+            v.Add(m_version, m_tsaPolicyID, m_messageImprint, m_serialNumber, m_genTime);
+            v.AddOptional(m_accuracy);
 
-            if (ordering != null && ordering.IsTrue)
+            if (m_ordering != null && m_ordering.IsTrue)
             {
-                v.Add(ordering);
+                v.Add(m_ordering);
             }
 
-            v.AddOptional(nonce);
-            v.AddOptionalTagged(true, 0, tsa);
-            v.AddOptionalTagged(false, 1, extensions);
+            v.AddOptional(m_nonce);
+            v.AddOptionalTagged(true, 0, m_tsa);
+            v.AddOptionalTagged(false, 1, m_extensions);
             return new DerSequence(v);
         }
-	}
+    }
 }
diff --git a/crypto/src/asn1/tsp/TimeStampReq.cs b/crypto/src/asn1/tsp/TimeStampReq.cs
index 027c0a45b..6b3afd553 100644
--- a/crypto/src/asn1/tsp/TimeStampReq.cs
+++ b/crypto/src/asn1/tsp/TimeStampReq.cs
@@ -8,107 +8,90 @@ namespace Org.BouncyCastle.Asn1.Tsp
 	public class TimeStampReq
 		: Asn1Encodable
 	{
-		private readonly DerInteger				version;
-		private readonly MessageImprint			messageImprint;
-		private readonly DerObjectIdentifier	tsaPolicy;
-		private readonly DerInteger				nonce;
-		private readonly DerBoolean				certReq;
-		private readonly X509Extensions			extensions;
+		private readonly DerInteger m_version;
+		private readonly MessageImprint m_messageImprint;
+		private readonly DerObjectIdentifier m_tsaPolicy;
+		private readonly DerInteger m_nonce;
+		private readonly DerBoolean m_certReq;
+		private readonly X509Extensions m_extensions;
 
         public static TimeStampReq GetInstance(object obj)
         {
-            if (obj is TimeStampReq)
-                return (TimeStampReq)obj;
             if (obj == null)
                 return null;
+            if (obj is TimeStampReq timeStampReq)
+                return timeStampReq;
             return new TimeStampReq(Asn1Sequence.GetInstance(obj));
         }
 
+		public static TimeStampReq GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+		{
+            return new TimeStampReq(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
         private TimeStampReq(Asn1Sequence seq)
 		{
 			int nbObjects = seq.Count;
 			int seqStart = 0;
 
 			// version
-			version = DerInteger.GetInstance(seq[seqStart++]);
+			m_version = DerInteger.GetInstance(seq[seqStart++]);
 
 			// messageImprint
-			messageImprint = MessageImprint.GetInstance(seq[seqStart++]);
+			m_messageImprint = MessageImprint.GetInstance(seq[seqStart++]);
 
 			for (int opt = seqStart; opt < nbObjects; opt++)
 			{
 				// tsaPolicy
 				if (seq[opt] is DerObjectIdentifier oid)
 				{
-					tsaPolicy = oid;
+					m_tsaPolicy = oid;
 				}
 				// nonce
 				else if (seq[opt] is DerInteger derInteger)
 				{
-					nonce = derInteger;
+					m_nonce = derInteger;
 				}
 				// certReq
 				else if (seq[opt] is DerBoolean derBoolean)
 				{
-					certReq = derBoolean;
+					m_certReq = derBoolean;
 				}
 				// extensions
 				else if (seq[opt] is Asn1TaggedObject tagged)
 				{
 					if (tagged.TagNo == 0)
 					{
-						extensions = X509Extensions.GetInstance(tagged, false);
+						m_extensions = X509Extensions.GetInstance(tagged, false);
 					}
 				}
 			}
 		}
 
-		public TimeStampReq(
-			MessageImprint		messageImprint,
-			DerObjectIdentifier	tsaPolicy,
-			DerInteger			nonce,
-			DerBoolean			certReq,
-			X509Extensions		extensions)
-		{
-			// default
-			this.version = new DerInteger(1);
-
-			this.messageImprint = messageImprint;
-			this.tsaPolicy = tsaPolicy;
-			this.nonce = nonce;
-			this.certReq = certReq;
-			this.extensions = extensions;
-		}
+        public TimeStampReq(MessageImprint messageImprint, DerObjectIdentifier tsaPolicy, DerInteger nonce,
+            DerBoolean certReq, X509Extensions extensions)
+        {
+            // default
+            m_version = new DerInteger(1);
+
+            m_messageImprint = messageImprint;
+            m_tsaPolicy = tsaPolicy;
+            m_nonce = nonce;
+            m_certReq = certReq;
+            m_extensions = extensions;
+        }
 
-		public DerInteger Version
-		{
-			get { return version; }
-		}
+		public DerInteger Version => m_version;
 
-		public MessageImprint MessageImprint
-		{
-			get { return messageImprint; }
-		}
+		public MessageImprint MessageImprint => m_messageImprint;
 
-		public DerObjectIdentifier ReqPolicy
-		{
-			get { return tsaPolicy; }
-		}
+		public DerObjectIdentifier ReqPolicy => m_tsaPolicy;
 
-		public DerInteger Nonce
-		{
-			get { return nonce; }
-		}
+		public DerInteger Nonce => m_nonce;
 
-		public DerBoolean CertReq
-		{
-			get { return certReq; }
-		}
+		public DerBoolean CertReq => m_certReq;
 
-		public X509Extensions Extensions
-		{
-			get { return extensions; }
-		}
+		public X509Extensions Extensions => m_extensions;
 
 		/**
 		 * 
@@ -126,15 +109,16 @@ namespace Org.BouncyCastle.Asn1.Tsp
 		 */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version, messageImprint);
-            v.AddOptional(tsaPolicy, nonce);
+            Asn1EncodableVector v = new Asn1EncodableVector(6);
+			v.Add(m_version, m_messageImprint);
+            v.AddOptional(m_tsaPolicy, m_nonce);
 
-            if (certReq != null && certReq.IsTrue)
+            if (m_certReq != null && m_certReq.IsTrue)
             {
-                v.Add(certReq);
+                v.Add(m_certReq);
             }
 
-            v.AddOptionalTagged(false, 0, extensions);
+            v.AddOptionalTagged(false, 0, m_extensions);
             return new DerSequence(v);
         }
 	}
diff --git a/crypto/src/asn1/tsp/TimeStampResp.cs b/crypto/src/asn1/tsp/TimeStampResp.cs
index 3dde0dfce..cc9c2ed4d 100644
--- a/crypto/src/asn1/tsp/TimeStampResp.cs
+++ b/crypto/src/asn1/tsp/TimeStampResp.cs
@@ -9,46 +9,42 @@ namespace Org.BouncyCastle.Asn1.Tsp
 	public class TimeStampResp
 		: Asn1Encodable
 	{
-		private readonly PkiStatusInfo	pkiStatusInfo;
-		private readonly ContentInfo	timeStampToken;
-
         public static TimeStampResp GetInstance(object obj)
         {
-            if (obj is TimeStampResp)
-                return (TimeStampResp)obj;
             if (obj == null)
                 return null;
+            if (obj is TimeStampResp timeStampResp)
+                return timeStampResp;
             return new TimeStampResp(Asn1Sequence.GetInstance(obj));
         }
 
-        private TimeStampResp(
-			Asn1Sequence seq)
+		public static TimeStampResp GetInstance(Asn1TaggedObject taggedObject, bool declaredExplicit)
+		{
+            return new TimeStampResp(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
+        }
+
+        private readonly PkiStatusInfo m_pkiStatusInfo;
+        private readonly ContentInfo m_timeStampToken;
+
+        private TimeStampResp(Asn1Sequence seq)
 		{
-			this.pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
+			m_pkiStatusInfo = PkiStatusInfo.GetInstance(seq[0]);
 
 			if (seq.Count > 1)
 			{
-				this.timeStampToken = ContentInfo.GetInstance(seq[1]);
+				m_timeStampToken = ContentInfo.GetInstance(seq[1]);
 			}
 		}
 
-		public TimeStampResp(
-			PkiStatusInfo	pkiStatusInfo,
-			ContentInfo		timeStampToken)
+		public TimeStampResp(PkiStatusInfo pkiStatusInfo, ContentInfo timeStampToken)
 		{
-			this.pkiStatusInfo = pkiStatusInfo;
-			this.timeStampToken = timeStampToken;
+			m_pkiStatusInfo = pkiStatusInfo;
+			m_timeStampToken = timeStampToken;
 		}
 
-		public PkiStatusInfo Status
-		{
-			get { return pkiStatusInfo; }
-		}
+		public PkiStatusInfo Status => m_pkiStatusInfo;
 
-		public ContentInfo TimeStampToken
-		{
-			get { return timeStampToken; }
-		}
+		public ContentInfo TimeStampToken => m_timeStampToken;
 
 		/**
 		 * 
@@ -59,8 +55,9 @@ namespace Org.BouncyCastle.Asn1.Tsp
 		 */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(pkiStatusInfo);
-            v.AddOptional(timeStampToken);
+            Asn1EncodableVector v = new Asn1EncodableVector(2);
+			v.Add(m_pkiStatusInfo);
+            v.AddOptional(m_timeStampToken);
             return new DerSequence(v);
         }
 	}
-- 
cgit 1.4.1