private static void TestCNG(byte[] key, byte[] iv, byte[] aad, byte[] ciphertext, byte[] tag, byte[] plaintext) { using (var algorithm = BCrypt.OpenAlgorithm("AES", "Microsoft Primitive Provider")) { BCrypt.SetProperty(algorithm, "ChainingMode", Encoding.Unicode.GetBytes("ChainingModeGCM")); using (var nativeKey = BCrypt.ImportKey(algorithm, key)) { var authInfo = new BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(); try { // Initialize the padding info structure. authInfo.InitGcm(iv, aad, tag); // For KISS, don't bother with breaking ciphertext into blocks and chaining calls. int outputSize; byte[] output = new byte[ciphertext.Length]; var chainData = new byte[16]; // Block size: 128 bits ErrorCode error = UnsafeNativeMethods.BCryptDecrypt(nativeKey, ciphertext, ciphertext.Length, ref authInfo, chainData, chainData.Length, output, output.Length, out outputSize, 0); if (error == ErrorCode.Success) { System.Diagnostics.Debug.Assert(outputSize == output.Length); // Decryption succeeded without tag mismatch if (plaintext != null && plaintext.SequenceEqual(output)) { testsPassedCNG++; } else { testsFailedCNG++; cngFailureReasons.Add("PT mismatch"); } } else { if (plaintext == null) { testsPassedCNG++; } else { testsFailedCNG++; cngFailureReasons.Add(error.ToString()); } } } finally { authInfo.Dispose(); } } } }
internal static extern ErrorCode BCryptDecrypt(SafeBCryptKeyHandle hKey, [In, MarshalAs(UnmanagedType.LPArray)] byte[] pbInput, int cbInput, [In, Out] ref BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO pPaddingInfo, [In, Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbIV, int cbIV, [Out, MarshalAs(UnmanagedType.LPArray)] byte[] pbOutput, int cbOutput, [Out] out int pcbResult, int dwFlags);