Пример #1
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions)
            : base(credential)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                unsafe
                {
                    _readCallback  = ReadFromConnection;
                    _writeCallback = WriteToConnection;
                }

                _sslContext = CreateSslContext(credential, sslAuthenticationOptions.IsServer);

                int osStatus = Interop.AppleCrypto.SslSetIoCallbacks(
                    _sslContext,
                    _readCallback,
                    _writeCallback);

                if (osStatus != 0)
                {
                    throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
Пример #2
0
        private static SafeSslHandle CreateSslContext(SafeFreeSslCredentials credential)
        {
            if (credential.CertificateContext == null)
            {
                return(Interop.AndroidCrypto.SSLStreamCreate());
            }

            SslStreamCertificateContext context = credential.CertificateContext;
            X509Certificate2            cert    = context.Certificate;

            Debug.Assert(context.Certificate.HasPrivateKey);

            PAL_KeyAlgorithm algorithm;

            byte[] keyBytes;
            using (AsymmetricAlgorithm key = GetPrivateKeyAlgorithm(cert, out algorithm))
            {
                keyBytes = key.ExportPkcs8PrivateKey();
            }
            IntPtr[] ptrs = new IntPtr[context.IntermediateCertificates.Length + 1];
            ptrs[0] = cert.Handle;
            for (int i = 0; i < context.IntermediateCertificates.Length; i++)
            {
                ptrs[i + 1] = context.IntermediateCertificates[i].Handle;
            }

            return(Interop.AndroidCrypto.SSLStreamCreateWithCertificates(keyBytes, algorithm, ptrs));
        }
Пример #3
0
        private static void InitializeSslContext(
            SafeSslHandle handle,
            Interop.AndroidCrypto.SSLReadCallback readCallback,
            Interop.AndroidCrypto.SSLWriteCallback writeCallback,
            SafeFreeSslCredentials credential,
            SslAuthenticationOptions authOptions)
        {
            bool isServer = authOptions.IsServer;

            if (authOptions.ApplicationProtocols != null ||
                authOptions.CipherSuitesPolicy != null ||
                credential.Protocols != SslProtocols.None ||
                (isServer && authOptions.RemoteCertRequired))
            {
                // TODO: [AndroidCrypto] Handle non-system-default options
                throw new NotImplementedException(nameof(SafeDeleteSslContext));
            }

            Interop.AndroidCrypto.SSLStreamInitialize(handle, isServer, readCallback, writeCallback, InitialBufferSize);

            if (!isServer && !string.IsNullOrEmpty(authOptions.TargetHost))
            {
                Interop.AndroidCrypto.SSLStreamConfigureParameters(handle, authOptions.TargetHost);
            }
        }
Пример #4
0
        private unsafe void InitializeSslContext(
            SafeSslHandle handle,
            SafeFreeSslCredentials credential,
            SslAuthenticationOptions authOptions)
        {
            switch (credential.Policy)
            {
            case EncryptionPolicy.RequireEncryption:
#pragma warning disable SYSLIB0040 // NoEncryption and AllowNoEncryption are obsolete
            case EncryptionPolicy.AllowNoEncryption:
                break;

#pragma warning restore SYSLIB0040
            default:
                throw new PlatformNotSupportedException(SR.Format(SR.net_encryptionpolicy_notsupported, credential.Policy));
            }

            bool isServer = authOptions.IsServer;

            if (authOptions.CipherSuitesPolicy != null)
            {
                // TODO: [AndroidCrypto] Handle non-system-default options
                throw new NotImplementedException(nameof(SafeDeleteSslContext));
            }

            // Make sure the class instance is associated to the session and is provided
            // in the Read/Write callback connection parameter
            IntPtr managedContextHandle = GCHandle.ToIntPtr(GCHandle.Alloc(this, GCHandleType.Weak));
            Interop.AndroidCrypto.SSLStreamInitialize(handle, isServer, managedContextHandle, &ReadFromConnection, &WriteToConnection, InitialBufferSize);

            if (credential.Protocols != SslProtocols.None)
            {
                SslProtocols protocolsToEnable = credential.Protocols & s_supportedSslProtocols.Value;
                if (protocolsToEnable == 0)
                {
                    throw new PlatformNotSupportedException(SR.Format(SR.net_security_sslprotocol_notsupported, credential.Protocols));
                }

                (int minIndex, int maxIndex) = protocolsToEnable.ValidateContiguous(s_orderedSslProtocols);
                Interop.AndroidCrypto.SSLStreamSetEnabledProtocols(handle, s_orderedSslProtocols.AsSpan(minIndex, maxIndex - minIndex + 1));
            }

            if (authOptions.ApplicationProtocols != null && authOptions.ApplicationProtocols.Count != 0 &&
                Interop.AndroidCrypto.SSLSupportsApplicationProtocolsConfiguration())
            {
                // Set application protocols if the platform supports it. Otherwise, we will silently ignore the option.
                Interop.AndroidCrypto.SSLStreamSetApplicationProtocols(handle, authOptions.ApplicationProtocols);
            }

            if (isServer && authOptions.RemoteCertRequired)
            {
                Interop.AndroidCrypto.SSLStreamRequestClientAuthentication(handle);
            }

            if (!isServer && !string.IsNullOrEmpty(authOptions.TargetHost))
            {
                Interop.AndroidCrypto.SSLStreamSetTargetHost(handle, authOptions.TargetHost);
            }
        }
Пример #5
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions authOptions)
            : base(credential)
        {
            Debug.Assert((credential != null) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            _sslContext = new SafeSslHandle();
            throw new NotImplementedException(nameof(SafeDeleteSslContext));
        }
Пример #6
0
        private static void InitializeSslContext(
            SafeSslHandle handle,
            Interop.AndroidCrypto.SSLReadCallback readCallback,
            Interop.AndroidCrypto.SSLWriteCallback writeCallback,
            SafeFreeSslCredentials credential,
            SslAuthenticationOptions authOptions)
        {
            switch (credential.Policy)
            {
            case EncryptionPolicy.RequireEncryption:
            case EncryptionPolicy.AllowNoEncryption:
                break;

            default:
                throw new PlatformNotSupportedException(SR.Format(SR.net_encryptionpolicy_notsupported, credential.Policy));
            }

            bool isServer = authOptions.IsServer;

            if (authOptions.CipherSuitesPolicy != null)
            {
                // TODO: [AndroidCrypto] Handle non-system-default options
                throw new NotImplementedException(nameof(SafeDeleteSslContext));
            }

            Interop.AndroidCrypto.SSLStreamInitialize(handle, isServer, readCallback, writeCallback, InitialBufferSize);

            if (credential.Protocols != SslProtocols.None)
            {
                ;
                SslProtocols protocolsToEnable = credential.Protocols & s_supportedSslProtocols.Value;
                if (protocolsToEnable == 0)
                {
                    throw new PlatformNotSupportedException(SR.Format(SR.net_security_sslprotocol_notsupported, credential.Protocols));
                }

                (int minIndex, int maxIndex) = protocolsToEnable.ValidateContiguous(s_orderedSslProtocols);
                Interop.AndroidCrypto.SSLStreamSetEnabledProtocols(handle, s_orderedSslProtocols.AsSpan(minIndex, maxIndex - minIndex + 1));
            }

            if (authOptions.ApplicationProtocols != null && authOptions.ApplicationProtocols.Count != 0 &&
                Interop.AndroidCrypto.SSLSupportsApplicationProtocolsConfiguration())
            {
                // Set application protocols if the platform supports it. Otherwise, we will silently ignore the option.
                Interop.AndroidCrypto.SSLStreamSetApplicationProtocols(handle, authOptions.ApplicationProtocols);
            }

            if (isServer && authOptions.RemoteCertRequired)
            {
                Interop.AndroidCrypto.SSLStreamRequestClientAuthentication(handle);
            }

            if (!isServer && !string.IsNullOrEmpty(authOptions.TargetHost))
            {
                Interop.AndroidCrypto.SSLStreamSetTargetHost(handle, authOptions.TargetHost);
            }
        }
Пример #7
0
        private static SafeSslHandle CreateSslContext(SafeFreeSslCredentials credential, bool isServer)
        {
            switch (credential.Policy)
            {
            case EncryptionPolicy.RequireEncryption:
#pragma warning disable SYSLIB0040 // NoEncryption and AllowNoEncryption are obsolete
            case EncryptionPolicy.AllowNoEncryption:
                // SecureTransport doesn't allow TLS_NULL_NULL_WITH_NULL, but
                // since AllowNoEncryption intersect OS-supported isn't nothing,
                // let it pass.
                break;

#pragma warning restore SYSLIB0040
            default:
                throw new PlatformNotSupportedException(SR.Format(SR.net_encryptionpolicy_notsupported, credential.Policy));
            }

            SafeSslHandle sslContext = Interop.AppleCrypto.SslCreateContext(isServer ? 1 : 0);

            try
            {
                if (sslContext.IsInvalid)
                {
                    // This is as likely as anything.  No error conditions are defined for
                    // the OS function, and our shim only adds a NULL if isServer isn't a normalized bool.
                    throw new OutOfMemoryException();
                }

                // Let None mean "system default"
                if (credential.Protocols != SslProtocols.None)
                {
                    SetProtocols(sslContext, credential.Protocols);
                }

                if (credential.CertificateContext != null)
                {
                    SetCertificate(sslContext, credential.CertificateContext);
                }

                Interop.AppleCrypto.SslBreakOnCertRequested(sslContext, true);
                Interop.AppleCrypto.SslBreakOnServerAuth(sslContext, true);
                Interop.AppleCrypto.SslBreakOnClientAuth(sslContext, true);
            }
            catch
            {
                sslContext.Dispose();
                throw;
            }

            return(sslContext);
        }
Пример #8
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions authOptions)
            : base(credential)
        {
            Debug.Assert((credential != null) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                _sslContext = CreateSslContext(credential);
                InitializeSslContext(_sslContext, credential, authOptions);
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
Пример #9
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions)
            : base(credential)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                unsafe
                {
                    _readCallback  = ReadFromConnection;
                    _writeCallback = WriteToConnection;
                }

                _sslContext = CreateSslContext(credential, sslAuthenticationOptions.IsServer);

                int osStatus = Interop.AppleCrypto.SslSetIoCallbacks(
                    _sslContext,
                    _readCallback,
                    _writeCallback);

                if (osStatus != 0)
                {
                    throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                }

                if (sslAuthenticationOptions.ApplicationProtocols != null)
                {
                    // On OSX coretls supports only client side. For server, we will silently ignore the option.
                    if (!sslAuthenticationOptions.IsServer)
                    {
                        Interop.AppleCrypto.SslCtxSetAlpnProtos(_sslContext, sslAuthenticationOptions.ApplicationProtocols);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
Пример #10
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions authOptions)
            : base(credential)
        {
            Debug.Assert((credential != null) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                unsafe
                {
                    _readCallback  = ReadFromConnection;
                    _writeCallback = WriteToConnection;
                }

                _sslContext = CreateSslContext(credential);
                InitializeSslContext(_sslContext, _readCallback, _writeCallback, credential, authOptions);
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
Пример #11
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions)
            : base(credential)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                int osStatus;

                _sslContext = CreateSslContext(credential, sslAuthenticationOptions.IsServer);

                // Make sure the class instance is associated to the session and is provided
                // in the Read/Write callback connection parameter
                SslSetConnection(_sslContext);

                unsafe
                {
                    osStatus = Interop.AppleCrypto.SslSetIoCallbacks(
                        _sslContext,
                        &ReadFromConnection,
                        &WriteToConnection);
                }

                if (osStatus != 0)
                {
                    throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                }

                if (sslAuthenticationOptions.CipherSuitesPolicy != null)
                {
                    uint[] tlsCipherSuites = sslAuthenticationOptions.CipherSuitesPolicy.Pal.TlsCipherSuites;

                    unsafe
                    {
                        fixed(uint *cipherSuites = tlsCipherSuites)
                        {
                            osStatus = Interop.AppleCrypto.SslSetEnabledCipherSuites(
                                _sslContext,
                                cipherSuites,
                                tlsCipherSuites.Length);

                            if (osStatus != 0)
                            {
                                throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                            }
                        }
                    }
                }

                if (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)
                {
                    // On OSX coretls supports only client side. For server, we will silently ignore the option.
                    if (!sslAuthenticationOptions.IsServer)
                    {
                        Interop.AppleCrypto.SslCtxSetAlpnProtos(_sslContext, sslAuthenticationOptions.ApplicationProtocols);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
Пример #12
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, SslAuthenticationOptions sslAuthenticationOptions)
            : base(credential)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                int osStatus;

                _sslContext = CreateSslContext(credential, sslAuthenticationOptions.IsServer);

                // Make sure the class instance is associated to the session and is provided
                // in the Read/Write callback connection parameter
                SslSetConnection(_sslContext);

                unsafe
                {
                    osStatus = Interop.AppleCrypto.SslSetIoCallbacks(
                        _sslContext,
                        &ReadFromConnection,
                        &WriteToConnection);
                }

                if (osStatus != 0)
                {
                    throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                }

                if (sslAuthenticationOptions.CipherSuitesPolicy != null)
                {
                    uint[] tlsCipherSuites = sslAuthenticationOptions.CipherSuitesPolicy.Pal.TlsCipherSuites;

                    unsafe
                    {
                        fixed(uint *cipherSuites = tlsCipherSuites)
                        {
                            osStatus = Interop.AppleCrypto.SslSetEnabledCipherSuites(
                                _sslContext,
                                cipherSuites,
                                tlsCipherSuites.Length);

                            if (osStatus != 0)
                            {
                                throw Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus);
                            }
                        }
                    }
                }

                if (sslAuthenticationOptions.ApplicationProtocols != null && sslAuthenticationOptions.ApplicationProtocols.Count != 0)
                {
                    // On OSX coretls supports only client side. For server, we will silently ignore the option.
                    if (!sslAuthenticationOptions.IsServer)
                    {
                        Interop.AppleCrypto.SslCtxSetAlpnProtos(_sslContext, sslAuthenticationOptions.ApplicationProtocols);
                    }
                }
            }
            catch (Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }

            if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost) && !sslAuthenticationOptions.IsServer)
            {
                Interop.AppleCrypto.SslSetTargetName(_sslContext, sslAuthenticationOptions.TargetHost);
            }

            if (sslAuthenticationOptions.CertificateContext == null && sslAuthenticationOptions.CertSelectionDelegate != null)
            {
                // certificate was not provided but there is user callback. We can break handshake if server asks for certificate
                // and we can try to get it based on remote certificate and trusted issuers.
                Interop.AppleCrypto.SslBreakOnCertRequested(_sslContext, true);
            }

            if (sslAuthenticationOptions.IsServer)
            {
                if (sslAuthenticationOptions.RemoteCertRequired)
                {
                    Interop.AppleCrypto.SslSetAcceptClientCert(_sslContext);
                }

                if (sslAuthenticationOptions.CertificateContext?.Trust?._sendTrustInHandshake == true)
                {
                    SslCertificateTrust        trust    = sslAuthenticationOptions.CertificateContext !.Trust !;
                    X509Certificate2Collection certList = (trust._trustList ?? trust._store !.Certificates);

                    Debug.Assert(certList != null, "certList != null");
                    Span <IntPtr> handles = certList.Count <= 256
                        ? stackalloc IntPtr[256]
                        : new IntPtr[certList.Count];

                    for (int i = 0; i < certList.Count; i++)
                    {
                        handles[i] = certList[i].Handle;
                    }

                    Interop.AppleCrypto.SslSetCertificateAuthorities(_sslContext, handles.Slice(0, certList.Count), true);
                }
            }
        }