diff options
Diffstat (limited to 'crypto/src/asn1/cms/EnvelopedData.cs')
-rw-r--r-- | crypto/src/asn1/cms/EnvelopedData.cs | 201 |
1 files changed, 122 insertions, 79 deletions
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; } } } |