summary refs log tree commit diff
diff options
context:
space:
mode:
authorPeter Dettman <peter.dettman@bouncycastle.org>2021-10-14 18:46:47 +0700
committerPeter Dettman <peter.dettman@bouncycastle.org>2021-10-14 18:46:47 +0700
commitc3a6083bace63a12515b08b30e4ffa42fc74a0a0 (patch)
tree694e96380bbf30b597462be7dcefe0dc4ceb7406
parentAdd WriteElements method (diff)
downloadBouncyCastle.NET-ed25519-c3a6083bace63a12515b08b30e4ffa42fc74a0a0.tar.xz
More ASN.1 updates from bc-java
-rw-r--r--crypto/src/asn1/Asn1Object.cs18
-rw-r--r--crypto/src/asn1/Asn1OutputStream.cs44
-rw-r--r--crypto/src/asn1/BEROctetStringGenerator.cs6
-rw-r--r--crypto/src/asn1/BerTaggedObject.cs6
-rw-r--r--crypto/src/asn1/DerOutputStream.cs182
-rw-r--r--crypto/src/asn1/DerTaggedObject.cs2
6 files changed, 126 insertions, 132 deletions
diff --git a/crypto/src/asn1/Asn1Object.cs b/crypto/src/asn1/Asn1Object.cs
index 1abf0e0bd..d60a85348 100644
--- a/crypto/src/asn1/Asn1Object.cs
+++ b/crypto/src/asn1/Asn1Object.cs
@@ -13,23 +13,7 @@ namespace Org.BouncyCastle.Asn1
 
         public override void EncodeTo(Stream output, string encoding)
         {
-            Asn1OutputStream asn1Out = Asn1OutputStream.Create(output, encoding);
-            Asn1Object asn1Object = this;
-
-            if (Der.Equals(encoding))
-            {
-                Asn1Set asn1Set = asn1Object as Asn1Set;
-                if (null != asn1Set)
-                {
-                    /*
-                     * NOTE: Even a DerSet isn't necessarily already in sorted order (particularly from DerSetParser),
-                     * so all sets have to be converted here.
-                     */
-                    asn1Object = new DerSet(asn1Set.elements);
-                }
-            }
-
-            asn1Out.WriteObject(asn1Object);
+            Asn1OutputStream.Create(output, encoding).WriteObject(this);
         }
 
         /// <summary>Create a base ASN.1 object from a byte array.</summary>
diff --git a/crypto/src/asn1/Asn1OutputStream.cs b/crypto/src/asn1/Asn1OutputStream.cs
index 5746d1c59..e6eec563e 100644
--- a/crypto/src/asn1/Asn1OutputStream.cs
+++ b/crypto/src/asn1/Asn1OutputStream.cs
@@ -29,6 +29,29 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
+        public override void WriteObject(Asn1Encodable encodable)
+        {
+            if (null == encodable)
+                throw new IOException("null object detected");
+
+            WritePrimitive(encodable.ToAsn1Object());
+            FlushInternal();
+        }
+
+        public override void WriteObject(Asn1Object primitive)
+        {
+            if (null == primitive)
+                throw new IOException("null object detected");
+
+            WritePrimitive(primitive);
+            FlushInternal();
+        }
+
+        internal void FlushInternal()
+        {
+            // Placeholder to support future internal buffering
+        }
+
         internal override bool IsBer
         {
             get { return true; }
@@ -42,27 +65,16 @@ namespace Org.BouncyCastle.Asn1
             }
         }
 
-        public override void WriteObject(Asn1Encodable obj)
+        internal virtual void WritePrimitive(Asn1Object primitive)
         {
-            if (obj == null)
-            {
-                WriteNull();
-            }
-            else
-            {
-                obj.ToAsn1Object().Encode(this);
-            }
+            primitive.Encode(this);
         }
 
-        public override void WriteObject(Asn1Object obj)
+        internal virtual void WritePrimitives(Asn1Object[] primitives)
         {
-            if (obj == null)
-            {
-                WriteNull();
-            }
-            else
+            for (int i = 0, count = primitives.Length; i < count; ++i)
             {
-                obj.Encode(this);
+                WritePrimitive(primitives[i]);
             }
         }
     }
