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); }
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); }
internal static int Encrypt( SafeDeleteContext securityContext, byte[] buffer, int offset, int count, bool isConfidential, bool isNtlm, ref byte[] output, uint sequenceNumber) { SecSizes sizes = SSPIWrapper.QueryContextAttributes( GlobalSSPI.SSPIAuth, securityContext, Interop.SspiCli.ContextAttribute.Sizes ) as SecSizes; try { int maxCount = checked (Int32.MaxValue - 4 - sizes.BlockSize - sizes.SecurityTrailer); 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.SecurityTrailer + sizes.BlockSize; 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.SecurityTrailer, count); // Prepare buffers TOKEN(signature), DATA and Padding. var securityBuffer = new SecurityBuffer[3]; securityBuffer[0] = new SecurityBuffer(output, 4, sizes.SecurityTrailer, SecurityBufferType.Token); securityBuffer[1] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer, count, SecurityBufferType.Data); securityBuffer[2] = new SecurityBuffer(output, 4 + sizes.SecurityTrailer + count, sizes.BlockSize, SecurityBufferType.Padding); int errorCode; if (isConfidential) { errorCode = SSPIWrapper.EncryptMessage(GlobalSSPI.SSPIAuth, securityContext, securityBuffer, sequenceNumber); } else { if (isNtlm) { securityBuffer[1].type |= SecurityBufferType.ReadOnlyFlag; } 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.SecurityTrailer) { 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.SecurityTrailer))) { Buffer.BlockCopy(output, securityBuffer[2].offset, output, 4 + resultSize, securityBuffer[2].size); } resultSize += securityBuffer[2].size; unchecked { // TODO (Issue #6063): Should be offset by offset 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); }