public static int QueryContextAttributes(ref SECURITY_HANDLE phContext,
                                          uint ulAttribute,
                                          out SecPkgContext_Sizes pContextAttributes)
 {
     NotImplemented(MethodBase.GetCurrentMethod());
     pContextAttributes = new SecPkgContext_Sizes {
     };
     return(0);
 }
Beispiel #2
0
        internal static unsafe int Wrap(SafeDeleteContext securityContext, ReadOnlySpan <byte> buffer, [NotNull] ref byte[]?output, bool isConfidential)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            // alloc new output buffer if not supplied or too small
            int resultSize = buffer.Length + sizes.cbMaxSignature;

            if (output == null || output.Length < resultSize)
            {
                output = new byte[resultSize];
            }

            // make a copy of user data for in-place encryption
            buffer.CopyTo(output.AsSpan(sizes.cbMaxSignature, buffer.Length));

            fixed(byte *outputPtr = output)
            {
                // Prepare buffers TOKEN(signature), DATA and Padding.
                Interop.SspiCli.SecBuffer *unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[2];
                Interop.SspiCli.SecBuffer *tokenBuffer     = &unmanagedBuffer[0];
                Interop.SspiCli.SecBuffer *dataBuffer      = &unmanagedBuffer[1];
                tokenBuffer->BufferType = SecurityBufferType.SECBUFFER_TOKEN;
                tokenBuffer->pvBuffer   = (IntPtr)(outputPtr);
                tokenBuffer->cbBuffer   = sizes.cbMaxSignature;
                dataBuffer->BufferType  = SecurityBufferType.SECBUFFER_DATA;
                dataBuffer->pvBuffer    = (IntPtr)(outputPtr + sizes.cbMaxSignature);
                dataBuffer->cbBuffer    = buffer.Length;

                Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(2)
                {
                    pBuffers = unmanagedBuffer
                };

                uint qop       = isConfidential ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
                int  errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(securityContext, ref sdcInOut, qop);

                if (errorCode != 0)
                {
                    Exception e = new Win32Exception(errorCode);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, e);
                    }
                    throw new Win32Exception(errorCode);
                }

                // return signed size
                return(tokenBuffer->cbBuffer + dataBuffer->cbBuffer);
            }
        }
Beispiel #3
0
        public void EnDecryptMessageTest()
        {
            const string msg = "This is the message.";

            using (var hCred = AcqCredHandle(UNISP_NAME, SECPKG_CRED.SECPKG_CRED_OUTBOUND))
                using (var pOut = new SafeSecBufferDesc())
                {
                    pOut.Add(SecBufferType.SECBUFFER_TOKEN);
                    pOut.Add(SecBufferType.SECBUFFER_EMPTY);
                    using (var hCtx = GetSecContext(hCred, pOut, Environment.MachineName))
                        using (var memSz = SafeHGlobalHandle.CreateFromStructure <SecPkgContext_Sizes>())
                        {
                            SecPkgContext_Sizes szs = default;
                            Assert.That(() => szs = QueryContextAttributes <SecPkgContext_Sizes>(hCtx, SECPKG_ATTR.SECPKG_ATTR_SIZES), Throws.Nothing);

                            using (var edesc = new SafeSecBufferDesc())
                            {
                                edesc.Add((int)szs.cbSecurityTrailer, SecBufferType.SECBUFFER_TOKEN);
                                edesc.Add(SecBufferType.SECBUFFER_DATA, msg);
                                edesc.Add((int)szs.cbBlockSize, SecBufferType.SECBUFFER_PADDING);

                                Assert.That(EncryptMessage(hCtx, 0, ref edesc.GetRef(), 0), Is.EqualTo((HRESULT)0));

                                using (var ddesc = new SafeSecBufferDesc())
                                    using (var mem = new SafeHGlobalHandle(edesc[1].cbBuffer + edesc[2].cbBuffer))
                                    {
                                        edesc[1].pvBuffer.CopyTo((IntPtr)mem, edesc[1].cbBuffer);
                                        edesc[2].pvBuffer.CopyTo(((IntPtr)mem).Offset(edesc[1].cbBuffer), edesc[2].cbBuffer);

                                        ddesc.Add(new SecBuffer(SecBufferType.SECBUFFER_STREAM)
                                        {
                                            pvBuffer = (IntPtr)mem, cbBuffer = mem.Size
                                        });
                                        ddesc.Add(new SecBuffer(SecBufferType.SECBUFFER_DATA));

                                        Assert.That(DecryptMessage(hCtx, ref ddesc.GetRef(), 0, out _), Is.EqualTo((HRESULT)0));
                                        Assert.That(StringHelper.GetString(ddesc[1].pvBuffer, CharSet.Unicode, ddesc[1].cbBuffer), Is.EqualTo(msg));
                                    }
                            }
                        }
                }
        }
