diff options
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r-- | crypto/src/asn1/Asn1InputStream.cs | 128 | ||||
-rw-r--r-- | crypto/src/asn1/DerBMPString.cs | 23 |
2 files changed, 107 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 + } } } diff --git a/crypto/src/asn1/DerBMPString.cs b/crypto/src/asn1/DerBMPString.cs index 284a4b830..bf21fa424 100644 --- a/crypto/src/asn1/DerBMPString.cs +++ b/crypto/src/asn1/DerBMPString.cs @@ -1,4 +1,7 @@ using System; +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER +using System.Buffers; +#endif using System.IO; using Org.BouncyCastle.Utilities; @@ -82,6 +85,16 @@ namespace Org.BouncyCastle.Asn1 throw new ArgumentException("malformed BMPString encoding encountered", "contents"); int charLen = byteLen / 2; + +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + m_str = string.Create(charLen, contents, (chars, bytes) => + { + for (int i = 0; i < chars.Length; ++i) + { + chars[i] = (char)((bytes[2 * i] << 8) | (bytes[2 * i + 1] & 0xff)); + } + }); +#else char[] cs = new char[charLen]; for (int i = 0; i != charLen; i++) @@ -90,8 +103,10 @@ namespace Org.BouncyCastle.Asn1 } m_str = new string(cs); +#endif } +#if !(NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER) internal DerBmpString(char[] str) { if (str == null) @@ -99,6 +114,7 @@ namespace Org.BouncyCastle.Asn1 m_str = new string(str); } +#endif /** * basic constructor @@ -157,10 +173,17 @@ namespace Org.BouncyCastle.Asn1 return new DerBmpString(contents); } +#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER + internal static DerBmpString CreatePrimitive<TState>(int length, TState state, SpanAction<char, TState> action) + { + return new DerBmpString(string.Create(length, state, action)); + } +#else internal static DerBmpString CreatePrimitive(char[] str) { // TODO[asn1] Asn1InputStream has a validator/converter that should be unified in this class somehow return new DerBmpString(str); } +#endif } } |