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 @@ -132,6 +132,58 @@ internal static bool MLDsaVerifyPure(
}
}

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

internal static void MLDsaSignPreEncoded(
SafeEvpPKeyHandle pkey,
ReadOnlySpan<byte> msg,
Span<byte> destination)
{
int ret = CryptoNative_MLDsaSignPreEncoded(
pkey, GetExtraHandle(pkey),
msg, msg.Length,
destination, destination.Length);

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

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

internal static bool MLDsaVerifyPreEncoded(
SafeEvpPKeyHandle pkey,
ReadOnlySpan<byte> msg,
ReadOnlySpan<byte> signature)
{
int ret = CryptoNative_MLDsaVerifyPreEncoded(
pkey, GetExtraHandle(pkey),
msg, msg.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);

Expand Down
61 changes: 53 additions & 8 deletions src/libraries/Common/src/System/Security/Cryptography/Helpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,20 +100,65 @@ internal static bool TryCopyToDestination(this ReadOnlySpan<byte> source, Span<b
return false;
}

internal static int HashOidToByteLength(string hashOid)
private static int? TryGetHashOidToByteLength(ReadOnlySpan<char> hashOid)
{
// This file is compiled in netstandard2.0, can't use the HashSizeInBytes consts.
return hashOid switch
{
Oids.Sha256 => 256 >> 3,
Oids.Sha384 => 384 >> 3,
Oids.Sha512 => 512 >> 3,
Oids.Sha1 => 160 >> 3,
Oids.Md5 => 128 >> 3,
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashOid)),
Oids.Md5 => 128 / 8,
Oids.Sha1 => 160 / 8,
Oids.Sha256 => 256 / 8,
Oids.Sha384 => 384 / 8,
Oids.Sha512 => 512 / 8,
Oids.Sha3_256 => 256 / 8,
Oids.Sha3_384 => 384 / 8,
Oids.Sha3_512 => 512 / 8,
Oids.Shake128 => 256 / 8,
Oids.Shake256 => 512 / 8,
_ => null,
};
}

internal static int HashOidToByteLength(string hashOid)
{
return TryGetHashOidToByteLength(hashOid) ??
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashOid));
}

#if !BUILDING_PKCS
/// <summary>
/// Validates if the hash length matches the expected output size for the given hash algorithm OID.
/// When the OID is not one of the common hash algorithms, it only validates the format of the OID.
/// </summary>
internal static void ValidateHashLength(ReadOnlySpan<byte> hash, ReadOnlySpan<char> hashAlgorithmOid)
{
int? outputSize = TryGetHashOidToByteLength(hashAlgorithmOid);

if (outputSize is not null)
{
if (hash.Length != outputSize)
{
throw new CryptographicException(SR.Cryptography_HashLengthMismatch);
}
}
else
{
// The OIDs for the algorithms above have max length 11. We'll just round up for a conservative initial estimate.
const int MaxEncodedOidLengthForCommonHashAlgorithms = 16;
AsnWriter writer = new AsnWriter(AsnEncodingRules.DER, MaxEncodedOidLengthForCommonHashAlgorithms);

try
{
// Only the format of the OID is validated here. The derived classes can decide to do more if they want to.
writer.WriteObjectIdentifier(hashAlgorithmOid);
}
catch (ArgumentException ae)
{
throw new CryptographicException(SR.Cryptography_HashLengthMismatch, ae);
}
}
}
#endif

internal static bool HashAlgorithmRequired(string? keyAlgorithm)
{
// This list could either be written as "ML-DSA and friends return false",
Expand Down
Loading
Loading