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(); } } }
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); }
//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); }
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); }
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); } }
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); }
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); }
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)); }
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)); }
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); }
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)); }
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)); }
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)); }
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)); }
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); } }
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); }
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); }
internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle context) { return libssl.SSL_get_peer_cert_chain(context); }
internal static void FreeSslContext(SafeSslHandle context) { Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext"); Disconnect(context); context.Dispose(); }
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; }
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; }
internal static SafeSharedX509StackHandle GetPeerCertificateChain(SafeSslHandle context) { return(libssl.SSL_get_peer_cert_chain(context)); }
internal static SafeX509Handle GetPeerCertificate(SafeSslHandle context) { return(libssl.SSL_get_peer_certificate(context)); }
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; }
private static SslException CreateSslException(SafeSslHandle context, string message, int error) { return CreateSslException(message, libssl.SSL_get_error(context, error)); }
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; }
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); } }
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; }
private static SslException CreateSslException(SafeSslHandle context, string message, int error) { return(CreateSslException(message, libssl.SSL_get_error(context, error))); }
internal static SafeX509Handle GetPeerCertificate(SafeSslHandle context) { return libssl.SSL_get_peer_certificate(context); }
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; }
internal static void FreeSslContext(SafeSslHandle context) { Debug.Assert((context != null) && !context.IsInvalid, "Expected a valid context in FreeSslContext"); Disconnect(context); context.Dispose(); }
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(); } } }
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; }