From 740c25a020c7539c99e82dd4531492c5b6bbd787 Mon Sep 17 00:00:00 2001 From: Peter Dettman Date: Tue, 18 Jun 2024 16:12:06 +0700 Subject: Refactoring in Asn1.Cms --- crypto/src/asn1/Asn1Utilities.cs | 14 + crypto/src/asn1/cms/Attribute.cs | 38 +-- crypto/src/asn1/cms/AttributeTable.cs | 112 ++++--- crypto/src/asn1/cms/Attributes.cs | 17 + crypto/src/asn1/cms/AuthEnvelopedData.cs | 194 +++++------ crypto/src/asn1/cms/AuthenticatedData.cs | 283 +++++++--------- crypto/src/asn1/cms/CcmParameters.cs | 29 +- crypto/src/asn1/cms/CmsAlgorithmProtection.cs | 61 ++-- crypto/src/asn1/cms/CompressedData.cs | 50 ++- crypto/src/asn1/cms/ContentInfo.cs | 54 ++-- crypto/src/asn1/cms/EncryptedContentInfo.cs | 60 ++-- crypto/src/asn1/cms/EncryptedData.cs | 62 ++-- crypto/src/asn1/cms/EnvelopedData.cs | 201 +++++++----- crypto/src/asn1/cms/Evidence.cs | 4 +- crypto/src/asn1/cms/GcmParameters.cs | 29 +- crypto/src/asn1/cms/IssuerAndSerialNumber.cs | 6 + crypto/src/asn1/cms/KEKIdentifier.cs | 68 ++-- crypto/src/asn1/cms/KEKRecipientInfo.cs | 63 ++-- crypto/src/asn1/cms/KemRecipientInfo.cs | 28 +- crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs | 40 +-- crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs | 87 ++--- crypto/src/asn1/cms/KeyTransRecipientInfo.cs | 72 ++--- crypto/src/asn1/cms/MetaData.cs | 116 ++++--- crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs | 2 +- crypto/src/asn1/cms/OriginatorInfo.cs | 65 ++-- crypto/src/asn1/cms/OriginatorPublicKey.cs | 10 +- crypto/src/asn1/cms/OtherKeyAttribute.cs | 54 ++-- crypto/src/asn1/cms/OtherRecipientInfo.cs | 37 +-- crypto/src/asn1/cms/OtherRevocationInfoFormat.cs | 39 +-- crypto/src/asn1/cms/PasswordRecipientInfo.cs | 79 ++--- crypto/src/asn1/cms/RecipientEncryptedKey.cs | 44 ++- crypto/src/asn1/cms/RecipientIdentifier.cs | 4 +- crypto/src/asn1/cms/RecipientInfo.cs | 138 ++++---- crypto/src/asn1/cms/RecipientKeyIdentifier.cs | 85 ++--- crypto/src/asn1/cms/SCVPReqRes.cs | 49 ++- crypto/src/asn1/cms/SignedData.cs | 354 +++++++++------------ crypto/src/asn1/cms/SignerIdentifier.cs | 31 +- crypto/src/asn1/cms/SignerInfo.cs | 157 +++------ crypto/src/asn1/cms/TimeStampAndCRL.cs | 48 +-- crypto/src/asn1/cms/TimeStampTokenEvidence.cs | 32 +- crypto/src/asn1/cms/TimeStampedData.cs | 89 +++--- crypto/src/asn1/x509/CertificateList.cs | 31 +- 42 files changed, 1333 insertions(+), 1703 deletions(-) (limited to 'crypto') diff --git a/crypto/src/asn1/Asn1Utilities.cs b/crypto/src/asn1/Asn1Utilities.cs index cdef45646..169f1fb37 100644 --- a/crypto/src/asn1/Asn1Utilities.cs +++ b/crypto/src/asn1/Asn1Utilities.cs @@ -652,6 +652,20 @@ namespace Org.BouncyCastle.Asn1 #region Sequence cursor + public static TResult ReadContextTagged(Asn1Sequence sequence, ref int sequencePosition, + int tagNo, TState state, Func constructor) + { + return ReadTagged(sequence, ref sequencePosition, Asn1Tags.ContextSpecific, tagNo, state, constructor); + } + + public static TResult ReadTagged(Asn1Sequence sequence, ref int sequencePosition, int tagClass, + int tagNo, TState state, Func constructor) + { + var tagged = Asn1TaggedObject.GetInstance(sequence[sequencePosition++], tagClass, tagNo); + + return constructor(tagged, state); + } + public static TResult ReadOptional(Asn1Sequence sequence, ref int sequencePosition, Func constructor) where TResult : class diff --git a/crypto/src/asn1/cms/Attribute.cs b/crypto/src/asn1/cms/Attribute.cs index 9e2ced198..f44646bbc 100644 --- a/crypto/src/asn1/cms/Attribute.cs +++ b/crypto/src/asn1/cms/Attribute.cs @@ -23,34 +23,29 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerObjectIdentifier attrType; - private Asn1Set attrValues; + private readonly DerObjectIdentifier m_attrType; + private readonly Asn1Set m_attrValues; [Obsolete("Use 'GetInstance' instead")] - public Attribute( - Asn1Sequence seq) + public Attribute(Asn1Sequence seq) { - attrType = (DerObjectIdentifier)seq[0]; - attrValues = (Asn1Set)seq[1]; + int count = seq.Count; + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_attrType = DerObjectIdentifier.GetInstance(seq[0]); + m_attrValues = Asn1Set.GetInstance(seq[1]); } - public Attribute( - DerObjectIdentifier attrType, - Asn1Set attrValues) + public Attribute(DerObjectIdentifier attrType, Asn1Set attrValues) { - this.attrType = attrType; - this.attrValues = attrValues; + m_attrType = attrType ?? throw new ArgumentNullException(nameof(attrType)); + m_attrValues = attrValues ?? throw new ArgumentNullException(nameof(attrValues)); } - public DerObjectIdentifier AttrType - { - get { return attrType; } - } + public DerObjectIdentifier AttrType => m_attrType; - public Asn1Set AttrValues - { - get { return attrValues; } - } + public Asn1Set AttrValues => m_attrValues; /** * Produce an object suitable for an Asn1OutputStream. @@ -61,9 +56,6 @@ namespace Org.BouncyCastle.Asn1.Cms * } * */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(attrType, attrValues); - } + public override Asn1Object ToAsn1Object() => new DerSequence(m_attrType, m_attrValues); } } diff --git a/crypto/src/asn1/cms/AttributeTable.cs b/crypto/src/asn1/cms/AttributeTable.cs index fc6d3cabc..188b651c1 100644 --- a/crypto/src/asn1/cms/AttributeTable.cs +++ b/crypto/src/asn1/cms/AttributeTable.cs @@ -14,22 +14,12 @@ namespace Org.BouncyCastle.Asn1.Cms public AttributeTable(Asn1EncodableVector v) { - m_attributes = new Dictionary(v.Count); - - foreach (Asn1Encodable e in v) - { - AddAttribute(Attribute.GetInstance(e)); - } + m_attributes = BuildAttributes(v); } public AttributeTable(Asn1Set s) { - m_attributes = new Dictionary(s.Count); - - foreach (Asn1Encodable e in s) - { - AddAttribute(Attribute.GetInstance(e)); - } + m_attributes = BuildAttributes(s); } public AttributeTable(Attributes attrs) @@ -37,34 +27,6 @@ namespace Org.BouncyCastle.Asn1.Cms { } - private void AddAttribute(Attribute a) - { - DerObjectIdentifier oid = a.AttrType; - - if (!m_attributes.TryGetValue(oid, out object existingValue)) - { - m_attributes[oid] = a; - return; - } - - if (existingValue is IList existingList) - { - existingList.Add(a); - return; - } - - if (existingValue is Attribute existingAttr) - { - var newList = new List(); - newList.Add(existingAttr); - newList.Add(a); - m_attributes[oid] = newList; - return; - } - - throw new InvalidOperationException(); - } - /// Return the first attribute matching the given OBJECT IDENTIFIER public Attribute this[DerObjectIdentifier oid] { @@ -73,7 +35,7 @@ namespace Org.BouncyCastle.Asn1.Cms if (!m_attributes.TryGetValue(oid, out object existingValue)) return null; - if (existingValue is IList existingList) + if (existingValue is List existingList) return existingList[0]; if (existingValue is Attribute existingAttr) @@ -96,7 +58,7 @@ namespace Org.BouncyCastle.Asn1.Cms if (m_attributes.TryGetValue(oid, out object existingValue)) { - if (existingValue is IList existingList) + if (existingValue is List existingList) { foreach (var attr in existingList) { @@ -124,7 +86,7 @@ namespace Org.BouncyCastle.Asn1.Cms foreach (object existingValue in m_attributes.Values) { - if (existingValue is IList existingList) + if (existingValue is List existingList) { total += existingList.Count; } @@ -153,7 +115,7 @@ namespace Org.BouncyCastle.Asn1.Cms foreach (object existingValue in m_attributes.Values) { - if (existingValue is IList existingList) + if (existingValue is List existingList) { foreach (Attribute existingAttr in existingList) { @@ -183,13 +145,12 @@ namespace Org.BouncyCastle.Asn1.Cms if (attributes == null || attributes.Length < 1) return this; - var newTable = new AttributeTable(m_attributes); + var result = new AttributeTable(m_attributes); foreach (Attribute attribute in attributes) { - newTable.AddAttribute(attribute); + AddAttribute(result.m_attributes, attribute); } - - return newTable; + return result; } /** @@ -201,20 +162,57 @@ namespace Org.BouncyCastle.Asn1.Cms */ public AttributeTable Add(DerObjectIdentifier attrType, Asn1Encodable attrValue) { - AttributeTable newTable = new AttributeTable(m_attributes); - - newTable.AddAttribute(new Attribute(attrType, new DerSet(attrValue))); - - return newTable; + AttributeTable result = new AttributeTable(m_attributes); + AddAttribute(result.m_attributes, new Attribute(attrType, new DerSet(attrValue))); + return result; } public AttributeTable Remove(DerObjectIdentifier attrType) { - AttributeTable newTable = new AttributeTable(m_attributes); - - newTable.m_attributes.Remove(attrType); + if (!m_attributes.ContainsKey(attrType)) + return this; - return newTable; + AttributeTable result = new AttributeTable(m_attributes); + result.m_attributes.Remove(attrType); + return result; } + + private static void AddAttribute(Dictionary attributes, Attribute a) + { + DerObjectIdentifier oid = a.AttrType; + + if (!attributes.TryGetValue(oid, out object existingValue)) + { + attributes[oid] = a; + return; + } + + if (existingValue is List existingList) + { + existingList.Add(a); + return; + } + + if (existingValue is Attribute existingAttr) + { + var newList = new List(); + newList.Add(existingAttr); + newList.Add(a); + attributes[oid] = newList; + return; + } + + throw new InvalidOperationException(); + } + + private static Dictionary BuildAttributes(IEnumerable e) + { + var result = new Dictionary(); + foreach (Asn1Encodable element in e) + { + AddAttribute(result, Attribute.GetInstance(element)); + } + return result; + } } } diff --git a/crypto/src/asn1/cms/Attributes.cs b/crypto/src/asn1/cms/Attributes.cs index 41018453d..cdcada6dc 100644 --- a/crypto/src/asn1/cms/Attributes.cs +++ b/crypto/src/asn1/cms/Attributes.cs @@ -1,3 +1,5 @@ +using System; + namespace Org.BouncyCastle.Asn1.Cms { public class Attributes @@ -17,6 +19,21 @@ namespace Org.BouncyCastle.Asn1.Cms return new Attributes(Asn1Set.GetInstance(taggedObject, declaredExplicit)); } + public static Attributes GetOptional(Asn1Encodable element) + { + if (element == null) + throw new ArgumentNullException(nameof(element)); + + if (element is Attributes attributes) + return attributes; + + Asn1Set asn1Set = Asn1Set.GetOptional(element); + if (asn1Set != null) + return new Attributes(asn1Set); + + return null; + } + private readonly Asn1Set m_attributes; private Attributes(Asn1Set attributes) diff --git a/crypto/src/asn1/cms/AuthEnvelopedData.cs b/crypto/src/asn1/cms/AuthEnvelopedData.cs index ae0380b64..62d54b33e 100644 --- a/crypto/src/asn1/cms/AuthEnvelopedData.cs +++ b/crypto/src/asn1/cms/AuthEnvelopedData.cs @@ -19,133 +19,80 @@ namespace Org.BouncyCastle.Asn1.Cms return new AuthEnvelopedData(Asn1Sequence.GetInstance(obj, isExplicit)); } - private DerInteger version; - private OriginatorInfo originatorInfo; - private Asn1Set recipientInfos; - private EncryptedContentInfo authEncryptedContentInfo; - private Asn1Set authAttrs; - private Asn1OctetString mac; - private Asn1Set unauthAttrs; - - public AuthEnvelopedData( - OriginatorInfo originatorInfo, - Asn1Set recipientInfos, - EncryptedContentInfo authEncryptedContentInfo, - Asn1Set authAttrs, - Asn1OctetString mac, - Asn1Set unauthAttrs) - { - // "It MUST be set to 0." - this.version = DerInteger.Zero; - - this.originatorInfo = originatorInfo; - - // "There MUST be at least one element in the collection." - this.recipientInfos = recipientInfos; - if (this.recipientInfos.Count < 1) - throw new ArgumentException("AuthEnvelopedData requires at least 1 RecipientInfo"); - - this.authEncryptedContentInfo = authEncryptedContentInfo; - - // "The authAttrs MUST be present if the content type carried in - // EncryptedContentInfo is not id-data." - this.authAttrs = authAttrs; - if (!authEncryptedContentInfo.ContentType.Equals(CmsObjectIdentifiers.Data)) - { - if (authAttrs == null || authAttrs.Count < 1) - throw new ArgumentException("authAttrs must be present with non-data content"); - } - - this.mac = mac; - - this.unauthAttrs = unauthAttrs; - } + private readonly DerInteger m_version; + private readonly OriginatorInfo m_originatorInfo; + private readonly Asn1Set m_recipientInfos; + private readonly EncryptedContentInfo m_authEncryptedContentInfo; + private readonly Asn1Set m_authAttrs; + private readonly Asn1OctetString m_mac; + private readonly Asn1Set m_unauthAttrs; + + public AuthEnvelopedData(OriginatorInfo originatorInfo, Asn1Set recipientInfos, + EncryptedContentInfo authEncryptedContentInfo, Asn1Set authAttrs, Asn1OctetString mac, + Asn1Set unauthAttrs) + { + m_version = DerInteger.Zero; + m_originatorInfo = originatorInfo; + m_recipientInfos = recipientInfos ?? throw new ArgumentNullException(nameof(recipientInfos)); + m_authEncryptedContentInfo = authEncryptedContentInfo ?? throw new ArgumentNullException(nameof(authEncryptedContentInfo)); + m_authAttrs = authAttrs; + m_mac = mac ?? throw new ArgumentNullException(nameof(mac)); + m_unauthAttrs = unauthAttrs; + + Validate(); + } - private AuthEnvelopedData(Asn1Sequence seq) + private AuthEnvelopedData(Asn1Sequence seq) { - int index = 0; - - // "It MUST be set to 0." - Asn1Object tmp = seq[index++].ToAsn1Object(); - version = DerInteger.GetInstance(tmp); - if (!version.HasValue(0)) - throw new ArgumentException("AuthEnvelopedData version number must be 0"); - - tmp = seq[index++].ToAsn1Object(); - if (tmp is Asn1TaggedObject taggedObject1) - { - originatorInfo = OriginatorInfo.GetInstance(taggedObject1, false); - tmp = seq[index++].ToAsn1Object(); - } - - // "There MUST be at least one element in the collection." - recipientInfos = Asn1Set.GetInstance(tmp); - if (recipientInfos.Count < 1) - throw new ArgumentException("AuthEnvelopedData requires at least 1 RecipientInfo"); - - tmp = seq[index++].ToAsn1Object(); - authEncryptedContentInfo = EncryptedContentInfo.GetInstance(tmp); - - tmp = seq[index++].ToAsn1Object(); - if (tmp is Asn1TaggedObject taggedObject2) - { - authAttrs = Asn1Set.GetInstance(taggedObject2, false); - tmp = seq[index++].ToAsn1Object(); - } - else - { - // "The authAttrs MUST be present if the content type carried in - // EncryptedContentInfo is not id-data." - if (!authEncryptedContentInfo.ContentType.Equals(CmsObjectIdentifiers.Data)) - { - if (authAttrs == null || authAttrs.Count < 1) - throw new ArgumentException("authAttrs must be present with non-data content"); - } - } - - mac = Asn1OctetString.GetInstance(tmp); - - if (seq.Count > index) - { - tmp = seq[index++].ToAsn1Object(); - unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)tmp, false); - } + int count = seq.Count, pos = 0; + if (count < 4 || count > 7) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[pos++]); + m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance); + m_recipientInfos = Asn1Set.GetInstance(seq[pos++]); + m_authEncryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]); + m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance); + m_mac = Asn1OctetString.GetInstance(seq[pos++]); + m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetInstance); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); + + Validate(); } - public DerInteger Version - { - get { return version; } - } + private void Validate() + { + // "It MUST be set to 0." + if (!m_version.HasValue(0)) + throw new ArgumentException("AuthEnvelopedData version number must be 0"); + + // "There MUST be at least one element in the collection." + if (m_recipientInfos.Count < 1) + throw new ArgumentException("AuthEnvelopedData requires at least 1 RecipientInfo"); + + // "The authAttrs MUST be present if the content type carried in EncryptedContentInfo is not id-data." + if (!CmsObjectIdentifiers.Data.Equals(m_authEncryptedContentInfo.ContentType)) + { + if (m_authAttrs == null || m_authAttrs.Count < 1) + throw new ArgumentException("authAttrs must be present with non-data content"); + } + } - public OriginatorInfo OriginatorInfo - { - get { return originatorInfo; } - } + public DerInteger Version => m_version; - public Asn1Set RecipientInfos - { - get { return recipientInfos; } - } + public OriginatorInfo OriginatorInfo => m_originatorInfo; - public EncryptedContentInfo AuthEncryptedContentInfo - { - get { return authEncryptedContentInfo; } - } + public Asn1Set RecipientInfos => m_recipientInfos; - public Asn1Set AuthAttrs - { - get { return authAttrs; } - } + public EncryptedContentInfo AuthEncryptedContentInfo => m_authEncryptedContentInfo; - public Asn1OctetString Mac - { - get { return mac; } - } + public Asn1Set AuthAttrs => m_authAttrs; - public Asn1Set UnauthAttrs - { - get { return unauthAttrs; } - } + public Asn1OctetString Mac => m_mac; + + public Asn1Set UnauthAttrs => m_unauthAttrs; /** * Produce an object suitable for an Asn1OutputStream. @@ -162,19 +109,20 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(version); - v.AddOptionalTagged(false, 0, originatorInfo); - v.Add(recipientInfos, authEncryptedContentInfo); + Asn1EncodableVector v = new Asn1EncodableVector(7); + v.Add(m_version); + v.AddOptionalTagged(false, 0, m_originatorInfo); + v.Add(m_recipientInfos, m_authEncryptedContentInfo); // "authAttrs optionally contains the authenticated attributes." // "AuthAttributes MUST be DER encoded, even if the rest of the // AuthEnvelopedData structure is BER encoded." - v.AddOptionalTagged(false, 1, authAttrs); + v.AddOptionalTagged(false, 1, m_authAttrs); - v.Add(mac); + v.Add(m_mac); // "unauthAttrs optionally contains the unauthenticated attributes." - v.AddOptionalTagged(false, 2, unauthAttrs); + v.AddOptionalTagged(false, 2, m_unauthAttrs); return new BerSequence(v); } diff --git a/crypto/src/asn1/cms/AuthenticatedData.cs b/crypto/src/asn1/cms/AuthenticatedData.cs index 47db0fa16..fad7de35f 100644 --- a/crypto/src/asn1/cms/AuthenticatedData.cs +++ b/crypto/src/asn1/cms/AuthenticatedData.cs @@ -21,132 +21,73 @@ namespace Org.BouncyCastle.Asn1.Cms return new AuthenticatedData(Asn1Sequence.GetInstance(obj, isExplicit)); } - private DerInteger version; - private OriginatorInfo originatorInfo; - private Asn1Set recipientInfos; - private AlgorithmIdentifier macAlgorithm; - private AlgorithmIdentifier digestAlgorithm; - private ContentInfo encapsulatedContentInfo; - private Asn1Set authAttrs; - private Asn1OctetString mac; - private Asn1Set unauthAttrs; - - public AuthenticatedData( - OriginatorInfo originatorInfo, - Asn1Set recipientInfos, - AlgorithmIdentifier macAlgorithm, - AlgorithmIdentifier digestAlgorithm, - ContentInfo encapsulatedContent, - Asn1Set authAttrs, - Asn1OctetString mac, - Asn1Set unauthAttrs) - { - if (digestAlgorithm != null || authAttrs != null) - { - if (digestAlgorithm == null || authAttrs == null) - { - throw new ArgumentException("digestAlgorithm and authAttrs must be set together"); - } - } - - version = new DerInteger(CalculateVersion(originatorInfo)); - - this.originatorInfo = originatorInfo; - this.macAlgorithm = macAlgorithm; - this.digestAlgorithm = digestAlgorithm; - this.recipientInfos = recipientInfos; - this.encapsulatedContentInfo = encapsulatedContent; - this.authAttrs = authAttrs; - this.mac = mac; - this.unauthAttrs = unauthAttrs; - } + private readonly DerInteger m_version; + private readonly OriginatorInfo m_originatorInfo; + private readonly Asn1Set m_recipientInfos; + private readonly AlgorithmIdentifier m_macAlgorithm; + private readonly AlgorithmIdentifier m_digestAlgorithm; + private readonly ContentInfo m_encapsulatedContentInfo; + private readonly Asn1Set m_authAttrs; + private readonly Asn1OctetString m_mac; + private readonly Asn1Set m_unauthAttrs; + + public AuthenticatedData(OriginatorInfo originatorInfo, Asn1Set recipientInfos, + AlgorithmIdentifier macAlgorithm, AlgorithmIdentifier digestAlgorithm, ContentInfo encapsulatedContent, + Asn1Set authAttrs, Asn1OctetString mac, Asn1Set unauthAttrs) + { + if ((digestAlgorithm == null) != (authAttrs == null)) + throw new ArgumentException("digestAlgorithm and authAttrs must be set together"); + + m_version = CalculateVersionField(originatorInfo); + m_originatorInfo = originatorInfo; + m_macAlgorithm = macAlgorithm ?? throw new ArgumentNullException(nameof(macAlgorithm)); + m_digestAlgorithm = digestAlgorithm; + m_recipientInfos = recipientInfos ?? throw new ArgumentNullException(nameof(recipientInfos)); + m_encapsulatedContentInfo = encapsulatedContent ?? throw new ArgumentNullException(nameof(encapsulatedContent)); + m_authAttrs = authAttrs; + m_mac = mac ?? throw new ArgumentNullException(nameof(mac)); + m_unauthAttrs = unauthAttrs; + } - private AuthenticatedData(Asn1Sequence seq) + private AuthenticatedData(Asn1Sequence seq) { - int index = 0; - - version = (DerInteger)seq[index++]; - - Asn1Encodable tmp = seq[index++]; - if (tmp is Asn1TaggedObject taggedObject1) - { - originatorInfo = OriginatorInfo.GetInstance(taggedObject1, false); - tmp = seq[index++]; - } - - recipientInfos = Asn1Set.GetInstance(tmp); - macAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]); - - tmp = seq[index++]; - if (tmp is Asn1TaggedObject taggedObject2) - { - digestAlgorithm = AlgorithmIdentifier.GetInstance(taggedObject2, false); - tmp = seq[index++]; - } - - encapsulatedContentInfo = ContentInfo.GetInstance(tmp); - - tmp = seq[index++]; - if (tmp is Asn1TaggedObject taggedObject3) - { - authAttrs = Asn1Set.GetInstance(taggedObject3, false); - tmp = seq[index++]; - } - - mac = Asn1OctetString.GetInstance(tmp); - - if (seq.Count > index) - { - unauthAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false); - } + int count = seq.Count, pos = 0; + if (count < 5 || count > 9) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[pos++]); + m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance); + m_recipientInfos = Asn1Set.GetInstance(seq[pos++]); + m_macAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_digestAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetInstance); + m_encapsulatedContentInfo = ContentInfo.GetInstance(seq[pos++]); + m_authAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, Asn1Set.GetInstance); + m_mac = Asn1OctetString.GetInstance(seq[pos++]); + m_unauthAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 3, false, Asn1Set.GetInstance); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public OriginatorInfo OriginatorInfo - { - get { return originatorInfo; } - } + public OriginatorInfo OriginatorInfo => m_originatorInfo; - public Asn1Set RecipientInfos - { - get { return recipientInfos; } - } + public Asn1Set RecipientInfos => m_recipientInfos; - public AlgorithmIdentifier MacAlgorithm - { - get { return macAlgorithm; } - } + public AlgorithmIdentifier MacAlgorithm => m_macAlgorithm; - public AlgorithmIdentifier DigestAlgorithm - { - get { return digestAlgorithm; } - } + public AlgorithmIdentifier DigestAlgorithm => m_digestAlgorithm; - public ContentInfo EncapsulatedContentInfo - { - get { return encapsulatedContentInfo; } - } + public ContentInfo EncapsulatedContentInfo => m_encapsulatedContentInfo; - public Asn1Set AuthAttrs - { - get { return authAttrs; } - } + public Asn1Set AuthAttrs => m_authAttrs; - public Asn1OctetString Mac - { - get { return mac; } - } + public Asn1OctetString Mac => m_mac; - public Asn1Set UnauthAttrs - { - get { return unauthAttrs; } - } + public Asn1Set UnauthAttrs => m_unauthAttrs; - /** + /** * Produce an object suitable for an Asn1OutputStream. *
 		 * AuthenticatedData ::= SEQUENCE {
@@ -167,55 +108,77 @@ namespace Org.BouncyCastle.Asn1.Cms
 		 * MessageAuthenticationCode ::= OCTET STRING
 		 * 
*/ - public override Asn1Object ToAsn1Object() - { - Asn1EncodableVector v = new Asn1EncodableVector(version); - v.AddOptionalTagged(false, 0, originatorInfo); - v.Add(recipientInfos, macAlgorithm); - v.AddOptionalTagged(false, 1, digestAlgorithm); - v.Add(encapsulatedContentInfo); - v.AddOptionalTagged(false, 2, authAttrs); - v.Add(mac); - v.AddOptionalTagged(false, 3, unauthAttrs); - return new BerSequence(v); - } + public override Asn1Object ToAsn1Object() + { + Asn1EncodableVector v = new Asn1EncodableVector(9); + v.Add(m_version); + v.AddOptionalTagged(false, 0, m_originatorInfo); + v.Add(m_recipientInfos, m_macAlgorithm); + v.AddOptionalTagged(false, 1, m_digestAlgorithm); + v.Add(m_encapsulatedContentInfo); + v.AddOptionalTagged(false, 2, m_authAttrs); + v.Add(m_mac); + v.AddOptionalTagged(false, 3, m_unauthAttrs); + return new BerSequence(v); + } + + public static int CalculateVersion(OriginatorInfo origInfo) => CalculateVersionField(origInfo).IntValueExact; - public static int CalculateVersion(OriginatorInfo origInfo) + private static DerInteger CalculateVersionField(OriginatorInfo originatorInfo) { - if (origInfo == null) - return 0; - - int ver = 0; - - foreach (object obj in origInfo.Certificates) - { - if (obj is Asn1TaggedObject tag) - { - if (tag.TagNo == 2) - { - ver = 1; - } - else if (tag.TagNo == 3) - { - ver = 3; - break; - } - } - } - - foreach (object obj in origInfo.Crls) - { - if (obj is Asn1TaggedObject tag) - { - if (tag.TagNo == 1) - { - ver = 3; - break; - } - } - } - - return ver; + /* + * IF (originatorInfo is present) AND + * ((any certificates with a type of other are present) OR + * (any crls with a type of other are present)) + * THEN version is 3 + * ELSE + * IF ((originatorInfo is present) AND + * (any version 2 attribute certificates are present)) + * THEN version is 1 + * ELSE version is 0 + */ + + if (originatorInfo != null) + { + var crls = originatorInfo.Crls; + if (crls != null) + { + foreach (var element in crls) + { + var tagged = Asn1TaggedObject.GetOptional(element); + if (tagged != null) + { + // RevocationInfoChoice.other + if (tagged.HasContextTag(1)) + return DerInteger.Three; + } + } + } + + var certs = originatorInfo.Certificates; + if (certs != null) + { + bool anyV2AttrCerts = false; + + foreach (var element in certs) + { + var tagged = Asn1TaggedObject.GetOptional(element); + if (tagged != null) + { + // CertificateChoices.other + if (tagged.HasContextTag(3)) + return DerInteger.Three; + + // CertificateChoices.v2AttrCert + anyV2AttrCerts = anyV2AttrCerts || tagged.HasContextTag(2); + } + } + + if (anyV2AttrCerts) + return DerInteger.One; + } + } + return DerInteger.Zero; } } } diff --git a/crypto/src/asn1/cms/CcmParameters.cs b/crypto/src/asn1/cms/CcmParameters.cs index bd725721b..6355f7f73 100644 --- a/crypto/src/asn1/cms/CcmParameters.cs +++ b/crypto/src/asn1/cms/CcmParameters.cs @@ -23,44 +23,39 @@ namespace Org.BouncyCastle.Asn1.Cms return new CcmParameters(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private readonly byte[] m_nonce; + private readonly Asn1OctetString m_nonce; private readonly int m_icvLen; private CcmParameters(Asn1Sequence seq) { - int count = seq.Count; + int count = seq.Count, pos = 0; if (count < 1 || count > 2) throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - m_nonce = Asn1OctetString.GetInstance(seq[0]).GetOctets(); + m_nonce = Asn1OctetString.GetInstance(seq[pos++]); + DerInteger icvLen = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional); - if (count > 1) - { - m_icvLen = DerInteger.GetInstance(seq[1]).IntValueExact; - } - else - { - m_icvLen = DefaultIcvLen; - } + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); + + m_icvLen = icvLen == null ? DefaultIcvLen : icvLen.IntValueExact; } public CcmParameters(byte[] nonce, int icvLen) { - m_nonce = Arrays.Clone(nonce); + m_nonce = new DerOctetString(nonce); m_icvLen = icvLen; } - public byte[] GetNonce() => Arrays.Clone(m_nonce); + public byte[] GetNonce() => Arrays.Clone(m_nonce.GetOctets()); public int IcvLen => m_icvLen; public override Asn1Object ToAsn1Object() { - var nonce = new DerOctetString(m_nonce); - return m_icvLen == DefaultIcvLen - ? new DerSequence(nonce) - : new DerSequence(nonce, new DerInteger(m_icvLen)); + ? new DerSequence(m_nonce) + : new DerSequence(m_nonce, new DerInteger(m_icvLen)); } } } diff --git a/crypto/src/asn1/cms/CmsAlgorithmProtection.cs b/crypto/src/asn1/cms/CmsAlgorithmProtection.cs index cb7a23f84..9923b0259 100644 --- a/crypto/src/asn1/cms/CmsAlgorithmProtection.cs +++ b/crypto/src/asn1/cms/CmsAlgorithmProtection.cs @@ -40,26 +40,26 @@ namespace Org.BouncyCastle.Asn1.Cms public static readonly int Signature = 1; public static readonly int Mac = 2; - private readonly AlgorithmIdentifier digestAlgorithm; - private readonly AlgorithmIdentifier signatureAlgorithm; - private readonly AlgorithmIdentifier macAlgorithm; + private readonly AlgorithmIdentifier m_digestAlgorithm; + private readonly AlgorithmIdentifier m_signatureAlgorithm; + private readonly AlgorithmIdentifier m_macAlgorithm; public CmsAlgorithmProtection(AlgorithmIdentifier digestAlgorithm, int type, AlgorithmIdentifier algorithmIdentifier) { - if (digestAlgorithm == null || algorithmIdentifier == null) - throw new ArgumentException("AlgorithmIdentifiers cannot be null"); + m_digestAlgorithm = digestAlgorithm ?? throw new ArgumentNullException(nameof(digestAlgorithm)); - this.digestAlgorithm = digestAlgorithm; + if (algorithmIdentifier == null) + throw new ArgumentNullException(nameof(algorithmIdentifier)); if (type == 1) { - this.signatureAlgorithm = algorithmIdentifier; - this.macAlgorithm = null; + m_signatureAlgorithm = algorithmIdentifier; + m_macAlgorithm = null; } else if (type == 2) { - this.signatureAlgorithm = null; - this.macAlgorithm = algorithmIdentifier; + m_signatureAlgorithm = null; + m_macAlgorithm = algorithmIdentifier; } else { @@ -67,43 +67,34 @@ namespace Org.BouncyCastle.Asn1.Cms } } - private CmsAlgorithmProtection(Asn1Sequence sequence) + private CmsAlgorithmProtection(Asn1Sequence seq) { - if (sequence.Count != 2) - throw new ArgumentException("Sequence wrong size: One of signatureAlgorithm or macAlgorithm must be present"); + int count = seq.Count, pos = 0; - this.digestAlgorithm = AlgorithmIdentifier.GetInstance(sequence[0]); + // RFC 6211 2. Exactly one of signatureAlgorithm or macAlgorithm SHALL be present. + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(sequence[1]); - if (tagged.TagNo == 1) - { - this.signatureAlgorithm = AlgorithmIdentifier.GetInstance(tagged, false); - this.macAlgorithm = null; - } - else if (tagged.TagNo == 2) - { - this.signatureAlgorithm = null; + m_digestAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_signatureAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, AlgorithmIdentifier.GetInstance); + m_macAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 2, false, AlgorithmIdentifier.GetInstance); - this.macAlgorithm = AlgorithmIdentifier.GetInstance(tagged, false); - } - else - { - throw new ArgumentException("Unknown tag found: " + tagged.TagNo); - } + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public AlgorithmIdentifier DigestAlgorithm => digestAlgorithm; + public AlgorithmIdentifier DigestAlgorithm => m_digestAlgorithm; - public AlgorithmIdentifier MacAlgorithm => macAlgorithm; + public AlgorithmIdentifier MacAlgorithm => m_macAlgorithm; - public AlgorithmIdentifier SignatureAlgorithm => signatureAlgorithm; + public AlgorithmIdentifier SignatureAlgorithm => m_signatureAlgorithm; public override Asn1Object ToAsn1Object() { Asn1EncodableVector v = new Asn1EncodableVector(3); - v.Add(digestAlgorithm); - v.AddOptionalTagged(false, 1, signatureAlgorithm); - v.AddOptionalTagged(false, 2, macAlgorithm); + v.Add(m_digestAlgorithm); + v.AddOptionalTagged(false, 1, m_signatureAlgorithm); + v.AddOptionalTagged(false, 2, m_macAlgorithm); return new DerSequence(v); } } diff --git a/crypto/src/asn1/cms/CompressedData.cs b/crypto/src/asn1/cms/CompressedData.cs index 5ae71708d..a22e153ef 100644 --- a/crypto/src/asn1/cms/CompressedData.cs +++ b/crypto/src/asn1/cms/CompressedData.cs @@ -35,46 +35,36 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerInteger version; - private AlgorithmIdentifier compressionAlgorithm; - private ContentInfo encapContentInfo; + private readonly DerInteger m_version; + private readonly AlgorithmIdentifier m_compressionAlgorithm; + private readonly ContentInfo m_encapContentInfo; - public CompressedData( - AlgorithmIdentifier compressionAlgorithm, - ContentInfo encapContentInfo) + public CompressedData(AlgorithmIdentifier compressionAlgorithm, ContentInfo encapContentInfo) { - this.version = DerInteger.Zero; - this.compressionAlgorithm = compressionAlgorithm; - this.encapContentInfo = encapContentInfo; + m_version = DerInteger.Zero; + m_compressionAlgorithm = compressionAlgorithm ?? throw new ArgumentNullException(nameof(compressionAlgorithm)); + m_encapContentInfo = encapContentInfo ?? throw new ArgumentNullException(nameof(encapContentInfo)); } [Obsolete("Use 'GetInstance' instead")] - public CompressedData( - Asn1Sequence seq) + public CompressedData(Asn1Sequence seq) { - this.version = (DerInteger) seq[0]; - this.compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); - this.encapContentInfo = ContentInfo.GetInstance(seq[2]); + int count = seq.Count; + if (count != 3) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[0]); + m_compressionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + m_encapContentInfo = ContentInfo.GetInstance(seq[2]); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public AlgorithmIdentifier CompressionAlgorithmIdentifier - { - get { return compressionAlgorithm; } - } + public AlgorithmIdentifier CompressionAlgorithmIdentifier => m_compressionAlgorithm; - public ContentInfo EncapContentInfo - { - get { return encapContentInfo; } - } + public ContentInfo EncapContentInfo => m_encapContentInfo; - public override Asn1Object ToAsn1Object() - { - return new BerSequence(version, compressionAlgorithm, encapContentInfo); - } + public override Asn1Object ToAsn1Object() => + new BerSequence(m_version, m_compressionAlgorithm, m_encapContentInfo); } } diff --git a/crypto/src/asn1/cms/ContentInfo.cs b/crypto/src/asn1/cms/ContentInfo.cs index 952884901..b440b06a9 100644 --- a/crypto/src/asn1/cms/ContentInfo.cs +++ b/crypto/src/asn1/cms/ContentInfo.cs @@ -19,64 +19,48 @@ namespace Org.BouncyCastle.Asn1.Cms return new ContentInfo(Asn1Sequence.GetInstance(obj, isExplicit)); } - private readonly DerObjectIdentifier contentType; - private readonly Asn1Encodable content; + private readonly DerObjectIdentifier m_contentType; + private readonly Asn1Encodable m_content; - private ContentInfo( - Asn1Sequence seq) + private ContentInfo(Asn1Sequence seq) { - if (seq.Count < 1 || seq.Count > 2) - throw new ArgumentException("Bad sequence size: " + seq.Count, "seq"); + int count = seq.Count; + if (count < 1 || count > 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - contentType = (DerObjectIdentifier) seq[0]; + m_contentType = DerObjectIdentifier.GetInstance(seq[0]); if (seq.Count > 1) { - Asn1TaggedObject tagged = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific); - if (!tagged.IsExplicit() || tagged.TagNo != 0) - throw new ArgumentException("Bad tag for 'content'", "seq"); - - content = tagged.GetExplicitBaseObject(); + m_content = Asn1TaggedObject.GetInstance(seq[1], Asn1Tags.ContextSpecific, 0).GetExplicitBaseObject(); } } - public ContentInfo( - DerObjectIdentifier contentType, - Asn1Encodable content) + public ContentInfo(DerObjectIdentifier contentType, Asn1Encodable content) { - this.contentType = contentType; - this.content = content; + // TODO[cms] Blocked by CmsSignedDataGenerator.GenerateCounterSigners transient usage of null here + //m_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); + m_contentType = contentType; + m_content = content; } - public DerObjectIdentifier ContentType - { - get { return contentType; } - } + public DerObjectIdentifier ContentType => m_contentType; - public Asn1Encodable Content - { - get { return content; } - } + public Asn1Encodable Content => m_content; /** * Produce an object suitable for an Asn1OutputStream. *
          * ContentInfo ::= Sequence {
          *          contentType ContentType,
-         *          content
-         *          [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
+         *          content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
          * 
*/ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(contentType); - - if (content != null) - { - v.Add(new BerTaggedObject(0, content)); - } - - return new BerSequence(v); + return m_content == null + ? new BerSequence(m_contentType) + : new BerSequence(m_contentType, new BerTaggedObject(0, m_content)); } } } diff --git a/crypto/src/asn1/cms/EncryptedContentInfo.cs b/crypto/src/asn1/cms/EncryptedContentInfo.cs index af697af5d..94a5c00c2 100644 --- a/crypto/src/asn1/cms/EncryptedContentInfo.cs +++ b/crypto/src/asn1/cms/EncryptedContentInfo.cs @@ -25,48 +25,38 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerObjectIdentifier contentType; - private AlgorithmIdentifier contentEncryptionAlgorithm; - private Asn1OctetString encryptedContent; + private DerObjectIdentifier m_contentType; + private AlgorithmIdentifier m_contentEncryptionAlgorithm; + private Asn1OctetString m_encryptedContent; - public EncryptedContentInfo( - DerObjectIdentifier contentType, - AlgorithmIdentifier contentEncryptionAlgorithm, - Asn1OctetString encryptedContent) + public EncryptedContentInfo(DerObjectIdentifier contentType, AlgorithmIdentifier contentEncryptionAlgorithm, + Asn1OctetString encryptedContent) { - this.contentType = contentType; - this.contentEncryptionAlgorithm = contentEncryptionAlgorithm; - this.encryptedContent = encryptedContent; + m_contentType = contentType ?? throw new ArgumentNullException(nameof(contentType)); + m_contentEncryptionAlgorithm = contentEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(contentEncryptionAlgorithm)); + m_encryptedContent = encryptedContent; } [Obsolete("Use 'GetInstance' instead")] - public EncryptedContentInfo( - Asn1Sequence seq) + public EncryptedContentInfo(Asn1Sequence seq) { - contentType = (DerObjectIdentifier) seq[0]; - contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); + int count = seq.Count, pos = 0; + if (count < 2 || count > 3) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - if (seq.Count > 2) - { - encryptedContent = Asn1OctetString.GetInstance( - (Asn1TaggedObject) seq[2], false); - } - } + m_contentType = DerObjectIdentifier.GetInstance(seq[pos++]); + m_contentEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_encryptedContent = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1OctetString.GetInstance); - public DerObjectIdentifier ContentType - { - get { return contentType; } + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public AlgorithmIdentifier ContentEncryptionAlgorithm - { - get { return contentEncryptionAlgorithm; } - } + public DerObjectIdentifier ContentType => m_contentType; - public Asn1OctetString EncryptedContent - { - get { return encryptedContent; } - } + public AlgorithmIdentifier ContentEncryptionAlgorithm => m_contentEncryptionAlgorithm; + + public Asn1OctetString EncryptedContent => m_encryptedContent; /** * Produce an object suitable for an Asn1OutputStream. @@ -80,12 +70,12 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector( - contentType, contentEncryptionAlgorithm); + Asn1EncodableVector v = new Asn1EncodableVector(3); + v.Add(m_contentType, m_contentEncryptionAlgorithm); - if (encryptedContent != null) + if (m_encryptedContent != null) { - v.Add(new BerTaggedObject(false, 0, encryptedContent)); + v.Add(new BerTaggedObject(false, 0, m_encryptedContent)); } return new BerSequence(v); diff --git a/crypto/src/asn1/cms/EncryptedData.cs b/crypto/src/asn1/cms/EncryptedData.cs index 4136994e6..fe0ff2c23 100644 --- a/crypto/src/asn1/cms/EncryptedData.cs +++ b/crypto/src/asn1/cms/EncryptedData.cs @@ -19,58 +19,41 @@ namespace Org.BouncyCastle.Asn1.Cms return new EncryptedData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private readonly DerInteger version; - private readonly EncryptedContentInfo encryptedContentInfo; - private readonly Asn1Set unprotectedAttrs; + private readonly DerInteger m_version; + private readonly EncryptedContentInfo m_encryptedContentInfo; + private readonly Asn1Set m_unprotectedAttrs; - public EncryptedData( - EncryptedContentInfo encInfo) - : this(encInfo, null) - { - } - - public EncryptedData( - EncryptedContentInfo encInfo, - Asn1Set unprotectedAttrs) - { - if (encInfo == null) - throw new ArgumentNullException("encInfo"); + public EncryptedData(EncryptedContentInfo encInfo) + : this(encInfo, null) + { + } - this.version = new DerInteger((unprotectedAttrs == null) ? 0 : 2); - this.encryptedContentInfo = encInfo; - this.unprotectedAttrs = unprotectedAttrs; + public EncryptedData(EncryptedContentInfo encInfo, Asn1Set unprotectedAttrs) + { + m_version = unprotectedAttrs == null ? DerInteger.Zero : DerInteger.Two; + m_encryptedContentInfo = encInfo ?? throw new ArgumentNullException(nameof(encInfo)); + m_unprotectedAttrs = unprotectedAttrs; } private EncryptedData(Asn1Sequence seq) { - int count = seq.Count; + int count = seq.Count, pos = 0; if (count < 2 || count > 3) throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - int pos = 0; - - this.version = DerInteger.GetInstance(seq[pos++]); - this.encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]); - this.unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance); + m_version = DerInteger.GetInstance(seq[pos++]); + m_encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]); + m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance); if (pos != count) throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public virtual DerInteger Version - { - get { return version; } - } + public virtual DerInteger Version => m_version; - public virtual EncryptedContentInfo EncryptedContentInfo - { - get { return encryptedContentInfo; } - } + public virtual EncryptedContentInfo EncryptedContentInfo => m_encryptedContentInfo; - public virtual Asn1Set UnprotectedAttrs - { - get { return unprotectedAttrs; } - } + public virtual Asn1Set UnprotectedAttrs => m_unprotectedAttrs; /** *
@@ -83,11 +66,12 @@ namespace Org.BouncyCastle.Asn1.Cms
 		*/
 		public override Asn1Object ToAsn1Object()
 		{
-			Asn1EncodableVector v = new Asn1EncodableVector(version, encryptedContentInfo);
+			Asn1EncodableVector v = new Asn1EncodableVector(3);
+			v.Add(m_version, m_encryptedContentInfo);
 
-			if (unprotectedAttrs != null)
+			if (m_unprotectedAttrs != null)
 			{
-				v.Add(new BerTaggedObject(false, 1, unprotectedAttrs));
+				v.Add(new BerTaggedObject(false, 1, m_unprotectedAttrs));
 			}
 
 			return new BerSequence(v);
diff --git a/crypto/src/asn1/cms/EnvelopedData.cs b/crypto/src/asn1/cms/EnvelopedData.cs
index 1b88d7791..846062f1c 100644
--- a/crypto/src/asn1/cms/EnvelopedData.cs
+++ b/crypto/src/asn1/cms/EnvelopedData.cs
@@ -1,3 +1,5 @@
+using System;
+
 namespace Org.BouncyCastle.Asn1.Cms
 {
     public class EnvelopedData
@@ -17,85 +19,53 @@ namespace Org.BouncyCastle.Asn1.Cms
             return new EnvelopedData(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-        private DerInteger				version;
-        private OriginatorInfo			originatorInfo;
-        private Asn1Set					recipientInfos;
-        private EncryptedContentInfo	encryptedContentInfo;
-        private Asn1Set					unprotectedAttrs;
-
-        public EnvelopedData(
-            OriginatorInfo			originatorInfo,
-            Asn1Set					recipientInfos,
-            EncryptedContentInfo	encryptedContentInfo,
-            Asn1Set					unprotectedAttrs)
+        private readonly DerInteger m_version;
+        private readonly OriginatorInfo m_originatorInfo;
+        private readonly Asn1Set m_recipientInfos;
+        private readonly EncryptedContentInfo m_encryptedContentInfo;
+        private readonly Asn1Set m_unprotectedAttrs;
+
+        public EnvelopedData(OriginatorInfo originatorInfo, Asn1Set recipientInfos,
+            EncryptedContentInfo encryptedContentInfo, Asn1Set unprotectedAttrs)
         {
-            this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, unprotectedAttrs));
-            this.originatorInfo = originatorInfo;
-            this.recipientInfos = recipientInfos;
-            this.encryptedContentInfo = encryptedContentInfo;
-            this.unprotectedAttrs = unprotectedAttrs;
+            m_version = CalculateVersionField(originatorInfo, recipientInfos, unprotectedAttrs);
+            m_originatorInfo = originatorInfo;
+            m_recipientInfos = recipientInfos ?? throw new ArgumentNullException(nameof(recipientInfos));
+            m_encryptedContentInfo = encryptedContentInfo ?? throw new ArgumentNullException(nameof(encryptedContentInfo));
+            m_unprotectedAttrs = unprotectedAttrs;
         }
 
-        public EnvelopedData(
-            OriginatorInfo originatorInfo,
-            Asn1Set recipientInfos,
-            EncryptedContentInfo encryptedContentInfo,
-            Attributes unprotectedAttrs)
+        public EnvelopedData(OriginatorInfo originatorInfo, Asn1Set recipientInfos,
+            EncryptedContentInfo encryptedContentInfo, Attributes unprotectedAttrs)
+            : this(originatorInfo, recipientInfos, encryptedContentInfo, Asn1Set.GetInstance(unprotectedAttrs))
         {
-            this.version = new DerInteger(CalculateVersion(originatorInfo, recipientInfos, Asn1Set.GetInstance(unprotectedAttrs)));
-            this.originatorInfo = originatorInfo;
-            this.recipientInfos = recipientInfos;
-            this.encryptedContentInfo = encryptedContentInfo;
-            this.unprotectedAttrs = Asn1Set.GetInstance(unprotectedAttrs);
         }
 
         private EnvelopedData(Asn1Sequence seq)
         {
-            int index = 0;
-
-            version = (DerInteger) seq[index++];
-
-            object tmp = seq[index++];
-
-            if (tmp is Asn1TaggedObject taggedObject)
-            {
-                originatorInfo = OriginatorInfo.GetInstance(taggedObject, false);
-                tmp = seq[index++];
-            }
-
-            recipientInfos = Asn1Set.GetInstance(tmp);
-            encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[index++]);
-
-            if (seq.Count > index)
-            {
-                unprotectedAttrs = Asn1Set.GetInstance((Asn1TaggedObject)seq[index], false);
-            }
+            int count = seq.Count, pos = 0;
+            if (count < 3 || count > 5)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_version = DerInteger.GetInstance(seq[pos++]);
+            m_originatorInfo = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, OriginatorInfo.GetInstance);
+            m_recipientInfos = Asn1Set.GetInstance(seq[pos++]);
+            m_encryptedContentInfo = EncryptedContentInfo.GetInstance(seq[pos++]);
+            m_unprotectedAttrs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-        public DerInteger Version
-        {
-            get { return version; }
-        }
+        public DerInteger Version => m_version;
 
-        public OriginatorInfo OriginatorInfo
-        {
-            get { return originatorInfo; }
-        }
+        public OriginatorInfo OriginatorInfo => m_originatorInfo;
 
-        public Asn1Set RecipientInfos
-        {
-            get { return recipientInfos; }
-        }
+        public Asn1Set RecipientInfos => m_recipientInfos;
 
-        public EncryptedContentInfo EncryptedContentInfo
-        {
-            get { return encryptedContentInfo; }
-        }
+        public EncryptedContentInfo EncryptedContentInfo => m_encryptedContentInfo;
 
-        public Asn1Set UnprotectedAttrs
-        {
-            get { return unprotectedAttrs; }
-        }
+        public Asn1Set UnprotectedAttrs => m_unprotectedAttrs;
 
         /**
          * Produce an object suitable for an Asn1OutputStream.
@@ -111,31 +81,104 @@ namespace Org.BouncyCastle.Asn1.Cms
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(version);
-            v.AddOptionalTagged(false, 0, originatorInfo);
-            v.Add(recipientInfos, encryptedContentInfo);
-            v.AddOptionalTagged(false, 1, unprotectedAttrs);
+            Asn1EncodableVector v = new Asn1EncodableVector(5);
+            v.Add(m_version);
+            v.AddOptionalTagged(false, 0, m_originatorInfo);
+            v.Add(m_recipientInfos, m_encryptedContentInfo);
+            v.AddOptionalTagged(false, 1, m_unprotectedAttrs);
             return new BerSequence(v);
         }
 
-        public static int CalculateVersion(OriginatorInfo originatorInfo, Asn1Set recipientInfos, Asn1Set unprotectedAttrs)
+        public static int CalculateVersion(OriginatorInfo originatorInfo, Asn1Set recipientInfos,
+            Asn1Set unprotectedAttrs)
         {
-            if (originatorInfo != null || unprotectedAttrs != null)
-            {
-                return 2;
-            }
+            return CalculateVersionField(originatorInfo, recipientInfos, unprotectedAttrs).IntValueExact;
+        }
 
-            foreach (object o in recipientInfos)
+        private static DerInteger CalculateVersionField(OriginatorInfo originatorInfo, Asn1Set recipientInfos,
+            Asn1Set unprotectedAttrs)
+        {
+            /*
+             * IF (originatorInfo is present) AND
+             *    ((any certificates with a type of other are present) OR
+             *    (any crls with a type of other are present))
+             * THEN version is 4
+             * ELSE
+             *    IF ((originatorInfo is present) AND
+             *       (any version 2 attribute certificates are present)) OR
+             *       (any RecipientInfo structures include pwri) OR
+             *       (any RecipientInfo structures include ori)
+             *    THEN version is 3
+             *    ELSE
+             *       IF (originatorInfo is absent) AND
+             *          (unprotectedAttrs is absent) AND
+             *          (all RecipientInfo structures are version 0)
+             *       THEN version is 0
+             *       ELSE version is 2
+             */
+
+            if (originatorInfo != null)
             {
-                RecipientInfo ri = RecipientInfo.GetInstance(o);
+                var crls = originatorInfo.Crls;
+                if (crls != null)
+                {
+                    foreach (var element in crls)
+                    {
+                        var tagged = Asn1TaggedObject.GetOptional(element);
+                        if (tagged != null)
+                        {
+                            // RevocationInfoChoice.other
+                            if (tagged.HasContextTag(1))
+                                return DerInteger.Four;
+                        }
+                    }
+                }
 
-                if (!ri.Version.HasValue(0))
+                var certs = originatorInfo.Certificates;
+                if (certs != null)
                 {
-                    return 2;
+                    bool anyV2AttrCerts = false;
+
+                    foreach (var element in certs)
+                    {
+                        var tagged = Asn1TaggedObject.GetOptional(element);
+                        if (tagged != null)
+                        {
+                            // CertificateChoices.other
+                            if (tagged.HasContextTag(3))
+                                return DerInteger.Four;
+
+                            // CertificateChoices.v2AttrCert
+                            anyV2AttrCerts = anyV2AttrCerts || tagged.HasContextTag(2);
+                        }
+                    }
+
+                    if (anyV2AttrCerts)
+                        return DerInteger.Three;
                 }
             }
 
-            return 0;
+            bool allV0Recipients = true;
+            foreach (var element in recipientInfos)
+            {
+                var recipientInfo = RecipientInfo.GetInstance(element);
+
+                // (any RecipientInfo structures include pwri) OR
+                // (any RecipientInfo structures include ori)
+                if (recipientInfo.IsPasswordOrOther())
+                    return DerInteger.Three;
+
+                // (all RecipientInfo structures are version 0)
+                // -- 'kari.version' is always 3
+                // -- 'kekri.version' is always 4
+                // -- 'pwri' and 'ori' have already been excluded
+                allV0Recipients = allV0Recipients && recipientInfo.IsKeyTransV0();
+            }
+
+            if (originatorInfo == null && unprotectedAttrs == null && allV0Recipients)
+                return DerInteger.Zero;
+
+            return DerInteger.Two;
         }
     }
 }
