smb_msg/
encrypted.rs

1//! Encrypted message and header implementation.
2
3use std::io::Cursor;
4
5use binrw::prelude::*;
6use smb_msg_derive::smb_message_binrw;
7const SIGNATURE_SIZE: usize = 16;
8
9/// The nonce used for encryption.
10/// Depending on the encryption algorithm, the nonce may be trimmed to a smaller size when used,
11/// or padded with zeroes to match the required size. When transmitted, the full 16 bytes are used.
12pub type EncryptionNonce = [u8; 16];
13
14/// This header is used by the client or server when sending encrypted messages
15#[smb_message_binrw]
16#[brw(little, magic(b"\xfdSMB"))]
17pub struct EncryptedHeader {
18    /// The 16-byte signature of the message generated using negotiated encryption algorithm
19    pub signature: u128,
20    /// An implementation-specific value assigned for every encrypted message. This MUST NOT be reused for all encrypted messages within a session.
21    pub nonce: EncryptionNonce,
22    /// The size, in bytes, of the SMB2 message.
23    pub original_message_size: u32,
24    reserved: u16,
25    #[bw(calc = 1)]
26    // MUST be set to 1, in SMB3.1.1 because encrypted, in others because encryption algorithm is AES128-CCM (0x1)
27    #[br(assert(_flags == 1))]
28    _flags: u16,
29    /// Uniquely identifies the established session for the command.
30    pub session_id: u64,
31}
32
33impl EncryptedHeader {
34    const MAGIC_SIZE: usize = 4;
35    pub const STRUCTURE_SIZE: usize = 4
36        + size_of::<u128>()
37        + size_of::<EncryptionNonce>()
38        + size_of::<u32>()
39        + size_of::<u16>()
40        + size_of::<u16>()
41        + size_of::<u64>();
42    const AEAD_BYTES_SIZE: usize = Self::STRUCTURE_SIZE - Self::MAGIC_SIZE - SIGNATURE_SIZE;
43
44    /// The bytes to use as the additional data for the AEAD out of this header.
45    /// Make sure to call it after all fields (except signature) are finalized.
46    ///
47    /// Returns (according to MS-SMB2) the bytes of the header, excluding the magic and the signature.
48    pub fn aead_bytes(&self) -> [u8; Self::AEAD_BYTES_SIZE] {
49        let mut cursor = Cursor::new([0u8; Self::STRUCTURE_SIZE]);
50        self.write(&mut cursor).unwrap();
51        cursor.into_inner()[Self::MAGIC_SIZE + SIGNATURE_SIZE..Self::STRUCTURE_SIZE]
52            .try_into()
53            .unwrap()
54    }
55}
56
57/// An entirely encrypted SMB2 message, that includes both the encrypted header and the encrypted message.
58#[smb_message_binrw]
59pub struct EncryptedMessage {
60    pub header: EncryptedHeader,
61    #[br(parse_with = binrw::helpers::until_eof)]
62    pub encrypted_message: Vec<u8>,
63}
64
65#[cfg(test)]
66mod tests {
67    use smb_tests::*;
68
69    use super::*;
70
71    test_binrw! {
72        EncryptedHeader => e0: EncryptedHeader {
73            signature: u128::from_le_bytes([
74                0x92, 0x2e, 0xe8, 0xf2, 0xa0, 0x6e, 0x7a, 0xd4, 0x70, 0x22, 0xd7, 0x1d, 0xb,
75                0x2, 0x6b, 0x11,
76            ]),
77            nonce: [
78                0xa, 0x57, 0x67, 0x55, 0x6d, 0xa0, 0x23, 0x73, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0,
79                0x0, 0x0,
80            ],
81            original_message_size: 104,
82            session_id: 0x300024000055,
83        } => "fd534d42922ee8f2a06e7ad47022d71d0b026b110a5767556da02373010000000000000068000000000001005500002400300000"
84    }
85
86    test_binrw! {
87        EncryptedHeader => e1: EncryptedHeader {
88            signature: u128::from_le_bytes([
89                0x2a, 0x45, 0x6c, 0x5d, 0xd0, 0xc3, 0x2d, 0xd4, 0x47, 0x85, 0x21, 0xf7, 0xf6, 0xa8,
90                0x87, 0x5b,
91            ]),
92            nonce: [
93                0xbe, 0xe6, 0xbf, 0xe5, 0xa1, 0xe6, 0x7b, 0xb1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
94                0x0,
95            ],
96            original_message_size: 248,
97            session_id: 0x0000300024000055,
98        } => "fd534d422a456c5dd0c32dd4478521f7f6a8875bbee6bfe5a1e67bb10000000000000000f8000000000001005500002400300000"
99    }
100}