summary refs log tree commit diff
path: root/crypto/src/asn1/DerApplicationSpecific.cs
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-11-12 01:54:30 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-11-12 01:54:30 +0700
commit8c32dba3fc4f2033e7597ee1999e793cf6552584 (patch)
treec48d45537cfbea6f7e0ab92de4793a2b35204573 /crypto/src/asn1/DerApplicationSpecific.cs
parentAdd new Equals method (diff)
downloadBouncyCastle.NET-ed25519-8c32dba3fc4f2033e7597ee1999e793cf6552584.tar.xz
Reimplement application-specific over tagged object
Diffstat (limited to 'crypto/src/asn1/DerApplicationSpecific.cs')
-rw-r--r--crypto/src/asn1/DerApplicationSpecific.cs334
1 files changed, 164 insertions, 170 deletions
diff --git a/crypto/src/asn1/DerApplicationSpecific.cs b/crypto/src/asn1/DerApplicationSpecific.cs
index bc48d24e5..39c2aec28 100644
--- a/crypto/src/asn1/DerApplicationSpecific.cs
+++ b/crypto/src/asn1/DerApplicationSpecific.cs
@@ -11,225 +11,219 @@ namespace Org.BouncyCastle.Asn1
     public class DerApplicationSpecific
         : Asn1Object
     {
-		private readonly bool	isConstructed;
-        private readonly int	tag;
-        private readonly byte[]	octets;
-
-		internal DerApplicationSpecific(
-			bool	isConstructed,
-			int		tag,
-			byte[]	octets)
-		{
-			this.isConstructed = isConstructed;
-			this.tag = tag;
-			this.octets = octets;
-		}
-
-		public DerApplicationSpecific(
-            int		tag,
-            byte[]	octets)
-			: this(false, tag, octets)
-        {
-        }
-
-		public DerApplicationSpecific(
-			int				tag, 
-			Asn1Encodable	obj) 
-			: this(true, tag, obj)
-		{
-		}
-
-		public DerApplicationSpecific(
-			bool			isExplicit,
-			int				tag,
-			Asn1Encodable	obj)
-		{
-            Asn1Object asn1Obj = obj.ToAsn1Object();
-
-            byte[] data = asn1Obj.GetDerEncoded();
-
-            this.isConstructed = Asn1TaggedObject.IsConstructed(isExplicit, asn1Obj);
-			this.tag = tag;
-
-			if (isExplicit)
-			{
-				this.octets = data;
-			}
-			else
-			{
-				int lenBytes = GetLengthOfHeader(data);
-				byte[] tmp = new byte[data.Length - lenBytes];
-				Array.Copy(data, lenBytes, tmp, 0, tmp.Length);
-				this.octets = tmp;
-			}
-		}
-
-		public DerApplicationSpecific(
-			int					tagNo,
-			Asn1EncodableVector	vec)
-		{
-			this.tag = tagNo;
-			this.isConstructed = true;
-			MemoryStream bOut = new MemoryStream();
-
-			for (int i = 0; i != vec.Count; i++)
-			{
-				try
-				{
-					byte[] bs = vec[i].GetDerEncoded();
-					bOut.Write(bs, 0, bs.Length);
-                }
-				catch (IOException e)
-				{
-					throw new InvalidOperationException("malformed object", e);
-				}
-			}
-			this.octets = bOut.ToArray();
-		}
-
-		private int GetLengthOfHeader(
-			byte[] data)
-		{
-            int length = data[1]; // TODO: assumes 1 byte tag
-
-            if (length == 0x80)
+        public static DerApplicationSpecific GetInstance(object obj)
+        {
+            if (obj == null || obj is DerApplicationSpecific)
             {
-                return 2;      // indefinite-length encoding
+                return (DerApplicationSpecific)obj;
             }
-
-            if (length > 127)
+            else if (obj is byte[])
             {
-                int size = length & 0x7f;
-
-                // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here
-                if (size > 4)
+                try
                 {
-                    throw new InvalidOperationException("DER length more than 4 bytes: " + size);
+                    return GetInstance(FromByteArray((byte[])obj));
+                }
+                catch (IOException e)
+                {
+                    throw new ArgumentException("failed to construct application-specific from byte[]: " + e.Message);
                 }
-
-                return size + 2;
             }
 
-            return 2;
+            throw new ArgumentException("illegal object in GetInstance: " + Platform.GetTypeName(obj), "obj");
         }
 
-		public bool IsConstructed()
+        internal readonly Asn1TaggedObject m_taggedObject;
+
+        /**
+         * Create an application specific object from the passed in data. This will assume
+         * the data does not represent a constructed object.
+         *
+         * @param tagNo the tag number for this object.
+         * @param contentsOctets the encoding of the object's body.
+         */
+        public DerApplicationSpecific(int tagNo, byte[] contentsOctets)
+            : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, new DerOctetString(contentsOctets)))
         {
-			return isConstructed;
         }
 
