diff options
author | Jeremy Barton <jbarton@microsoft.com> | 2018-04-30 23:46:39 +0300 |
---|---|---|
committer | Stephen Toub <stoub@microsoft.com> | 2018-04-30 23:46:39 +0300 |
commit | 136199dfb896d0470a72f96c43c1bb4d1eb786f8 (patch) | |
tree | 0126c21d4442fcb9df03a905fe45c6ed95e62a23 /src/System.Security.Cryptography.Encoding | |
parent | ecbece3a9f702bb9fd3ea1a723eb5fd8680378e6 (diff) |
Correctly deserialize constructed octet and bit strings (#29389)
When a BIT STRING or OCTET STRING is implicitly tagged using a tag from the
context-specific, application, or private tag classes and has a constructed
representation, the outer tag is the specified tag and the inner tags are 03 or 04.
In the deserializer the correct tag was used for TryGetPrimitive[Type]Bytes, but
that returns false for indefinite length encodings (because the content bytes
are not contiguous). During the fallback to TryCopy[Type]Bytes the expected
tag value was not passed along, so the read operation failed with a tag
mismatch.
Now we correctly pass the expected tag, so TryCopy[Type]Bytes matches the
expected outer tag and continues with the constructed encoding (definite or
indefinite length) rules for the BIT STRING or OCTET STRING value.
Character string types also have TryGetPrimitive overloads, but these aren't
used in the deserializer, currently only the string-allocating forms are
supported.
Diffstat (limited to 'src/System.Security.Cryptography.Encoding')
-rw-r--r-- | src/System.Security.Cryptography.Encoding/tests/Asn1/Serializer/SimpleDeserialize.cs | 40 |
1 files changed, 40 insertions, 0 deletions
diff --git a/src/System.Security.Cryptography.Encoding/tests/Asn1/Serializer/SimpleDeserialize.cs b/src/System.Security.Cryptography.Encoding/tests/Asn1/Serializer/SimpleDeserialize.cs index 1b19ddd670..e61f3ac4a6 100644 --- a/src/System.Security.Cryptography.Encoding/tests/Asn1/Serializer/SimpleDeserialize.cs +++ b/src/System.Security.Cryptography.Encoding/tests/Asn1/Serializer/SimpleDeserialize.cs @@ -470,6 +470,34 @@ namespace System.Security.Cryptography.Tests.Asn1 Assert.Throws<CryptographicException>( () => AsnSerializer.Deserialize<OptionalValues>(inputData, AsnEncodingRules.BER)); } + + [Fact] + public static void ReadIndefiniteLengthCustomTaggedStrings() + { + byte[] inputData = ( + // (constructed) SEQUENCE (indefinite) + "3080" + + // (constructed) CONTEXT-SPECIFIC 0 (indefinite) + "A080" + + // OCTET STRING (3): 020100 + "0403020100" + + // EoC ([0]) + "0000" + + // (constructed) CONTEXT-SPECIFIC 1 (indefinite) + "A180" + + // BIT STRING (4) (0 unused bits): 010203 + "030400010203" + + // EoC ([1]) + "0000" + + // EoC (SEQUENCE) + "0000").HexToByteArray(); + + CustomTaggedBinaryStrings parsed = + AsnSerializer.Deserialize<CustomTaggedBinaryStrings>(inputData, AsnEncodingRules.BER); + + Assert.Equal("020100", parsed.OctetString.ByteArrayToHex()); + Assert.Equal("010203", parsed.BitString.ByteArrayToHex()); + } } // RFC 3280 / ITU-T X.509 @@ -841,4 +869,16 @@ namespace System.Security.Cryptography.Tests.Asn1 [IA5String, OptionalValue] public string IA5String; } + + [StructLayout(LayoutKind.Sequential)] + public struct CustomTaggedBinaryStrings + { + [OctetString] + [ExpectedTag(0)] + public ReadOnlyMemory<byte> OctetString; + + [BitString] + [ExpectedTag(1)] + public ReadOnlyMemory<byte> BitString; + } } |