1 #[cfg(test)]
2 mod fingerprint_test;
3
4 use crate::attributes::ATTR_FINGERPRINT;
5 use crate::checks::*;
6 use crate::error::*;
7 use crate::message::*;
8
9 use crc::{Crc, CRC_32_ISO_HDLC};
10
11 // FingerprintAttr represents FINGERPRINT attribute.
12 //
13 // RFC 5389 Section 15.5
14 pub struct FingerprintAttr;
15
16 // FINGERPRINT is shorthand for FingerprintAttr.
17 //
18 // Example:
19 //
20 // m := New()
21 // FINGERPRINT.add_to(m)
22 pub const FINGERPRINT: FingerprintAttr = FingerprintAttr {};
23
24 pub const FINGERPRINT_XOR_VALUE: u32 = 0x5354554e;
25 pub const FINGERPRINT_SIZE: usize = 4; // 32 bit
26
27 // FingerprintValue returns CRC-32 of b XOR-ed by 0x5354554e.
28 //
29 // The value of the attribute is computed as the CRC-32 of the STUN message
30 // up to (but excluding) the FINGERPRINT attribute itself, XOR'ed with
31 // the 32-bit value 0x5354554e (the XOR helps in cases where an
32 // application packet is also using CRC-32 in it).
fingerprint_value(b: &[u8]) -> u3233 pub fn fingerprint_value(b: &[u8]) -> u32 {
34 let checksum = Crc::<u32>::new(&CRC_32_ISO_HDLC).checksum(b);
35 checksum ^ FINGERPRINT_XOR_VALUE // XOR
36 }
37
38 impl Setter for FingerprintAttr {
39 // add_to adds fingerprint to message.
add_to(&self, m: &mut Message) -> Result<()>40 fn add_to(&self, m: &mut Message) -> Result<()> {
41 let l = m.length;
42 // length in header should include size of fingerprint attribute
43 m.length += (FINGERPRINT_SIZE + ATTRIBUTE_HEADER_SIZE) as u32; // increasing length
44 m.write_length(); // writing Length to Raw
45 let val = fingerprint_value(&m.raw);
46 let b = val.to_be_bytes();
47 m.length = l;
48 m.add(ATTR_FINGERPRINT, &b);
49 Ok(())
50 }
51 }
52
53 impl FingerprintAttr {
54 // Check reads fingerprint value from m and checks it, returning error if any.
55 // Can return *AttrLengthErr, ErrAttributeNotFound, and *CRCMismatch.
check(&self, m: &Message) -> Result<()>56 pub fn check(&self, m: &Message) -> Result<()> {
57 let b = m.get(ATTR_FINGERPRINT)?;
58 check_size(ATTR_FINGERPRINT, b.len(), FINGERPRINT_SIZE)?;
59 let val = u32::from_be_bytes([b[0], b[1], b[2], b[3]]);
60 let attr_start = m.raw.len() - (FINGERPRINT_SIZE + ATTRIBUTE_HEADER_SIZE);
61 let expected = fingerprint_value(&m.raw[..attr_start]);
62 check_fingerprint(val, expected)
63 }
64 }
65