示例#1
0
        public SslConnectionInfo(SafeSslHandle sslContext)
        {
            string protocolVersion = Interop.Ssl.GetProtocolVersion(sslContext);
            Protocol = (int)MapProtocolVersion(protocolVersion);

            int dataCipherAlg;
            int keyExchangeAlg;
            int dataHashAlg;
            int dataKeySize;
            int dataHashKeySize;

            if (!Interop.Ssl.GetSslConnectionInfo(
                sslContext,
                out dataCipherAlg,
                out keyExchangeAlg,
                out dataHashAlg,
                out dataKeySize,
                out dataHashKeySize))
            {
                throw Interop.OpenSsl.CreateSslException(SR.net_ssl_get_connection_info_failed);
            }

            DataCipherAlg = dataCipherAlg;
            KeyExchangeAlg = keyExchangeAlg;
            DataHashAlg = dataHashAlg;
            DataKeySize = dataKeySize;
            DataHashKeySize = dataHashKeySize;

            //Openssl does not provide a way to return a exchange key size.
            //It internally does calculate the key size before generating key to exchange
            //It is not a constant (Algorthim specific) either that we can hardcode and return. 
            KeyExchKeySize = 0;
        }
示例#2
0
 internal static extern bool GetSslConnectionInfo(
     SafeSslHandle ssl,
     out int dataCipherAlg,
     out int keyExchangeAlg,
     out int dataHashAlg,
     out int dataKeySize,
     out int hashKeySize);
示例#3
0
        internal static SafeSharedX509NameStackHandle SSL_get_client_CA_list(SafeSslHandle ssl)
        {
            Interop.Crypto.CheckValidOpenSslHandle(ssl);

            SafeSharedX509NameStackHandle handle = SSL_get_client_CA_list_private(ssl);

            if (!handle.IsInvalid)
            {
                handle.SetParent(ssl);
            }

            return handle;
        }
示例#4
0
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (null != _sslContext)
                {
                    _sslContext.Dispose();
                    _sslContext = null;
                }
            }

            base.Dispose(disposing);
        }
示例#5
0
        internal SslConnectionInfo(SafeSslHandle sslContext)
        {
            string protocolVersion = Interop.Ssl.GetProtocolVersion(sslContext);
            Protocol = (int)MapProtocolVersion(protocolVersion);

            if (!Interop.Ssl.GetSslConnectionInfo(
                sslContext,
                out DataCipherAlg,
                out KeyExchangeAlg,
                out DataHashAlg,
                out DataKeySize))
            {
                throw Interop.OpenSsl.CreateSslException(SR.net_ssl_get_connection_info_failed);
            }
            // TODO (Issue #3362) map key sizes
        }
示例#6
0
        internal static bool DoSslHandshake(SafeSslHandle context, byte[] recvBuf, int recvOffset, int recvCount, out byte[] sendBuf, out int sendCount)
        {
            sendBuf = null;
            sendCount = 0;
            if ((recvBuf != null) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvBuf, recvOffset, recvCount);
            }

            libssl.SslErrorCode error;
            int retVal = libssl.SSL_do_handshake(context);

            if (retVal != 1)
            {
                error = GetSslError(context, retVal);

                if ((retVal != -1) || (error != libssl.SslErrorCode.SSL_ERROR_WANT_READ))
                {
                    throw CreateSslException(context, SR.net_ssl_handshake_failed_error, retVal);
                }
            }

            sendCount = libssl.BIO_ctrl_pending(context.OutputBio);

            if (sendCount > 0)
            {
                sendBuf = new byte[sendCount];

                try
                {
                    sendCount = BioRead(context.OutputBio, sendBuf, sendCount);
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        sendBuf = null;
                        sendCount = 0;
                    }
                }
            }

            return ((libssl.SSL_state(context) == (int)libssl.SslState.SSL_ST_OK));

        }
