예제 #1
0
        public SafeDeleteContext(SafeFreeCredentials credential, long options, bool isServer, bool remoteCertRequired)
            : base(IntPtr.Zero, true)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteContext");

            // When a credential handle is first associated with the context we keep credential
            // ref count bumped up to ensure ordered finalization. The certificate handle and
            // key handle are used in the SSL data structures and should survive the lifetime of
            // the SSL context
            bool ignore = false;

            _credential = credential;
            _credential.DangerousAddRef(ref ignore);

            try
            {
                _sslContext = Interop.OpenSsl.AllocateSslContext(
                    options,
                    credential.CertHandle,
                    credential.CertKeyHandle,
                    isServer,
                    remoteCertRequired);
            }
            finally
            {
                if (IsInvalid)
                {
                    _credential.DangerousRelease();
                }
            }
        }
예제 #2
0
        internal static int Encrypt(SafeSslHandle context, IntPtr buffer, int offset, int count, int bufferCapacity, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal = libssl.SSL_write(context, new IntPtr(buffer.ToInt64() + offset), count);

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

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

                default:
                    throw CreateSslException(SR.net_ssl_encrypt_failed, errorCode);
                }
            }
            else
            {
                int capacityNeeded = libssl.BIO_ctrl_pending(context.OutputBio);

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

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

            return(retVal);
        }
예제 #3
0
        //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("Failed to allocate SSL/TLS context");
                }

                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("Failed to create SSL object from SSL context");
                }
            }

            return(context);
        }
예제 #4
0
 private static libssl.SslErrorCode GetSslError(SafeSslHandle context, int result)
 {
     libssl.SslErrorCode retVal = libssl.SSL_get_error(context, result);
     if (retVal == libssl.SslErrorCode.SSL_ERROR_SYSCALL)
     {
         retVal = (libssl.SslErrorCode)libssl.ERR_get_error();
     }
     return(retVal);
 }
예제 #5
0
        private static void Disconnect(SafeSslHandle context)
        {
            int retVal = libssl.SSL_shutdown(context);

            if (retVal < 0)
            {
                //TODO (Issue #3362) check this error
                libssl.SSL_get_error(context, retVal);
            }
        }
예제 #6
0
        internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle context)
        {
            IntPtr cipherPtr = libssl.SSL_get_current_cipher(context);
            var    cipher    = new libssl.SSL_CIPHER();

            if (IntPtr.Zero != cipherPtr)
            {
                cipher = Marshal.PtrToStructure <libssl.SSL_CIPHER>(cipherPtr);
            }

            return(cipher);
        }
예제 #7
0
        internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle sslHandle, out string protocolVersion)
        {
            IntPtr cipherPtr = libssl.SSL_get_current_cipher(sslHandle);
            var    cipher    = new libssl.SSL_CIPHER();

            if (IntPtr.Zero != cipherPtr)
            {
                cipher = Marshal.PtrToStructure <libssl.SSL_CIPHER>(cipherPtr);
            }

            IntPtr versionPtr = libssl.SSL_get_version(sslHandle);

            protocolVersion = Marshal.PtrToStringAnsi(versionPtr);
            return(cipher);
        }
예제 #8
0
        internal static bool DoSslHandshake(SafeSslHandle context, IntPtr recvPtr, int recvCount, out IntPtr sendPtr, out int sendCount)
        {
            sendPtr   = IntPtr.Zero;
            sendCount = 0;
            if ((IntPtr.Zero != recvPtr) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvPtr, recvCount);
            }

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

            if (retVal == 1)
            {
                // In case of a client, this indicates successful handshake completion
                if (!context.IsServer)
                {
                    return(true);
                }
            }
            else
            {
                error = GetSslError(context, retVal);

                if ((retVal != -1) || (error != libssl.SslErrorCode.SSL_ERROR_WANT_READ))
                {
                    throw CreateSslException(context, "SSL Handshake failed: ", retVal);
                }
            }

            sendCount = libssl.BIO_ctrl_pending(context.OutputBio);

            if (sendCount > 0)
            {
                sendPtr   = Marshal.AllocHGlobal(sendCount);
                sendCount = BioRead(context.OutputBio, sendPtr, sendCount);
                if (sendCount <= 0)
                {
                    int errorCode = sendCount;
                    Marshal.FreeHGlobal(sendPtr);
                    sendPtr   = IntPtr.Zero;
                    sendCount = 0;
                    throw CreateSslException(context, "Read Bio failed: ", errorCode);
                }
            }

            return((libssl.SSL_state(context) == (int)libssl.SslState.SSL_ST_OK));
        }
