public static SecurityStatusPal ApplyShutdownToken(ref SafeFreeCredentials credentialsHandle, SafeDeleteContext securityContext)
        {
            SafeDeleteSslContext sslContext = ((SafeDeleteSslContext)securityContext);

            // Unset the quiet shutdown option initially configured.
            Interop.Ssl.SslSetQuietShutdown(sslContext.SslContext, 0);

            int status = Interop.Ssl.SslShutdown(sslContext.SslContext);

            if (status == 0)
            {
                // Call SSL_shutdown again for a bi-directional shutdown.
                status = Interop.Ssl.SslShutdown(sslContext.SslContext);
            }

            if (status == 1)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }

            Interop.Ssl.SslErrorCode code = Interop.Ssl.SslGetError(sslContext.SslContext, status);
            if (code == Interop.Ssl.SslErrorCode.SSL_ERROR_WANT_READ ||
                code == Interop.Ssl.SslErrorCode.SSL_ERROR_WANT_WRITE)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }
            else
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, new Interop.OpenSsl.SslException((int)code)));
            }
        }
Beispiel #2
0
        public static SecurityStatusPal DecryptMessage(
            SafeDeleteContext securityContext,
            byte[] buffer,
            ref int offset,
            ref int count)
        {
            try
            {
                SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;
                SafeSslHandle        sslHandle  = sslContext.SslContext;

                sslContext.Write(buffer, offset, count);

                unsafe
                {
                    fixed(byte *offsetInput = &buffer[offset])
                    {
                        int       written;
                        PAL_TlsIo status;

                        lock (sslHandle)
                        {
                            status = Interop.AppleCrypto.SslRead(sslHandle, offsetInput, count, out written);
                        }

                        if (status < 0)
                        {
                            return(new SecurityStatusPal(
                                       SecurityStatusPalErrorCode.InternalError,
                                       Interop.AppleCrypto.CreateExceptionForOSStatus((int)status)));
                        }

                        count = written;

                        switch (status)
                        {
                        case PAL_TlsIo.Success:
                        case PAL_TlsIo.WouldBlock:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));

                        case PAL_TlsIo.ClosedGracefully:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.ContextExpired));

                        case PAL_TlsIo.Renegotiate:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.Renegotiate));

                        default:
                            Debug.Fail($"Unknown status value: {status}");
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, e));
            }
        }
Beispiel #3
0
 public static SecurityStatusPal AcceptSecurityContext(
     ref SafeFreeCredentials credential,
     ref SafeDeleteSslContext context,
     byte[] inputBuffer, int offset, int count,
     ref byte[] outputBuffer,
     SslAuthenticationOptions sslAuthenticationOptions)
 {
     return(HandshakeInternal(credential, ref context, new ReadOnlySpan <byte>(inputBuffer, offset, count), ref outputBuffer, sslAuthenticationOptions));
 }
Beispiel #4
0
 public static SecurityStatusPal AcceptSecurityContext(
     ref SafeFreeCredentials credential,
     ref SafeDeleteSslContext context,
     ArraySegment <byte> inputBuffer,
     ref byte[] outputBuffer,
     SslAuthenticationOptions sslAuthenticationOptions)
 {
     return(HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions));
 }
Beispiel #5
0
        //-------------------------------------------------------------------
        internal static unsafe int InitializeSecurityContext(
            ref SafeFreeCredentials inCredentials,
            ref SafeDeleteSslContext refContext,
            string targetName,
            Interop.SspiCli.ContextFlags inFlags,
            Interop.SspiCli.Endianness endianness,
            ReadOnlySpan <SecurityBuffer> inSecBuffers,
            ref SecurityBuffer outSecBuffer,
            ref Interop.SspiCli.ContextFlags outFlags)
        {
#if TRACE_VERBOSE
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(null, $"credential:{inCredentials}, crefContext:{refContext}, targetName:{targetName}, inFlags:{inFlags}, endianness:{endianness}");
                NetEventSource.Info(null, $"inSecBuffers.Length = {inSecBuffers.Length}");
            }
