diff options
author | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 01:18:46 +0700 |
---|---|---|
committer | Peter Dettman <peter.dettman@bouncycastle.org> | 2021-10-15 01:18:46 +0700 |
commit | d3fd5f9580f7f9d5f2d63f86e8e08d22ad18654c (patch) | |
tree | ae679455ccc8aae2c64a0a23823b1a7ee9f12469 /crypto/src/asn1 | |
parent | Add utility methods (diff) | |
download | BouncyCastle.NET-ed25519-d3fd5f9580f7f9d5f2d63f86e8e08d22ad18654c.tar.xz |
ASN1InputStream updates from bc-java
- improve tag validation - improve handling of long form definite-length
Diffstat (limited to 'crypto/src/asn1')
-rw-r--r-- | crypto/src/asn1/Asn1InputStream.cs | 79 |
1 files changed, 46 insertions, 33 deletions
diff --git a/crypto/src/asn1/Asn1InputStream.cs b/crypto/src/asn1/Asn1InputStream.cs index 1791e5356..6bb6311e1 100644 --- a/crypto/src/asn1/Asn1InputStream.cs +++ b/crypto/src/asn1/Asn1InputStream.cs @@ -242,9 +242,7 @@ namespace Org.BouncyCastle.Asn1 get { return limit; } } - internal static int ReadTagNumber( - Stream s, - int tag) + internal static int ReadTagNumber(Stream s, int tag) { int tagNo = tag & 0x1f; @@ -256,23 +254,32 @@ namespace Org.BouncyCastle.Asn1 tagNo = 0; int b = s.ReadByte(); + if (b < 31) + { + if (b < 0) + throw new EndOfStreamException("EOF found inside tag value."); + + throw new IOException("corrupted stream - high tag number < 31 found"); + } // 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 + if ((b & 0x7f) == 0) throw new IOException("corrupted stream - invalid high tag number found"); - while ((b >= 0) && ((b & 0x80) != 0)) + while ((b & 0x80) != 0) { - tagNo |= (b & 0x7f); + if (((uint)tagNo >> 24) != 0U) + throw new IOException("Tag number more than 31 bits"); + + tagNo |= b & 0x7f; tagNo <<= 7; b = s.ReadByte(); + if (b < 0) + throw new EndOfStreamException("EOF found inside tag value."); } - if (b < 0) - throw new EndOfStreamException("EOF found inside tag value."); - - tagNo |= (b & 0x7f); + tagNo |= b & 0x7f; } return tagNo; @@ -281,37 +288,43 @@ namespace Org.BouncyCastle.Asn1 internal static int ReadLength(Stream s, int limit, bool isParsing) { int length = s.ReadByte(); + if (0U == ((uint)length >> 7)) + { + // definite-length short form + return length; + } + if (0x80 == length) + { + // indefinite-length + return -1; + } if (length < 0) + { throw new EndOfStreamException("EOF found when length expected"); - - if (length == 0x80) - return -1; // indefinite-length encoding - - if (length > 127) + } + if (0xFF == length) { - int size = length & 0x7f; - - // Note: The invalid long form "0xff" (see X.690 8.1.3.5c) will be caught here - if (size > 4) - throw new IOException("DER length more than 4 bytes: " + size); - - length = 0; - for (int i = 0; i < size; i++) - { - int next = s.ReadByte(); + throw new IOException("invalid long form definite-length 0xFF"); + } - if (next < 0) - throw new EndOfStreamException("EOF found reading length"); + int octetsCount = length & 0x7F, octetsPos = 0; - length = (length << 8) + next; - } + length = 0; + do + { + int octet = s.ReadByte(); + if (octet < 0) + throw new EndOfStreamException("EOF found reading length"); - if (length < 0) - throw new IOException("corrupted stream - negative length found"); + if (((uint)length >> 23) != 0U) + throw new IOException("long form definite-length more than 31 bits"); - if (length >= limit && !isParsing) // after all we must have read at least 1 byte - throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit); + length = (length << 8) + octet; } + while (++octetsPos < octetsCount); + + if (length >= limit && !isParsing) // after all we must have read at least 1 byte + throw new IOException("corrupted stream - out of bounds length found: " + length + " >= " + limit); return length; } |