Skip to content

Commit

Permalink
Perform SKI encode and decode using managed implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
vcsjones authored Jan 30, 2024
1 parent cfd9092 commit a74a920
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,5 @@ internal interface IX509Pal
void DecodeX509BasicConstraints2Extension(byte[] encoded, out bool certificateAuthority, out bool hasPathLengthConstraint, out int pathLengthConstraint);
byte[] EncodeX509EnhancedKeyUsageExtension(OidCollection usages);
void DecodeX509EnhancedKeyUsageExtension(byte[] encoded, out OidCollection usages);
byte[] EncodeX509SubjectKeyIdentifierExtension(ReadOnlySpan<byte> subjectKeyIdentifier);
void DecodeX509SubjectKeyIdentifierExtension(byte[] encoded, out byte[] subjectKeyIdentifier);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -281,7 +281,7 @@ public void FindBySubjectKeyIdentifier(byte[] keyIdentifier)
{
// The extension exposes the value as a hexadecimal string, or we can decode here.
// Enough parsing has gone on, let's decode.
certKeyId = ManagedX509ExtensionProcessor.DecodeX509SubjectKeyIdentifierExtension(ext.RawData);
certKeyId = X509SubjectKeyIdentifierExtension.DecodeX509SubjectKeyIdentifierExtension(ext.RawData);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,54 +162,6 @@ public virtual void DecodeX509EnhancedKeyUsageExtension(byte[] encoded, out OidC
}
}

public virtual byte[] EncodeX509SubjectKeyIdentifierExtension(ReadOnlySpan<byte> subjectKeyIdentifier)
{
// https://tools.ietf.org/html/rfc5280#section-4.2.1.2
//
// subjectKeyIdentifier EXTENSION ::= {
// SYNTAX SubjectKeyIdentifier
// IDENTIFIED BY id - ce - subjectKeyIdentifier
// }
//
// SubjectKeyIdentifier::= KeyIdentifier
//
// KeyIdentifier ::= OCTET STRING

AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
writer.WriteOctetString(subjectKeyIdentifier);
return writer.Encode();
}

public virtual void DecodeX509SubjectKeyIdentifierExtension(byte[] encoded, out byte[] subjectKeyIdentifier)
{
subjectKeyIdentifier = DecodeX509SubjectKeyIdentifierExtension(encoded);
}

internal static byte[] DecodeX509SubjectKeyIdentifierExtension(byte[] encoded)
{
ReadOnlySpan<byte> contents;

try
{
bool gotContents = AsnDecoder.TryReadPrimitiveOctetString(
encoded,
AsnEncodingRules.BER,
out contents,
out int consumed);

if (!gotContents || consumed != encoded.Length)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}

return contents.ToArray();
}

private static byte ReverseBitOrder(byte b)
{
return (byte)(unchecked(b * 0x0202020202ul & 0x010884422010ul) % 1023);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -157,32 +157,5 @@ static delegate (void* pvDecoded, int cbDecoded)
});
}
}

public byte[] EncodeX509SubjectKeyIdentifierExtension(ReadOnlySpan<byte> subjectKeyIdentifier)
{
unsafe
{
fixed (byte* pSubkectKeyIdentifier = subjectKeyIdentifier)
{
Interop.Crypt32.DATA_BLOB blob = new Interop.Crypt32.DATA_BLOB(new IntPtr(pSubkectKeyIdentifier), (uint)subjectKeyIdentifier.Length);
return Interop.crypt32.EncodeObject(Oids.SubjectKeyIdentifier, &blob);
}
}
}

public void DecodeX509SubjectKeyIdentifierExtension(byte[] encoded, out byte[] subjectKeyIdentifier)
{
unsafe
{
subjectKeyIdentifier = encoded.DecodeObject(
Oids.SubjectKeyIdentifier,
static delegate (void* pvDecoded, int cbDecoded)
{
Debug.Assert(cbDecoded >= sizeof(Interop.Crypt32.DATA_BLOB));
Interop.Crypt32.DATA_BLOB* pBlob = (Interop.Crypt32.DATA_BLOB*)pvDecoded;
return pBlob->ToByteArray();
});
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,17 +92,55 @@ public override void CopyFrom(AsnEncodedData asnEncodedData)

private void Decode(byte[] rawData)
{
X509Pal.Instance.DecodeX509SubjectKeyIdentifierExtension(rawData, out _subjectKeyIdentifierBytes);
_subjectKeyIdentifierBytes = DecodeX509SubjectKeyIdentifierExtension(rawData);
_subjectKeyIdentifierString = _subjectKeyIdentifierBytes.ToHexStringUpper();
_decoded = true;
}

internal static byte[] DecodeX509SubjectKeyIdentifierExtension(byte[] encoded)
{
ReadOnlySpan<byte> contents;

try
{
bool gotContents = AsnDecoder.TryReadPrimitiveOctetString(
encoded,
AsnEncodingRules.BER,
out contents,
out int consumed);

if (!gotContents || consumed != encoded.Length)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
}
}
catch (AsnContentException e)
{
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, e);
}

return contents.ToArray();
}

private static byte[] EncodeExtension(ReadOnlySpan<byte> subjectKeyIdentifier)
{
if (subjectKeyIdentifier.Length == 0)
throw new ArgumentException(SR.Arg_EmptyOrNullArray, nameof(subjectKeyIdentifier));

return X509Pal.Instance.EncodeX509SubjectKeyIdentifierExtension(subjectKeyIdentifier);
// https://tools.ietf.org/html/rfc5280#section-4.2.1.2
//
// subjectKeyIdentifier EXTENSION ::= {
// SYNTAX SubjectKeyIdentifier
// IDENTIFIED BY id - ce - subjectKeyIdentifier
// }
//
// SubjectKeyIdentifier::= KeyIdentifier
//
// KeyIdentifier ::= OCTET STRING

AsnWriter writer = new AsnWriter(AsnEncodingRules.DER);
writer.WriteOctetString(subjectKeyIdentifier);
return writer.Encode();
}

private static byte[] EncodeExtension(string subjectKeyIdentifier)
Expand Down

0 comments on commit a74a920

Please sign in to comment.