#endif

            if (inCredentials == null)
            {
                throw new ArgumentNullException(nameof(inCredentials));
            }

            Interop.SspiCli.SecBufferDesc inSecurityBufferDescriptor  = new Interop.SspiCli.SecBufferDesc(inSecBuffers.Length);
            Interop.SspiCli.SecBufferDesc outSecurityBufferDescriptor = new Interop.SspiCli.SecBufferDesc(1);

            // Actually, this is returned in outFlags.
            bool isSspiAllocated = (inFlags & Interop.SspiCli.ContextFlags.AllocateMemory) != 0 ? true : false;

            int errorCode = -1;

            bool isContextAbsent = true;
            if (refContext != null)
            {
                isContextAbsent = refContext._handle.IsZero;
            }

            // Optional output buffer that may need to be freed.
            SafeFreeContextBuffer outFreeContextBuffer = null;
            try
            {
                Span <Interop.SspiCli.SecBuffer> inUnmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[inSecurityBufferDescriptor.cBuffers];
                inUnmanagedBuffer.Clear();

                fixed(void *inUnmanagedBufferPtr = inUnmanagedBuffer)
                fixed(void *pinnedToken0 = inSecBuffers.Length > 0 ? inSecBuffers[0].token : null)
                fixed(void *pinnedToken1 = inSecBuffers.Length > 1 ? inSecBuffers[1].token : null)
                fixed(void *pinnedToken2 = inSecBuffers.Length > 2 ? inSecBuffers[2].token : null)  // pin all buffers, even if null or not used, to avoid needing to allocate GCHandles
                {
                    Debug.Assert(inSecBuffers.Length <= 3);

                    // Fix Descriptor pointer that points to unmanaged SecurityBuffers.
                    inSecurityBufferDescriptor.pBuffers = inUnmanagedBufferPtr;
                    for (int index = 0; index < inSecurityBufferDescriptor.cBuffers; ++index)
                    {
                        ref readonly SecurityBuffer securityBuffer = ref inSecBuffers[index];
        internal static SecurityStatusPal InitializeSecurityContext(
            ref SafeFreeCredentials credentialsHandle,
            ref SafeDeleteContext securityContext,
            string spn,
            ContextFlagsPal requestedContextFlags,
            byte[] incomingBlob,
            ChannelBinding channelBinding,
            ref byte[] resultBlob,
            ref ContextFlagsPal contextFlags)
        {
#if netstandard
            Span <SecurityBuffer> inSecurityBufferSpan = new SecurityBuffer[2];
#else
            TwoSecurityBuffers    twoSecurityBuffers   = default;
            Span <SecurityBuffer> inSecurityBufferSpan = MemoryMarshal.CreateSpan(ref twoSecurityBuffers._item0, 2);
#endif

            int inSecurityBufferSpanLength = 0;
            if (incomingBlob != null && channelBinding != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);
                inSecurityBufferSpan[1]    = new SecurityBuffer(channelBinding);
                inSecurityBufferSpanLength = 2;
            }
            else if (incomingBlob != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);
                inSecurityBufferSpanLength = 1;
            }
            else if (channelBinding != null)
            {
                inSecurityBufferSpan[0]    = new SecurityBuffer(channelBinding);
                inSecurityBufferSpanLength = 1;
            }
            inSecurityBufferSpan = inSecurityBufferSpan.Slice(0, inSecurityBufferSpanLength);

            var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN);

            Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero;
            // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe.
            SafeDeleteSslContext    sslContext = (SafeDeleteSslContext)securityContext;
            Interop.SECURITY_STATUS winStatus  = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext(
                GlobalSSPI.SSPIAuth,
                ref credentialsHandle,
                ref sslContext,
                spn,
                ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags),
                Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP,
                inSecurityBufferSpan,
                ref outSecurityBuffer,
                ref outContextFlags);
            securityContext = sslContext;
            resultBlob      = outSecurityBuffer.token;
            contextFlags    = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags);
            return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus));
        }
Beispiel #7
0
 public static SecurityStatusPal InitializeSecurityContext(
     ref SafeFreeCredentials credential,
     ref SafeDeleteSslContext context,
     string targetName,
     ReadOnlySpan <byte> inputBuffer,
     ref byte[] outputBuffer,
     SslAuthenticationOptions sslAuthenticationOptions)
 {
     return(HandshakeInternal(credential, ref context, inputBuffer, ref outputBuffer, sslAuthenticationOptions));
 }
Beispiel #8
0
        private static SecurityStatusPal HandshakeInternal(
            SafeFreeCredentials credential,
            ref SafeDeleteContext context,
            SecurityBuffer inputBuffer,
            SecurityBuffer outputBuffer,
            SslAuthenticationOptions sslAuthenticationOptions)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                SafeDeleteSslContext sslContext = ((SafeDeleteSslContext)context);

                if ((null == context) || context.IsInvalid)
                {
                    sslContext = new SafeDeleteSslContext(credential as SafeFreeSslCredentials, sslAuthenticationOptions);
                    context    = sslContext;

                    if (!string.IsNullOrEmpty(sslAuthenticationOptions.TargetHost))
                    {
                        Debug.Assert(!sslAuthenticationOptions.IsServer, "targetName should not be set for server-side handshakes");
                        Interop.AppleCrypto.SslSetTargetName(sslContext.SslContext, sslAuthenticationOptions.TargetHost);
                    }

                    if (sslAuthenticationOptions.IsServer && sslAuthenticationOptions.RemoteCertRequired)
                    {
                        Interop.AppleCrypto.SslSetAcceptClientCert(sslContext.SslContext);
                    }
                }

                if (inputBuffer != null && inputBuffer.size > 0)
                {
                    sslContext.Write(inputBuffer.token, inputBuffer.offset, inputBuffer.size);
                }

                SafeSslHandle     sslHandle = sslContext.SslContext;
                SecurityStatusPal status;

                lock (sslHandle)
                {
                    status = PerformHandshake(sslHandle);
                }

                byte[] output = sslContext.ReadPendingWrites();
                outputBuffer.offset = 0;
                outputBuffer.size   = output?.Length ?? 0;
                outputBuffer.token  = output;

                return(status);
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
Beispiel #9
0
        public static SecurityStatusPal DecryptMessage(
            SafeDeleteSslContext securityContext,
            Span <byte> buffer,
            out int offset,
            out int count)
        {
            offset = 0;
            count  = 0;

            try
            {
                SafeSslHandle sslHandle = securityContext.SslContext;
                securityContext.Write(buffer);

                unsafe
                {
                    fixed(byte *ptr = buffer)
                    {
                        PAL_TlsIo status = Interop.AppleCrypto.SslRead(sslHandle, ptr, buffer.Length, out int written);

                        if (status < 0)
                        {
                            return(new SecurityStatusPal(
                                       SecurityStatusPalErrorCode.InternalError,
                                       Interop.AppleCrypto.CreateExceptionForOSStatus((int)status)));
                        }

                        count  = written;
                        offset = 0;

                        switch (status)
                        {
                        case PAL_TlsIo.Success:
                        case PAL_TlsIo.WouldBlock:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));

                        case PAL_TlsIo.ClosedGracefully:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.ContextExpired));

                        case PAL_TlsIo.Renegotiate:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.Renegotiate));

                        default:
                            Debug.Fail($"Unknown status value: {status}");
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError));
                        }
                    }
                }
            }
            catch (Exception e)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, e));
            }
        }
