Imported Upstream version 5.10.0.69

Former-commit-id: fc39669a0b707dd3c063977486506b6793da2890
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-01-29 19:03:06 +00:00
parent d8f8abd549
commit e2950ec768
6283 changed files with 453847 additions and 91879 deletions

View File

@@ -55,6 +55,10 @@ namespace Internal.Cryptography
private static readonly Dictionary<string, string> s_extraFriendlyNameToOid =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "pkcs7-data", "1.2.840.113549.1.7.1" },
{ "contentType", "1.2.840.113549.1.9.3" },
{ "messageDigest", "1.2.840.113549.1.9.4" },
{ "signingTime", "1.2.840.113549.1.9.5" },
{ "X509v3 Subject Key Identifier", "2.5.29.14" },
{ "X509v3 Key Usage", "2.5.29.15" },
{ "X509v3 Basic Constraints", "2.5.29.19" },

View File

@@ -98,7 +98,6 @@
<ItemGroup>
<Reference Include="System.Collections" />
<Reference Include="System.Collections.Concurrent" />
<Reference Include="System.Diagnostics.Contracts" />
<Reference Include="System.Diagnostics.Debug" />
<Reference Include="System.Linq" />
<Reference Include="System.Resources.ResourceManager" />

View File

@@ -0,0 +1,26 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
namespace System.Security.Cryptography.Tests.Asn1
{
public abstract partial class Asn1ReaderTests
{
public enum PublicTagClass : byte
{
Universal = TagClass.Universal,
Application = TagClass.Application,
ContextSpecific = TagClass.ContextSpecific,
Private = TagClass.Private,
}
public enum PublicEncodingRules
{
BER = AsnEncodingRules.BER,
CER = AsnEncodingRules.CER,
DER = AsnEncodingRules.DER,
}
}
}

View File

@@ -0,0 +1,266 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
using X509KeyUsageCSharpStyle=System.Security.Cryptography.Tests.Asn1.ReadNamedBitList.X509KeyUsageCSharpStyle;
namespace System.Security.Cryptography.Tests.Asn1
{
public static class ComprehensiveReadTests
{
[Fact]
public static void ReadMicrosoftComCert()
{
byte[] bytes = MicrosoftDotComSslCertBytes;
AsnReader fileReader = new AsnReader(bytes, AsnEncodingRules.DER);
AsnReader certReader = fileReader.ReadSequence();
Assert.False(fileReader.HasData, "fileReader.HasData");
AsnReader tbsCertReader = certReader.ReadSequence();
AsnReader sigAlgReader = certReader.ReadSequence();
Assert.True(
certReader.TryGetPrimitiveBitStringValue(
out int unusedBitCount,
out ReadOnlyMemory<byte> signature),
"certReader.TryGetBitStringBytes");
Assert.Equal(0, unusedBitCount);
AssertRefSame(signature, ref bytes[1176], "Signature is a ref to bytes[1176]");
Assert.False(certReader.HasData, "certReader.HasData");
AsnReader versionExplicitWrapper = tbsCertReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
Assert.True(versionExplicitWrapper.TryReadInt32(out int certVersion));
Assert.Equal(2, certVersion);
Assert.False(versionExplicitWrapper.HasData, "versionExplicitWrapper.HasData");
ReadOnlyMemory<byte> serialBytes = tbsCertReader.GetIntegerBytes();
AssertRefSame(serialBytes, ref bytes[15], "Serial number starts at bytes[15]");
AsnReader tbsSigAlgReader = tbsCertReader.ReadSequence();
Assert.Equal("1.2.840.113549.1.1.11", tbsSigAlgReader.ReadObjectIdentifierAsString());
Assert.True(tbsSigAlgReader.HasData, "tbsSigAlgReader.HasData before ReadNull");
tbsSigAlgReader.ReadNull();
Assert.False(tbsSigAlgReader.HasData, "tbsSigAlgReader.HasData after ReadNull");
AsnReader issuerReader = tbsCertReader.ReadSequence();
Asn1Tag printableString = new Asn1Tag(UniversalTagNumber.PrintableString);
AssertRdn(issuerReader, "2.5.4.6", 57, printableString, bytes, "issuer[C]");
AssertRdn(issuerReader, "2.5.4.10", 70, printableString, bytes, "issuer[O]");
AssertRdn(issuerReader, "2.5.4.11", 101, printableString, bytes, "issuer[OU]");
AssertRdn(issuerReader, "2.5.4.3", 134, printableString, bytes, "issuer[CN]");
Assert.False(issuerReader.HasData, "issuerReader.HasData");
AsnReader validityReader = tbsCertReader.ReadSequence();
Assert.Equal(new DateTimeOffset(2014, 10, 15, 0, 0, 0, TimeSpan.Zero), validityReader.GetUtcTime());
Assert.Equal(new DateTimeOffset(2016, 10, 15, 23, 59, 59, TimeSpan.Zero), validityReader.GetUtcTime());
Assert.False(validityReader.HasData, "validityReader.HasData");
AsnReader subjectReader = tbsCertReader.ReadSequence();
Asn1Tag utf8String = new Asn1Tag(UniversalTagNumber.UTF8String);
AssertRdn(subjectReader, "1.3.6.1.4.1.311.60.2.1.3", 220, printableString, bytes, "subject[EV Country]");
AssertRdn(subjectReader, "1.3.6.1.4.1.311.60.2.1.2", 241, utf8String, bytes, "subject[EV State]", "Washington");
AssertRdn(subjectReader, "2.5.4.15", 262, printableString, bytes, "subject[Business Category]");
AssertRdn(subjectReader, "2.5.4.5", 293, printableString, bytes, "subject[Serial Number]");
AssertRdn(subjectReader, "2.5.4.6", 313, printableString, bytes, "subject[C]");
AssertRdn(subjectReader, "2.5.4.17", 326, utf8String, bytes, "subject[Postal Code]", "98052");
AssertRdn(subjectReader, "2.5.4.8", 342, utf8String, bytes, "subject[ST]", "Washington");
AssertRdn(subjectReader, "2.5.4.7", 363, utf8String, bytes, "subject[L]", "Redmond");
AssertRdn(subjectReader, "2.5.4.9", 381, utf8String, bytes, "subject[Street Address]", "1 Microsoft Way");
AssertRdn(subjectReader, "2.5.4.10", 407, utf8String, bytes, "subject[O]", "Microsoft Corporation");
AssertRdn(subjectReader, "2.5.4.11", 439, utf8String, bytes, "subject[OU]", "MSCOM");
AssertRdn(subjectReader, "2.5.4.3", 455, utf8String, bytes, "subject[CN]", "www.microsoft.com");
Assert.False(subjectReader.HasData, "subjectReader.HasData");
AsnReader subjectPublicKeyInfo = tbsCertReader.ReadSequence();
AsnReader spkiAlgorithm = subjectPublicKeyInfo.ReadSequence();
Assert.Equal("1.2.840.113549.1.1.1", spkiAlgorithm.ReadObjectIdentifierAsString());
spkiAlgorithm.ReadNull();
Assert.False(spkiAlgorithm.HasData, "spkiAlgorithm.HasData");
Assert.True(
subjectPublicKeyInfo.TryGetPrimitiveBitStringValue(
out unusedBitCount,
out ReadOnlyMemory<byte> encodedPublicKey),
"subjectPublicKeyInfo.TryGetBitStringBytes");
Assert.Equal(0, unusedBitCount);
AssertRefSame(encodedPublicKey, ref bytes[498], "Encoded public key starts at byte 498");
Assert.False(subjectPublicKeyInfo.HasData, "subjectPublicKeyInfo.HasData");
AsnReader publicKeyReader = new AsnReader(encodedPublicKey, AsnEncodingRules.DER);
AsnReader rsaPublicKeyReader = publicKeyReader.ReadSequence();
AssertRefSame(rsaPublicKeyReader.GetIntegerBytes(), ref bytes[506], "RSA Modulus is at bytes[502]");
Assert.True(rsaPublicKeyReader.TryReadInt32(out int rsaExponent));
Assert.Equal(65537, rsaExponent);
Assert.False(rsaPublicKeyReader.HasData, "rsaPublicKeyReader.HasData");
Assert.False(publicKeyReader.HasData, "publicKeyReader.HasData");
AsnReader extensionsContainer = tbsCertReader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 3));
AsnReader extensions = extensionsContainer.ReadSequence();
Assert.False(extensionsContainer.HasData, "extensionsContainer.HasData");
AsnReader sanExtension = extensions.ReadSequence();
Assert.Equal("2.5.29.17", sanExtension.ReadObjectIdentifierAsString());
Assert.True(sanExtension.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> sanExtensionBytes));
Assert.False(sanExtension.HasData, "sanExtension.HasData");
AsnReader sanExtensionPayload = new AsnReader(sanExtensionBytes, AsnEncodingRules.DER);
AsnReader sanExtensionValue = sanExtensionPayload.ReadSequence();
Assert.False(sanExtensionPayload.HasData, "sanExtensionPayload.HasData");
Asn1Tag dnsName = new Asn1Tag(TagClass.ContextSpecific, 2);
Assert.Equal("www.microsoft.com", sanExtensionValue.GetCharacterString(dnsName, UniversalTagNumber.IA5String));
Assert.Equal("wwwqa.microsoft.com", sanExtensionValue.GetCharacterString(dnsName, UniversalTagNumber.IA5String));
Assert.False(sanExtensionValue.HasData, "sanExtensionValue.HasData");
AsnReader basicConstraints = extensions.ReadSequence();
Assert.Equal("2.5.29.19", basicConstraints.ReadObjectIdentifierAsString());
Assert.True(basicConstraints.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> basicConstraintsBytes));
AsnReader basicConstraintsPayload = new AsnReader(basicConstraintsBytes, AsnEncodingRules.DER);
AsnReader basicConstraintsValue = basicConstraintsPayload.ReadSequence();
Assert.False(basicConstraintsValue.HasData, "basicConstraintsValue.HasData");
Assert.False(basicConstraintsPayload.HasData, "basicConstraintsPayload.HasData");
AsnReader keyUsageExtension = extensions.ReadSequence();
Assert.Equal("2.5.29.15", keyUsageExtension.ReadObjectIdentifierAsString());
Assert.True(keyUsageExtension.ReadBoolean(), "keyUsageExtension.ReadBoolean() (IsCritical)");
Assert.True(keyUsageExtension.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> keyUsageBytes));
AsnReader keyUsagePayload = new AsnReader(keyUsageBytes, AsnEncodingRules.DER);
Assert.Equal(
X509KeyUsageCSharpStyle.DigitalSignature | X509KeyUsageCSharpStyle.KeyEncipherment,
keyUsagePayload.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.False(keyUsagePayload.HasData, "keyUsagePayload.HasData");
AssertExtension(extensions, "2.5.29.37", false, 863, bytes);
AssertExtension(extensions, "2.5.29.32", false, 894, bytes);
AssertExtension(extensions, "2.5.29.35", false, 998, bytes);
AssertExtension(extensions, "2.5.29.31", false, 1031, bytes);
AssertExtension(extensions, "1.3.6.1.5.5.7.1.1", false, 1081, bytes);
Assert.False(extensions.HasData, "extensions.HasData");
Assert.Equal("1.2.840.113549.1.1.11", sigAlgReader.ReadObjectIdentifierAsString());
sigAlgReader.ReadNull();
Assert.False(sigAlgReader.HasData);
}
private static void AssertExtension(AsnReader extensions, string oid, bool critical, int index, byte[] bytes)
{
AsnReader extension = extensions.ReadSequence();
Assert.Equal(oid, extension.ReadObjectIdentifierAsString());
if (critical)
{
Assert.True(extension.ReadBoolean(), $"{oid} is critical");
}
Assert.True(extension.TryGetPrimitiveOctetStringBytes(out ReadOnlyMemory<byte> extensionBytes));
AssertRefSame(extensionBytes, ref bytes[index], $"{oid} extension value is at byte {index}");
}
private static void AssertRdn(
AsnReader reader,
string atvOid,
int offset,
Asn1Tag valueTag,
byte[] bytes,
string label,
string stringValue=null)
{
AsnReader rdn = reader.ReadSetOf();
AsnReader attributeTypeAndValue = rdn.ReadSequence();
Assert.Equal(atvOid, attributeTypeAndValue.ReadObjectIdentifierAsString());
ReadOnlyMemory<byte> value = attributeTypeAndValue.GetEncodedValue();
ReadOnlySpan<byte> valueSpan = value.Span;
Assert.True(Asn1Tag.TryParse(valueSpan, out Asn1Tag actualTag, out int bytesRead));
Assert.Equal(1, bytesRead);
Assert.Equal(valueTag, actualTag);
AssertRefSame(
ref MemoryMarshal.GetReference(valueSpan),
ref bytes[offset],
$"{label} is at bytes[{offset}]");
if (stringValue != null)
{
AsnReader valueReader = new AsnReader(value, AsnEncodingRules.DER);
Assert.Equal(stringValue, valueReader.GetCharacterString((UniversalTagNumber)valueTag.TagValue));
Assert.False(valueReader.HasData, "valueReader.HasData");
}
Assert.False(attributeTypeAndValue.HasData, $"attributeTypeAndValue.HasData ({label})");
Assert.False(rdn.HasData, $"rdn.HasData ({label})");
}
private static void AssertRefSame(ReadOnlyMemory<byte> a, ref byte b, string msg)
{
AssertRefSame(ref MemoryMarshal.GetReference(a.Span), ref b, msg);
}
private static void AssertRefSame(ref byte a, ref byte b, string msg)
{
Assert.True(Unsafe.AreSame(ref a, ref b), msg);
}
internal static readonly byte[] MicrosoftDotComSslCertBytes = (
"308205943082047CA00302010202103DF70C5D9903F8D8868B9B8CCF20DF6930" +
"0D06092A864886F70D01010B05003077310B3009060355040613025553311D30" +
"1B060355040A131453796D616E74656320436F72706F726174696F6E311F301D" +
"060355040B131653796D616E746563205472757374204E6574776F726B312830" +
"260603550403131F53796D616E74656320436C61737320332045562053534C20" +
"4341202D204733301E170D3134313031353030303030305A170D313631303135" +
"3233353935395A3082010F31133011060B2B0601040182373C02010313025553" +
"311B3019060B2B0601040182373C0201020C0A57617368696E67746F6E311D30" +
"1B060355040F131450726976617465204F7267616E697A6174696F6E31123010" +
"06035504051309363030343133343835310B3009060355040613025553310E30" +
"0C06035504110C0539383035323113301106035504080C0A57617368696E6774" +
"6F6E3110300E06035504070C075265646D6F6E643118301606035504090C0F31" +
"204D6963726F736F667420576179311E301C060355040A0C154D6963726F736F" +
"667420436F72706F726174696F6E310E300C060355040B0C054D53434F4D311A" +
"301806035504030C117777772E6D6963726F736F66742E636F6D30820122300D" +
"06092A864886F70D01010105000382010F003082010A0282010100A46861FA9D" +
"5DB763633BF5A64EF6E7C2C2367F48D2D46643A22DFCFCCB24E58A14D0F06BDC" +
"956437F2A56BA4BEF70BA361BF12964A0D665AFD84B0F7494C8FA4ABC5FCA2E0" +
"17C06178AEF2CDAD1B5F18E997A14B965C074E8F564970607276B00583932240" +
"FE6E2DD013026F9AE13D7C91CC07C4E1E8E87737DC06EF2B575B89D62EFE4685" +
"9F8255A123692A706C68122D4DAFE11CB205A7B3DE06E553F7B95F978EF8601A" +
"8DF819BF32040BDF92A0DE0DF269B4514282E17AC69934E8440A48AB9D1F5DF8" +
"9A502CEF6DFDBE790045BD45E0C94E5CA8ADD76A013E9C978440FC8A9E2A9A49" +
"40B2460819C3E302AA9C9F355AD754C86D3ED77DDAA3DA13810B4D0203010001" +
"A38201803082017C30310603551D11042A302882117777772E6D6963726F736F" +
"66742E636F6D821377777771612E6D6963726F736F66742E636F6D3009060355" +
"1D1304023000300E0603551D0F0101FF0404030205A0301D0603551D25041630" +
"1406082B0601050507030106082B0601050507030230660603551D20045F305D" +
"305B060B6086480186F84501071706304C302306082B06010505070201161768" +
"747470733A2F2F642E73796D63622E636F6D2F637073302506082B0601050507" +
"020230191A1768747470733A2F2F642E73796D63622E636F6D2F727061301F06" +
"03551D230418301680140159ABE7DD3A0B59A66463D6CF200757D591E76A302B" +
"0603551D1F042430223020A01EA01C861A687474703A2F2F73722E73796D6362" +
"2E636F6D2F73722E63726C305706082B06010505070101044B3049301F06082B" +
"060105050730018613687474703A2F2F73722E73796D63642E636F6D30260608" +
"2B06010505073002861A687474703A2F2F73722E73796D63622E636F6D2F7372" +
"2E637274300D06092A864886F70D01010B0500038201010015F8505B627ED7F9" +
"F96707097E93A51E7A7E05A3D420A5C258EC7A1CFE1843EC20ACF728AAFA7A1A" +
"1BC222A7CDBF4AF90AA26DEEB3909C0B3FB5C78070DAE3D645BFCF840A4A3FDD" +
"988C7B3308BFE4EB3FD66C45641E96CA3352DBE2AEB4488A64A9C5FB96932BA7" +
"0059CE92BD278B41299FD213471BD8165F924285AE3ECD666C703885DCA65D24" +
"DA66D3AFAE39968521995A4C398C7DF38DFA82A20372F13D4A56ADB21B582254" +
"9918015647B5F8AC131CC5EB24534D172BC60218A88B65BCF71C7F388CE3E0EF" +
"697B4203720483BB5794455B597D80D48CD3A1D73CBBC609C058767D1FF060A6" +
"09D7E3D4317079AF0CD0A8A49251AB129157F9894A036487").HexToByteArray();
}
}

