Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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 @@ -145,15 +145,37 @@ public byte[] SignData(byte[] data, byte[]? context = default)

if (Algorithm.SignatureSize.IsExact)
{
return ExportExactSize(
Algorithm.MaxSignatureSizeInBytes,
(key, dest, out written) => key.TrySignData(new ReadOnlySpan<byte>(data), dest, out written, new ReadOnlySpan<byte>(context)));
byte[] signature = new byte[Algorithm.MaxSignatureSizeInBytes];
int bytesWritten = SignDataCore(new ReadOnlySpan<byte>(data), new ReadOnlySpan<byte>(context), signature);

if (signature.Length != bytesWritten)
{
throw new CryptographicException();
}

return signature;
}

return ExportWithCallback(
Algorithm.MaxSignatureSizeInBytes,
(key, dest, out written) => key.TrySignData(new ReadOnlySpan<byte>(data), dest, out written, new ReadOnlySpan<byte>(context)),
key => key.ToArray());
byte[] rented = CryptoPool.Rent(Algorithm.MaxSignatureSizeInBytes);

try
{
int bytesWritten = SignDataCore(
new ReadOnlySpan<byte>(data),
new ReadOnlySpan<byte>(context),
rented.AsSpan(0, Algorithm.MaxSignatureSizeInBytes));

if (!Algorithm.SignatureSize.IsValidSize(bytesWritten))
{
throw new CryptographicException();
}

return rented.AsSpan(0, bytesWritten).ToArray();
}
finally
{
CryptoPool.Return(rented);
}
}

/// <summary>
Expand All @@ -169,13 +191,8 @@ public byte[] SignData(byte[] data, byte[]? context = default)
/// An optional context-specific value to limit the scope of the signature.
/// The default value is an empty buffer.
/// </param>
/// <param name="bytesWritten">
/// When this method returns, contains the number of bytes written to the <paramref name="destination"/> buffer.
/// This parameter is treated as uninitialized.
/// </param>
/// <returns>
/// <see langword="true" /> if <paramref name="destination"/> was large enough to hold the result;
/// otherwise, <see langword="false" />.
/// The number of bytes written to the <paramref name="destination"/> buffer.
/// </returns>
/// <exception cref="ArgumentOutOfRangeException">
/// <paramref name="context"/> has a <see cref="ReadOnlySpan{T}.Length"/> in excess of
Expand All @@ -192,7 +209,7 @@ public byte[] SignData(byte[] data, byte[]? context = default)
/// <remarks>
/// The signature will be at most <see cref="CompositeMLDsaAlgorithm.MaxSignatureSizeInBytes"/> in length.
/// </remarks>
public bool TrySignData(ReadOnlySpan<byte> data, Span<byte> destination, out int bytesWritten, ReadOnlySpan<byte> context = default)
public int SignData(ReadOnlySpan<byte> data, Span<byte> destination, ReadOnlySpan<byte> context = default)
{
if (context.Length > MaxContextLength)
{
Expand All @@ -202,30 +219,24 @@ public bool TrySignData(ReadOnlySpan<byte> data, Span<byte> destination, out int
SR.Argument_SignatureContextTooLong255);
}

ThrowIfDisposed();

if (Algorithm.SignatureSize.IsAlwaysLargerThan(destination.Length))
if (destination.Length < Algorithm.MaxSignatureSizeInBytes)
{
bytesWritten = 0;
return false;
throw new ArgumentException(SR.Argument_DestinationTooShort, nameof(destination));
}

if (TrySignDataCore(data, context, destination, out int written))
{
if (!Algorithm.SignatureSize.IsValidSize(written))
{
CryptographicOperations.ZeroMemory(destination);
ThrowIfDisposed();

bytesWritten = 0;
throw new CryptographicException(SR.Cryptography_UnexpectedExportBufferSize);
}
int bytesWritten = SignDataCore(data, context, destination.Slice(0, Algorithm.MaxSignatureSizeInBytes));

bytesWritten = written;
return true;
// Make sure minimum size is also satisfied.
if (!Algorithm.SignatureSize.IsValidSize(bytesWritten))
{
CryptographicOperations.ZeroMemory(destination);

throw new CryptographicException();
}

bytesWritten = 0;
return false;
return bytesWritten;
}

/// <summary>
Expand All @@ -239,20 +250,15 @@ public bool TrySignData(ReadOnlySpan<byte> data, Span<byte> destination, out int
/// The signature context.
/// </param>
/// <param name="destination">
/// The buffer to receive the signature, whose length will be at least the ML-DSA component's signature size.
/// </param>
/// <param name="bytesWritten">
/// When this method returns, contains the number of bytes written to the <paramref name="destination"/> buffer.
/// This parameter is treated as uninitialized.
/// The buffer to receive the signature, whose length will be exactly <see cref="CompositeMLDsaAlgorithm.MaxSignatureSizeInBytes" />.
/// </param>
/// <returns>
/// <see langword="true" /> if <paramref name="destination"/> was large enough to hold the result;
/// otherwise, <see langword="false" />.
/// The number of bytes written to the <paramref name="destination"/> buffer.
/// </returns>
/// <exception cref="CryptographicException">
/// An error occurred while signing the data.
/// </exception>
protected abstract bool TrySignDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, Span<byte> destination, out int bytesWritten);
protected abstract int SignDataCore(ReadOnlySpan<byte> data, ReadOnlySpan<byte> context, Span<byte> destination);

/// <summary>
/// Verifies that the specified signature is valid for this key and the provided data.
Expand Down Expand Up @@ -331,7 +337,12 @@ public bool VerifyData(ReadOnlySpan<byte> data, ReadOnlySpan<byte> signature, Re

ThrowIfDisposed();

return Algorithm.SignatureSize.IsValidSize(signature.Length) && VerifyDataCore(data, context, signature);
if (!Algorithm.SignatureSize.IsValidSize(signature.Length))
{
return false;
}

return VerifyDataCore(data, context, signature);
}

/// <summary>
Expand Down Expand Up @@ -1549,7 +1560,7 @@ public bool TryExportCompositeMLDsaPublicKey(Span<byte> destination, out int byt
CryptographicOperations.ZeroMemory(destination);

bytesWritten = 0;
throw new CryptographicException(SR.Cryptography_UnexpectedExportBufferSize);
throw new CryptographicException();
}

bytesWritten = written;
Expand Down Expand Up @@ -1626,7 +1637,7 @@ public bool TryExportCompositeMLDsaPrivateKey(Span<byte> destination, out int by
CryptographicOperations.ZeroMemory(destination);

bytesWritten = 0;
throw new CryptographicException(SR.Cryptography_UnexpectedExportBufferSize);
throw new CryptographicException();
}

bytesWritten = written;
Expand Down Expand Up @@ -1845,7 +1856,7 @@ private byte[] ExportExactSize(int exactSize, TryExportFunc tryExportFunc)
{
CryptographicOperations.ZeroMemory(ret);

throw new CryptographicException(SR.Cryptography_UnexpectedExportBufferSize);
throw new CryptographicException();
}

return ret;
Expand Down
Loading
Loading