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 @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Cryptography.X509Certificates;
using Microsoft.Win32.SafeHandles;

Expand Down Expand Up @@ -102,6 +103,29 @@ private static partial int CryptoNative_X509StoreSetVerifyTime(
[LibraryImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_CheckX509Hostname", StringMarshalling = StringMarshalling.Utf8)]
internal static partial int CheckX509Hostname(SafeX509Handle x509, string hostname, int cchHostname);

[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial int CryptoNative_IsSignatureAlgorithmAvailable(string algorithm);

internal static string? IsSignatureAlgorithmAvailable(string algorithm)
{
const int Available = 1;
const int NotAvailable = 0;

int ret = CryptoNative_IsSignatureAlgorithmAvailable(algorithm);
return ret switch
{
Available => algorithm,
NotAvailable => null,
int other => throw Fail(other),
};

static CryptographicException Fail(int result)
{
Debug.Fail($"Unexpected result {result} from {nameof(CryptoNative_IsSignatureAlgorithmAvailable)}");
return new CryptographicException();
}
}

internal static byte[] GetAsn1StringBytes(IntPtr asn1)
{
return GetDynamicBuffer(GetAsn1StringBytes, asn1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,13 +107,13 @@ internal static void EvpKemDecapsulate(SafeEvpPKeyHandle key, ReadOnlySpan<byte>
}

internal static void EvpKemExportPrivateSeed(SafeEvpPKeyHandle key, Span<byte> destination) =>
ExportKeyContents(key, destination, CryptoNative_EvpKemExportPrivateSeed);
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_EvpKemExportPrivateSeed);

internal static void EvpKemExportDecapsulationKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
ExportKeyContents(key, destination, CryptoNative_EvpKemExportDecapsulationKey);
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_EvpKemExportDecapsulationKey);

internal static void EvpKemExportEncapsulationKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
ExportKeyContents(key, destination, CryptoNative_EvpKemExportEncapsulationKey);
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_EvpKemExportEncapsulationKey);

internal static void EvpKemEncapsulate(SafeEvpPKeyHandle key, Span<byte> ciphertext, Span<byte> sharedSecret)
{
Expand All @@ -137,33 +137,5 @@ internal static void EvpKemEncapsulate(SafeEvpPKeyHandle key, Span<byte> ciphert
throw new CryptographicException();
}
}

private static void ExportKeyContents(
SafeEvpPKeyHandle key,
Span<byte> destination,
Func<SafeEvpPKeyHandle, Span<byte>, int, int> action)
{
const int Success = 1;
const int Fail = 0;
const int NotRetrievable = -1;

int ret = action(key, destination, destination.Length);

switch (ret)
{
case Success:
return;
case NotRetrievable:
destination.Clear();
throw new CryptographicException(SR.Cryptography_NotRetrievable);
case Fail:
destination.Clear();
throw CreateOpenSslCryptographicException();
default:
destination.Clear();
Debug.Fail($"Unexpected return value {ret}.");
throw new CryptographicException();
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Crypto
{
[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpPKeyHandle CryptoNative_MLDsaGenerateKey(string keyType, ReadOnlySpan<byte> seed, int seedLength);

internal static SafeEvpPKeyHandle MLDsaGenerateKey(string algorithmName, ReadOnlySpan<byte> seed)
{
SafeEvpPKeyHandle handle = CryptoNative_MLDsaGenerateKey(algorithmName, seed, seed.Length);
Debug.Assert(handle != null, "handle != null");

if (handle.IsInvalid)
{
Exception ex = Interop.Crypto.CreateOpenSslCryptographicException();
handle.Dispose();
throw ex;
}

return handle;
}

[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpPKeyHandle CryptoNative_MLDsaImportSecretKey(string keyType, ReadOnlySpan<byte> sk, int skLength);

internal static SafeEvpPKeyHandle MLDsaImportSecretKey(string algorithmName, ReadOnlySpan<byte> sk)
{
SafeEvpPKeyHandle? handle = CryptoNative_MLDsaImportSecretKey(algorithmName, sk, sk.Length);
Debug.Assert(handle != null, "handle != null");

if (handle.IsInvalid)
{
Exception ex = Interop.Crypto.CreateOpenSslCryptographicException();
handle.Dispose();
throw ex;
}

return handle;
}

[LibraryImport(Libraries.CryptoNative, StringMarshalling = StringMarshalling.Utf8)]
private static partial SafeEvpPKeyHandle CryptoNative_MLDsaImportPublicKey(string keyType, ReadOnlySpan<byte> pk, int pkLength);

internal static SafeEvpPKeyHandle MLDsaImportPublicKey(string algorithmName, ReadOnlySpan<byte> pk)
{
SafeEvpPKeyHandle handle = CryptoNative_MLDsaImportPublicKey(algorithmName, pk, pk.Length);
Debug.Assert(handle != null, "handle != null");

if (handle.IsInvalid)
{
Exception ex = Interop.Crypto.CreateOpenSslCryptographicException();
handle.Dispose();
throw ex;
}

return handle;
}

[LibraryImport(Libraries.CryptoNative)]
private static partial int CryptoNative_MLDsaSignPure(
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
ReadOnlySpan<byte> msg, int msgLength,
ReadOnlySpan<byte> context, int contextLength,
Span<byte> destination, int destinationLength);

internal static void MLDsaSignPure(
SafeEvpPKeyHandle pkey,
ReadOnlySpan<byte> msg,
ReadOnlySpan<byte> context,
Span<byte> destination)
{
int ret = CryptoNative_MLDsaSignPure(
pkey, pkey.ExtraHandle,
msg, msg.Length,
context, context.Length,
destination, destination.Length);

if (ret != 1)
{
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
}

[LibraryImport(Libraries.CryptoNative)]
private static partial int CryptoNative_MLDsaVerifyPure(
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
ReadOnlySpan<byte> msg, int msgLength,
ReadOnlySpan<byte> context, int contextLength,
ReadOnlySpan<byte> signature, int signatureLength);

internal static bool MLDsaVerifyPure(
SafeEvpPKeyHandle pkey,
ReadOnlySpan<byte> msg,
ReadOnlySpan<byte> context,
ReadOnlySpan<byte> signature)
{
int ret = CryptoNative_MLDsaVerifyPure(
pkey, pkey.ExtraHandle,
msg, msg.Length,
context, context.Length,
signature, signature.Length);

if (ret == 1)
{
return true;
}
else if (ret == 0)
{
return false;
}
else
{
throw Interop.Crypto.CreateOpenSslCryptographicException();
}
}

[LibraryImport(Libraries.CryptoNative)]
private static partial int CryptoNative_MLDsaExportSecretKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);

[LibraryImport(Libraries.CryptoNative)]
private static partial int CryptoNative_MLDsaExportSeed(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);

[LibraryImport(Libraries.CryptoNative)]
private static partial int CryptoNative_MLDsaExportPublicKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);

internal static void MLDsaExportSecretKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_MLDsaExportSecretKey);

internal static void MLDsaExportSeed(SafeEvpPKeyHandle key, Span<byte> destination) =>
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_MLDsaExportSeed);

internal static void MLDsaExportPublicKey(SafeEvpPKeyHandle key, Span<byte> destination) =>
Interop.Crypto.ExportKeyContents(key, destination, CryptoNative_MLDsaExportPublicKey);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using Microsoft.Win32.SafeHandles;

internal static partial class Interop
{
internal static partial class Crypto
{
internal static partial class EvpPKeyMLDsaAlgs
{
internal static string? MLDsa44 { get; }
internal static string? MLDsa65 { get; }
internal static string? MLDsa87 { get; }

static EvpPKeyMLDsaAlgs()
{
CryptoInitializer.Initialize();

// Do not use property initializers for these because we need to ensure CryptoInitializer.Initialize
// is called first. Property initializers happen before cctors, so instead set the property after the
// initializer is run.
MLDsa44 = IsSignatureAlgorithmAvailable(MLDsaAlgorithm.MLDsa44.Name);
MLDsa65 = IsSignatureAlgorithmAvailable(MLDsaAlgorithm.MLDsa65.Name);
MLDsa87 = IsSignatureAlgorithmAvailable(MLDsaAlgorithm.MLDsa87.Name);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,34 @@ internal static SafeEvpPKeyHandle LoadKeyFromProvider(
}
}

internal static void ExportKeyContents(
SafeEvpPKeyHandle key,
Span<byte> destination,
Func<SafeEvpPKeyHandle, Span<byte>, int, int> action)
{
const int Success = 1;
const int Fail = 0;
const int NotRetrievable = -1;

int ret = action(key, destination, destination.Length);

switch (ret)
{
case Success:
return;
case NotRetrievable:
destination.Clear();
throw new CryptographicException(SR.Cryptography_NotRetrievable);
case Fail:
destination.Clear();
throw CreateOpenSslCryptographicException();
default:
destination.Clear();
Debug.Fail($"Unexpected return value {ret}.");
throw new CryptographicException();
}
}

internal enum EvpAlgorithmId
{
Unknown = 0,
Expand Down
Loading
Loading