Beispiel #10
0
        private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteSslContext context,
                                                           ArraySegment <byte> inputBuffer, ref byte[] outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
        {
            Debug.Assert(!credential.IsInvalid);

            byte[] output     = null;
            int    outputSize = 0;

            try
            {
                if ((null == context) || context.IsInvalid)
                {
                    context = new SafeDeleteSslContext(credential as SafeFreeSslCredentials, sslAuthenticationOptions);
                }

                bool done;

                if (inputBuffer.Array == null)
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, 0, 0, out output, out outputSize);
                }
                else
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, inputBuffer.Array, inputBuffer.Offset, inputBuffer.Count, out output, out outputSize);
                }

                // When the handshake is done, and the context is server, check if the alpnHandle target was set to null during ALPN.
                // If it was, then that indicates ALPN failed, send failure.
                // We have this workaround, as openssl supports terminating handshake only from version 1.1.0,
                // whereas ALPN is supported from version 1.0.2.
                SafeSslHandle sslContext = ((SafeDeleteSslContext)context).SslContext;
                if (done && sslAuthenticationOptions.IsServer && sslAuthenticationOptions.ApplicationProtocols != null && sslContext.AlpnHandle.IsAllocated && sslContext.AlpnHandle.Target == null)
                {
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, Interop.OpenSsl.CreateSslException(SR.net_alpn_failed)));
                }

                outputBuffer =
                    outputSize == 0 ? null :
                    outputSize == output.Length ? output :
                    new Span <byte>(output, 0, outputSize).ToArray();

                return(new SecurityStatusPal(done ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.ContinueNeeded));
            }
            catch (Exception exc)
            {
                // Even if handshake failed we may have Alert to sent.
                if (outputSize > 0)
                {
                    outputBuffer = outputSize == output.Length ? output : new Span <byte>(output, 0, outputSize).ToArray();
                }

                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
        public static SecurityStatusPal DecryptMessage(SafeDeleteSslContext securityContext, byte[] buffer, ref int offset, ref int count)
        {
            SecurityStatusPal retVal = EncryptDecryptHelper(securityContext, buffer, offset, count, false, ref buffer, out int resultSize);

            if (retVal.ErrorCode == SecurityStatusPalErrorCode.OK ||
                retVal.ErrorCode == SecurityStatusPalErrorCode.Renegotiate)
            {
                count = resultSize;
            }
            return(retVal);
        }
Beispiel #12
0
        public static SecurityStatusPal EncryptMessage(SafeDeleteSslContext securityContext, ReadOnlyMemory <byte> input, int headerSize, int trailerSize, ref byte[] output, out int resultSize)
        {
            try
            {
                resultSize = Interop.OpenSsl.Encrypt(securityContext.SslContext, input.Span, ref output, out Interop.Ssl.SslErrorCode errorCode);

                return(MapNativeErrorCode(errorCode));
            }
            catch (Exception ex)
            {
                resultSize = 0;
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex));
            }
        }
        internal static SecurityStatusPal CompleteAuthToken(
            ref SafeDeleteContext securityContext,
            byte[] incomingBlob)
        {
            // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe.
            SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;
            var inSecurityBuffer            = new SecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN);

            Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.CompleteAuthToken(
                GlobalSSPI.SSPIAuth,
                ref sslContext,
                in inSecurityBuffer);
            securityContext = sslContext;
            return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus));
        }
Beispiel #14
0
        private static SecurityStatusPal HandshakeInternal(
            SafeFreeCredentials credential,
            ref SafeDeleteSslContext?context,
            ReadOnlySpan <byte> inputBuffer,
            ref byte[]?outputBuffer,
            SslAuthenticationOptions sslAuthenticationOptions,
            SelectClientCertificate?clientCertificateSelectionCallback)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context);

                if ((null == context) || context.IsInvalid)
                {
                    sslContext = new SafeDeleteSslContext((credential as SafeFreeSslCredentials) !, sslAuthenticationOptions);
                    context    = sslContext;
                }

                if (inputBuffer.Length > 0)
                {
                    sslContext !.Write(inputBuffer);
                }

                SafeSslHandle     sslHandle = sslContext !.SslContext;
                SecurityStatusPal status    = PerformHandshake(sslHandle);
                if (status.ErrorCode == SecurityStatusPalErrorCode.CredentialsNeeded && clientCertificateSelectionCallback != null)
                {
                    X509Certificate2?clientCertificate = clientCertificateSelectionCallback(out bool _);
                    if (clientCertificate != null)
                    {
                        sslAuthenticationOptions.CertificateContext = SslStreamCertificateContext.Create(clientCertificate);
                        SafeDeleteSslContext.SetCertificate(sslContext.SslContext, sslAuthenticationOptions.CertificateContext);
                    }

                    // We either got certificate or we can proceed without it. It is up to the server to decide if either is OK.
                    status = PerformHandshake(sslHandle);
                }

                outputBuffer = sslContext.ReadPendingWrites();
                return(status);
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
Beispiel #15
0
        public static SecurityStatusPal ApplyShutdownToken(
            ref SafeFreeCredentials?credentialsHandle,
            SafeDeleteSslContext securityContext)
        {
            SafeSslHandle sslHandle = securityContext.SslContext;


            bool success = Interop.AndroidCrypto.SSLStreamShutdown(sslHandle);

            if (success)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }

            return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError));
        }
Beispiel #16
0
        public static SecurityStatusPal ApplyShutdownToken(
            ref SafeFreeCredentials credentialsHandle,
            SafeDeleteContext securityContext)
        {
            SafeDeleteSslContext sslContext = ((SafeDeleteSslContext)securityContext);
            int osStatus = Interop.AppleCrypto.SslShutdown(sslContext.SslContext);

            if (osStatus == 0)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }

            return(new SecurityStatusPal(
                       SecurityStatusPalErrorCode.InternalError,
                       Interop.AppleCrypto.CreateExceptionForOSStatus(osStatus)));
        }
