1 // Copyright 2022 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! V0 data element deserialization.
16 //!
17 //! This module only deals with the _contents_ of an advertisement, not the advertisement header.
18 
19 use core::fmt;
20 use core::marker::PhantomData;
21 
22 use crate::legacy::data_elements::tx_power::TxPowerDataElement;
23 use crate::{
24     credential::v0::V0,
25     legacy::{
26         data_elements::{
27             actions,
28             de_type::{DeEncodedLength, DeTypeCode},
29             DataElementDeserializeError, DeserializeDataElement, LengthMapper,
30         },
31         Ciphertext, PacketFlavor,
32     },
33     DeLengthOutOfRange,
34 };
35 use array_view::ArrayView;
36 use ldt_np_adv::{V0IdentityToken, V0Salt, NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN};
37 use nom::{bytes, combinator, number, Finish};
38 
39 #[cfg(test)]
40 mod tests;
41 
42 pub(crate) mod intermediate;
43 
44 use crate::credential::matched::HasIdentityMatch;
45 use crate::legacy::data_elements::actions::ActionsDataElement;
46 use crate::legacy::data_elements::de_type::{DataElementType, DeActualLength};
47 use crate::legacy::Plaintext;
48 /// exposed because the unencrypted case isn't just for intermediate: no further processing is needed
49 pub use intermediate::UnencryptedAdvContents;
50 
51 /// Legacy advertisement parsing errors
52 #[derive(Debug, Clone, Copy, PartialEq, Eq)]
53 pub(crate) enum AdvDeserializeError {
54     /// Header or other structure was invalid
55     InvalidStructure,
56     /// DE contents must not be empty
57     NoDataElements,
58 }
59 
60 /// A data element with content length determined and validated per its type's length rules, but
61 /// no further decoding performed.
62 #[derive(Debug, PartialEq, Eq)]
63 pub(in crate::legacy) struct RawDataElement<'d, D: DataElementDeserializer> {
64     pub(in crate::legacy) de_type: D::DeTypeDisambiguator,
65     /// Byte array payload of the data element, without the DE header.
66     pub(in crate::legacy) contents: &'d [u8],
67 }
68 
69 impl<'d, D: DataElementDeserializer> RawDataElement<'d, D> {
70     /// Parse an individual DE into its header and contents.
parse(input: &'d [u8]) -> nom::IResult<&[u8], Self, DataElementDeserializeError>71     fn parse(input: &'d [u8]) -> nom::IResult<&[u8], Self, DataElementDeserializeError> {
72         let (input, (de_type, actual_len)) = combinator::map_res(
73             combinator::map_opt(number::complete::u8, |de_header| {
74                 // header: LLLLTTTT
75                 let len = de_header >> 4;
76                 let de_type_num = de_header & 0x0F;
77 
78                 // these can't fail since both inputs are 4 bits and will fit
79                 DeTypeCode::try_from(de_type_num).ok().and_then(|de_type| {
80                     DeEncodedLength::try_from(len).ok().map(|encoded_len| (de_type, encoded_len))
81                 })
82             }),
83             |(de_type, encoded_len)| {
84                 D::map_encoded_len_to_actual_len(de_type, encoded_len).map_err(|e| match e {
85                     LengthError::InvalidLength => {
86                         DataElementDeserializeError::InvalidDeLength { de_type, len: encoded_len }
87                     }
88                     LengthError::InvalidType => {
89                         DataElementDeserializeError::InvalidDeType { de_type }
90                     }
91                 })
92             },
93         )(input)?;
94 
95         combinator::map(bytes::complete::take(actual_len.as_usize()), move |contents| {
96             RawDataElement { de_type, contents }
97         })(input)
98     }
99 }
100 
101 /// An iterator that parses the given data elements iteratively. In environments
102 /// where memory is not severely constrained, it is usually safer to collect
103 /// this into `Result<Vec<DeserializedDataElement>>` so the validity of the whole
104 /// advertisement can be checked before proceeding with further processing.
105 #[derive(Clone, Debug, PartialEq, Eq)]
106 pub struct DeIterator<'d, F> {
107     delegate: GenericDeIterator<'d, F, StandardDeserializer>,
108 }
109 
110 impl<'d, F> DeIterator<'d, F> {
new(data: &'d [u8]) -> Self111     pub(in crate::legacy) fn new(data: &'d [u8]) -> Self {
112         Self { delegate: GenericDeIterator::new(data) }
113     }
114 }
115 
116 impl<'d, F: PacketFlavor> Iterator for DeIterator<'d, F> {
117     type Item = Result<DeserializedDataElement<F>, DataElementDeserializeError>;
118 
next(&mut self) -> Option<Self::Item>119     fn next(&mut self) -> Option<Self::Item> {
120         self.delegate.next()
121     }
122 }
123 
124 /// The generified innards of [DeIterator] so that it's possible to also use test-only
125 /// deserializers.
126 #[derive(Clone, Debug, PartialEq, Eq)]
127 pub(in crate::legacy) struct GenericDeIterator<'d, F, D> {
128     /// Data to be parsed, containing a sequence of data elements in serialized
129     /// form.
130     data: &'d [u8],
131     _flavor_marker: PhantomData<F>,
132     _deser_marker: PhantomData<D>,
133 }
134 
135 impl<'d, F, D> GenericDeIterator<'d, F, D> {
new(data: &'d [u8]) -> Self136     fn new(data: &'d [u8]) -> Self {
137         Self { data, _flavor_marker: Default::default(), _deser_marker: Default::default() }
138     }
139 }
140 
141 impl<'d, F: PacketFlavor, D: DataElementDeserializer> Iterator for GenericDeIterator<'d, F, D> {
142     type Item = Result<D::Deserialized<F>, DataElementDeserializeError>;
143 
next(&mut self) -> Option<Self::Item>144     fn next(&mut self) -> Option<Self::Item> {
145         if self.data.is_empty() {
146             return None;
147         }
148         let parse_result = combinator::cut(combinator::map_res(
149             RawDataElement::parse,
150             D::deserialize_de,
151         ))(self.data);
152 
153         match parse_result.finish() {
154             Ok((rem, de)) => {
155                 self.data = rem;
156                 Some(Ok(de))
157             }
158             Err(e) => Some(Err(e)),
159         }
160     }
161 }
162 
163 /// Errors that can occur decrypting encrypted advertisements.
164 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
165 pub(crate) enum DecryptError {
166     /// Decrypting or verifying the advertisement ciphertext failed
167     DecryptOrVerifyError,
168 }
169 
170 /// All v0 DE types with deserialized contents.
171 #[derive(Debug, PartialEq, Eq, Clone)]
172 #[allow(missing_docs)]
173 pub enum DeserializedDataElement<F: PacketFlavor> {
174     Actions(actions::ActionsDataElement<F>),
175     TxPower(TxPowerDataElement),
176 }
177 
178 impl<F: PacketFlavor> DeserializedDataElement<F> {
179     /// Returns the DE type as a u8
180     #[cfg(feature = "devtools")]
de_type_code(&self) -> u8181     pub fn de_type_code(&self) -> u8 {
182         match self {
183             DeserializedDataElement::Actions(_) => ActionsDataElement::<F>::DE_TYPE_CODE.as_u8(),
184             DeserializedDataElement::TxPower(_) => TxPowerDataElement::DE_TYPE_CODE.as_u8(),
185         }
186     }
187 
188     /// Returns the serialized contents of the DE
189     #[cfg(feature = "devtools")]
190     #[allow(clippy::unwrap_used)]
de_contents(&self) -> alloc::vec::Vec<u8> where actions::ActionsDataElement<F>: crate::legacy::data_elements::SerializeDataElement<F>,191     pub fn de_contents(&self) -> alloc::vec::Vec<u8>
192     where
193         actions::ActionsDataElement<F>: crate::legacy::data_elements::SerializeDataElement<F>,
194     {
195         use crate::legacy::data_elements::{DataElementSerializationBuffer, SerializeDataElement};
196 
197         let mut sink = DataElementSerializationBuffer::new(super::NP_MAX_ADV_CONTENT_LEN).unwrap();
198         match self {
199             DeserializedDataElement::Actions(a) => a.serialize_contents(&mut sink),
200             DeserializedDataElement::TxPower(t) => {
201                 SerializeDataElement::<F>::serialize_contents(t, &mut sink)
202             }
203         }
204         .unwrap();
205         sink.into_inner().into_inner().as_slice().to_vec()
206     }
207 }
208 
209 /// Contents of an LDT advertisement after decryption.
210 #[derive(Debug, PartialEq, Eq)]
211 pub struct DecryptedAdvContents {
212     identity_token: V0IdentityToken,
213     salt: V0Salt,
214     /// The decrypted data in this advertisement after the identity token.
215     /// This is hopefully a sequence of serialized data elements, but that hasn't been validated
216     /// yet at construction time.
217     data: ArrayView<u8, { NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN }>,
218 }
219 
220 impl DecryptedAdvContents {
221     /// Returns a new DecryptedAdvContents with the provided contents.
222     fn new(
223         metadata_key: V0IdentityToken,
224         salt: V0Salt,
225         data: ArrayView<u8, { NP_LDT_MAX_EFFECTIVE_PAYLOAD_LEN }>,
226     ) -> Self {
227         Self { identity_token: metadata_key, salt, data }
228     }
229 
230     /// Iterator over the data elements in an advertisement, except for any DEs related to resolving
231     /// the identity or otherwise validating the payload (e.g. any identity DEs like Private
232     /// Identity).
data_elements(&self) -> DeIterator<Ciphertext>233     pub fn data_elements(&self) -> DeIterator<Ciphertext> {
234         DeIterator::new(self.data.as_slice())
235     }
236 
237     /// The salt used for decryption of this advertisement.
salt(&self) -> V0Salt238     pub fn salt(&self) -> V0Salt {
239         self.salt
240     }
241 
242     #[cfg(test)]
generic_data_elements<D: DataElementDeserializer>( &self, ) -> GenericDeIterator<Ciphertext, D>243     pub(in crate::legacy) fn generic_data_elements<D: DataElementDeserializer>(
244         &self,
245     ) -> GenericDeIterator<Ciphertext, D> {
246         GenericDeIterator::new(self.data.as_slice())
247     }
248 }
249 
250 impl HasIdentityMatch for DecryptedAdvContents {
251     type Version = V0;
identity_token(&self) -> V0IdentityToken252     fn identity_token(&self) -> V0IdentityToken {
253         self.identity_token
254     }
255 }
256 
257 /// Overall strategy for deserializing adv contents (once decrypted, if applicable) into data
258 /// elements
259 pub(in crate::legacy) trait DataElementDeserializer: Sized {
260     /// Disambiguates the intermediate form of a DE
261     type DeTypeDisambiguator: Copy;
262     /// The fully deserialized form of a DE
263     type Deserialized<F: PacketFlavor>: fmt::Debug + PartialEq + Eq + Clone;
264 
265     /// Map the encoded len found in a DE header to the actual len that should be consumed from the
266     /// advertisement payload
map_encoded_len_to_actual_len( de_type: DeTypeCode, encoded_len: DeEncodedLength, ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError>267     fn map_encoded_len_to_actual_len(
268         de_type: DeTypeCode,
269         encoded_len: DeEncodedLength,
270     ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError>;
271 
272     /// Deserialize into a [Self::Deserialized] to expose DE-type-specific data representations.
273     ///
274     /// Returns `Err` if the contents of the raw DE can't be deserialized into the corresponding
275     /// DE's representation.
deserialize_de<F: PacketFlavor>( raw_de: RawDataElement<Self>, ) -> Result<Self::Deserialized<F>, DataElementDeserializeError>276     fn deserialize_de<F: PacketFlavor>(
277         raw_de: RawDataElement<Self>,
278     ) -> Result<Self::Deserialized<F>, DataElementDeserializeError>;
279 }
280 
281 /// Possible errors when mapping DE encoded lengths to actual lengths
282 pub(in crate::legacy) enum LengthError {
283     /// The DE type was known, but the encoded length was invalid
284     InvalidLength,
285     /// The DE type was not unrecognized
286     InvalidType,
287 }
288 
289 impl From<DeLengthOutOfRange> for LengthError {
from(_value: DeLengthOutOfRange) -> Self290     fn from(_value: DeLengthOutOfRange) -> Self {
291         Self::InvalidLength
292     }
293 }
294 
295 /// The default deserialization strategy that maps type codes to [DataElementType], and deserializes
296 /// to [DeserializedDataElement].
297 #[derive(Debug, PartialEq, Eq, Clone)]
298 struct StandardDeserializer;
299 
300 impl DataElementDeserializer for StandardDeserializer {
301     type DeTypeDisambiguator = DataElementType;
302     type Deserialized<F: PacketFlavor> = DeserializedDataElement<F>;
303 
map_encoded_len_to_actual_len( de_type: DeTypeCode, encoded_len: DeEncodedLength, ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError>304     fn map_encoded_len_to_actual_len(
305         de_type: DeTypeCode,
306         encoded_len: DeEncodedLength,
307     ) -> Result<(Self::DeTypeDisambiguator, DeActualLength), LengthError> {
308         match de_type {
309             TxPowerDataElement::DE_TYPE_CODE => {
310                 <TxPowerDataElement as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
311                     .map_err(|e| e.into())
312                     .map(|l| (DataElementType::TxPower, l))
313             }
314             ActionsDataElement::<Plaintext>::DE_TYPE_CODE => {
315                 <ActionsDataElement<Plaintext> as DeserializeDataElement>::LengthMapper::map_encoded_len_to_actual_len(encoded_len)
316                     .map_err(|e| e.into())
317                     .map(|l| (DataElementType::Actions, l))
318             }
319             _ => Err(LengthError::InvalidType),
320         }
321     }
322 
deserialize_de<F: PacketFlavor>( raw_de: RawDataElement<Self>, ) -> Result<Self::Deserialized<F>, DataElementDeserializeError>323     fn deserialize_de<F: PacketFlavor>(
324         raw_de: RawDataElement<Self>,
325     ) -> Result<Self::Deserialized<F>, DataElementDeserializeError> {
326         match raw_de.de_type {
327             DataElementType::Actions => {
328                 actions::ActionsDataElement::deserialize::<F>(raw_de.contents)
329                     .map(DeserializedDataElement::Actions)
330             }
331             DataElementType::TxPower => TxPowerDataElement::deserialize::<F>(raw_de.contents)
332                 .map(DeserializedDataElement::TxPower),
333         }
334     }
335 }
336