internal BCryptAuthenticatedSymmetricCryptoTransform(SafeBCryptAlgorithmHandle algorithm, byte[] key, byte[] nonce, byte[] authenticatedData, byte[] tag, bool chainingSupported) { Debug.Assert(algorithm != null, "algorithm != null"); Debug.Assert(!algorithm.IsClosed && !algorithm.IsInvalid, "!algorithm.IsClosed && !algorithm.IsInvalid"); if (key == null) { throw new ArgumentNullException("key"); } if (tag == null) { throw new ArgumentNullException("tag"); } bool initializationComplete = false; RuntimeHelpers.PrepareConstrainedRegions(); try { m_algorithm = algorithm; m_key = BCryptNative.ImportSymmetricKey(algorithm, key); // Initialize the padding info structure. m_authInfo = new BCryptNative.BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO(); BCryptNative.InitializeAuthnenticatedCipherModeInfo(ref m_authInfo); if (nonce != null) { m_authInfo.cbNonce = nonce.Length; m_authInfo.pbNonce = Marshal.AllocCoTaskMem(m_authInfo.cbNonce); Marshal.Copy(nonce, 0, m_authInfo.pbNonce, m_authInfo.cbNonce); } if (authenticatedData != null) { m_authInfo.cbAuthData = authenticatedData.Length; m_authInfo.pbAuthData = Marshal.AllocCoTaskMem(m_authInfo.cbAuthData); Marshal.Copy(authenticatedData, 0, m_authInfo.pbAuthData, m_authInfo.cbAuthData); } if (chainingSupported) { m_chainingSupported = chainingSupported; m_authInfo.cbMacContext = tag.Length; m_authInfo.pbMacContext = Marshal.AllocCoTaskMem(m_authInfo.cbMacContext); BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT tagLengths = BCryptNative.GetValueTypeProperty <SafeBCryptAlgorithmHandle, BCryptNative.BCRYPT_KEY_LENGTHS_STRUCT>( algorithm, BCryptNative.ObjectPropertyName.AuthTagLength); m_chainData = new byte[tagLengths.dwMaxLength]; } else { m_inputBuffer = new MemoryStream(); } m_authInfo.cbTag = tag.Length; m_authInfo.pbTag = Marshal.AllocCoTaskMem(m_authInfo.cbTag); Marshal.Copy(tag, 0, m_authInfo.pbTag, m_authInfo.cbTag); // Set chaining mode if supported. if (CanChainBlocks) { m_authInfo.dwFlags |= BCryptNative.AuthenticatedCipherModeInfoFlags.ChainCalls; } initializationComplete = true; } finally { // If we failed to complete initialization we may have already allocated some native // resources. Clean those up before leaving the constructor. if (!initializationComplete) { Dispose(); } } }