diff --git a/crypto/src/asn1/cms/Evidence.cs b/crypto/src/asn1/cms/Evidence.cs
index baa93d6b9..f3687009a 100644
--- a/crypto/src/asn1/cms/Evidence.cs
+++ b/crypto/src/asn1/cms/Evidence.cs
@@ -31,12 +31,12 @@ namespace Org.BouncyCastle.Asn1.Cms
 
         public Evidence(TimeStampTokenEvidence tstEvidence)
 		{
-			m_tstEvidence = tstEvidence;
+			m_tstEvidence = tstEvidence ?? throw new ArgumentNullException(nameof(tstEvidence));
 		}
 
         public Evidence(EvidenceRecord ersEvidence)
         {
-            m_ersEvidence = ersEvidence;
+            m_ersEvidence = ersEvidence ?? throw new ArgumentNullException(nameof(ersEvidence));
         }
 
         private Evidence(Asn1TaggedObject tagged)
diff --git a/crypto/src/asn1/cms/GcmParameters.cs b/crypto/src/asn1/cms/GcmParameters.cs
index 06b4b88ca..b97ba6806 100644
--- a/crypto/src/asn1/cms/GcmParameters.cs
+++ b/crypto/src/asn1/cms/GcmParameters.cs
@@ -23,44 +23,39 @@ namespace Org.BouncyCastle.Asn1.Cms
             return new GcmParameters(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
-        private readonly byte[] m_nonce;
+        private readonly Asn1OctetString m_nonce;
         private readonly int m_icvLen;
 
         private GcmParameters(Asn1Sequence seq)
         {
-            int count = seq.Count;
+            int count = seq.Count, pos = 0;
             if (count < 1 || count > 2)
                 throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-            m_nonce = Asn1OctetString.GetInstance(seq[0]).GetOctets();
+            m_nonce = Asn1OctetString.GetInstance(seq[pos++]);
+            DerInteger icvLen = Asn1Utilities.ReadOptional(seq, ref pos, DerInteger.GetOptional);
 
-            if (count > 1)
-            {
-                m_icvLen = DerInteger.GetInstance(seq[1]).IntValueExact;
-            }
-            else
-            {
-                m_icvLen = DefaultIcvLen;
-            }
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
+
+            m_icvLen = icvLen == null ? DefaultIcvLen : icvLen.IntValueExact;
         }
 
         public GcmParameters(byte[] nonce, int icvLen)
         {
-            m_nonce = Arrays.Clone(nonce);
+            m_nonce = new DerOctetString(nonce);
             m_icvLen = icvLen;
         }
 
-        public byte[] GetNonce() => Arrays.Clone(m_nonce);
+        public byte[] GetNonce() => Arrays.Clone(m_nonce.GetOctets());
 
         public int IcvLen => m_icvLen;
 
         public override Asn1Object ToAsn1Object()
         {
-            var nonce = new DerOctetString(m_nonce);
-
             return m_icvLen == DefaultIcvLen
-                ?   new DerSequence(nonce)
-                :   new DerSequence(nonce, new DerInteger(m_icvLen));
+                ?  new DerSequence(m_nonce)
+                :  new DerSequence(m_nonce, new DerInteger(m_icvLen));
         }
     }
 }
