private static byte[] Encrypt(ulong sessionId, Smb2CryptoInfo cryptoInfo, Smb2Role role, Smb2Packet originalPacket) { Packet_Header header; if (originalPacket is Smb2SinglePacket) { header = (originalPacket as Smb2SinglePacket).Header; } else { header = (originalPacket as Smb2CompoundPacket).Packets[0].Header; } // Encrypt all messages after session setup if global encryption enabled. // Encrypt all messages after tree connect if global encryption disabled but share encryption enabled. if ((cryptoInfo.EnableSessionEncryption || (cryptoInfo.EnableTreeEncryption.Contains(header.TreeId) && header.Command != Smb2Command.TREE_CONNECT ) ) ) { using (var bcrypt = new BCryptAlgorithm("AES")) { byte[] originalBinary = originalPacket.ToBytes(); Transform_Header transformHeader = new Transform_Header { ProtocolId = Smb2Consts.ProtocolIdInTransformHeader, OriginalMessageSize = (uint)originalBinary.Length, SessionId = sessionId, Signature = new byte[16] }; if (cryptoInfo.Dialect == DialectRevision.Smb311) { transformHeader.Flags = TransformHeaderFlags.Encrypted; } else { transformHeader.EncryptionAlgorithm = EncryptionAlgorithm.ENCRYPTION_AES128_CCM; } byte[] tag; int nonceLength = 0; BCryptCipherMode mode = BCryptCipherMode.NotAvailable; GetCryptoParams(cryptoInfo, CryptoOperationType.Encrypt, out mode, out nonceLength); bcrypt.Mode = mode; bcrypt.Key = role == Smb2Role.Server ? cryptoInfo.ServerOutKey : cryptoInfo.ServerInKey; // The reserved field (5 bytes for CCM, 4 bytes for GCM) must be set to zero. byte[] nonce = new byte[16]; Buffer.BlockCopy(Guid.NewGuid().ToByteArray(), 0, nonce, 0, nonceLength); transformHeader.Nonce = new Guid(nonce); byte[] output = bcrypt.Encrypt( originalBinary, transformHeader.Nonce.ToByteArray().Take(nonceLength).ToArray(), // Use the fields including and after Nonce field as auth data Smb2Utility.MarshalStructure(transformHeader).Skip(20).ToArray(), // Signature is 16 bytes in length 16, out tag); transformHeader.Signature = tag; return(Smb2Utility.MarshalStructure(transformHeader).Concat(output).ToArray()); } } // Return null if the message is not required to be encrypted. return(null); }