public byte[] TransformFinalBlock(byte[] input, int inputOffset, int count) { ulong ivLength = this.iv == null ? 0 : (ulong)this.iv.Length; uint result; ulong outputSize; // Get the required size of the plaintext/ciphertext buffer if (this.isEncrypting) { result = BCryptCore.BCryptEncrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, null, 0, out outputSize, BCryptConstants.BCRYPT_BLOCK_PADDING); if (result != 0) { throw new SystemException("An error was encountered while retrieving the ciphertext size."); } } else { result = BCryptCore.BCryptDecrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, null, 0, out outputSize, BCryptConstants.BCRYPT_BLOCK_PADDING); if (result != 0) { throw new SystemException("An error was encountered while retrieving the plaintext size."); } } byte[] output = new byte[outputSize]; // No padding is used with authenticatied modes // Bypass final block transformation and defer to regular transformation if (this.mode == BlockCipherMode.GCM || this.mode == BlockCipherMode.CCM) { this.TransformBlock(input, inputOffset, output, 0, count); return(output); } ulong pcbResult; if (this.isEncrypting) { result = BCryptCore.BCryptEncrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, output, (ulong)output.Length, out pcbResult, BCryptConstants.BCRYPT_BLOCK_PADDING); if (result != 0) { throw new SystemException("An error was encountered during encryption."); } } else { result = BCryptCore.BCryptDecrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, output, (ulong)output.Length, out pcbResult, BCryptConstants.BCRYPT_BLOCK_PADDING); if (result != 0) { throw new SystemException("An error was encountered during decryption."); } } return(output); }
public static void SetBlockChainingMode(IntPtr hAlgorithmProvider, BlockCipherMode mode) { string chainingModeValue; switch (mode) { case BlockCipherMode.CBC: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_CBC; break; case BlockCipherMode.CCM: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_CCM; break; case BlockCipherMode.CFB: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_CFB; break; case BlockCipherMode.ECB: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_ECB; break; case BlockCipherMode.GCM: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_GCM; break; case BlockCipherMode.Unspecified: chainingModeValue = BCryptConstants.BCRYPT_CHAIN_MODE_NA; break; default: throw new ArgumentException("The specified block cipher chaining mode is not recognized.", nameof(mode)); } GCHandle gcChainingModeValue = GCHandle.Alloc(chainingModeValue, GCHandleType.Pinned); uint result; try { result = BCryptCore.BCryptSetProperty(hAlgorithmProvider, BCryptConstants.BCRYPT_CHAINING_MODE, gcChainingModeValue.AddrOfPinnedObject(), (ulong)chainingModeValue.Length, 0); } finally { gcChainingModeValue.Free(); } if (result != 0) { throw new SystemException("An error was encountered while setting the cipher chaining mode."); } }
public void TransformBlock(byte[] input, int inputOffset, byte[] output, int outputOffset, int count) { ulong pcbResult; ulong ivLength = this.iv == null ? 0 : (ulong)this.iv.Length; if (this.isEncrypting) { uint result = BCryptCore.BCryptEncrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, output, (ulong)output.Length, out pcbResult, BCryptConstants.BCRYPT_NO_PADDING); if (result != 0) { throw new SystemException("An error was encountered during encryption."); } } else { uint result = BCryptCore.BCryptDecrypt(this.hKey, input, (ulong)count, IntPtr.Zero, this.iv, ivLength, output, (ulong)output.Length, out pcbResult, BCryptConstants.BCRYPT_NO_PADDING); if (result != 0) { throw new SystemException("An error was encountered during decryption."); } } }
public BCryptAesTransformer(BlockCipherMode mode, byte[] key, byte[] iv, bool isEncrypting) { this.mode = mode; uint result = BCryptCore.BCryptOpenAlgorithmProvider(out this.hAlgorithmProvider, "AES", null, 0); if (result != 0) { throw new SystemException("An error was encountered while opening the algorithm provider."); } BCryptHelper.SetBlockChainingMode(this.hAlgorithmProvider, mode); result = BCryptCore.BCryptGenerateSymmetricKey(this.hAlgorithmProvider, out this.hKey, null, 0, key, (ulong)key.Length, 0); if (result != 0) { throw new SystemException("An error was encountered while generating a symmetric key."); } this.iv = iv; this.isEncrypting = isEncrypting; }
protected virtual void Dispose(bool disposing) { BCryptCore.BCryptDestroyKey(this.hKey); BCryptCore.BCryptCloseAlgorithmProvider(this.hAlgorithmProvider, 0); }