Beispiel #4
0
        internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, [AllowNull] ref byte[] output)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            // alloc new output buffer if not supplied or too small
            int resultSize = count + sizes.cbMaxSignature;

            if (output == null || output.Length < resultSize)
            {
                output = new byte[resultSize];
            }

            // make a copy of user data for in-place encryption
            Buffer.BlockCopy(buffer, offset, output, sizes.cbMaxSignature, count);

            // setup security buffers for ssp call
#if NETSTANDARD2_0
            Span <SecurityBuffer> securityBuffer = new SecurityBuffer[2];
#else
            TwoSecurityBuffers    stackBuffer    = default;
            Span <SecurityBuffer> securityBuffer = MemoryMarshal.CreateSpan(ref stackBuffer._item0, 2);
#endif
            securityBuffer[0] = new SecurityBuffer(output, 0, sizes.cbMaxSignature, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, sizes.cbMaxSignature, count, SecurityBufferType.SECBUFFER_DATA);

            // call SSP Function
            int errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);

            // throw if error
            if (errorCode != 0)
            {
                NetEventSource.Info($"MakeSignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}");
                throw new Win32Exception(errorCode);
            }

            // return signed size
            return(securityBuffer[0].size + securityBuffer[1].size);
        }
        internal static int MakeSignature(SafeDeleteContext securityContext, byte[] buffer, int offset, int count, ref byte[] output)
        {
            SecPkgContext_Sizes sizes = SSPIWrapper.QueryContextAttributes(
                GlobalSSPI.SSPIAuth,
                securityContext,
                Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES
                ) as SecPkgContext_Sizes;

            // alloc new output buffer if not supplied or too small
            int resultSize = count + sizes.cbMaxSignature;

            if (output == null || output.Length < resultSize)
            {
                output = new byte[resultSize];
            }

            // make a copy of user data for in-place encryption
            Buffer.BlockCopy(buffer, offset, output, sizes.cbMaxSignature, count);

            // setup security buffers for ssp call
            SecurityBuffer[] securityBuffer = new SecurityBuffer[2];
            securityBuffer[0] = new SecurityBuffer(output, 0, sizes.cbMaxSignature, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, sizes.cbMaxSignature, count, SecurityBufferType.SECBUFFER_DATA);

            // call SSP Function
            int errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);

            // throw if error
            if (errorCode != 0)
            {
                NetEventSource.Info($"MakeSignature threw error: {errorCode.ToString("x", NumberFormatInfo.InvariantInfo)}");
                throw new Win32Exception(errorCode);
            }

            // return signed size
            return(securityBuffer[0].size + securityBuffer[1].size);
        }
Beispiel #6
0
        internal static int Encrypt(
            SafeDeleteContext securityContext,
            byte[] buffer,
            int offset,
            int count,
            bool isConfidential,
            bool isNtlm,
            ref byte[] output,
            uint sequenceNumber)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            try
            {
                int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer);

                if (count > maxCount || count < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount));
                }
            }
            catch (Exception e) when(!ExceptionCheck.IsFatal(e))
            {
                NetEventSource.Fail(null, "Arguments out of range.");
                throw;
            }

            int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            Buffer.BlockCopy(buffer, offset, output, 4 + sizes.cbSecurityTrailer, count);

            // Prepare buffers TOKEN(signature), DATA and Padding.
            ThreeSecurityBuffers buffers = default;
            var securityBuffer           = MemoryMarshal.CreateSpan(ref buffers._item0, 3);

            securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA);
            securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING);

            int errorCode;

            if (isConfidential)
            {
                errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber);
            }
            else
            {
                if (isNtlm)
                {
                    securityBuffer[1].type |= SecurityBufferType.SECBUFFER_READONLY;
                }

                errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);
            }

            if (errorCode != 0)
            {
                Exception e = new Win32Exception(errorCode);
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Error(null, e);
                }
                throw e;
            }

            // Compacting the result.
            resultSize = securityBuffer[0].size;
            bool forceCopy = false;

            if (resultSize != sizes.cbSecurityTrailer)
            {
                forceCopy = true;
                Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size);
            }

            resultSize += securityBuffer[1].size;
            if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.cbSecurityTrailer)))
            {
                Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size);
            }

            resultSize += securityBuffer[2].size;
            unchecked
            {
                output[0] = (byte)((resultSize) & 0xFF);
                output[1] = (byte)(((resultSize) >> 8) & 0xFF);
                output[2] = (byte)(((resultSize) >> 16) & 0xFF);
                output[3] = (byte)(((resultSize) >> 24) & 0xFF);
            }

            return(resultSize + 4);
        }
