Skip to content
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
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,59 @@ internal static bool RepresentsNull(ReadOnlyMemory<byte>? parameters)
return span[1] == 0;
}
}

internal ref partial struct ValueAlgorithmIdentifierAsn
{
internal static ReadOnlySpan<byte> ExplicitDerNull => [0x05, 0x00];

internal bool Equals(ref readonly ValueAlgorithmIdentifierAsn other)
{
if (Algorithm != other.Algorithm)
{
return false;
}

bool isNull = RepresentsNull(ref this);
bool isOtherNull = RepresentsNull(in other);

if (isNull != isOtherNull)
{
return false;
}

if (isNull)
{
return true;
}

return Parameters.SequenceEqual(other.Parameters);
}

internal readonly bool HasNullEquivalentParameters()
{
return RepresentsNull(in this);
}

internal static bool RepresentsNull(ref readonly ValueAlgorithmIdentifierAsn algorithm)
{
if (!algorithm.HasParameters)
{
return true;
}

ReadOnlySpan<byte> span = algorithm.Parameters;

if (span.Length != 2)
{
return false;
}

if (span[0] != 0x05)
{
return false;
}

return span[1] == 0;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<asn:Sequence
xmlns:asn="http://schemas.dot.net/asnxml/201808/"
name="AlgorithmIdentifierAsn"
namespace="System.Security.Cryptography.Asn1">
namespace="System.Security.Cryptography.Asn1"
emitType="both">

<!--
https://tools.ietf.org/html/rfc3280#section-4.1.1.2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,68 @@ private static void DecodeCore(ref ValueAsnReader reader, Asn1Tag expectedTag, R
}


sequenceReader.ThrowIfNotEmpty();
}
}

