• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 //! The "Actions" data element and associated types.
16 //!
17 //! This DE is somewhat more complex than other DEs. Whether or not it supports a particular flavor
18 //! depends on the actions set, so it has to be treated as two separate types based on which
19 //! flavor type parameter is used.
20 use crate::legacy::data_elements::{DirectMapPredicate, DirectMapper, LengthMapper};
21 use crate::{
22     legacy::{
23         data_elements::{
24             de_type::{DeActualLength, DeEncodedLength, DeTypeCode},
25             DataElementDeserializeError, DataElementSerializationBuffer, DataElementSerializeError,
26             DeserializeDataElement, SerializeDataElement,
27         },
28         PacketFlavor, PacketFlavorEnum,
29     },
30     private::Sealed,
31 };
32 
33 #[cfg(feature = "devtools")]
34 use core::ops::Range;
35 use core::{marker, ops};
36 use nom::{bytes, combinator, error};
37 use sink::Sink;
38 use strum::IntoEnumIterator as _;
39 
40 mod macros;
41 #[cfg(test)]
42 pub(crate) mod tests;
43 
44 /// Actions DE.
45 /// Only as many DE payload bytes will be present as needed to represent all set bits that are encoded,
46 /// with a lower bound of 1 byte in the special case of no set action bits, and an upper bound
47 /// of 3 bytes occupied by the DE payload.
48 #[derive(Debug, PartialEq, Eq, Clone)]
49 pub struct ActionsDataElement<F: PacketFlavor> {
50     /// The action bits
51     pub action: ActionBits<F>,
52 }
53 
54 /// Max length of an actions DE contents
55 pub(crate) const ACTIONS_MAX_LEN: usize = 3;
56 /// Range of valid actual lengths
57 pub(crate) const ACTIONS_VALID_ACTUAL_LEN: ops::RangeInclusive<usize> = 1..=ACTIONS_MAX_LEN;
58 
59 impl<F> ActionsDataElement<F>
60 where
61     F: PacketFlavor,
62 {
63     /// Generic deserialize, not meant to be called directly -- use [DeserializeDataElement] impls instead.
64     #[allow(clippy::assertions_on_constants)]
deserialize(de_contents: &[u8]) -> Result<Self, DataElementDeserializeError>65     fn deserialize(de_contents: &[u8]) -> Result<Self, DataElementDeserializeError> {
66         combinator::all_consuming::<&[u8], _, error::Error<&[u8]>, _>(combinator::map(
67             bytes::complete::take_while_m_n(0, ACTIONS_MAX_LEN, |_| true),
68             |bytes: &[u8]| {
69                 // pack bits into u32 for convenient access
70                 debug_assert!(4 >= ACTIONS_MAX_LEN, "Actions must fit in u32");
71                 let mut action_bytes = [0_u8; 4];
72                 action_bytes[..bytes.len()].copy_from_slice(bytes);
73                 u32::from_be_bytes(action_bytes)
74             },
75         ))(de_contents)
76         .map_err(|_| DataElementDeserializeError::DeserializeError { de_type: Self::DE_TYPE_CODE })
77         .map(|(_remaining, actions)| actions)
78         .and_then(|action_bits_num| {
79             let action = ActionBits::try_from(action_bits_num).map_err(|e| {
80                 DataElementDeserializeError::FlavorNotSupported {
81                     de_type: Self::DE_TYPE_CODE,
82                     flavor: e.flavor,
83                 }
84             })?;
85             Ok(Self { action })
86         })
87     }
88 }
89 
90 impl<F: PacketFlavor> From<ActionBits<F>> for ActionsDataElement<F> {
from(action: ActionBits<F>) -> Self91     fn from(action: ActionBits<F>) -> Self {
92         Self { action }
93     }
94 }
95 
96 impl<F: PacketFlavor> Sealed for ActionsDataElement<F> {}
97 
98 impl<F: PacketFlavor> SerializeDataElement<F> for ActionsDataElement<F> {
de_type_code(&self) -> DeTypeCode99     fn de_type_code(&self) -> DeTypeCode {
100         ActionsDataElement::<F>::DE_TYPE_CODE
101     }
102 
map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength103     fn map_actual_len_to_encoded_len(&self, actual_len: DeActualLength) -> DeEncodedLength {
104         <Self as DeserializeDataElement>::LengthMapper::map_actual_len_to_encoded_len(actual_len)
105     }
106 
serialize_contents( &self, sink: &mut DataElementSerializationBuffer, ) -> Result<(), DataElementSerializeError>107     fn serialize_contents(
108         &self,
109         sink: &mut DataElementSerializationBuffer,
110     ) -> Result<(), DataElementSerializeError> {
111         let used = self.action.bytes_used();
112         sink.try_extend_from_slice(&self.action.bits.to_be_bytes()[..used])
113             .ok_or(DataElementSerializeError::InsufficientSpace)
114     }
115 }
116 
117 impl<E: PacketFlavor> DeserializeDataElement for ActionsDataElement<E> {
118     const DE_TYPE_CODE: DeTypeCode = match DeTypeCode::try_from(0b0110) {
119         Ok(t) => t,
120         Err(_) => unreachable!(),
121     };
122 
123     type LengthMapper = DirectMapper<ActionsLengthPredicate>;
124 
deserialize<F: PacketFlavor>( de_contents: &[u8], ) -> Result<Self, DataElementDeserializeError>125     fn deserialize<F: PacketFlavor>(
126         de_contents: &[u8],
127     ) -> Result<Self, DataElementDeserializeError> {
128         if E::ENUM_VARIANT == F::ENUM_VARIANT {
129             ActionsDataElement::deserialize(de_contents)
130         } else {
131             Err(DataElementDeserializeError::FlavorNotSupported {
132                 de_type: Self::DE_TYPE_CODE,
133                 flavor: F::ENUM_VARIANT,
134             })
135         }
136     }
137 }
138 
139 pub(in crate::legacy) struct ActionsLengthPredicate;
140 
141 impl DirectMapPredicate for ActionsLengthPredicate {
is_valid(len: usize) -> bool142     fn is_valid(len: usize) -> bool {
143         ACTIONS_VALID_ACTUAL_LEN.contains(&len)
144     }
145 }
146 
147 /// Container for the 24 bits defined for "actions" (feature flags and the like).
148 /// This internally stores a u32, but only the 24 highest bits of this
149 /// field will actually ever be populated.
150 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
151 pub struct ActionBits<F: PacketFlavor> {
152     bits: u32,
153     // marker for element type
154     flavor: marker::PhantomData<F>,
155 }
156 
157 impl<F: PacketFlavor> ActionBits<F> {
158     /// Returns the actions bits as a u32. The upper limit of an actions field is 3 bytes,
159     /// so the last bytes of this u32 will always be 0
as_u32(self) -> u32160     pub fn as_u32(self) -> u32 {
161         self.bits
162     }
163 
164     /// Return whether a boolean action type is set in this data element, or `None` if the given
165     /// action type does not represent a boolean.
has_action(&self, action_type: ActionType) -> bool166     pub fn has_action(&self, action_type: ActionType) -> bool {
167         self.bits_for_type(action_type) != 0
168     }
169 }
170 
171 impl<F: PacketFlavor> Default for ActionBits<F> {
default() -> Self172     fn default() -> Self {
173         ActionBits {
174             bits: 0, // no bits set
175             flavor: marker::PhantomData,
176         }
177     }
178 }
179 
180 /// At least one action doesn't support the required flavor
181 #[derive(PartialEq, Eq, Debug)]
182 pub struct FlavorNotSupported {
183     flavor: PacketFlavorEnum,
184 }
185 
186 lazy_static::lazy_static! {
187     /// All bits for plaintext action types: 1 where a plaintext action could have a bit, 0 elsewhere.
188     static ref ALL_PLAINTEXT_ELEMENT_BITS: u32 = ActionType::iter()
189         .filter(|t| t.supports_flavor(PacketFlavorEnum::Plaintext))
190         .map(|t| t.all_bits())
191         .fold(0_u32, |accum, bits| accum | bits);
192 }
193 
194 lazy_static::lazy_static! {
195     /// All bits for ciphertext action types: 1 where a ciphertext action could have a bit, 0 elsewhere.
196     static ref ALL_CIPHERTEXT_ELEMENT_BITS: u32 = ActionType::iter()
197         .filter(|t| t.supports_flavor(PacketFlavorEnum::Ciphertext))
198         .map(|t| t.all_bits())
199         .fold(0_u32, |accum, bits| accum | bits);
200 }
201 
202 impl<F: PacketFlavor> ActionBits<F> {
203     /// Tries to create ActionBits from a u32, returning error in the event a specific bit is set for
204     /// an unsupported flavor
try_from(value: u32) -> Result<Self, FlavorNotSupported>205     pub fn try_from(value: u32) -> Result<Self, FlavorNotSupported> {
206         let ok_bits: u32 = match F::ENUM_VARIANT {
207             PacketFlavorEnum::Plaintext => *ALL_PLAINTEXT_ELEMENT_BITS,
208             PacketFlavorEnum::Ciphertext => *ALL_CIPHERTEXT_ELEMENT_BITS,
209         };
210 
211         // no bits set beyond what's allowed for this flavor
212         if value | ok_bits == ok_bits {
213             Ok(Self { bits: value, flavor: marker::PhantomData })
214         } else {
215             Err(FlavorNotSupported { flavor: F::ENUM_VARIANT })
216         }
217     }
218 
219     /// Set the bits for the provided element.
220     /// Bits outside the range set by the action will be unaffected.
set_action<E: ActionElementFlavor<F>>(&mut self, action_element: E)221     pub fn set_action<E: ActionElementFlavor<F>>(&mut self, action_element: E) {
222         let bits = action_element.bits();
223 
224         // validate that the element is not horribly broken
225         debug_assert!(E::HIGH_BIT_INDEX < 32);
226         // must not have bits set past the low `len` bits
227         debug_assert_eq!(0, bits >> 1);
228 
229         // 0-extend to u32
230         let byte_extended = bits as u32;
231         // Shift so that the high bit is at the desired index.
232         // Won't overflow since length > 0.
233         let bits_in_position = byte_extended << (31 - E::HIGH_BIT_INDEX);
234 
235         // We want to effectively clear out the bits already in place, so we don't want to just |=.
236         // Instead, we construct a u32 with all 1s above and below the relevant bits and &=, so that
237         // if the new bits are 0, the stored bits will be cleared.
238 
239         // avoid overflow when index = 0 -- need zero 1 bits to the left in that case
240         let left_1s = u32::MAX.checked_shl(32 - E::HIGH_BIT_INDEX).unwrap_or(0);
241         // avoid underflow when index + len = 32 -- zero 1 bits to the right
242         let right_1s = u32::MAX.checked_shr(E::HIGH_BIT_INDEX + 1).unwrap_or(0);
243         let mask = left_1s | right_1s;
244         let bits_for_other_actions = self.bits & mask;
245         self.bits = bits_for_other_actions | bits_in_position;
246     }
247 
248     /// How many bytes (1-3) are needed to represent the set bits, starting from the most
249     /// significant bit. The lower bound of 1 is because the unique special case of
250     /// an actions field of all zeroes is required by the spec to occupy exactly one byte.
bytes_used(&self) -> usize251     fn bytes_used(&self) -> usize {
252         let bits_used = 32 - self.bits.trailing_zeros();
253         let raw_count = (bits_used as usize + 7) / 8;
254         if raw_count == 0 {
255             1 // Uncommon case - should only be hit for all-zero action bits
256         } else {
257             raw_count
258         }
259     }
260 
261     /// Return the bits for a given action type as the low bits in the returned u32.
262     ///
263     /// For example, when extracting the bits `B` from `0bXXXXXXXXXXBBBBBBXXXXXXXXXXXXXXXX`, the
264     /// return value will be `0b00000000000000000000000000BBBBBB`.
bits_for_type(&self, action_type: ActionType) -> u32265     pub fn bits_for_type(&self, action_type: ActionType) -> u32 {
266         self.bits << action_type.high_bit_index() >> (31)
267     }
268 }
269 
270 /// Core trait for an individual action
271 pub trait ActionElement {
272     /// The assigned offset for this type from the high bit in the eventual bit sequence of all
273     /// actions.
274     ///
275     /// Each implementation must have a non-conflicting index defined by
276     /// [Self::HIGH_BIT_INDEX]
277     const HIGH_BIT_INDEX: u32;
278 
279     /// Forces implementations to have a matching enum variant so the enum can be kept up to date.
280     const ACTION_TYPE: ActionType;
281 
282     /// Returns whether this action supports the provided `flavor`.
283     ///
284     /// Must match the implementations of [ActionElementFlavor].
supports_flavor(flavor: PacketFlavorEnum) -> bool285     fn supports_flavor(flavor: PacketFlavorEnum) -> bool;
286 
287     /// Returns the low bit that should be included in the final bit vector
288     /// starting at [Self::HIGH_BIT_INDEX].
bits(&self) -> u8289     fn bits(&self) -> u8;
290 }
291 
292 /// Marker trait indicating support for a particular [PacketFlavor].
293 pub trait ActionElementFlavor<F: PacketFlavor>: ActionElement {}
294 
295 /// Provides a way to iterate over all action types.
296 #[derive(Clone, Copy, strum_macros::EnumIter, PartialEq, Eq, Hash, Debug)]
297 #[allow(missing_docs)]
298 pub enum ActionType {
299     CrossDevSdk,
300     CallTransfer,
301     ActiveUnlock,
302     NearbyShare,
303     InstantTethering,
304     PhoneHub,
305 }
306 
307 impl ActionType {
308     /// A u32 with all possible bits for this action type set
all_bits(&self) -> u32309     const fn all_bits(&self) -> u32 {
310         (u32::MAX << (31_u32)) >> self.high_bit_index()
311     }
312 
313     /// Get the range of the bits occupied used by this bit index. For example, if the action type
314     /// uses the 5th and 6th bits, the returned range will be (5..7).
315     /// (0 is the index of the most significant bit).
316     #[cfg(feature = "devtools")]
bits_range_for_devtools(&self) -> Range<u32>317     pub const fn bits_range_for_devtools(&self) -> Range<u32> {
318         let high_bit_index = self.high_bit_index();
319         high_bit_index..high_bit_index + 1
320     }
321 
high_bit_index(&self) -> u32322     const fn high_bit_index(&self) -> u32 {
323         match self {
324             ActionType::CrossDevSdk => CrossDevSdk::HIGH_BIT_INDEX,
325             ActionType::CallTransfer => CallTransfer::HIGH_BIT_INDEX,
326             ActionType::ActiveUnlock => ActiveUnlock::HIGH_BIT_INDEX,
327             ActionType::NearbyShare => NearbyShare::HIGH_BIT_INDEX,
328             ActionType::InstantTethering => InstantTethering::HIGH_BIT_INDEX,
329             ActionType::PhoneHub => PhoneHub::HIGH_BIT_INDEX,
330         }
331     }
332 
supports_flavor(&self, flavor: PacketFlavorEnum) -> bool333     pub(crate) fn supports_flavor(&self, flavor: PacketFlavorEnum) -> bool {
334         match self {
335             ActionType::CrossDevSdk => CrossDevSdk::supports_flavor(flavor),
336             ActionType::CallTransfer => CallTransfer::supports_flavor(flavor),
337             ActionType::ActiveUnlock => ActiveUnlock::supports_flavor(flavor),
338             ActionType::NearbyShare => NearbyShare::supports_flavor(flavor),
339             ActionType::InstantTethering => InstantTethering::supports_flavor(flavor),
340             ActionType::PhoneHub => PhoneHub::supports_flavor(flavor),
341         }
342     }
343 }
344 
345 // enabling an element for public adv requires privacy approval due to fingerprinting risk
346 macros::boolean_element!(CrossDevSdk, 1, plaintext_and_ciphertext);
347 macros::boolean_element!(CallTransfer, 4, ciphertext_only);
348 macros::boolean_element!(ActiveUnlock, 8, ciphertext_only);
349 macros::boolean_element!(NearbyShare, 9, plaintext_and_ciphertext);
350 macros::boolean_element!(InstantTethering, 10, ciphertext_only);
351 macros::boolean_element!(PhoneHub, 11, ciphertext_only);
352