예제 #9
0
        internal static bool DoSslHandshake(SafeSslHandle context, IntPtr recvPtr, int recvCount, out IntPtr sendPtr, out int sendCount)
        {
            sendPtr = IntPtr.Zero;
            sendCount = 0;
            if ((IntPtr.Zero != recvPtr) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvPtr, recvCount);
            }

            libssl.SslErrorCode error;
            int retVal = libssl.SSL_do_handshake(context);
            if (retVal == 1)
            {
                // In case of a client, this indicates successful handshake completion
                if (!context.IsServer)
                {
                    return true;
                }
            }
            else
            {
                error = GetSslError(context, retVal);

                if ((retVal != -1) || (error != libssl.SslErrorCode.SSL_ERROR_WANT_READ))
                {
                    throw CreateSslException(context, "SSL Handshake failed: ", retVal);
                }
            }

            sendCount = libssl.BIO_ctrl_pending(context.OutputBio);

            if (sendCount > 0)
            {
                sendPtr = Marshal.AllocHGlobal(sendCount);
                sendCount = BioRead(context.OutputBio, sendPtr, sendCount);
                if (sendCount <= 0)
                {
                    int errorCode = sendCount;
                    Marshal.FreeHGlobal(sendPtr);
                    sendPtr = IntPtr.Zero;
                    sendCount = 0;                  
                    throw CreateSslException(context, "Read Bio failed: ", errorCode);                   
                }
            }
        
            return ((libssl.SSL_state(context) == (int)libssl.SslState.SSL_ST_OK));

        }
예제 #10
0
        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 = Crypto.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);
        }
예제 #11
0
        internal static bool DoSslHandshake(SafeSslHandle context, IntPtr recvPtr, int recvCount, out IntPtr sendPtr, out int sendCount)
        {
            sendPtr = IntPtr.Zero;
            sendCount = 0;
            if ((IntPtr.Zero != recvPtr) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvPtr, 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)
            {
                sendPtr = Marshal.AllocHGlobal(sendCount);

                try
                {
                    sendCount = BioRead(context.OutputBio, sendPtr, sendCount);
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        Marshal.FreeHGlobal(sendPtr);
                        sendPtr = IntPtr.Zero;
                        sendCount = 0;
                    }
                }
            }
        
            return ((libssl.SSL_state(context) == (int)libssl.SslState.SSL_ST_OK));

        }
예제 #12
0
        internal static bool DoSslHandshake(SafeSslHandle context, IntPtr recvPtr, int recvCount, out IntPtr sendPtr, out int sendCount)
        {
            sendPtr   = IntPtr.Zero;
            sendCount = 0;
            if ((IntPtr.Zero != recvPtr) && (recvCount > 0))
            {
                BioWrite(context.InputBio, recvPtr, 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)
            {
                sendPtr = Marshal.AllocHGlobal(sendCount);

                try
                {
                    sendCount = BioRead(context.OutputBio, sendPtr, sendCount);
                }
                finally
                {
                    if (sendCount <= 0)
                    {
                        Marshal.FreeHGlobal(sendPtr);
                        sendPtr   = IntPtr.Zero;
                        sendCount = 0;
                    }
                }
            }

            return((libssl.SSL_state(context) == (int)libssl.SslState.SSL_ST_OK));
        }
예제 #13
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));

        }
예제 #14
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));
        }