[StructLayout(LayoutKind.Sequential)]
internal ref partial struct ValueAlgorithmIdentifierAsn
{
internal string Algorithm;
internal ReadOnlySpan<byte> Parameters;
internal bool HasParameters;

internal static void Decode(ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet, out ValueAlgorithmIdentifierAsn decoded)
{
Decode(Asn1Tag.Sequence, encoded, ruleSet, out decoded);
}

internal static void Decode(Asn1Tag expectedTag, ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet, out ValueAlgorithmIdentifierAsn decoded)
{
try
{
ValueAsnReader reader = new ValueAsnReader(encoded, ruleSet);

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

internal static void Decode(scoped ref ValueAsnReader reader, out ValueAlgorithmIdentifierAsn decoded)
{
Decode(ref reader, Asn1Tag.Sequence, out decoded);
}

internal static void Decode(scoped ref ValueAsnReader reader, Asn1Tag expectedTag, out ValueAlgorithmIdentifierAsn decoded)
{
try
{
DecodeCore(ref reader, expectedTag, out decoded);
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

private static void DecodeCore(scoped ref ValueAsnReader reader, Asn1Tag expectedTag, out ValueAlgorithmIdentifierAsn decoded)
{
decoded = default;
ValueAsnReader sequenceReader = reader.ReadSequence(expectedTag);

decoded.Algorithm = sequenceReader.ReadObjectIdentifier();

if (sequenceReader.HasData)
{
decoded.Parameters = sequenceReader.ReadEncodedValue();
decoded.HasParameters = true;
}


sequenceReader.ThrowIfNotEmpty();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<asn:Sequence
xmlns:asn="http://schemas.dot.net/asnxml/201808/"
name="AttributeAsn"
namespace="System.Security.Cryptography.Asn1">
namespace="System.Security.Cryptography.Asn1"
emitType="both">

<!--
https://tools.ietf.org/html/rfc5652#section-5.3
Expand All @@ -15,7 +16,7 @@
AttributeValue ::= ANY
-->
<asn:ObjectIdentifier name="AttrType" />
<asn:SetOf name="AttrValues">
<asn:SetOf name="AttrValues" valueName="GetAttrValues">
<asn:AnyValue />
</asn:SetOf>
</asn:Sequence>
Original file line number Diff line number Diff line change
Expand Up @@ -119,4 +119,116 @@ private static void DecodeCore(ref ValueAsnReader reader, Asn1Tag expectedTag, R
sequenceReader.ThrowIfNotEmpty();
}
}

[StructLayout(LayoutKind.Sequential)]
internal ref partial struct ValueAttributeAsn
{
internal string AttrType;
internal ReadOnlySpan<byte> AttrValues;

internal static void Decode(ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet, out ValueAttributeAsn decoded)
{
Decode(Asn1Tag.Sequence, encoded, ruleSet, out decoded);
}

internal static void Decode(Asn1Tag expectedTag, ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet, out ValueAttributeAsn decoded)
{
try
{
ValueAsnReader reader = new ValueAsnReader(encoded, ruleSet);

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

internal static void Decode(scoped ref ValueAsnReader reader, out ValueAttributeAsn decoded)
{
Decode(ref reader, Asn1Tag.Sequence, out decoded);
}

internal static void Decode(scoped ref ValueAsnReader reader, Asn1Tag expectedTag, out ValueAttributeAsn decoded)
{
try
{
DecodeCore(ref reader, expectedTag, out decoded);
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}
}

private static void DecodeCore(scoped ref ValueAsnReader reader, Asn1Tag expectedTag, out ValueAttributeAsn decoded)
{
decoded = default;
ValueAsnReader sequenceReader = reader.ReadSequence(expectedTag);

decoded.AttrType = sequenceReader.ReadObjectIdentifier();

if (!sequenceReader.PeekTag().HasSameClassAndValue(Asn1Tag.SetOf))
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}

decoded.AttrValues = sequenceReader.ReadEncodedValue();

sequenceReader.ThrowIfNotEmpty();
}


internal AttrValuesEnumerable GetAttrValues(AsnEncodingRules ruleSet)
{
return new AttrValuesEnumerable(AttrValues, ruleSet);
}

internal readonly ref struct AttrValuesEnumerable
{
private readonly ReadOnlySpan<byte> _encoded;
private readonly AsnEncodingRules _ruleSet;

internal AttrValuesEnumerable(ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet)
{
_encoded = encoded;
_ruleSet = ruleSet;
}

public Enumerator GetEnumerator() => new Enumerator(_encoded, _ruleSet);

internal ref struct Enumerator
{
private ValueAsnReader _reader;
private ReadOnlySpan<byte> _current;

internal Enumerator(ReadOnlySpan<byte> encoded, AsnEncodingRules ruleSet)
{
if (!encoded.IsEmpty)
{
ValueAsnReader outerReader = new ValueAsnReader(encoded, ruleSet);
_reader = outerReader.ReadSetOf();
outerReader.ThrowIfNotEmpty();
}

_current = default;
}

public ReadOnlySpan<byte> Current => _current;

public bool MoveNext()
{
if (!_reader.HasData)
{
return false;
}

_current = _reader.ReadEncodedValue();
return true;
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,17 @@

namespace System.Security.Cryptography.X509Certificates.Asn1
{
[StructLayout(LayoutKind.Sequential)]
internal partial struct GeneralSubtreeAsn
file static class SharedGeneralSubtreeAsn
{
private static ReadOnlySpan<byte> DefaultMinimum => [0x02, 0x01, 0x00];

internal System.Security.Cryptography.Asn1.GeneralNameAsn Base;
internal int Minimum;
internal int? Maximum;
internal static ReadOnlySpan<byte> DefaultMinimum => [0x02, 0x01, 0x00];

#if DEBUG
static GeneralSubtreeAsn()
static SharedGeneralSubtreeAsn()
{
GeneralSubtreeAsn decoded = default;
ValueAsnReader reader;

reader = new ValueAsnReader(DefaultMinimum, AsnEncodingRules.DER);
reader = new ValueAsnReader(SharedGeneralSubtreeAsn.DefaultMinimum, AsnEncodingRules.DER);

if (!reader.TryReadInt32(out decoded.Minimum))
{
Expand All @@ -33,6 +28,14 @@ static GeneralSubtreeAsn()
reader.ThrowIfNotEmpty();
}
#endif
}

[StructLayout(LayoutKind.Sequential)]
internal partial struct GeneralSubtreeAsn
{
internal System.Security.Cryptography.Asn1.GeneralNameAsn Base;
internal int Minimum;
internal int? Maximum;

internal readonly void Encode(AsnWriter writer)
{
Expand All @@ -51,7 +54,7 @@ internal readonly void Encode(AsnWriter writer, Asn1Tag tag)
AsnWriter tmp = new AsnWriter(AsnEncodingRules.DER, initialCapacity: AsnManagedIntegerDerMaxEncodeSize);
tmp.WriteInteger(Minimum);

if (!tmp.EncodedValueEquals(DefaultMinimum))
if (!tmp.EncodedValueEquals(SharedGeneralSubtreeAsn.DefaultMinimum))
{
writer.PushSequence(new Asn1Tag(TagClass.ContextSpecific, 0));
tmp.CopyTo(writer);
Expand Down Expand Up @@ -130,7 +133,7 @@ private static void DecodeCore(ref ValueAsnReader reader, Asn1Tag expectedTag, R
}
else
{
defaultReader = new ValueAsnReader(DefaultMinimum, AsnEncodingRules.DER);
defaultReader = new ValueAsnReader(SharedGeneralSubtreeAsn.DefaultMinimum, AsnEncodingRules.DER);

if (!defaultReader.TryReadInt32(out decoded.Minimum))
{
Expand Down
Loading
Loading