|
|
debe55 |
From 7111a92546253d6fc857f7cad8b0bff425df0798 Mon Sep 17 00:00:00 2001
|
|
|
debe55 |
From: Jeremy Barton <jbarton@microsoft.com>
|
|
|
debe55 |
Date: Fri, 2 Apr 2021 09:10:08 -0700
|
|
|
debe55 |
Subject: [PATCH 03/11] Use EVP_PKEY for RSA signing operations
|
|
|
debe55 |
|
|
|
debe55 |
With this change all RSA private key operations (excluding import/export) use the EVP_PKEY APIs.
|
|
|
debe55 |
|
|
|
debe55 |
* RSAPaddingProcessor is no longer used in conjunction with the private keys, on Linux.
|
|
|
debe55 |
* The pal_rsa.c copy of HasPrivateKey has been removed.
|
|
|
debe55 |
---
|
|
|
debe55 |
.../Interop.EvpPkey.Rsa.cs | 35 ++++++
|
|
|
debe55 |
.../Interop.Rsa.cs | 20 ----
|
|
|
debe55 |
.../Security/Cryptography/RSAOpenSsl.cs | 87 ++++-----------
|
|
|
debe55 |
.../opensslshim.h | 19 +++-
|
|
|
debe55 |
.../pal_evp_pkey_rsa.c | 76 ++++++++++++-
|
|
|
debe55 |
.../pal_evp_pkey_rsa.h | 14 +++
|
|
|
debe55 |
.../pal_rsa.c | 100 ------------------
|
|
|
debe55 |
7 files changed, 156 insertions(+), 195 deletions(-)
|
|
|
debe55 |
|
|
|
debe55 |
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs
|
|
|
debe55 |
index f023ced7f9..6aab764cff 100644
|
|
|
debe55 |
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs
|
|
|
debe55 |
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs
|
|
|
debe55 |
@@ -63,6 +63,41 @@ internal static SafeEvpPKeyHandle RsaGenerateKey(int keySize)
|
|
|
debe55 |
return written;
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
+ [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaSignHash")]
|
|
|
debe55 |
+ private static extern int CryptoNative_RsaSignHash(
|
|
|
debe55 |
+ SafeEvpPKeyHandle pkey,
|
|
|
debe55 |
+ RSASignaturePaddingMode paddingMode,
|
|
|
debe55 |
+ IntPtr digestAlgorithm,
|
|
|
debe55 |
+ ref byte hash,
|
|
|
debe55 |
+ int hashLength,
|
|
|
debe55 |
+ ref byte destination,
|
|
|
debe55 |
+ int destinationLength);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ internal static int RsaSignHash(
|
|
|
debe55 |
+ SafeEvpPKeyHandle pkey,
|
|
|
debe55 |
+ RSASignaturePaddingMode paddingMode,
|
|
|
debe55 |
+ IntPtr digestAlgorithm,
|
|
|
debe55 |
+ ReadOnlySpan<byte> hash,
|
|
|
debe55 |
+ Span<byte> destination)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ int written = CryptoNative_RsaSignHash(
|
|
|
debe55 |
+ pkey,
|
|
|
debe55 |
+ paddingMode,
|
|
|
debe55 |
+ digestAlgorithm,
|
|
|
debe55 |
+ ref MemoryMarshal.GetReference(hash),
|
|
|
debe55 |
+ hash.Length,
|
|
|
debe55 |
+ ref MemoryMarshal.GetReference(destination),
|
|
|
debe55 |
+ destination.Length);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (written < 0)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ Debug.Assert(written == -1);
|
|
|
debe55 |
+ throw CreateOpenSslCryptographicException();
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+ return written;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetRsa")]
|
|
|
debe55 |
internal static extern SafeRsaHandle EvpPkeyGetRsa(SafeEvpPKeyHandle pkey);
|
|
|
debe55 |
|
|
|
debe55 |
diff --git a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs
|
|
|
debe55 |
index 5ad534a8f2..b2f250ffe9 100644
|
|
|
debe55 |
--- a/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs
|
|
|
debe55 |
+++ b/src/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs
|
|
|
debe55 |
@@ -44,19 +44,6 @@ internal static partial class Crypto
|
|
|
debe55 |
SafeRsaHandle rsa,
|
|
|
debe55 |
RsaPadding padding);
|
|
|
debe55 |
|
|
|
debe55 |
- internal static int RsaSignPrimitive(
|
|
|
debe55 |
- ReadOnlySpan<byte> from,
|
|
|
debe55 |
- Span<byte> to,
|
|
|
debe55 |
- SafeRsaHandle rsa) =>
|
|
|
debe55 |
- RsaSignPrimitive(from.Length, ref MemoryMarshal.GetReference(from), ref MemoryMarshal.GetReference(to), rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaSignPrimitive")]
|
|
|
debe55 |
- private static extern int RsaSignPrimitive(
|
|
|
debe55 |
- int flen,
|
|
|
debe55 |
- ref byte from,
|
|
|
debe55 |
- ref byte to,
|
|
|
debe55 |
- SafeRsaHandle rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
internal static int RsaVerificationPrimitive(
|
|
|
debe55 |
ReadOnlySpan<byte> from,
|
|
|
debe55 |
Span<byte> to,
|
|
|
debe55 |
@@ -73,13 +60,6 @@ internal static partial class Crypto
|
|
|
debe55 |
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaSize")]
|
|
|
debe55 |
internal static extern int RsaSize(SafeRsaHandle rsa);
|
|
|
debe55 |
|
|
|
debe55 |
- internal static bool RsaSign(int type, ReadOnlySpan<byte> m, int m_len, Span<byte> sigret, out int siglen, SafeRsaHandle rsa) =>
|
|
|
debe55 |
- RsaSign(type, ref MemoryMarshal.GetReference(m), m_len, ref MemoryMarshal.GetReference(sigret), out siglen, rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- [DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaSign")]
|
|
|
debe55 |
- [return: MarshalAs(UnmanagedType.Bool)]
|
|
|
debe55 |
- private static extern bool RsaSign(int type, ref byte m, int m_len, ref byte sigret, out int siglen, SafeRsaHandle rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
internal static bool RsaVerify(int type, ReadOnlySpan<byte> m, ReadOnlySpan<byte> sigbuf, SafeRsaHandle rsa)
|
|
|
debe55 |
{
|
|
|
debe55 |
bool ret = RsaVerify(
|
|
|
debe55 |
diff --git a/src/Common/src/System/Security/Cryptography/RSAOpenSsl.cs b/src/Common/src/System/Security/Cryptography/RSAOpenSsl.cs
|
|
|
debe55 |
index 87e31b9dde..225968fc50 100644
|
|
|
debe55 |
--- a/src/Common/src/System/Security/Cryptography/RSAOpenSsl.cs
|
|
|
debe55 |
+++ b/src/Common/src/System/Security/Cryptography/RSAOpenSsl.cs
|
|
|
debe55 |
@@ -655,84 +655,33 @@ public override byte[] SignHash(byte[] hash, HashAlgorithmName hashAlgorithm, RS
|
|
|
debe55 |
{
|
|
|
debe55 |
Debug.Assert(!string.IsNullOrEmpty(hashAlgorithm.Name));
|
|
|
debe55 |
Debug.Assert(padding != null);
|
|
|
debe55 |
+ ValidatePadding(padding);
|
|
|
debe55 |
|
|
|
debe55 |
signature = null;
|
|
|
debe55 |
|
|
|
debe55 |
- // Do not factor out getting _key.Value, since the key creation should not happen on
|
|
|
debe55 |
- // invalid padding modes.
|
|
|
debe55 |
+ IntPtr digestAlgorithm = Interop.Crypto.HashAlgorithmToEvp(hashAlgorithm.Name);
|
|
|
debe55 |
+ SafeEvpPKeyHandle key = GetPKey();
|
|
|
debe55 |
+ int bytesRequired = Interop.Crypto.EvpPKeySize(key);
|
|
|
debe55 |
|
|
|
debe55 |
- if (padding.Mode == RSASignaturePaddingMode.Pkcs1)
|
|
|
debe55 |
+ if (allocateSignature)
|
|
|
debe55 |
{
|
|
|
debe55 |
- int algorithmNid = GetAlgorithmNid(hashAlgorithm);
|
|
|
debe55 |
- SafeRsaHandle rsa = GetKey();
|
|
|
debe55 |
-
|
|
|
debe55 |
- int bytesRequired = Interop.Crypto.RsaSize(rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (allocateSignature)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- Debug.Assert(destination.Length == 0);
|
|
|
debe55 |
- signature = new byte[bytesRequired];
|
|
|
debe55 |
- destination = signature;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (destination.Length < bytesRequired)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- bytesWritten = 0;
|
|
|
debe55 |
- return false;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (!Interop.Crypto.RsaSign(algorithmNid, hash, hash.Length, destination, out int signatureSize, rsa))
|
|
|
debe55 |
- {
|
|
|
debe55 |
- throw Interop.Crypto.CreateOpenSslCryptographicException();
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- Debug.Assert(
|
|
|
debe55 |
- signatureSize == bytesRequired,
|
|
|
debe55 |
- $"RSA_sign reported signatureSize was {signatureSize}, when {bytesRequired} was expected");
|
|
|
debe55 |
-
|
|
|
debe55 |
- bytesWritten = signatureSize;
|
|
|
debe55 |
- return true;
|
|
|
debe55 |
+ Debug.Assert(destination.Length == 0);
|
|
|
debe55 |
+ signature = new byte[bytesRequired];
|
|
|
debe55 |
+ destination = signature;
|
|
|
debe55 |
}
|
|
|
debe55 |
- else if (padding.Mode == RSASignaturePaddingMode.Pss)
|
|
|
debe55 |
+ else if (destination.Length < bytesRequired)
|
|
|
debe55 |
{
|
|
|
debe55 |
- RsaPaddingProcessor processor = RsaPaddingProcessor.OpenProcessor(hashAlgorithm);
|
|
|
debe55 |
- SafeRsaHandle rsa = GetKey();
|
|
|
debe55 |
-
|
|
|
debe55 |
- int bytesRequired = Interop.Crypto.RsaSize(rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (allocateSignature)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- Debug.Assert(destination.Length == 0);
|
|
|
debe55 |
- signature = new byte[bytesRequired];
|
|
|
debe55 |
- destination = signature;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (destination.Length < bytesRequired)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- bytesWritten = 0;
|
|
|
debe55 |
- return false;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- byte[] pssRented = CryptoPool.Rent(bytesRequired);
|
|
|
debe55 |
- Span<byte> pssBytes = new Span<byte>(pssRented, 0, bytesRequired);
|
|
|
debe55 |
-
|
|
|
debe55 |
- processor.EncodePss(hash, pssBytes, KeySize);
|
|
|
debe55 |
-
|
|
|
debe55 |
- int ret = Interop.Crypto.RsaSignPrimitive(pssBytes, destination, rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- CryptoPool.Return(pssRented, bytesRequired);
|
|
|
debe55 |
-
|
|
|
debe55 |
- CheckReturn(ret);
|
|
|
debe55 |
-
|
|
|
debe55 |
- Debug.Assert(
|
|
|
debe55 |
- ret == bytesRequired,
|
|
|
debe55 |
- $"RSA_private_encrypt returned {ret} when {bytesRequired} was expected");
|
|
|
debe55 |
-
|
|
|
debe55 |
- bytesWritten = ret;
|
|
|
debe55 |
- return true;
|
|
|
debe55 |
+ bytesWritten = 0;
|
|
|
debe55 |
+ return false;
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
- throw PaddingModeNotSupported();
|
|
|
debe55 |
+ int written = Interop.Crypto.RsaSignHash(key, padding.Mode, digestAlgorithm, hash, destination);
|
|
|
debe55 |
+ Debug.Assert(written == bytesRequired);
|
|
|
debe55 |
+ bytesWritten = written;
|
|
|
debe55 |
+
|
|
|
debe55 |
+ // Until EVP_PKEY is what gets stored, free the temporary key handle.
|
|
|
debe55 |
+ key.Dispose();
|
|
|
debe55 |
+ return true;
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
public override bool VerifyHash(
|
|
|
debe55 |
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
|
|
|
debe55 |
index 47cb142d25..4c15914d25 100644
|
|
|
debe55 |
--- a/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
|
|
|
debe55 |
+++ b/src/Native/Unix/System.Security.Cryptography.Native/opensslshim.h
|
|
|
debe55 |
@@ -179,11 +179,15 @@ int32_t X509_up_ref(X509* x509);
|
|
|
debe55 |
#define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
|
|
|
debe55 |
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
|
|
|
debe55 |
|
|
|
debe55 |
+// EVP_PKEY_CTX_set_rsa_oaep_md doesn't call RSA_pkey_ctx_ctrl in 1.1, so don't redefine it here.
|
|
|
debe55 |
+
|
|
|
debe55 |
#undef EVP_PKEY_CTX_set_rsa_padding
|
|
|
debe55 |
#define EVP_PKEY_CTX_set_rsa_padding(ctx, pad) \
|
|
|
debe55 |
RSA_pkey_ctx_ctrl(ctx, -1, EVP_PKEY_CTRL_RSA_PADDING, pad, NULL)
|
|
|
debe55 |
|
|
|
debe55 |
-// EVP_PKEY_CTX_set_rsa_oaep_md doesn't call RSA_pkey_ctx_ctrl in 1.1, so don't redefine it here.
|
|
|
debe55 |
+#undef EVP_PKEY_CTX_set_rsa_pss_saltlen
|
|
|
debe55 |
+#define EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, len) \
|
|
|
debe55 |
+ RSA_pkey_ctx_ctrl(ctx, (EVP_PKEY_OP_SIGN|EVP_PKEY_OP_VERIFY), EVP_PKEY_CTRL_RSA_PSS_SALTLEN, len, NULL)
|
|
|
debe55 |
|
|
|
debe55 |
#endif
|
|
|
debe55 |
|
|
|
debe55 |
@@ -209,6 +213,11 @@ void SSL_CTX_set_alpn_select_cb(SSL_CTX* ctx,
|
|
|
debe55 |
void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsigned int* len);
|
|
|
debe55 |
#endif
|
|
|
debe55 |
|
|
|
debe55 |
+// The value -1 has the correct meaning on 1.0.x, but the constant wasn't named.
|
|
|
debe55 |
+#ifndef RSA_PSS_SALTLEN_DIGEST
|
|
|
debe55 |
+#define RSA_PSS_SALTLEN_DIGEST -1
|
|
|
debe55 |
+#endif
|
|
|
debe55 |
+
|
|
|
debe55 |
#define API_EXISTS(fn) (fn != NULL)
|
|
|
debe55 |
|
|
|
debe55 |
// List of all functions from the libssl that are used in the System.Security.Cryptography.Native.
|
|
|
debe55 |
@@ -378,6 +387,8 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
|
|
|
debe55 |
REQUIRED_FUNCTION(EVP_PKEY_set1_DSA) \
|
|
|
debe55 |
REQUIRED_FUNCTION(EVP_PKEY_set1_EC_KEY) \
|
|
|
debe55 |
REQUIRED_FUNCTION(EVP_PKEY_set1_RSA) \
|
|
|
debe55 |
+ REQUIRED_FUNCTION(EVP_PKEY_sign) \
|
|
|
debe55 |
+ REQUIRED_FUNCTION(EVP_PKEY_sign_init) \
|
|
|
debe55 |
REQUIRED_FUNCTION(EVP_PKEY_size) \
|
|
|
debe55 |
FALLBACK_FUNCTION(EVP_PKEY_up_ref) \
|
|
|
debe55 |
REQUIRED_FUNCTION(EVP_rc2_cbc) \
|
|
|
debe55 |
@@ -459,14 +470,12 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_new) \
|
|
|
debe55 |
FALLBACK_FUNCTION(RSA_pkey_ctx_ctrl) \
|
|
|
debe55 |
RENAMED_FUNCTION(RSA_PKCS1_OpenSSL, RSA_PKCS1_SSLeay) \
|
|
|
debe55 |
- REQUIRED_FUNCTION(RSA_private_encrypt) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_public_decrypt) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_public_encrypt) \
|
|
|
debe55 |
FALLBACK_FUNCTION(RSA_set0_crt_params) \
|
|
|
debe55 |
FALLBACK_FUNCTION(RSA_set0_factors) \
|
|
|
debe55 |
FALLBACK_FUNCTION(RSA_set0_key) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_set_method) \
|
|
|
debe55 |
- REQUIRED_FUNCTION(RSA_sign) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_size) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_up_ref) \
|
|
|
debe55 |
REQUIRED_FUNCTION(RSA_verify) \
|
|
|
debe55 |
@@ -774,6 +783,8 @@ FOR_ALL_OPENSSL_FUNCTIONS
|
|
|
debe55 |
#define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr
|
|
|
debe55 |
#define EVP_PKEY_set1_EC_KEY EVP_PKEY_set1_EC_KEY_ptr
|
|
|
debe55 |
#define EVP_PKEY_set1_RSA EVP_PKEY_set1_RSA_ptr
|
|
|
debe55 |
+#define EVP_PKEY_sign_init EVP_PKEY_sign_init_ptr
|
|
|
debe55 |
+#define EVP_PKEY_sign EVP_PKEY_sign_ptr
|
|
|
debe55 |
#define EVP_PKEY_size EVP_PKEY_size_ptr
|
|
|
debe55 |
#define EVP_PKEY_up_ref EVP_PKEY_up_ref_ptr
|
|
|
debe55 |
#define EVP_rc2_cbc EVP_rc2_cbc_ptr
|
|
|
debe55 |
@@ -855,14 +866,12 @@ FOR_ALL_OPENSSL_FUNCTIONS
|
|
|
debe55 |
#define RSA_new RSA_new_ptr
|
|
|
debe55 |
#define RSA_pkey_ctx_ctrl RSA_pkey_ctx_ctrl_ptr
|
|
|
debe55 |
#define RSA_PKCS1_OpenSSL RSA_PKCS1_OpenSSL_ptr
|
|
|
debe55 |
-#define RSA_private_encrypt RSA_private_encrypt_ptr
|
|
|
debe55 |
#define RSA_public_decrypt RSA_public_decrypt_ptr
|
|
|
debe55 |
#define RSA_public_encrypt RSA_public_encrypt_ptr
|
|
|
debe55 |
#define RSA_set0_crt_params RSA_set0_crt_params_ptr
|
|
|
debe55 |
#define RSA_set0_factors RSA_set0_factors_ptr
|
|
|
debe55 |
#define RSA_set0_key RSA_set0_key_ptr
|
|
|
debe55 |
#define RSA_set_method RSA_set_method_ptr
|
|
|
debe55 |
-#define RSA_sign RSA_sign_ptr
|
|
|
debe55 |
#define RSA_size RSA_size_ptr
|
|
|
debe55 |
#define RSA_up_ref RSA_up_ref_ptr
|
|
|
debe55 |
#define RSA_verify RSA_verify_ptr
|
|
|
debe55 |
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c
|
|
|
debe55 |
index 6235c905db..68b6a34a5d 100644
|
|
|
debe55 |
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c
|
|
|
debe55 |
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c
|
|
|
debe55 |
@@ -91,7 +91,6 @@ int32_t CryptoNative_RsaDecrypt(EVP_PKEY* pkey,
|
|
|
debe55 |
if (rsa == NULL || HasNoPrivateKey(rsa))
|
|
|
debe55 |
{
|
|
|
debe55 |
ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
|
|
|
debe55 |
- ret = -1;
|
|
|
debe55 |
goto done;
|
|
|
debe55 |
}
|
|
|
debe55 |
}
|
|
|
debe55 |
@@ -112,6 +111,81 @@ done:
|
|
|
debe55 |
return ret;
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
+int32_t CryptoNative_RsaSignHash(EVP_PKEY* pkey,
|
|
|
debe55 |
+ RsaPaddingMode padding,
|
|
|
debe55 |
+ const EVP_MD* digest,
|
|
|
debe55 |
+ const uint8_t* hash,
|
|
|
debe55 |
+ int32_t hashLen,
|
|
|
debe55 |
+ uint8_t* destination,
|
|
|
debe55 |
+ int32_t destinationLen)
|
|
|
debe55 |
+{
|
|
|
debe55 |
+ assert(pkey != NULL);
|
|
|
debe55 |
+ assert(destination != NULL);
|
|
|
debe55 |
+ assert(padding >= RsaPaddingPkcs1 && padding <= RsaPaddingOaepOrPss);
|
|
|
debe55 |
+ assert(digest != NULL || padding == RsaPaddingPkcs1);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new(pkey, NULL);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ int ret = -1;
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (ctx == NULL || EVP_PKEY_sign_init(ctx) <= 0)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ goto done;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (padding == RsaPaddingPkcs1)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PADDING) <= 0)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ goto done;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+ else
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ assert(padding == RsaPaddingOaepOrPss);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING) <= 0 ||
|
|
|
debe55 |
+ EVP_PKEY_CTX_set_rsa_pss_saltlen(ctx, RSA_PSS_SALTLEN_DIGEST) <= 0)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ goto done;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+#pragma clang diagnostic push
|
|
|
debe55 |
+#pragma clang diagnostic ignored "-Wcast-qual"
|
|
|
debe55 |
+ if (EVP_PKEY_CTX_set_signature_md(ctx, digest) <= 0)
|
|
|
debe55 |
+#pragma clang diagnostic pop
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ goto done;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+ // This check may no longer be needed on OpenSSL 3.0
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ RSA* rsa = EVP_PKEY_get0_RSA(pkey);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (rsa == NULL || HasNoPrivateKey(rsa))
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_DECRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
|
|
|
debe55 |
+ goto done;
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+ size_t written = Int32ToSizeT(destinationLen);
|
|
|
debe55 |
+
|
|
|
debe55 |
+ if (EVP_PKEY_sign(ctx, destination, &written, hash, Int32ToSizeT(hashLen)) > 0)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ ret = SizeTToInt32(written);
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+done:
|
|
|
debe55 |
+ if (ctx != NULL)
|
|
|
debe55 |
+ {
|
|
|
debe55 |
+ EVP_PKEY_CTX_free(ctx);
|
|
|
debe55 |
+ }
|
|
|
debe55 |
+
|
|
|
debe55 |
+ return ret;
|
|
|
debe55 |
+}
|
|
|
debe55 |
+
|
|
|
debe55 |
RSA* CryptoNative_EvpPkeyGetRsa(EVP_PKEY* pkey)
|
|
|
debe55 |
{
|
|
|
debe55 |
return EVP_PKEY_get1_RSA(pkey);
|
|
|
debe55 |
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
|
|
|
debe55 |
index d220065adf..f811523f78 100644
|
|
|
debe55 |
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
|
|
|
debe55 |
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h
|
|
|
debe55 |
@@ -34,6 +34,20 @@ DLLEXPORT int32_t CryptoNative_RsaDecrypt(EVP_PKEY* pkey,
|
|
|
debe55 |
uint8_t* destination,
|
|
|
debe55 |
int32_t destinationLen);
|
|
|
debe55 |
|
|
|
debe55 |
+/*
|
|
|
debe55 |
+Complete the RSA signature generation for the specified hash using the provided RSA key
|
|
|
debe55 |
+(wrapped in an EVP_PKEY) and padding/digest options.
|
|
|
debe55 |
+
|
|
|
debe55 |
+Returns the number of bytes written to destination, -1 on error.
|
|
|
debe55 |
+*/
|
|
|
debe55 |
+DLLEXPORT int32_t CryptoNative_RsaSignHash(EVP_PKEY* pkey,
|
|
|
debe55 |
+ RsaPaddingMode padding,
|
|
|
debe55 |
+ const EVP_MD* digest,
|
|
|
debe55 |
+ const uint8_t* hash,
|
|
|
debe55 |
+ int32_t hashLen,
|
|
|
debe55 |
+ uint8_t* destination,
|
|
|
debe55 |
+ int32_t destinationLen);
|
|
|
debe55 |
+
|
|
|
debe55 |
/*
|
|
|
debe55 |
Shims the EVP_PKEY_get1_RSA method.
|
|
|
debe55 |
|
|
|
debe55 |
diff --git a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.c b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.c
|
|
|
debe55 |
index 0c635dfca7..43268e88e1 100644
|
|
|
debe55 |
--- a/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.c
|
|
|
debe55 |
+++ b/src/Native/Unix/System.Security.Cryptography.Native/pal_rsa.c
|
|
|
debe55 |
@@ -48,60 +48,6 @@ static int GetOpenSslPadding(RsaPadding padding)
|
|
|
debe55 |
}
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
-static int HasNoPrivateKey(RSA* rsa)
|
|
|
debe55 |
-{
|
|
|
debe55 |
- if (rsa == NULL)
|
|
|
debe55 |
- return 1;
|
|
|
debe55 |
-
|
|
|
debe55 |
- // Shared pointer, don't free.
|
|
|
debe55 |
- const RSA_METHOD* meth = RSA_get_method(rsa);
|
|
|
debe55 |
-
|
|
|
debe55 |
- // The method has descibed itself as having the private key external to the structure.
|
|
|
debe55 |
- // That doesn't mean it's actually present, but we can't tell.
|
|
|
debe55 |
-#pragma clang diagnostic push
|
|
|
debe55 |
-#pragma clang diagnostic ignored "-Wcast-qual"
|
|
|
debe55 |
- if (RSA_meth_get_flags((RSA_METHOD*)meth) & RSA_FLAG_EXT_PKEY)
|
|
|
debe55 |
-#pragma clang diagnostic pop
|
|
|
debe55 |
- {
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- // In the event that there's a middle-ground where we report failure when success is expected,
|
|
|
debe55 |
- // one could do something like check if the RSA_METHOD intercepts all private key operations:
|
|
|
debe55 |
- //
|
|
|
debe55 |
- // * meth->rsa_priv_enc
|
|
|
debe55 |
- // * meth->rsa_priv_dec
|
|
|
debe55 |
- // * meth->rsa_sign (in 1.0.x this is only respected if the RSA_FLAG_SIGN_VER flag is asserted)
|
|
|
debe55 |
- //
|
|
|
debe55 |
- // But, for now, leave it at the EXT_PKEY flag test.
|
|
|
debe55 |
-
|
|
|
debe55 |
- // The module is documented as accepting either d or the full set of CRT parameters (p, q, dp, dq, qInv)
|
|
|
debe55 |
- // So if we see d, we're good. Otherwise, if any of the rest are missing, we're public-only.
|
|
|
debe55 |
- const BIGNUM* d;
|
|
|
debe55 |
- RSA_get0_key(rsa, NULL, NULL, &d);
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (d != NULL)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- const BIGNUM* p;
|
|
|
debe55 |
- const BIGNUM* q;
|
|
|
debe55 |
- const BIGNUM* dmp1;
|
|
|
debe55 |
- const BIGNUM* dmq1;
|
|
|
debe55 |
- const BIGNUM* iqmp;
|
|
|
debe55 |
-
|
|
|
debe55 |
- RSA_get0_factors(rsa, &p, &q);
|
|
|
debe55 |
- RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp);
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (p == NULL || q == NULL || dmp1 == NULL || dmq1 == NULL || iqmp == NULL)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- return 1;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
-}
|
|
|
debe55 |
-
|
|
|
debe55 |
int32_t
|
|
|
debe55 |
CryptoNative_RsaPublicEncrypt(int32_t flen, const uint8_t* from, uint8_t* to, RSA* rsa, RsaPadding padding)
|
|
|
debe55 |
{
|
|
|
debe55 |
@@ -109,17 +55,6 @@ CryptoNative_RsaPublicEncrypt(int32_t flen, const uint8_t* from, uint8_t* to, RS
|
|
|
debe55 |
return RSA_public_encrypt(flen, from, to, rsa, openSslPadding);
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
-int32_t CryptoNative_RsaSignPrimitive(int32_t flen, const uint8_t* from, uint8_t* to, RSA* rsa)
|
|
|
debe55 |
-{
|
|
|
debe55 |
- if (HasNoPrivateKey(rsa))
|
|
|
debe55 |
- {
|
|
|
debe55 |
- ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_NULL_PRIVATE_ENCRYPT, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
|
|
|
debe55 |
- return -1;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- return RSA_private_encrypt(flen, from, to, rsa, RSA_NO_PADDING);
|
|
|
debe55 |
-}
|
|
|
debe55 |
-
|
|
|
debe55 |
int32_t CryptoNative_RsaVerificationPrimitive(int32_t flen, const uint8_t* from, uint8_t* to, RSA* rsa)
|
|
|
debe55 |
{
|
|
|
debe55 |
return RSA_public_decrypt(flen, from, to, rsa, RSA_NO_PADDING);
|
|
|
debe55 |
@@ -130,41 +65,6 @@ int32_t CryptoNative_RsaSize(RSA* rsa)
|
|
|
debe55 |
return RSA_size(rsa);
|
|
|
debe55 |
}
|
|
|
debe55 |
|
|
|
debe55 |
-int32_t
|
|
|
debe55 |
-CryptoNative_RsaSign(int32_t type, const uint8_t* m, int32_t mlen, uint8_t* sigret, int32_t* siglen, RSA* rsa)
|
|
|
debe55 |
-{
|
|
|
debe55 |
- if (siglen == NULL)
|
|
|
debe55 |
- {
|
|
|
debe55 |
- assert(false);
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- *siglen = 0;
|
|
|
debe55 |
-
|
|
|
debe55 |
- if (HasNoPrivateKey(rsa))
|
|
|
debe55 |
- {
|
|
|
debe55 |
- ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_SIGN, RSA_R_VALUE_MISSING, __FILE__, __LINE__);
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- // Shared pointer to the metadata about the message digest algorithm
|
|
|
debe55 |
- const EVP_MD* digest = EVP_get_digestbynid(type);
|
|
|
debe55 |
-
|
|
|
debe55 |
- // If the digest itself isn't known then RSA_R_UNKNOWN_ALGORITHM_TYPE will get reported, but
|
|
|
debe55 |
- // we have to check that the digest size matches what we expect.
|
|
|
debe55 |
- if (digest != NULL && mlen != EVP_MD_size(digest))
|
|
|
debe55 |
- {
|
|
|
debe55 |
- ERR_PUT_error(ERR_LIB_RSA, RSA_F_RSA_SIGN, RSA_R_INVALID_MESSAGE_LENGTH, __FILE__, __LINE__);
|
|
|
debe55 |
- return 0;
|
|
|
debe55 |
- }
|
|
|
debe55 |
-
|
|
|
debe55 |
- unsigned int unsignedSigLen = 0;
|
|
|
debe55 |
- int32_t ret = RSA_sign(type, m, Int32ToUint32(mlen), sigret, &unsignedSigLen, rsa);
|
|
|
debe55 |
- assert(unsignedSigLen <= INT32_MAX);
|
|
|
debe55 |
- *siglen = (int32_t)unsignedSigLen;
|
|
|
debe55 |
- return ret;
|
|
|
debe55 |
-}
|
|
|
debe55 |
-
|
|
|
debe55 |
int32_t
|
|
|
debe55 |
CryptoNative_RsaVerify(int32_t type, const uint8_t* m, int32_t mlen, uint8_t* sigbuf, int32_t siglen, RSA* rsa)
|
|
|
debe55 |
{
|
|
|
debe55 |
--
|
|
|
debe55 |
2.31.1
|
|
|
debe55 |
|