Beispiel #17
0
        private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer,
                                                           SecurityBuffer outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                if ((null == context) || context.IsInvalid)
                {
                    context = new SafeDeleteSslContext(credential as SafeFreeSslCredentials, sslAuthenticationOptions);
                }

                byte[] output = null;
                int    outputSize;
                bool   done;

                if (null == inputBuffer)
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, 0, 0, out output, out outputSize);
                }
                else
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, inputBuffer.token, inputBuffer.offset, inputBuffer.size, out output, out outputSize);
                }

                // When the handshake is done, and the context is server, check if the alpnHandle target was set to null during ALPN.
                // If it was, then that indiciates ALPN failed, send failure.
                // We have this workaround, as openssl supports terminating handshake only from version 1.1.0,
                // whereas ALPN is supported from version 1.0.2.
                SafeSslHandle sslContext = ((SafeDeleteSslContext)context).SslContext;
                if (done && sslAuthenticationOptions.IsServer && sslAuthenticationOptions.ApplicationProtocols != null && sslContext.AlpnHandle.IsAllocated && sslContext.AlpnHandle.Target == null)
                {
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, Interop.OpenSsl.CreateSslException(SR.net_alpn_failed)));
                }

                outputBuffer.size   = outputSize;
                outputBuffer.offset = 0;
                outputBuffer.token  = outputSize > 0 ? output : null;

                return(new SecurityStatusPal(done ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.ContinueNeeded));
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
Beispiel #18
0
        public static SecurityStatusPal EncryptMessage(
            SafeDeleteContext securityContext,
            ReadOnlyMemory <byte> input,
            int headerSize,
            int trailerSize,
            ref byte[] output,
            out int resultSize)
        {
            resultSize = 0;
            Debug.Assert(input.Length > 0, $"{nameof(input.Length)} > 0 since {nameof(CanEncryptEmptyMessage)} is false");

            try
            {
                SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;
                SafeSslHandle        sslHandle  = sslContext.SslContext;

                PAL_SSLStreamStatus        ret        = Interop.AndroidCrypto.SSLStreamWrite(sslHandle, input);
                SecurityStatusPalErrorCode statusCode = ret switch
                {
                    PAL_SSLStreamStatus.OK => SecurityStatusPalErrorCode.OK,
                    PAL_SSLStreamStatus.NeedData => SecurityStatusPalErrorCode.ContinueNeeded,
                    PAL_SSLStreamStatus.Renegotiate => SecurityStatusPalErrorCode.Renegotiate,
                    PAL_SSLStreamStatus.Closed => SecurityStatusPalErrorCode.ContextExpired,
                    _ => SecurityStatusPalErrorCode.InternalError
                };

                if (sslContext.BytesReadyForConnection <= output?.Length)
                {
                    resultSize = sslContext.ReadPendingWrites(output, 0, output.Length);
                }
                else
                {
                    output     = sslContext.ReadPendingWrites() !;
                    resultSize = output.Length;
                }

                return(new SecurityStatusPal(statusCode));
            }
            catch (Exception e)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, e));
            }
        }
        internal static SecurityStatusPal InitializeSecurityContext(
            ref SafeFreeCredentials credentialsHandle,
            ref SafeDeleteContext securityContext,
            string spn,
            ContextFlagsPal requestedContextFlags,
            byte[] incomingBlob,
            ChannelBinding channelBinding,
            ref byte[] resultBlob,
            ref ContextFlagsPal contextFlags)
        {
            InputSecurityBuffers inputBuffers = default;

            if (incomingBlob != null)
            {
                inputBuffers.SetNextBuffer(new InputSecurityBuffer(incomingBlob, SecurityBufferType.SECBUFFER_TOKEN));
            }

            if (channelBinding != null)
            {
                inputBuffers.SetNextBuffer(new InputSecurityBuffer(channelBinding));
            }

            var outSecurityBuffer = new SecurityBuffer(resultBlob, SecurityBufferType.SECBUFFER_TOKEN);

            Interop.SspiCli.ContextFlags outContextFlags = Interop.SspiCli.ContextFlags.Zero;
            // There is only one SafeDeleteContext type on Windows which is SafeDeleteSslContext so this cast is safe.
            SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;

            Interop.SECURITY_STATUS winStatus = (Interop.SECURITY_STATUS)SSPIWrapper.InitializeSecurityContext(
                GlobalSSPI.SSPIAuth,
                ref credentialsHandle,
                ref sslContext,
                spn,
                ContextFlagsAdapterPal.GetInteropFromContextFlagsPal(requestedContextFlags),
                Interop.SspiCli.Endianness.SECURITY_NETWORK_DREP,
                inputBuffers,
                ref outSecurityBuffer,
                ref outContextFlags);
            securityContext = sslContext;
            resultBlob      = outSecurityBuffer.token;
            contextFlags    = ContextFlagsAdapterPal.GetContextFlagsPalFromInterop(outContextFlags);
            return(SecurityStatusAdapterPal.GetSecurityStatusPalFromInterop(winStatus));
        }
Beispiel #20
0
        private static SecurityStatusPal HandshakeInternal(
            SafeFreeCredentials credential,
            ref SafeDeleteSslContext?context,
            ReadOnlySpan <byte> inputBuffer,
            ref byte[]?outputBuffer,
            SslAuthenticationOptions sslAuthenticationOptions)
        {
            try
            {
                SafeDeleteSslContext?sslContext = ((SafeDeleteSslContext?)context);

                if ((context == null) || context.IsInvalid)
                {
                    context    = new SafeDeleteSslContext(sslAuthenticationOptions);
                    sslContext = context;
                }

                if (inputBuffer.Length > 0)
                {
                    sslContext !.Write(inputBuffer);
                }

                SafeSslHandle sslHandle = sslContext !.SslContext;

                PAL_SSLStreamStatus        ret        = Interop.AndroidCrypto.SSLStreamHandshake(sslHandle);
                SecurityStatusPalErrorCode statusCode = ret switch
                {
                    PAL_SSLStreamStatus.OK => SecurityStatusPalErrorCode.OK,
                    PAL_SSLStreamStatus.NeedData => SecurityStatusPalErrorCode.ContinueNeeded,
                    _ => SecurityStatusPalErrorCode.InternalError
                };

                outputBuffer = sslContext.ReadPendingWrites();

                return(new SecurityStatusPal(statusCode));
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
Beispiel #21
0
        public static SecurityStatusPal DecryptMessage(SafeDeleteSslContext securityContext, byte[] buffer, ref int offset, ref int count)
        {
            try
            {
                int resultSize = Interop.OpenSsl.Decrypt(securityContext.SslContext, new Span <byte>(buffer, offset, count), out Interop.Ssl.SslErrorCode errorCode);

                SecurityStatusPal retVal = MapNativeErrorCode(errorCode);

                if (retVal.ErrorCode == SecurityStatusPalErrorCode.OK ||
                    retVal.ErrorCode == SecurityStatusPalErrorCode.Renegotiate)
                {
                    count = resultSize;
                }

                return(retVal);
            }
            catch (Exception ex)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex));
            }
        }
