public void Dispose() { if (_caStackHandle != null) { _caStackHandle.Dispose(); _caStackHandle = null; } if (_x509Handle != null) { _x509Handle.Dispose(); _x509Handle = null; } if (_evpPkeyHandle != null) { _evpPkeyHandle.Dispose(); _evpPkeyHandle = null; } if (_pkcs12Handle != null) { _pkcs12Handle.Dispose(); } }
//TODO (Issue #3362) Set remote certificate options internal static SafeSslHandle AllocateSslContext(long options, SafeX509Handle certHandle, SafeEvpPKeyHandle certKeyHandle, bool isServer, bool remoteCertRequired) { SafeSslHandle context = null; IntPtr method = GetSslMethod(isServer, options); using (libssl.SafeSslContextHandle innerContext = new libssl.SafeSslContextHandle(method)) { if (innerContext.IsInvalid) { throw CreateSslException(SR.net_allocate_ssl_context_failed); } libssl.SSL_CTX_ctrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero); libssl.SSL_CTX_set_quiet_shutdown(innerContext, 1); if (certHandle != null && certKeyHandle != null) { SetSslCertificate(innerContext, certHandle, certKeyHandle); } context = SafeSslHandle.Create(innerContext, isServer); Debug.Assert(context != null, "Expected non-null return value from SafeSslHandle.Create"); if (context.IsInvalid) { context.Dispose(); throw CreateSslException(SR.net_allocate_ssl_context_failed); } } return context; }
internal unsafe OpenSslX509CertificateReader(byte[] data) { SafeX509Handle cert; // If the first byte is a hyphen then this is likely PEM-encoded, // otherwise it's DER-encoded (or not a certificate). if (data[0] == '-') { using (SafeBioHandle bio = Interop.libcrypto.BIO_new(Interop.libcrypto.BIO_s_mem())) { Interop.libcrypto.CheckValidOpenSslHandle(bio); Interop.libcrypto.BIO_write(bio, data, data.Length); cert = Interop.libcrypto.PEM_read_bio_X509_AUX(bio, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero); } } else { cert = Interop.libcrypto.OpenSslD2I(Interop.libcrypto.d2i_X509, data); } Interop.libcrypto.CheckValidOpenSslHandle(cert); // X509_check_purpose has the effect of populating the sha1_hash value, // and other "initialize" type things. bool init = Interop.libcrypto.X509_check_purpose(cert, -1, 0); if (!init) { throw Interop.libcrypto.CreateOpenSslCryptographicException(); } _cert = cert; }
internal static SafeSharedAsn1IntegerHandle X509GetSerialNumber(SafeX509Handle x) { CheckValidOpenSslHandle(x); return SafeInteriorHandle.OpenInteriorHandle( handle => X509GetSerialNumber_private(handle), x); }
internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX509Handle certHandle, SafeEvpPKeyHandle certKeyHandle, EncryptionPolicy policy, bool isServer, bool remoteCertRequired) { SafeSslHandle context = null; IntPtr method = GetSslMethod(protocols); using (SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method)) { if (innerContext.IsInvalid) { throw CreateSslException(SR.net_allocate_ssl_context_failed); } // Configure allowed protocols. It's ok to use DangerousGetHandle here without AddRef/Release as we just // create the handle, it's rooted by the using, no one else has a reference to it, etc. Ssl.SetProtocolOptions(innerContext.DangerousGetHandle(), protocols); // The logic in SafeSslHandle.Disconnect is simple because we are doing a quiet // shutdown (we aren't negotiating for session close to enable later session // restoration). // // If you find yourself wanting to remove this line to enable bidirectional // close-notify, you'll probably need to rewrite SafeSslHandle.Disconnect(). // https://www.openssl.org/docs/manmaster/ssl/SSL_shutdown.html Ssl.SslCtxSetQuietShutdown(innerContext); if (!Ssl.SetEncryptionPolicy(innerContext, policy)) { throw new PlatformNotSupportedException(SR.Format(SR.net_ssl_encryptionpolicy_notsupported, policy)); } if (certHandle != null && certKeyHandle != null) { SetSslCertificate(innerContext, certHandle, certKeyHandle); } if (remoteCertRequired) { Debug.Assert(isServer, "isServer flag should be true"); Ssl.SslCtxSetVerify(innerContext, s_verifyClientCertificate); //update the client CA list UpdateCAListFromRootStore(innerContext); } context = SafeSslHandle.Create(innerContext, isServer); Debug.Assert(context != null, "Expected non-null return value from SafeSslHandle.Create"); if (context.IsInvalid) { context.Dispose(); throw CreateSslException(SR.net_allocate_ssl_context_failed); } } return context; }
internal static extern SafePkcs12Handle PKCS12_create( string pass, string name, SafeEvpPKeyHandle pkey, SafeX509Handle cert, SafeX509StackHandle ca, int nid_key, int nid_cert, int iter, int mac_iter, int keytype);
internal OpenSslX509CertificateReader(SafeX509Handle handle) { // X509_check_purpose has the effect of populating the sha1_hash value, // and other "initialize" type things. bool init = Interop.Crypto.X509CheckPurpose(handle, -1, 0); if (!init) { throw Interop.Crypto.CreateOpenSslCryptographicException(); } _cert = handle; }
public SafeFreeCertContext(SafeX509Handle certificate) : base(IntPtr.Zero, true) { // In certain scenarios (eg. server querying for a client cert), the // input certificate may be invalid and this is OK if ((null != certificate) && !certificate.IsInvalid) { bool gotRef = false; certificate.DangerousAddRef(ref gotRef); Debug.Assert(gotRef, "Unexpected failure in AddRef of certificate"); _certificate = certificate; handle = _certificate.DangerousGetHandle(); } }
internal static SafeSslHandle AllocateSslContext(long options, SafeX509Handle certHandle, SafeEvpPKeyHandle certKeyHandle, string encryptionPolicy, bool isServer, bool remoteCertRequired) { SafeSslHandle context = null; IntPtr method = GetSslMethod(isServer, options); using (libssl.SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method)) { if (innerContext.IsInvalid) { throw CreateSslException(SR.net_allocate_ssl_context_failed); } libssl.SSL_CTX_ctrl(innerContext, libssl.SSL_CTRL_OPTIONS, options, IntPtr.Zero); libssl.SSL_CTX_set_quiet_shutdown(innerContext, 1); libssl.SSL_CTX_set_cipher_list(innerContext, encryptionPolicy); if (certHandle != null && certKeyHandle != null) { SetSslCertificate(innerContext, certHandle, certKeyHandle); } if (remoteCertRequired) { Debug.Assert(isServer, "isServer flag should be true"); libssl.SSL_CTX_set_verify(innerContext, (int)libssl.ClientCertOption.SSL_VERIFY_PEER | (int)libssl.ClientCertOption.SSL_VERIFY_FAIL_IF_NO_PEER_CERT, s_verifyClientCertificate); //update the client CA list UpdateCAListFromRootStore(innerContext); } context = SafeSslHandle.Create(innerContext, isServer); Debug.Assert(context != null, "Expected non-null return value from SafeSslHandle.Create"); if (context.IsInvalid) { context.Dispose(); throw CreateSslException(SR.net_allocate_ssl_context_failed); } } return context; }
public SafeFreeSslCredentials(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy) : base(IntPtr.Zero, true) { Debug.Assert( certificate == null || certificate is X509Certificate2, "Only X509Certificate2 certificates are supported at this time"); X509Certificate2 cert = (X509Certificate2)certificate; if (cert != null) { Debug.Assert(cert.HasPrivateKey, "cert.HasPrivateKey"); using (RSAOpenSsl rsa = (RSAOpenSsl)cert.GetRSAPrivateKey()) { if (rsa != null) { _certKeyHandle = rsa.DuplicateKeyHandle(); Interop.Crypto.CheckValidOpenSslHandle(_certKeyHandle); } } if (_certKeyHandle == null) { using (ECDsaOpenSsl ecdsa = (ECDsaOpenSsl)cert.GetECDsaPrivateKey()) { if (ecdsa != null) { _certKeyHandle = ecdsa.DuplicateKeyHandle(); Interop.Crypto.CheckValidOpenSslHandle(_certKeyHandle); } } } if (_certKeyHandle == null) { throw new NotSupportedException(SR.net_ssl_io_no_server_cert); } _certHandle = Interop.Crypto.X509UpRef(cert.Handle); Interop.Crypto.CheckValidOpenSslHandle(_certHandle); } _protocols = protocols; _policy = policy; }
internal static SafeSslHandle AllocateSslContext(SslProtocols protocols, SafeX509Handle certHandle, SafeEvpPKeyHandle certKeyHandle, EncryptionPolicy policy, bool isServer, bool remoteCertRequired) { SafeSslHandle context = null; IntPtr method = GetSslMethod(protocols); using (SafeSslContextHandle innerContext = Ssl.SslCtxCreate(method)) { if (innerContext.IsInvalid) { throw CreateSslException(SR.net_allocate_ssl_context_failed); } Ssl.SetProtocolOptions(innerContext, protocols); Ssl.SslCtxSetQuietShutdown(innerContext); Ssl.SetEncryptionPolicy(innerContext, policy); if (certHandle != null && certKeyHandle != null) { SetSslCertificate(innerContext, certHandle, certKeyHandle); } if (remoteCertRequired) { Debug.Assert(isServer, "isServer flag should be true"); Ssl.SslCtxSetVerify(innerContext, s_verifyClientCertificate); //update the client CA list UpdateCAListFromRootStore(innerContext); } context = SafeSslHandle.Create(innerContext, isServer); Debug.Assert(context != null, "Expected non-null return value from SafeSslHandle.Create"); if (context.IsInvalid) { context.Dispose(); throw CreateSslException(SR.net_allocate_ssl_context_failed); } } return context; }
internal unsafe OpenSslX509CertificateReader(byte[] data) { fixed (byte* pDataFixed = data) { byte* pData = pDataFixed; byte** ppData = &pData; _cert = Interop.libcrypto.d2i_X509(IntPtr.Zero, ppData, data.Length); if (_cert.IsInvalid) { throw new CryptographicException(); } // X509_check_purpose has the effect of populating the sha1_hash value, // and other "initialize" type things. bool init = Interop.libcrypto.X509_check_purpose(_cert, -1, 0); if (!init) { throw new CryptographicException(Interop.libcrypto.GetOpenSslErrorString()); } } }
internal static extern ulong X509IssuerNameHash(SafeX509Handle x);
public List<OpenSslX509CertificateReader> ReadCertificates() { var certs = new List<OpenSslX509CertificateReader>(); if (_caStackHandle != null && !_caStackHandle.IsInvalid) { int caCertCount = Interop.Crypto.GetX509StackFieldCount(_caStackHandle); for (int i = 0; i < caCertCount; i++) { IntPtr certPtr = Interop.Crypto.GetX509StackField(_caStackHandle, i); if (certPtr != IntPtr.Zero) { // The STACK_OF(X509) still needs to be cleaned up, so upref the handle out of it. certs.Add(new OpenSslX509CertificateReader(Interop.Crypto.X509UpRef(certPtr))); } } } if (_x509Handle != null && !_x509Handle.IsInvalid) { // The certificate and (if applicable) private key handles will be given over // to the OpenSslX509CertificateReader, and the fields here are thus nulled out to // prevent double-Dispose. OpenSslX509CertificateReader reader = new OpenSslX509CertificateReader(_x509Handle); _x509Handle = null; if (_evpPkeyHandle != null && !_evpPkeyHandle.IsInvalid) { reader.SetPrivateKey(_evpPkeyHandle); _evpPkeyHandle = null; } certs.Add(reader); } return certs; }
internal static extern bool SslAddExtraChainCert(SafeSslHandle ssl, SafeX509Handle x509);
internal static extern SafeX509Handle X509Duplicate(SafeX509Handle handle);
internal static extern SafeEvpPKeyHandle GetX509EvpPublicKey(SafeX509Handle x509);
private int TlsClientCertCallback(IntPtr ssl, out IntPtr certHandle, out IntPtr privateKeyHandle) { Interop.Crypto.CheckValidOpenSslHandle(ssl); using (SafeSslHandle sslHandle = new SafeSslHandle(ssl, false)) { certHandle = IntPtr.Zero; privateKeyHandle = IntPtr.Zero; VerboseTrace("libssl's client certificate callback"); ISet<string> issuerNames = GetRequestCertificateAuthorities(sslHandle); X509Certificate2 certificate; X509Chain chain; if (!GetClientCertificate(issuerNames, out certificate, out chain)) { VerboseTrace("no cert or chain"); return 0; } Interop.Crypto.CheckValidOpenSslHandle(certificate.Handle); using (RSAOpenSsl rsa = certificate.GetRSAPrivateKey() as RSAOpenSsl) { if (rsa != null) { _privateKeyHandle = rsa.DuplicateKeyHandle(); } else { using (ECDsaOpenSsl ecdsa = certificate.GetECDsaPrivateKey() as ECDsaOpenSsl) { if (ecdsa != null) { _privateKeyHandle = ecdsa.DuplicateKeyHandle(); } } } } if (_privateKeyHandle == null || _privateKeyHandle.IsInvalid) { VerboseTrace("invalid private key"); return 0; } _certHandle = Interop.Crypto.X509Duplicate(certificate.Handle); Interop.Crypto.CheckValidOpenSslHandle(_certHandle); if (chain != null) { for (int i = chain.ChainElements.Count - 2; i > 0; i--) { SafeX509Handle dupCertHandle = Interop.Crypto.X509Duplicate(chain.ChainElements[i].Certificate.Handle); Interop.Crypto.CheckValidOpenSslHandle(dupCertHandle); if (!Interop.Ssl.SslAddExtraChainCert(sslHandle, dupCertHandle)) { VerboseTrace("failed to add extra chain cert"); return -1; } } } certHandle = _certHandle.DangerousGetHandle(); privateKeyHandle = _privateKeyHandle.DangerousGetHandle(); return 1; } }
internal static extern bool X509StoreAddCert(SafeX509StoreHandle ctx, SafeX509Handle x);
internal static extern IntPtr X509GetExt(SafeX509Handle x, int loc);
internal static extern int EncodeX509(SafeX509Handle x, byte[] buf);
public SafeFreeCredentials(X509Certificate certificate, SslProtocols protocols, EncryptionPolicy policy) : base(IntPtr.Zero, true) { Debug.Assert( certificate == null || certificate is X509Certificate2, "Only X509Certificate2 certificates are supported at this time"); X509Certificate2 cert = (X509Certificate2)certificate; if (cert != null) { Debug.Assert(cert.HasPrivateKey, "cert.HasPrivateKey"); using (RSAOpenSsl rsa = (RSAOpenSsl)cert.GetRSAPrivateKey()) { if (rsa != null) { _certKeyHandle = rsa.DuplicateKeyHandle(); Interop.libcrypto.CheckValidOpenSslHandle(_certKeyHandle); } } // TODO (3390): Add support for ECDSA. Debug.Assert(_certKeyHandle != null, "Failed to extract a private key handle"); _certHandle = Interop.libcrypto.X509_dup(cert.Handle); Interop.libcrypto.CheckValidOpenSslHandle(_certHandle); } _protocols = protocols; _policy = policy; }
public void Dispose() { if (_privateKey != null) { _privateKey.Dispose(); _privateKey = null; } if (_cert != null) { _cert.Dispose(); _cert = null; } }
internal static extern IntPtr X509GetSubjectName(SafeX509Handle x);
internal static extern IntPtr X509GetIssuerName(SafeX509Handle x);
private static extern SafeSharedAsn1IntegerHandle X509GetSerialNumber_private(SafeX509Handle x);
internal static extern bool X509CheckPurpose(SafeX509Handle x, int id, int ca);
internal static extern int X509GetExtCount(SafeX509Handle x);
private static void SetSslCertificate(SafeSslContextHandle contextPtr, SafeX509Handle certPtr, SafeEvpPKeyHandle keyPtr) { Debug.Assert(certPtr != null && !certPtr.IsInvalid, "certPtr != null && !certPtr.IsInvalid"); Debug.Assert(keyPtr != null && !keyPtr.IsInvalid, "keyPtr != null && !keyPtr.IsInvalid"); int retVal = Ssl.SslCtxUseCertificate(contextPtr, certPtr); if (1 != retVal) { throw CreateSslException(SR.net_ssl_use_cert_failed); } retVal = Ssl.SslCtxUsePrivateKey(contextPtr, keyPtr); if (1 != retVal) { throw CreateSslException(SR.net_ssl_use_private_key_failed); } //check private key retVal = Ssl.SslCtxCheckPrivateKey(contextPtr); if (1 != retVal) { throw CreateSslException(SR.net_ssl_check_private_key_failed); } }
internal static extern int X509CheckIssued(SafeX509Handle issuer, SafeX509Handle subject);