-		public byte[] GetContents()
+        /**
+         * Create an application specific object with a tagging of explicit/constructed.
+         *
+         * @param tag the tag number for this object.
+         * @param object the object to be contained.
+         */
+        public DerApplicationSpecific(int tag, Asn1Encodable baseEncodable)
+            : this(true, tag, baseEncodable)
         {
-            return octets;
         }
 
-		public int ApplicationTag
+        /**
+         * Create an application specific object with the tagging style given by the value of explicit.
+         *
+         * @param explicit true if the object is explicitly tagged.
+         * @param tagNo the tag number for this object.
+         * @param baseEncodable the object to be contained.
+         */
+        public DerApplicationSpecific(bool isExplicit, int tagNo, Asn1Encodable baseEncodable)
+            : this(new DerTaggedObject(isExplicit, Asn1Tags.Application, tagNo, baseEncodable))
         {
-            get { return tag; }
         }
 
-		/**
-		 * Return the enclosed object assuming explicit tagging.
-		 *
-		 * @return  the resulting object
-		 * @throws IOException if reconstruction fails.
-		 */
-		public Asn1Object GetObject()
+        /**
+         * Create an application specific object which is marked as constructed
+         *
+         * @param tagNo the tag number for this object.
+         * @param contentsElements   the objects making up the application specific object.
+         */
+        public DerApplicationSpecific(int tagNo, Asn1EncodableVector contentsElements)
+            : this(new DerTaggedObject(false, Asn1Tags.Application, tagNo, DerSequence.FromVector(contentsElements)))
         {
-			return FromByteArray(GetContents());
-		}
+        }
 
-		/**
-		 * Return the enclosed object assuming implicit tagging.
-		 *
-		 * @param derTagNo the type tag that should be applied to the object's contents.
-		 * @return  the resulting object
-		 * @throws IOException if reconstruction fails.
-		 */
-		public Asn1Object GetObject(
-			int derTagNo)
-		{
-			if (derTagNo >= 0x1f)
-				throw new IOException("unsupported tag number");
+        internal DerApplicationSpecific(Asn1TaggedObject taggedObject)
+            //: base(taggedObject.explicitness, CheckTagClass(taggedObject.tagClass), taggedObject.tagNo,
+            //      taggedObject.obj)
+        {
+            CheckTagClass(taggedObject.TagClass);
 
-			byte[] orig = this.GetEncoded();
-			byte[] tmp = ReplaceTagNumber(derTagNo, orig);
+            this.m_taggedObject = taggedObject;
+        }
 
-			if ((orig[0] & Asn1Tags.Constructed) != 0)
-			{
-				tmp[0] |= Asn1Tags.Constructed;
-			}
+        public int ApplicationTag
+        {
+            get { return m_taggedObject.TagNo; }
+        }
 
-			return FromByteArray(tmp);
-		}
+        public byte[] GetContents()
+        {
+            return m_taggedObject.GetContents();
+        }
 
-        internal override bool EncodeConstructed(int encoding)
+        public Asn1Object GetEnclosedObject()
         {
-            return isConstructed;
+            return m_taggedObject.GetBaseObject().ToAsn1Object();
         }
 
-        internal override int EncodedLength(int encoding, bool withID)
+        [Obsolete("Use GetEnclosedObject instead")]
+        public Asn1Object GetObject()
         {
-            return Asn1OutputStream.GetLengthOfEncodingDL(withID, tag, octets.Length);
+            return GetEnclosedObject();
         }
 