Beispiel #7
0
        internal static unsafe int Encrypt(
            SafeDeleteContext securityContext,
            ReadOnlySpan <byte> buffer,
            bool isConfidential,
            bool isNtlm,
            [NotNull] ref byte[]?output)
        {
            SecPkgContext_Sizes sizes = default;
            bool success = SSPIWrapper.QueryBlittableContextAttributes(GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES, ref sizes);

            Debug.Assert(success);

            int maxCount = checked (int.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer);

            if (buffer.Length > maxCount)
            {
                throw new ArgumentOutOfRangeException(nameof(buffer.Length), SR.Format(SR.net_io_out_range, maxCount));
            }

            int resultSize = buffer.Length + sizes.cbSecurityTrailer + sizes.cbBlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            buffer.CopyTo(output.AsSpan(4 + sizes.cbSecurityTrailer));

            fixed(byte *outputPtr = output)
            {
                // Prepare buffers TOKEN(signature), DATA and Padding.
                Interop.SspiCli.SecBuffer *unmanagedBuffer = stackalloc Interop.SspiCli.SecBuffer[3];
                Interop.SspiCli.SecBuffer *tokenBuffer     = &unmanagedBuffer[0];
                Interop.SspiCli.SecBuffer *dataBuffer      = &unmanagedBuffer[1];
                Interop.SspiCli.SecBuffer *paddingBuffer   = &unmanagedBuffer[2];
                tokenBuffer->BufferType   = SecurityBufferType.SECBUFFER_TOKEN;
                tokenBuffer->pvBuffer     = (IntPtr)(outputPtr + 4);
                tokenBuffer->cbBuffer     = sizes.cbSecurityTrailer;
                dataBuffer->BufferType    = SecurityBufferType.SECBUFFER_DATA;
                dataBuffer->pvBuffer      = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer);
                dataBuffer->cbBuffer      = buffer.Length;
                paddingBuffer->BufferType = SecurityBufferType.SECBUFFER_PADDING;
                paddingBuffer->pvBuffer   = (IntPtr)(outputPtr + 4 + sizes.cbSecurityTrailer + buffer.Length);
                paddingBuffer->cbBuffer   = sizes.cbBlockSize;

                Interop.SspiCli.SecBufferDesc sdcInOut = new Interop.SspiCli.SecBufferDesc(3)
                {
                    pBuffers = unmanagedBuffer
                };

                if (isNtlm && !isConfidential)
                {
                    dataBuffer->BufferType |= SecurityBufferType.SECBUFFER_READONLY;
                }

                uint qop       = isConfidential ? 0 : Interop.SspiCli.SECQOP_WRAP_NO_ENCRYPT;
                int  errorCode = GlobalSSPI.SSPIAuth.EncryptMessage(securityContext, ref sdcInOut, qop);

                if (errorCode != 0)
                {
                    Exception e = new Win32Exception(errorCode);
                    if (NetEventSource.Log.IsEnabled())
                    {
                        NetEventSource.Error(null, e);
                    }
                    throw new Win32Exception(errorCode);
                }

                // Compacting the result.
                resultSize = tokenBuffer->cbBuffer;
                bool forceCopy = false;

                if (resultSize != sizes.cbSecurityTrailer)
                {
                    forceCopy = true;
                    output.AsSpan(4 + sizes.cbSecurityTrailer, dataBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, dataBuffer->cbBuffer));
                }

                resultSize += dataBuffer->cbBuffer;
                if (paddingBuffer->cbBuffer != 0 && (forceCopy || resultSize != (buffer.Length + sizes.cbSecurityTrailer)))
                {
                    output.AsSpan(4 + sizes.cbSecurityTrailer + buffer.Length, paddingBuffer->cbBuffer).CopyTo(output.AsSpan(4 + resultSize, paddingBuffer->cbBuffer));
                }

                resultSize += paddingBuffer->cbBuffer;
                BinaryPrimitives.WriteInt32LittleEndian(output, resultSize);

                return(resultSize + 4);
            }
        }
