예제 #1
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))
            {
                if (BioWrite(context.InputBio, recvBuf, recvOffset, recvCount) <= 0)
                {
                    // Make sure we clear out the error that is stored in the queue
                    throw Crypto.CreateOpenSslCryptographicException();
                }
            }

            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)
                    {
                        // Make sure we clear out the error that is stored in the queue
                        Crypto.ErrGetError();
                        sendBuf   = null;
                        sendCount = 0;
                    }
                }
            }

            bool stateOk = Ssl.IsSslStateOK(context);

            if (stateOk)
            {
                context.MarkHandshakeCompleted();
            }
            return(stateOk);
        }
예제 #2
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);
            }

            Ssl.SslErrorCode error;
            int retVal = Ssl.SslDoHandshake(context);

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

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

            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);
        }
예제 #3
0
        internal static bool DoSslHandshake(SafeSslHandle context, ReadOnlySpan <byte> input, out byte[]?sendBuf, out int sendCount)
        {
            sendBuf   = null;
            sendCount = 0;
            Exception?handshakeException = null;

            if (input.Length > 0)
            {
                if (Ssl.BioWrite(context.InputBio !, ref MemoryMarshal.GetReference(input), input.Length) != input.Length)
                {
                    // Make sure we clear out the error that is stored in the queue
                    throw Crypto.CreateOpenSslCryptographicException();
                }
            }

            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))
                {
                    // Handshake failed, but even if the handshake does not need to read, there may be an Alert going out.
                    // To handle that we will fall-through the block below to pull it out, and we will fail after.
                    handshakeException = new SslException(SR.Format(SR.net_ssl_handshake_failed_error, error), innerError);
                    Crypto.ErrClearError();
                }
            }

            sendCount = Crypto.BioCtrlPending(context.OutputBio !);
            if (sendCount > 0)
            {
                sendBuf = new byte[sendCount];

                try
                {
                    sendCount = BioRead(context.OutputBio !, sendBuf, sendCount);
                }
                catch (Exception) when(handshakeException != null)
                {
                    // If we already have handshake exception, ignore any exception from BioRead().
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        // Make sure we clear out the error that is stored in the queue
                        Crypto.ErrClearError();
                        sendBuf   = null;
                        sendCount = 0;
                    }
                }
            }

            if (handshakeException != null)
            {
                throw handshakeException;
            }

            bool stateOk = Ssl.IsSslStateOK(context);

            if (stateOk)
            {
                context.MarkHandshakeCompleted();
            }
            return(stateOk);
        }