Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make System.Formats.Asn1 library public #36729

Merged
merged 4 commits into from
Jun 9, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

using System;
using System.Diagnostics;
using System.Formats.Asn1;
using System.Security.Cryptography;
using System.Security.Cryptography.Asn1;

namespace Internal.Cryptography
{
Expand All @@ -19,21 +19,17 @@ internal static partial class AsymmetricAlgorithmHelpers
/// </summary>
public static byte[] ConvertIeee1363ToDer(ReadOnlySpan<byte> input)
{
using (AsnWriter writer = WriteIeee1363ToDer(input))
{
return writer.Encode();
}
AsnWriter writer = WriteIeee1363ToDer(input);
return writer.Encode();
}

internal static bool TryConvertIeee1363ToDer(
ReadOnlySpan<byte> input,
Span<byte> destination,
out int bytesWritten)
{
using (AsnWriter writer = WriteIeee1363ToDer(input))
{
return writer.TryEncode(destination, out bytesWritten);
}
AsnWriter writer = WriteIeee1363ToDer(input);
return writer.TryEncode(destination, out bytesWritten);
}

private static AsnWriter WriteIeee1363ToDer(ReadOnlySpan<byte> input)
Expand Down Expand Up @@ -73,16 +69,23 @@ internal static int ConvertDerToIeee1363(ReadOnlySpan<byte> input, int fieldSize

Debug.Assert(destination.Length >= encodedSize);

AsnValueReader reader = new AsnValueReader(input, AsnEncodingRules.DER);
AsnValueReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
ReadOnlySpan<byte> rDer = sequenceReader.ReadIntegerBytes();
ReadOnlySpan<byte> sDer = sequenceReader.ReadIntegerBytes();
sequenceReader.ThrowIfNotEmpty();

CopySignatureField(rDer, destination.Slice(0, fieldSizeBytes));
CopySignatureField(sDer, destination.Slice(fieldSizeBytes, fieldSizeBytes));
return encodedSize;
try
{
AsnValueReader reader = new AsnValueReader(input, AsnEncodingRules.DER);
AsnValueReader sequenceReader = reader.ReadSequence();
reader.ThrowIfNotEmpty();
ReadOnlySpan<byte> rDer = sequenceReader.ReadIntegerBytes();
ReadOnlySpan<byte> sDer = sequenceReader.ReadIntegerBytes();
sequenceReader.ThrowIfNotEmpty();

CopySignatureField(rDer, destination.Slice(0, fieldSizeBytes));
CopySignatureField(sDer, destination.Slice(fieldSizeBytes, fieldSizeBytes));
return encodedSize;
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

internal static int GetMaxDerSignatureSize(int fieldSizeBits)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
// 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;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Asn1;

using System.Formats.Asn1;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
Expand Down Expand Up @@ -35,8 +36,17 @@ internal static byte[] GetAsn1IntegerBytes(SafeSharedAsn1IntegerHandle asn1Integ
(handle, buf) => EncodeAsn1Integer(handle, buf),
asn1Integer);

AsnReader reader = new AsnReader(derEncoded, AsnEncodingRules.DER);
return reader.ReadIntegerBytes().ToArray();
try
{
return AsnDecoder.ReadIntegerBytes(
derEncoded,
AsnEncodingRules.DER,
out _).ToArray();
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,15 @@

#pragma warning disable SA1028 // ignore whitespace warnings for generated code
using System;
using System.Formats.Asn1;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Asn1;

namespace System.Security.Cryptography.Asn1
{
[StructLayout(LayoutKind.Sequential)]
internal partial struct AlgorithmIdentifierAsn
{
internal Oid Algorithm;
internal string Algorithm;
internal ReadOnlyMemory<byte>? Parameters;

internal void Encode(AsnWriter writer)
Expand All @@ -25,11 +24,25 @@ internal void Encode(AsnWriter writer, Asn1Tag tag)
{
writer.PushSequence(tag);

writer.WriteObjectIdentifier(Algorithm);
try
{
writer.WriteObjectIdentifier(Algorithm);
}
catch (ArgumentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}

if (Parameters.HasValue)
{
writer.WriteEncodedValue(Parameters.Value.Span);
try
{
writer.WriteEncodedValue(Parameters.Value.Span);
}
catch (ArgumentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

writer.PopSequence(tag);
Expand All @@ -42,11 +55,18 @@ internal static AlgorithmIdentifierAsn Decode(ReadOnlyMemory<byte> encoded, AsnE

internal static AlgorithmIdentifierAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);
try
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);

Decode(ref reader, expectedTag, encoded, out AlgorithmIdentifierAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
DecodeCore(ref reader, expectedTag, encoded, out AlgorithmIdentifierAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebind, out AlgorithmIdentifierAsn decoded)
Expand All @@ -55,6 +75,18 @@ internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebi
}

internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out AlgorithmIdentifierAsn decoded)
{
try
{
DecodeCore(ref reader, expectedTag, rebind, out decoded);
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out AlgorithmIdentifierAsn decoded)
{
decoded = default;
AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public AttributeAsn(AsnEncodedData attribute)
throw new ArgumentNullException(nameof(attribute));
}

AttrType = new Oid(attribute.Oid!);
AttrType = attribute.Oid!.Value!;
AttrValues = new[] { new ReadOnlyMemory<byte>(attribute.RawData) };
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,15 @@
#pragma warning disable SA1028 // ignore whitespace warnings for generated code
using System;
using System.Collections.Generic;
using System.Formats.Asn1;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Asn1;

namespace System.Security.Cryptography.Asn1
{
[StructLayout(LayoutKind.Sequential)]
internal partial struct AttributeAsn
{
internal Oid AttrType;
internal string AttrType;
internal ReadOnlyMemory<byte>[] AttrValues;

internal void Encode(AsnWriter writer)
Expand All @@ -26,12 +25,26 @@ internal void Encode(AsnWriter writer, Asn1Tag tag)
{
writer.PushSequence(tag);

writer.WriteObjectIdentifier(AttrType);
try
{
writer.WriteObjectIdentifier(AttrType);
}
catch (ArgumentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}

writer.PushSetOf();
for (int i = 0; i < AttrValues.Length; i++)
{
writer.WriteEncodedValue(AttrValues[i].Span);
try
{
writer.WriteEncodedValue(AttrValues[i].Span);
}
catch (ArgumentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}
writer.PopSetOf();

Expand All @@ -45,11 +58,18 @@ internal static AttributeAsn Decode(ReadOnlyMemory<byte> encoded, AsnEncodingRul

internal static AttributeAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);
try
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);

Decode(ref reader, expectedTag, encoded, out AttributeAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
DecodeCore(ref reader, expectedTag, encoded, out AttributeAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebind, out AttributeAsn decoded)
Expand All @@ -58,6 +78,18 @@ internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebi
}

internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out AttributeAsn decoded)
{
try
{
DecodeCore(ref reader, expectedTag, rebind, out decoded);
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out AttributeAsn decoded)
{
decoded = default;
AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@

#pragma warning disable SA1028 // ignore whitespace warnings for generated code
using System;
using System.Formats.Asn1;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.Asn1;

namespace System.Security.Cryptography.Asn1
{
Expand All @@ -31,7 +30,7 @@ internal void Encode(AsnWriter writer, Asn1Tag tag)

if (Seed.HasValue)
{
writer.WriteBitString(Seed.Value.Span);
writer.WriteBitString(Seed.Value.Span, 0);
}

writer.PopSequence(tag);
Expand All @@ -44,11 +43,18 @@ internal static CurveAsn Decode(ReadOnlyMemory<byte> encoded, AsnEncodingRules r

internal static CurveAsn Decode(Asn1Tag expectedTag, ReadOnlyMemory<byte> encoded, AsnEncodingRules ruleSet)
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);
try
{
AsnValueReader reader = new AsnValueReader(encoded.Span, ruleSet);

Decode(ref reader, expectedTag, encoded, out CurveAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
DecodeCore(ref reader, expectedTag, encoded, out CurveAsn decoded);
reader.ThrowIfNotEmpty();
return decoded;
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebind, out CurveAsn decoded)
Expand All @@ -57,6 +63,18 @@ internal static void Decode(ref AsnValueReader reader, ReadOnlyMemory<byte> rebi
}

internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out CurveAsn decoded)
{
try
{
DecodeCore(ref reader, expectedTag, rebind, out decoded);
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

private static void DecodeCore(ref AsnValueReader reader, Asn1Tag expectedTag, ReadOnlyMemory<byte> rebind, out CurveAsn decoded)
{
decoded = default;
AsnValueReader sequenceReader = reader.ReadSequence(expectedTag);
Expand All @@ -65,7 +83,7 @@ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, Read
ReadOnlySpan<byte> tmpSpan;


if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
if (sequenceReader.TryReadPrimitiveOctetString(out tmpSpan))
{
decoded.A = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
}
Expand All @@ -75,7 +93,7 @@ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, Read
}


if (sequenceReader.TryReadPrimitiveOctetStringBytes(out tmpSpan))
if (sequenceReader.TryReadPrimitiveOctetString(out tmpSpan))
{
decoded.B = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
}
Expand All @@ -88,7 +106,7 @@ internal static void Decode(ref AsnValueReader reader, Asn1Tag expectedTag, Read
if (sequenceReader.HasData && sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.PrimitiveBitString))
{

if (sequenceReader.TryReadPrimitiveBitStringValue(out _, out tmpSpan))
if (sequenceReader.TryReadPrimitiveBitString(out _, out tmpSpan))
{
decoded.Seed = rebindSpan.Overlaps(tmpSpan, out offset) ? rebind.Slice(offset, tmpSpan.Length) : tmpSpan.ToArray();
}
Expand Down
Loading