summary refs log tree commit diff
path: root/Crypto/src/asn1/cms/SignedData.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Crypto/src/asn1/cms/SignedData.cs')
-rw-r--r--Crypto/src/asn1/cms/SignedData.cs282
1 files changed, 282 insertions, 0 deletions
diff --git a/Crypto/src/asn1/cms/SignedData.cs b/Crypto/src/asn1/cms/SignedData.cs
new file mode 100644
index 000000000..40ed09f32
--- /dev/null
+++ b/Crypto/src/asn1/cms/SignedData.cs
@@ -0,0 +1,282 @@
+using System;
+using System.Collections;
+
+using Org.BouncyCastle.Asn1;
+
+namespace Org.BouncyCastle.Asn1.Cms
+{
+    /**
+     * a signed data object.
+     */
+    public class SignedData
+        : Asn1Encodable
+    {
+        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 static SignedData GetInstance(
+            object obj)
+        {
+            if (obj is SignedData)
+                return (SignedData) obj;
+
+			if (obj is Asn1Sequence)
+                return new SignedData((Asn1Sequence) obj);
+
+			throw new ArgumentException("Unknown object in factory: " + obj.GetType().FullName, "obj");
+		}
+
+		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)
+					{
+						Asn1TaggedObject tagged = (Asn1TaggedObject)obj;
+
+						if (tagged.TagNo == 1)
+						{
+							attrCertV1Found = true;
+						}
+						else if (tagged.TagNo == 2)
+						{
+							attrCertV2Found = true;
+						}
+						else if (tagged.TagNo == 3)
+						{
+							otherCert = true;
+							break;
+						}
+					}
+				}
+			}
+
+			if (otherCert)
+			{
+				return new DerInteger(5);
+			}
+
+			if (crls != null)
+			{
+				foreach (object obj in crls)
+				{
+					if (obj is Asn1TaggedObject)
+					{
+						otherCrl = true;
+						break;
+					}
+				}
+			}
+
+			if (otherCrl)
+			{
+				return new DerInteger(5);
+			}
+
+			if (attrCertV2Found)
+			{
+				return new DerInteger(4);
+			}
+
+			if (attrCertV1Found || !CmsObjectIdentifiers.Data.Equals(contentOid) || CheckForVersion3(signerInfs))
+			{
+				return new DerInteger(3);
+			}
+
+            return new DerInteger(1);
+		}
+
+		private bool CheckForVersion3(
+			Asn1Set signerInfs)
+		{
+			foreach (object obj in signerInfs)
+			{
+				SignerInfo s = SignerInfo.GetInstance(obj);
+
+				if (s.Version.Value.IntValue == 3)
+				{
+					return true;
+				}
+			}
+
+			return false;
+		}
+
+		private SignedData(
+            Asn1Sequence seq)
+        {
+            IEnumerator e = seq.GetEnumerator();
+
+			e.MoveNext();
+            version = (DerInteger)e.Current;
+
+			e.MoveNext();
+            digestAlgorithms = ((Asn1Set)e.Current);
+
+			e.MoveNext();
+            contentInfo = ContentInfo.GetInstance(e.Current);
+
+			while (e.MoveNext())
+            {
+                Asn1Object o = (Asn1Object)e.Current;
+
+				//
+                // 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)
+                {
+                    Asn1TaggedObject tagged = (Asn1TaggedObject)o;
+
+                    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;
+                }
+            }
+        }
+
+		public DerInteger Version
+		{
+			get { return version; }
+		}
+
+		public Asn1Set DigestAlgorithms
+		{
+			get { return digestAlgorithms; }
+		}
+
+		public ContentInfo EncapContentInfo
+		{
+			get { return contentInfo; }
+		}
+
+		public Asn1Set Certificates
+		{
+			get { return certificates; }
+		}
+
+		public Asn1Set CRLs
+		{
+			get { return crls; }
+		}
+
+		public Asn1Set SignerInfos
+		{
+			get { return signerInfos; }
+		}
+
+		/**
+         * Produce an object suitable for an Asn1OutputStream.
+         * <pre>
+         * SignedData ::= Sequence {
+         *     version CMSVersion,
+         *     digestAlgorithms DigestAlgorithmIdentifiers,
+         *     encapContentInfo EncapsulatedContentInfo,
+         *     certificates [0] IMPLICIT CertificateSet OPTIONAL,
+         *     crls [1] IMPLICIT CertificateRevocationLists OPTIONAL,
+         *     signerInfos SignerInfos
+         *   }
+         * </pre>
+         */
+        public override Asn1Object ToAsn1Object()
+        {
+            Asn1EncodableVector v = new Asn1EncodableVector(
+				version, digestAlgorithms, contentInfo);
+
+			if (certificates != null)
+            {
+                if (certsBer)
+                {
+                    v.Add(new BerTaggedObject(false, 0, certificates));
+                }
+                else
+                {
+                    v.Add(new DerTaggedObject(false, 0, certificates));
+                }
+            }
+
+			if (crls != null)
+            {
+                if (crlsBer)
+                {
+                    v.Add(new BerTaggedObject(false, 1, crls));
+                }
+                else
+                {
+                    v.Add(new DerTaggedObject(false, 1, crls));
+                }
+            }
+
+			v.Add(signerInfos);
+
+			return new BerSequence(v);
+        }
+    }
+}