diff --git a/crypto/src/asn1/cms/IssuerAndSerialNumber.cs b/crypto/src/asn1/cms/IssuerAndSerialNumber.cs
index dcd489336..f88652def 100644
--- a/crypto/src/asn1/cms/IssuerAndSerialNumber.cs
+++ b/crypto/src/asn1/cms/IssuerAndSerialNumber.cs
@@ -1,3 +1,5 @@
+using System;
+
 using Org.BouncyCastle.Asn1.X509;
 using Org.BouncyCastle.Math;
 
@@ -25,6 +27,10 @@ namespace Org.BouncyCastle.Asn1.Cms
 
         private IssuerAndSerialNumber(Asn1Sequence seq)
         {
+            int count = seq.Count;
+            if (count != 2)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
             m_name = X509Name.GetInstance(seq[0]);
             m_serialNumber = DerInteger.GetInstance(seq[1]);
         }
diff --git a/crypto/src/asn1/cms/KEKIdentifier.cs b/crypto/src/asn1/cms/KEKIdentifier.cs
index 433157ef3..cde145f04 100644
--- a/crypto/src/asn1/cms/KEKIdentifier.cs
+++ b/crypto/src/asn1/cms/KEKIdentifier.cs
@@ -23,62 +23,37 @@ namespace Org.BouncyCastle.Asn1.Cms
 #pragma warning restore CS0618 // Type or member is obsolete
         }
 
