diff options
Diffstat (limited to '')
42 files changed, 1333 insertions, 1703 deletions
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<TState, TResult>(Asn1Sequence sequence, ref int sequencePosition, + int tagNo, TState state, Func<Asn1TaggedObject, TState, TResult> constructor) + { + return ReadTagged(sequence, ref sequencePosition, Asn1Tags.ContextSpecific, tagNo, state, constructor); + } + + public static TResult ReadTagged<TState, TResult>(Asn1Sequence sequence, ref int sequencePosition, int tagClass, + int tagNo, TState state, Func<Asn1TaggedObject, TState, TResult> constructor) + { + var tagged = Asn1TaggedObject.GetInstance(sequence[sequencePosition++], tagClass, tagNo); + + return constructor(tagged, state); + } + public static TResult ReadOptional<TResult>(Asn1Sequence sequence, ref int sequencePosition, Func<Asn1Encodable, TResult> 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 * } * </pre> */ - 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<DerObjectIdentifier, object>(v.Count); - - foreach (Asn1Encodable e in v) - { - AddAttribute(Attribute.GetInstance(e)); - } + m_attributes = BuildAttributes(v); } public AttributeTable(Asn1Set s) { - m_attributes = new Dictionary<DerObjectIdentifier, object>(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<Attribute> existingList) - { - existingList.Add(a); - return; - } - - if (existingValue is Attribute existingAttr) - { - var newList = new List<Attribute>(); - newList.Add(existingAttr); - newList.Add(a); - m_attributes[oid] = newList; - return; - } - - throw new InvalidOperationException(); - } - /// <summary>Return the first attribute matching the given OBJECT IDENTIFIER</summary> 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<Attribute> existingList) + if (existingValue is List<Attribute> 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<Attribute> existingList) + if (existingValue is List<Attribute> 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<Attribute> existingList) + if (existingValue is List<Attribute> existingList) { total += existingList.Count; } @@ -153,7 +115,7 @@ namespace Org.BouncyCastle.Asn1.Cms foreach (object existingValue in m_attributes.Values) { - if (existingValue is IList<Attribute> existingList) + if (existingValue is List<Attribute> 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<DerObjectIdentifier, object> attributes, Attribute a) + { + DerObjectIdentifier oid = a.AttrType; + + if (!attributes.TryGetValue(oid, out object existingValue)) + { + attributes[oid] = a; + return; + } + + if (existingValue is List<Attribute> existingList) + { + existingList.Add(a); + return; + } + + if (existingValue is Attribute existingAttr) + { + var newList = new List<Attribute>(); + newList.Add(existingAttr); + newList.Add(a); + attributes[oid] = newList; + return; + } + + throw new InvalidOperationException(); + } + + private static Dictionary<DerObjectIdentifier, object> BuildAttributes(IEnumerable<Asn1Encodable> e) + { + var result = new Dictionary<DerObjectIdentifier, object>(); + 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. * <pre> * AuthenticatedData ::= SEQUENCE { @@ -167,55 +108,77 @@ namespace Org.BouncyCastle.Asn1.Cms * MessageAuthenticationCode ::= OCTET STRING * </pre> */ - 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. * <pre> * ContentInfo ::= Sequence { * contentType ContentType, - * content - * [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } + * content [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL } * </pre> */ 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; /** * <pre> @@ -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 * } * </pre> */ - 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 * } * </pre> */ - 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; + + /** * <pre> * MetaData ::= SEQUENCE { * hashProtected BOOLEAN, @@ -69,31 +82,12 @@ namespace Org.BouncyCastle.Asn1.Cms * </pre> * @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 } * </pre> */ - 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 } * </pre> */ - 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 * } * </pre> */ - 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. * <pre> * RecipientInfo ::= CHOICE { @@ -140,9 +133,30 @@ namespace Org.BouncyCastle.Asn1.Cms * ori [4] OtherRecipientInfo } * </pre> */ - 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; /** * <pre> @@ -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 * </pre> */ - 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; + /** * <pre> * 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(); /** * <pre> @@ -53,9 +50,6 @@ namespace Org.BouncyCastle.Asn1.Cms * </pre> * @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; /** * <pre> @@ -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) { |