diff --git a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs index 55e50666acdee5..e656d8411de491 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/Helpers.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System; +using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Formats.Asn1; using System.Runtime.CompilerServices; @@ -168,5 +169,47 @@ internal static CryptographicException CreateAlgorithmUnknownException(string al throw new CryptographicException( SR.Format(SR.Cryptography_UnknownAlgorithmIdentifier, algorithmId)); } + +#if !BUILDING_PKCS + internal static string EncodeAsnWriterToPem(string label, AsnWriter writer, bool clear = true) + { +#if NET10_0_OR_GREATER + return writer.Encode(label, static (label, span) => PemEncoding.WriteString(label, span)); +#else + int length = writer.GetEncodedLength(); + byte[] rent = CryptoPool.Rent(length); + + try + { + int written = writer.Encode(rent); + Debug.Assert(written == length); + return PemEncoding.WriteString(label, rent.AsSpan(0, written)); + } + finally + { + CryptoPool.Return(rent, clear ? length : 0); + } +#endif + } +#endif + + internal static void ThrowIfAsnInvalidLength(ReadOnlySpan data) + { + int bytesRead; + + try + { + AsnDecoder.ReadEncodedValue(data, AsnEncodingRules.BER, out _, out _, out bytesRead); + } + catch (AsnContentException ace) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, ace); + } + + if (bytesRead != data.Length) + { + throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); + } + } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs index 112b95c5b01960..647316f173c206 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/MLDsa.cs @@ -251,7 +251,7 @@ public string ExportSubjectPublicKeyInfoPem() AsnWriter writer = ExportSubjectPublicKeyInfoCore(); // SPKI does not contain sensitive data. - return EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); } /// @@ -638,7 +638,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem( AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(password, pbeParameters); // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } /// @@ -682,7 +682,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem( AsnWriter writer = ExportEncryptedPkcs8PrivateKeyCore(passwordBytes, pbeParameters); // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } /// @@ -835,7 +835,7 @@ public static MLDsa GenerateKey(MLDsaAlgorithm algorithm) /// public static MLDsa ImportSubjectPublicKeyInfo(ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); unsafe @@ -904,7 +904,7 @@ public static MLDsa ImportSubjectPublicKeyInfo(byte[] source) /// public static MLDsa ImportPkcs8PrivateKey(ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); KeyFormatHelper.ReadPkcs8(KnownOids, source, MLDsaKeyReader, out int read, out MLDsa dsa); @@ -967,7 +967,7 @@ public static MLDsa ImportPkcs8PrivateKey(byte[] source) /// public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1016,7 +1016,7 @@ public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBy /// public static MLDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password, ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1668,45 +1668,7 @@ internal static void ThrowIfNotSupported() } } - private static void ThrowIfInvalidLength(ReadOnlySpan data) - { - int bytesRead; - - try - { - AsnDecoder.ReadEncodedValue(data, AsnEncodingRules.BER, out _, out _, out bytesRead); - } - catch (AsnContentException ace) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, ace); - } - - if (bytesRead != data.Length) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - } - - private static string EncodeAsnWriterToPem(string label, AsnWriter writer, bool clear = true) - { -#if NET10_0_OR_GREATER - return writer.Encode(label, static (label, span) => PemEncoding.WriteString(label, span)); -#else - int length = writer.GetEncodedLength(); - byte[] rent = CryptoPool.Rent(length); - try - { - int written = writer.Encode(rent); - Debug.Assert(written == length); - return PemEncoding.WriteString(label, rent.AsSpan(0, written)); - } - finally - { - CryptoPool.Return(rent, clear ? length : 0); - } -#endif - } private delegate TResult ExportPkcs8PrivateKeyFunc(ReadOnlySpan pkcs8); } diff --git a/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs b/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs index 35e26a97c1f322..478d8be5a6d072 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/MLKem.cs @@ -660,7 +660,7 @@ public string ExportSubjectPublicKeyInfoPem() ThrowIfDisposed(); AsnWriter writer = ExportSubjectPublicKeyInfoCore(); // SPKI does not contain sensitive data. - return EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); } /// @@ -1064,7 +1064,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan passwordBytes KeyFormatHelper.WriteEncryptedPkcs8); // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } /// @@ -1105,7 +1105,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem(ReadOnlySpan password, Pbe KeyFormatHelper.WriteEncryptedPkcs8); // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } /// @@ -1168,7 +1168,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem(string password, PbeParameters p /// public static MLKem ImportSubjectPublicKeyInfo(ReadOnlySpan source) { - ThrowIfTrailingData(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); KeyFormatHelper.ReadSubjectPublicKeyInfo(s_knownOids, source, SubjectPublicKeyReader, out int read, out MLKem kem); @@ -1230,7 +1230,7 @@ public static MLKem ImportSubjectPublicKeyInfo(byte[] source) /// public static MLKem ImportPkcs8PrivateKey(ReadOnlySpan source) { - ThrowIfTrailingData(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); KeyFormatHelper.ReadPkcs8(s_knownOids, source, MLKemKeyReader, out int read, out MLKem kem); @@ -1288,7 +1288,7 @@ public static MLKem ImportPkcs8PrivateKey(byte[] source) /// public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, ReadOnlySpan source) { - ThrowIfTrailingData(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1333,7 +1333,7 @@ public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBy /// public static MLKem ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password, ReadOnlySpan source) { - ThrowIfTrailingData(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1383,7 +1383,7 @@ public static MLKem ImportEncryptedPkcs8PrivateKey(string password, byte[] sourc { ArgumentNullException.ThrowIfNull(password); ArgumentNullException.ThrowIfNull(source); - ThrowIfTrailingData(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1744,19 +1744,6 @@ private static void MLKemKeyReader( } } - private static void ThrowIfTrailingData(ReadOnlySpan data) - { - // The only thing we are checking here is that TryReadEncodedValue was able to decode it and that, given - // the length of the data, that it the same length as the span. The encoding rules don't matter for length - // checking, so just use BER. - bool success = AsnDecoder.TryReadEncodedValue(data, AsnEncodingRules.BER, out _, out _, out _, out int bytesRead); - - if (!success || bytesRead != data.Length) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - } - private protected void ThrowIfDisposed() { ObjectDisposedException.ThrowIf(_disposed, typeof(MLKem)); @@ -1822,27 +1809,6 @@ private TResult ExportPkcs8PrivateKeyCallback(ExportPkcs8PrivateKeyFunc return result; } - private static string EncodeAsnWriterToPem(string label, AsnWriter writer, bool clear = true) - { -#if NET10_0_OR_GREATER - return writer.Encode(label, static (label, span) => PemEncoding.WriteString(label, span)); -#else - int length = writer.GetEncodedLength(); - byte[] rent = CryptoPool.Rent(length); - - try - { - int written = writer.Encode(rent); - Debug.Assert(written == length); - return PemEncoding.WriteString(label, rent.AsSpan(0, written)); - } - finally - { - CryptoPool.Return(rent, clear ? length : 0); - } -#endif - } - private protected static void ThrowIfNoSeed(bool hasSeed) { if (!hasSeed) diff --git a/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.MLKem.cs b/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.MLKem.cs deleted file mode 100644 index 0ec9b81fe3c479..00000000000000 --- a/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.MLKem.cs +++ /dev/null @@ -1,123 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Diagnostics; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; -using System.Text; - -using BCRYPT_MLKEM_KEY_BLOB = Interop.BCrypt.BCRYPT_MLKEM_KEY_BLOB; -using KeyBlobMagicNumber = Interop.BCrypt.KeyBlobMagicNumber; -using KeyBlobType = Interop.BCrypt.KeyBlobType; - -namespace System.Security.Cryptography -{ - internal static partial class PqcBlobHelpers - { - internal const string BCRYPT_MLKEM_PARAMETER_SET_512 = "512"; - internal const string BCRYPT_MLKEM_PARAMETER_SET_768 = "768"; - internal const string BCRYPT_MLKEM_PARAMETER_SET_1024 = "1024"; - - internal static string GetMLKemParameterSet(MLKemAlgorithm algorithm) - { - if (algorithm == MLKemAlgorithm.MLKem512) - { - return BCRYPT_MLKEM_PARAMETER_SET_512; - } - else if (algorithm == MLKemAlgorithm.MLKem768) - { - return BCRYPT_MLKEM_PARAMETER_SET_768; - } - else if (algorithm == MLKemAlgorithm.MLKem1024) - { - return BCRYPT_MLKEM_PARAMETER_SET_1024; - } - - Debug.Fail($"Unknown MLKemAlgorithm: {algorithm.Name}"); - throw new PlatformNotSupportedException(); - } - - internal static string MLKemBlobMagicToBlobType(KeyBlobMagicNumber magicNumber) - { - return magicNumber switch - { - KeyBlobMagicNumber.BCRYPT_MLKEM_PRIVATE_SEED_MAGIC => KeyBlobType.BCRYPT_MLKEM_PRIVATE_SEED_BLOB, - KeyBlobMagicNumber.BCRYPT_MLKEM_PRIVATE_MAGIC => KeyBlobType.BCRYPT_MLKEM_PRIVATE_BLOB, - KeyBlobMagicNumber.BCRYPT_MLKEM_PUBLIC_MAGIC => KeyBlobType.BCRYPT_MLKEM_PUBLIC_BLOB, - KeyBlobMagicNumber other => throw Fail(other), - }; - - static CryptographicException Fail(KeyBlobMagicNumber other) - { - Debug.Fail($"Unknown blob type '{other}'."); - return new CryptographicException(); - } - } - - internal delegate TReturn EncodeMLKemBlobCallback( - TState state, - string blobKind, - ReadOnlySpan blob); - - internal static TReturn EncodeMLKemBlob( - KeyBlobMagicNumber kind, - MLKemAlgorithm algorithm, - ReadOnlySpan key, - TState state, - EncodeMLKemBlobCallback callback) - { - checked - { - // ML-KEM 1024 seeds are 86 byte blobs. Round it off to 128. - // Other keys like encapsulation or decapsulation keys will never fit in a stack buffer, so don't - // try to accommodate them. - const int MaxKeyStackSize = 128; - string parameterSet = GetMLKemParameterSet(algorithm); - int blobHeaderSize = Marshal.SizeOf(); - int parameterSetMarshalLength = (parameterSet.Length + 1) * 2; - int blobSize = - blobHeaderSize + - parameterSetMarshalLength + - key.Length; - - byte[]? rented = null; - Span buffer = (uint)blobSize <= MaxKeyStackSize ? - stackalloc byte[MaxKeyStackSize] : - (rented = CryptoPool.Rent(blobSize)); - - try - { - buffer.Clear(); - - unsafe - { - fixed (byte* pBuffer = buffer) - { - BCRYPT_MLKEM_KEY_BLOB* blob = (BCRYPT_MLKEM_KEY_BLOB*)pBuffer; - blob->dwMagic = kind; - blob->cbParameterSet = (uint)parameterSetMarshalLength; - blob->cbKey = (uint)key.Length; - } - } - - // This won't write the null byte, but we zeroed the whole buffer earlier. - Encoding.Unicode.GetBytes(parameterSet, buffer.Slice(blobHeaderSize)); - key.CopyTo(buffer.Slice(blobHeaderSize + parameterSetMarshalLength)); - string blobKind = MLKemBlobMagicToBlobType(kind); - return callback(state, blobKind, buffer.Slice(0, blobSize)); - } - finally - { - CryptographicOperations.ZeroMemory(buffer.Slice(0, blobSize)); - - if (rented is not null) - { - // buffer is a slice of rented which was zeroed, since it needs to be zeroed regardless of being - // a rent or a stack buffer. - CryptoPool.Return(rented, 0); - } - } - } - } - } -} diff --git a/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.cs b/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.cs index 90db6623d1baf0..566234e5bec251 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/PqcBlobHelpers.cs @@ -4,8 +4,11 @@ using System.Diagnostics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; +using System.Text; +using KeyBlobType = Interop.BCrypt.KeyBlobType; using KeyBlobMagicNumber = Interop.BCrypt.KeyBlobMagicNumber; +using BCRYPT_MLKEM_KEY_BLOB = Interop.BCrypt.BCRYPT_MLKEM_KEY_BLOB; using BCRYPT_PQDSA_KEY_BLOB = Interop.BCrypt.BCRYPT_PQDSA_KEY_BLOB; namespace System.Security.Cryptography @@ -15,6 +18,9 @@ internal static partial class PqcBlobHelpers internal const string BCRYPT_MLDSA_PARAMETER_SET_44 = "44"; internal const string BCRYPT_MLDSA_PARAMETER_SET_65 = "65"; internal const string BCRYPT_MLDSA_PARAMETER_SET_87 = "87"; + internal const string BCRYPT_MLKEM_PARAMETER_SET_512 = "512"; + internal const string BCRYPT_MLKEM_PARAMETER_SET_768 = "768"; + internal const string BCRYPT_MLKEM_PARAMETER_SET_1024 = "1024"; internal static string GetMLDsaParameterSet(MLDsaAlgorithm algorithm) { @@ -168,5 +174,107 @@ private static ReadOnlySpan DecodePQDsaBlob( return blobBytes.Slice(index, keyLength); } + + internal static string GetMLKemParameterSet(MLKemAlgorithm algorithm) + { + if (algorithm == MLKemAlgorithm.MLKem512) + { + return BCRYPT_MLKEM_PARAMETER_SET_512; + } + else if (algorithm == MLKemAlgorithm.MLKem768) + { + return BCRYPT_MLKEM_PARAMETER_SET_768; + } + else if (algorithm == MLKemAlgorithm.MLKem1024) + { + return BCRYPT_MLKEM_PARAMETER_SET_1024; + } + + Debug.Fail($"Unknown MLKemAlgorithm: {algorithm.Name}"); + throw new PlatformNotSupportedException(); + } + + internal static string MLKemBlobMagicToBlobType(KeyBlobMagicNumber magicNumber) + { + return magicNumber switch + { + KeyBlobMagicNumber.BCRYPT_MLKEM_PRIVATE_SEED_MAGIC => KeyBlobType.BCRYPT_MLKEM_PRIVATE_SEED_BLOB, + KeyBlobMagicNumber.BCRYPT_MLKEM_PRIVATE_MAGIC => KeyBlobType.BCRYPT_MLKEM_PRIVATE_BLOB, + KeyBlobMagicNumber.BCRYPT_MLKEM_PUBLIC_MAGIC => KeyBlobType.BCRYPT_MLKEM_PUBLIC_BLOB, + KeyBlobMagicNumber other => throw Fail(other), + }; + + static CryptographicException Fail(KeyBlobMagicNumber other) + { + Debug.Fail($"Unknown blob type '{other}'."); + return new CryptographicException(); + } + } + + internal delegate TReturn EncodeMLKemBlobCallback( + TState state, + string blobKind, + ReadOnlySpan blob); + + internal static TReturn EncodeMLKemBlob( + KeyBlobMagicNumber kind, + MLKemAlgorithm algorithm, + ReadOnlySpan key, + TState state, + EncodeMLKemBlobCallback callback) + { + checked + { + // ML-KEM 1024 seeds are 86 byte blobs. Round it off to 128. + // Other keys like encapsulation or decapsulation keys will never fit in a stack buffer, so don't + // try to accommodate them. + const int MaxKeyStackSize = 128; + string parameterSet = GetMLKemParameterSet(algorithm); + int blobHeaderSize = Marshal.SizeOf(); + int parameterSetMarshalLength = (parameterSet.Length + 1) * 2; + int blobSize = + blobHeaderSize + + parameterSetMarshalLength + + key.Length; + + byte[]? rented = null; + Span buffer = (uint)blobSize <= MaxKeyStackSize ? + stackalloc byte[MaxKeyStackSize] : + (rented = CryptoPool.Rent(blobSize)); + + try + { + buffer.Clear(); + + unsafe + { + fixed (byte* pBuffer = buffer) + { + BCRYPT_MLKEM_KEY_BLOB* blob = (BCRYPT_MLKEM_KEY_BLOB*)pBuffer; + blob->dwMagic = kind; + blob->cbParameterSet = (uint)parameterSetMarshalLength; + blob->cbKey = (uint)key.Length; + } + } + + // This won't write the null byte, but we zeroed the whole buffer earlier. + Encoding.Unicode.GetBytes(parameterSet, buffer.Slice(blobHeaderSize)); + key.CopyTo(buffer.Slice(blobHeaderSize + parameterSetMarshalLength)); + string blobKind = MLKemBlobMagicToBlobType(kind); + return callback(state, blobKind, buffer.Slice(0, blobSize)); + } + finally + { + CryptographicOperations.ZeroMemory(buffer.Slice(0, blobSize)); + + if (rented is not null) + { + // buffer is a slice of rented which was zeroed, since it needs to be zeroed regardless of being + // a rent or a stack buffer. + CryptoPool.Return(rented, 0); + } + } + } + } } } diff --git a/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs b/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs index 5a4056ba37c704..40f3057e88bb7f 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/SlhDsa.cs @@ -556,7 +556,7 @@ public string ExportSubjectPublicKeyInfoPem() AsnWriter writer = ExportSubjectPublicKeyInfoCore(); // SPKI does not contain sensitive data. - return EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.SpkiPublicKey, writer, clear: false); } /// @@ -980,7 +980,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem( try { // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } finally { @@ -1031,7 +1031,7 @@ public string ExportEncryptedPkcs8PrivateKeyPem( try { // Skip clear since the data is already encrypted. - return EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); + return Helpers.EncodeAsnWriterToPem(PemLabels.EncryptedPkcs8PrivateKey, writer, clear: false); } finally { @@ -1217,7 +1217,7 @@ public static SlhDsa GenerateKey(SlhDsaAlgorithm algorithm) /// public static SlhDsa ImportSubjectPublicKeyInfo(ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); KeyFormatHelper.ReadSubjectPublicKeyInfo(s_knownOids, source, SubjectPublicKeyReader, out int read, out SlhDsa slhDsa); @@ -1280,7 +1280,7 @@ public static SlhDsa ImportSubjectPublicKeyInfo(byte[] source) /// public static SlhDsa ImportPkcs8PrivateKey(ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); KeyFormatHelper.ReadPkcs8( @@ -1360,7 +1360,7 @@ public static SlhDsa ImportPkcs8PrivateKey(byte[] source) /// public static SlhDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordBytes, ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -1409,7 +1409,7 @@ public static SlhDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan passwordB /// public static SlhDsa ImportEncryptedPkcs8PrivateKey(ReadOnlySpan password, ReadOnlySpan source) { - ThrowIfInvalidLength(source); + Helpers.ThrowIfAsnInvalidLength(source); ThrowIfNotSupported(); return KeyFormatHelper.DecryptPkcs8( @@ -2045,45 +2045,6 @@ private static void ThrowIfNotSupported() } } - private static void ThrowIfInvalidLength(ReadOnlySpan data) - { - int bytesRead; - try - { - AsnDecoder.ReadEncodedValue(data, AsnEncodingRules.BER, out _, out _, out bytesRead); - } - catch (AsnContentException ace) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding, ace); - } - - if (bytesRead != data.Length) - { - throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding); - } - } - - private static string EncodeAsnWriterToPem(string label, AsnWriter writer, bool clear = true) - { -#if NET10_0_OR_GREATER - return writer.Encode(label, static (label, span) => PemEncoding.WriteString(label, span)); -#else - int length = writer.GetEncodedLength(); - byte[] rent = CryptoPool.Rent(length); - - try - { - int written = writer.Encode(rent); - Debug.Assert(written == length); - return PemEncoding.WriteString(label, rent.AsSpan(0, written)); - } - finally - { - CryptoPool.Return(rent, clear ? length : 0); - } -#endif - } - private delegate TResult ExportPkcs8PrivateKeyFunc(ReadOnlySpan pkcs8); } } diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj index 57daaf088756da..22bd0002fc4f02 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/Microsoft.Bcl.Cryptography.csproj @@ -405,8 +405,6 @@ Link="Common\System\Security\Cryptography\PemLabels.cs" /> - - - -