-        private Asn1OctetString		keyIdentifier;
-        private Asn1GeneralizedTime date;
-        private OtherKeyAttribute	other;
+        private readonly Asn1OctetString m_keyIdentifier;
+        private readonly Asn1GeneralizedTime m_date;
+        private readonly OtherKeyAttribute m_other;
 
-		public KekIdentifier(
-            byte[]              keyIdentifier,
-            Asn1GeneralizedTime date,
-            OtherKeyAttribute   other)
+        public KekIdentifier(byte[] keyIdentifier, Asn1GeneralizedTime date, OtherKeyAttribute other)
         {
-            this.keyIdentifier = new DerOctetString(keyIdentifier);
-            this.date = date;
-            this.other = other;
+            m_keyIdentifier = new DerOctetString(keyIdentifier);
+            m_date = date;
+            m_other = other;
         }
 
         [Obsolete("Use 'GetInstance' instead")]
         public KekIdentifier(Asn1Sequence seq)
         {
-            keyIdentifier = (Asn1OctetString)seq[0];
+            int count = seq.Count, pos = 0;
+            if (count < 1 || count > 3)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
 
-			switch (seq.Count)
-            {
-            case 1:
-				break;
-            case 2:
-				if (seq[1] is Asn1GeneralizedTime asn1GeneralizedTime)
-				{
-					date = asn1GeneralizedTime;
-				}
-				else
-				{
-					other = OtherKeyAttribute.GetInstance(seq[2]);
-				}
-				break;
-            case 3:
-				date = (Asn1GeneralizedTime)seq[1];
-				other = OtherKeyAttribute.GetInstance(seq[2]);
-				break;
-            default:
-				throw new ArgumentException("Invalid KekIdentifier");
-            }
+            m_keyIdentifier = Asn1OctetString.GetInstance(seq[pos++]);
+            m_date = Asn1Utilities.ReadOptional(seq, ref pos, Asn1GeneralizedTime.GetOptional);
+            m_other = Asn1Utilities.ReadOptional(seq, ref pos, OtherKeyAttribute.GetOptional);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-        public Asn1OctetString KeyIdentifier
-		{
-			get { return keyIdentifier; }
-		}
+        public Asn1OctetString KeyIdentifier => m_keyIdentifier;
 
-		public Asn1GeneralizedTime Date
-		{
-			get { return date; }
-		}
+        public Asn1GeneralizedTime Date => m_date;
 
-		public OtherKeyAttribute Other
-		{
-			get { return other; }
-		}
+        public OtherKeyAttribute Other => m_other;
 
 		/**
          * Produce an object suitable for an Asn1OutputStream.
@@ -92,8 +67,9 @@ namespace Org.BouncyCastle.Asn1.Cms
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(keyIdentifier);
-			v.AddOptional(date, other);
+            Asn1EncodableVector v = new Asn1EncodableVector(3);
+            v.Add(m_keyIdentifier);
+			v.AddOptional(m_date, m_other);
 			return new DerSequence(v);
         }
     }
diff --git a/crypto/src/asn1/cms/KEKRecipientInfo.cs b/crypto/src/asn1/cms/KEKRecipientInfo.cs
index b1b85953e..ea1a2e080 100644
--- a/crypto/src/asn1/cms/KEKRecipientInfo.cs
+++ b/crypto/src/asn1/cms/KEKRecipientInfo.cs
@@ -25,51 +25,40 @@ namespace Org.BouncyCastle.Asn1.Cms
 #pragma warning restore CS0618 // Type or member is obsolete
         }
 
-        private DerInteger			version;
-        private KekIdentifier       kekID;
-        private AlgorithmIdentifier keyEncryptionAlgorithm;
-        private Asn1OctetString     encryptedKey;
+        private readonly DerInteger m_version;
+        private readonly KekIdentifier m_kekID;
+        private readonly AlgorithmIdentifier m_keyEncryptionAlgorithm;
+        private readonly Asn1OctetString m_encryptedKey;
 
-		public KekRecipientInfo(
-            KekIdentifier       kekID,
-            AlgorithmIdentifier keyEncryptionAlgorithm,
-            Asn1OctetString     encryptedKey)
+        public KekRecipientInfo(KekIdentifier kekID, AlgorithmIdentifier keyEncryptionAlgorithm,
+            Asn1OctetString encryptedKey)
         {
-            this.version = DerInteger.Four;
-            this.kekID = kekID;
-            this.keyEncryptionAlgorithm = keyEncryptionAlgorithm;
-            this.encryptedKey = encryptedKey;
+            m_version = DerInteger.Four;
+            m_kekID = kekID ?? throw new ArgumentNullException(nameof(kekID));
+            m_keyEncryptionAlgorithm = keyEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(keyEncryptionAlgorithm));
+            m_encryptedKey = encryptedKey ?? throw new ArgumentNullException(nameof(encryptedKey));
         }
 
         [Obsolete("Use 'GetInstance' instead")]
-        public KekRecipientInfo(
-            Asn1Sequence seq)
+        public KekRecipientInfo(Asn1Sequence seq)
         {
-            version = (DerInteger) seq[0];
-            kekID = KekIdentifier.GetInstance(seq[1]);
-            keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
-            encryptedKey = (Asn1OctetString) seq[3];
+            int count = seq.Count;
+            if (count != 4)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_version = DerInteger.GetInstance(seq[0]);
+            m_kekID = KekIdentifier.GetInstance(seq[1]);
+            m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]);
+            m_encryptedKey = Asn1OctetString.GetInstance(seq[3]);
         }
 
-        public DerInteger Version
-		{
-			get { return version; }
-		}
+        public DerInteger Version => m_version;
 
-		public KekIdentifier KekID
-		{
-			get { return kekID; }
-		}
+        public KekIdentifier KekID => m_kekID;
 
-		public AlgorithmIdentifier KeyEncryptionAlgorithm
-		{
-			get { return keyEncryptionAlgorithm; }
-		}
+		public AlgorithmIdentifier KeyEncryptionAlgorithm => m_keyEncryptionAlgorithm;
 
-		public Asn1OctetString EncryptedKey
-		{
-			get { return encryptedKey; }
-		}
+        public Asn1OctetString EncryptedKey => m_encryptedKey;
 
 		/**
          * Produce an object suitable for an Asn1OutputStream.
@@ -82,9 +71,7 @@ namespace Org.BouncyCastle.Asn1.Cms
          * }
          * 
*/ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(version, kekID, keyEncryptionAlgorithm, encryptedKey); - } + public override Asn1Object ToAsn1Object() => + new DerSequence(m_version, m_kekID, m_keyEncryptionAlgorithm, m_encryptedKey); } } diff --git a/crypto/src/asn1/cms/KemRecipientInfo.cs b/crypto/src/asn1/cms/KemRecipientInfo.cs index 4f771784a..ccfae719c 100644 --- a/crypto/src/asn1/cms/KemRecipientInfo.cs +++ b/crypto/src/asn1/cms/KemRecipientInfo.cs @@ -62,27 +62,25 @@ namespace Org.BouncyCastle.Asn1.Cms private KemRecipientInfo(Asn1Sequence seq) { - int count = seq.Count; + int count = seq.Count, pos = 0; if (count < 8 || count > 9) throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - int index = 0; + m_cmsVersion = DerInteger.GetInstance(seq[pos++]); + m_rid = RecipientIdentifier.GetInstance(seq[pos++]); + m_kem = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_kemct = Asn1OctetString.GetInstance(seq[pos++]); + m_kdf = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_kekLength = DerInteger.GetInstance(seq[pos++]); + m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, Asn1OctetString.GetInstance); + m_wrap = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_encryptedKey = Asn1OctetString.GetInstance(seq[pos++]); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); - m_cmsVersion = DerInteger.GetInstance(seq[index++]); if (!m_cmsVersion.HasValue(0)) throw new ArgumentException("Unsupported version (hex): " + m_cmsVersion.Value.ToString(16)); - - m_rid = RecipientIdentifier.GetInstance(seq[index++]); - m_kem = AlgorithmIdentifier.GetInstance(seq[index++]); - m_kemct = Asn1OctetString.GetInstance(seq[index++]); - m_kdf = AlgorithmIdentifier.GetInstance(seq[index++]); - m_kekLength = DerInteger.GetInstance(seq[index++]); - m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref index, 0, true, Asn1OctetString.GetInstance); - m_wrap = AlgorithmIdentifier.GetInstance(seq[index++]); - m_encryptedKey = Asn1OctetString.GetInstance(seq[index++]); - - if (index != count) - throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } public RecipientIdentifier RecipientIdentifier => m_rid; diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs index 9e6e3bd5a..fb393b9ba 100644 --- a/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs +++ b/crypto/src/asn1/cms/KeyAgreeRecipientIdentifier.cs @@ -35,30 +35,22 @@ namespace Org.BouncyCastle.Asn1.Cms return Asn1Utilities.GetInstanceFromChoice(obj, isExplicit, GetInstance); } - private readonly IssuerAndSerialNumber issuerSerial; - private readonly RecipientKeyIdentifier rKeyID; + private readonly IssuerAndSerialNumber m_issuerSerial; + private readonly RecipientKeyIdentifier m_rKeyID; - public KeyAgreeRecipientIdentifier( - IssuerAndSerialNumber issuerSerial) - { - this.issuerSerial = issuerSerial; - } + public KeyAgreeRecipientIdentifier(IssuerAndSerialNumber issuerSerial) + { + m_issuerSerial = issuerSerial ?? throw new ArgumentNullException(nameof(issuerSerial)); + } - public KeyAgreeRecipientIdentifier( - RecipientKeyIdentifier rKeyID) - { - this.rKeyID = rKeyID; - } + public KeyAgreeRecipientIdentifier(RecipientKeyIdentifier rKeyID) + { + m_rKeyID = rKeyID ?? throw new ArgumentNullException(nameof(rKeyID)); + } - public IssuerAndSerialNumber IssuerAndSerialNumber - { - get { return issuerSerial; } - } + public IssuerAndSerialNumber IssuerAndSerialNumber => m_issuerSerial; - public RecipientKeyIdentifier RKeyID - { - get { return rKeyID; } - } + public RecipientKeyIdentifier RKeyID => m_rKeyID; /** * Produce an object suitable for an Asn1OutputStream. @@ -71,12 +63,10 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - if (issuerSerial != null) - { - return issuerSerial.ToAsn1Object(); - } + if (m_issuerSerial != null) + return m_issuerSerial.ToAsn1Object(); - return new DerTaggedObject(false, 0, rKeyID); + return new DerTaggedObject(false, 0, m_rKeyID); } } } diff --git a/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs index 345a45029..c1255adc9 100644 --- a/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs +++ b/crypto/src/asn1/cms/KeyAgreeRecipientInfo.cs @@ -25,68 +25,48 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerInteger version; - private OriginatorIdentifierOrKey originator; - private Asn1OctetString ukm; - private AlgorithmIdentifier keyEncryptionAlgorithm; - private Asn1Sequence recipientEncryptedKeys; - - public KeyAgreeRecipientInfo( - OriginatorIdentifierOrKey originator, - Asn1OctetString ukm, - AlgorithmIdentifier keyEncryptionAlgorithm, - Asn1Sequence recipientEncryptedKeys) + private readonly DerInteger m_version; + private readonly OriginatorIdentifierOrKey m_originator; + private readonly Asn1OctetString m_ukm; + private readonly AlgorithmIdentifier m_keyEncryptionAlgorithm; + private readonly Asn1Sequence m_recipientEncryptedKeys; + + public KeyAgreeRecipientInfo(OriginatorIdentifierOrKey originator, Asn1OctetString ukm, + AlgorithmIdentifier keyEncryptionAlgorithm, Asn1Sequence recipientEncryptedKeys) { - this.version = DerInteger.Three; - this.originator = originator; - this.ukm = ukm; - this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; - this.recipientEncryptedKeys = recipientEncryptedKeys; + m_version = DerInteger.Three; + m_originator = originator ?? throw new ArgumentNullException(nameof(originator)); + m_ukm = ukm; + m_keyEncryptionAlgorithm = keyEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(keyEncryptionAlgorithm)); + m_recipientEncryptedKeys = recipientEncryptedKeys ?? throw new ArgumentNullException(nameof(recipientEncryptedKeys)); } [Obsolete("Use 'GetInstance' instead")] public KeyAgreeRecipientInfo(Asn1Sequence seq) { - int index = 0; - - version = (DerInteger) seq[index++]; - originator = OriginatorIdentifierOrKey.GetInstance((Asn1TaggedObject)seq[index++], true); - - if (seq[index] is Asn1TaggedObject taggedObject) - { - ukm = Asn1OctetString.GetInstance(taggedObject, true); - ++index; - } - - keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[index++]); - - recipientEncryptedKeys = (Asn1Sequence)seq[index++]; + int count = seq.Count, pos = 0; + if (count < 4 || count > 5) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[pos++]); + m_originator = Asn1Utilities.ReadContextTagged(seq, ref pos, 0, true, OriginatorIdentifierOrKey.GetInstance); + m_ukm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, true, Asn1OctetString.GetInstance); + m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_recipientEncryptedKeys = Asn1Sequence.GetInstance(seq[pos++]); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public OriginatorIdentifierOrKey Originator - { - get { return originator; } - } + public OriginatorIdentifierOrKey Originator => m_originator; - public Asn1OctetString UserKeyingMaterial - { - get { return ukm; } - } + public Asn1OctetString UserKeyingMaterial => m_ukm; - public AlgorithmIdentifier KeyEncryptionAlgorithm - { - get { return keyEncryptionAlgorithm; } - } + public AlgorithmIdentifier KeyEncryptionAlgorithm => m_keyEncryptionAlgorithm; - public Asn1Sequence RecipientEncryptedKeys - { - get { return recipientEncryptedKeys; } - } + public Asn1Sequence RecipientEncryptedKeys => m_recipientEncryptedKeys; /** * Produce an object suitable for an Asn1OutputStream. @@ -104,9 +84,10 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(version, new DerTaggedObject(true, 0, originator)); - v.AddOptionalTagged(true, 1, ukm); - v.Add(keyEncryptionAlgorithm, recipientEncryptedKeys); + Asn1EncodableVector v = new Asn1EncodableVector(5); + v.Add(m_version, new DerTaggedObject(true, 0, m_originator)); + v.AddOptionalTagged(true, 1, m_ukm); + v.Add(m_keyEncryptionAlgorithm, m_recipientEncryptedKeys); return new DerSequence(v); } } diff --git a/crypto/src/asn1/cms/KeyTransRecipientInfo.cs b/crypto/src/asn1/cms/KeyTransRecipientInfo.cs index 1d9825b02..2274d1631 100644 --- a/crypto/src/asn1/cms/KeyTransRecipientInfo.cs +++ b/crypto/src/asn1/cms/KeyTransRecipientInfo.cs @@ -1,7 +1,6 @@ using System; using Org.BouncyCastle.Asn1.X509; -using Org.BouncyCastle.Utilities; namespace Org.BouncyCastle.Asn1.Cms { @@ -26,59 +25,40 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerInteger version; - private RecipientIdentifier rid; - private AlgorithmIdentifier keyEncryptionAlgorithm; - private Asn1OctetString encryptedKey; + private readonly DerInteger m_version; + private readonly RecipientIdentifier m_rid; + private readonly AlgorithmIdentifier m_keyEncryptionAlgorithm; + private readonly Asn1OctetString m_encryptedKey; - public KeyTransRecipientInfo( - RecipientIdentifier rid, - AlgorithmIdentifier keyEncryptionAlgorithm, - Asn1OctetString encryptedKey) + public KeyTransRecipientInfo(RecipientIdentifier rid, AlgorithmIdentifier keyEncryptionAlgorithm, + Asn1OctetString encryptedKey) { - if (rid.ToAsn1Object() is Asn1TaggedObject) - { - this.version = DerInteger.Two; - } - else - { - this.version = DerInteger.Zero; - } - - this.rid = rid; - this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; - this.encryptedKey = encryptedKey; + m_rid = rid ?? throw new ArgumentNullException(nameof(rid)); + m_keyEncryptionAlgorithm = keyEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(keyEncryptionAlgorithm)); + m_encryptedKey = encryptedKey ?? throw new ArgumentNullException(nameof(encryptedKey)); + m_version = rid.IsTagged ? DerInteger.Two : DerInteger.Zero; } [Obsolete("Use 'GetInstance' instead")] - public KeyTransRecipientInfo( - Asn1Sequence seq) + public KeyTransRecipientInfo(Asn1Sequence seq) { - this.version = (DerInteger) seq[0]; - this.rid = RecipientIdentifier.GetInstance(seq[1]); - this.keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); - this.encryptedKey = (Asn1OctetString) seq[3]; + int count = seq.Count; + if (count != 4) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[0]); + m_rid = RecipientIdentifier.GetInstance(seq[1]); + m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); + m_encryptedKey = Asn1OctetString.GetInstance(seq[3]); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public RecipientIdentifier RecipientIdentifier - { - get { return rid; } - } + public RecipientIdentifier RecipientIdentifier => m_rid; - public AlgorithmIdentifier KeyEncryptionAlgorithm - { - get { return keyEncryptionAlgorithm; } - } + public AlgorithmIdentifier KeyEncryptionAlgorithm => m_keyEncryptionAlgorithm; - public Asn1OctetString EncryptedKey - { - get { return encryptedKey; } - } + public Asn1OctetString EncryptedKey => m_encryptedKey; /** * Produce an object suitable for an Asn1OutputStream. @@ -91,9 +71,7 @@ namespace Org.BouncyCastle.Asn1.Cms * } * */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(version, rid, keyEncryptionAlgorithm, encryptedKey); - } + public override Asn1Object ToAsn1Object() => + new DerSequence(m_version, m_rid, m_keyEncryptionAlgorithm, m_encryptedKey); } } diff --git a/crypto/src/asn1/cms/MetaData.cs b/crypto/src/asn1/cms/MetaData.cs index a0d783d59..5754fd6f1 100644 --- a/crypto/src/asn1/cms/MetaData.cs +++ b/crypto/src/asn1/cms/MetaData.cs @@ -19,46 +19,59 @@ namespace Org.BouncyCastle.Asn1.Cms return new MetaData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private DerBoolean hashProtected; - private DerUtf8String fileName; - private DerIA5String mediaType; - private Attributes otherMetaData; - - public MetaData( - DerBoolean hashProtected, - DerUtf8String fileName, - DerIA5String mediaType, - Attributes otherMetaData) - { - this.hashProtected = hashProtected; - this.fileName = fileName; - this.mediaType = mediaType; - this.otherMetaData = otherMetaData; - } + public static MetaData GetOptional(Asn1Encodable element) + { + if (element == null) + throw new ArgumentNullException(nameof(element)); - private MetaData(Asn1Sequence seq) - { - this.hashProtected = DerBoolean.GetInstance(seq[0]); - - int index = 1; - - if (index < seq.Count && seq[index] is DerUtf8String utf8) - { - this.fileName = utf8; - ++index; - } - if (index < seq.Count && seq[index] is DerIA5String ia5) - { - this.mediaType = ia5; - ++index; - } - if (index < seq.Count) - { - this.otherMetaData = Attributes.GetInstance(seq[index++]); - } - } + if (element is MetaData metaData) + return metaData; + + Asn1Sequence asn1Sequence = Asn1Sequence.GetOptional(element); + if (asn1Sequence != null) + return new MetaData(asn1Sequence); + + return null; + } + + private readonly DerBoolean m_hashProtected; + private readonly DerUtf8String m_fileName; + private readonly DerIA5String m_mediaType; + private readonly Attributes m_otherMetaData; + + public MetaData(DerBoolean hashProtected, DerUtf8String fileName, DerIA5String mediaType, + Attributes otherMetaData) + { + m_hashProtected = hashProtected ?? throw new ArgumentNullException(nameof(hashProtected)); + m_fileName = fileName; + m_mediaType = mediaType; + m_otherMetaData = otherMetaData; + } + + private MetaData(Asn1Sequence seq) + { + int count = seq.Count, pos = 0; + if (count < 1 || count > 4) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_hashProtected = DerBoolean.GetInstance(seq[pos++]); + m_fileName = Asn1Utilities.ReadOptional(seq, ref pos, DerUtf8String.GetOptional); + m_mediaType = Asn1Utilities.ReadOptional(seq, ref pos, DerIA5String.GetOptional); + m_otherMetaData = Asn1Utilities.ReadOptional(seq, ref pos, Attributes.GetOptional); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); + } - /** + public virtual bool IsHashProtected => m_hashProtected.IsTrue; + + public virtual DerUtf8String FileName => m_fileName; + + public virtual DerIA5String MediaType => m_mediaType; + + public virtual Attributes OtherMetaData => m_otherMetaData; + + /** *
 		 * MetaData ::= SEQUENCE {
 		 *   hashProtected        BOOLEAN,
@@ -69,31 +82,12 @@ namespace Org.BouncyCastle.Asn1.Cms
 		 * 
* @return */ - public override Asn1Object ToAsn1Object() + public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(hashProtected); - v.AddOptional(fileName, mediaType, otherMetaData); + Asn1EncodableVector v = new Asn1EncodableVector(4); + v.Add(m_hashProtected); + v.AddOptional(m_fileName, m_mediaType, m_otherMetaData); return new DerSequence(v); } - - public virtual bool IsHashProtected - { - get { return hashProtected.IsTrue; } - } - - public virtual DerUtf8String FileName - { - get { return fileName; } - } - - public virtual DerIA5String MediaType - { - get { return mediaType; } - } - - public virtual Attributes OtherMetaData - { - get { return otherMetaData; } - } } } diff --git a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs index 6d127ccc3..f5cc1f2f7 100644 --- a/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs +++ b/crypto/src/asn1/cms/OriginatorIdentifierOrKey.cs @@ -43,7 +43,7 @@ namespace Org.BouncyCastle.Asn1.Cms public OriginatorIdentifierOrKey(IssuerAndSerialNumber id) { - m_id = id; + m_id = id ?? throw new ArgumentNullException(nameof(id)); } public OriginatorIdentifierOrKey(SubjectKeyIdentifier id) diff --git a/crypto/src/asn1/cms/OriginatorInfo.cs b/crypto/src/asn1/cms/OriginatorInfo.cs index 48b771bcb..74569cbec 100644 --- a/crypto/src/asn1/cms/OriginatorInfo.cs +++ b/crypto/src/asn1/cms/OriginatorInfo.cs @@ -1,7 +1,5 @@ using System; -using Org.BouncyCastle.Utilities; - namespace Org.BouncyCastle.Asn1.Cms { public class OriginatorInfo @@ -25,57 +23,32 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private Asn1Set certs; - private Asn1Set crls; + private readonly Asn1Set m_certs; + private readonly Asn1Set m_crls; - public OriginatorInfo( - Asn1Set certs, - Asn1Set crls) + public OriginatorInfo(Asn1Set certs, Asn1Set crls) { - this.certs = certs; - this.crls = crls; + m_certs = certs; + m_crls = crls; } [Obsolete("Use 'GetInstance' instead")] - public OriginatorInfo( - Asn1Sequence seq) + public OriginatorInfo(Asn1Sequence seq) { - switch (seq.Count) - { - case 0: // empty - break; - case 1: - Asn1TaggedObject o = (Asn1TaggedObject) seq[0]; - switch (o.TagNo) - { - case 0 : - certs = Asn1Set.GetInstance(o, false); - break; - case 1 : - crls = Asn1Set.GetInstance(o, false); - break; - default: - throw new ArgumentException("Bad tag in OriginatorInfo: " + o.TagNo); - } - break; - case 2: - certs = Asn1Set.GetInstance((Asn1TaggedObject) seq[0], false); - crls = Asn1Set.GetInstance((Asn1TaggedObject) seq[1], false); - break; - default: - throw new ArgumentException("OriginatorInfo too big"); - } + int count = seq.Count, pos = 0; + if (count < 0 || count > 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_certs = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance); + m_crls = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public Asn1Set Certificates - { - get { return certs; } - } + public Asn1Set Certificates => m_certs; - public Asn1Set Crls - { - get { return crls; } - } + public Asn1Set Crls => m_crls; /** * Produce an object suitable for an Asn1OutputStream. @@ -89,8 +62,8 @@ namespace Org.BouncyCastle.Asn1.Cms public override Asn1Object ToAsn1Object() { Asn1EncodableVector v = new Asn1EncodableVector(2); - v.AddOptionalTagged(false, 0, certs); - v.AddOptionalTagged(false, 1, crls); + v.AddOptionalTagged(false, 0, m_certs); + v.AddOptionalTagged(false, 1, m_crls); return new DerSequence(v); } } diff --git a/crypto/src/asn1/cms/OriginatorPublicKey.cs b/crypto/src/asn1/cms/OriginatorPublicKey.cs index 6ed017877..eb302c00b 100644 --- a/crypto/src/asn1/cms/OriginatorPublicKey.cs +++ b/crypto/src/asn1/cms/OriginatorPublicKey.cs @@ -1,3 +1,5 @@ +using System; + using Org.BouncyCastle.Asn1.X509; namespace Org.BouncyCastle.Asn1.Cms @@ -29,12 +31,16 @@ namespace Org.BouncyCastle.Asn1.Cms public OriginatorPublicKey(AlgorithmIdentifier algorithm, DerBitString publicKey) { - m_algorithm = algorithm; - m_publicKey = publicKey; + m_algorithm = algorithm ?? throw new ArgumentNullException(nameof(algorithm)); + m_publicKey = publicKey ?? throw new ArgumentNullException(nameof(publicKey)); } private OriginatorPublicKey(Asn1Sequence seq) { + int count = seq.Count; + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + m_algorithm = AlgorithmIdentifier.GetInstance(seq[0]); m_publicKey = DerBitString.GetInstance(seq[1]); } diff --git a/crypto/src/asn1/cms/OtherKeyAttribute.cs b/crypto/src/asn1/cms/OtherKeyAttribute.cs index 52f013950..901009209 100644 --- a/crypto/src/asn1/cms/OtherKeyAttribute.cs +++ b/crypto/src/asn1/cms/OtherKeyAttribute.cs @@ -23,34 +23,46 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private DerObjectIdentifier keyAttrId; - private Asn1Encodable keyAttr; + public static OtherKeyAttribute GetOptional(Asn1Encodable element) + { + if (element == null) + throw new ArgumentNullException(nameof(element)); + + if (element is OtherKeyAttribute otherKeyAttribute) + return otherKeyAttribute; + + Asn1Sequence asn1Sequence = Asn1Sequence.GetOptional(element); + if (asn1Sequence != null) +#pragma warning disable CS0618 // Type or member is obsolete + return new OtherKeyAttribute(asn1Sequence); +#pragma warning restore CS0618 // Type or member is obsolete + + return null; + } + + private readonly DerObjectIdentifier m_keyAttrId; + private readonly Asn1Encodable m_keyAttr; [Obsolete("Use 'GetInstance' instead")] - public OtherKeyAttribute( - Asn1Sequence seq) + public OtherKeyAttribute(Asn1Sequence seq) { - keyAttrId = (DerObjectIdentifier) seq[0]; - keyAttr = seq[1]; + int count = seq.Count; + if (count < 1 || count > 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_keyAttrId = DerObjectIdentifier.GetInstance(seq[0]); + m_keyAttr = count == 1 ? null : seq[1]; } - public OtherKeyAttribute( - DerObjectIdentifier keyAttrId, - Asn1Encodable keyAttr) + public OtherKeyAttribute(DerObjectIdentifier keyAttrId, Asn1Encodable keyAttr) { - this.keyAttrId = keyAttrId; - this.keyAttr = keyAttr; + m_keyAttrId = keyAttrId ?? throw new ArgumentNullException(nameof(keyAttrId)); + m_keyAttr = keyAttr; } - public DerObjectIdentifier KeyAttrId - { - get { return keyAttrId; } - } + public DerObjectIdentifier KeyAttrId => m_keyAttrId; - public Asn1Encodable KeyAttr - { - get { return keyAttr; } - } + public Asn1Encodable KeyAttr => m_keyAttr; /** * Produce an object suitable for an Asn1OutputStream. @@ -63,7 +75,9 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - return new DerSequence(keyAttrId, keyAttr); + return m_keyAttr == null + ? new DerSequence(m_keyAttrId) + : new DerSequence(m_keyAttrId, m_keyAttr); } } } diff --git a/crypto/src/asn1/cms/OtherRecipientInfo.cs b/crypto/src/asn1/cms/OtherRecipientInfo.cs index 989b6183e..b47a256f9 100644 --- a/crypto/src/asn1/cms/OtherRecipientInfo.cs +++ b/crypto/src/asn1/cms/OtherRecipientInfo.cs @@ -1,3 +1,5 @@ +using System; + namespace Org.BouncyCastle.Asn1.Cms { public class OtherRecipientInfo @@ -17,32 +19,28 @@ namespace Org.BouncyCastle.Asn1.Cms return new OtherRecipientInfo(Asn1Sequence.GetInstance(obj, explicitly)); } - private readonly DerObjectIdentifier oriType; - private readonly Asn1Encodable oriValue; + private readonly DerObjectIdentifier m_oriType; + private readonly Asn1Encodable m_oriValue; - public OtherRecipientInfo( - DerObjectIdentifier oriType, - Asn1Encodable oriValue) + public OtherRecipientInfo(DerObjectIdentifier oriType, Asn1Encodable oriValue) { - this.oriType = oriType; - this.oriValue = oriValue; + m_oriType = oriType ?? throw new ArgumentNullException(nameof(oriType)); + m_oriValue = oriValue ?? throw new ArgumentNullException(nameof(oriValue)); } private OtherRecipientInfo(Asn1Sequence seq) { - oriType = DerObjectIdentifier.GetInstance(seq[0]); - oriValue = seq[1]; - } + int count = seq.Count; + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - public virtual DerObjectIdentifier OriType - { - get { return oriType; } + m_oriType = DerObjectIdentifier.GetInstance(seq[0]); + m_oriValue = seq[1]; } - public virtual Asn1Encodable OriValue - { - get { return oriValue; } - } + public virtual DerObjectIdentifier OriType => m_oriType; + + public virtual Asn1Encodable OriValue => m_oriValue; /** * Produce an object suitable for an Asn1OutputStream. @@ -52,9 +50,6 @@ namespace Org.BouncyCastle.Asn1.Cms * oriValue ANY DEFINED BY oriType } * */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(oriType, oriValue); - } + public override Asn1Object ToAsn1Object() => new DerSequence(m_oriType, m_oriValue); } } diff --git a/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs index d39f14aa8..b85468beb 100644 --- a/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs +++ b/crypto/src/asn1/cms/OtherRevocationInfoFormat.cs @@ -1,4 +1,6 @@ -namespace Org.BouncyCastle.Asn1.Cms +using System; + +namespace Org.BouncyCastle.Asn1.Cms { public class OtherRevocationInfoFormat : Asn1Encodable @@ -17,32 +19,28 @@ return new OtherRevocationInfoFormat(Asn1Sequence.GetInstance(obj, isExplicit)); } - private readonly DerObjectIdentifier otherRevInfoFormat; - private readonly Asn1Encodable otherRevInfo; + private readonly DerObjectIdentifier m_otherRevInfoFormat; + private readonly Asn1Encodable m_otherRevInfo; - public OtherRevocationInfoFormat( - DerObjectIdentifier otherRevInfoFormat, - Asn1Encodable otherRevInfo) + public OtherRevocationInfoFormat(DerObjectIdentifier otherRevInfoFormat, Asn1Encodable otherRevInfo) { - this.otherRevInfoFormat = otherRevInfoFormat; - this.otherRevInfo = otherRevInfo; + m_otherRevInfoFormat = otherRevInfoFormat ?? throw new ArgumentNullException(nameof(otherRevInfoFormat)); + m_otherRevInfo = otherRevInfo ?? throw new ArgumentNullException(nameof(otherRevInfo)); } private OtherRevocationInfoFormat(Asn1Sequence seq) { - otherRevInfoFormat = DerObjectIdentifier.GetInstance(seq[0]); - otherRevInfo = seq[1]; - } + int count = seq.Count; + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - public virtual DerObjectIdentifier InfoFormat - { - get { return otherRevInfoFormat; } + m_otherRevInfoFormat = DerObjectIdentifier.GetInstance(seq[0]); + m_otherRevInfo = seq[1]; } - public virtual Asn1Encodable Info - { - get { return otherRevInfo; } - } + public virtual DerObjectIdentifier InfoFormat => m_otherRevInfoFormat; + + public virtual Asn1Encodable Info => m_otherRevInfo; /** * Produce an object suitable for an ASN1OutputStream. @@ -52,9 +50,6 @@ * otherRevInfo ANY DEFINED BY otherRevInfoFormat } * */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(otherRevInfoFormat, otherRevInfo); - } + public override Asn1Object ToAsn1Object() => new DerSequence(m_otherRevInfoFormat, m_otherRevInfo); } } diff --git a/crypto/src/asn1/cms/PasswordRecipientInfo.cs b/crypto/src/asn1/cms/PasswordRecipientInfo.cs index 5fac434ca..41ab686ef 100644 --- a/crypto/src/asn1/cms/PasswordRecipientInfo.cs +++ b/crypto/src/asn1/cms/PasswordRecipientInfo.cs @@ -25,68 +25,46 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private readonly DerInteger version; - private readonly AlgorithmIdentifier keyDerivationAlgorithm; - private readonly AlgorithmIdentifier keyEncryptionAlgorithm; - private readonly Asn1OctetString encryptedKey; + private readonly DerInteger m_version; + private readonly AlgorithmIdentifier m_keyDerivationAlgorithm; + private readonly AlgorithmIdentifier m_keyEncryptionAlgorithm; + private readonly Asn1OctetString m_encryptedKey; - public PasswordRecipientInfo( - AlgorithmIdentifier keyEncryptionAlgorithm, - Asn1OctetString encryptedKey) + public PasswordRecipientInfo(AlgorithmIdentifier keyEncryptionAlgorithm, Asn1OctetString encryptedKey) + : this(keyDerivationAlgorithm: null, keyEncryptionAlgorithm, encryptedKey) { - this.version = DerInteger.Zero; - this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; - this.encryptedKey = encryptedKey; } - public PasswordRecipientInfo( - AlgorithmIdentifier keyDerivationAlgorithm, - AlgorithmIdentifier keyEncryptionAlgorithm, - Asn1OctetString encryptedKey) + public PasswordRecipientInfo(AlgorithmIdentifier keyDerivationAlgorithm, + AlgorithmIdentifier keyEncryptionAlgorithm, Asn1OctetString encryptedKey) { - this.version = DerInteger.Zero; - this.keyDerivationAlgorithm = keyDerivationAlgorithm; - this.keyEncryptionAlgorithm = keyEncryptionAlgorithm; - this.encryptedKey = encryptedKey; + m_version = DerInteger.Zero; + m_keyDerivationAlgorithm = keyDerivationAlgorithm; + m_keyEncryptionAlgorithm = keyEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(keyEncryptionAlgorithm)); + m_encryptedKey = encryptedKey ?? throw new ArgumentNullException(nameof(encryptedKey)); } [Obsolete("Use 'GetInstance' instead")] public PasswordRecipientInfo(Asn1Sequence seq) { - version = (DerInteger)seq[0]; + int count = seq.Count, pos = 0; + if (count < 3 || count > 4) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - if (seq[1] is Asn1TaggedObject taggedObject) - { - keyDerivationAlgorithm = AlgorithmIdentifier.GetInstance(taggedObject, false); - keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[2]); - encryptedKey = (Asn1OctetString)seq[3]; - } - else - { - keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[1]); - encryptedKey = (Asn1OctetString)seq[2]; - } + m_version = DerInteger.GetInstance(seq[pos++]); + m_keyDerivationAlgorithm = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, + AlgorithmIdentifier.GetInstance); + m_keyEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_encryptedKey = Asn1OctetString.GetInstance(seq[pos++]); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public AlgorithmIdentifier KeyDerivationAlgorithm - { - get { return keyDerivationAlgorithm; } - } + public AlgorithmIdentifier KeyDerivationAlgorithm => m_keyDerivationAlgorithm; - public AlgorithmIdentifier KeyEncryptionAlgorithm - { - get { return keyEncryptionAlgorithm; } - } + public AlgorithmIdentifier KeyEncryptionAlgorithm => m_keyEncryptionAlgorithm; - public Asn1OctetString EncryptedKey - { - get { return encryptedKey; } - } + public Asn1OctetString EncryptedKey => m_encryptedKey; /** * Produce an object suitable for an Asn1OutputStream. @@ -101,10 +79,11 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(version); - v.AddOptionalTagged(false, 0, keyDerivationAlgorithm); - v.Add(keyEncryptionAlgorithm, encryptedKey); - return new DerSequence(v); + if (m_keyDerivationAlgorithm == null) + return new DerSequence(m_version, m_keyEncryptionAlgorithm, m_encryptedKey); + + return new DerSequence(m_version, new DerTaggedObject(false, 0, m_keyDerivationAlgorithm), + m_keyEncryptionAlgorithm, m_encryptedKey); } } } diff --git a/crypto/src/asn1/cms/RecipientEncryptedKey.cs b/crypto/src/asn1/cms/RecipientEncryptedKey.cs index 0e0214909..3a31b3c93 100644 --- a/crypto/src/asn1/cms/RecipientEncryptedKey.cs +++ b/crypto/src/asn1/cms/RecipientEncryptedKey.cs @@ -1,3 +1,5 @@ +using System; + namespace Org.BouncyCastle.Asn1.Cms { public class RecipientEncryptedKey @@ -17,33 +19,28 @@ namespace Org.BouncyCastle.Asn1.Cms return new RecipientEncryptedKey(Asn1Sequence.GetInstance(obj, isExplicit)); } - private readonly KeyAgreeRecipientIdentifier identifier; - private readonly Asn1OctetString encryptedKey; + private readonly KeyAgreeRecipientIdentifier m_identifier; + private readonly Asn1OctetString m_encryptedKey; - private RecipientEncryptedKey( - Asn1Sequence seq) + private RecipientEncryptedKey(Asn1Sequence seq) { - identifier = KeyAgreeRecipientIdentifier.GetInstance(seq[0]); - encryptedKey = (Asn1OctetString) seq[1]; - } + int count = seq.Count; + if (count != 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - public RecipientEncryptedKey( - KeyAgreeRecipientIdentifier id, - Asn1OctetString encryptedKey) - { - this.identifier = id; - this.encryptedKey = encryptedKey; + m_identifier = KeyAgreeRecipientIdentifier.GetInstance(seq[0]); + m_encryptedKey = Asn1OctetString.GetInstance(seq[1]); } - public KeyAgreeRecipientIdentifier Identifier - { - get { return identifier; } - } + public RecipientEncryptedKey(KeyAgreeRecipientIdentifier id, Asn1OctetString encryptedKey) + { + m_identifier = id ?? throw new ArgumentNullException(nameof(id)); + m_encryptedKey = encryptedKey ?? throw new ArgumentNullException(nameof(encryptedKey)); + } - public Asn1OctetString EncryptedKey - { - get { return encryptedKey; } - } + public KeyAgreeRecipientIdentifier Identifier => m_identifier; + + public Asn1OctetString EncryptedKey => m_encryptedKey; /** * Produce an object suitable for an Asn1OutputStream. @@ -54,9 +51,6 @@ namespace Org.BouncyCastle.Asn1.Cms * } * */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(identifier, encryptedKey); - } + public override Asn1Object ToAsn1Object() => new DerSequence(m_identifier, m_encryptedKey); } } diff --git a/crypto/src/asn1/cms/RecipientIdentifier.cs b/crypto/src/asn1/cms/RecipientIdentifier.cs index de9fd5e75..4fe181dff 100644 --- a/crypto/src/asn1/cms/RecipientIdentifier.cs +++ b/crypto/src/asn1/cms/RecipientIdentifier.cs @@ -32,7 +32,7 @@ namespace Org.BouncyCastle.Asn1.Cms public RecipientIdentifier(IssuerAndSerialNumber id) { - m_id = id; + m_id = id ?? throw new ArgumentNullException(nameof(id)); } public RecipientIdentifier(Asn1OctetString id) @@ -42,7 +42,7 @@ namespace Org.BouncyCastle.Asn1.Cms public RecipientIdentifier(Asn1Object id) { - m_id = id; + m_id = id ?? throw new ArgumentNullException(nameof(id)); } public bool IsTagged => m_id is Asn1TaggedObject; diff --git a/crypto/src/asn1/cms/RecipientInfo.cs b/crypto/src/asn1/cms/RecipientInfo.cs index 85bd7e585..424ea4d10 100644 --- a/crypto/src/asn1/cms/RecipientInfo.cs +++ b/crypto/src/asn1/cms/RecipientInfo.cs @@ -29,107 +29,100 @@ namespace Org.BouncyCastle.Asn1.Cms return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance); } - internal Asn1Encodable info; + private readonly Asn1Encodable m_info; - public RecipientInfo( - KeyTransRecipientInfo info) + public RecipientInfo(KeyTransRecipientInfo info) { - this.info = info; + m_info = info ?? throw new ArgumentNullException(nameof(info)); } - public RecipientInfo( - KeyAgreeRecipientInfo info) + public RecipientInfo(KeyAgreeRecipientInfo info) { - this.info = new DerTaggedObject(false, 1, info); + m_info = new DerTaggedObject(false, 1, info); } - public RecipientInfo( - KekRecipientInfo info) + public RecipientInfo(KekRecipientInfo info) { - this.info = new DerTaggedObject(false, 2, info); + m_info = new DerTaggedObject(false, 2, info); } - public RecipientInfo( - PasswordRecipientInfo info) + public RecipientInfo(PasswordRecipientInfo info) { - this.info = new DerTaggedObject(false, 3, info); + m_info = new DerTaggedObject(false, 3, info); } - public RecipientInfo( - OtherRecipientInfo info) + public RecipientInfo(OtherRecipientInfo info) { - this.info = new DerTaggedObject(false, 4, info); + m_info = new DerTaggedObject(false, 4, info); } - public RecipientInfo( - Asn1Object info) + public RecipientInfo(Asn1Object info) { - this.info = info; + m_info = info ?? throw new ArgumentNullException(nameof(info)); } + [Obsolete("Will be removed")] public DerInteger Version { get { - if (info is Asn1TaggedObject o) - { - switch (o.TagNo) - { - case 1: - return KeyAgreeRecipientInfo.GetInstance(o, false).Version; - case 2: - return GetKekInfo(o).Version; - case 3: - return PasswordRecipientInfo.GetInstance(o, false).Version; - case 4: - return DerInteger.Zero; // no syntax version for OtherRecipientInfo - default: - throw new InvalidOperationException("unknown tag"); - } - } - - return KeyTransRecipientInfo.GetInstance(info).Version; + if (!(m_info is Asn1TaggedObject tagged)) + return KeyTransRecipientInfo.GetInstance(m_info).Version; + + if (tagged.HasContextTag()) + { + switch (tagged.TagNo) + { + case 1: + return KeyAgreeRecipientInfo.GetInstance(tagged, false).Version; + case 2: + return GetKekInfo(tagged).Version; + case 3: + return PasswordRecipientInfo.GetInstance(tagged, false).Version; + case 4: + return DerInteger.Zero; // no syntax version for OtherRecipientInfo + } + } + throw new InvalidOperationException("unknown tag"); } } - public bool IsTagged - { - get { return info is Asn1TaggedObject; } - } + public bool IsTagged => m_info is Asn1TaggedObject; public Asn1Encodable Info { get { - if (info is Asn1TaggedObject o) - { - switch (o.TagNo) + if (!(m_info is Asn1TaggedObject tagged)) + return KeyTransRecipientInfo.GetInstance(m_info); + + if (tagged.HasContextTag()) + { + switch (tagged.TagNo) { case 1: - return KeyAgreeRecipientInfo.GetInstance(o, false); + return KeyAgreeRecipientInfo.GetInstance(tagged, false); case 2: - return GetKekInfo(o); + return GetKekInfo(tagged); case 3: - return PasswordRecipientInfo.GetInstance(o, false); + return PasswordRecipientInfo.GetInstance(tagged, false); case 4: - return OtherRecipientInfo.GetInstance(o, false); - default: - throw new InvalidOperationException("unknown tag"); + return OtherRecipientInfo.GetInstance(tagged, false); } - } - - return KeyTransRecipientInfo.GetInstance(info); + } + throw new InvalidOperationException("unknown tag"); } } - private KekRecipientInfo GetKekInfo( - Asn1TaggedObject o) - { - // For compatibility with erroneous version, we don't always pass 'false' here - return KekRecipientInfo.GetInstance(o, o.IsExplicit()); - } + private KekRecipientInfo GetKekInfo(Asn1TaggedObject tagged) + { + // For compatibility with erroneous version, we don't always pass 'false' here + bool declaredExplicit = tagged.IsExplicit(); + + return KekRecipientInfo.GetInstance(tagged, declaredExplicit); + } - /** + /** * Produce an object suitable for an Asn1OutputStream. *
          * RecipientInfo ::= CHOICE {
@@ -140,9 +133,30 @@ namespace Org.BouncyCastle.Asn1.Cms
          *     ori [4] OtherRecipientInfo }
          * 
*/ - public override Asn1Object ToAsn1Object() + public override Asn1Object ToAsn1Object() => m_info.ToAsn1Object(); + + internal bool IsKeyTransV0() + { + if (m_info is Asn1TaggedObject) + return false; + + var ktri = KeyTransRecipientInfo.GetInstance(m_info); + + return ktri.Version.HasValue(0); + } + + internal bool IsPasswordOrOther() { - return info.ToAsn1Object(); + if (m_info is Asn1TaggedObject tagged && tagged.HasContextTag()) + { + switch (tagged.TagNo) + { + case 3: + case 4: + return true; + } + } + return false; } } } diff --git a/crypto/src/asn1/cms/RecipientKeyIdentifier.cs b/crypto/src/asn1/cms/RecipientKeyIdentifier.cs index daae426d2..8bb82f924 100644 --- a/crypto/src/asn1/cms/RecipientKeyIdentifier.cs +++ b/crypto/src/asn1/cms/RecipientKeyIdentifier.cs @@ -25,78 +25,50 @@ namespace Org.BouncyCastle.Asn1.Cms #pragma warning restore CS0618 // Type or member is obsolete } - private Asn1OctetString subjectKeyIdentifier; - private Asn1GeneralizedTime date; - private OtherKeyAttribute other; + private readonly Asn1OctetString m_subjectKeyIdentifier; + private readonly Asn1GeneralizedTime m_date; + private readonly OtherKeyAttribute m_other; - public RecipientKeyIdentifier( - Asn1OctetString subjectKeyIdentifier, - Asn1GeneralizedTime date, - OtherKeyAttribute other) + public RecipientKeyIdentifier(Asn1OctetString subjectKeyIdentifier, Asn1GeneralizedTime date, + OtherKeyAttribute other) { - this.subjectKeyIdentifier = subjectKeyIdentifier; - this.date = date; - this.other = other; + m_subjectKeyIdentifier = subjectKeyIdentifier ?? throw new ArgumentNullException(nameof(subjectKeyIdentifier)); + m_date = date; + m_other = other; } - - public RecipientKeyIdentifier( - byte[] subjectKeyIdentifier) + + public RecipientKeyIdentifier(byte[] subjectKeyIdentifier) : this(subjectKeyIdentifier, null, null) { } - public RecipientKeyIdentifier( - byte[] subjectKeyIdentifier, - Asn1GeneralizedTime date, - OtherKeyAttribute other) + public RecipientKeyIdentifier(byte[] subjectKeyIdentifier, Asn1GeneralizedTime date, OtherKeyAttribute other) { - this.subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier); - this.date = date; - this.other = other; + m_subjectKeyIdentifier = new DerOctetString(subjectKeyIdentifier); + m_date = date; + m_other = other; } [Obsolete("Use 'GetInstance' instead")] public RecipientKeyIdentifier(Asn1Sequence seq) { - subjectKeyIdentifier = Asn1OctetString.GetInstance(seq[0]); + int count = seq.Count, pos = 0; + if (count < 1 || count > 3) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_subjectKeyIdentifier = Asn1OctetString.GetInstance(seq[pos++]); + m_date = Asn1Utilities.ReadOptional(seq, ref pos, Asn1GeneralizedTime.GetOptional); + m_other = Asn1Utilities.ReadOptional(seq, ref pos, OtherKeyAttribute.GetOptional); - switch(seq.Count) - { - case 1: - break; - case 2: - if (seq[1] is Asn1GeneralizedTime asn1GeneralizedTime) - { - date = asn1GeneralizedTime; - } - else - { - other = OtherKeyAttribute.GetInstance(seq[2]); - } - break; - case 3: - date = (Asn1GeneralizedTime)seq[1]; - other = OtherKeyAttribute.GetInstance(seq[2]); - break; - default: - throw new ArgumentException("Invalid RecipientKeyIdentifier"); - } + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public Asn1OctetString SubjectKeyIdentifier - { - get { return subjectKeyIdentifier; } - } + public Asn1OctetString SubjectKeyIdentifier => m_subjectKeyIdentifier; - public Asn1GeneralizedTime Date - { - get { return date; } - } + public Asn1GeneralizedTime Date => m_date; - public OtherKeyAttribute OtherKeyAttribute - { - get { return other; } - } + public OtherKeyAttribute OtherKeyAttribute => m_other; /** * Produce an object suitable for an Asn1OutputStream. @@ -112,8 +84,9 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(subjectKeyIdentifier); - v.AddOptional(date, other); + Asn1EncodableVector v = new Asn1EncodableVector(3); + v.Add(m_subjectKeyIdentifier); + v.AddOptional(m_date, m_other); return new DerSequence(v); } } diff --git a/crypto/src/asn1/cms/SCVPReqRes.cs b/crypto/src/asn1/cms/SCVPReqRes.cs index ec36ff9fa..11df63ea9 100644 --- a/crypto/src/asn1/cms/SCVPReqRes.cs +++ b/crypto/src/asn1/cms/SCVPReqRes.cs @@ -1,4 +1,6 @@ -namespace Org.BouncyCastle.Asn1.Cms +using System; + +namespace Org.BouncyCastle.Asn1.Cms { public class ScvpReqRes : Asn1Encodable @@ -17,21 +19,20 @@ return new ScvpReqRes(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private readonly ContentInfo request; - private readonly ContentInfo response; + private readonly ContentInfo m_request; + private readonly ContentInfo m_response; private ScvpReqRes(Asn1Sequence seq) { - if (seq[0] is Asn1TaggedObject taggedObject) - { - this.request = ContentInfo.GetInstance(taggedObject, true); - this.response = ContentInfo.GetInstance(seq[1]); - } - else - { - this.request = null; - this.response = ContentInfo.GetInstance(seq[0]); - } + int count = seq.Count, pos = 0; + if (count < 1 || count > 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_request = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, true, ContentInfo.GetInstance); + m_response = ContentInfo.GetInstance(seq[pos++]); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } public ScvpReqRes(ContentInfo response) @@ -41,19 +42,13 @@ public ScvpReqRes(ContentInfo request, ContentInfo response) { - this.request = request; - this.response = response; + m_request = request; + m_response = response ?? throw new ArgumentNullException(nameof(response)); } - public virtual ContentInfo Request - { - get { return request; } - } + public virtual ContentInfo Request => m_request; - public virtual ContentInfo Response - { - get { return response; } - } + public virtual ContentInfo Response => m_response; /** *
@@ -65,10 +60,10 @@
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(2);
-            v.AddOptionalTagged(true, 0, request);
-            v.Add(response);
-            return new DerSequence(v);
+            if (m_request == null)
+                return new DerSequence(m_response);
+
+            return new DerSequence(new DerTaggedObject(true, 0, m_request), m_response);
         }
     }
 }
