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 @@ -19,11 +19,6 @@ internal static partial class Crypto
private static volatile IntPtr s_evpSha3_512;
private static volatile IntPtr s_evpSha3_Shake128;
private static volatile IntPtr s_evpSha3_Shake256;
private static volatile bool s_evpSha3_256Cached;
private static volatile bool s_evpSha3_384Cached;
private static volatile bool s_evpSha3_512Cached;
private static volatile bool s_evpSha3_Shake128Cached;
private static volatile bool s_evpSha3_Shake256Cached;

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpMd5();
Expand Down Expand Up @@ -58,99 +53,48 @@ private static IntPtr EvpSha512() =>
[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpSha3_256();

private static IntPtr EvpSha3_256()
{
if (!s_evpSha3_256Cached)
{
s_evpSha3_256 = CryptoNative_EvpSha3_256();
s_evpSha3_256Cached = true;
}

return s_evpSha3_256;
}
private static IntPtr EvpSha3_256() =>
s_evpSha3_256 != IntPtr.Zero ? s_evpSha3_256 : (s_evpSha3_256 = CryptoNative_EvpSha3_256());

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpSha3_384();

private static IntPtr EvpSha3_384()
{
if (!s_evpSha3_384Cached)
{
s_evpSha3_384 = CryptoNative_EvpSha3_384();
s_evpSha3_384Cached = true;
}

return s_evpSha3_384;
}
private static IntPtr EvpSha3_384() =>
s_evpSha3_384 != IntPtr.Zero ? s_evpSha3_384 : (s_evpSha3_384 = CryptoNative_EvpSha3_384());

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpSha3_512();

private static IntPtr EvpSha3_512()
{
if (!s_evpSha3_512Cached)
{
s_evpSha3_512 = CryptoNative_EvpSha3_512();
s_evpSha3_512Cached = true;
}

return s_evpSha3_512;
}
private static IntPtr EvpSha3_512() =>
s_evpSha3_512 != IntPtr.Zero ? s_evpSha3_512 : (s_evpSha3_512 = CryptoNative_EvpSha3_512());

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpShake128();

private static IntPtr EvpShake128()
{
if (!s_evpSha3_Shake128Cached)
{
s_evpSha3_Shake128 = CryptoNative_EvpShake128();
s_evpSha3_Shake128Cached = true;
}

return s_evpSha3_Shake128;
}
private static IntPtr EvpShake128() =>
s_evpSha3_Shake128 != IntPtr.Zero ? s_evpSha3_Shake128 : (s_evpSha3_Shake128 = CryptoNative_EvpShake128());

[LibraryImport(Libraries.CryptoNative)]
private static partial IntPtr CryptoNative_EvpShake256();

private static IntPtr EvpShake256()
{
if (!s_evpSha3_Shake256Cached)
{
s_evpSha3_Shake256 = CryptoNative_EvpShake256();
s_evpSha3_Shake256Cached = true;
}

return s_evpSha3_Shake256;
}
private static IntPtr EvpShake256() =>
s_evpSha3_Shake256 != IntPtr.Zero ? s_evpSha3_Shake256 : (s_evpSha3_Shake256 = CryptoNative_EvpShake256());

internal static IntPtr HashAlgorithmToEvp(string hashAlgorithmId)
{
switch (hashAlgorithmId)
return hashAlgorithmId switch
{
case HashAlgorithmNames.SHA1: return EvpSha1();
case HashAlgorithmNames.SHA256: return EvpSha256();
case HashAlgorithmNames.SHA384: return EvpSha384();
case HashAlgorithmNames.SHA512: return EvpSha512();
case HashAlgorithmNames.SHA3_256:
IntPtr sha3_256 = EvpSha3_256();
return sha3_256 != 0 ? sha3_256 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHA3_384:
IntPtr sha3_384 = EvpSha3_384();
return sha3_384 != 0 ? sha3_384 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHA3_512:
IntPtr sha3_512 = EvpSha3_512();
return sha3_512 != 0 ? sha3_512 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHAKE128:
IntPtr shake128 = EvpShake128();
return shake128 != 0 ? shake128 : throw new PlatformNotSupportedException();
case HashAlgorithmNames.SHAKE256:
IntPtr shake256 = EvpShake256();
return shake256 != 0 ? shake256 : throw new PlatformNotSupportedException();
case nameof(HashAlgorithmName.MD5): return EvpMd5();
default:
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
HashAlgorithmNames.MD5 => EvpMd5(),
HashAlgorithmNames.SHA1 => EvpSha1(),
HashAlgorithmNames.SHA256 => EvpSha256(),
HashAlgorithmNames.SHA384 => EvpSha384(),
HashAlgorithmNames.SHA512 => EvpSha512(),
HashAlgorithmNames.SHA3_256 => EvpSha3_256(),
HashAlgorithmNames.SHA3_384 => EvpSha3_384(),
HashAlgorithmNames.SHA3_512 => EvpSha3_512(),
HashAlgorithmNames.SHAKE128 => EvpShake128(),
HashAlgorithmNames.SHAKE256 => EvpShake256(),
_ => throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId)),
};
}