diff --git a/crypto/src/asn1/BEROctetStringGenerator.cs b/crypto/src/asn1/BEROctetStringGenerator.cs
index de039014b..4a7f1e8e5 100644
--- a/crypto/src/asn1/BEROctetStringGenerator.cs
+++ b/crypto/src/asn1/BEROctetStringGenerator.cs
@@ -112,6 +112,8 @@ namespace Org.BouncyCastle.Asn1
 					    DerOctetString.Encode(_derOut, _buf, 0, _off);
 				    }
 
+                    _derOut.FlushInternal();
+
 				    _gen.WriteBerEnd();
                 }
                 base.Dispose(disposing);
@@ -124,7 +126,9 @@ namespace Org.BouncyCastle.Asn1
 					DerOctetString.Encode(_derOut, _buf, 0, _off);
 				}
 
-				_gen.WriteBerEnd();
+                _derOut.FlushInternal();
+
+                _gen.WriteBerEnd();
 				base.Close();
 			}
 #endif
diff --git a/crypto/src/asn1/BerTaggedObject.cs b/crypto/src/asn1/BerTaggedObject.cs
index 9dadc24ba..097f77610 100644
--- a/crypto/src/asn1/BerTaggedObject.cs
+++ b/crypto/src/asn1/BerTaggedObject.cs
@@ -51,7 +51,7 @@ namespace Org.BouncyCastle.Asn1
 		{
 			if (asn1Out.IsBer)
 			{
-				asn1Out.WriteTag(Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
+				asn1Out.WriteIdentifier(true, Asn1Tags.Constructed | Asn1Tags.Tagged, tagNo);
 				asn1Out.WriteByte(0x80);
 
 				if (!IsEmpty())
@@ -86,12 +86,12 @@ namespace Org.BouncyCastle.Asn1
 
 						foreach (Asn1Encodable o in eObj)
 						{
-							asn1Out.WriteObject(o);
+							asn1Out.WritePrimitive(o.ToAsn1Object());
 						}
 					}
 					else
 					{
-						asn1Out.WriteObject(obj);
+						asn1Out.WritePrimitive(obj.ToAsn1Object());
 					}
 				}
 
diff --git a/crypto/src/asn1/DerOutputStream.cs b/crypto/src/asn1/DerOutputStream.cs
index 3ecdcd11f..84d1af44b 100644
--- a/crypto/src/asn1/DerOutputStream.cs
+++ b/crypto/src/asn1/DerOutputStream.cs
@@ -15,43 +15,52 @@ namespace Org.BouncyCastle.Asn1
         {
         }
 
+        public virtual void WriteObject(Asn1Encodable encodable)
+        {
+            new DerOutputStreamNew(s).WriteObject(encodable);
+        }
+
+        public virtual void WriteObject(Asn1Object primitive)
+        {
+            new DerOutputStreamNew(s).WriteObject(primitive);
+        }
+
         internal virtual bool IsBer
         {
             get { return false; }
         }
 
-		private void WriteLength(
-			int length)
+		internal void WriteDL(int length)
 		{
-			if (length > 127)
-			{
-				int size = 1;
-				uint val = (uint)length;
-
-				while ((val >>= 8) != 0)
-				{
-					size++;
-				}
-
-				WriteByte((byte)(size | 0x80));
-
-				for (int i = (size - 1) * 8; i >= 0; i -= 8)
-				{
-					WriteByte((byte)(length >> i));
-				}
-			}
-			else
-			{
-				WriteByte((byte)length);
-			}
-		}
+            if (length < 128)
+            {
+                WriteByte((byte)length);
+            }
+            else
+            {
+                byte[] stack = new byte[5];
+                int pos = stack.Length;
+
+                do
+                {
+                    stack[--pos] = (byte)length;
+                    length >>= 8;
+                }
+                while (length > 0);
+
+                int count = stack.Length - pos;
+                stack[--pos] = (byte)(0x80 | count);
+
+                Write(stack, pos, count + 1);
+            }
+        }
 
-		internal void WriteEncoded(
+        internal void WriteEncoded(
 			int		tag,
 			byte[]	bytes)
 		{
 			WriteByte((byte)tag);
-			WriteLength(bytes.Length);
+			WriteDL(bytes.Length);
 			Write(bytes, 0, bytes.Length);
 		}
 
@@ -61,7 +70,7 @@ namespace Org.BouncyCastle.Asn1
             byte[]  bytes)
         {
             WriteByte((byte)tag);
-            WriteLength(bytes.Length + 1);
+            WriteDL(bytes.Length + 1);
             WriteByte(first);
             Write(bytes, 0, bytes.Length);
         }