diff --git a/crypto/src/asn1/cms/SignedData.cs b/crypto/src/asn1/cms/SignedData.cs
index 380305c32..4ceb0155b 100644
--- a/crypto/src/asn1/cms/SignedData.cs
+++ b/crypto/src/asn1/cms/SignedData.cs
@@ -22,213 +22,56 @@ namespace Org.BouncyCastle.Asn1.Cms
             return new SignedData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit));
         }
 
-        private static readonly DerInteger Version1 = DerInteger.One;
-        private static readonly DerInteger Version3 = DerInteger.Three;
-        private static readonly DerInteger Version4 = DerInteger.Four;
-        private static readonly DerInteger Version5 = DerInteger.Five;
-
-        private readonly DerInteger		version;
-        private readonly Asn1Set		digestAlgorithms;
-        private readonly ContentInfo	contentInfo;
-        private readonly Asn1Set		certificates;
-        private readonly Asn1Set		crls;
-        private readonly Asn1Set		signerInfos;
-        private readonly bool			certsBer;
-        private readonly bool		    crlsBer;
-
-        public SignedData(
-            Asn1Set     digestAlgorithms,
-            ContentInfo contentInfo,
-            Asn1Set     certificates,
-            Asn1Set     crls,
-            Asn1Set     signerInfos)
+        private readonly DerInteger m_version;
+        private readonly Asn1Set m_digestAlgorithms;
+        private readonly ContentInfo m_contentInfo;
+        private readonly Asn1Set m_certificates;
+        private readonly Asn1Set m_crls;
+        private readonly Asn1Set m_signerInfos;
+        private readonly bool m_certsBer;
+        private readonly bool m_crlsBer;
+
+        public SignedData(Asn1Set digestAlgorithms, ContentInfo contentInfo, Asn1Set certificates, Asn1Set crls,
+            Asn1Set signerInfos)
         {
-            this.version = CalculateVersion(contentInfo.ContentType, certificates, crls, signerInfos);
-            this.digestAlgorithms = digestAlgorithms;
-            this.contentInfo = contentInfo;
-            this.certificates = certificates;
-            this.crls = crls;
-            this.signerInfos = signerInfos;
-            this.crlsBer = crls is BerSet;
-            this.certsBer = certificates is BerSet;
-        }
-
-        // 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
-        //
-        private DerInteger CalculateVersion(
-            DerObjectIdentifier	contentOid,
-            Asn1Set				certs,
-            Asn1Set				crls,
-            Asn1Set				signerInfs)
-        {
-            bool otherCert = false;
-            bool otherCrl = false;
-            bool attrCertV1Found = false;
-            bool attrCertV2Found = false;
-
-            if (certs != null)
-            {
-                foreach (object obj in certs)
-                {
-                    if (obj is Asn1TaggedObject tagged)
-                    {
-                        if (tagged.TagNo == 1)
-                        {
-                            attrCertV1Found = true;
-                        }
-                        else if (tagged.TagNo == 2)
-                        {
-                            attrCertV2Found = true;
-                        }
-                        else if (tagged.TagNo == 3)
-                        {
-                            otherCert = true;
-                            break;
-                        }
-                    }
-                }
-            }
-
-            if (otherCert)
-            {
-                return Version5;
-            }
-
-            if (crls != null)
-            {
-                foreach (object obj in crls)
-                {
-                    if (obj is Asn1TaggedObject)
-                    {
-                        otherCrl = true;
-                        break;
-                    }
-                }
-            }
-
-            if (otherCrl)
-            {
-                return Version5;
-            }
-
-            if (attrCertV2Found)
-            {
-                return Version4;
-            }
-
-            if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
-            {
-                return Version3;
-            }
-
-            return Version1;
-        }
-
-        private bool CheckForVersion3(Asn1Set signerInfs)
-        {
-            foreach (object obj in signerInfs)
-            {
-                SignerInfo s = SignerInfo.GetInstance(obj);
-
-                if (s.Version.HasValue(3))
-                {
-                    return true;
-                }
-            }
-
-            return false;
+            m_digestAlgorithms = digestAlgorithms ?? throw new ArgumentNullException(nameof(digestAlgorithms));
+            m_contentInfo = contentInfo ?? throw new ArgumentNullException(nameof(contentInfo));
+            m_certificates = certificates;
+            m_crls = crls;
+            m_signerInfos = signerInfos ?? throw new ArgumentNullException(nameof(signerInfos));
+            m_crlsBer = crls is BerSet;
+            m_certsBer = certificates is BerSet;
+            m_version = CalculateVersionField(contentInfo.ContentType, certificates, crls, signerInfos);
         }
 
         private SignedData(Asn1Sequence seq)
         {
-            var e = seq.GetEnumerator();
-
-            e.MoveNext();
-            version = (DerInteger)e.Current;
-
-            e.MoveNext();
-            digestAlgorithms = (Asn1Set)e.Current.ToAsn1Object();
-
-            e.MoveNext();
-            contentInfo = ContentInfo.GetInstance(e.Current.ToAsn1Object());
-
-            while (e.MoveNext())
-            {
-                Asn1Object o = e.Current.ToAsn1Object();
-
-                //
-                // an interesting feature of SignedData is that there appear
-                // to be varying implementations...
-                // for the moment we ignore anything which doesn't fit.
-                //
-                if (o is Asn1TaggedObject tagged)
-                {
-                    switch (tagged.TagNo)
-                    {
-                    case 0:
-                        certsBer = tagged is BerTaggedObject;
-                        certificates = Asn1Set.GetInstance(tagged, false);
-                        break;
-                    case 1:
-                        crlsBer = tagged is BerTaggedObject;
-                        crls = Asn1Set.GetInstance(tagged, false);
-                        break;
-                    default:
-                        throw new ArgumentException("unknown tag value " + tagged.TagNo);
-                    }
-                }
-                else
-                {
-                    signerInfos = (Asn1Set) o;
-                }
-            }
+            int count = seq.Count, pos = 0;
+            if (count < 4 || count > 6)
+                throw new ArgumentException("Bad sequence size: " + count, nameof(seq));
+
+            m_version = DerInteger.GetInstance(seq[pos++]);
+            m_digestAlgorithms = Asn1Set.GetInstance(seq[pos++]);
+            m_contentInfo = ContentInfo.GetInstance(seq[pos++]);
+            m_certificates = ReadOptionalTaggedSet(seq, ref pos, 0, out m_certsBer);
+            m_crls = ReadOptionalTaggedSet(seq, ref pos, 1, out m_crlsBer);
+            m_signerInfos = Asn1Set.GetInstance(seq[pos++]);
+
+            if (pos != count)
+                throw new ArgumentException("Unexpected elements in sequence", nameof(seq));
         }
 