View File

@@ -0,0 +1,160 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ParseTag : Asn1ReaderTests
{
[Theory]
[InlineData(PublicTagClass.Universal, false, 0, "00")]
[InlineData(PublicTagClass.Universal, false, 1, "01")]
[InlineData(PublicTagClass.Application, true, 1, "61")]
[InlineData(PublicTagClass.ContextSpecific, false, 1, "81")]
[InlineData(PublicTagClass.ContextSpecific, true, 1, "A1")]
[InlineData(PublicTagClass.Private, false, 1, "C1")]
[InlineData(PublicTagClass.Universal, false, 30, "1E")]
[InlineData(PublicTagClass.Application, false, 30, "5E")]
[InlineData(PublicTagClass.ContextSpecific, false, 30, "9E")]
[InlineData(PublicTagClass.Private, false, 30, "DE")]
[InlineData(PublicTagClass.Universal, false, 31, "1F1F")]
[InlineData(PublicTagClass.Application, false, 31, "5F1F")]
[InlineData(PublicTagClass.ContextSpecific, false, 31, "9F1F")]
[InlineData(PublicTagClass.Private, false, 31, "DF1F")]
[InlineData(PublicTagClass.Private, false, 127, "DF7F")]
[InlineData(PublicTagClass.Private, false, 128, "DF8100")]
[InlineData(PublicTagClass.Private, false, 253, "DF817D")]
[InlineData(PublicTagClass.Private, false, 255, "DF817F")]
[InlineData(PublicTagClass.Private, false, 256, "DF8200")]
[InlineData(PublicTagClass.Private, false, 1 << 9, "DF8400")]
[InlineData(PublicTagClass.Private, false, 1 << 10, "DF8800")]
[InlineData(PublicTagClass.Private, false, 0b0011_1101_1110_0111, "DFFB67")]
[InlineData(PublicTagClass.Private, false, 1 << 14, "DF818000")]
[InlineData(PublicTagClass.Private, false, 1 << 18, "DF908000")]
[InlineData(PublicTagClass.Private, false, 1 << 18 | 1 << 9, "DF908400")]
[InlineData(PublicTagClass.Private, false, 1 << 20, "DFC08000")]
[InlineData(PublicTagClass.Private, false, 0b0001_1110_1010_0111_0000_0001, "DFFACE01")]
[InlineData(PublicTagClass.Private, false, 1 << 21, "DF81808000")]
[InlineData(PublicTagClass.Private, false, 1 << 27, "DFC0808000")]
[InlineData(PublicTagClass.Private, false, 1 << 28, "DF8180808000")]
[InlineData(PublicTagClass.Private, true, int.MaxValue, "FF87FFFFFF7F")]
[InlineData(PublicTagClass.Universal, false, 119, "1F77")]
public static void ParseValidTag(
PublicTagClass tagClass,
bool isConstructed,
int tagValue,
string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
bool parsed = Asn1Tag.TryParse(inputBytes, out Asn1Tag tag, out int bytesRead);
Assert.True(parsed, "Asn1Tag.TryParse");
Assert.Equal(inputBytes.Length, bytesRead);
Assert.Equal((TagClass)tagClass, tag.TagClass);
Assert.Equal(tagValue, tag.TagValue);
if (isConstructed)
{
Assert.True(tag.IsConstructed, "tag.IsConstructed");
}
else
{
Assert.False(tag.IsConstructed, "tag.IsConstructed");
}
byte[] secondBytes = new byte[inputBytes.Length];
int written;
Assert.False(tag.TryWrite(secondBytes.AsSpan().Slice(0, inputBytes.Length - 1), out written));
Assert.Equal(0, written);
Assert.True(tag.TryWrite(secondBytes, out written));
Assert.Equal(inputBytes.Length, written);
Assert.Equal(inputHex, secondBytes.ByteArrayToHex());
}
[Theory]
[InlineData("Empty", "")]
[InlineData("MultiByte-NoFollow", "1F")]
[InlineData("MultiByte-NoFollow2", "1F81")]
[InlineData("MultiByte-NoFollow3", "1F8180")]
[InlineData("MultiByte-TooLow", "1F01")]
[InlineData("MultiByte-TooLowMax", "1F1E")]
[InlineData("MultiByte-Leading0", "1F807F")]
[InlineData("MultiByte-ValueTooBig", "FF8880808000")]
[InlineData("MultiByte-ValueSubtlyTooBig", "DFC1C0808000")]
public static void ParseCorruptTag(string description, string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
Assert.False(Asn1Tag.TryParse(inputBytes, out Asn1Tag tag, out var bytesRead));
Assert.Equal(default(Asn1Tag), tag);
Assert.Equal(0, bytesRead);
}
[Fact]
public static void TestEquals()
{
Asn1Tag integer = new Asn1Tag(TagClass.Universal, 2);
Asn1Tag integerAgain = new Asn1Tag(TagClass.Universal, 2);
Asn1Tag context2 = new Asn1Tag(TagClass.ContextSpecific, 2);
Asn1Tag constructedContext2 = new Asn1Tag(TagClass.ContextSpecific, 2, true);
Asn1Tag application2 = new Asn1Tag(TagClass.Application, 2);
Assert.False(integer.Equals(null));
Assert.False(integer.Equals(0x02));
Assert.False(integer.Equals(context2));
Assert.False(context2.Equals(constructedContext2));
Assert.False(context2.Equals(application2));
Assert.Equal(integer, integerAgain);
Assert.True(integer == integerAgain);
Assert.True(integer != context2);
Assert.False(integer == context2);
Assert.False(context2 == constructedContext2);
Assert.False(context2 == application2);
Assert.NotEqual(integer.GetHashCode(), context2.GetHashCode());
Assert.NotEqual(context2.GetHashCode(), constructedContext2.GetHashCode());
Assert.NotEqual(context2.GetHashCode(), application2.GetHashCode());
Assert.Equal(integer.GetHashCode(), integerAgain.GetHashCode());
}
[Theory]
[InlineData(PublicTagClass.Universal, false, 0, "00")]
[InlineData(PublicTagClass.ContextSpecific, true, 1, "A1")]
[InlineData(PublicTagClass.Application, false, 31, "5F1F")]
[InlineData(PublicTagClass.Private, false, 128, "DF8100")]
[InlineData(PublicTagClass.Private, false, 0b0001_1110_1010_0111_0000_0001, "DFFACE01")]
[InlineData(PublicTagClass.Private, true, int.MaxValue, "FF87FFFFFF7F")]
public static void ParseTagWithMoreData(
PublicTagClass tagClass,
bool isConstructed,
int tagValue,
string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
Array.Resize(ref inputBytes, inputBytes.Length + 3);
bool parsed = Asn1Tag.TryParse(inputBytes, out Asn1Tag tag, out int bytesRead);
Assert.True(parsed, "Asn1Tag.TryParse");
Assert.Equal(inputHex.Length / 2, bytesRead);
Assert.Equal((TagClass)tagClass, tag.TagClass);
Assert.Equal(tagValue, tag.TagValue);
if (isConstructed)
{
Assert.True(tag.IsConstructed, "tag.IsConstructed");
}
else
{
Assert.False(tag.IsConstructed, "tag.IsConstructed");
}
}
}
}

