smb_msg/
encrypted.rs

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