예제 #15
0
        private SecurityStatus EncryptDecryptHelper(SafeDeleteContext securityContext, byte[] buffer, int offset, int size, int headerSize, int trailerSize, bool encrypt, out int resultSize)
        {
            resultSize = 0;
            try
            {
                Interop.libssl.SslErrorCode errorCode = Interop.libssl.SslErrorCode.SSL_ERROR_NONE;

                unsafe
                {
                    fixed(byte *bufferPtr = buffer)
                    {
                        IntPtr inputPtr = new IntPtr(bufferPtr);

                        Interop.libssl.SafeSslHandle scHandle = securityContext.SslContext;

                        resultSize = encrypt ?
                                     Interop.OpenSsl.Encrypt(scHandle, inputPtr, offset, size, buffer.Length, out errorCode) :
                                     Interop.OpenSsl.Decrypt(scHandle, inputPtr, size, out errorCode);
                    }
                }

                switch (errorCode)
                {
                case Interop.libssl.SslErrorCode.SSL_ERROR_RENEGOTIATE:
                    return(SecurityStatus.Renegotiate);

                case Interop.libssl.SslErrorCode.SSL_ERROR_ZERO_RETURN:
                    return(SecurityStatus.ContextExpired);

                case Interop.libssl.SslErrorCode.SSL_ERROR_NONE:
                case Interop.libssl.SslErrorCode.SSL_ERROR_WANT_READ:
                    return(SecurityStatus.OK);

                default:
                    return(SecurityStatus.InternalError);
                }
            }
            catch (Exception ex)
            {
                Debug.Fail("Exception Caught. - " + ex);
                return(SecurityStatus.InternalError);
            }
        }
예제 #16
0
        internal static int Encrypt(SafeSslHandle context, IntPtr buffer, int offset, int count, int bufferCapacity, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal = libssl.SSL_write(context, new IntPtr(buffer.ToInt64() + offset), count);

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

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

                default:
                    throw CreateSslException("OpenSsl::Encrypt failed");
                }
            }
            else
            {
                int capacityNeeded = libssl.BIO_ctrl_pending(context.OutputBio);

                if (capacityNeeded > bufferCapacity)
                {
                    throw CreateSslException("OpenSsl::Encrypt capacity needed is more than buffer capacity. capacityNeeded = " + capacityNeeded + "," + "bufferCapacity = " + bufferCapacity);
                }

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

                if (retVal < 0)
                {
                    throw CreateSslException("OpenSsl::Encrypt failed");
                }
            }

            return(retVal);
        }
예제 #17
0
        internal static int Decrypt(SafeSslHandle context, byte[] outBuffer, int count, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

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

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

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

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

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

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

                default:
                    throw CreateSslException(SR.net_ssl_decrypt_failed, errorCode);
                }
            }

            return(retVal);
        }
예제 #18
0
 internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle context)
 {
     return libssl.SSL_get_peer_cert_chain(context);
 }
예제 #19
0
 internal static void FreeSslContext(SafeSslHandle context)
 {
     Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext");
     Disconnect(context);
     context.Dispose();
 }
예제 #20
0
        internal static int Encrypt(SafeSslHandle context, IntPtr buffer, int offset, int count, int bufferCapacity, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal = libssl.SSL_write(context, new IntPtr(buffer.ToInt64() + offset), count);
            if (retVal != count)
            {
                errorCode = GetSslError(context, retVal);
                retVal = 0;

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

                    default:
                        throw CreateSslException(SR.net_ssl_encrypt_failed, errorCode);
                }
            }
            else
            {
                int capacityNeeded = libssl.BIO_ctrl_pending(context.OutputBio);

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

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

            return retVal;
        }
예제 #21
0
        internal static int Encrypt(SafeSslHandle context, byte[] buffer, int offset, int count, out libssl.SslErrorCode errorCode)
        {
            Debug.Assert(buffer != null);
            Debug.Assert(offset >= 0);
            Debug.Assert(count >= 0);
            Debug.Assert(buffer.Length >= offset + count);

            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

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

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

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

                    default:
                        throw CreateSslException(SR.net_ssl_encrypt_failed, errorCode);
                }
            }
            else
            {
                int capacityNeeded = libssl.BIO_ctrl_pending(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;
        }
예제 #22
0
 internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle context)
 {
     return(libssl.SSL_get_peer_cert_chain(context));
 }
예제 #23
0
 internal static SafeX509Handle GetPeerCertificate(SafeSslHandle context)
 {
     return(libssl.SSL_get_peer_certificate(context));
 }
예제 #24
0
        internal static int Decrypt(SafeSslHandle context, byte[] outBuffer, int count, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

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

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

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

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

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

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

                    default:
                        throw CreateSslException(SR.net_ssl_decrypt_failed, errorCode);
                }
            }

            return retVal;
        }
예제 #25
0
 private static SslException CreateSslException(SafeSslHandle context, string message, int error)
 {
     return CreateSslException(message, libssl.SSL_get_error(context, error));
 }
