/// <summary> /// Encrypts a block of data with cipher mode info specified. /// </summary> /// <param name="input"> /// The input to be encrypted. /// </param> /// <param name="nonce"> /// Nonce. /// </param> /// <param name="authData"> /// Auth data. /// </param> /// <param name="tagLength"> /// Length of tag. /// </param> /// <param name="tag"> /// Tag. /// </param> /// <returns> /// Encrypted output. /// </returns> public byte[] Encrypt(byte[] input, byte[] nonce, byte[] authData, int tagLength, out byte[] tag) { if (input == null) throw new ArgumentNullException("input"); ValidateKeyExists(); tag = new byte[tagLength]; IntPtr pbInfo = IntPtr.Zero; BcryptAuthenticatedCipherModeInfo info = new BcryptAuthenticatedCipherModeInfo(); try { if (nonce != null || authData != null || tagLength > 0) { info = new BcryptAuthenticatedCipherModeInfo { cbSize = (uint)Marshal.SizeOf(typeof(BcryptAuthenticatedCipherModeInfo)), dwInfoVersion = 1, }; if (nonce != null) { info.cbNonce = (uint)nonce.Length; info.pbNonce = Marshal.AllocHGlobal(nonce.Length); Marshal.Copy(nonce, 0, info.pbNonce, nonce.Length); } if (authData != null) { info.cbAuthData = (uint)authData.Length; info.pbAuthData = Marshal.AllocHGlobal(authData.Length); Marshal.Copy(authData, 0, info.pbAuthData, authData.Length); } if (tagLength > 0) { info.cbTag = (uint)tagLength; info.pbTag = Marshal.AllocHGlobal(tagLength); } info.pbMacContext = IntPtr.Zero; info.cbMacContext = 0; info.cbAAD = 0; info.cbData = 0; info.dwFlags = 0; pbInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(BcryptAuthenticatedCipherModeInfo))); Marshal.StructureToPtr(info, pbInfo, false); } uint cbOutput; uint status = NativeMethods.BCryptEncrypt( hKey, input, (uint)input.Length, pbInfo, null, 0, null, 0, out cbOutput, 0); if (status != (uint)NtStatus.STATUS_SUCCESS) { throw new CryptographicException(GetErrorNameFromCode(status)); } byte[] output = new byte[cbOutput]; status = NativeMethods.BCryptEncrypt( hKey, input, (uint)input.Length, pbInfo, null, 0, output, cbOutput, out cbOutput, 0); if (status != (uint)NtStatus.STATUS_SUCCESS) { throw new CryptographicException(GetErrorNameFromCode(status)); } return output; } finally { if (pbInfo != IntPtr.Zero) { Marshal.Copy(info.pbTag, tag, 0, tagLength); Marshal.FreeHGlobal(info.pbNonce); Marshal.FreeHGlobal(info.pbAuthData); Marshal.FreeHGlobal(info.pbTag); Marshal.FreeHGlobal(pbInfo); } } }