Skip to content

Commit 6841143

Browse files
authored
Use EVP_PKEY for RSA key generation
1 parent 88be24b commit 6841143

File tree

13 files changed

+103
-54
lines changed

13 files changed

+103
-54
lines changed

src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.EvpPkey.Rsa.cs

+16
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,22 @@ internal static partial class Interop
99
{
1010
internal static partial class Crypto
1111
{
12+
[DllImport(Libraries.CryptoNative)]
13+
private static extern SafeEvpPKeyHandle CryptoNative_RsaGenerateKey(int keySize);
14+
15+
internal static SafeEvpPKeyHandle RsaGenerateKey(int keySize)
16+
{
17+
SafeEvpPKeyHandle pkey = CryptoNative_RsaGenerateKey(keySize);
18+
19+
if (pkey.IsInvalid)
20+
{
21+
pkey.Dispose();
22+
throw CreateOpenSslCryptographicException();
23+
}
24+
25+
return pkey;
26+
}
27+
1228
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_EvpPkeyGetRsa")]
1329
internal static extern SafeRsaHandle EvpPkeyGetRsa(SafeEvpPKeyHandle pkey);
1430

src/libraries/Common/src/Interop/Unix/System.Security.Cryptography.Native/Interop.Rsa.cs

-3
Original file line numberDiff line numberDiff line change
@@ -88,9 +88,6 @@ private static extern int RsaVerificationPrimitive(
8888
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaSize")]
8989
internal static extern int RsaSize(SafeRsaHandle rsa);
9090

91-
[DllImport(Libraries.CryptoNative, EntryPoint = "CryptoNative_RsaGenerateKeyEx")]
92-
internal static extern int RsaGenerateKeyEx(SafeRsaHandle rsa, int bits, SafeBignumHandle e);
93-
9491
internal static bool RsaSign(int type, ReadOnlySpan<byte> m, int m_len, Span<byte> sigret, out int siglen, SafeRsaHandle rsa) =>
9592
RsaSign(type, ref MemoryMarshal.GetReference(m), m_len, ref MemoryMarshal.GetReference(sigret), out siglen, rsa);
9693

src/libraries/Common/src/System/Security/Cryptography/RSAOpenSsl.cs

+8-29
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,6 @@ public sealed partial class RSAOpenSsl : RSA
2323
{
2424
private const int BitsPerByte = 8;
2525

26-
// 65537 (0x10001) in big-endian form
27-
private static ReadOnlySpan<byte> DefaultExponent => new byte[] { 0x01, 0x00, 0x01 };
28-
2926
private Lazy<SafeRsaHandle> _key;
3027

3128
public RSAOpenSsl()
@@ -590,36 +587,18 @@ private static void CheckBoolReturn(int returnValue)
590587

591588
private SafeRsaHandle GenerateKey()
592589
{
593-
SafeRsaHandle key = Interop.Crypto.RsaCreate();
594-
bool generated = false;
595-
596-
Interop.Crypto.CheckValidOpenSslHandle(key);
597-
598-
try
590+
using (SafeEvpPKeyHandle pkey = Interop.Crypto.RsaGenerateKey(KeySize))
599591
{
600-
using (SafeBignumHandle exponent = Interop.Crypto.CreateBignum(DefaultExponent))
601-
{
602-
// The documentation for RSA_generate_key_ex does not say that it returns only
603-
// 0 or 1, so the call marshals it back as a full Int32 and checks for a value
604-
// of 1 explicitly.
605-
int response = Interop.Crypto.RsaGenerateKeyEx(
606-
key,
607-
KeySize,
608-
exponent);
609-
610-
CheckBoolReturn(response);
611-
generated = true;
612-
}
613-
}
614-
finally
615-
{
616-
if (!generated)
592+
SafeRsaHandle rsa = Interop.Crypto.EvpPkeyGetRsa(pkey);
593+
594+
if (rsa.IsInvalid)
617595
{
618-
key.Dispose();
596+
rsa.Dispose();
597+
throw Interop.Crypto.CreateOpenSslCryptographicException();
619598
}
620-
}
621599

622-
return key;
600+
return rsa;
601+
}
623602
}
624603

625604
protected override byte[] HashData(byte[] data, int offset, int count, HashAlgorithmName hashAlgorithm) =>

src/libraries/Native/Unix/System.Security.Cryptography.Native/apibridge.c

+8
Original file line numberDiff line numberDiff line change
@@ -788,4 +788,12 @@ int local_BIO_up_ref(BIO *bio)
788788

789789
return CRYPTO_add_lock(&bio->references, 1, CRYPTO_LOCK_BIO, __FILE__, __LINE__) > 1;
790790
}
791+
792+
int32_t local_RSA_pkey_ctx_ctrl(EVP_PKEY_CTX* ctx, int32_t optype, int32_t cmd, int32_t p1, void* p2)
793+
{
794+
// On OpenSSL 1.0.2 there aren't two different identifiers for RSA,
795+
// so just pass the request on th EVP_PKEY_CTX_ctrl with the only identifier defined.
796+
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_RSA, optype, cmd, p1, p2);
797+
}
798+
791799
#endif

src/libraries/Native/Unix/System.Security.Cryptography.Native/apibridge.h

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ int32_t local_RSA_meth_get_flags(const RSA_METHOD* meth);
2626
int32_t local_RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
2727
int32_t local_RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q);
2828
int32_t local_RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d);
29+
int32_t local_RSA_pkey_ctx_ctrl(EVP_PKEY_CTX* ctx, int32_t optype, int32_t cmd, int32_t p1, void* p2);
2930
int32_t local_SSL_is_init_finished(const SSL* ssl);
3031
int32_t local_SSL_CTX_config(SSL_CTX* ctx, const char* name);
3132
unsigned long local_SSL_CTX_set_options(SSL_CTX* ctx, unsigned long options);

