MySQL.Data/src/common/Ssl.cs | 45 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) diff --git a/MySQL.Data/src/common/Ssl.cs b/MySQL.Data/src/common/Ssl.cs index 60e053f9..a0c0a1b0 100644 --- a/MySQL.Data/src/common/Ssl.cs +++ b/MySQL.Data/src/common/Ssl.cs @@ -38,6 +38,7 @@ using System.Collections.Generic; using System.IO; using System.Net.Security; using System.Security.Authentication; +using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; @@ -145,6 +146,45 @@ namespace MySql.Data.Common return certs; } + private X509CertificateCollection GetPEMClientCertificates() + { + X509CertificateCollection certs = new X509CertificateCollection(); +#if !NETSTANDARD1_6 + if (_settings.SslCert != null && _settings.SslKey != null) + { + var pemcert = ReadSslCertificate(_settings.SslCert); + var pemkey = ReadKey(_settings.SslKey); + + var pemkeyparams = (Org.BouncyCastle.Crypto.Parameters.RsaPrivateCrtKeyParameters)pemkey.Private; + var keyparams = new RSAParameters(); + keyparams.Modulus = pemkeyparams.Modulus.ToByteArrayUnsigned(); + keyparams.P = pemkeyparams.P.ToByteArrayUnsigned(); + keyparams.Q = pemkeyparams.Q.ToByteArrayUnsigned(); + keyparams.DP = pemkeyparams.DP.ToByteArrayUnsigned(); + keyparams.DQ = pemkeyparams.DQ.ToByteArrayUnsigned(); + keyparams.InverseQ = pemkeyparams.QInv.ToByteArrayUnsigned(); + keyparams.D = pemkeyparams.Exponent.ToByteArrayUnsigned(); + keyparams.Exponent = pemkeyparams.PublicExponent.ToByteArrayUnsigned(); + + var key = new RSACryptoServiceProvider(new CspParameters + { + // SslStream isn't happy on windows if a name isn't set + KeyContainerName = "test", + }); + key.ImportParameters(keyparams); + + var cert = new X509Certificate2(pemcert.GetEncoded()); +#if NETCOREAPP2_0 + cert = cert.CopyWithPrivateKey(key); +#else + cert.PrivateKey = key; +#endif + certs.Add(cert); + } +#endif + return certs; + } + /// /// Initiates the SSL connection. /// @@ -167,7 +207,7 @@ namespace MySql.Data.Common new RemoteCertificateValidationCallback(ServerCheckValidation); SslStream ss = new SslStream(baseStream, false, sslValidateCallback, null); X509CertificateCollection certs = _treatCertificatesAsPemFormat - ? new X509CertificateCollection() + ? GetPEMClientCertificates() : GetPFXClientCertificates(); string connectionId = connectionString.GetHashCode().ToString(); @@ -489,7 +529,8 @@ namespace MySql.Data.Common /// The server certificate. private void VerifyIssuer(Org.BouncyCastle.X509.X509Certificate CACertificate, System.Security.Cryptography.X509Certificates.X509Certificate serverCertificate) { - if (CACertificate.IssuerDN.ToString() != serverCertificate.Issuer) + var cacert = new System.Security.Cryptography.X509Certificates.X509Certificate(CACertificate.GetEncoded()); + if (cacert.Issuer != serverCertificate.Issuer) throw new MySqlException(Resources.SslConnectionError, new Exception(Resources.SslCertificateCAMismatch)); }