Expand All @@ -163,17 +107,12 @@ internal static bool HashAlgorithmSupported(string hashAlgorithmId)
case HashAlgorithmNames.SHA384:
case HashAlgorithmNames.SHA512:
case HashAlgorithmNames.MD5:
return true;
case HashAlgorithmNames.SHA3_256:
return EvpSha3_256() != 0;
case HashAlgorithmNames.SHA3_384:
return EvpSha3_384() != 0;
case HashAlgorithmNames.SHA3_512:
return EvpSha3_512() != 0;
case HashAlgorithmNames.SHAKE128:
return EvpShake128() != 0;
case HashAlgorithmNames.SHAKE256:
return EvpShake256() != 0;
return true;
default:
throw new CryptographicException(SR.Format(SR.Cryptography_UnknownHashAlgorithm, hashAlgorithmId));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,6 @@ check_function_exists(
SSL_get0_alpn_selected
HAVE_OPENSSL_ALPN)

check_function_exists(
EVP_sha3_256
HAVE_OPENSSL_SHA3
)

check_function_exists(
EVP_DigestSqueeze
HAVE_OPENSSL_SHA3_SQUEEZE
Expand Down
21 changes: 5 additions & 16 deletions src/native/libs/System.Security.Cryptography.Native/opensslshim.h
Original file line number Diff line number Diff line change
Expand Up @@ -245,17 +245,6 @@ const EVP_CIPHER* EVP_chacha20_poly1305(void);
#define EVP_CTRL_AEAD_SET_TAG 0x11
#endif

#if !HAVE_OPENSSL_SHA3
#undef HAVE_OPENSSL_SHA3
#define HAVE_OPENSSL_SHA3 1
const EVP_MD *EVP_sha3_256(void);
const EVP_MD *EVP_sha3_384(void);
const EVP_MD *EVP_sha3_512(void);
const EVP_MD *EVP_shake128(void);
const EVP_MD *EVP_shake256(void);
int EVP_DigestFinalXOF(EVP_MD_CTX *ctx, unsigned char *md, size_t len);
#endif

#if !HAVE_OPENSSL_SHA3_SQUEEZE
#undef HAVE_OPENSSL_SHA3_SQUEEZE
#define HAVE_OPENSSL_SHA3_SQUEEZE 1
Expand Down Expand Up @@ -580,11 +569,11 @@ extern bool g_libSslUses32BitTime;
REQUIRED_FUNCTION(EVP_sha256) \
REQUIRED_FUNCTION(EVP_sha384) \
REQUIRED_FUNCTION(EVP_sha512) \
LIGHTUP_FUNCTION(EVP_sha3_256) \
LIGHTUP_FUNCTION(EVP_sha3_384) \
LIGHTUP_FUNCTION(EVP_sha3_512) \
LIGHTUP_FUNCTION(EVP_shake128) \
LIGHTUP_FUNCTION(EVP_shake256) \
REQUIRED_FUNCTION(EVP_sha3_256) \
REQUIRED_FUNCTION(EVP_sha3_384) \
REQUIRED_FUNCTION(EVP_sha3_512) \
REQUIRED_FUNCTION(EVP_shake128) \
REQUIRED_FUNCTION(EVP_shake256) \
LIGHTUP_FUNCTION(EVP_SIGNATURE_fetch) \
LIGHTUP_FUNCTION(EVP_SIGNATURE_free) \
REQUIRED_FUNCTION(GENERAL_NAMES_free) \
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
#cmakedefine01 HAVE_OPENSSL_EC2M
#cmakedefine01 HAVE_OPENSSL_ALPN
#cmakedefine01 HAVE_OPENSSL_CHACHA20POLY1305
#cmakedefine01 HAVE_OPENSSL_SHA3
#cmakedefine01 HAVE_OPENSSL_SHA3_SQUEEZE
#cmakedefine01 HAVE_OPENSSL_EVP_PKEY_SIGN_MESSAGE_INIT
#cmakedefine01 HAVE_OPENSSL_ENGINE
88 changes: 29 additions & 59 deletions src/native/libs/System.Security.Cryptography.Native/pal_evp.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,30 +33,12 @@
pthread_once(&g_evpFetchInit##export, EnsureFetchEvpMd##export); \
return g_evpFetch##export; \
}
#define BUILD_MD_FETCH_LIGHTUP_SHA3(...) BUILD_MD_FETCH(__VA_ARGS__)
#else
#define BUILD_MD_FETCH(export, fn, name, query) \
const EVP_MD* export(void) \
{ \
return fn(); \
}
#if HAVE_OPENSSL_SHA3
#define BUILD_MD_FETCH_LIGHTUP_SHA3(export, fn, name, query) \
const EVP_MD* export(void) \
{ \
if (API_EXISTS(fn)) \
{ \
return fn(); \
} \
\
return NULL; \
}
#else
const EVP_MD* export(void) \
{ \
return NULL; \
}
#endif
#endif


Expand Down Expand Up @@ -128,43 +110,31 @@ int32_t CryptoNative_EvpDigestFinalEx(EVP_MD_CTX* ctx, uint8_t* md, uint32_t* s)

int32_t CryptoNative_EvpDigestFinalXOF(EVP_MD_CTX* ctx, uint8_t* md, uint32_t len)
{
#if HAVE_OPENSSL_SHA3
if (API_EXISTS(EVP_DigestFinalXOF))
{
ERR_clear_error();

// https://github.com/openssl/openssl/issues/9431
// EVP_DigestFinalXOF has a bug in some arch-optimized code paths where it cannot tolerate a zero length
// digest.
// If the caller asked for no bytes, use a temporary buffer to ask for 1 byte, then throw away the result.
// We don't want to skip calling FinalXOF entirely because we want to make sure the EVP_MD_CTX is in a
// finalized state regardless of the length of the digest.
// We can remove this work around when OpenSSL 3.0 is the minimum OpenSSL requirement.
if (len == 0)
{
uint8_t single[1] = { 0 };
int result = EVP_DigestFinalXOF(ctx, single, 1);
OPENSSL_cleanse(single, sizeof(single));
return result;
}
else if (!md)
{
// Length is not zero but we don't have a buffer to write to.
return -1;
}
else
{
return EVP_DigestFinalXOF(ctx, md, len);
}
}
#else
// Use each parameter to avoid unused parameter warnings.
(void)(ctx);
(void)(md);
(void)(len);
#endif
ERR_clear_error();

return 0;
// https://github.com/openssl/openssl/issues/9431
// EVP_DigestFinalXOF has a bug in some arch-optimized code paths where it cannot tolerate a zero length
// digest.
// If the caller asked for no bytes, use a temporary buffer to ask for 1 byte, then throw away the result.
// We don't want to skip calling FinalXOF entirely because we want to make sure the EVP_MD_CTX is in a
// finalized state regardless of the length of the digest.
// We can remove this work around when OpenSSL 3.0 is the minimum OpenSSL requirement.
if (len == 0)
{
uint8_t single[1] = { 0 };
int result = EVP_DigestFinalXOF(ctx, single, 1);
OPENSSL_cleanse(single, sizeof(single));
return result;
}
else if (!md)
{
// Length is not zero but we don't have a buffer to write to.
return -1;
}
else
{
return EVP_DigestFinalXOF(ctx, md, len);
}
}

EVP_MD_CTX* CryptoNative_EvpMdCtxCopyEx(const EVP_MD_CTX* ctx)
Expand Down Expand Up @@ -322,11 +292,11 @@ BUILD_MD_FETCH(CryptoNative_EvpSha1, EVP_sha1, "SHA1", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha256, EVP_sha256, "SHA256", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha384, EVP_sha384, "SHA384", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha512, EVP_sha512, "SHA512", NULL)
BUILD_MD_FETCH_LIGHTUP_SHA3(CryptoNative_EvpSha3_256, EVP_sha3_256, "SHA3-256", NULL)
BUILD_MD_FETCH_LIGHTUP_SHA3(CryptoNative_EvpSha3_384, EVP_sha3_384, "SHA3-384", NULL)
BUILD_MD_FETCH_LIGHTUP_SHA3(CryptoNative_EvpSha3_512, EVP_sha3_512, "SHA3-512", NULL)
BUILD_MD_FETCH_LIGHTUP_SHA3(CryptoNative_EvpShake128, EVP_shake128, "SHAKE-128", NULL)
BUILD_MD_FETCH_LIGHTUP_SHA3(CryptoNative_EvpShake256, EVP_shake256, "SHAKE-256", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha3_256, EVP_sha3_256, "SHA3-256", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha3_384, EVP_sha3_384, "SHA3-384", NULL)
BUILD_MD_FETCH(CryptoNative_EvpSha3_512, EVP_sha3_512, "SHA3-512", NULL)
BUILD_MD_FETCH(CryptoNative_EvpShake128, EVP_shake128, "SHAKE-128", NULL)
BUILD_MD_FETCH(CryptoNative_EvpShake256, EVP_shake256, "SHAKE-256", NULL)

int32_t CryptoNative_GetMaxMdSize(void)
{
Expand Down