Beispiel #22
0
        public static SecurityStatusPal DecryptMessage(
            SafeDeleteSslContext securityContext,
            Span <byte> buffer,
            out int offset,
            out int count)
        {
            offset = 0;
            count  = 0;

            try
            {
                SafeSslHandle sslHandle = securityContext.SslContext;

                securityContext.Write(buffer);

                PAL_SSLStreamStatus ret = Interop.AndroidCrypto.SSLStreamRead(sslHandle, buffer, out int read);
                if (ret == PAL_SSLStreamStatus.Error)
                {
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError));
                }

                count = read;

                SecurityStatusPalErrorCode statusCode = ret switch
                {
                    PAL_SSLStreamStatus.OK => SecurityStatusPalErrorCode.OK,
                    PAL_SSLStreamStatus.NeedData => SecurityStatusPalErrorCode.OK,
                    PAL_SSLStreamStatus.Renegotiate => SecurityStatusPalErrorCode.Renegotiate,
                    PAL_SSLStreamStatus.Closed => SecurityStatusPalErrorCode.ContextExpired,
                    _ => SecurityStatusPalErrorCode.InternalError
                };

                return(new SecurityStatusPal(statusCode));
            }
            catch (Exception e)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, e));
            }
        }
        public static ChannelBinding?QueryContextChannelBinding(SafeDeleteSslContext securityContext, ChannelBindingKind attribute)
        {
            ChannelBinding?bindingHandle;

            if (attribute == ChannelBindingKind.Endpoint)
            {
                bindingHandle = EndpointChannelBindingToken.Build(securityContext);

                if (bindingHandle == null)
                {
                    throw Interop.OpenSsl.CreateSslException(SR.net_ssl_invalid_certificate);
                }
            }
            else
            {
                bindingHandle = Interop.OpenSsl.QueryChannelBinding(
                    securityContext.SslContext,
                    attribute);
            }

            return(bindingHandle);
        }
        private static SecurityStatusPal EncryptDecryptHelper(SafeDeleteSslContext securityContext, ReadOnlyMemory <byte> input, int offset, int size, bool encrypt, ref byte[] output, out int resultSize)
        {
            resultSize = 0;
            try
            {
                Interop.Ssl.SslErrorCode errorCode = Interop.Ssl.SslErrorCode.SSL_ERROR_NONE;
                SafeSslHandle            scHandle  = securityContext.SslContext;

                if (encrypt)
                {
                    resultSize = Interop.OpenSsl.Encrypt(scHandle, input.Span, ref output, out errorCode);
                }
                else
                {
                    resultSize = Interop.OpenSsl.Decrypt(scHandle, output, offset, size, out errorCode);
                }

                switch (errorCode)
                {
                case Interop.Ssl.SslErrorCode.SSL_ERROR_RENEGOTIATE:
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.Renegotiate));

                case Interop.Ssl.SslErrorCode.SSL_ERROR_ZERO_RETURN:
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.ContextExpired));

                case Interop.Ssl.SslErrorCode.SSL_ERROR_NONE:
                case Interop.Ssl.SslErrorCode.SSL_ERROR_WANT_READ:
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));

                default:
                    return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, new Interop.OpenSsl.SslException((int)errorCode)));
                }
            }
            catch (Exception ex)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, ex));
            }
        }
Beispiel #25
0
        public static SecurityStatusPal ApplyShutdownToken(ref SafeFreeCredentials credentialsHandle, SafeDeleteContext securityContext)
        {
            SafeDeleteSslContext sslContext = ((SafeDeleteSslContext)securityContext);

            // Unset the quiet shutdown option initially configured.
            Interop.Ssl.SslSetQuietShutdown(sslContext.SslContext, 0);

            int status = Interop.Ssl.SslShutdown(sslContext.SslContext);

            if (status == 0)
            {
                // Call SSL_shutdown again for a bi-directional shutdown.
                status = Interop.Ssl.SslShutdown(sslContext.SslContext);
            }

            if (status == 1)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }

            Interop.Ssl.SslErrorCode code = Interop.Ssl.SslGetError(sslContext.SslContext, status);
            if (code == Interop.Ssl.SslErrorCode.SSL_ERROR_WANT_READ ||
                code == Interop.Ssl.SslErrorCode.SSL_ERROR_WANT_WRITE)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));
            }
            else if (code == Interop.Ssl.SslErrorCode.SSL_ERROR_SSL)
            {
                // OpenSSL failure occurred.  The error queue contains more details, when building the exception the queue will be cleared.
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, Interop.Crypto.CreateOpenSslCryptographicException()));
            }
            else
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, new Interop.OpenSsl.SslException((int)code)));
            }
        }