示例#7
0
        public SafeDeleteSslContext(SafeFreeSslCredentials credential, bool isServer, bool remoteCertRequired)
            : base(credential)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteSslContext");

            try
            {
                _sslContext = Interop.OpenSsl.AllocateSslContext(
                    credential.Protocols,
                    credential.CertHandle,
                    credential.CertKeyHandle,
                    credential.Policy,
                    isServer,
                    remoteCertRequired);
            }
            catch(Exception ex)
            {
                Debug.Write("Exception Caught. - " + ex);
                Dispose();
                throw;
            }
        }
示例#8
0
        internal static SafeChannelBindingHandle QueryChannelBinding(SafeSslHandle context, ChannelBindingKind bindingType)
        {
            SafeChannelBindingHandle bindingHandle;
            switch (bindingType)
            {
                case ChannelBindingKind.Endpoint:
                    bindingHandle = new SafeChannelBindingHandle(bindingType);
                    QueryEndPointChannelBinding(context, bindingHandle);
                    break;

                case ChannelBindingKind.Unique:
                    bindingHandle = new SafeChannelBindingHandle(bindingType);
                    QueryUniqueChannelBinding(context, bindingHandle);
                    break;

                default:
                    // Keeping parity with windows, we should return null in this case.
                    bindingHandle = null;
                    break;
            }

            return bindingHandle;
        }
示例#9
0
        private static void QueryUniqueChannelBinding(SafeSslHandle context, SafeChannelBindingHandle bindingHandle)
        {
            bool sessionReused = Ssl.SslSessionReused(context);
            int certHashLength = context.IsServer ^ sessionReused ?
                                 Ssl.SslGetPeerFinished(context, bindingHandle.CertHashPtr, bindingHandle.Length) :
                                 Ssl.SslGetFinished(context, bindingHandle.CertHashPtr, bindingHandle.Length);

            if (0 == certHashLength)
            {
                throw CreateSslException(SR.net_ssl_get_channel_binding_token_failed);
            }

            bindingHandle.SetCertHashLength(certHashLength);
        }
示例#10
0
 internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle context)
 {
     return Ssl.SslGetPeerCertChain(context);
 }
示例#11
0
        internal static int Encrypt(SafeSslHandle context, byte[] buffer, int offset, int count, out Ssl.SslErrorCode errorCode)
        {
            Debug.Assert(buffer != null);
            Debug.Assert(offset >= 0);
            Debug.Assert(count >= 0);
            Debug.Assert(buffer.Length >= offset + count);

            errorCode = Ssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal;
            unsafe
            {
                fixed (byte* fixedBuffer = buffer)
                {
                    retVal = Ssl.SslWrite(context, fixedBuffer + offset, count);
                }
            }

            if (retVal != count)
            {
                Exception innerError;
                errorCode = GetSslError(context, retVal, out innerError);
                retVal = 0;

                switch (errorCode)
                {
                    // indicate end-of-file
                    case Ssl.SslErrorCode.SSL_ERROR_ZERO_RETURN:
                    case Ssl.SslErrorCode.SSL_ERROR_WANT_READ:
                        break;

                    default:
                        throw new SslException(SR.Format(SR.net_ssl_encrypt_failed, errorCode), innerError);
                }
            }
            else
            {
                int capacityNeeded = Crypto.BioCtrlPending(context.OutputBio);

                Debug.Assert(buffer.Length >= capacityNeeded, "Input buffer of size " + buffer.Length +
                                                              " bytes is insufficient since encryption needs " + capacityNeeded + " bytes.");

                retVal = BioRead(context.OutputBio, buffer, capacityNeeded);
            }

            return retVal;
        }
示例#12
0
 internal static extern bool IsSslStateOK(SafeSslHandle ssl);
示例#13
0
 internal static extern void SslSetBio(SafeSslHandle ssl, SafeBioHandle rbio, SafeBioHandle wbio);
示例#14
0
 internal static extern int SslRead(SafeSslHandle ssl, byte[] buf, int num);
示例#15
0
 internal static extern bool SslAddExtraChainCert(SafeSslHandle ssl, SafeX509Handle x509);