-        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+        public Asn1Object GetObject(int tagNo)
+        {
+            // TODO[asn1] Implement Asn1TaggedObject.GetBaseUniversal
+            //return taggedObject.GetBaseUniversal(false, tagNo);
+
+            if (tagNo >= 0x1F)
+                throw new IOException("unsupported tag number");
+
+            byte[] orig = this.GetEncoded();
+            byte[] tmp = ReplaceTagNumber(tagNo, orig);
+
+            if ((orig[0] & Asn1Tags.Constructed) != 0)
+            {
+                tmp[0] |= Asn1Tags.Constructed;
+            }
+
+            return FromByteArray(tmp);
+        }
+
+        public bool HasApplicationTag(int tagNo)
+        {
+            return m_taggedObject.HasTag(Asn1Tags.Application, tagNo);
+        }
+
+        public bool IsConstructed()
+        {
+            return m_taggedObject.IsConstructed();
+        }
+
+        /**
+         * DerApplicationSpecific uses an internal Asn1TaggedObject for the
+         * implementation, and will soon be deprecated in favour of using
+         * Asn1TaggedObject with a tag class of {@link Asn1Tags#Application}. This method
+         * lets you get the internal Asn1TaggedObject so that client code can begin the
+         * migration.
+         */
+        public Asn1TaggedObject TaggedObject
         {
-			int flags = Asn1Tags.Application;
-			if (isConstructed)
-			{
-                flags |= Asn1Tags.Constructed; 
-			}
+            get { return m_taggedObject; }
+        }
 
-            asn1Out.WriteEncodingDL(withID, flags, tag, octets);
-		}
+        protected override bool Asn1Equals(Asn1Object asn1Object)
+        {
+            Asn1TaggedObject that;
+            if (asn1Object is DerApplicationSpecific)
+            {
+                that = ((DerApplicationSpecific)asn1Object).m_taggedObject;
+            }
+            else if (asn1Object is Asn1TaggedObject)
+            {
+                that = (Asn1TaggedObject)asn1Object;
+            }
+            else
+            {
+                return false;
+            }
+
+            return m_taggedObject.Equals(that);
+        }
 
-		protected override bool Asn1Equals(
-			Asn1Object asn1Object)
+        protected override int Asn1GetHashCode()
         {
-			DerApplicationSpecific other = asn1Object as DerApplicationSpecific;
+            return m_taggedObject.CallAsn1GetHashCode();
+        }
 
-			if (other == null)
-				return false;
+        internal override bool EncodeConstructed(int encoding)
+        {
+            return m_taggedObject.EncodeConstructed(encoding);
+        }
 
-			return this.isConstructed == other.isConstructed
-				&& this.tag == other.tag
-				&& Arrays.AreEqual(this.octets, other.octets);
+        internal override int EncodedLength(int encoding, bool withID)
+        {
+            return m_taggedObject.EncodedLength(encoding, withID);
         }
 
-		protected override int Asn1GetHashCode()
-		{
-			return isConstructed.GetHashCode() ^ tag.GetHashCode() ^ Arrays.GetHashCode(octets);
+        internal override void Encode(Asn1OutputStream asn1Out, bool withID)
+        {
+            m_taggedObject.Encode(asn1Out, withID);
         }
 
-		private byte[] ReplaceTagNumber(
-			int		newTag,
-			byte[]	input)
-		{
-			int tagNo = input[0] & 0x1f;
-			int index = 1;
+        private byte[] ReplaceTagNumber(int newTag, byte[] input)
+        {
+            int tagNo = input[0] & 0x1f;
+            int index = 1;
 
             // with tagged object tag number is bottom 5 bits, or stored at the start of the content
-			if (tagNo == 0x1f)
-			{
-				int b = input[index++];
+            if (tagNo == 0x1f)
+            {
+                int b = input[index++];
 
                 // X.690-0207 8.1.2.4.2
-				// "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
-				if ((b & 0x7f) == 0) // Note: -1 will pass
-					throw new IOException("corrupted stream - invalid high tag number found");
+                // "c) bits 7 to 1 of the first subsequent octet shall not all be zero."
+                if ((b & 0x7f) == 0) // Note: -1 will pass
+                    throw new IOException("corrupted stream - invalid high tag number found");
 
                 while ((b & 0x80) != 0)
-				{
-					b = input[index++];
-				}
-			}
+                {
+                    b = input[index++];
+                }
+            }
 
             int remaining = input.Length - index;
             byte[] tmp = new byte[1 + remaining];
             tmp[0] = (byte)newTag;
-			Array.Copy(input, index, tmp, 1, remaining);
-			return tmp;
-		}
+            Array.Copy(input, index, tmp, 1, remaining);
+            return tmp;
+        }
+
+        private static int CheckTagClass(int tagClass)
+        {
+            if (Asn1Tags.Application != tagClass)
+                throw new ArgumentException();
+
+            return tagClass;
+        }
     }
 }