Beispiel #26
0
        private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteContext context, SecurityBuffer inputBuffer,
                                                           SecurityBuffer outputBuffer, SslAuthenticationOptions sslAuthenticationOptions)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                if ((null == context) || context.IsInvalid)
                {
                    context = new SafeDeleteSslContext(credential as SafeFreeSslCredentials, sslAuthenticationOptions);
                }

                byte[] output = null;
                int    outputSize;
                bool   done;

                if (null == inputBuffer)
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, 0, 0, out output, out outputSize);
                }
                else
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, inputBuffer.token, inputBuffer.offset, inputBuffer.size, out output, out outputSize);
                }

                outputBuffer.size   = outputSize;
                outputBuffer.offset = 0;
                outputBuffer.token  = outputSize > 0 ? output : null;

                return(new SecurityStatusPal(done ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.ContinueNeeded));
            }
            catch (Exception exc)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc));
            }
        }
Beispiel #27
0
        internal static unsafe int AcceptSecurityContext(
            ref SafeFreeCredentials?inCredentials,
            ref SafeDeleteSslContext?refContext,
            Interop.SspiCli.ContextFlags inFlags,
            Interop.SspiCli.Endianness endianness,
            InputSecurityBuffers inSecBuffers,
            ref SecurityBuffer outSecBuffer,
            ref Interop.SspiCli.ContextFlags outFlags)
        {
#if TRACE_VERBOSE
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(null, $"credential={inCredentials}, refContext={refContext}, inFlags={inFlags}");
                NetEventSource.Info(null, $"inSecBuffers.Length = {inSecBuffers.Length}");
            }
#endif

            if (inCredentials == null)
            {
                throw new ArgumentNullException(nameof(inCredentials));
            }

            Debug.Assert(inSecBuffers.Count <= 3);
            Interop.SspiCli.SecBufferDesc inSecurityBufferDescriptor  = new Interop.SspiCli.SecBufferDesc(inSecBuffers.Count);
            Interop.SspiCli.SecBufferDesc outSecurityBufferDescriptor = new Interop.SspiCli.SecBufferDesc(count: 2);

            // Actually, this is returned in outFlags.
            bool isSspiAllocated = (inFlags & Interop.SspiCli.ContextFlags.AllocateMemory) != 0 ? true : false;

            int errorCode = -1;

            bool isContextAbsent = true;
            if (refContext != null)
            {
                isContextAbsent = refContext._handle.IsZero;
            }

            // Optional output buffer that may need to be freed.
            SafeFreeContextBuffer?           outFreeContextBuffer = null;
            Span <Interop.SspiCli.SecBuffer> outUnmanagedBuffer   = stackalloc Interop.SspiCli.SecBuffer[2];
            outUnmanagedBuffer[1].pvBuffer = IntPtr.Zero;
            try
            {
                // Allocate always maximum to allow better code optimization.
                Span <Interop.SspiCli.SecBuffer> inUnmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3];

                fixed(void *inUnmanagedBufferPtr = inUnmanagedBuffer)
                fixed(void *outUnmanagedBufferPtr = outUnmanagedBuffer)
                fixed(void *pinnedToken0          = inSecBuffers._item0.Token)
                fixed(void *pinnedToken1          = inSecBuffers._item1.Token)
                fixed(void *pinnedToken2          = inSecBuffers._item2.Token)
                {
                    inSecurityBufferDescriptor.pBuffers = inUnmanagedBufferPtr;
                    // Updated pvBuffer with pinned address. UnmanagedToken takes precedence.
                    if (inSecBuffers.Count > 2)
                    {
                        inUnmanagedBuffer[2].BufferType = inSecBuffers._item2.Type;
                        inUnmanagedBuffer[2].cbBuffer   = inSecBuffers._item2.Token.Length;
                        inUnmanagedBuffer[2].pvBuffer   = inSecBuffers._item2.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item2.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken2;
                    }

                    if (inSecBuffers.Count > 1)
                    {
                        inUnmanagedBuffer[1].BufferType = inSecBuffers._item1.Type;
                        inUnmanagedBuffer[1].cbBuffer   = inSecBuffers._item1.Token.Length;
                        inUnmanagedBuffer[1].pvBuffer   = inSecBuffers._item1.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item1.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken1;
                    }

                    if (inSecBuffers.Count > 0)
                    {
                        inUnmanagedBuffer[0].BufferType = inSecBuffers._item0.Type;
                        inUnmanagedBuffer[0].cbBuffer   = inSecBuffers._item0.Token.Length;
                        inUnmanagedBuffer[0].pvBuffer   = inSecBuffers._item0.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item0.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken0;
                    }

                    fixed(byte *pinnedOutBytes = outSecBuffer.token)
                    {
                        // Fix Descriptor pointer that points to unmanaged SecurityBuffers.
                        outSecurityBufferDescriptor.pBuffers = outUnmanagedBufferPtr;

                        // Copy the SecurityBuffer content into unmanaged place holder.
                        outUnmanagedBuffer[0].cbBuffer   = outSecBuffer.size;
                        outUnmanagedBuffer[0].BufferType = outSecBuffer.type;
                        outUnmanagedBuffer[0].pvBuffer   = outSecBuffer.token == null || outSecBuffer.token.Length == 0 ?
                                                           IntPtr.Zero :
                                                           (IntPtr)(pinnedOutBytes + outSecBuffer.offset);

                        outUnmanagedBuffer[1].cbBuffer   = 0;
                        outUnmanagedBuffer[1].BufferType = SecurityBufferType.SECBUFFER_ALERT;

                        if (isSspiAllocated)
                        {
                            outFreeContextBuffer = SafeFreeContextBuffer.CreateEmptyHandle();
                        }

                        if (refContext == null || refContext.IsInvalid)
                        {
                            // Previous versions unconditionally built a new "refContext" here, but would pass
                            // incorrect arguments to AcceptSecurityContext in cases where an "contextHandle" was
                            // already present and non-zero.
                            if (isContextAbsent)
                            {
                                refContext = new SafeDeleteSslContext();
                            }
                        }

                        errorCode = MustRunAcceptSecurityContext_SECURITY(
                            ref inCredentials,
                            isContextAbsent,
                            &inSecurityBufferDescriptor,
                            inFlags,
                            endianness,
                            refContext !,
                            ref outSecurityBufferDescriptor,
                            ref outFlags,
                            outFreeContextBuffer);

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(null, "Marshaling OUT buffer");
                        }

                        // No data written out but there is Alert
                        if (outUnmanagedBuffer[0].cbBuffer == 0 && outUnmanagedBuffer[1].cbBuffer > 0)
                        {
                            outSecBuffer.size  = outUnmanagedBuffer[1].cbBuffer;
                            outSecBuffer.type  = outUnmanagedBuffer[1].BufferType;
                            outSecBuffer.token = new Span <byte>((byte *)outUnmanagedBuffer[1].pvBuffer, outUnmanagedBuffer[1].cbBuffer).ToArray();
                        }
                        else
                        {
                            outSecBuffer.size  = outUnmanagedBuffer[0].cbBuffer;
                            outSecBuffer.type  = outUnmanagedBuffer[0].BufferType;
                            outSecBuffer.token = outUnmanagedBuffer[0].cbBuffer > 0 ?
                                                 new Span <byte>((byte *)outUnmanagedBuffer[0].pvBuffer, outUnmanagedBuffer[0].cbBuffer).ToArray() :
                                                 null;
                        }
                    }
                }
            }
            finally
            {
                outFreeContextBuffer?.Dispose();
                if (outUnmanagedBuffer[1].pvBuffer != IntPtr.Zero)
                {
                    Interop.SspiCli.FreeContextBuffer(outUnmanagedBuffer[1].pvBuffer);
                }
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(null, $"errorCode:0x{errorCode:x8}, refContext:{refContext}");
            }
            return(errorCode);
        }