示例#16
0
 internal static unsafe extern int SslWrite(SafeSslHandle ssl, byte* buf, int num);
示例#17
0
 private static extern SafeSharedX509NameStackHandle SslGetClientCAList_private(SafeSslHandle ssl);
示例#18
0
 internal static extern bool IsSslRenegotiatePending(SafeSslHandle ssl);
示例#19
0
        internal static SafeSharedX509NameStackHandle SslGetClientCAList(SafeSslHandle ssl)
        {
            Crypto.CheckValidOpenSslHandle(ssl);

            SafeSharedX509NameStackHandle handle = SslGetClientCAList_private(ssl);

            if (!handle.IsInvalid)
            {
                handle.SetParent(ssl);
            }

            return handle;
        }
示例#20
0
 internal static extern int SslDoHandshake(SafeSslHandle ssl);
示例#21
0
 internal static extern SslErrorCode SslGetError(SafeSslHandle ssl, int ret);
示例#22
0
        internal static bool DoSslHandshake(SafeSslHandle context, byte[] recvBuf, int recvOffset, int recvCount, out byte[] sendBuf, out int sendCount)
        {
            sendBuf = null;
            sendCount = 0;
            if ((recvBuf != null) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvBuf, recvOffset, recvCount);
            }

            int retVal = Ssl.SslDoHandshake(context);

            if (retVal != 1)
            {
                Exception innerError;
                Ssl.SslErrorCode error = GetSslError(context, retVal, out innerError);

                if ((retVal != -1) || (error != Ssl.SslErrorCode.SSL_ERROR_WANT_READ))
                {
                    throw new SslException(SR.Format(SR.net_ssl_handshake_failed_error, error), innerError);
                }
            }

            sendCount = Crypto.BioCtrlPending(context.OutputBio);

            if (sendCount > 0)
            {
                sendBuf = new byte[sendCount];

                try
                {
                    sendCount = BioRead(context.OutputBio, sendBuf, sendCount);
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        sendBuf = null;
                        sendCount = 0;
                    }
                }
            }

            bool stateOk = Ssl.IsSslStateOK(context);
            if (stateOk)
            {
                context.MarkHandshakeCompleted();
            }
            return stateOk;
        }
示例#23
0
 internal static extern void SslSetConnectState(SafeSslHandle ssl);
示例#24
0
        internal static int Decrypt(SafeSslHandle context, byte[] outBuffer, int count, out Ssl.SslErrorCode errorCode)
        {
            errorCode = Ssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal = BioWrite(context.InputBio, outBuffer, 0, count);

            if (retVal == count)
            {
                retVal = Ssl.SslRead(context, outBuffer, outBuffer.Length);

                if (retVal > 0)
                {
                    count = retVal;
                }
            }

            if (retVal != count)
            {
                Exception innerError;
                errorCode = GetSslError(context, retVal, out innerError);
                retVal = 0;

                switch (errorCode)
                {
                    // indicate end-of-file
                    case Ssl.SslErrorCode.SSL_ERROR_ZERO_RETURN:
                        break;

                    case Ssl.SslErrorCode.SSL_ERROR_WANT_READ:
                        // update error code to renegotiate if renegotiate is pending, otherwise make it SSL_ERROR_WANT_READ
                        errorCode = Ssl.IsSslRenegotiatePending(context) ?
                                    Ssl.SslErrorCode.SSL_ERROR_RENEGOTIATE :
                                    Ssl.SslErrorCode.SSL_ERROR_WANT_READ;
                        break;

                    default:
                        throw new SslException(SR.Format(SR.net_ssl_decrypt_failed, errorCode), innerError);
                }
            }

            return retVal;
        }
示例#25
0
 internal static extern void SslSetAcceptState(SafeSslHandle ssl);
示例#26
0
 internal static SafeX509Handle GetPeerCertificate(SafeSslHandle context)
 {
     return Ssl.SslGetPeerCertificate(context);
 }
示例#27
0
 private static extern IntPtr SslGetVersion(SafeSslHandle ssl);