@@ -73,85 +82,55 @@ namespace Org.BouncyCastle.Asn1
 			int		length)
 		{
 			WriteByte((byte)tag);
-			WriteLength(length);
+            WriteDL(length);
 			Write(bytes, offset, length);
 		}
 
-		internal void WriteTag(
-			int	flags,
-			int	tagNo)
-		{
-			if (tagNo < 31)
-			{
-				WriteByte((byte)(flags | tagNo));
-			}
-			else
-			{
-				WriteByte((byte)(flags | 0x1f));
-				if (tagNo < 128)
-				{
-					WriteByte((byte)tagNo);
-				}
-				else
-				{
-					byte[] stack = new byte[5];
-					int pos = stack.Length;
-
-					stack[--pos] = (byte)(tagNo & 0x7F);
-
-					do
-					{
-						tagNo >>= 7;
-						stack[--pos] = (byte)(tagNo & 0x7F | 0x80);
-					}
-					while (tagNo > 127);
-
-					Write(stack, pos, stack.Length - pos);
-				}
-			}
-		}
-
 		internal void WriteEncoded(
 			int		flags,
 			int		tagNo,
 			byte[]	bytes)
 		{
-			WriteTag(flags, tagNo);
-			WriteLength(bytes.Length);
+			WriteIdentifier(true, flags, tagNo);
+            WriteDL(bytes.Length);
 			Write(bytes, 0, bytes.Length);
 		}
 
-		protected void WriteNull()
-		{
-			WriteByte(Asn1Tags.Null);
-			WriteByte(0x00);
-		}
-
-		public virtual void WriteObject(
-			Asn1Encodable obj)
-		{
-			if (obj == null)
-			{
-				WriteNull();
-			}
-			else
-			{
-				obj.ToAsn1Object().Encode(new DerOutputStreamNew(s));
-			}
-		}
+        internal void WriteIdentifier(bool withID, int identifier)
+        {
+            if (withID)
+            {
+                WriteByte((byte)identifier);
+            }
+        }
 
-		public virtual void WriteObject(
-			Asn1Object obj)
-		{
-			if (obj == null)
-			{
-				WriteNull();
-			}
-			else
-			{
-				obj.Encode(new DerOutputStreamNew(s));
-			}
-		}
+        internal void WriteIdentifier(bool withID, int flags, int tag)
+        {
+            if (!withID)
+            {
+                // Don't write the identifier
+            }
+            else if (tag < 31)
+            {
+                WriteByte((byte)(flags | tag));
+            }
+            else
+            {
+                byte[] stack = new byte[6];
+                int pos = stack.Length;
+
+                stack[--pos] = (byte)(tag & 0x7F);
+                while (tag > 127)
+                {
+                    tag >>= 7;
+                    stack[--pos] = (byte)(tag & 0x7F | 0x80);
+                }
+
+                stack[--pos] = (byte)(flags | 0x1F);
+
+                Write(stack, pos, stack.Length - pos);
+            }
+        }
 	}
 
     internal class DerOutputStreamNew
@@ -166,5 +145,20 @@ namespace Org.BouncyCastle.Asn1
         {
             get { return false; }
         }
+
+        internal override void WritePrimitive(Asn1Object primitive)
+        {
+            Asn1Set asn1Set = primitive as Asn1Set;
+            if (null != asn1Set)
+            {
+                /*
+                 * NOTE: Even a DerSet isn't necessarily already in sorted order (particularly from DerSetParser),
+                 * so all sets have to be converted here.
+                 */
+                primitive = new DerSet(asn1Set.elements);
+            }
+
+            primitive.Encode(this);
+        }
     }
 }
diff --git a/crypto/src/asn1/DerTaggedObject.cs b/crypto/src/asn1/DerTaggedObject.cs
index 182d5ee47..40776ace3 100644
--- a/crypto/src/asn1/DerTaggedObject.cs
+++ b/crypto/src/asn1/DerTaggedObject.cs
@@ -58,7 +58,7 @@ namespace Org.BouncyCastle.Asn1
 					// need to mark constructed types... (preserve Constructed tag)
 					//
 					int flags = (bytes[0] & Asn1Tags.Constructed) | Asn1Tags.Tagged;
-					asn1Out.WriteTag(flags, tagNo);
+					asn1Out.WriteIdentifier(true, flags, tagNo);
 					asn1Out.Write(bytes, 1, bytes.Length - 1);
 				}
 			}