Beispiel #28
0
        internal static unsafe int InitializeSecurityContext(
            ref SafeFreeCredentials?inCredentials,
            ref SafeDeleteSslContext?refContext,
            string?targetName,
            Interop.SspiCli.ContextFlags inFlags,
            Interop.SspiCli.Endianness endianness,
            InputSecurityBuffers inSecBuffers,
            ref SecurityBuffer outSecBuffer,
            ref Interop.SspiCli.ContextFlags outFlags)
        {
#if TRACE_VERBOSE
            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Enter(null, $"credential:{inCredentials}, crefContext:{refContext}, targetName:{targetName}, inFlags:{inFlags}, endianness:{endianness}");
                NetEventSource.Info(null, $"inSecBuffers.Length = {inSecBuffers.Length}");
            }
#endif

            if (inCredentials == null)
            {
                throw new ArgumentNullException(nameof(inCredentials));
            }

            Debug.Assert(inSecBuffers.Count <= 3);
            Interop.SspiCli.SecBufferDesc inSecurityBufferDescriptor  = new Interop.SspiCli.SecBufferDesc(inSecBuffers.Count);
            Interop.SspiCli.SecBufferDesc outSecurityBufferDescriptor = new Interop.SspiCli.SecBufferDesc(1);

            // Actually, this is returned in outFlags.
            bool isSspiAllocated = (inFlags & Interop.SspiCli.ContextFlags.AllocateMemory) != 0 ? true : false;

            int errorCode = -1;

            bool isContextAbsent = true;
            if (refContext != null)
            {
                isContextAbsent = refContext._handle.IsZero;
            }

            // Optional output buffer that may need to be freed.
            SafeFreeContextBuffer?outFreeContextBuffer = null;
            try
            {
                Span <Interop.SspiCli.SecBuffer> inUnmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3];

                fixed(void *inUnmanagedBufferPtr = inUnmanagedBuffer)
                fixed(void *pinnedToken0 = inSecBuffers._item0.Token)
                fixed(void *pinnedToken1 = inSecBuffers._item1.Token)
                fixed(void *pinnedToken2 = inSecBuffers._item2.Token)
                {
                    // Fix Descriptor pointer that points to unmanaged SecurityBuffers.
                    inSecurityBufferDescriptor.pBuffers = inUnmanagedBufferPtr;
                    // Updated pvBuffer with pinned address. UnmanagedToken takes precedence.
                    if (inSecBuffers.Count > 2)
                    {
                        inUnmanagedBuffer[2].BufferType = inSecBuffers._item2.Type;
                        inUnmanagedBuffer[2].cbBuffer   = inSecBuffers._item2.Token.Length;
                        inUnmanagedBuffer[2].pvBuffer   = inSecBuffers._item2.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item2.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken2;
                    }

                    if (inSecBuffers.Count > 1)
                    {
                        inUnmanagedBuffer[1].BufferType = inSecBuffers._item1.Type;
                        inUnmanagedBuffer[1].cbBuffer   = inSecBuffers._item1.Token.Length;
                        inUnmanagedBuffer[1].pvBuffer   = inSecBuffers._item1.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item1.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken1;
                    }

                    if (inSecBuffers.Count > 0)
                    {
                        inUnmanagedBuffer[0].BufferType = inSecBuffers._item0.Type;
                        inUnmanagedBuffer[0].cbBuffer   = inSecBuffers._item0.Token.Length;
                        inUnmanagedBuffer[0].pvBuffer   = inSecBuffers._item0.UnmanagedToken != null ?
                                                          (IntPtr)inSecBuffers._item0.UnmanagedToken.DangerousGetHandle() :
                                                          (IntPtr)pinnedToken0;
                    }

                    fixed(byte *pinnedOutBytes = outSecBuffer.token)
                    {
                        // Fix Descriptor pointer that points to unmanaged SecurityBuffers.
                        Interop.SspiCli.SecBuffer outUnmanagedBuffer = default;
                        outSecurityBufferDescriptor.pBuffers = &outUnmanagedBuffer;
                        outUnmanagedBuffer.cbBuffer          = outSecBuffer.size;
                        outUnmanagedBuffer.BufferType        = outSecBuffer.type;
                        outUnmanagedBuffer.pvBuffer          = outSecBuffer.token == null || outSecBuffer.token.Length == 0 ?
                                                               IntPtr.Zero :
                                                               (IntPtr)(pinnedOutBytes + outSecBuffer.offset);

                        if (isSspiAllocated)
                        {
                            outFreeContextBuffer = SafeFreeContextBuffer.CreateEmptyHandle();
                        }

                        if (refContext == null || refContext.IsInvalid)
                        {
                            // Previous versions unconditionally built a new "refContext" here, but would pass
                            // incorrect arguments to InitializeSecurityContextW in cases where an "contextHandle" was
                            // already present and non-zero.
                            if (isContextAbsent)
                            {
                                refContext = new SafeDeleteSslContext();
                            }
                        }

                        if (targetName == null || targetName.Length == 0)
                        {
                            targetName = dummyStr;
                        }

                        string punyCode = s_idnMapping.GetAscii(targetName);

                        fixed(char *namePtr = punyCode)
                        {
                            errorCode = MustRunInitializeSecurityContext(
                                ref inCredentials,
                                isContextAbsent,
                                (byte *)(((object)targetName == (object)dummyStr) ? null : namePtr),
                                inFlags,
                                endianness,
                                &inSecurityBufferDescriptor,
                                refContext !,
                                ref outSecurityBufferDescriptor,
                                ref outFlags,
                                outFreeContextBuffer);
                        }

                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.Info(null, "Marshalling OUT buffer");
                        }

                        // Get unmanaged buffer with index 0 as the only one passed into PInvoke.
                        outSecBuffer.size  = outUnmanagedBuffer.cbBuffer;
                        outSecBuffer.type  = outUnmanagedBuffer.BufferType;
                        outSecBuffer.token = outSecBuffer.size > 0 ?
                                             new Span <byte>((byte *)outUnmanagedBuffer.pvBuffer, outUnmanagedBuffer.cbBuffer).ToArray() :
                                             null;
                    }
                }
            }
            finally
            {
                outFreeContextBuffer?.Dispose();
            }

            if (NetEventSource.IsEnabled)
            {
                NetEventSource.Exit(null, $"errorCode:0x{errorCode:x8}, refContext:{refContext}");
            }
            return(errorCode);
        }