src/libraries/Native/Unix/System.Security.Cryptography.Native/entrypoints.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ static const Entry s_cryptoNative[] =
222222
DllImportEntry(CryptoNative_RecursiveFreeX509Stack)
223223
DllImportEntry(CryptoNative_RsaCreate)
224224
DllImportEntry(CryptoNative_RsaDestroy)
225-
DllImportEntry(CryptoNative_RsaGenerateKeyEx)
225+
DllImportEntry(CryptoNative_RsaGenerateKey)
226226
DllImportEntry(CryptoNative_RsaPrivateDecrypt)
227227
DllImportEntry(CryptoNative_RsaPublicEncrypt)
228228
DllImportEntry(CryptoNative_RsaSign)

src/libraries/Native/Unix/System.Security.Cryptography.Native/opensslshim.h

+23
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,7 @@ void RSA_get0_factors(const RSA* rsa, const BIGNUM** p, const BIGNUM** q);
148148
void RSA_get0_key(const RSA* rsa, const BIGNUM** n, const BIGNUM** e, const BIGNUM** d);
149149
int32_t RSA_meth_get_flags(const RSA_METHOD* meth);
150150
const RSA_METHOD* RSA_PKCS1_OpenSSL(void);
151+
int32_t RSA_pkey_ctx_ctrl(EVP_PKEY_CTX* ctx, int32_t optype, int32_t cmd, int32_t p1, void* p2);
151152
int32_t RSA_set0_crt_params(RSA* rsa, BIGNUM* dmp1, BIGNUM* dmq1, BIGNUM* iqmp);
152153
int32_t RSA_set0_factors(RSA* rsa, BIGNUM* p, BIGNUM* q);
153154
int32_t RSA_set0_key(RSA* rsa, BIGNUM* n, BIGNUM* e, BIGNUM* d);
@@ -176,6 +177,13 @@ const X509_ALGOR* X509_get0_tbs_sigalg(const X509* x509);
176177
X509_PUBKEY* X509_get_X509_PUBKEY(const X509* x509);
177178
int32_t X509_get_version(const X509* x509);
178179
int32_t X509_up_ref(X509* x509);
180+
181+
// Redefine EVP_PKEY_CTX_set_rsa operations to use (local_)RSA_pkey_ctx_ctrl so the path is the same
182+
// for 1.0-built on 1.1 as on 1.1-built on 1.1.
183+
#undef EVP_PKEY_CTX_set_rsa_keygen_bits
184+
#define EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, bits) \
185+
RSA_pkey_ctx_ctrl(ctx, EVP_PKEY_OP_KEYGEN, EVP_PKEY_CTRL_RSA_KEYGEN_BITS, bits, NULL)
186+
179187
#endif
180188

