mirror of https://github.com/dotnet/runtime
Merge 9a34f67a9b
into 02596ba8d9
This commit is contained in:
commit
1fe2d953b3
|
@ -184,6 +184,65 @@ internal static partial class Interop
|
|||
}
|
||||
}
|
||||
|
||||
[LibraryImport(Libraries.CryptoNative)]
|
||||
private static partial int CryptoNative_MLDsaSignExternalMu(
|
||||
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
|
||||
ReadOnlySpan<byte> mu, int muLength,
|
||||
Span<byte> destination, int destinationLength);
|
||||
|
||||
internal static void MLDsaSignExternalMu(
|
||||
SafeEvpPKeyHandle pkey,
|
||||
ReadOnlySpan<byte> mu,
|
||||
Span<byte> destination)
|
||||
{
|
||||
const int Success = 1;
|
||||
const int SigningFailure = 0;
|
||||
|
||||
int ret = CryptoNative_MLDsaSignExternalMu(
|
||||
pkey, GetExtraHandle(pkey),
|
||||
mu, mu.Length,
|
||||
destination, destination.Length);
|
||||
|
||||
if (ret != Success)
|
||||
{
|
||||
Debug.Assert(ret == SigningFailure, $"Unexpected return value {ret} from {nameof(CryptoNative_MLDsaSignExternalMu)}.");
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport(Libraries.CryptoNative)]
|
||||
private static partial int CryptoNative_MLDsaVerifyExternalMu(
|
||||
SafeEvpPKeyHandle pkey, IntPtr extraHandle,
|
||||
ReadOnlySpan<byte> mu, int muLength,
|
||||
ReadOnlySpan<byte> signature, int signatureLength);
|
||||
|
||||
internal static bool MLDsaVerifyExternalMu(
|
||||
SafeEvpPKeyHandle pkey,
|
||||
ReadOnlySpan<byte> mu,
|
||||
ReadOnlySpan<byte> signature)
|
||||
{
|
||||
const int ValidSignature = 1;
|
||||
const int InvalidSignature = 0;
|
||||
|
||||
int ret = CryptoNative_MLDsaVerifyExternalMu(
|
||||
pkey, GetExtraHandle(pkey),
|
||||
mu, mu.Length,
|
||||
signature, signature.Length);
|
||||
|
||||
if (ret == ValidSignature)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (ret == InvalidSignature)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw Interop.Crypto.CreateOpenSslCryptographicException();
|
||||
}
|
||||
}
|
||||
|
||||
[LibraryImport(Libraries.CryptoNative)]
|
||||
private static partial int CryptoNative_MLDsaExportSecretKey(SafeEvpPKeyHandle pkey, Span<byte> destination, int destinationLength);
|
||||
|
||||
|
|
|
@ -264,5 +264,18 @@ namespace Internal.Cryptography
|
|||
throw new CryptographicException(SR.Cryptography_Der_Invalid_Encoding);
|
||||
}
|
||||
}
|
||||
|
||||
#if !BUILDING_PKCS
|
||||
internal static void ThrowIfDestinationWrongLength(
|
||||
Span<byte> destination,
|
||||
int expectedLength,
|
||||
[System.Runtime.CompilerServices.CallerArgumentExpression(nameof(destination))] string? paramName = null)
|
||||
{
|
||||
if (destination.Length != expectedLength)
|
||||
{
|
||||
throw new ArgumentException(SR.Format(SR.Argument_DestinationImprecise, expectedLength), paramName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
|
|
@ -120,14 +120,7 @@ namespace System.Security.Cryptography
|
|||
/// </exception>
|
||||
public void SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpan<byte> context = default)
|
||||
{
|
||||
int signatureSizeInBytes = Algorithm.SignatureSizeInBytes;
|
||||
|
||||
if (destination.Length != signatureSizeInBytes)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
SR.Format(SR.Argument_DestinationImprecise, signatureSizeInBytes),
|
||||
nameof(destination));
|
||||
}
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.SignatureSizeInBytes);
|
||||
|
||||
if (context.Length > MaxContextLength)
|
||||
{
|
||||
|
@ -309,13 +302,7 @@ namespace System.Security.Cryptography
|
|||
public void SignPreHash(ReadOnlySpan<byte> hash, Span<byte> destination, string hashAlgorithmOid, ReadOnlySpan<byte> context = default)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(hashAlgorithmOid);
|
||||
|
||||
if (destination.Length != Algorithm.SignatureSizeInBytes)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
SR.Format(SR.Argument_DestinationImprecise, Algorithm.SignatureSizeInBytes),
|
||||
nameof(destination));
|
||||
}
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.SignatureSizeInBytes);
|
||||
|
||||
if (context.Length > MaxContextLength)
|
||||
{
|
||||
|
@ -507,6 +494,155 @@ namespace System.Security.Cryptography
|
|||
new ReadOnlySpan<byte>(context));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="SignMu(ReadOnlySpan{byte})"/>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="externalMu"/> is <see langword="null"/>.</exception>
|
||||
public byte[] SignMu(byte[] externalMu)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(externalMu);
|
||||
|
||||
return SignMu(new ReadOnlySpan<byte>(externalMu));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signs the specified externally computed signature mu (μ) value.
|
||||
/// </summary>
|
||||
/// <param name="externalMu">
|
||||
/// The signature mu value to sign.
|
||||
/// </param>
|
||||
/// <returns>
|
||||
/// ML-DSA signature for the specified mu value.
|
||||
/// </returns>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// The buffer in <paramref name="externalMu"/> is the incorrect length for the signature mu value.
|
||||
/// </exception>
|
||||
/// <exception cref="ObjectDisposedException">
|
||||
/// This instance has been disposed.
|
||||
/// </exception>
|
||||
/// <exception cref="CryptographicException">
|
||||
/// <para>The instance represents only a public key.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para>An error occurred while signing the hash.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="PlatformNotSupportedException">
|
||||
/// The current platform does not support signing with an externally computed mu value.
|
||||
/// </exception>
|
||||
/// <seealso cref="VerifyMu(byte[], byte[])"/>
|
||||
public byte[] SignMu(ReadOnlySpan<byte> externalMu)
|
||||
{
|
||||
byte[] destination = new byte[Algorithm.SignatureSizeInBytes];
|
||||
SignMu(externalMu, destination.AsSpan());
|
||||
return destination;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signs the specified externally computed signature mu (μ) value,
|
||||
/// writing the signature into the provided buffer.
|
||||
/// </summary>
|
||||
/// <param name="externalMu">
|
||||
/// The signature mu value to sign.
|
||||
/// </param>
|
||||
/// <param name="destination">
|
||||
/// The buffer to receive the signature. Its length must be exactly
|
||||
/// <see cref="MLDsaAlgorithm.SignatureSizeInBytes"/>.
|
||||
/// </param>
|
||||
/// <exception cref="ArgumentException">
|
||||
/// <para>
|
||||
/// The buffer in <paramref name="externalMu"/> is the incorrect length for the signature mu value.
|
||||
/// </para>
|
||||
/// <para>-or-</para>
|
||||
/// <para>
|
||||
/// The buffer in <paramref name="destination"/> is the incorrect length to receive the signature.
|
||||
/// </para>
|
||||
/// </exception>
|
||||
/// <exception cref="ObjectDisposedException">
|
||||
/// This instance has been disposed.
|
||||
/// </exception>
|
||||
/// <exception cref="CryptographicException">
|
||||
/// <para>The instance represents only a public key.</para>
|
||||
/// <para>-or-</para>
|
||||
/// <para>An error occurred while signing the hash.</para>
|
||||
/// </exception>
|
||||
/// <exception cref="PlatformNotSupportedException">
|
||||
/// The current platform does not support signing with an externally computed mu value.
|
||||
/// </exception>
|
||||
/// <seealso cref="VerifyMu(ReadOnlySpan{byte}, ReadOnlySpan{byte})"/>
|
||||
public void SignMu(ReadOnlySpan<byte> externalMu, Span<byte> destination)
|
||||
{
|
||||
if (externalMu.Length != Algorithm.MuSizeInBytes)
|
||||
throw new ArgumentException(SR.Argument_MLDsaMuInvalidLength, nameof(externalMu));
|
||||
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.SignatureSizeInBytes);
|
||||
ThrowIfDisposed();
|
||||
|
||||
SignMuCore(externalMu, destination);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class, computes the remainder of the signature from the
|
||||
/// precomputed mu (μ) value, writing it into the provided buffer.
|
||||
/// </summary>
|
||||
/// <param name="externalMu">
|
||||
/// The signature mu value to sign.
|
||||
/// </param>
|
||||
/// <param name="destination">
|
||||
/// The buffer to receive the signature, which will always be the exactly correct size for the algorithm.
|
||||
/// </param>
|
||||
/// <exception cref="CryptographicException">
|
||||
/// An error occurred while computing the signature.
|
||||
/// </exception>
|
||||
protected abstract void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination);
|
||||
|
||||
/// <inheritdoc cref="VerifyMu(ReadOnlySpan{byte}, ReadOnlySpan{byte})"/>
|
||||
/// <exception cref="ArgumentNullException">
|
||||
/// <paramref name="externalMu"/> or <paramref name="signature"/> is <see langword="null"/>.
|
||||
/// </exception>
|
||||
public bool VerifyMu(byte[] externalMu, byte[] signature)
|
||||
{
|
||||
ArgumentNullException.ThrowIfNull(externalMu);
|
||||
ArgumentNullException.ThrowIfNull(signature);
|
||||
|
||||
return VerifyMu(new ReadOnlySpan<byte>(externalMu), new ReadOnlySpan<byte>(signature));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that a digital signature is valid for the provided externally computed signature mu (μ) value.
|
||||
/// </summary>
|
||||
/// <param name="externalMu">The signature mu value.</param>
|
||||
/// <param name="signature">The signature to verify.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the digital signature is valid for the provided mu value;
|
||||
/// otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
/// <exception cref="ObjectDisposedException">
|
||||
/// This instance has been disposed.
|
||||
/// </exception>
|
||||
/// <exception cref="CryptographicException">An error occurred while verifying the mu value.</exception>
|
||||
/// <exception cref="PlatformNotSupportedException">
|
||||
/// The current platform does not support verification with an externally computed mu value.
|
||||
/// </exception>
|
||||
public bool VerifyMu(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature)
|
||||
{
|
||||
if (externalMu.Length != Algorithm.MuSizeInBytes || signature.Length != Algorithm.SignatureSizeInBytes)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
ThrowIfDisposed();
|
||||
|
||||
return VerifyMuCore(externalMu, signature);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// When overridden in a derived class,
|
||||
/// verifies that a digital signature is valid for the provided externally computed signature mu (μ) value.
|
||||
/// </summary>
|
||||
/// <param name="externalMu">The signature mu value.</param>
|
||||
/// <param name="signature">The signature to verify.</param>
|
||||
/// <returns>
|
||||
/// <see langword="true"/> if the mu value is valid; otherwise, <see langword="false"/>.
|
||||
/// </returns>
|
||||
protected abstract bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature);
|
||||
|
||||
/// <summary>
|
||||
/// Exports the public-key portion of the current key in the X.509 SubjectPublicKeyInfo format.
|
||||
/// </summary>
|
||||
|
@ -1063,15 +1199,7 @@ namespace System.Security.Cryptography
|
|||
/// </remarks>
|
||||
public void ExportMLDsaPublicKey(Span<byte> destination)
|
||||
{
|
||||
int publicKeySizeInBytes = Algorithm.PublicKeySizeInBytes;
|
||||
|
||||
if (destination.Length != publicKeySizeInBytes)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
SR.Format(SR.Argument_DestinationImprecise, publicKeySizeInBytes),
|
||||
nameof(destination));
|
||||
}
|
||||
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.PublicKeySizeInBytes);
|
||||
ThrowIfDisposed();
|
||||
|
||||
ExportMLDsaPublicKeyCore(destination);
|
||||
|
@ -1113,15 +1241,7 @@ namespace System.Security.Cryptography
|
|||
/// </exception>
|
||||
public void ExportMLDsaSecretKey(Span<byte> destination)
|
||||
{
|
||||
int secretKeySizeInBytes = Algorithm.SecretKeySizeInBytes;
|
||||
|
||||
if (destination.Length != secretKeySizeInBytes)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
SR.Format(SR.Argument_DestinationImprecise, secretKeySizeInBytes),
|
||||
nameof(destination));
|
||||
}
|
||||
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.SecretKeySizeInBytes);
|
||||
ThrowIfDisposed();
|
||||
|
||||
ExportMLDsaSecretKeyCore(destination);
|
||||
|
@ -1161,14 +1281,7 @@ namespace System.Security.Cryptography
|
|||
/// </exception>
|
||||
public void ExportMLDsaPrivateSeed(Span<byte> destination)
|
||||
{
|
||||
int privateSeedSizeInBytes = Algorithm.PrivateSeedSizeInBytes;
|
||||
if (destination.Length != privateSeedSizeInBytes)
|
||||
{
|
||||
throw new ArgumentException(
|
||||
SR.Format(SR.Argument_DestinationImprecise, privateSeedSizeInBytes),
|
||||
nameof(destination));
|
||||
}
|
||||
|
||||
Helpers.ThrowIfDestinationWrongLength(destination, Algorithm.PrivateSeedSizeInBytes);
|
||||
ThrowIfDisposed();
|
||||
|
||||
ExportMLDsaPrivateSeedCore(destination);
|
||||
|
|
|
@ -53,6 +53,14 @@ namespace System.Security.Cryptography
|
|||
/// </value>
|
||||
public int SignatureSizeInBytes { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the size, in bytes, of the mu (μ) value for the current ML-DSA algorithm.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The size, in bytes, of the mu (μ) value for the current ML-DSA algorithm.
|
||||
/// </value>
|
||||
public int MuSizeInBytes => 64;
|
||||
|
||||
internal string Oid { get; }
|
||||
internal int LambdaCollisionStrength { get; }
|
||||
|
||||
|
|
|
@ -48,6 +48,14 @@ namespace System.Security.Cryptography
|
|||
_key = duplicateKey;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> mu, Span<byte> destination) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> mu, ReadOnlySpan<byte> signature) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
private static MLDsaAlgorithm AlgorithmFromHandleWithPlatformCheck(CngKey key, out CngKey duplicateKey)
|
||||
{
|
||||
if (!Helpers.IsOSPlatformWindows)
|
||||
|
|
|
@ -31,6 +31,12 @@ namespace System.Security.Cryptography
|
|||
protected override bool VerifyPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> mu, Span<byte> destination) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> mu, ReadOnlySpan<byte> signature) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
protected override void ExportMLDsaPublicKeyCore(Span<byte> destination) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
|
|
|
@ -91,6 +91,12 @@ namespace System.Security.Cryptography
|
|||
return Interop.BCrypt.BCryptVerifySignaturePqcPreHash(_key, hash, hashAlgorithmIdentifier, context, signature);
|
||||
}
|
||||
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature) =>
|
||||
throw new PlatformNotSupportedException();
|
||||
|
||||
internal static partial MLDsaImplementation GenerateKeyImpl(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
Debug.Assert(SupportsAny());
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace System.Security.Cryptography.Tests
|
|||
// TODO: Windows does not support signing empty data. Remove this and use MLDsa.IsSupported (or remove condition) when it does.
|
||||
internal static bool SigningEmptyDataIsSupported => MLDsa.IsSupported && !PlatformDetection.IsWindows;
|
||||
|
||||
internal static bool ExternalMuIsSupported => MLDsa.IsSupported && !PlatformDetection.IsWindows;
|
||||
|
||||
// DER encoding of ASN.1 BitString "foo"
|
||||
internal static readonly ReadOnlyMemory<byte> s_derBitStringFoo = new byte[] { 0x03, 0x04, 0x00, 0x66, 0x6f, 0x6f };
|
||||
|
||||
|
@ -28,29 +30,48 @@ namespace System.Security.Cryptography.Tests
|
|||
internal static void VerifyDisposed(MLDsa mldsa)
|
||||
{
|
||||
PbeParameters pbeParams = new PbeParameters(PbeEncryptionAlgorithm.Aes128Cbc, HashAlgorithmName.SHA256, 10);
|
||||
byte[] signature = new byte[mldsa.Algorithm.SignatureSizeInBytes];
|
||||
byte[] bigBuffer = new byte[10000];
|
||||
byte[] mu = new byte[64];
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignData(ReadOnlySpan<byte>.Empty, new byte[mldsa.Algorithm.SignatureSizeInBytes]));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyData(ReadOnlySpan<byte>.Empty, new byte[mldsa.Algorithm.SignatureSizeInBytes]));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignData(Array.Empty<byte>()));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignData(ReadOnlySpan<byte>.Empty, signature));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyData(Array.Empty<byte>(), signature));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyData(ReadOnlySpan<byte>.Empty, signature));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignPreHash(mu, HashInfo.Sha512.Oid));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignPreHash(mu, signature, HashInfo.Sha512.Oid));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyPreHash(mu, signature, HashInfo.Sha512.Oid));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyPreHash(new ReadOnlySpan<byte>(mu), signature, HashInfo.Sha512.Oid));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignMu(mu));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.SignMu(new ReadOnlySpan<byte>(mu)));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyMu(mu, signature));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.VerifyMu(new ReadOnlySpan<byte>(mu), signature));
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaPrivateSeed());
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaPrivateSeed(new byte[mldsa.Algorithm.PrivateSeedSizeInBytes]));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaPublicKey());
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaPublicKey(new byte[mldsa.Algorithm.PublicKeySizeInBytes]));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaSecretKey());
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportMLDsaSecretKey(new byte[mldsa.Algorithm.SecretKeySizeInBytes]));
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportPkcs8PrivateKey());
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportPkcs8PrivateKey(new byte[10000], out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportPkcs8PrivateKey(bigBuffer, out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportPkcs8PrivateKeyPem());
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportEncryptedPkcs8PrivateKey([1, 2, 3], pbeParams));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportEncryptedPkcs8PrivateKey("123", pbeParams));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportEncryptedPkcs8PrivateKey([1, 2, 3], pbeParams, new byte[10000], out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportEncryptedPkcs8PrivateKey("123", pbeParams, new byte[10000], out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportEncryptedPkcs8PrivateKey([1, 2, 3], pbeParams, bigBuffer, out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportEncryptedPkcs8PrivateKey("123", pbeParams, bigBuffer, out _));
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportEncryptedPkcs8PrivateKeyPem([1, 2, 3], pbeParams));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportEncryptedPkcs8PrivateKeyPem("123", pbeParams));
|
||||
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportSubjectPublicKeyInfo());
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportSubjectPublicKeyInfo(new byte[10000], out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.TryExportSubjectPublicKeyInfo(bigBuffer, out _));
|
||||
Assert.Throws<ObjectDisposedException>(() => mldsa.ExportSubjectPublicKeyInfoPem());
|
||||
|
||||
// Doesn't throw:
|
||||
Assert.NotNull(mldsa.Algorithm);
|
||||
}
|
||||
|
||||
internal static void AssertImportPublicKey(Action<Func<MLDsa>> test, MLDsaAlgorithm algorithm, byte[] publicKey) =>
|
||||
|
|
|
@ -13,11 +13,16 @@ namespace System.Security.Cryptography.Tests
|
|||
internal delegate bool VerifyFunc(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, ReadOnlySpan<byte> signature);
|
||||
internal delegate void SignPreHashAction(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, Span<byte> destination);
|
||||
internal delegate bool VerifyPreHashFunc(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature);
|
||||
internal delegate void SignMuAction(ReadOnlySpan<byte> mu, Span<byte> destination);
|
||||
internal delegate bool VerifyMuFunc(ReadOnlySpan<byte> mu, ReadOnlySpan<byte> signature);
|
||||
|
||||
internal int VerifyDataCoreCallCount = 0;
|
||||
internal int SignDataCoreCallCount = 0;
|
||||
internal int SignPreHashCoreCallCount = 0;
|
||||
internal int VerifyPreHashCoreCallCount = 0;
|
||||
internal int OpenExternalMuHashCoreCallCount = 0;
|
||||
internal int SignMuCoreCallCount = 0;
|
||||
internal int VerifyMuCoreCallCount = 0;
|
||||
internal int ExportMLDsaPrivateSeedCoreCallCount = 0;
|
||||
internal int ExportMLDsaPublicKeyCoreCallCount = 0;
|
||||
internal int ExportMLDsaSecretKeyCoreCallCount = 0;
|
||||
|
@ -32,6 +37,8 @@ namespace System.Security.Cryptography.Tests
|
|||
internal VerifyFunc VerifyDataHook { get; set; }
|
||||
internal SignPreHashAction SignPreHashHook { get; set; }
|
||||
internal VerifyPreHashFunc VerifyPreHashHook { get; set; }
|
||||
internal SignMuAction SignMuHook { get; set; }
|
||||
internal VerifyMuFunc VerifyMuHook { get; set; }
|
||||
internal Action<bool> DisposeHook { get; set; }
|
||||
|
||||
private MLDsaTestImplementation(MLDsaAlgorithm algorithm) : base(algorithm)
|
||||
|
@ -85,12 +92,25 @@ namespace System.Security.Cryptography.Tests
|
|||
SignPreHashCoreCallCount++;
|
||||
SignPreHashHook(hash, context, hashAlgorithmOid, destination);
|
||||
}
|
||||
|
||||
protected override bool VerifyPreHashCore(ReadOnlySpan<byte> hash, ReadOnlySpan<byte> context, string hashAlgorithmOid, ReadOnlySpan<byte> signature)
|
||||
{
|
||||
VerifyPreHashCoreCallCount++;
|
||||
return VerifyPreHashHook(hash, context, hashAlgorithmOid, signature);
|
||||
}
|
||||
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination)
|
||||
{
|
||||
SignMuCoreCallCount++;
|
||||
SignMuHook(externalMu, destination);
|
||||
}
|
||||
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature)
|
||||
{
|
||||
VerifyMuCoreCallCount++;
|
||||
return VerifyMuHook(externalMu, signature);
|
||||
}
|
||||
|
||||
internal static MLDsaTestImplementation CreateOverriddenCoreMethodsFail(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
return new MLDsaTestImplementation(algorithm)
|
||||
|
@ -100,8 +120,10 @@ namespace System.Security.Cryptography.Tests
|
|||
ExportMLDsaSecretKeyHook = _ => Assert.Fail(),
|
||||
SignDataHook = (_, _, _) => Assert.Fail(),
|
||||
SignPreHashHook = delegate { Assert.Fail(); },
|
||||
SignMuHook = (_, _) => Assert.Fail(),
|
||||
VerifyDataHook = (_, _, _) => { Assert.Fail(); return false; },
|
||||
VerifyPreHashHook = delegate { Assert.Fail(); return false; },
|
||||
VerifyPreHashHook = (_, _, _, _) => { Assert.Fail(); return false; },
|
||||
VerifyMuHook = (_, _) => { Assert.Fail(); return false; },
|
||||
DisposeHook = _ => { },
|
||||
|
||||
TryExportPkcs8PrivateKeyHook = (_, out bytesWritten) =>
|
||||
|
@ -122,6 +144,10 @@ namespace System.Security.Cryptography.Tests
|
|||
ExportMLDsaSecretKeyHook = d => d.Clear(),
|
||||
SignDataHook = (data, context, destination) => destination.Clear(),
|
||||
VerifyDataHook = (data, context, signature) => false,
|
||||
SignPreHashHook = (hash, context, hashAlgorithmOid, destination) => destination.Clear(),
|
||||
VerifyPreHashHook = (hash, context, hashAlgorithmOid, signature) => false,
|
||||
SignMuHook = (mu, destination) => destination.Clear(),
|
||||
VerifyMuHook = (mu, signature) => false,
|
||||
DisposeHook = _ => { },
|
||||
|
||||
TryExportPkcs8PrivateKeyHook = (Span<byte> destination, out int bytesWritten) =>
|
||||
|
@ -202,6 +228,23 @@ namespace System.Security.Cryptography.Tests
|
|||
Assert.Equal(Algorithm.SignatureSizeInBytes, signature.Length);
|
||||
return ret;
|
||||
};
|
||||
|
||||
SignMuAction oldSignExternalMuHook = SignMuHook;
|
||||
SignMuHook = (ReadOnlySpan<byte> mu, Span<byte> destination) =>
|
||||
{
|
||||
oldSignExternalMuHook(mu, destination);
|
||||
Assert.Equal(64, mu.Length);
|
||||
Assert.Equal(Algorithm.SignatureSizeInBytes, destination.Length);
|
||||
};
|
||||
|
||||
VerifyMuFunc oldVerifyExternalMuHook = VerifyMuHook;
|
||||
VerifyMuHook = (ReadOnlySpan<byte> mu, ReadOnlySpan<byte> signature) =>
|
||||
{
|
||||
bool ret = oldVerifyExternalMuHook(mu, signature);
|
||||
Assert.Equal(64, mu.Length);
|
||||
Assert.Equal(Algorithm.SignatureSizeInBytes, signature.Length);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
public void AddDestinationBufferIsSameAssertion(ReadOnlyMemory<byte> buffer)
|
||||
|
@ -333,6 +376,21 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.Same(buffer.Span, hash);
|
||||
return ret;
|
||||
};
|
||||
|
||||
SignMuAction oldSignExternalMuHook = SignMuHook;
|
||||
SignMuHook = (ReadOnlySpan<byte> mu, Span<byte> destination) =>
|
||||
{
|
||||
oldSignExternalMuHook(mu, destination);
|
||||
AssertExtensions.Same(buffer.Span, mu);
|
||||
};
|
||||
|
||||
VerifyMuFunc oldVerifyExternalMuHook = VerifyMuHook;
|
||||
VerifyMuHook = (ReadOnlySpan<byte> mu, ReadOnlySpan<byte> signature) =>
|
||||
{
|
||||
bool ret = oldVerifyExternalMuHook(mu, signature);
|
||||
AssertExtensions.Same(buffer.Span, mu);
|
||||
return ret;
|
||||
};
|
||||
}
|
||||
|
||||
public void AddHashAlgorithmIsSameAssertion(ReadOnlyMemory<char> buffer)
|
||||
|
|
|
@ -6,7 +6,6 @@ using System.Formats.Asn1;
|
|||
using System.Linq;
|
||||
using System.Security.Cryptography.Asn1;
|
||||
using Microsoft.DotNet.RemoteExecutor;
|
||||
using Microsoft.DotNet.XUnitExtensions;
|
||||
using Test.Cryptography;
|
||||
using Xunit;
|
||||
|
||||
|
@ -86,6 +85,10 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.Throws<ArgumentNullException>("signature", () => mldsa.VerifyPreHash(hash, null, null));
|
||||
AssertExtensions.Throws<ArgumentNullException>("hashAlgorithmOid", () => mldsa.VerifyPreHash(hash, signature, null));
|
||||
|
||||
AssertExtensions.Throws<ArgumentNullException>("externalMu", () => mldsa.SignMu(null));
|
||||
AssertExtensions.Throws<ArgumentNullException>("externalMu", () => mldsa.VerifyMu(null, null));
|
||||
AssertExtensions.Throws<ArgumentNullException>("signature", () => mldsa.VerifyMu(Array.Empty<byte>(), null));
|
||||
|
||||
AssertExtensions.Throws<ArgumentNullException>("password", () => mldsa.ExportEncryptedPkcs8PrivateKey((string)null, pbeParameters));
|
||||
AssertExtensions.Throws<ArgumentNullException>("password", () => mldsa.ExportEncryptedPkcs8PrivateKeyPem((string)null, pbeParameters));
|
||||
AssertExtensions.Throws<ArgumentNullException>("password", () => mldsa.TryExportEncryptedPkcs8PrivateKey((string)null, pbeParameters, Span<byte>.Empty, out _));
|
||||
|
@ -113,6 +116,11 @@ namespace System.Security.Cryptography.Tests
|
|||
int signatureSize = algorithm.SignatureSizeInBytes;
|
||||
byte[] signature = new byte[signatureSize];
|
||||
byte[] hash = new byte[HashInfo.Sha256.OutputSize];
|
||||
byte[] mu = new byte[64];
|
||||
byte[] shortMu = new byte[mu.Length - 1];
|
||||
byte[] longMu = new byte[mu.Length + 1];
|
||||
byte[] shortSignature = new byte[signatureSize - 1];
|
||||
byte[] longSignature = new byte[signatureSize + 1];
|
||||
|
||||
if (shouldDispose)
|
||||
{
|
||||
|
@ -126,10 +134,12 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.ExportMLDsaSecretKey(new byte[secretKeySize + 1]));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.ExportMLDsaPrivateSeed(new byte[privateSeedSize - 1]));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.ExportMLDsaPrivateSeed(new byte[privateSeedSize + 1]));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignData(ReadOnlySpan<byte>.Empty, new byte[signatureSize - 1], ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignData(ReadOnlySpan<byte>.Empty, new byte[signatureSize + 1], ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize], new byte[signatureSize - 1], HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize], new byte[signatureSize + 1], HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignData(ReadOnlySpan<byte>.Empty, shortSignature, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignData(ReadOnlySpan<byte>.Empty, longSignature, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignMu(mu, shortSignature));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignMu(mu, longSignature));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize], shortSignature, HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<ArgumentException>("destination", () => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize], longSignature, HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
|
||||
// Context length must be less than 256
|
||||
AssertExtensions.Throws<ArgumentOutOfRangeException>("context", () => mldsa.SignData(ReadOnlySpan<byte>.Empty, signature, new byte[256]));
|
||||
|
@ -139,6 +149,12 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.Throws<ArgumentOutOfRangeException>("context", () => mldsa.SignPreHash(hash.AsSpan(), signature, HashInfo.Sha256.Oid, new byte[256]));
|
||||
AssertExtensions.Throws<ArgumentOutOfRangeException>("context", () => mldsa.SignPreHash(hash, HashInfo.Sha256.Oid, new byte[256]));
|
||||
|
||||
// Mu must be the correct size
|
||||
AssertExtensions.Throws<ArgumentException>("externalMu", () => mldsa.SignMu(shortMu));
|
||||
AssertExtensions.Throws<ArgumentException>("externalMu", () => mldsa.SignMu(longMu));
|
||||
AssertExtensions.Throws<ArgumentException>("externalMu", () => mldsa.SignMu(shortMu, signature));
|
||||
AssertExtensions.Throws<ArgumentException>("externalMu", () => mldsa.SignMu(longMu, signature));
|
||||
|
||||
// Hash length of known OID hash algorithms must be correct
|
||||
AssertExtensions.Throws<CryptographicException>(() => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize - 1], new byte[signatureSize], HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
AssertExtensions.Throws<CryptographicException>(() => mldsa.SignPreHash(new byte[HashInfo.Sha512.OutputSize + 1], new byte[signatureSize], HashInfo.Sha512.Oid, ReadOnlySpan<byte>.Empty));
|
||||
|
@ -915,6 +931,82 @@ namespace System.Security.Cryptography.Tests
|
|||
});
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public static void SignExternalMu_GetsMuAndDestination(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsaTestImplementation mldsa = MLDsaTestImplementation.CreateOverriddenCoreMethodsFail(algorithm);
|
||||
int signatureSize = algorithm.SignatureSizeInBytes;
|
||||
byte[] buffer = CreatePaddedFilledArray(signatureSize, 0x42);
|
||||
Memory<byte> signature = buffer.AsMemory(PaddingSize, signatureSize);
|
||||
byte[] mu = new byte[64];
|
||||
|
||||
mldsa.SignMuHook = (mu, destination) => destination.Fill(0xAB);
|
||||
mldsa.AddLengthAssertion();
|
||||
mldsa.AddDataBufferIsSameAssertion(mu);
|
||||
mldsa.AddDestinationBufferIsSameAssertion(signature);
|
||||
|
||||
mldsa.SignMu(mu, signature.Span);
|
||||
Assert.Equal(1, mldsa.SignMuCoreCallCount);
|
||||
|
||||
AssertExpectedFill(buffer, fillElement: 0xAB, paddingElement: 0x42, PaddingSize, signatureSize);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public static void VerifyExternalMu_GetsMuAndSignature(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsaTestImplementation mldsa = MLDsaTestImplementation.CreateOverriddenCoreMethodsFail(algorithm);
|
||||
byte[] buffer = CreatePaddedFilledArray(algorithm.SignatureSizeInBytes, 0x42);
|
||||
Memory<byte> signature = buffer.AsMemory(PaddingSize, algorithm.SignatureSizeInBytes);
|
||||
byte[] mu = new byte[64];
|
||||
|
||||
mldsa.VerifyMuHook = (mu, signature) => true;
|
||||
mldsa.AddLengthAssertion();
|
||||
mldsa.AddDataBufferIsSameAssertion(mu);
|
||||
mldsa.AddDestinationBufferIsSameAssertion(signature);
|
||||
|
||||
mldsa.VerifyMu(mu, signature.Span);
|
||||
Assert.Equal(1, mldsa.VerifyMuCoreCallCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public static void VerifyExternalMu_EarlyFalseForWrongSizeMu(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsaTestImplementation mldsa = MLDsaTestImplementation.CreateOverriddenCoreMethodsFail(algorithm);
|
||||
byte[] mu = new byte[100];
|
||||
byte[] signature = new byte[mldsa.Algorithm.SignatureSizeInBytes];
|
||||
const int CorrectMuLength = 64;
|
||||
|
||||
for (int i = 0; i < mu.Length; i++)
|
||||
{
|
||||
// Don't check with the correct length, since the callback is Assert.Fail.
|
||||
if (i == CorrectMuLength)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyMu(mu.AsSpan(0, i), signature));
|
||||
}
|
||||
|
||||
Assert.Equal(0, mldsa.VerifyMuCoreCallCount);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public static void VerifyExternalMu_EarlyFalseForWrongSizeSignature(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsaTestImplementation mldsa = MLDsaTestImplementation.CreateOverriddenCoreMethodsFail(algorithm);
|
||||
byte[] mu = new byte[64];
|
||||
byte[] signature = new byte[mldsa.Algorithm.SignatureSizeInBytes + 1];
|
||||
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyMu(mu, signature));
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyMu(mu, signature.AsSpan(2)));
|
||||
|
||||
Assert.Equal(0, mldsa.VerifyMuCoreCallCount);
|
||||
}
|
||||
|
||||
private static void AssertExpectedFill(ReadOnlySpan<byte> source, byte fillElement) =>
|
||||
AssertExpectedFill(source, fillElement, 255, 0, source.Length);
|
||||
|
||||
|
|
|
@ -45,6 +45,15 @@ namespace System.Security.Cryptography.Tests
|
|||
ExerciseSuccessfulVerifyPreHash(mldsa, HashInfo.Sha512.Oid, hash, signature, []);
|
||||
}
|
||||
|
||||
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.ExternalMuIsSupported))]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignVerifyExternalMuNoContext(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
byte[] data = [1, 2, 3, 4, 5];
|
||||
using MLDsa mldsa = GenerateKey(algorithm);
|
||||
SignAndVerifyExternalMu(mldsa, data, []);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignVerifyWithContext(MLDsaAlgorithm algorithm)
|
||||
|
@ -70,6 +79,16 @@ namespace System.Security.Cryptography.Tests
|
|||
ExerciseSuccessfulVerifyPreHash(mldsa, HashInfo.Sha512.Oid, hash, signature, context);
|
||||
}
|
||||
|
||||
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.ExternalMuIsSupported))]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignVerifyExternalMuWithContext(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
byte[] data = [1, 2, 3, 4, 5];
|
||||
byte[] context = [1, 1, 3, 5, 6];
|
||||
using MLDsa mldsa = GenerateKey(algorithm);
|
||||
SignAndVerifyExternalMu(mldsa, data, context);
|
||||
}
|
||||
|
||||
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported))]
|
||||
[ActiveIssue("https://github.com/dotnet/runtime/issues/116461", TestPlatforms.Windows)]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
|
@ -91,6 +110,27 @@ namespace System.Security.Cryptography.Tests
|
|||
ExerciseSuccessfulVerify(mldsa, [], signature, context);
|
||||
}
|
||||
|
||||
[ConditionalTheory(
|
||||
typeof(MLDsaTestHelpers),
|
||||
[nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported), nameof(MLDsaTestHelpers.ExternalMuIsSupported)])]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignVerifyEmptyMessageExternalMuNoContext(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsa mldsa = GenerateKey(algorithm);
|
||||
SignAndVerifyExternalMu(mldsa, [], []);
|
||||
}
|
||||
|
||||
[ConditionalTheory(
|
||||
typeof(MLDsaTestHelpers),
|
||||
[nameof(MLDsaTestHelpers.SigningEmptyDataIsSupported), nameof(MLDsaTestHelpers.ExternalMuIsSupported)])]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignVerifyEmptyMessageExternalMuWithContext(MLDsaAlgorithm algorithm)
|
||||
{
|
||||
using MLDsa mldsa = GenerateKey(algorithm);
|
||||
byte[] context = [1, 1, 3, 5, 6];
|
||||
SignAndVerifyExternalMu(mldsa, [], context);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllMLDsaAlgorithms), MemberType = typeof(MLDsaTestsData))]
|
||||
public void GenerateSignExportPublicVerifyWithPublicOnly(MLDsaAlgorithm algorithm)
|
||||
|
@ -100,6 +140,8 @@ namespace System.Security.Cryptography.Tests
|
|||
byte[] signature;
|
||||
byte[] hash = HashInfo.Sha512.GetHash(data);
|
||||
byte[] signaturePreHash;
|
||||
byte[]? mu = null;
|
||||
byte[] muSignature = null;
|
||||
|
||||
using (MLDsa mldsa = GenerateKey(algorithm))
|
||||
{
|
||||
|
@ -110,13 +152,25 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.TrueExpression(mldsa.VerifyPreHash(hash, signaturePreHash, HashInfo.Sha512.Oid));
|
||||
|
||||
publicKey = mldsa.ExportMLDsaPublicKey();
|
||||
|
||||
mu = CalculateMu(mldsa, data);
|
||||
|
||||
if (mu is not null)
|
||||
{
|
||||
muSignature = mldsa.SignMu(mu);
|
||||
}
|
||||
}
|
||||
|
||||
using (MLDsa mldsaPub = ImportPublicKey(algorithm, publicKey))
|
||||
{
|
||||
ExerciseSuccessfulVerify(mldsaPub, data, signature, []);
|
||||
ExerciseSuccessfulVerify(mldsaPub, data, signature, [], mu);
|
||||
ExerciseSuccessfulVerifyPreHash(mldsaPub, HashInfo.Sha512.Oid, hash, signaturePreHash, []);
|
||||
AssertExtensions.FalseExpression(mldsaPub.VerifyPreHash(hash, signature, HashInfo.Sha512.Oid));
|
||||
|
||||
if (muSignature is not null)
|
||||
{
|
||||
ExerciseSuccessfulVerify(mldsaPub, data, muSignature, [], mu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,6 +287,14 @@ namespace System.Security.Cryptography.Tests
|
|||
Assert.Equal(testCase.ShouldPass, mldsa.VerifyPreHash(hash, testCase.Signature, testCase.HashAlgOid, testCase.Context));
|
||||
}
|
||||
|
||||
[ConditionalTheory(typeof(MLDsaTestHelpers), nameof(MLDsaTestHelpers.ExternalMuIsSupported))]
|
||||
[MemberData(nameof(MLDsaTestsData.AllExternalMuMLDsaNistTestCases), MemberType = typeof(MLDsaTestsData))]
|
||||
public void NistImportPublicKeyVerifyExternalMu(MLDsaNistTestCase testCase)
|
||||
{
|
||||
using MLDsa mldsa = ImportPublicKey(testCase.Algorithm, testCase.PublicKey);
|
||||
Assert.Equal(testCase.ShouldPass, mldsa.VerifyMu(testCase.Mu, testCase.Signature));
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(MLDsaTestsData.AllPureMLDsaNistTestCases), MemberType = typeof(MLDsaTestsData))]
|
||||
public void NistImportSecretKeyVerifyExportsAndSignature(MLDsaNistTestCase testCase)
|
||||
|
@ -330,7 +392,63 @@ namespace System.Security.Cryptography.Tests
|
|||
Assert.Contains(hashInfo.Name.Name, ce.Message);
|
||||
}
|
||||
|
||||
protected static void ExerciseSuccessfulVerify(MLDsa mldsa, byte[] data, byte[] signature, byte[] context)
|
||||
protected static byte[]? CalculateMu(MLDsa mldsa, byte[] data, byte[]? context = null)
|
||||
{
|
||||
#if NET8_0_OR_GREATER
|
||||
if (MLDsaTestHelpers.ExternalMuIsSupported)
|
||||
{
|
||||
byte[] mu = new byte[mldsa.Algorithm.MuSizeInBytes];
|
||||
Span<byte> trSpan = mu.AsSpan(0, 64);
|
||||
|
||||
using (Shake256 shake = new Shake256())
|
||||
{
|
||||
shake.AppendData(mldsa.ExportMLDsaPublicKey());
|
||||
shake.GetHashAndReset(trSpan);
|
||||
|
||||
shake.AppendData(trSpan);
|
||||
|
||||
Span<byte> delimOrContextLength = [ 0 ];
|
||||
shake.AppendData(delimOrContextLength);
|
||||
|
||||
delimOrContextLength[0] = checked((byte)(context?.Length ?? 0));
|
||||
shake.AppendData(delimOrContextLength);
|
||||
|
||||
if (context is not null)
|
||||
{
|
||||
shake.AppendData(context);
|
||||
}
|
||||
|
||||
if (data is not null)
|
||||
{
|
||||
shake.AppendData(data);
|
||||
}
|
||||
|
||||
shake.GetHashAndReset(mu);
|
||||
}
|
||||
|
||||
return mu;
|
||||
}
|
||||
#endif
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected static void SignAndVerifyExternalMu(MLDsa mldsa, byte[] data, byte[] context)
|
||||
{
|
||||
byte[]? mu = CalculateMu(mldsa, data, context);
|
||||
byte[] signature;
|
||||
|
||||
if (mu is not null)
|
||||
{
|
||||
signature = mldsa.SignMu(mu);
|
||||
ExerciseSuccessfulVerify(mldsa, data, signature, context, mu);
|
||||
}
|
||||
|
||||
signature = mldsa.SignData(data, context);
|
||||
ExerciseSuccessfulVerify(mldsa, data, signature, context, mu);
|
||||
}
|
||||
|
||||
protected static void ExerciseSuccessfulVerify(MLDsa mldsa, byte[] data, byte[] signature, byte[]? context, byte[]? mu = null)
|
||||
{
|
||||
ReadOnlySpan<byte> buffer = [0, 1, 2, 3];
|
||||
|
||||
|
@ -354,11 +472,23 @@ namespace System.Security.Cryptography.Tests
|
|||
AssertExtensions.FalseExpression(mldsa.VerifyData(buffer.Slice(1, 3), signature, context));
|
||||
}
|
||||
|
||||
if (mu is not null)
|
||||
{
|
||||
AssertExtensions.TrueExpression(mldsa.VerifyMu(mu, signature));
|
||||
}
|
||||
|
||||
signature[0] ^= 1;
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyData(data, signature, context));
|
||||
{
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyData(data, signature, context));
|
||||
|
||||
if (mu is not null)
|
||||
{
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyMu(mu, signature));
|
||||
}
|
||||
}
|
||||
signature[0] ^= 1;
|
||||
|
||||
if (context.Length > 0)
|
||||
if (context?.Length > 0)
|
||||
{
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyData(data, signature, Array.Empty<byte>()));
|
||||
AssertExtensions.FalseExpression(mldsa.VerifyData(data, signature, ReadOnlySpan<byte>.Empty));
|
||||
|
@ -377,6 +507,11 @@ namespace System.Security.Cryptography.Tests
|
|||
}
|
||||
|
||||
AssertExtensions.TrueExpression(mldsa.VerifyData(data, signature, context));
|
||||
|
||||
if (mu is not null)
|
||||
{
|
||||
AssertExtensions.TrueExpression(mldsa.VerifyMu(mu, signature));
|
||||
}
|
||||
}
|
||||
|
||||
protected static void ExerciseSuccessfulVerifyPreHash(MLDsa mldsa, string hashAlgorithmOid, byte[] hash, byte[] signature, byte[] context)
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -87,6 +87,9 @@
|
|||
<data name="Argument_KemInvalidSeedLength" xml:space="preserve">
|
||||
<value>The specified private seed is not the correct length for the ML-KEM algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_MLDsaMuInvalidLength" xml:space="preserve">
|
||||
<value>The specified mu value is not the correct length for the ML-DSA algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_PemEncoding_InvalidLabel" xml:space="preserve">
|
||||
<value>The specified label is not valid.</value>
|
||||
</data>
|
||||
|
@ -108,15 +111,15 @@
|
|||
<data name="Argument_PrivateKeyWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The private key is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_PrivateSeedWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The private seed is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_PublicKeyWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The public key is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_SecretKeyWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The secret key is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_PrivateSeedWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The private seed is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_SignatureContextTooLong255" xml:space="preserve">
|
||||
<value>The specified signature context exceeds the maximum length of 255 bytes.</value>
|
||||
</data>
|
||||
|
|
|
@ -1961,8 +1961,12 @@ namespace System.Security.Cryptography
|
|||
public static System.Security.Cryptography.MLDsa ImportSubjectPublicKeyInfo(byte[] source) { throw null; }
|
||||
public static System.Security.Cryptography.MLDsa ImportSubjectPublicKeyInfo(System.ReadOnlySpan<byte> source) { throw null; }
|
||||
public byte[] SignData(byte[] data, byte[]? context = null) { throw null; }
|
||||
public void SignData(System.ReadOnlySpan<byte> data, System.Span<byte> destination, System.ReadOnlySpan<byte> context = default(System.ReadOnlySpan<byte>)) { throw null; }
|
||||
public void SignData(System.ReadOnlySpan<byte> data, System.Span<byte> destination, System.ReadOnlySpan<byte> context = default(System.ReadOnlySpan<byte>)) { }
|
||||
protected abstract void SignDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.Span<byte> destination);
|
||||
public byte[] SignMu(byte[] externalMu) { throw null; }
|
||||
public byte[] SignMu(System.ReadOnlySpan<byte> externalMu) { throw null; }
|
||||
public void SignMu(System.ReadOnlySpan<byte> externalMu, System.Span<byte> destination) { }
|
||||
protected abstract void SignMuCore(System.ReadOnlySpan<byte> externalMu, System.Span<byte> destination);
|
||||
public byte[] SignPreHash(byte[] hash, string hashAlgorithmOid, byte[]? context = null) { throw null; }
|
||||
public void SignPreHash(System.ReadOnlySpan<byte> hash, System.Span<byte> destination, string hashAlgorithmOid, System.ReadOnlySpan<byte> context = default(System.ReadOnlySpan<byte>)) { }
|
||||
protected abstract void SignPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.Span<byte> destination);
|
||||
|
@ -1975,6 +1979,9 @@ namespace System.Security.Cryptography
|
|||
public bool VerifyData(byte[] data, byte[] signature, byte[]? context = null) { throw null; }
|
||||
public bool VerifyData(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> signature, System.ReadOnlySpan<byte> context = default(System.ReadOnlySpan<byte>)) { throw null; }
|
||||
protected abstract bool VerifyDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.ReadOnlySpan<byte> signature);
|
||||
public bool VerifyMu(byte[] externalMu, byte[] signature) { throw null; }
|
||||
public bool VerifyMu(System.ReadOnlySpan<byte> externalMu, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected abstract bool VerifyMuCore(System.ReadOnlySpan<byte> externalMu, System.ReadOnlySpan<byte> signature);
|
||||
public bool VerifyPreHash(byte[] hash, byte[] signature, string hashAlgorithmOid, byte[]? context = null) { throw null; }
|
||||
public bool VerifyPreHash(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> signature, string hashAlgorithmOid, System.ReadOnlySpan<byte> context = default(System.ReadOnlySpan<byte>)) { throw null; }
|
||||
protected abstract bool VerifyPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.ReadOnlySpan<byte> signature);
|
||||
|
@ -1986,6 +1993,7 @@ namespace System.Security.Cryptography
|
|||
public static System.Security.Cryptography.MLDsaAlgorithm MLDsa44 { get { throw null; } }
|
||||
public static System.Security.Cryptography.MLDsaAlgorithm MLDsa65 { get { throw null; } }
|
||||
public static System.Security.Cryptography.MLDsaAlgorithm MLDsa87 { get { throw null; } }
|
||||
public int MuSizeInBytes { get { throw null; } }
|
||||
public string Name { get { throw null; } }
|
||||
public int PrivateSeedSizeInBytes { get { throw null; } }
|
||||
public int PublicKeySizeInBytes { get { throw null; } }
|
||||
|
@ -2009,9 +2017,11 @@ namespace System.Security.Cryptography
|
|||
protected override void ExportMLDsaSecretKeyCore(System.Span<byte> destination) { }
|
||||
public System.Security.Cryptography.CngKey GetKey() { throw null; }
|
||||
protected override void SignDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.Span<byte> destination) { }
|
||||
protected override void SignMuCore(System.ReadOnlySpan<byte> externalMu, System.Span<byte> destination) { }
|
||||
protected override void SignPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.Span<byte> destination) { }
|
||||
protected override bool TryExportPkcs8PrivateKeyCore(System.Span<byte> destination, out int bytesWritten) { throw null; }
|
||||
protected override bool VerifyDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected override bool VerifyMuCore(System.ReadOnlySpan<byte> externalMu, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected override bool VerifyPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
}
|
||||
[System.Diagnostics.CodeAnalysis.ExperimentalAttribute("SYSLIB5006", UrlFormat="https://aka.ms/dotnet-warnings/{0}")]
|
||||
|
@ -2030,9 +2040,11 @@ namespace System.Security.Cryptography
|
|||
protected override void ExportMLDsaPublicKeyCore(System.Span<byte> destination) { }
|
||||
protected override void ExportMLDsaSecretKeyCore(System.Span<byte> destination) { }
|
||||
protected override void SignDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.Span<byte> destination) { }
|
||||
protected override void SignMuCore(System.ReadOnlySpan<byte> externalMu, System.Span<byte> destination) { }
|
||||
protected override void SignPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.Span<byte> destination) { }
|
||||
protected override bool TryExportPkcs8PrivateKeyCore(System.Span<byte> destination, out int bytesWritten) { throw null; }
|
||||
protected override bool VerifyDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected override bool VerifyMuCore(System.ReadOnlySpan<byte> externalMu, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected override bool VerifyPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
}
|
||||
public abstract partial class MLKem : System.IDisposable
|
||||
|
@ -3163,6 +3175,7 @@ namespace System.Security.Cryptography
|
|||
protected override void ExportSlhDsaSecretKeyCore(System.Span<byte> destination) { }
|
||||
protected override void SignDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.Span<byte> destination) { }
|
||||
protected override void SignPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.Span<byte> destination) { }
|
||||
protected override bool TryExportPkcs8PrivateKeyCore(System.Span<byte> destination, out int bytesWritten) { throw null; }
|
||||
protected override bool VerifyDataCore(System.ReadOnlySpan<byte> data, System.ReadOnlySpan<byte> context, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
protected override bool VerifyPreHashCore(System.ReadOnlySpan<byte> hash, System.ReadOnlySpan<byte> context, string hashAlgorithmOid, System.ReadOnlySpan<byte> signature) { throw null; }
|
||||
}
|
||||
|
|
|
@ -141,6 +141,9 @@
|
|||
<data name="Argument_KemInvalidSeedLength" xml:space="preserve">
|
||||
<value>The specified private seed is not the correct length for the ML-KEM algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_MLDsaMuInvalidLength" xml:space="preserve">
|
||||
<value>The specified mu value is not the correct length for the ML-DSA algorithm.</value>
|
||||
</data>
|
||||
<data name="Argument_PrivateKeyWrongSizeForAlgorithm" xml:space="preserve">
|
||||
<value>The private key is not the correct size for the indicated algorithm.</value>
|
||||
</data>
|
||||
|
|
|
@ -100,6 +100,12 @@ namespace System.Security.Cryptography
|
|||
signature,
|
||||
static (key, encodedMessage, signature) => Interop.Crypto.MLDsaVerifyPreEncoded(key, encodedMessage, signature));
|
||||
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination) =>
|
||||
Interop.Crypto.MLDsaSignExternalMu(_key, externalMu, destination);
|
||||
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature) =>
|
||||
Interop.Crypto.MLDsaVerifyExternalMu(_key, externalMu, signature);
|
||||
|
||||
protected override void ExportMLDsaPublicKeyCore(Span<byte> destination) =>
|
||||
Interop.Crypto.MLDsaExportPublicKey(_key, destination);
|
||||
|
||||
|
|
|
@ -52,6 +52,18 @@ namespace System.Security.Cryptography
|
|||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination)
|
||||
{
|
||||
Debug.Fail("Caller should have checked platform availability.");
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature)
|
||||
{
|
||||
Debug.Fail("Caller should have checked platform availability.");
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
protected override void ExportMLDsaPublicKeyCore(Span<byte> destination)
|
||||
{
|
||||
Debug.Fail("Caller should have checked platform availability.");
|
||||
|
|
|
@ -101,6 +101,14 @@ namespace System.Security.Cryptography
|
|||
signature,
|
||||
static (key, encodedMessage, signature) => Interop.Crypto.MLDsaVerifyPreEncoded(key, encodedMessage, signature));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void SignMuCore(ReadOnlySpan<byte> externalMu, Span<byte> destination) =>
|
||||
Interop.Crypto.MLDsaSignExternalMu(_key, externalMu, destination);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool VerifyMuCore(ReadOnlySpan<byte> externalMu, ReadOnlySpan<byte> signature) =>
|
||||
Interop.Crypto.MLDsaVerifyExternalMu(_key, externalMu, signature);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void ExportMLDsaPublicKeyCore(Span<byte> destination) =>
|
||||
Interop.Crypto.MLDsaExportPublicKey(_key, destination);
|
||||
|
|
|
@ -256,10 +256,12 @@ static const Entry s_cryptoNative[] =
|
|||
DllImportEntry(CryptoNative_MLDsaExportPublicKey)
|
||||
DllImportEntry(CryptoNative_MLDsaGenerateKey)
|
||||
DllImportEntry(CryptoNative_MLDsaGetPalId)
|
||||
DllImportEntry(CryptoNative_MLDsaSignPure)
|
||||
DllImportEntry(CryptoNative_MLDsaVerifyPure)
|
||||
DllImportEntry(CryptoNative_MLDsaSignExternalMu)
|
||||
DllImportEntry(CryptoNative_MLDsaSignPreEncoded)
|
||||
DllImportEntry(CryptoNative_MLDsaSignPure)
|
||||
DllImportEntry(CryptoNative_MLDsaVerifyExternalMu)
|
||||
DllImportEntry(CryptoNative_MLDsaVerifyPreEncoded)
|
||||
DllImportEntry(CryptoNative_MLDsaVerifyPure)
|
||||
DllImportEntry(CryptoNative_NewX509Stack)
|
||||
DllImportEntry(CryptoNative_ObjNid2Obj)
|
||||
DllImportEntry(CryptoNative_ObjObj2Txt)
|
||||
|
|
|
@ -168,6 +168,10 @@ c_static_assert(EVP_PKEY_PUBLIC_KEY == 134);
|
|||
#define OSSL_SIGNATURE_PARAM_CONTEXT_STRING "context-string"
|
||||
#endif
|
||||
|
||||
#ifndef OSSL_SIGNATURE_PARAM_MU
|
||||
#define OSSL_SIGNATURE_PARAM_MU "mu"
|
||||
#endif
|
||||
|
||||
#if defined FEATURE_DISTRO_AGNOSTIC_SSL || OPENSSL_VERSION_NUMBER >= OPENSSL_VERSION_3_0_RTM
|
||||
#include "apibridge_30_rev.h"
|
||||
#endif
|
||||
|
|
|
@ -152,6 +152,137 @@ int32_t CryptoNative_MLDsaVerifyPreEncoded(EVP_PKEY *pkey,
|
|||
return CryptoNative_EvpPKeyVerifyPreEncoded(pkey, extraHandle, msg, msgLen, sig, sigLen);
|
||||
}
|
||||
|
||||
int32_t CryptoNative_MLDsaSignExternalMu(EVP_PKEY* pKey,
|
||||
void* extraHandle,
|
||||
uint8_t* mu, int32_t muLen,
|
||||
uint8_t* destination, int32_t destinationLen)
|
||||
{
|
||||
assert(pKey);
|
||||
assert(muLen >= 0);
|
||||
assert(destination);
|
||||
|
||||
#if defined(NEED_OPENSSL_3_0) && HAVE_OPENSSL_EVP_PKEY_SIGN_MESSAGE_INIT
|
||||
if (!API_EXISTS(EVP_PKEY_sign_message_init) ||
|
||||
!API_EXISTS(EVP_PKEY_verify_message_init))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
EVP_PKEY_CTX* ctx = NULL;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
ctx = EvpPKeyCtxCreateFromPKey(pKey, extraHandle);
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
int muYes = 1;
|
||||
|
||||
OSSL_PARAM initParams[] =
|
||||
{
|
||||
OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MU, &muYes),
|
||||
OSSL_PARAM_construct_end(),
|
||||
};
|
||||
|
||||
if (EVP_PKEY_sign_message_init(ctx, NULL, initParams) <= 0)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
size_t dstLen = Int32ToSizeT(destinationLen);
|
||||
|
||||
if (EVP_PKEY_sign(ctx, destination, &dstLen, mu, Int32ToSizeT(muLen)) == 1)
|
||||
{
|
||||
if (dstLen != Int32ToSizeT(destinationLen))
|
||||
{
|
||||
assert(false); // length mismatch
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ctx != NULL) EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
#else
|
||||
(void)pKey;
|
||||
(void)extraHandle;
|
||||
(void)mu;
|
||||
(void)muLen;
|
||||
(void)destination;
|
||||
(void)destinationLen;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t CryptoNative_MLDsaVerifyExternalMu(EVP_PKEY* pKey,
|
||||
void* extraHandle,
|
||||
uint8_t* mu, int32_t muLen,
|
||||
uint8_t* sig, int32_t sigLen)
|
||||
{
|
||||
assert(pKey);
|
||||
assert(muLen >= 0);
|
||||
assert(sig);
|
||||
|
||||
#if defined(NEED_OPENSSL_3_0) && HAVE_OPENSSL_EVP_PKEY_SIGN_MESSAGE_INIT
|
||||
if (!API_EXISTS(EVP_PKEY_sign_message_init) ||
|
||||
!API_EXISTS(EVP_PKEY_verify_message_init))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
ERR_clear_error();
|
||||
|
||||
EVP_PKEY_CTX* ctx = NULL;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
ctx = EvpPKeyCtxCreateFromPKey(pKey, extraHandle);
|
||||
|
||||
if (!ctx)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
int muYes = 1;
|
||||
|
||||
OSSL_PARAM initParams[] =
|
||||
{
|
||||
OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MU, &muYes),
|
||||
OSSL_PARAM_construct_end(),
|
||||
};
|
||||
|
||||
if (EVP_PKEY_verify_message_init(ctx, NULL, initParams) <= 0)
|
||||
{
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = EVP_PKEY_verify(ctx, sig, Int32ToSizeT(sigLen), mu, Int32ToSizeT(muLen)) == 1;
|
||||
|
||||
done:
|
||||
if (ctx != NULL) EVP_PKEY_CTX_free(ctx);
|
||||
return ret;
|
||||
#else
|
||||
(void)pKey;
|
||||
(void)extraHandle;
|
||||
(void)mu;
|
||||
(void)muLen;
|
||||
(void)sig;
|
||||
(void)sigLen;
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
int32_t CryptoNative_MLDsaExportSecretKey(const EVP_PKEY* pKey, uint8_t* destination, int32_t destinationLength)
|
||||
{
|
||||
return EvpPKeyGetKeyOctetStringParam(pKey, OSSL_PKEY_PARAM_PRIV_KEY, destination, destinationLength);
|
||||
|
|
|
@ -24,7 +24,7 @@ PALEXPORT EVP_PKEY* CryptoNative_MLDsaGenerateKey(const char* keyType, uint8_t*
|
|||
/*
|
||||
Sign a message using the provided ML-DSA key.
|
||||
|
||||
Returns 1 on success, 0 on a mismatched signature, -1 on error.
|
||||
Returns 1 on success, 0 on signing failure, -1 on other error.
|
||||
*/
|
||||
PALEXPORT int32_t CryptoNative_MLDsaSignPure(EVP_PKEY *pkey,
|
||||
void* extraHandle,
|
||||
|
@ -46,7 +46,7 @@ PALEXPORT int32_t CryptoNative_MLDsaVerifyPure(EVP_PKEY *pkey,
|
|||
/*
|
||||
Sign an encoded message using the provided ML-DSA key.
|
||||
|
||||
Returns 1 on success, 0 on a mismatched signature, -1 on error.
|
||||
Returns 1 on success, 0 on signing failure, -1 on other error.
|
||||
*/
|
||||
PALEXPORT int32_t CryptoNative_MLDsaSignPreEncoded(EVP_PKEY *pkey,
|
||||
void* extraHandle,
|
||||
|
@ -63,6 +63,26 @@ PALEXPORT int32_t CryptoNative_MLDsaVerifyPreEncoded(EVP_PKEY *pkey,
|
|||
uint8_t* msg, int32_t msgLen,
|
||||
uint8_t* sig, int32_t sigLen);
|
||||
|
||||
/*
|
||||
Sign an externally produced signature mu with the provided ML-DSA key.
|
||||
|
||||
Returns 1 on success, 0 on signing failure, -1 on other error.
|
||||
*/
|
||||
PALEXPORT int32_t CryptoNative_MLDsaSignExternalMu(EVP_PKEY* pKey,
|
||||
void* extraHandle,
|
||||
uint8_t* mu, int32_t muLen,
|
||||
uint8_t* destination, int32_t destinationLen);
|
||||
|
||||
/*
|
||||
Verifies an externally produced signature mu with the provided ML-DSA key.
|
||||
|
||||
Returns 1 on success, 0 on mismatched signature, -1 on error.
|
||||
*/
|
||||
PALEXPORT int32_t CryptoNative_MLDsaVerifyExternalMu(EVP_PKEY* pKey,
|
||||
void* extraHandle,
|
||||
uint8_t* mu, int32_t muLen,
|
||||
uint8_t* sig, int32_t sigLen);
|
||||
|
||||
/*
|
||||
Export the secret key from the given ML-DSA key.
|
||||
*/
|
||||
|
|
Loading…
Reference in New Issue