Beispiel #29
0
        private static SecurityStatusPal HandshakeInternal(SafeFreeCredentials credential, ref SafeDeleteContext context,
            SecurityBuffer inputBuffer, SecurityBuffer outputBuffer, bool isServer, bool remoteCertRequired)
        {
            Debug.Assert(!credential.IsInvalid);

            try
            {
                if ((null == context) || context.IsInvalid)
                {
                    context = new SafeDeleteSslContext(credential as SafeFreeSslCredentials, isServer, remoteCertRequired);
                }

                byte[] output = null;
                int outputSize;
                bool done;

                if (null == inputBuffer)
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, null, 0, 0, out output, out outputSize);
                }
                else
                {
                    done = Interop.OpenSsl.DoSslHandshake(((SafeDeleteSslContext)context).SslContext, inputBuffer.token, inputBuffer.offset, inputBuffer.size, out output, out outputSize);
                }

                outputBuffer.size = outputSize;
                outputBuffer.offset = 0;
                outputBuffer.token = outputSize > 0 ? output : null;

                return new SecurityStatusPal(done ? SecurityStatusPalErrorCode.OK : SecurityStatusPalErrorCode.ContinueNeeded);
            }
            catch (Exception exc)
            {
                return new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, exc);     
            }
        }
Beispiel #30
0
 public static void QueryContextConnectionInfo(
     SafeDeleteSslContext securityContext,
     ref SslConnectionInfo connectionInfo)
 {
     connectionInfo.UpdateSslConnectionInfo(securityContext.SslContext);
 }
Beispiel #31
0
        public static SecurityStatusPal EncryptMessage(
            SafeDeleteContext securityContext,
            ReadOnlyMemory <byte> input,
            int headerSize,
            int trailerSize,
            ref byte[] output,
            out int resultSize)
        {
            resultSize = 0;

            Debug.Assert(input.Length > 0, $"{nameof(input.Length)} > 0 since {nameof(CanEncryptEmptyMessage)} is false");

            try
            {
                SafeDeleteSslContext sslContext = (SafeDeleteSslContext)securityContext;
                SafeSslHandle        sslHandle  = sslContext.SslContext;

                unsafe
                {
                    MemoryHandle memHandle = input.Retain(pin: true);
                    try
                    {
                        PAL_TlsIo status;

                        lock (sslHandle)
                        {
                            status = Interop.AppleCrypto.SslWrite(
                                sslHandle,
                                (byte *)memHandle.Pointer,
                                input.Length,
                                out int written);
                        }

                        if (status < 0)
                        {
                            return(new SecurityStatusPal(
                                       SecurityStatusPalErrorCode.InternalError,
                                       Interop.AppleCrypto.CreateExceptionForOSStatus((int)status)));
                        }

                        if (sslContext.BytesReadyForConnection <= output?.Length)
                        {
                            resultSize = sslContext.ReadPendingWrites(output, 0, output.Length);
                        }
                        else
                        {
                            output     = sslContext.ReadPendingWrites();
                            resultSize = output.Length;
                        }

                        switch (status)
                        {
                        case PAL_TlsIo.Success:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.OK));

                        case PAL_TlsIo.WouldBlock:
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.ContinueNeeded));

                        default:
                            Debug.Fail($"Unknown status value: {status}");
                            return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError));
                        }
                    }
                    finally
                    {
                        memHandle.Dispose();
                    }
                }
            }
            catch (Exception e)
            {
                return(new SecurityStatusPal(SecurityStatusPalErrorCode.InternalError, e));
            }
        }