-        public DerInteger Version
-        {
-            get { return version; }
-        }
+        public DerInteger Version => m_version;
 
-        public Asn1Set DigestAlgorithms
-        {
-            get { return digestAlgorithms; }
-        }
+        public Asn1Set DigestAlgorithms => m_digestAlgorithms;
 
-        public ContentInfo EncapContentInfo
-        {
-            get { return contentInfo; }
-        }
+        public ContentInfo EncapContentInfo => m_contentInfo;
 
-        public Asn1Set Certificates
-        {
-            get { return certificates; }
-        }
+        public Asn1Set Certificates => m_certificates;
 
-        public Asn1Set CRLs
-        {
-            get { return crls; }
-        }
+        public Asn1Set CRLs => m_crls;
 
-        public Asn1Set SignerInfos
-        {
-            get { return signerInfos; }
-        }
+        public Asn1Set SignerInfos => m_signerInfos;
 
         /**
          * Produce an object suitable for an Asn1OutputStream.
@@ -245,36 +88,135 @@ namespace Org.BouncyCastle.Asn1.Cms
          */
         public override Asn1Object ToAsn1Object()
         {
-            Asn1EncodableVector v = new Asn1EncodableVector(
-                version, digestAlgorithms, contentInfo);
+            Asn1EncodableVector v = new Asn1EncodableVector(6);
+            v.Add(m_version, m_digestAlgorithms, m_contentInfo);
 
-            if (certificates != null)
+            if (m_certificates != null)
             {
-                if (certsBer)
+                if (m_certsBer)
                 {
-                    v.Add(new BerTaggedObject(false, 0, certificates));
+                    v.Add(new BerTaggedObject(false, 0, m_certificates));
                 }
                 else
                 {
-                    v.Add(new DerTaggedObject(false, 0, certificates));
+                    v.Add(new DerTaggedObject(false, 0, m_certificates));
                 }
             }
 
-            if (crls != null)
+            if (m_crls != null)
             {
-                if (crlsBer)
+                if (m_crlsBer)
                 {
-                    v.Add(new BerTaggedObject(false, 1, crls));
+                    v.Add(new BerTaggedObject(false, 1, m_crls));
                 }
                 else
                 {
-                    v.Add(new DerTaggedObject(false, 1, crls));
+                    v.Add(new DerTaggedObject(false, 1, m_crls));
                 }
             }
 
-            v.Add(signerInfos);
+            v.Add(m_signerInfos);
 
             return new BerSequence(v);
         }