View File

@@ -0,0 +1,214 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class PeekTests : Asn1ReaderTests
{
[Fact]
public static void ReaderPeekTag_Valid()
{
// SEQUENCE(NULL)
byte[] data = { 0x30, 0x02, 0x05, 0x00 };
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
Asn1Tag tag = reader.PeekTag();
Assert.Equal((int)UniversalTagNumber.Sequence, tag.TagValue);
Assert.True(tag.IsConstructed, "tag.IsConstructed");
Assert.Equal(TagClass.Universal, tag.TagClass);
}
[Fact]
public static void ReaderPeekTag_Invalid()
{
// (UNIVERSAL [continue into next byte])
byte[] data = { 0x1F };
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
try
{
reader.PeekTag();
Assert.True(false, "CryptographicException was thrown");
}
catch (CryptographicException)
{
}
}
[Fact]
public static void PeekEncodedValue_Primitive()
{
const string EncodedContents = "010203040506";
const string EncodedValue = "0406" + EncodedContents;
byte[] data = (EncodedValue + "0500").HexToByteArray();
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
// It's Peek, so it's reproducible.
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
}
[Fact]
public static void PeekEncodedValue_Indefinite()
{
const string EncodedContents = "040101" + "04050203040506";
const string EncodedValue = "2480" + EncodedContents + "0000";
byte[] data = (EncodedValue + "0500").HexToByteArray();
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
// It's Peek, so it's reproducible.
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
}
[Fact]
public static void PeekEncodedValue_Corrupt_Throws()
{
const string EncodedContents = "040101" + "04050203040506";
// Constructed bit isn't set, so indefinite length is invalid.
const string EncodedValue = "0480" + EncodedContents + "0000";
byte[] data = (EncodedValue + "0500").HexToByteArray();
Assert.Throws<CryptographicException>(
() =>
{
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
reader.PeekEncodedValue();
});
}
[Fact]
public static void PeekContentSpan_Primitive()
{
const string EncodedContents = "010203040506";
const string EncodedValue = "0406" + EncodedContents;
byte[] data = (EncodedValue + "0500").HexToByteArray();
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
Assert.Equal(EncodedContents, reader.PeekContentBytes().ByteArrayToHex());
// It's Peek, so it's reproducible.
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
}
[Fact]
public static void PeekContentSpan_Indefinite()
{
const string EncodedContents = "040101" + "04050203040506";
const string EncodedValue = "2480" + EncodedContents + "0000";
byte[] data = (EncodedValue + "0500").HexToByteArray();
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
Assert.Equal(EncodedContents, reader.PeekContentBytes().ByteArrayToHex());
// It's Peek, so it's reproducible.
Assert.Equal(EncodedValue, reader.PeekEncodedValue().ByteArrayToHex());
}
[Fact]
public static void PeekContentSpan_Corrupt_Throws()
{
const string EncodedContents = "040101" + "04050203040506";
// Constructed bit isn't set, so indefinite length is invalid.
const string EncodedValue = "0480" + EncodedContents + "0000";
byte[] data = (EncodedValue + "0500").HexToByteArray();
Assert.Throws<CryptographicException>(
() =>
{
AsnReader reader = new AsnReader(data, AsnEncodingRules.BER);
reader.PeekContentBytes();
});
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public static void PeekContentSpan_ExtremelyNested(bool fullArray)
{
byte[] dataBytes = new byte[4 * 16384];
// For a full array this will build 2^14 nested indefinite length values.
// PeekContentBytes should return dataBytes.Slice(2, dataBytes.Length - 4)
//
// For what it's worth, the initial algorithm succeeded at 1650, and StackOverflowed with 1651.
//
// With the counter-and-no-recursion algorithm a nesting depth of 534773759 was verified,
// at a cost of 10 minutes of execution and a 2139095036 byte array.
// (The size was "a little bit less than int.MaxValue, since that OOMed my 32-bit process")
int end = dataBytes.Length / 2;
int expectedLength = dataBytes.Length - 4;
if (!fullArray)
{
// Use 3/4 of what's available, just to prove we're not counting from the end.
// So with "full" being a nesting value 16384 this will use 12288
end = end / 4 * 3;
expectedLength = 2 * end - 4;
}
for (int i = 0; i < end; i += 2)
{
// Context-Specific 0 [Constructed]
dataBytes[i] = 0xA0;
// Indefinite length
dataBytes[i + 1] = 0x80;
}
AsnReader reader = new AsnReader(dataBytes, AsnEncodingRules.BER);
ReadOnlyMemory<byte> contents = reader.PeekContentBytes();
Assert.Equal(expectedLength, contents.Length);
Assert.True(Unsafe.AreSame(ref dataBytes[2], ref MemoryMarshal.GetReference(contents.Span)));
}
[Theory]
[InlineData(false)]
[InlineData(true)]
public static void PeekEncodedValue_ExtremelyNested(bool fullArray)
{
byte[] dataBytes = new byte[4 * 16384];
// For a full array this will build 2^14 nested indefinite length values.
// PeekEncodedValue should return the whole array.
int end = dataBytes.Length / 2;
int expectedLength = dataBytes.Length;
if (!fullArray)
{
// Use 3/4 of what's available, just to prove we're not counting from the end.
// So with "full" being a nesting value 16384 this will use 12288, and
// PeekEncodedValue should give us back 48k, not 64k.
end = end / 4 * 3;
expectedLength = 2 * end;
}
for (int i = 0; i < end; i += 2)
{
// Context-Specific 0 [Constructed]
dataBytes[i] = 0xA0;
// Indefinite length
dataBytes[i + 1] = 0x80;
}
AsnReader reader = new AsnReader(dataBytes, AsnEncodingRules.BER);
ReadOnlyMemory<byte> contents = reader.PeekEncodedValue();
Assert.Equal(expectedLength, contents.Length);
Assert.True(Unsafe.AreSame(ref dataBytes[0], ref MemoryMarshal.GetReference(contents.Span)));
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,220 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadBoolean : Asn1ReaderTests
{
[Theory]
[InlineData(PublicEncodingRules.BER, false, 3, "010100")]
[InlineData(PublicEncodingRules.BER, true, 3, "010101")]
// Padded length
[InlineData(PublicEncodingRules.BER, true, 4, "01810101")]
[InlineData(PublicEncodingRules.BER, true, 3, "0101FF0500")]
[InlineData(PublicEncodingRules.CER, false, 3, "0101000500")]
[InlineData(PublicEncodingRules.CER, true, 3, "0101FF")]
[InlineData(PublicEncodingRules.DER, false, 3, "010100")]
[InlineData(PublicEncodingRules.DER, true, 3, "0101FF0500")]
// Context Specific 0
[InlineData(PublicEncodingRules.DER, true, 3, "8001FF0500")]
// Application 31
[InlineData(PublicEncodingRules.DER, true, 4, "5F1F01FF0500")]
// Private 253
[InlineData(PublicEncodingRules.CER, false, 5, "DF817D01000500")]
public static void ReadBoolean_Success(
PublicEncodingRules ruleSet,
bool expectedValue,
int expectedBytesRead,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Asn1Tag tag = reader.PeekTag();
bool value;
if (tag.TagClass == TagClass.Universal)
{
value = reader.ReadBoolean();
}
else
{
value = reader.ReadBoolean(tag);
}
if (inputData.Length == expectedBytesRead)
{
Assert.False(reader.HasData, "reader.HasData");
}
else
{
Assert.True(reader.HasData, "reader.HasData");
}
if (expectedValue)
{
Assert.True(value, "value");
}
else
{
Assert.False(value, "value");
}
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal(PublicEncodingRules ruleSet)
{
byte[] inputData = { 1, 1, 0 };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadBoolean(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadBoolean(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
bool value = reader.ReadBoolean();
Assert.False(value, "value");
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom(PublicEncodingRules ruleSet)
{
byte[] inputData = { 0x80, 1, 0xFF };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadBoolean(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadBoolean());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(() => reader.ReadBoolean(new Asn1Tag(TagClass.Application, 0)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(() => reader.ReadBoolean(new Asn1Tag(TagClass.ContextSpecific, 1)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
bool value = reader.ReadBoolean(new Asn1Tag(TagClass.ContextSpecific, 0));
Assert.True(value, "value");
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "0101FF", PublicTagClass.Universal, 1)]
[InlineData(PublicEncodingRules.CER, "0101FF", PublicTagClass.Universal, 1)]
[InlineData(PublicEncodingRules.DER, "0101FF", PublicTagClass.Universal, 1)]
[InlineData(PublicEncodingRules.BER, "8001FF", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.CER, "4C01FF", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "DF8A4601FF", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
bool val1 = reader.ReadBoolean(new Asn1Tag((TagClass)tagClass, tagValue, true));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
bool val2 = reader.ReadBoolean(new Asn1Tag((TagClass)tagClass, tagValue, false));
Assert.False(reader.HasData);
Assert.Equal(val1, val2);
}
[Theory]
[InlineData("Empty", PublicEncodingRules.DER, "")]
[InlineData("Empty", PublicEncodingRules.CER, "")]
[InlineData("Empty", PublicEncodingRules.BER, "")]
[InlineData("TagOnly", PublicEncodingRules.BER, "01")]
[InlineData("TagOnly", PublicEncodingRules.CER, "01")]
[InlineData("TagOnly", PublicEncodingRules.DER, "01")]
[InlineData("MultiByte TagOnly", PublicEncodingRules.DER, "9F1F")]
[InlineData("MultiByte TagOnly", PublicEncodingRules.CER, "9F1F")]
[InlineData("MultiByte TagOnly", PublicEncodingRules.BER, "9F1F")]
[InlineData("TagAndLength", PublicEncodingRules.BER, "0101")]
[InlineData("Tag and MultiByteLength", PublicEncodingRules.BER, "01820001")]
[InlineData("TagAndLength", PublicEncodingRules.CER, "8001")]
[InlineData("TagAndLength", PublicEncodingRules.DER, "C001")]
[InlineData("MultiByteTagAndLength", PublicEncodingRules.DER, "9F2001")]
[InlineData("MultiByteTagAndLength", PublicEncodingRules.CER, "9F2001")]
[InlineData("MultiByteTagAndLength", PublicEncodingRules.BER, "9F2001")]
[InlineData("MultiByteTagAndMultiByteLength", PublicEncodingRules.BER, "9F28200001")]
[InlineData("TooShort", PublicEncodingRules.BER, "0100")]
[InlineData("TooShort", PublicEncodingRules.CER, "8000")]
[InlineData("TooShort", PublicEncodingRules.DER, "0100")]
[InlineData("TooLong", PublicEncodingRules.DER, "C0020000")]
[InlineData("TooLong", PublicEncodingRules.CER, "01020000")]
[InlineData("TooLong", PublicEncodingRules.BER, "C081020000")]
[InlineData("MissingContents", PublicEncodingRules.BER, "C001")]
[InlineData("MissingContents", PublicEncodingRules.CER, "0101")]
[InlineData("MissingContents", PublicEncodingRules.DER, "8001")]
[InlineData("NonCanonical", PublicEncodingRules.DER, "0101FE")]
[InlineData("NonCanonical", PublicEncodingRules.CER, "800101")]
[InlineData("Constructed", PublicEncodingRules.BER, "2103010101")]
[InlineData("Constructed", PublicEncodingRules.CER, "2103010101")]
[InlineData("Constructed", PublicEncodingRules.DER, "2103010101")]
[InlineData("WrongTag", PublicEncodingRules.DER, "0400")]
[InlineData("WrongTag", PublicEncodingRules.CER, "0400")]
[InlineData("WrongTag", PublicEncodingRules.BER, "0400")]
public static void ReadBoolean_Failure(
string description,
PublicEncodingRules ruleSet,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Asn1Tag tag = default(Asn1Tag);
if (inputData.Length > 0)
{
tag = reader.PeekTag();
}
if (tag.TagClass == TagClass.Universal)
{
Assert.Throws<CryptographicException>(() => reader.ReadBoolean());
}
else
{
Assert.Throws<CryptographicException>(() => reader.ReadBoolean(tag));
}
if (inputData.Length == 0)
{
// If we started with nothing, where did the data come from?
Assert.False(reader.HasData, "reader.HasData");
}
else
{
// Nothing should have moved
Assert.True(reader.HasData, "reader.HasData");
}
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,162 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadLength : Asn1ReaderTests
{
[Theory]
[InlineData(4, 0, "0400")]
[InlineData(1, 1, "0101")]
[InlineData(4, 127, "047F")]
[InlineData(4, 128, "048180")]
[InlineData(4, 255, "0481FF")]
[InlineData(2, 256, "02820100")]
[InlineData(4, int.MaxValue, "04847FFFFFFF")]
public static void MinimalPrimitiveLength(int tagValue, int length, string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
foreach (PublicEncodingRules rules in Enum.GetValues(typeof(PublicEncodingRules)))
{
AsnReader reader = new AsnReader(inputBytes, (AsnEncodingRules)rules);
Asn1Tag tag = reader.ReadTagAndLength(out int ? parsedLength, out int bytesRead);
Assert.Equal(inputBytes.Length, bytesRead);
Assert.False(tag.IsConstructed, "tag.IsConstructed");
Assert.Equal(tagValue, tag.TagValue);
Assert.Equal(length, parsedLength.Value);
// ReadTagAndLength doesn't move the _data span forward.
Assert.True(reader.HasData, "reader.HasData");
}
}
[Theory]
[InlineData(-1)]
[InlineData(3)]
public static void ReadWithUnknownRuleSet(int invalidRuleSetValue)
{
byte[] data = { 0x05, 0x00 };
Assert.Throws<ArgumentOutOfRangeException>(
() => new AsnReader(data, (AsnEncodingRules)invalidRuleSetValue));
}
[Theory]
[InlineData("")]
[InlineData("05")]
[InlineData("0481")]
[InlineData("048201")]
[InlineData("04830102")]
[InlineData("0484010203")]
public static void ReadWithInsufficientData(string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, AsnEncodingRules.DER);
Assert.Throws<CryptographicException>(() => reader.ReadTagAndLength(out _, out _));
}
[Theory]
[InlineData("DER indefinite constructed", PublicEncodingRules.DER, "3080" + "0500" + "0000")]
[InlineData("0xFF-BER", PublicEncodingRules.BER, "04FF")]
[InlineData("0xFF-CER", PublicEncodingRules.CER, "04FF")]
[InlineData("0xFF-DER", PublicEncodingRules.DER, "04FF")]
[InlineData("CER definite constructed", PublicEncodingRules.CER, "30820500")]
[InlineData("BER indefinite primitive", PublicEncodingRules.BER, "0480" + "0000")]
[InlineData("CER indefinite primitive", PublicEncodingRules.CER, "0480" + "0000")]
[InlineData("DER indefinite primitive", PublicEncodingRules.DER, "0480" + "0000")]
[InlineData("DER non-minimal 0", PublicEncodingRules.DER, "048100")]
[InlineData("DER non-minimal 7F", PublicEncodingRules.DER, "04817F")]
[InlineData("DER non-minimal 80", PublicEncodingRules.DER, "04820080")]
[InlineData("CER non-minimal 0", PublicEncodingRules.CER, "048100")]
[InlineData("CER non-minimal 7F", PublicEncodingRules.CER, "04817F")]
[InlineData("CER non-minimal 80", PublicEncodingRules.CER, "04820080")]
[InlineData("BER too large", PublicEncodingRules.BER, "048480000000")]
[InlineData("CER too large", PublicEncodingRules.CER, "048480000000")]
[InlineData("DER too large", PublicEncodingRules.DER, "048480000000")]
[InlineData("BER padded too large", PublicEncodingRules.BER, "0486000080000000")]
[InlineData("BER uint.MaxValue", PublicEncodingRules.BER, "0484FFFFFFFF")]
[InlineData("CER uint.MaxValue", PublicEncodingRules.CER, "0484FFFFFFFF")]
[InlineData("DER uint.MaxValue", PublicEncodingRules.DER, "0484FFFFFFFF")]
[InlineData("BER padded uint.MaxValue", PublicEncodingRules.BER, "048800000000FFFFFFFF")]
[InlineData("BER 5 byte spread", PublicEncodingRules.BER, "04850100000000")]
[InlineData("CER 5 byte spread", PublicEncodingRules.CER, "04850100000000")]
[InlineData("DER 5 byte spread", PublicEncodingRules.DER, "04850100000000")]
[InlineData("BER padded 5 byte spread", PublicEncodingRules.BER, "0486000100000000")]
public static void InvalidLengths(
string description,
PublicEncodingRules rules,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)rules);
Assert.Throws<CryptographicException>(() => reader.ReadTagAndLength(out _, out _));
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void IndefiniteLength(PublicEncodingRules ruleSet)
{
// SEQUENCE (indefinite)
// NULL
// End-of-Contents
byte[] data = { 0x30, 0x80, 0x05, 0x00, 0x00, 0x00 };
AsnReader reader = new AsnReader(data, (AsnEncodingRules)ruleSet);
Asn1Tag tag = reader.ReadTagAndLength(out int? length, out int bytesRead);
Assert.Equal(2, bytesRead);
Assert.False(length.HasValue, "length.HasValue");
Assert.Equal((int)UniversalTagNumber.Sequence, tag.TagValue);
Assert.True(tag.IsConstructed, "tag.IsConstructed");
}
[Theory]
[InlineData(0, "0483000000")]
[InlineData(1, "048A00000000000000000001")]
[InlineData(128, "049000000000000000000000000000000080")]
public static void BerNonMinimalLength(int expectedLength, string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, AsnEncodingRules.BER);
Asn1Tag tag = reader.ReadTagAndLength(out int? length, out int bytesRead);
Assert.Equal(inputData.Length, bytesRead);
Assert.Equal(expectedLength, length.Value);
// ReadTagAndLength doesn't move the _data span forward.
Assert.True(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData(PublicEncodingRules.BER, 4, 0, 5, "0483000000" + "0500")]
[InlineData(PublicEncodingRules.DER, 1, 1, 2, "0101" + "FF")]
[InlineData(PublicEncodingRules.CER, 0x10, null, 2, "3080" + "0500" + "0000")]
public static void ReadWithDataRemaining(
PublicEncodingRules ruleSet,
int tagValue,
int? expectedLength,
int expectedBytesRead,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Asn1Tag tag = reader.ReadTagAndLength(out int? length, out int bytesRead);
Assert.Equal(expectedBytesRead, bytesRead);
Assert.Equal(tagValue, tag.TagValue);
Assert.Equal(expectedLength, length);
}
}
}

View File

@@ -0,0 +1,315 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadNamedBitList : Asn1ReaderTests
{
[Flags]
public enum X509KeyUsageCSharpStyle
{
None = 0,
DigitalSignature = 1,
NonRepudiation = 1 << 1,
KeyEncipherment = 1 << 2,
DataEncipherment = 1 << 3,
KeyAgreement = 1 << 4,
KeyCertSign = 1 << 5,
CrlSign = 1 << 6,
EncipherOnly = 1 << 7,
DecipherOnly = 1 << 8,
}
[Flags]
public enum ULongFlags : ulong
{
None = 0,
Min = 1,
Mid = 1L << 32,
AlmostMax = 1L << 62,
Max = 1UL << 63,
}
[Flags]
public enum LongFlags : long
{
None = 0,
Mid = 1L << 32,
Max = 1L << 62,
Min = long.MinValue,
}
[Theory]
[InlineData(
PublicEncodingRules.BER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.None,
"030100")]
[InlineData(
PublicEncodingRules.CER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.DecipherOnly | X509KeyUsageCSharpStyle.KeyCertSign,
"0303070480")]
[InlineData(
PublicEncodingRules.DER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.KeyAgreement,
"03020308")]
[InlineData(
PublicEncodingRules.BER,
typeof(LongFlags),
LongFlags.Mid | LongFlags.Max,
"0309010000000080000002")]
[InlineData(
PublicEncodingRules.CER,
typeof(LongFlags),
LongFlags.Mid | LongFlags.Min,
"0309000000000080000001")]
[InlineData(
PublicEncodingRules.DER,
typeof(LongFlags),
LongFlags.Min | LongFlags.Max,
"0309000000000000000003")]
// BER: Unused bits are unmapped, regardless of value.
[InlineData(
PublicEncodingRules.BER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.DecipherOnly | X509KeyUsageCSharpStyle.KeyCertSign,
"030307048F")]
// BER: Trailing zeros are permitted.
[InlineData(
PublicEncodingRules.BER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.DecipherOnly | X509KeyUsageCSharpStyle.KeyCertSign | X509KeyUsageCSharpStyle.DataEncipherment,
"03050014800000")]
// BER: Trailing 0-bits don't have to be declared "unused"
[InlineData(
PublicEncodingRules.BER,
typeof(X509KeyUsageCSharpStyle),
X509KeyUsageCSharpStyle.DecipherOnly | X509KeyUsageCSharpStyle.KeyCertSign | X509KeyUsageCSharpStyle.DataEncipherment,
"0303001480")]
public static void VerifyReadNamedBitListEncodings(
PublicEncodingRules ruleSet,
Type enumType,
long enumValue,
string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputBytes, (AsnEncodingRules)ruleSet);
Enum readValue = reader.GetNamedBitListValue(enumType);
Assert.Equal(Enum.ToObject(enumType, enumValue), readValue);
}
[Theory]
[InlineData(
PublicEncodingRules.BER,
typeof(ULongFlags),
ULongFlags.Mid | ULongFlags.Max,
"0309000000000080000001")]
[InlineData(
PublicEncodingRules.CER,
typeof(ULongFlags),
ULongFlags.Min | ULongFlags.Mid,
"0306078000000080")]
[InlineData(
PublicEncodingRules.DER,
typeof(ULongFlags),
ULongFlags.Min | ULongFlags.Max,
"0309008000000000000001")]
public static void VerifyReadNamedBitListEncodings_ULong(
PublicEncodingRules ruleSet,
Type enumType,
ulong enumValue,
string inputHex)
{
byte[] inputBytes = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputBytes, (AsnEncodingRules)ruleSet);
Enum readValue = reader.GetNamedBitListValue(enumType);
Assert.Equal(Enum.ToObject(enumType, enumValue), readValue);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void VerifyGenericReadNamedBitList(PublicEncodingRules ruleSet)
{
string inputHex = "0306078000000080" + "0309010000000080000002";
AsnReader reader = new AsnReader(inputHex.HexToByteArray(), (AsnEncodingRules)ruleSet);
ULongFlags uLongFlags = reader.GetNamedBitListValue<ULongFlags>();
LongFlags longFlags = reader.GetNamedBitListValue<LongFlags>();
Assert.False(reader.HasData);
Assert.Equal(ULongFlags.Mid | ULongFlags.Min, uLongFlags);
Assert.Equal(LongFlags.Mid | LongFlags.Max, longFlags);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadNamedBitList_RequiresFlags(PublicEncodingRules ruleSet)
{
string inputHex = "030100";
AsnReader reader = new AsnReader(inputHex.HexToByteArray(), (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"tFlagsEnum",
() => reader.GetNamedBitListValue<AsnEncodingRules>());
Assert.True(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadNamedBitList_DataOutOfRange(PublicEncodingRules ruleSet)
{
string inputHex = "0309000000000100000001";
AsnReader reader = new AsnReader(inputHex.HexToByteArray(), (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.True(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadNamedBitList_ExcessiveBytes(PublicEncodingRules ruleSet)
{
string inputHex = "03050014800000";
AsnReader reader = new AsnReader(inputHex.HexToByteArray(), (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.True(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadNamedBitList_ExcessiveBits(PublicEncodingRules ruleSet)
{
string inputHex = "0303061480";
AsnReader reader = new AsnReader(inputHex.HexToByteArray(), (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.True(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal(PublicEncodingRules ruleSet)
{
byte[] inputData = { 3, 2, 1, 2 };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
Assert.Equal(
X509KeyUsageCSharpStyle.CrlSign,
reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom(PublicEncodingRules ruleSet)
{
byte[] inputData = { 0x87, 2, 2, 4 };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(new Asn1Tag(TagClass.Application, 0)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(new Asn1Tag(TagClass.ContextSpecific, 1)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
Assert.Equal(
X509KeyUsageCSharpStyle.KeyCertSign,
reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "0303070080", PublicTagClass.Universal, 3)]
[InlineData(PublicEncodingRules.CER, "0303070080", PublicTagClass.Universal, 3)]
[InlineData(PublicEncodingRules.DER, "0303070080", PublicTagClass.Universal, 3)]
[InlineData(PublicEncodingRules.BER, "8003070080", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.CER, "4C03070080", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "DF8A4603070080", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Equal(
X509KeyUsageCSharpStyle.DecipherOnly,
reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(
new Asn1Tag((TagClass)tagClass, tagValue, true)));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Equal(
X509KeyUsageCSharpStyle.DecipherOnly,
reader.GetNamedBitListValue<X509KeyUsageCSharpStyle>(
new Asn1Tag((TagClass)tagClass, tagValue, false)));
Assert.False(reader.HasData);
}
}
}

View File

@@ -0,0 +1,130 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadNull : Asn1ReaderTests
{
[Theory]
[InlineData(PublicEncodingRules.BER, "0500")]
[InlineData(PublicEncodingRules.CER, "0500")]
[InlineData(PublicEncodingRules.DER, "0500")]
[InlineData(PublicEncodingRules.BER, "0583000000")]
public static void ReadNull_Success(PublicEncodingRules ruleSet, string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
reader.ReadNull();
Assert.False(reader.HasData, "reader.HasData");
}
[Theory]
[InlineData("Long length", PublicEncodingRules.CER, "0583000000")]
[InlineData("Long length", PublicEncodingRules.DER, "0583000000")]
[InlineData("Constructed definite length", PublicEncodingRules.BER, "2500")]
[InlineData("Constructed definite length", PublicEncodingRules.DER, "2500")]
[InlineData("Constructed indefinite length", PublicEncodingRules.BER, "25800000")]
[InlineData("Constructed indefinite length", PublicEncodingRules.CER, "25800000")]
[InlineData("No length", PublicEncodingRules.BER, "05")]
[InlineData("No length", PublicEncodingRules.CER, "05")]
[InlineData("No length", PublicEncodingRules.DER, "05")]
[InlineData("No data", PublicEncodingRules.BER, "")]
[InlineData("No data", PublicEncodingRules.CER, "")]
[InlineData("No data", PublicEncodingRules.DER, "")]
[InlineData("NonEmpty", PublicEncodingRules.BER, "050100")]
[InlineData("NonEmpty", PublicEncodingRules.CER, "050100")]
[InlineData("NonEmpty", PublicEncodingRules.DER, "050100")]
[InlineData("Incomplete length", PublicEncodingRules.BER, "0581")]
public static void ReadNull_Throws(string description, PublicEncodingRules ruleSet, string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(() => reader.ReadNull());
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal(PublicEncodingRules ruleSet)
{
byte[] inputData = { 5, 0 };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadNull(new Asn1Tag(UniversalTagNumber.Integer)));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadNull(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
reader.ReadNull();
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom(PublicEncodingRules ruleSet)
{
byte[] inputData = { 0x87, 0 };
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadNull(new Asn1Tag(UniversalTagNumber.Integer)));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadNull());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(() => reader.ReadNull(new Asn1Tag(TagClass.Application, 0)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(() => reader.ReadNull(new Asn1Tag(TagClass.ContextSpecific, 1)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
reader.ReadNull(new Asn1Tag(TagClass.ContextSpecific, 7));
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "0500", PublicTagClass.Universal, 5)]
[InlineData(PublicEncodingRules.CER, "0500", PublicTagClass.Universal, 5)]
[InlineData(PublicEncodingRules.DER, "0500", PublicTagClass.Universal, 5)]
[InlineData(PublicEncodingRules.BER, "8000", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.CER, "4C00", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "DF8A4600", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
reader.ReadNull(new Asn1Tag((TagClass)tagClass, tagValue, true));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
reader.ReadNull(new Asn1Tag((TagClass)tagClass, tagValue, false));
Assert.False(reader.HasData);
}
}
}

View File

@@ -0,0 +1,286 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using System.Text;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadObjectIdentifier : Asn1ReaderTests
{
[Theory]
[InlineData("Wrong tag", PublicEncodingRules.BER, "010100")]
[InlineData("Wrong tag", PublicEncodingRules.CER, "010100")]
[InlineData("Wrong tag", PublicEncodingRules.DER, "010100")]
[InlineData("Overreaching length", PublicEncodingRules.BER, "0608883703")]
[InlineData("Overreaching length", PublicEncodingRules.CER, "0608883703")]
[InlineData("Overreaching length", PublicEncodingRules.DER, "0608883703")]
[InlineData("Zero length", PublicEncodingRules.BER, "0600")]
[InlineData("Zero length", PublicEncodingRules.CER, "0600")]
[InlineData("Zero length", PublicEncodingRules.DER, "0600")]
[InlineData("Constructed Definite Form", PublicEncodingRules.BER, "2605" + "0603883703")]
[InlineData("Constructed Indefinite Form", PublicEncodingRules.BER, "2680" + "0603883703" + "0000")]
[InlineData("Constructed Indefinite Form", PublicEncodingRules.CER, "2680" + "0603883703" + "0000")]
[InlineData("Unresolved carry-bit (first sub-identifier)", PublicEncodingRules.BER, "060188")]
[InlineData("Unresolved carry-bit (first sub-identifier)", PublicEncodingRules.CER, "060188")]
[InlineData("Unresolved carry-bit (first sub-identifier)", PublicEncodingRules.DER, "060188")]
[InlineData("Unresolved carry-bit (later sub-identifier)", PublicEncodingRules.BER, "0603883781")]
[InlineData("Unresolved carry-bit (later sub-identifier)", PublicEncodingRules.CER, "0603883781")]
[InlineData("Unresolved carry-bit (later sub-identifier)", PublicEncodingRules.DER, "0603883781")]
[InlineData("Sub-Identifier with leading 0x80", PublicEncodingRules.BER, "060488378001")]
[InlineData("Sub-Identifier with leading 0x80", PublicEncodingRules.CER, "060488378001")]
[InlineData("Sub-Identifier with leading 0x80", PublicEncodingRules.DER, "060488378001")]
public static void ReadObjectIdentifier_Throws(
string description,
PublicEncodingRules ruleSet,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(() => reader.ReadObjectIdentifier(true));
}
[Theory]
[InlineData(PublicEncodingRules.BER, "0603883703", "2.999.3")]
[InlineData(PublicEncodingRules.CER, "06028837", "2.999")]
[InlineData(PublicEncodingRules.DER, "06068837C27B0302", "2.999.8571.3.2")]
[InlineData(PublicEncodingRules.BER, "0603550406", "2.5.4.6")]
[InlineData(PublicEncodingRules.CER, "06092A864886F70D010105", "1.2.840.113549.1.1.5")]
[InlineData(PublicEncodingRules.DER, "060100", "0.0")]
[InlineData(PublicEncodingRules.BER, "06080992268993F22C63", "0.9.2342.19200300.99")]
[InlineData(
PublicEncodingRules.DER,
"0616824F83F09DA7EBCFDEE0C7A1A7B2C0948CC8F9D77603",
// Using the rules of ITU-T-REC-X.667-201210 for 2.25.{UUID} unregistered arcs, and
// their sample value of f81d4fae-7dec-11d0-a765-00a0c91e6bf6
// this is
// { joint-iso-itu-t(2) uuid(255) thatuuid(329800735698586629295641978511506172918) three(3) }
"2.255.329800735698586629295641978511506172918.3")]
public static void ReadObjectIdentifierAsString_Success(
PublicEncodingRules ruleSet,
string inputHex,
string expectedValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
string oidValue = reader.ReadObjectIdentifierAsString();
Assert.Equal(expectedValue, oidValue);
}
[Theory]
// Start at a UUID as a big integer. 128 semantic bits takes 19
// content bytes to write down. Walk it backwards to 1.
// This uses the OID from the last case of ReadObjectIdentifierAsString_Success, but
// without the "255" arc (therefore the initial second arc is the UUID decimal value - 80)
[InlineData("061383F09DA7EBCFDEE0C7A1A7B2C0948CC8F9D776", "2.329800735698586629295641978511506172838")]
// Drop the last byte, clear the high bit in the last remaining byte, secondArc = (secondArc + 80) >> 7 - 80.
[InlineData("061283F09DA7EBCFDEE0C7A1A7B2C0948CC8F957", "2.2576568247645208041372202957121141895")]
[InlineData("061183F09DA7EBCFDEE0C7A1A7B2C0948CC879", "2.20129439434728187823220335602508841")]
[InlineData("061083F09DA7EBCFDEE0C7A1A7B2C0948C48", "2.157261245583813967368908871894520")]
[InlineData("060F83F09DA7EBCFDEE0C7A1A7B2C0940C", "2.1228603481123546620069600561596")]
[InlineData("060E83F09DA7EBCFDEE0C7A1A7B2C014", "2.9598464696277707969293754308")]
[InlineData("060D83F09DA7EBCFDEE0C7A1A7B240", "2.74988005439669593510107376")]
[InlineData("060C83F09DA7EBCFDEE0C7A1A732", "2.585843792497418699297634")]
[InlineData("060B83F09DA7EBCFDEE0C7A127", "2.4576904628886083588183")]
[InlineData("060A83F09DA7EBCFDEE0C721", "2.35757067413172527953")]
[InlineData("060983F09DA7EBCFDEE047", "2.279352089165410295")]
[InlineData("060883F09DA7EBCFDE60", "2.2182438196604688")]
[InlineData("060783F09DA7EBCF5E", "2.17050298410894")]
[InlineData("060683F09DA7EB4F", "2.133205456255")]
[InlineData("060583F09DA76B", "2.1040667547")]
[InlineData("060483F09D27", "2.8130135")]
[InlineData("060383F01D", "2.63437")]
[InlineData("06028370", "2.416")]
[InlineData("060103", "0.3")]
public static void VerifyMultiByteParsing(string inputHex, string expectedValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, AsnEncodingRules.DER);
string oidValue = reader.ReadObjectIdentifierAsString();
Assert.Equal(expectedValue, oidValue);
}
[Theory]
[InlineData(PublicEncodingRules.BER, "06082A864886F70D0307", false, "3des")]
[InlineData(PublicEncodingRules.CER, "06082A864886F70D0307", true, "1.2.840.113549.3.7")]
[InlineData(PublicEncodingRules.DER, "0609608648016503040201", true, "2.16.840.1.101.3.4.2.1")]
[InlineData(PublicEncodingRules.BER, "0609608648016503040201", false, "sha256")]
public static void ReadObjectIdentifier_SkipFriendlyName(
PublicEncodingRules ruleSet,
string inputHex,
bool skipFriendlyName,
string expectedFriendlyName)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Oid oid = reader.ReadObjectIdentifier(skipFriendlyName);
Assert.Equal(expectedFriendlyName, oid.FriendlyName);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal(PublicEncodingRules ruleSet)
{
byte[] inputData = "06028837".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.GetIntegerBytes(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.ReadObjectIdentifierAsString(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
Assert.Equal("2.999", reader.ReadObjectIdentifierAsString());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom(PublicEncodingRules ruleSet)
{
byte[] inputData = "87028837".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.GetIntegerBytes(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadObjectIdentifierAsString());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.ReadObjectIdentifierAsString(new Asn1Tag(TagClass.Application, 0)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.ReadObjectIdentifierAsString(new Asn1Tag(TagClass.ContextSpecific, 1)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
Assert.Equal(
"2.999",
reader.ReadObjectIdentifierAsString(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "06028837", PublicTagClass.Universal, 6)]
[InlineData(PublicEncodingRules.CER, "06028837", PublicTagClass.Universal, 6)]
[InlineData(PublicEncodingRules.DER, "06028837", PublicTagClass.Universal, 6)]
[InlineData(PublicEncodingRules.BER, "80028837", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.CER, "4C028837", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "DF8A46028837", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
string val1 = reader.ReadObjectIdentifierAsString(new Asn1Tag((TagClass)tagClass, tagValue, true));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
string val2 = reader.ReadObjectIdentifierAsString(new Asn1Tag((TagClass)tagClass, tagValue, false));
Assert.False(reader.HasData);
Assert.Equal(val1, val2);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadVeryLongOid(PublicEncodingRules ruleSet)
{
byte[] inputData = new byte[100000];
// 06 83 02 00 00 (OBJECT IDENTIFIER, 65536 bytes).
inputData[0] = 0x06;
inputData[1] = 0x83;
inputData[2] = 0x01;
inputData[3] = 0x00;
inputData[4] = 0x00;
// and the rest are all zero.
// The first byte produces "0.0". Each of the remaining 65535 bytes produce
// another ".0".
const int ExpectedLength = 65536 * 2 + 1;
StringBuilder builder = new StringBuilder(ExpectedLength);
builder.Append('0');
for (int i = 0; i <= ushort.MaxValue; i++)
{
builder.Append('.');
builder.Append(0);
}
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
string oidString = reader.ReadObjectIdentifierAsString();
Assert.Equal(ExpectedLength, oidString.Length);
Assert.Equal(builder.ToString(), oidString);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadVeryLongOidArc(PublicEncodingRules ruleSet)
{
byte[] inputData = new byte[255];
// 06 81 93 (OBJECT IDENTIFIER, 147 bytes).
inputData[0] = 0x06;
inputData[1] = 0x81;
inputData[2] = 0x93;
// With 147 bytes we get 147*7 = 1029 value bits.
// The smallest legal number to encode would have a top byte of 0x81,
// leaving 1022 bits remaining. If they're all zero then we have 2^1022.
//
// Since it's our first sub-identifier it's really encoding "2.(2^1022 - 80)".
inputData[3] = 0x81;
// Leave the last byte as 0.
new Span<byte>(inputData, 4, 145).Fill(0x80);
const string ExpectedOid =
"2." +
"449423283715578976932326297697256183404494244735576643183575" +
"202894331689513752407831771193306018840052800284699678483394" +
"146974422036041556232118576598685310944419733562163713190755" +
"549003115235298632707380212514422095376705856157203684782776" +
"352068092908376276711465745599868114846199290762088390824060" +
"56034224";
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
string oidString = reader.ReadObjectIdentifierAsString();
Assert.Equal(ExpectedOid, oidString);
}
}
}

View File

@@ -0,0 +1,338 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadSequence : Asn1ReaderTests
{
[Theory]
[InlineData(PublicEncodingRules.BER, "3000", false, -1)]
[InlineData(PublicEncodingRules.BER, "30800000", false, -1)]
[InlineData(PublicEncodingRules.BER, "3083000000", false, -1)]
[InlineData(PublicEncodingRules.CER, "30800000", false, -1)]
[InlineData(PublicEncodingRules.DER, "3000", false, -1)]
[InlineData(PublicEncodingRules.BER, "3000" + "0500", true, -1)]
[InlineData(PublicEncodingRules.BER, "3002" + "0500", false, 5)]
[InlineData(PublicEncodingRules.CER, "3080" + "0500" + "0000", false, 5)]
[InlineData(PublicEncodingRules.CER, "3080" + "010100" + "0000" + "0500", true, 1)]
[InlineData(PublicEncodingRules.DER, "3005" + "0500" + "0101FF", false, 5)]
public static void ReadSequence_Success(
PublicEncodingRules ruleSet,
string inputHex,
bool expectDataRemaining,
int expectedSequenceTagNumber)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader sequence = reader.ReadSequence();
if (expectDataRemaining)
{
Assert.True(reader.HasData, "reader.HasData");
}
else
{
Assert.False(reader.HasData, "reader.HasData");
}
if (expectedSequenceTagNumber < 0)
{
Assert.False(sequence.HasData, "sequence.HasData");
}
else
{
Assert.True(sequence.HasData, "sequence.HasData");
Asn1Tag firstTag = sequence.PeekTag();
Assert.Equal(expectedSequenceTagNumber, firstTag.TagValue);
}
}
[Theory]
[InlineData("Empty", PublicEncodingRules.BER, "")]
[InlineData("Empty", PublicEncodingRules.CER, "")]
[InlineData("Empty", PublicEncodingRules.DER, "")]
[InlineData("Incomplete Tag", PublicEncodingRules.BER, "1F")]
[InlineData("Incomplete Tag", PublicEncodingRules.CER, "1F")]
[InlineData("Incomplete Tag", PublicEncodingRules.DER, "1F")]
[InlineData("Missing Length", PublicEncodingRules.BER, "30")]
[InlineData("Missing Length", PublicEncodingRules.CER, "30")]
[InlineData("Missing Length", PublicEncodingRules.DER, "30")]
[InlineData("Primitive Encoding", PublicEncodingRules.BER, "1000")]
[InlineData("Primitive Encoding", PublicEncodingRules.CER, "1000")]
[InlineData("Primitive Encoding", PublicEncodingRules.DER, "1000")]
[InlineData("Definite Length Encoding", PublicEncodingRules.CER, "3000")]
[InlineData("Indefinite Length Encoding", PublicEncodingRules.DER, "3080" + "0000")]
[InlineData("Missing Content", PublicEncodingRules.BER, "3001")]
[InlineData("Missing Content", PublicEncodingRules.DER, "3001")]
[InlineData("Length Out Of Bounds", PublicEncodingRules.BER, "3005" + "010100")]
[InlineData("Length Out Of Bounds", PublicEncodingRules.DER, "3005" + "010100")]
[InlineData("Missing Content - Indefinite", PublicEncodingRules.BER, "3080")]
[InlineData("Missing Content - Indefinite", PublicEncodingRules.CER, "3080")]
[InlineData("Missing EoC", PublicEncodingRules.BER, "3080" + "010100")]
[InlineData("Missing EoC", PublicEncodingRules.CER, "3080" + "010100")]
[InlineData("Missing Outer EoC", PublicEncodingRules.BER, "3080" + "010100" + ("3080" + "0000"))]
[InlineData("Missing Outer EoC", PublicEncodingRules.CER, "3080" + "010100" + ("3080" + "0000"))]
[InlineData("Wrong Tag - Definite", PublicEncodingRules.BER, "3100")]
[InlineData("Wrong Tag - Definite", PublicEncodingRules.DER, "3100")]
[InlineData("Wrong Tag - Indefinite", PublicEncodingRules.BER, "3180" + "0000")]
[InlineData("Wrong Tag - Indefinite", PublicEncodingRules.CER, "3180" + "0000")]
public static void ReadSequence_Throws(
string description,
PublicEncodingRules ruleSet,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(() => reader.ReadSequence());
}
private static void ReadEcPublicKey(AsnEncodingRules ruleSet, byte[] inputData)
{
AsnReader mainReader = new AsnReader(inputData, ruleSet);
AsnReader spkiReader = mainReader.ReadSequence();
Assert.False(mainReader.HasData, "mainReader.HasData after reading SPKI");
AsnReader algorithmReader = spkiReader.ReadSequence();
Assert.True(spkiReader.HasData, "spkiReader.HasData after reading algorithm");
ReadOnlyMemory<byte> publicKeyValue;
int unusedBitCount;
if (!spkiReader.TryGetPrimitiveBitStringValue(out unusedBitCount, out publicKeyValue))
{
// The correct answer is 65 bytes.
for (int i = 10; ; i *= 2)
{
byte[] buf = new byte[i];
if (spkiReader.TryCopyBitStringBytes(buf, out unusedBitCount, out int bytesWritten))
{
publicKeyValue = new ReadOnlyMemory<byte>(buf, 0, bytesWritten);
break;
}
}
}
Assert.False(spkiReader.HasData, "spkiReader.HasData after reading subjectPublicKey");
Assert.True(algorithmReader.HasData, "algorithmReader.HasData before reading");
Oid algorithmOid = algorithmReader.ReadObjectIdentifier(true);
Assert.True(algorithmReader.HasData, "algorithmReader.HasData after reading first OID");
Assert.Equal("1.2.840.10045.2.1", algorithmOid.Value);
Oid curveOid = algorithmReader.ReadObjectIdentifier(true);
Assert.False(algorithmReader.HasData, "algorithmReader.HasData after reading second OID");
Assert.Equal("1.2.840.10045.3.1.7", curveOid.Value);
const string PublicKeyValue =
"04" +
"2363DD131DA65E899A2E63E9E05E50C830D4994662FFE883DB2B9A767DCCABA2" +
"F07081B5711BE1DEE90DFC8DE17970C2D937A16CD34581F52B8D59C9E9532D13";
Assert.Equal(PublicKeyValue, publicKeyValue.ByteArrayToHex());
Assert.Equal(0, unusedBitCount);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.DER)]
public static void ReadEcPublicKey_DefiniteLength(PublicEncodingRules ruleSet)
{
const string InputHex =
"3059" +
"3013" +
"06072A8648CE3D0201" +
"06082A8648CE3D030107" +
"0342" +
"00" +
"04" +
"2363DD131DA65E899A2E63E9E05E50C830D4994662FFE883DB2B9A767DCCABA2" +
"F07081B5711BE1DEE90DFC8DE17970C2D937A16CD34581F52B8D59C9E9532D13";
byte[] inputData = InputHex.HexToByteArray();
ReadEcPublicKey((AsnEncodingRules)ruleSet, inputData);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void ReadEcPublicKey_IndefiniteLength(PublicEncodingRules ruleSet)
{
const string InputHex =
"3080" +
"3080" +
"06072A8648CE3D0201" +
"06082A8648CE3D030107" +
"0000" +
"0342" +
"00" +
"04" +
"2363DD131DA65E899A2E63E9E05E50C830D4994662FFE883DB2B9A767DCCABA2" +
"F07081B5711BE1DEE90DFC8DE17970C2D937A16CD34581F52B8D59C9E9532D13" +
"0000";
byte[] inputData = InputHex.HexToByteArray();
ReadEcPublicKey((AsnEncodingRules)ruleSet, inputData);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal_Definite(PublicEncodingRules ruleSet)
{
byte[] inputData = "30020500".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSequence(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
AsnReader seq = reader.ReadSequence();
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void TagMustBeCorrect_Universal_Indefinite(PublicEncodingRules ruleSet)
{
byte[] inputData = "308005000000".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSequence(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
AsnReader seq = reader.ReadSequence();
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom_Definite(PublicEncodingRules ruleSet)
{
byte[] inputData = "A5020500".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSequence(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadSequence());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.Application, 5)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
AsnReader seq = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 5));
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void TagMustBeCorrect_Custom_Indefinite(PublicEncodingRules ruleSet)
{
byte[] inputData = "A58005000000".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSequence(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadSequence());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.Application, 5)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
AsnReader seq = reader.ReadSequence(new Asn1Tag(TagClass.ContextSpecific, 5));
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "30030101FF", PublicTagClass.Universal, 16)]
[InlineData(PublicEncodingRules.BER, "30800101000000", PublicTagClass.Universal, 16)]
[InlineData(PublicEncodingRules.CER, "30800101000000", PublicTagClass.Universal, 16)]
[InlineData(PublicEncodingRules.DER, "30030101FF", PublicTagClass.Universal, 16)]
[InlineData(PublicEncodingRules.BER, "A0030101FF", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.BER, "A1800101000000", PublicTagClass.ContextSpecific, 1)]
[InlineData(PublicEncodingRules.CER, "6C800101000000", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "FF8A46030101FF", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader val1 = reader.ReadSequence(new Asn1Tag((TagClass)tagClass, tagValue, true));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader val2 = reader.ReadSequence(new Asn1Tag((TagClass)tagClass, tagValue, false));
Assert.False(reader.HasData);
Assert.Equal(val1.GetEncodedValue().ByteArrayToHex(), val2.GetEncodedValue().ByteArrayToHex());
}
}
}

View File

@@ -0,0 +1,304 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Security.Cryptography.Asn1;
using Test.Cryptography;
using Xunit;
namespace System.Security.Cryptography.Tests.Asn1
{
public sealed class ReadSetOf : Asn1ReaderTests
{
[Theory]
[InlineData(PublicEncodingRules.BER, "3100", false, -1)]
[InlineData(PublicEncodingRules.BER, "31800000", false, -1)]
[InlineData(PublicEncodingRules.BER, "3183000000", false, -1)]
[InlineData(PublicEncodingRules.CER, "31800000", false, -1)]
[InlineData(PublicEncodingRules.DER, "3100", false, -1)]
[InlineData(PublicEncodingRules.BER, "3100" + "0500", true, -1)]
[InlineData(PublicEncodingRules.BER, "3102" + "0500", false, 5)]
[InlineData(PublicEncodingRules.CER, "3180" + "0500" + "0000", false, 5)]
[InlineData(PublicEncodingRules.CER, "3180" + "010100" + "0000" + "0500", true, 1)]
[InlineData(PublicEncodingRules.CER, "3180" + "010100" + "0101FF" + "0500" + "0000", false, 1)]
[InlineData(PublicEncodingRules.DER, "3105" + "0101FF" + "0500", false, 1)]
public static void ReadSetOf_Success(
PublicEncodingRules ruleSet,
string inputHex,
bool expectDataRemaining,
int expectedSequenceTagNumber)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader sequence = reader.ReadSetOf();
if (expectDataRemaining)
{
Assert.True(reader.HasData, "reader.HasData");
}
else
{
Assert.False(reader.HasData, "reader.HasData");
}
if (expectedSequenceTagNumber < 0)
{
Assert.False(sequence.HasData, "sequence.HasData");
}
else
{
Assert.True(sequence.HasData, "sequence.HasData");
Asn1Tag firstTag = sequence.PeekTag();
Assert.Equal(expectedSequenceTagNumber, firstTag.TagValue);
}
}
[Theory]
[InlineData("Empty", PublicEncodingRules.BER, "")]
[InlineData("Empty", PublicEncodingRules.CER, "")]
[InlineData("Empty", PublicEncodingRules.DER, "")]
[InlineData("Incomplete Tag", PublicEncodingRules.BER, "1F")]
[InlineData("Incomplete Tag", PublicEncodingRules.CER, "1F")]
[InlineData("Incomplete Tag", PublicEncodingRules.DER, "1F")]
[InlineData("Missing Length", PublicEncodingRules.BER, "31")]
[InlineData("Missing Length", PublicEncodingRules.CER, "31")]
[InlineData("Missing Length", PublicEncodingRules.DER, "31")]
[InlineData("Primitive Encoding", PublicEncodingRules.BER, "1100")]
[InlineData("Primitive Encoding", PublicEncodingRules.CER, "1100")]
[InlineData("Primitive Encoding", PublicEncodingRules.DER, "1100")]
[InlineData("Definite Length Encoding", PublicEncodingRules.CER, "3100")]
[InlineData("Indefinite Length Encoding", PublicEncodingRules.DER, "3180" + "0000")]
[InlineData("Missing Content", PublicEncodingRules.BER, "3101")]
[InlineData("Missing Content", PublicEncodingRules.DER, "3101")]
[InlineData("Length Out Of Bounds", PublicEncodingRules.BER, "3105" + "010100")]
[InlineData("Length Out Of Bounds", PublicEncodingRules.DER, "3105" + "010100")]
[InlineData("Missing Content - Indefinite", PublicEncodingRules.BER, "3180")]
[InlineData("Missing Content - Indefinite", PublicEncodingRules.CER, "3180")]
[InlineData("Missing EoC", PublicEncodingRules.BER, "3180" + "010100")]
[InlineData("Missing EoC", PublicEncodingRules.CER, "3180" + "010100")]
[InlineData("Missing Outer EoC", PublicEncodingRules.BER, "3180" + "010100" + ("3180" + "0000"))]
[InlineData("Missing Outer EoC", PublicEncodingRules.CER, "3180" + "010100" + ("3180" + "0000"))]
[InlineData("Wrong Tag - Definite", PublicEncodingRules.BER, "3000")]
[InlineData("Wrong Tag - Definite", PublicEncodingRules.DER, "3000")]
[InlineData("Wrong Tag - Indefinite", PublicEncodingRules.BER, "3080" + "0000")]
[InlineData("Wrong Tag - Indefinite", PublicEncodingRules.CER, "3080" + "0000")]
public static void ReadSetOf_Throws(
string description,
PublicEncodingRules ruleSet,
string inputHex)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(() => reader.ReadSetOf());
}
[Theory]
// BER can read out of order (indefinite)
[InlineData(PublicEncodingRules.BER, "3180" + "0101FF" + "010100" + "0000", true, 1)]
// BER can read out of order (definite)
[InlineData(PublicEncodingRules.BER, "3106" + "0101FF" + "010100", true, 1)]
// CER will not read out of order
[InlineData(PublicEncodingRules.CER, "3180" + "0500" + "010100" + "0000", false, 1)]
[InlineData(PublicEncodingRules.CER, "3180" + "0101FF" + "010100" + "0000", false, 1)]
// CER is happy in order:
[InlineData(PublicEncodingRules.CER, "3180" + "010100" + "0500" + "0000", true, 5)]
[InlineData(PublicEncodingRules.CER, "3180" + "010100" + "0101FF" + "0500" + "0000", true, 5)]
[InlineData(PublicEncodingRules.CER, "3180" + "010100" + "010100" + "0500" + "0000", true, 5)]
// DER will not read out of order
[InlineData(PublicEncodingRules.DER, "3106" + "0101FF" + "010100", false, 1)]
[InlineData(PublicEncodingRules.DER, "3105" + "0500" + "010100", false, 1)]
// DER is happy in order:
[InlineData(PublicEncodingRules.DER, "3105" + "010100" + "0500", true, 5)]
[InlineData(PublicEncodingRules.DER, "3108" + "010100" + "0101FF" + "0500", true, 5)]
[InlineData(PublicEncodingRules.DER, "3108" + "010100" + "010100" + "0500", true, 5)]
public static void ReadSetOf_DataSorting(
PublicEncodingRules ruleSet,
string inputHex,
bool expectSuccess,
int lastTagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader setOf;
if (expectSuccess)
{
setOf = reader.ReadSetOf();
}
else
{
AsnReader alsoReader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
Assert.Throws<CryptographicException>(() => alsoReader.ReadSetOf());
setOf = reader.ReadSetOf(skipSortOrderValidation: true);
}
int lastTag = -1;
while (setOf.HasData)
{
Asn1Tag tag = setOf.PeekTag();
lastTag = tag.TagValue;
// Ignore the return, just drain it.
setOf.GetEncodedValue();
}
Assert.Equal(lastTagValue, lastTag);
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Universal_Definite(PublicEncodingRules ruleSet)
{
byte[] inputData = "31020500".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSetOf(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
AsnReader seq = reader.ReadSetOf();
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void TagMustBeCorrect_Universal_Indefinite(PublicEncodingRules ruleSet)
{
byte[] inputData = "318005000000".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSetOf(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 0)));
Assert.True(reader.HasData, "HasData after wrong tag");
AsnReader seq = reader.ReadSetOf();
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after read");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.DER)]
public static void TagMustBeCorrect_Custom_Definite(PublicEncodingRules ruleSet)
{
byte[] inputData = "A5020500".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSetOf(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadSetOf());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.Application, 5)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
AsnReader seq = reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 5));
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER)]
[InlineData(PublicEncodingRules.CER)]
public static void TagMustBeCorrect_Custom_Indefinite(PublicEncodingRules ruleSet)
{
byte[] inputData = "A58005000000".HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AssertExtensions.Throws<ArgumentException>(
"expectedTag",
() => reader.ReadSetOf(Asn1Tag.Null));
Assert.True(reader.HasData, "HasData after bad universal tag");
Assert.Throws<CryptographicException>(() => reader.ReadSetOf());
Assert.True(reader.HasData, "HasData after default tag");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.Application, 5)));
Assert.True(reader.HasData, "HasData after wrong custom class");
Assert.Throws<CryptographicException>(
() => reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 7)));
Assert.True(reader.HasData, "HasData after wrong custom tag value");
AsnReader seq = reader.ReadSetOf(new Asn1Tag(TagClass.ContextSpecific, 5));
Assert.Equal("0500", seq.GetEncodedValue().ByteArrayToHex());
Assert.False(reader.HasData, "HasData after reading value");
}
[Theory]
[InlineData(PublicEncodingRules.BER, "31030101FF", PublicTagClass.Universal, 17)]
[InlineData(PublicEncodingRules.BER, "31800101000000", PublicTagClass.Universal, 17)]
[InlineData(PublicEncodingRules.CER, "31800101000000", PublicTagClass.Universal, 17)]
[InlineData(PublicEncodingRules.DER, "31030101FF", PublicTagClass.Universal, 17)]
[InlineData(PublicEncodingRules.BER, "A0030101FF", PublicTagClass.ContextSpecific, 0)]
[InlineData(PublicEncodingRules.BER, "A1800101000000", PublicTagClass.ContextSpecific, 1)]
[InlineData(PublicEncodingRules.CER, "6C800101000000", PublicTagClass.Application, 12)]
[InlineData(PublicEncodingRules.DER, "FF8A46030101FF", PublicTagClass.Private, 1350)]
public static void ExpectedTag_IgnoresConstructed(
PublicEncodingRules ruleSet,
string inputHex,
PublicTagClass tagClass,
int tagValue)
{
byte[] inputData = inputHex.HexToByteArray();
AsnReader reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader val1 = reader.ReadSetOf(new Asn1Tag((TagClass)tagClass, tagValue, true));
Assert.False(reader.HasData);
reader = new AsnReader(inputData, (AsnEncodingRules)ruleSet);
AsnReader val2 = reader.ReadSetOf(new Asn1Tag((TagClass)tagClass, tagValue, false));
Assert.False(reader.HasData);
Assert.Equal(val1.GetEncodedValue().ByteArrayToHex(), val2.GetEncodedValue().ByteArrayToHex());
}
}
}

Some files were not shown because too many files have changed in this diff Show More