/// <summary> /// Calls VerifySignature SSPI API function to ensure that given signature /// is correct. /// Throws an exception if the call fails. /// </summary> /// <param name="phContext">Established security context handle.</param> /// <param name="contentBuffer">Content to check the signature for.</param> /// <param name="signature">Stream containing the signature.</param> public static void VerifySignature(SspiApi.SecHandle phContext, byte[] contentBuffer, byte[] signature) { SspiApi.SecBufferDescNative secDesc = new SspiApi.SecBufferDescNative(); SspiApi.SecBufferNative[] secBuffers = new SspiApi.SecBufferNative[2]; using (GCHandleKeeper pinnedSignature = new GCHandleKeeper(signature, GCHandleType.Pinned)) { // the first contains the signature secBuffers[0].BufferType = SspiApi.SECBUFFER_TOKEN; secBuffers[0].cbBuffer = signature.Length; secBuffers[0].pvBuffer = pinnedSignature.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedContentBuffer = new GCHandleKeeper(contentBuffer, GCHandleType.Pinned)) { // and pin it for signing secBuffers[1].BufferType = SspiApi.SECBUFFER_DATA; secBuffers[1].cbBuffer = contentBuffer.Length; secBuffers[1].pvBuffer = pinnedContentBuffer.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedSecBuffers = new GCHandleKeeper(secBuffers, GCHandleType.Pinned)) { // setup descriptor secDesc.ulVersion = SspiApi.SECBUFFER_VERSION; secDesc.cBuffers = 2; secDesc.pBuffers = pinnedSecBuffers.GCHandle.AddrOfPinnedObject(); int result = 0; int pfQOP = 0; if (_isNT) result = VerifySignature_NT(phContext, ref secDesc, 0, ref pfQOP); else result = VerifySignature__(phContext, ref secDesc, 0, ref pfQOP); if (result != SspiApi.SEC_E_OK) throw GenuineExceptions.Get_Windows_SspiError(result); } // pin sec buffers } // pin the content buffer } // pin the signature buffer }
/// <summary> /// Calls EncryptMessage SSPI API function. /// Throws an exception if the call fails. /// </summary> /// <param name="phContext">Established security context handle.</param> /// <param name="sourceContent">Source data.</param> /// <param name="outputContent">Writer to write encrypted data to.</param> /// <param name="secPkgContext_Sizes">Current package's sizes.</param> public static void EncryptMessage(SspiApi.SecHandle phContext, Stream sourceContent, BinaryWriter outputContent, ref SecPkgContext_Sizes secPkgContext_Sizes) { SspiApi.SecBufferDescNative secDesc = new SspiApi.SecBufferDescNative(); // for token, data and padding SspiApi.SecBufferNative[] secBuffers = new SspiApi.SecBufferNative[3]; byte[] signature = new byte[secPkgContext_Sizes.cbSecurityTrailer]; byte[] message = new byte[(int) sourceContent.Length]; byte[] padding = new byte[secPkgContext_Sizes.cbBlockSize]; GenuineUtility.ReadDataFromStream(sourceContent, message, 0, message.Length); using (GCHandleKeeper pinnedSignature = new GCHandleKeeper(signature, GCHandleType.Pinned)) { // the first is for signature secBuffers[0].BufferType = SspiApi.SECBUFFER_TOKEN; secBuffers[0].cbBuffer = signature.Length; secBuffers[0].pvBuffer = pinnedSignature.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedMessage = new GCHandleKeeper(message, GCHandleType.Pinned)) { // the second contains data secBuffers[1].BufferType = SspiApi.SECBUFFER_DATA; secBuffers[1].cbBuffer = message.Length; secBuffers[1].pvBuffer = pinnedMessage.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedPadding = new GCHandleKeeper(padding, GCHandleType.Pinned)) { // the third is for padding secBuffers[2].BufferType = SspiApi.SECBUFFER_PADDING; secBuffers[2].cbBuffer = padding.Length; secBuffers[2].pvBuffer = pinnedPadding.GCHandle.AddrOfPinnedObject(); // setup descriptor secDesc.ulVersion = SspiApi.SECBUFFER_VERSION; secDesc.cBuffers = 3; using (GCHandleKeeper pinnedSecBuffers = new GCHandleKeeper(secBuffers, GCHandleType.Pinned)) { secDesc.pBuffers = pinnedSecBuffers.GCHandle.AddrOfPinnedObject(); // make the call int result = 0; if (_isNT) result = EncryptMessage_NT(phContext, 0, ref secDesc, 0); else result = EncryptMessage__(phContext, 0, ref secDesc, 0); if (result != SspiApi.SEC_E_OK) throw GenuineExceptions.Get_Windows_SspiError(result); } } } } // write sizes outputContent.Write( (int) secBuffers[0].cbBuffer ); outputContent.Write( (int) secBuffers[1].cbBuffer ); outputContent.Write( (int) secBuffers[2].cbBuffer ); // and content outputContent.Write( signature, 0, secBuffers[0].cbBuffer ); outputContent.Write( message, 0, secBuffers[1].cbBuffer ); outputContent.Write( padding, 0, secBuffers[2].cbBuffer ); }
/// <summary> /// Calls MakeSignature SSPI API function and saves obtained signature to /// outputSignature parameter. /// Throws an exception if the call fails. /// </summary> /// <param name="phContext">Established security context handle.</param> /// <param name="contentBuffer">Content to make signature for.</param> /// <param name="outputSignature">Output stream to write signature to.</param> /// <param name="secPkgContext_Sizes">Security context size constants.</param> public static void MakeSignature(SspiApi.SecHandle phContext, byte[] contentBuffer, BinaryWriter outputSignature, ref SecPkgContext_Sizes secPkgContext_Sizes) { SspiApi.SecBufferDescNative secDesc = new SspiApi.SecBufferDescNative(); SspiApi.SecBufferNative[] secBuffers = new SspiApi.SecBufferNative[2]; byte[] signBuffer = new byte[secPkgContext_Sizes.cbMaxSignature]; using (GCHandleKeeper pinnedSignBuffer = new GCHandleKeeper(signBuffer, GCHandleType.Pinned)) { // the first is for getting a sign secBuffers[0].BufferType = SspiApi.SECBUFFER_TOKEN; secBuffers[0].cbBuffer = secPkgContext_Sizes.cbMaxSignature; secBuffers[0].pvBuffer = pinnedSignBuffer.GCHandle.AddrOfPinnedObject(); // pin contentBuffer secBuffers[1].BufferType = SspiApi.SECBUFFER_DATA; secBuffers[1].cbBuffer = (int) contentBuffer.Length; using (GCHandleKeeper pinnedContentBuffer = new GCHandleKeeper(contentBuffer, GCHandleType.Pinned)) { secBuffers[1].pvBuffer = pinnedContentBuffer.GCHandle.AddrOfPinnedObject(); // setup descriptor secDesc.ulVersion = SspiApi.SECBUFFER_VERSION; secDesc.cBuffers = 2; using (GCHandleKeeper pinnedSecBuffers = new GCHandleKeeper(secBuffers, GCHandleType.Pinned)) { secDesc.pBuffers = pinnedSecBuffers.GCHandle.AddrOfPinnedObject(); int result = 0; if (_isNT) result = MakeSignature_NT(phContext, 0, ref secDesc, 0); else result = MakeSignature__(phContext, 0, ref secDesc, 0); if (result != SspiApi.SEC_E_OK) throw GenuineExceptions.Get_Windows_SspiError(result); outputSignature.Write(signBuffer, 0, secBuffers[0].cbBuffer); } // pin sec buffers } // pin the content buffer } // pin the signature buffer }
/// <summary> /// Calls DecryptMessage SSPI API function. /// Throws an exception if the call fails. /// </summary> /// <param name="phContext">Established security context handle.</param> /// <param name="sourceContent">Stream containing encrypted data.</param> /// <returns>Stream containing decrypted data.</returns> public static Stream DecryptMessage(SspiApi.SecHandle phContext, BinaryReader sourceContent) { SspiApi.SecBufferDescNative secDesc = new SspiApi.SecBufferDescNative(); // for token, data and padding SspiApi.SecBufferNative[] secBuffers = new SspiApi.SecBufferNative[3]; // read sizes int signatureSize = sourceContent.ReadInt32(); int messageSize = sourceContent.ReadInt32(); int paddingSize = sourceContent.ReadInt32(); // allocate buffers byte[] signature = new byte[signatureSize]; byte[] message = new byte[messageSize]; byte[] padding = new byte[paddingSize]; // read content GenuineUtility.ReadDataFromStream(sourceContent.BaseStream, signature, 0, signatureSize); GenuineUtility.ReadDataFromStream(sourceContent.BaseStream, message, 0, messageSize); GenuineUtility.ReadDataFromStream(sourceContent.BaseStream, padding, 0, paddingSize); using (GCHandleKeeper pinnedSignature = new GCHandleKeeper(signature, GCHandleType.Pinned)) { // the first is for signature secBuffers[0].BufferType = SspiApi.SECBUFFER_TOKEN; secBuffers[0].cbBuffer = signatureSize; secBuffers[0].pvBuffer = pinnedSignature.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedMessage = new GCHandleKeeper(message, GCHandleType.Pinned)) { // the second contains data secBuffers[1].BufferType = SspiApi.SECBUFFER_DATA; secBuffers[1].cbBuffer = messageSize; secBuffers[1].pvBuffer = pinnedMessage.GCHandle.AddrOfPinnedObject(); using (GCHandleKeeper pinnedPadding = new GCHandleKeeper(padding, GCHandleType.Pinned)) { // the third is for padding secBuffers[2].BufferType = SspiApi.SECBUFFER_PADDING; secBuffers[2].cbBuffer = paddingSize; secBuffers[2].pvBuffer = pinnedPadding.GCHandle.AddrOfPinnedObject(); // setup descriptor secDesc.ulVersion = SspiApi.SECBUFFER_VERSION; secDesc.cBuffers = 3; using (GCHandleKeeper pinnedSecBuffers = new GCHandleKeeper(secBuffers, GCHandleType.Pinned)) { secDesc.pBuffers = pinnedSecBuffers.GCHandle.AddrOfPinnedObject(); // make the call int result = 0; int pfQOP = 0; if (_isNT) result = DecryptMessage_NT(phContext, ref secDesc, 0, ref pfQOP); else result = DecryptMessage__(phContext, ref secDesc, 0, ref pfQOP); if (result != SspiApi.SEC_E_OK) throw GenuineExceptions.Get_Windows_SspiError(result); } } } } // return the result return new MemoryStream(message, 0, secBuffers[1].cbBuffer, false, true); }