+
+        private static DerInteger CalculateVersionField(DerObjectIdentifier contentOid, Asn1Set certs, Asn1Set crls,
+            Asn1Set signerInfs)
+        {
+            /*
+             * 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 (crls != null)
+            {
+                foreach (var element in crls)
+                {
+                    var tagged = Asn1TaggedObject.GetOptional(element);
+                    if (tagged != null)
+                    {
+                        // RevocationInfoChoice.other
+                        if (tagged.HasContextTag(1))
+                            return DerInteger.Five;
+                    }
+                }
+            }
+
+            bool anyV1AttrCerts = false;
+
+            if (certs != null)
+            {
+                bool anyV2AttrCerts = false;
+
+                foreach (var element in certs)
+                {
+                    var tagged = Asn1TaggedObject.GetOptional(element);
+                    if (tagged != null)
+                    {
+                        // CertificateChoices.other
+                        if (tagged.HasContextTag(3))
+                            return DerInteger.Five;
+
+                        // CertificateChoices.v2AttrCert
+                        anyV2AttrCerts = anyV2AttrCerts || tagged.HasContextTag(2);
+
+                        // CertificateChoices.v1AttrCert
+                        anyV1AttrCerts = anyV1AttrCerts || tagged.HasContextTag(1);
+                    }
+                }
+
+                if (anyV2AttrCerts)
+                    return DerInteger.Four;
+            }
+
+            if (anyV1AttrCerts || !CmsObjectIdentifiers.Data.Equals(contentOid) || HasV3SignerInfos(signerInfs))
+                return DerInteger.Three;
+
+            return DerInteger.One;
+        }
+
+        // (any SignerInfo structures are version 3)
+        private static bool HasV3SignerInfos(Asn1Set signerInfs)
+        {
+            foreach (object obj in signerInfs)
+            {
+                var signerInfo = SignerInfo.GetInstance(obj);
+                if (signerInfo.Version.HasValue(3))
+                    return true;
+            }
+            return false;
+        }
+
+        private static Asn1Set ReadOptionalTaggedSet(Asn1Sequence sequence, ref int sequencePosition, int tagNo,
+            out bool isBer)
+        {
+            if (sequencePosition < sequence.Count &&
+                sequence[sequencePosition] is Asn1TaggedObject taggedObject &&
+                taggedObject.HasContextTag(tagNo))
+            {
+                var result = Asn1Set.GetInstance(taggedObject, false);
+                sequencePosition++;
+                isBer = taggedObject is BerTaggedObject;
+                return result;
+            }
+
+            isBer = default;
+            return null;
+        }
     }
 }
diff --git a/crypto/src/asn1/cms/SignerIdentifier.cs b/crypto/src/asn1/cms/SignerIdentifier.cs
index 17f3f08c2..055a393df 100644
--- a/crypto/src/asn1/cms/SignerIdentifier.cs
+++ b/crypto/src/asn1/cms/SignerIdentifier.cs
@@ -32,39 +32,33 @@ namespace Org.BouncyCastle.Asn1.Cms
             return Asn1Utilities.GetInstanceFromChoice(taggedObject, declaredExplicit, GetInstance);
         }
 
-        private Asn1Encodable id;
+        private readonly Asn1Encodable m_id;
 
-		public SignerIdentifier(
-            IssuerAndSerialNumber id)
+        public SignerIdentifier(IssuerAndSerialNumber id)
         {
-            this.id = id;
+            m_id = id ?? throw new ArgumentNullException(nameof(id));
         }
 
-		public SignerIdentifier(
-            Asn1OctetString id)
+		public SignerIdentifier(Asn1OctetString id)
         {
-            this.id = new DerTaggedObject(false, 0, id);
+            m_id = new DerTaggedObject(false, 0, id);
         }
 
-		public SignerIdentifier(
-            Asn1Object id)
+		public SignerIdentifier(Asn1Object id)
         {
-            this.id = id;
+            m_id = id ?? throw new ArgumentNullException(nameof(id));
         }
 
-		public bool IsTagged
-		{
-			get { return (id is Asn1TaggedObject); }
-		}
+        public bool IsTagged => m_id is Asn1TaggedObject;
 
         public Asn1Encodable ID
         {
             get
             {
-                if (id is Asn1TaggedObject taggedObject)
+                if (m_id is Asn1TaggedObject taggedObject)
                     return Asn1OctetString.GetInstance(taggedObject, false);
 
-                return id;
+                return m_id;
             }
         }
 
@@ -79,9 +73,6 @@ namespace Org.BouncyCastle.Asn1.Cms
          * SubjectKeyIdentifier ::= OCTET STRING
          * 
*/ - public override Asn1Object ToAsn1Object() - { - return id.ToAsn1Object(); - } + public override Asn1Object ToAsn1Object() => m_id.ToAsn1Object(); } } diff --git a/crypto/src/asn1/cms/SignerInfo.cs b/crypto/src/asn1/cms/SignerInfo.cs index bce33e699..fbd4bcca7 100644 --- a/crypto/src/asn1/cms/SignerInfo.cs +++ b/crypto/src/asn1/cms/SignerInfo.cs @@ -1,3 +1,5 @@ +using System; + using Org.BouncyCastle.Asn1.X509; namespace Org.BouncyCastle.Asn1.Cms @@ -19,124 +21,66 @@ namespace Org.BouncyCastle.Asn1.Cms return new SignerInfo(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private DerInteger version; - private SignerIdentifier sid; - private AlgorithmIdentifier digAlgorithm; - private Asn1Set authenticatedAttributes; - private AlgorithmIdentifier digEncryptionAlgorithm; - private Asn1OctetString encryptedDigest; - private Asn1Set unauthenticatedAttributes; - - public SignerInfo( - SignerIdentifier sid, - AlgorithmIdentifier digAlgorithm, - Asn1Set authenticatedAttributes, - AlgorithmIdentifier digEncryptionAlgorithm, - Asn1OctetString encryptedDigest, - Asn1Set unauthenticatedAttributes) + private readonly DerInteger m_version; + private readonly SignerIdentifier m_sid; + private readonly AlgorithmIdentifier m_digAlgorithm; + private readonly Asn1Set m_authenticatedAttributes; + private readonly AlgorithmIdentifier m_digEncryptionAlgorithm; + private readonly Asn1OctetString m_encryptedDigest; + private readonly Asn1Set m_unauthenticatedAttributes; + + public SignerInfo(SignerIdentifier sid, AlgorithmIdentifier digAlgorithm, Attributes authenticatedAttributes, + AlgorithmIdentifier digEncryptionAlgorithm, Asn1OctetString encryptedDigest, + Attributes unauthenticatedAttributes) + : this(sid, digAlgorithm, Asn1Set.GetInstance(authenticatedAttributes), digEncryptionAlgorithm, + encryptedDigest, Asn1Set.GetInstance(unauthenticatedAttributes)) { - this.version = new DerInteger(sid.IsTagged ? 3 : 1); - this.sid = sid; - this.digAlgorithm = digAlgorithm; - this.authenticatedAttributes = authenticatedAttributes; - this.digEncryptionAlgorithm = digEncryptionAlgorithm; - this.encryptedDigest = encryptedDigest; - this.unauthenticatedAttributes = unauthenticatedAttributes; } - public SignerInfo( - SignerIdentifier sid, - AlgorithmIdentifier digAlgorithm, - Attributes authenticatedAttributes, - AlgorithmIdentifier digEncryptionAlgorithm, - Asn1OctetString encryptedDigest, - Attributes unauthenticatedAttributes) + public SignerInfo(SignerIdentifier sid, AlgorithmIdentifier digAlgorithm, Asn1Set authenticatedAttributes, + AlgorithmIdentifier digEncryptionAlgorithm, Asn1OctetString encryptedDigest, + Asn1Set unauthenticatedAttributes) { - this.version = new DerInteger(sid.IsTagged ? 3 : 1); - this.sid = sid; - this.digAlgorithm = digAlgorithm; - this.authenticatedAttributes = Asn1Set.GetInstance(authenticatedAttributes); - this.digEncryptionAlgorithm = digEncryptionAlgorithm; - this.encryptedDigest = encryptedDigest; - this.unauthenticatedAttributes = Asn1Set.GetInstance(unauthenticatedAttributes); + m_sid = sid ?? throw new ArgumentNullException(nameof(sid)); + m_digAlgorithm = digAlgorithm ?? throw new ArgumentNullException(nameof(digAlgorithm)); + m_authenticatedAttributes = authenticatedAttributes; + m_digEncryptionAlgorithm = digEncryptionAlgorithm ?? throw new ArgumentNullException(nameof(digEncryptionAlgorithm)); + m_encryptedDigest = encryptedDigest ?? throw new ArgumentNullException(nameof(encryptedDigest)); + m_unauthenticatedAttributes = unauthenticatedAttributes; + m_version = sid.IsTagged ? DerInteger.Three : DerInteger.One; } private SignerInfo(Asn1Sequence seq) { - var e = seq.GetEnumerator(); - - e.MoveNext(); - version = (DerInteger)e.Current; - - e.MoveNext(); - sid = SignerIdentifier.GetInstance(e.Current.ToAsn1Object()); - - e.MoveNext(); - digAlgorithm = AlgorithmIdentifier.GetInstance(e.Current.ToAsn1Object()); - - e.MoveNext(); - var obj = e.Current.ToAsn1Object(); - - if (obj is Asn1TaggedObject tagged) - { - authenticatedAttributes = Asn1Set.GetInstance(tagged, false); - - e.MoveNext(); - digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(e.Current.ToAsn1Object()); - } - else - { - authenticatedAttributes = null; - digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(obj); - } - - e.MoveNext(); - encryptedDigest = Asn1OctetString.GetInstance(e.Current.ToAsn1Object()); - - if (e.MoveNext()) - { - unauthenticatedAttributes = Asn1Set.GetInstance((Asn1TaggedObject)e.Current.ToAsn1Object(), false); - } - else - { - unauthenticatedAttributes = null; - } + int count = seq.Count, pos = 0; + if (count < 5 || count > 7) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); + + m_version = DerInteger.GetInstance(seq[pos++]); + m_sid = SignerIdentifier.GetInstance(seq[pos++]); + m_digAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_authenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 0, false, Asn1Set.GetInstance); + m_digEncryptionAlgorithm = AlgorithmIdentifier.GetInstance(seq[pos++]); + m_encryptedDigest = Asn1OctetString.GetInstance(seq[pos++]); + m_unauthenticatedAttributes = Asn1Utilities.ReadOptionalContextTagged(seq, ref pos, 1, false, Asn1Set.GetInstance); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } - public DerInteger Version - { - get { return version; } - } + public DerInteger Version => m_version; - public SignerIdentifier SignerID - { - get { return sid; } - } + public SignerIdentifier SignerID => m_sid; - public Asn1Set AuthenticatedAttributes - { - get { return authenticatedAttributes; } - } + public Asn1Set AuthenticatedAttributes => m_authenticatedAttributes; - public AlgorithmIdentifier DigestAlgorithm - { - get { return digAlgorithm; } - } + public AlgorithmIdentifier DigestAlgorithm => m_digAlgorithm; - public Asn1OctetString EncryptedDigest - { - get { return encryptedDigest; } - } + public Asn1OctetString EncryptedDigest => m_encryptedDigest; - public AlgorithmIdentifier DigestEncryptionAlgorithm - { - get { return digEncryptionAlgorithm; } - } + public AlgorithmIdentifier DigestEncryptionAlgorithm => m_digEncryptionAlgorithm; - public Asn1Set UnauthenticatedAttributes - { - get { return unauthenticatedAttributes; } - } + public Asn1Set UnauthenticatedAttributes => m_unauthenticatedAttributes; /** * Produce an object suitable for an Asn1OutputStream. @@ -160,10 +104,11 @@ namespace Org.BouncyCastle.Asn1.Cms */ public override Asn1Object ToAsn1Object() { - Asn1EncodableVector v = new Asn1EncodableVector(version, sid, digAlgorithm); - v.AddOptionalTagged(false, 0, authenticatedAttributes); - v.Add(digEncryptionAlgorithm, encryptedDigest); - v.AddOptionalTagged(false, 1, unauthenticatedAttributes); + Asn1EncodableVector v = new Asn1EncodableVector(7); + v.Add(m_version, m_sid, m_digAlgorithm); + v.AddOptionalTagged(false, 0, m_authenticatedAttributes); + v.Add(m_digEncryptionAlgorithm, m_encryptedDigest); + v.AddOptionalTagged(false, 1, m_unauthenticatedAttributes); return new DerSequence(v); } } diff --git a/crypto/src/asn1/cms/TimeStampAndCRL.cs b/crypto/src/asn1/cms/TimeStampAndCRL.cs index c0cd48905..a76ce7680 100644 --- a/crypto/src/asn1/cms/TimeStampAndCRL.cs +++ b/crypto/src/asn1/cms/TimeStampAndCRL.cs @@ -1,3 +1,7 @@ +using System; + +using Org.BouncyCastle.Asn1.X509; + namespace Org.BouncyCastle.Asn1.Cms { public class TimeStampAndCrl @@ -17,33 +21,37 @@ namespace Org.BouncyCastle.Asn1.Cms return new TimeStampAndCrl(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private ContentInfo timeStamp; - private X509.CertificateList crl; + private readonly ContentInfo m_timeStamp; + private readonly CertificateList m_crl; public TimeStampAndCrl(ContentInfo timeStamp) + : this(timeStamp, null) { - this.timeStamp = timeStamp; } - private TimeStampAndCrl(Asn1Sequence seq) - { - this.timeStamp = ContentInfo.GetInstance(seq[0]); - if (seq.Count == 2) - { - this.crl = X509.CertificateList.GetInstance(seq[1]); - } - } + public TimeStampAndCrl(ContentInfo timeStamp, CertificateList crl) + { + m_timeStamp = timeStamp ?? throw new ArgumentNullException(nameof(timeStamp)); + m_crl = crl; + } - public virtual ContentInfo TimeStampToken + private TimeStampAndCrl(Asn1Sequence seq) { - get { return this.timeStamp; } - } + int count = seq.Count, pos = 0; + if (count < 1 || count > 2) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - public virtual X509.CertificateList Crl - { - get { return this.crl; } + m_timeStamp = ContentInfo.GetInstance(seq[pos++]); + m_crl = Asn1Utilities.ReadOptional(seq, ref pos, CertificateList.GetOptional); + + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); } + public virtual ContentInfo TimeStampToken => m_timeStamp; + + public virtual CertificateList Crl => m_crl; + /** *
 		 * TimeStampAndCRL ::= SEQUENCE {
@@ -55,9 +63,9 @@ namespace Org.BouncyCastle.Asn1.Cms
 		 */
 		public override Asn1Object ToAsn1Object()
 		{
-			Asn1EncodableVector v = new Asn1EncodableVector(timeStamp);
-			v.AddOptional(crl);
-			return new DerSequence(v);
+			return m_crl == null
+				?  new DerSequence(m_timeStamp)
+                :  new DerSequence(m_timeStamp, m_crl);
 		}
 	}
 }
