summary refs log tree commit diff
path: root/crypto/src/asn1/Asn1InputStream.cs
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/src/asn1/Asn1InputStream.cs')
-rw-r--r--crypto/src/asn1/Asn1InputStream.cs128
1 files changed, 84 insertions, 44 deletions
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs
index 0e772010f..b09322234 100644
--- a/crypto/src/asn1/Asn1InputStream.cs
+++ b/crypto/src/asn1/Asn1InputStream.cs
@@ -359,56 +359,13 @@ namespace Org.BouncyCastle.Asn1
             return buf;
         }
 
-        private static char[] GetBmpCharBuffer(DefiniteLengthInputStream defIn)
-        {
-            int remainingBytes = defIn.Remaining;
-            if (0 != (remainingBytes & 1))
-                throw new IOException("malformed BMPString encoding encountered");
-
-            char[] str = new char[remainingBytes / 2];
-            int stringPos = 0;
-
-            byte[] buf = new byte[8];
-            while (remainingBytes >= 8)
-            {
-                if (Streams.ReadFully(defIn, buf, 0, 8) != 8)
-                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
-
-                str[stringPos    ] = (char)((buf[0] << 8) | (buf[1] & 0xFF));
-                str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF));
-                str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF));
-                str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF));
-                stringPos += 4;
-                remainingBytes -= 8;
-            }
-            if (remainingBytes > 0)
-            {
-                if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes)
-                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
-
-                int bufPos = 0;
-                do
-                {
-                    int b1 = buf[bufPos++] << 8;
-                    int b2 = buf[bufPos++] & 0xFF;
-                    str[stringPos++] = (char)(b1 | b2);
-                }
-                while (bufPos < remainingBytes);
-            }
-
-            if (0 != defIn.Remaining || str.Length != stringPos)
-                throw new InvalidOperationException();
-
-            return str;
-        }
-
         internal static Asn1Object CreatePrimitiveDerObject(int tagNo, DefiniteLengthInputStream defIn,
             byte[][] tmpBuffers)
         {
             switch (tagNo)
             {
             case Asn1Tags.BmpString:
-                return DerBmpString.CreatePrimitive(GetBmpCharBuffer(defIn));
+                return CreateDerBmpString(defIn);
             case Asn1Tags.Boolean:
                 return DerBoolean.CreatePrimitive(GetBuffer(defIn, tmpBuffers));
             case Asn1Tags.Enumerated:
@@ -463,5 +420,88 @@ namespace Org.BouncyCastle.Asn1
                 throw new IOException("unknown tag " + tagNo + " encountered");
             }
         }
+
+        private static DerBmpString CreateDerBmpString(DefiniteLengthInputStream defIn)
+        {
+            int remainingBytes = defIn.Remaining;
+            if (0 != (remainingBytes & 1))
+                throw new IOException("malformed BMPString encoding encountered");
+
+            int length = remainingBytes / 2;
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+            return DerBmpString.CreatePrimitive(length, defIn, (str, defIn) =>
+            {
+                int stringPos = 0;
+
+                Span<byte> buf = stackalloc byte[8];
+                while (remainingBytes >= 8)
+                {
+                    if (Streams.ReadFully(defIn, buf) != 8)
+                        throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                    str[stringPos    ] = (char)((buf[0] << 8) | (buf[1] & 0xFF));
+                    str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF));
+                    str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF));
+                    str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF));
+                    stringPos += 4;
+                    remainingBytes -= 8;
+                }
+                if (remainingBytes > 0)
+                {
+                    if (Streams.ReadFully(defIn, buf) != remainingBytes)
+                        throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                    int bufPos = 0;
+                    do
+                    {
+                        int b1 = buf[bufPos++] << 8;
+                        int b2 = buf[bufPos++] & 0xFF;
+                        str[stringPos++] = (char)(b1 | b2);
+                    }
+                    while (bufPos < remainingBytes);
+                }
+
+                if (0 != defIn.Remaining || str.Length != stringPos)
+                    throw new InvalidOperationException();
+            });
+#else
+            char[] str = new char[length];
+            int stringPos = 0;
+
+            byte[] buf = new byte[8];
+            while (remainingBytes >= 8)
+            {
+                if (Streams.ReadFully(defIn, buf, 0, 8) != 8)
+                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                str[stringPos    ] = (char)((buf[0] << 8) | (buf[1] & 0xFF));
+                str[stringPos + 1] = (char)((buf[2] << 8) | (buf[3] & 0xFF));
+                str[stringPos + 2] = (char)((buf[4] << 8) | (buf[5] & 0xFF));
+                str[stringPos + 3] = (char)((buf[6] << 8) | (buf[7] & 0xFF));
+                stringPos += 4;
+                remainingBytes -= 8;
+            }
+            if (remainingBytes > 0)
+            {
+                if (Streams.ReadFully(defIn, buf, 0, remainingBytes) != remainingBytes)
+                    throw new EndOfStreamException("EOF encountered in middle of BMPString");
+
+                int bufPos = 0;
+                do
+                {
+                    int b1 = buf[bufPos++] << 8;
+                    int b2 = buf[bufPos++] & 0xFF;
+                    str[stringPos++] = (char)(b1 | b2);
+                }
+                while (bufPos < remainingBytes);
+            }
+
+            if (0 != defIn.Remaining || str.Length != stringPos)
+                throw new InvalidOperationException();
+
+            return DerBmpString.CreatePrimitive(str);
+#endif
+        }
     }
 }