181189
#if OPENSSL_VERSION_NUMBER < OPENSSL_VERSION_1_0_2_RTM
@@ -362,15 +370,21 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
362370
RENAMED_FUNCTION(EVP_MD_CTX_free, EVP_MD_CTX_destroy) \
363371
RENAMED_FUNCTION(EVP_MD_CTX_new, EVP_MD_CTX_create) \
364372
REQUIRED_FUNCTION(EVP_MD_size) \
373+
REQUIRED_FUNCTION(EVP_PKEY_CTX_ctrl) \
365374
REQUIRED_FUNCTION(EVP_PKEY_CTX_free) \
375+
REQUIRED_FUNCTION(EVP_PKEY_CTX_get0_pkey) \
366376
REQUIRED_FUNCTION(EVP_PKEY_CTX_new) \
377+
REQUIRED_FUNCTION(EVP_PKEY_CTX_new_id) \
378+
REQUIRED_FUNCTION(EVP_PKEY_base_id) \
367379
REQUIRED_FUNCTION(EVP_PKEY_derive_set_peer) \
368380
REQUIRED_FUNCTION(EVP_PKEY_derive_init) \
369381
REQUIRED_FUNCTION(EVP_PKEY_derive) \
370382
REQUIRED_FUNCTION(EVP_PKEY_free) \
371383
REQUIRED_FUNCTION(EVP_PKEY_get1_DSA) \
372384
REQUIRED_FUNCTION(EVP_PKEY_get1_EC_KEY) \
373385
REQUIRED_FUNCTION(EVP_PKEY_get1_RSA) \
386+
REQUIRED_FUNCTION(EVP_PKEY_keygen) \
387+
REQUIRED_FUNCTION(EVP_PKEY_keygen_init) \
374388
REQUIRED_FUNCTION(EVP_PKEY_new) \
375389
REQUIRED_FUNCTION(EVP_PKEY_set1_DSA) \
376390
REQUIRED_FUNCTION(EVP_PKEY_set1_EC_KEY) \
@@ -453,6 +467,7 @@ void SSL_get0_alpn_selected(const SSL* ssl, const unsigned char** protocol, unsi
453467
FALLBACK_FUNCTION(RSA_get0_key) \
454468
FALLBACK_FUNCTION(RSA_meth_get_flags) \
455469
REQUIRED_FUNCTION(RSA_new) \
470+
FALLBACK_FUNCTION(RSA_pkey_ctx_ctrl) \
456471
RENAMED_FUNCTION(RSA_PKCS1_OpenSSL, RSA_PKCS1_SSLeay) \
457472
REQUIRED_FUNCTION(RSA_private_decrypt) \
458473
REQUIRED_FUNCTION(RSA_private_encrypt) \
@@ -773,15 +788,21 @@ FOR_ALL_OPENSSL_FUNCTIONS
773788
#define EVP_MD_CTX_free EVP_MD_CTX_free_ptr
774789
#define EVP_MD_CTX_new EVP_MD_CTX_new_ptr
775790
#define EVP_MD_size EVP_MD_size_ptr
791+
#define EVP_PKEY_CTX_ctrl EVP_PKEY_CTX_ctrl_ptr
776792
#define EVP_PKEY_CTX_free EVP_PKEY_CTX_free_ptr
793+
#define EVP_PKEY_CTX_get0_pkey EVP_PKEY_CTX_get0_pkey_ptr
777794
#define EVP_PKEY_CTX_new EVP_PKEY_CTX_new_ptr
795+
#define EVP_PKEY_CTX_new_id EVP_PKEY_CTX_new_id_ptr
796+
#define EVP_PKEY_base_id EVP_PKEY_base_id_ptr
778797
#define EVP_PKEY_derive_set_peer EVP_PKEY_derive_set_peer_ptr
779798
#define EVP_PKEY_derive_init EVP_PKEY_derive_init_ptr
780799
#define EVP_PKEY_derive EVP_PKEY_derive_ptr
781800
#define EVP_PKEY_free EVP_PKEY_free_ptr
782801
#define EVP_PKEY_get1_DSA EVP_PKEY_get1_DSA_ptr
783802
#define EVP_PKEY_get1_EC_KEY EVP_PKEY_get1_EC_KEY_ptr
784803
#define EVP_PKEY_get1_RSA EVP_PKEY_get1_RSA_ptr
804+
#define EVP_PKEY_keygen EVP_PKEY_keygen_ptr
805+
#define EVP_PKEY_keygen_init EVP_PKEY_keygen_init_ptr
785806
#define EVP_PKEY_new EVP_PKEY_new_ptr
786807
#define EVP_PKEY_set1_DSA EVP_PKEY_set1_DSA_ptr
787808
#define EVP_PKEY_set1_EC_KEY EVP_PKEY_set1_EC_KEY_ptr
@@ -864,6 +885,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
864885
#define RSA_get_method RSA_get_method_ptr
865886
#define RSA_meth_get_flags RSA_meth_get_flags_ptr
866887
#define RSA_new RSA_new_ptr
888+
#define RSA_pkey_ctx_ctrl RSA_pkey_ctx_ctrl_ptr
867889
#define RSA_PKCS1_OpenSSL RSA_PKCS1_OpenSSL_ptr
868890
#define RSA_private_decrypt RSA_private_decrypt_ptr
869891
#define RSA_private_encrypt RSA_private_encrypt_ptr
@@ -1084,6 +1106,7 @@ FOR_ALL_OPENSSL_FUNCTIONS
10841106
#define RSA_set0_crt_params local_RSA_set0_crt_params
10851107
#define RSA_set0_factors local_RSA_set0_factors
10861108
#define RSA_set0_key local_RSA_set0_key
1109+
#define RSA_pkey_ctx_ctrl local_RSA_pkey_ctx_ctrl
10871110
#define SSL_CTX_set_security_level local_SSL_CTX_set_security_level
10881111
#define SSL_is_init_finished local_SSL_is_init_finished
10891112
#define X509_CRL_get0_nextUpdate local_X509_CRL_get0_nextUpdate

src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.c

+29
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,35 @@
33

44
#include "pal_evp_pkey_rsa.h"
55

6+
EVP_PKEY* CryptoNative_RsaGenerateKey(int keySize)
7+
{
8+
EVP_PKEY_CTX* ctx = EVP_PKEY_CTX_new_id(EVP_PKEY_RSA, NULL);
9+
10+
if (ctx == NULL)
11+
{
12+
return NULL;
13+
}
14+
15+
EVP_PKEY* pkey = NULL;
16+
EVP_PKEY* ret = NULL;
17+
18+
if (EVP_PKEY_keygen_init(ctx) == 1 &&
19+
EVP_PKEY_CTX_set_rsa_keygen_bits(ctx, keySize) == 1 &&
20+
EVP_PKEY_keygen(ctx, &pkey) == 1)
21+
{
22+
ret = pkey;
23+
pkey = NULL;
24+
}
25+
26+
if (pkey != NULL)
27+
{
28+
EVP_PKEY_free(pkey);
29+
}
30+
31+
EVP_PKEY_CTX_free(ctx);
32+
return ret;
33+
}
34+
635
RSA* CryptoNative_EvpPkeyGetRsa(EVP_PKEY* pkey)
736
{
837
return EVP_PKEY_get1_RSA(pkey);

src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_evp_pkey_rsa.h

+5
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,11 @@
55
#include "pal_compiler.h"
66
#include "opensslshim.h"
77

8+
/*
9+
Creates an RSA key of the requested size.
10+
*/
11+
PALEXPORT EVP_PKEY* CryptoNative_RsaGenerateKey(int32_t keySize);
12+
813
/*
914
Shims the EVP_PKEY_get1_RSA method.
1015

src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_rsa.c

-5
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,6 @@ int32_t CryptoNative_RsaSize(RSA* rsa)
144144
return RSA_size(rsa);
145145
}
146146

147-
int32_t CryptoNative_RsaGenerateKeyEx(RSA* rsa, int32_t bits, BIGNUM* e)
148-
{
149-
return RSA_generate_key_ex(rsa, bits, e, NULL);
150-
}
151-
152147
int32_t
153148
CryptoNative_RsaSign(int32_t type, const uint8_t* m, int32_t mlen, uint8_t* sigret, int32_t* siglen, RSA* rsa)
154149
{

src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_rsa.h

-7
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,6 @@ Returns the RSA modulus size in bytes.
8585
*/
8686
PALEXPORT int32_t CryptoNative_RsaSize(RSA* rsa);
8787

88-
/*
89-
Shims the RSA_generate_key_ex method.
90-
91-
Returns 1 upon success, otherwise 0.
92-
*/
93-
PALEXPORT int32_t CryptoNative_RsaGenerateKeyEx(RSA* rsa, int32_t bits, BIGNUM* e);
94-
9588
/*
9689
Shims the RSA_sign method.
9790

src/libraries/Native/Unix/System.Security.Cryptography.Native/pal_ssl.c

+10-9
Original file line numberDiff line numberDiff line change
@@ -644,16 +644,22 @@ int32_t CryptoNative_SslGetCurrentCipherId(SSL* ssl, int32_t* cipherId)
644644
// This function generates key pair and creates simple certificate.
645645
static int MakeSelfSignedCertificate(X509 * cert, EVP_PKEY* evp)
646646
{
647-
RSA* rsa = CryptoNative_RsaCreate();
647+
RSA* rsa = NULL;
648648
ASN1_TIME* time = ASN1_TIME_new();
649-
BIGNUM* bn = BN_new();
650-
BN_set_word(bn, RSA_F4);
651649
X509_NAME * asnName;
652650
unsigned char * name = (unsigned char*)"localhost";
653651

654652
int ret = 0;
655653

656-
if (rsa != NULL && CryptoNative_RsaGenerateKeyEx(rsa, 2048, bn) == 1)
654+
EVP_PKEY* pkey = CryptoNative_RsaGenerateKey(2048);
655+
656+
if (pkey != NULL)
657+
{
658+
rsa = EVP_PKEY_get1_RSA(pkey);
659+
EVP_PKEY_free(pkey);
660+
}
661+
662+
if (rsa != NULL)
657663
{
658664
if (CryptoNative_EvpPkeySetRsa(evp, rsa) == 1)
659665
{
@@ -675,11 +681,6 @@ static int MakeSelfSignedCertificate(X509 * cert, EVP_PKEY* evp)
675681
ret = X509_sign(cert, evp, EVP_sha256());
676682
}
677683

678-
if (bn != NULL)
679-
{
680-
BN_free(bn);
681-
}
682-
683684
if (rsa != NULL)
684685
{
685686
RSA_free(rsa);

src/libraries/System.Security.Cryptography.Algorithms/src/System.Security.Cryptography.Algorithms.csproj

+2
Original file line numberDiff line numberDiff line change
@@ -582,6 +582,8 @@
582582
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EcKey.cs" />
583583
<Compile Include="$(CommonPath)Interop\Unix\System.Security.Cryptography.Native\Interop.EcDsa.cs"
584584
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EcDsa.cs" />
585+
<Compile Include="$(CommonPath)Interop\Unix\System.Security.Cryptography.Native\Interop.EvpPkey.Rsa.cs"
586+
Link="Common\Interop\Unix\System.Security.Cryptography.Native\Interop.EvpPkey.Rsa.cs" />
585587
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeBignumHandle.Unix.cs"
586588
Link="Common\Microsoft\Win32\SafeHandles\SafeBignumHandle.Unix.cs" />
587589
<Compile Include="$(CommonPath)Microsoft\Win32\SafeHandles\SafeEcKeyHandle.Unix.cs"

0 commit comments

Comments
 (0)