diff --git a/crypto/src/asn1/cms/TimeStampTokenEvidence.cs b/crypto/src/asn1/cms/TimeStampTokenEvidence.cs
index 6ac1eb11d..f7c5298a7 100644
--- a/crypto/src/asn1/cms/TimeStampTokenEvidence.cs
+++ b/crypto/src/asn1/cms/TimeStampTokenEvidence.cs
@@ -1,3 +1,7 @@
+using System;
+
+using Org.BouncyCastle.Utilities;
+
 namespace Org.BouncyCastle.Asn1.Cms
 {
     public class TimeStampTokenEvidence
@@ -17,34 +21,27 @@ namespace Org.BouncyCastle.Asn1.Cms
             return new TimeStampTokenEvidence(Asn1Sequence.GetInstance(tagged, isExplicit));
         }
 
-        private TimeStampAndCrl[] timeStampAndCrls;
+        private readonly TimeStampAndCrl[] m_timeStampAndCrls;
 
 		public TimeStampTokenEvidence(TimeStampAndCrl[] timeStampAndCrls)
 		{
-			this.timeStampAndCrls = timeStampAndCrls;
+			if (Arrays.IsNullOrContainsNull(timeStampAndCrls))
+                throw new NullReferenceException("'timeStampAndCrls' cannot be null, or contain null");
+
+            m_timeStampAndCrls = timeStampAndCrls;
 		}
 
 		public TimeStampTokenEvidence(TimeStampAndCrl timeStampAndCrl)
 		{
-			this.timeStampAndCrls = new TimeStampAndCrl[]{ timeStampAndCrl };
+			m_timeStampAndCrls = new []{ timeStampAndCrl ?? throw new ArgumentNullException(nameof(timeStampAndCrl)) };
 		}
 
 		private TimeStampTokenEvidence(Asn1Sequence seq)
 		{
-			this.timeStampAndCrls = new TimeStampAndCrl[seq.Count];
-
-			int count = 0;
-
-			foreach (Asn1Encodable ae in seq)
-			{
-				this.timeStampAndCrls[count++] = TimeStampAndCrl.GetInstance(ae.ToAsn1Object());
-			}
+			m_timeStampAndCrls = seq.MapElements(TimeStampAndCrl.GetInstance);
 		}
 
-        public virtual TimeStampAndCrl[] ToTimeStampAndCrlArray()
-		{
-			return (TimeStampAndCrl[])timeStampAndCrls.Clone();
-		}
+        public virtual TimeStampAndCrl[] ToTimeStampAndCrlArray() => (TimeStampAndCrl[])m_timeStampAndCrls.Clone();
 
 		/**
 		 * 
@@ -53,9 +50,6 @@ namespace Org.BouncyCastle.Asn1.Cms
 		 * 
* @return */ - public override Asn1Object ToAsn1Object() - { - return new DerSequence(timeStampAndCrls); - } + public override Asn1Object ToAsn1Object() => new DerSequence(m_timeStampAndCrls); } } diff --git a/crypto/src/asn1/cms/TimeStampedData.cs b/crypto/src/asn1/cms/TimeStampedData.cs index cae290609..53a8334ec 100644 --- a/crypto/src/asn1/cms/TimeStampedData.cs +++ b/crypto/src/asn1/cms/TimeStampedData.cs @@ -19,63 +19,45 @@ namespace Org.BouncyCastle.Asn1.Cms return new TimeStampedData(Asn1Sequence.GetInstance(taggedObject, declaredExplicit)); } - private DerInteger version; - private DerIA5String dataUri; - private MetaData metaData; - private Asn1OctetString content; - private Evidence temporalEvidence; + private readonly DerInteger m_version; + private readonly DerIA5String m_dataUri; + private readonly MetaData m_metaData; + private readonly Asn1OctetString m_content; + private readonly Evidence m_temporalEvidence; - public TimeStampedData(DerIA5String dataUri, MetaData metaData, Asn1OctetString content, - Evidence temporalEvidence) - { - this.version = DerInteger.One; - this.dataUri = dataUri; - this.metaData = metaData; - this.content = content; - this.temporalEvidence = temporalEvidence; - } + public TimeStampedData(DerIA5String dataUri, MetaData metaData, Asn1OctetString content, + Evidence temporalEvidence) + { + m_version = DerInteger.One; + m_dataUri = dataUri; + m_metaData = metaData; + m_content = content; + m_temporalEvidence = temporalEvidence ?? throw new ArgumentNullException(nameof(temporalEvidence)); + } - private TimeStampedData(Asn1Sequence seq) + private TimeStampedData(Asn1Sequence seq) { - this.version = DerInteger.GetInstance(seq[0]); - - int index = 1; - if (seq[index] is DerIA5String ia5) - { - this.dataUri = ia5; - ++index; - } - if (seq[index] is MetaData || seq[index] is Asn1Sequence) - { - this.metaData = MetaData.GetInstance(seq[index++]); - } - if (seq[index] is Asn1OctetString octets) - { - this.content = octets; - ++index; - } - this.temporalEvidence = Evidence.GetInstance(seq[index]); - } + int count = seq.Count, pos = 0; + if (count < 2 || count > 5) + throw new ArgumentException("Bad sequence size: " + count, nameof(seq)); - public virtual DerIA5String DataUri - { - get { return dataUri; } - } + m_version = DerInteger.GetInstance(seq[pos++]); + m_dataUri = Asn1Utilities.ReadOptional(seq, ref pos, DerIA5String.GetOptional); + m_metaData = Asn1Utilities.ReadOptional(seq, ref pos, MetaData.GetOptional); + m_content = Asn1Utilities.ReadOptional(seq, ref pos, Asn1OctetString.GetOptional); + m_temporalEvidence = Evidence.GetInstance(seq[pos++]); - public MetaData MetaData - { - get { return metaData; } - } + if (pos != count) + throw new ArgumentException("Unexpected elements in sequence", nameof(seq)); + } - public Asn1OctetString Content - { - get { return content; } - } + public virtual DerIA5String DataUri => m_dataUri; - public Evidence TemporalEvidence - { - get { return temporalEvidence; } - } + public MetaData MetaData => m_metaData; + + public Asn1OctetString Content => m_content; + + public Evidence TemporalEvidence => m_temporalEvidence; /** *
@@ -91,9 +73,10 @@ namespace Org.BouncyCastle.Asn1.Cms
 		 */
 		public override Asn1Object ToAsn1Object()
 		{
-			Asn1EncodableVector v = new Asn1EncodableVector(version);
-			v.AddOptional(dataUri, metaData, content);
-			v.Add(temporalEvidence);
+            Asn1EncodableVector v = new Asn1EncodableVector(5);
+            v.Add(m_version);
+			v.AddOptional(m_dataUri, m_metaData, m_content);
+			v.Add(m_temporalEvidence);
 			return new BerSequence(v);
 		}
 	}
diff --git a/crypto/src/asn1/x509/CertificateList.cs b/crypto/src/asn1/x509/CertificateList.cs
index 5d73cf411..ecf22e372 100644
--- a/crypto/src/asn1/x509/CertificateList.cs
+++ b/crypto/src/asn1/x509/CertificateList.cs
@@ -19,24 +19,39 @@ namespace Org.BouncyCastle.Asn1.X509
     public class CertificateList
         : Asn1Encodable
     {
-        private readonly TbsCertificateList	tbsCertList;
-        private readonly AlgorithmIdentifier sigAlgID;
-        private readonly DerBitString sig;
+        public static CertificateList GetInstance(object obj)
+        {
+            if (obj == null)
+                return null;
+            if (obj is CertificateList certificateList)
+                return certificateList;
+            return new CertificateList(Asn1Sequence.GetInstance(obj));
+        }
 
         public static CertificateList GetInstance(Asn1TaggedObject obj, bool explicitly)
         {
             return GetInstance(Asn1Sequence.GetInstance(obj, explicitly));
         }
 
-        public static CertificateList GetInstance(object obj)
+        public static CertificateList GetOptional(Asn1Encodable element)
         {
-            if (obj == null)
-                return null;
-            if (obj is CertificateList certificateList)
+            if (element == null)
+                throw new ArgumentNullException(nameof(element));
+
+            if (element is CertificateList certificateList)
                 return certificateList;
-            return new CertificateList(Asn1Sequence.GetInstance(obj));
+
+            Asn1Sequence asn1Sequence = Asn1Sequence.GetOptional(element);
+            if (asn1Sequence != null)
+                return new CertificateList(asn1Sequence);
+
+            return null;
         }
 
+        private readonly TbsCertificateList tbsCertList;
+        private readonly AlgorithmIdentifier sigAlgID;
+        private readonly DerBitString sig;
+
         private CertificateList(
             Asn1Sequence seq)
         {
-- 
cgit 1.4.1