예제 #26
0
 private static libssl.SslErrorCode GetSslError(SafeSslHandle context, int result)
 {
     libssl.SslErrorCode retVal = libssl.SSL_get_error(context, result);
     if (retVal == libssl.SslErrorCode.SSL_ERROR_SYSCALL)
     {
         retVal = (libssl.SslErrorCode)libssl.ERR_get_error();
     }
     return retVal;
 }
예제 #27
0
 private static void Disconnect(SafeSslHandle context)
 {
     int retVal = libssl.SSL_shutdown(context);
     if (retVal < 0)
     {
         //TODO (Issue #3362) check this error
         libssl.SSL_get_error(context, retVal);
     }
 }
예제 #28
0
        internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle context)
        {
            IntPtr cipherPtr = libssl.SSL_get_current_cipher(context);
            var cipher = new libssl.SSL_CIPHER();
            if (IntPtr.Zero != cipherPtr)
            {
                cipher = Marshal.PtrToStructure<libssl.SSL_CIPHER>(cipherPtr);
            }

            return cipher;
        }
예제 #29
0
 private static SslException CreateSslException(SafeSslHandle context, string message, int error)
 {
     return(CreateSslException(message, libssl.SSL_get_error(context, error)));
 }
예제 #30
0
 internal static SafeX509Handle GetPeerCertificate(SafeSslHandle context)
 {
     return libssl.SSL_get_peer_certificate(context);
 }
예제 #31
0
        internal static libssl.SSL_CIPHER GetConnectionInfo(SafeSslHandle sslHandle, out string protocolVersion)
        {
            IntPtr cipherPtr = libssl.SSL_get_current_cipher(sslHandle);
            var cipher = new libssl.SSL_CIPHER();
            if (IntPtr.Zero != cipherPtr)
            {
                cipher = Marshal.PtrToStructure<libssl.SSL_CIPHER>(cipherPtr);
            }

            IntPtr versionPtr = libssl.SSL_get_version(sslHandle);
            protocolVersion = Marshal.PtrToStringAnsi(versionPtr);
            return cipher;
        }
예제 #32
0
 internal static void FreeSslContext(SafeSslHandle context)
 {
     Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext");
     Disconnect(context);
     context.Dispose();
 }
예제 #33
0
        public SafeDeleteContext(SafeFreeCredentials credential, long options, bool isServer, bool remoteCertRequired)
            : base(IntPtr.Zero, true)
        {
            Debug.Assert((null != credential) && !credential.IsInvalid, "Invalid credential used in SafeDeleteContext");

            // When a credential handle is first associated with the context we keep credential
            // ref count bumped up to ensure ordered finalization. The certificate handle and
            // key handle are used in the SSL data structures and should survive the lifetime of
            // the SSL context
            bool ignore = false;
            _credential = credential;
            _credential.DangerousAddRef(ref ignore);

            try
            {
                _sslContext = Interop.OpenSsl.AllocateSslContext(
                    options,
                    credential.CertHandle,
                    credential.CertKeyHandle,
                    isServer,
                    remoteCertRequired);
            }
            finally
            {
                if (IsInvalid)
                {
                    _credential.DangerousRelease();
                }
            }
        }
예제 #34
0
        internal static int Encrypt(SafeSslHandle context, IntPtr buffer, int offset, int count, int bufferCapacity, out libssl.SslErrorCode errorCode)
        {
            errorCode = libssl.SslErrorCode.SSL_ERROR_NONE;

            int retVal = libssl.SSL_write(context, new IntPtr(buffer.ToInt64() + offset), count);
            if (retVal != count)
            {
                errorCode = GetSslError(context, retVal);
                retVal = 0;

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

                    default:
                        throw CreateSslException("OpenSsl::Encrypt failed");
                }
            }
            else
            {
                int capacityNeeded = libssl.BIO_ctrl_pending(context.OutputBio);      

                if (capacityNeeded > bufferCapacity)
                {
                    throw CreateSslException("OpenSsl::Encrypt capacity needed is more than buffer capacity. capacityNeeded = " + capacityNeeded + "," + "bufferCapacity = " + bufferCapacity);
                }             

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

                if (retVal < 0)
                {
                    throw CreateSslException("OpenSsl::Encrypt failed");
                }
            }

            return retVal;
        }