stun_rs/attributes/stun/
fingerprint.rs1use crate::attributes::{stunt_attribute, DecodeAttributeValue, EncodeAttributeValue};
2use crate::common::check_buffer_boundaries;
3use crate::context::{AttributeDecoderContext, AttributeEncoderContext};
4use crate::error::{StunError, StunErrorType};
5use crate::{Decode, DecoderContext};
6use byteorder::{BigEndian, ByteOrder};
7
8const FINGERPRINT: u16 = 0x8028;
9const FINGERPRINT_SIZE: usize = 4;
10const FINGERPRINT_XOR_VALUE: u32 = 0x5354_554e;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
16pub struct EncodableFingerprint {}
17
18#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct DecodableFingerprint(u32);
21
22impl DecodableFingerprint {
23 fn validate(&self, input: &[u8]) -> bool {
24 let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC).checksum(input);
25 self.0 == crc32
26 }
27}
28
29impl crate::Decode<'_> for DecodableFingerprint {
30 fn decode(buffer: &[u8]) -> Result<(Self, usize), StunError> {
31 let (value, _) = u32::decode(buffer)?;
32 let crc32 = value ^ FINGERPRINT_XOR_VALUE;
33 Ok((DecodableFingerprint(crc32), FINGERPRINT_SIZE))
34 }
35}
36
37#[derive(Debug, Clone, PartialEq, Eq)]
51pub enum Fingerprint {
52 Encodable(EncodableFingerprint),
54 Decodable(DecodableFingerprint),
56}
57
58impl Default for Fingerprint {
59 fn default() -> Self {
60 Fingerprint::Encodable(EncodableFingerprint {})
61 }
62}
63
64impl From<&[u8; FINGERPRINT_SIZE]> for Fingerprint {
65 fn from(val: &[u8; FINGERPRINT_SIZE]) -> Self {
66 let (attr, _) =
67 DecodableFingerprint::decode(val).expect("Could not decode Fingerprint attribute");
68 Fingerprint::Decodable(attr)
69 }
70}
71
72impl From<[u8; FINGERPRINT_SIZE]> for Fingerprint {
73 fn from(val: [u8; FINGERPRINT_SIZE]) -> Self {
74 Fingerprint::from(&val)
75 }
76}
77
78impl EncodeAttributeValue for Fingerprint {
79 fn encode(&self, mut ctx: AttributeEncoderContext) -> Result<usize, StunError> {
80 match self {
81 Fingerprint::Encodable(_) => {
82 let raw_value = ctx.raw_value_mut();
83 check_buffer_boundaries(raw_value, FINGERPRINT_SIZE)?;
84 raw_value[0..FINGERPRINT_SIZE]
85 .iter_mut()
86 .for_each(|v| *v = 0);
87 Ok(FINGERPRINT_SIZE)
88 }
89 _ => Err(StunError::new(
90 StunErrorType::InvalidParam,
91 "Not encodable attribute",
92 )),
93 }
94 }
95
96 fn post_encode(&self, mut ctx: AttributeEncoderContext) -> Result<(), StunError> {
97 match self {
98 Fingerprint::Encodable(_) => {
99 check_buffer_boundaries(ctx.raw_value(), FINGERPRINT_SIZE)?;
100 let crc32 = crc::Crc::<u32>::new(&crc::CRC_32_ISO_HDLC)
101 .checksum(ctx.encoded_message())
102 ^ FINGERPRINT_XOR_VALUE;
103 BigEndian::write_u32(ctx.raw_value_mut(), crc32);
104 Ok(())
105 }
106 _ => Err(StunError::new(
107 StunErrorType::InvalidParam,
108 "Not encodable attribute",
109 )),
110 }
111 }
112}
113
114impl DecodeAttributeValue for Fingerprint {
115 fn decode(ctx: AttributeDecoderContext) -> Result<(Self, usize), crate::StunError> {
116 let (val, size) = DecodableFingerprint::decode(ctx.raw_value())?;
117 Ok((Fingerprint::Decodable(val), size))
118 }
119}
120
121impl crate::attributes::Verifiable for Fingerprint {
122 fn verify(&self, input: &[u8], _cxt: &DecoderContext) -> bool {
123 self.validate(input)
124 }
125}
126
127impl crate::attributes::AsVerifiable for Fingerprint {
128 fn as_verifiable_ref(&self) -> Option<&dyn crate::attributes::Verifiable> {
129 Some(self)
130 }
131}
132
133impl Fingerprint {
134 pub fn validate(&self, input: &[u8]) -> bool {
140 match self {
141 Fingerprint::Decodable(attr) => attr.validate(input),
142 _ => false,
143 }
144 }
145}
146stunt_attribute!(Fingerprint, FINGERPRINT);
147
148#[cfg(test)]
149mod tests {
150 use super::*;
151 use crate::attributes::EncodeAttributeValue;
152 use crate::StunAttribute;
153
154 #[test]
155 fn encode_fingerprint() {
156 let input = &stun_vectors::SAMPLE_IPV4_RESPONSE[..72];
157 let mut output: [u8; 4] = [0xff; 4];
158 let ctx = AttributeEncoderContext::new(None, input, &mut output);
159
160 let fingerprint = Fingerprint::default();
161 let size = fingerprint
162 .encode(ctx)
163 .expect("Could not encode Fingerprint");
164
165 assert_eq!(size, FINGERPRINT_SIZE);
166 output.iter().for_each(|x| assert_eq!(*x, 0x00));
168
169 let ctx = AttributeEncoderContext::new(None, input, &mut output[..size]);
170 fingerprint
172 .post_encode(ctx)
173 .expect("Could not encode Fingerprint");
174
175 assert_eq!(output, [0xc0, 0x7d, 0x4c, 0x96]);
176
177 let fingerprint = Fingerprint::from([0xc0, 0x7d, 0x4c, 0x96]);
179 let ctx = AttributeEncoderContext::new(None, input, &mut output);
180 let error = fingerprint
181 .encode(ctx)
182 .expect_err("Expected error to encode a decodable fingerprint");
183 assert_eq!(error, StunErrorType::InvalidParam);
184
185 let ctx = AttributeEncoderContext::new(None, input, &mut output);
186 let error = fingerprint
187 .post_encode(ctx)
188 .expect_err("Expected error to encode a decodable fingerprint");
189 assert_eq!(error, StunErrorType::InvalidParam);
190 }
191
192 #[test]
193 fn validate_fingerprint() {
194 let input = crate::get_input_text::<Fingerprint>(&stun_vectors::SAMPLE_IPV4_RESPONSE)
195 .expect("Can not get input buffer");
196
197 let fingerprint = Fingerprint::from([0xc0, 0x7d, 0x4c, 0x96]);
198 let _val = format!("{:?}", fingerprint);
199
200 assert!(fingerprint.validate(&input));
201
202 let fingerprint = Fingerprint::default();
203 assert!(!fingerprint.validate(&input));
204 }
205
206 #[test]
207 fn fingerprint_stunt_attribute() {
208 let attr = StunAttribute::Fingerprint(Fingerprint::default());
209 assert!(attr.is_fingerprint());
210 assert!(attr.as_fingerprint().is_ok());
211 assert!(attr.as_unknown().is_err());
212
213 assert!(!attr.attribute_type().is_comprehension_required());
214 assert!(attr.attribute_type().is_comprehension_optional());
215
216 let dbg_fmt = format!("{:?}", attr);
217 assert_eq!("Fingerprint(Encodable(EncodableFingerprint))", dbg_fmt);
218 }
219}