Beispiel #8
0
 public static extern int QueryContextAttributes(ref SECURITY_HANDLE phContext,
                                                 uint ulAttribute,
                                                 out SecPkgContext_Sizes pContextAttributes);
 public static extern int QueryContextAttributes(ref SECURITY_HANDLE phContext,
                                                 uint ulAttribute,
                                                 out SecPkgContext_Sizes pContextAttributes);
        internal static int Encrypt(
            SafeDeleteContext securityContext,
            byte[] buffer,
            int offset,
            int count,
            bool isConfidential,
            bool isNtlm,
            ref byte[] output,
            uint sequenceNumber)
        {
            SecPkgContext_Sizes sizes = SSPIWrapper.QueryContextAttributes(
                GlobalSSPI.SSPIAuth,
                securityContext,
                Interop.SspiCli.ContextAttribute.SECPKG_ATTR_SIZES
                ) as SecPkgContext_Sizes;

            try
            {
                int maxCount = checked (Int32.MaxValue - 4 - sizes.cbBlockSize - sizes.cbSecurityTrailer);

                if (count > maxCount || count < 0)
                {
                    throw new ArgumentOutOfRangeException(nameof(count), SR.Format(SR.net_io_out_range, maxCount));
                }
            }
            catch (Exception e)
            {
                if (!ExceptionCheck.IsFatal(e))
                {
                    if (GlobalLog.IsEnabled)
                    {
                        GlobalLog.Assert("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range.");
                    }

                    Debug.Fail("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt", "Arguments out of range.");
                }

                throw;
            }

            int resultSize = count + sizes.cbSecurityTrailer + sizes.cbBlockSize;

            if (output == null || output.Length < resultSize + 4)
            {
                output = new byte[resultSize + 4];
            }

            // Make a copy of user data for in-place encryption.
            Buffer.BlockCopy(buffer, offset, output, 4 + sizes.cbSecurityTrailer, count);

            // Prepare buffers TOKEN(signature), DATA and Padding.
            var securityBuffer = new SecurityBuffer[3];

            securityBuffer[0] = new SecurityBuffer(output, 4, sizes.cbSecurityTrailer, SecurityBufferType.SECBUFFER_TOKEN);
            securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer, count, SecurityBufferType.SECBUFFER_DATA);
            securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.cbSecurityTrailer + count, sizes.cbBlockSize, SecurityBufferType.SECBUFFER_PADDING);

            int errorCode;

            if (isConfidential)
            {
                errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber);
            }
            else
            {
                if (isNtlm)
                {
                    securityBuffer[1].type |= SecurityBufferType.SECBUFFER_READONLY;
                }

                errorCode = SSPIWrapper.MakeSignature(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, 0);
            }

            if (errorCode != 0)
            {
                if (GlobalLog.IsEnabled)
                {
                    GlobalLog.Print("NTAuthentication#" + LoggingHash.HashString(securityContext) + "::Encrypt() throw Error = " + errorCode.ToString("x", NumberFormatInfo.InvariantInfo));
                }
                throw new Win32Exception(errorCode);
            }

            // Compacting the result.
            resultSize = securityBuffer[0].size;
            bool forceCopy = false;

            if (resultSize != sizes.cbSecurityTrailer)
            {
                forceCopy = true;
                Buffer.BlockCopy(output, securityBuffer[1].offset, output, 4 + resultSize, securityBuffer[1].size);
            }

            resultSize += securityBuffer[1].size;
            if (securityBuffer[2].size != 0 && (forceCopy || resultSize != (count + sizes.cbSecurityTrailer)))
            {
                Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size);
            }

            resultSize += securityBuffer[2].size;
            unchecked
            {
                output[0] = (byte)((resultSize) & 0xFF);
                output[1] = (byte)(((resultSize) >> 8) & 0xFF);
                output[2] = (byte)(((resultSize) >> 16) & 0xFF);
                output[3] = (byte)(((resultSize) >> 24) & 0xFF);
            }

            return(resultSize + 4);
        }