示例#28
0
        private static void QueryEndPointChannelBinding(SafeSslHandle context, SafeChannelBindingHandle bindingHandle)
        {
            using (SafeX509Handle certSafeHandle = GetPeerCertificate(context))
            {
                if (certSafeHandle == null || certSafeHandle.IsInvalid)
                {
                    throw CreateSslException(SR.net_ssl_invalid_certificate);
                }

                bool gotReference = false;

                try
                {
                    certSafeHandle.DangerousAddRef(ref gotReference);
                    using (X509Certificate2 cert = new X509Certificate2(certSafeHandle.DangerousGetHandle()))
                    using (HashAlgorithm hashAlgo = GetHashForChannelBinding(cert))
                    {
                        byte[] bindingHash = hashAlgo.ComputeHash(cert.RawData);
                        bindingHandle.SetCertHash(bindingHash);
                    }
                }
                finally
                {
                    if (gotReference)
                    {
                        certSafeHandle.DangerousRelease();
                    }
                }
            }
        }
示例#29
0
 internal static string GetProtocolVersion(SafeSslHandle ssl)
 {
     return Marshal.PtrToStringAnsi(SslGetVersion(ssl));
 }
示例#30
0
        private static Ssl.SslErrorCode GetSslError(SafeSslHandle context, int result, out Exception innerError)
        {
            ErrorInfo lastErrno = Sys.GetLastErrorInfo(); // cache it before we make more P/Invoke calls, just in case we need it

            Ssl.SslErrorCode retVal = Ssl.SslGetError(context, result);
            switch (retVal)
            {
                case Ssl.SslErrorCode.SSL_ERROR_SYSCALL:
                    // Some I/O error occurred
                    innerError =
                        Crypto.ErrPeekError() != 0 ? Crypto.CreateOpenSslCryptographicException() : // crypto error queue not empty
                        result == 0 ? new EndOfStreamException() : // end of file that violates protocol
                        result == -1 && lastErrno.Error != Error.SUCCESS ? new IOException(lastErrno.GetErrorMessage(), lastErrno.RawErrno) : // underlying I/O error
                        null; // no additional info available
                    break;

                case Ssl.SslErrorCode.SSL_ERROR_SSL:
                    // OpenSSL failure occurred.  The error queue contains more details.
                    innerError = Interop.Crypto.CreateOpenSslCryptographicException();
                    break;

                default:
                    // No additional info available.
                    innerError = null;
                    break;
            }
            return retVal;
        }
示例#31
0
        public static SafeSslHandle Create(SafeSslContextHandle context, bool isServer)
        {
            SafeBioHandle readBio = Interop.Crypto.CreateMemoryBio();

            if (readBio.IsInvalid)
            {
                return(new SafeSslHandle());
            }

            SafeBioHandle writeBio = Interop.Crypto.CreateMemoryBio();

            if (writeBio.IsInvalid)
            {
                readBio.Dispose();
                return(new SafeSslHandle());
            }

            SafeSslHandle handle = Interop.Ssl.SslCreate(context);

            if (handle.IsInvalid)
            {
                readBio.Dispose();
                writeBio.Dispose();
                return(handle);
            }
            handle._isServer = isServer;

            // After SSL_set_bio, the BIO handles are owned by SSL pointer
            // and are automatically freed by SSL_free. To prevent a double
            // free, we need to keep the ref counts bumped up till SSL_free
            bool gotRef = false;

            readBio.DangerousAddRef(ref gotRef);
            try
            {
                bool ignore = false;
                writeBio.DangerousAddRef(ref ignore);
            }
            catch
            {
                if (gotRef)
                {
                    readBio.DangerousRelease();
                }
                throw;
            }

            Interop.Ssl.SslSetBio(handle, readBio, writeBio);
            handle._readBio  = readBio;
            handle._writeBio = writeBio;

            if (isServer)
            {
                Interop.Ssl.SslSetAcceptState(handle);
            }
            else
            {
                Interop.Ssl.SslSetConnectState(handle);
            }
            return(handle);
        }