der/asn1/
bit_string.rs

1//! ASN.1 `BIT STRING` support.
2
3use crate::{
4    asn1::AnyRef, ByteSlice, DecodeValue, DerOrd, EncodeValue, Error, ErrorKind, FixedTag, Header,
5    Length, Reader, Result, Tag, ValueOrd, Writer,
6};
7use core::{cmp::Ordering, iter::FusedIterator};
8
9#[cfg(feature = "alloc")]
10use alloc::vec::Vec;
11
12/// ASN.1 `BIT STRING` type.
13///
14/// This type contains a sequence of any number of bits, modeled internally as
15/// a sequence of bytes with a known number of "unused bits".
16///
17/// This is a zero-copy reference type which borrows from the input data.
18#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
19pub struct BitStringRef<'a> {
20    /// Number of unused bits in the final octet.
21    unused_bits: u8,
22
23    /// Length of this `BIT STRING` in bits.
24    bit_length: usize,
25
26    /// Bitstring represented as a slice of bytes.
27    inner: ByteSlice<'a>,
28}
29
30impl<'a> BitStringRef<'a> {
31    /// Maximum number of unused bits allowed.
32    pub const MAX_UNUSED_BITS: u8 = 7;
33
34    /// Create a new ASN.1 `BIT STRING` from a byte slice.
35    ///
36    /// Accepts an optional number of "unused bits" (0-7) which are omitted
37    /// from the final octet. This number is 0 if the value is octet-aligned.
38    pub fn new(unused_bits: u8, bytes: &'a [u8]) -> Result<Self> {
39        if (unused_bits > Self::MAX_UNUSED_BITS) || (unused_bits != 0 && bytes.is_empty()) {
40            return Err(Self::TAG.value_error());
41        }
42
43        let inner = ByteSlice::new(bytes).map_err(|_| Self::TAG.length_error())?;
44
45        let bit_length = usize::try_from(inner.len())?
46            .checked_mul(8)
47            .and_then(|n| n.checked_sub(usize::from(unused_bits)))
48            .ok_or(ErrorKind::Overflow)?;
49
50        Ok(Self {
51            unused_bits,
52            bit_length,
53            inner,
54        })
55    }
56
57    /// Create a new ASN.1 `BIT STRING` from the given bytes.
58    ///
59    /// The "unused bits" are set to 0.
60    pub fn from_bytes(bytes: &'a [u8]) -> Result<Self> {
61        Self::new(0, bytes)
62    }
63
64    /// Get the number of unused bits in this byte slice.
65    pub fn unused_bits(&self) -> u8 {
66        self.unused_bits
67    }
68
69    /// Is the number of unused bits a value other than 0?
70    pub fn has_unused_bits(&self) -> bool {
71        self.unused_bits != 0
72    }
73
74    /// Get the length of this `BIT STRING` in bits.
75    pub fn bit_len(&self) -> usize {
76        self.bit_length
77    }
78
79    /// Get the number of bytes/octets needed to represent this `BIT STRING`
80    /// when serialized in an octet-aligned manner.
81    pub fn byte_len(&self) -> Length {
82        self.inner.len()
83    }
84
85    /// Is the inner byte slice empty?
86    pub fn is_empty(&self) -> bool {
87        self.inner.is_empty()
88    }
89
90    /// Borrow the inner byte slice.
91    ///
92    /// Returns `None` if the number of unused bits is *not* equal to zero,
93    /// i.e. if the `BIT STRING` is not octet aligned.
94    ///
95    /// Use [`BitString::raw_bytes`] to obtain access to the raw value
96    /// regardless of the presence of unused bits.
97    pub fn as_bytes(&self) -> Option<&'a [u8]> {
98        if self.has_unused_bits() {
99            None
100        } else {
101            Some(self.raw_bytes())
102        }
103    }
104
105    /// Borrow the raw bytes of this `BIT STRING`.
106    ///
107    /// Note that the byte string may contain extra unused bits in the final
108    /// octet. If the number of unused bits is expected to be 0, the
109    /// [`BitStringRef::as_bytes`] function can be used instead.
110    pub fn raw_bytes(&self) -> &'a [u8] {
111        self.inner.as_slice()
112    }
113
114    /// Iterator over the bits of this `BIT STRING`.
115    pub fn bits(self) -> BitStringIter<'a> {
116        BitStringIter {
117            bit_string: self,
118            position: 0,
119        }
120    }
121}
122
123impl<'a> DecodeValue<'a> for BitStringRef<'a> {
124    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
125        let header = Header {
126            tag: header.tag,
127            length: (header.length - Length::ONE)?,
128        };
129
130        let unused_bits = reader.read_byte()?;
131        let inner = ByteSlice::decode_value(reader, header)?;
132        Self::new(unused_bits, inner.as_slice())
133    }
134}
135
136impl EncodeValue for BitStringRef<'_> {
137    fn value_len(&self) -> Result<Length> {
138        self.byte_len() + Length::ONE
139    }
140
141    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
142        writer.write_byte(self.unused_bits)?;
143        writer.write(self.raw_bytes())
144    }
145}
146
147impl ValueOrd for BitStringRef<'_> {
148    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
149        match self.unused_bits.cmp(&other.unused_bits) {
150            Ordering::Equal => self.inner.der_cmp(&other.inner),
151            ordering => Ok(ordering),
152        }
153    }
154}
155
156impl<'a> From<&BitStringRef<'a>> for BitStringRef<'a> {
157    fn from(value: &BitStringRef<'a>) -> BitStringRef<'a> {
158        *value
159    }
160}
161
162impl<'a> TryFrom<AnyRef<'a>> for BitStringRef<'a> {
163    type Error = Error;
164
165    fn try_from(any: AnyRef<'a>) -> Result<BitStringRef<'a>> {
166        any.decode_into()
167    }
168}
169
170impl<'a> TryFrom<&'a [u8]> for BitStringRef<'a> {
171    type Error = Error;
172
173    fn try_from(bytes: &'a [u8]) -> Result<BitStringRef<'a>> {
174        BitStringRef::from_bytes(bytes)
175    }
176}
177
178/// Hack for simplifying the custom derive use case.
179impl<'a> TryFrom<&&'a [u8]> for BitStringRef<'a> {
180    type Error = Error;
181
182    fn try_from(bytes: &&'a [u8]) -> Result<BitStringRef<'a>> {
183        BitStringRef::from_bytes(*bytes)
184    }
185}
186
187impl<'a> TryFrom<BitStringRef<'a>> for &'a [u8] {
188    type Error = Error;
189
190    fn try_from(bit_string: BitStringRef<'a>) -> Result<&'a [u8]> {
191        bit_string
192            .as_bytes()
193            .ok_or_else(|| Tag::BitString.value_error())
194    }
195}
196
197impl<'a> FixedTag for BitStringRef<'a> {
198    const TAG: Tag = Tag::BitString;
199}
200
201/// Owned form of ASN.1 `BIT STRING` type.
202///
203/// This type provides the same functionality as [`BitStringRef`] but owns the
204/// backing data.
205#[cfg(feature = "alloc")]
206#[cfg_attr(docsrs, doc(cfg(feature = "alloc")))]
207#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Ord)]
208pub struct BitString {
209    /// Number of unused bits in the final octet.
210    unused_bits: u8,
211
212    /// Length of this `BIT STRING` in bits.
213    bit_length: usize,
214
215    /// Bitstring represented as a slice of bytes.
216    inner: Vec<u8>,
217}
218
219#[cfg(feature = "alloc")]
220impl BitString {
221    /// Maximum number of unused bits allowed.
222    pub const MAX_UNUSED_BITS: u8 = 7;
223
224    /// Create a new ASN.1 `BIT STRING` from a byte slice.
225    ///
226    /// Accepts an optional number of "unused bits" (0-7) which are omitted
227    /// from the final octet. This number is 0 if the value is octet-aligned.
228    pub fn new(unused_bits: u8, bytes: impl Into<Vec<u8>>) -> Result<Self> {
229        let inner = bytes.into();
230
231        // Ensure parameters parse successfully as a `BitStringRef`.
232        let bit_length = BitStringRef::new(unused_bits, &inner)?.bit_length;
233
234        Ok(BitString {
235            unused_bits,
236            bit_length,
237            inner,
238        })
239    }
240
241    /// Create a new ASN.1 `BIT STRING` from the given bytes.
242    ///
243    /// The "unused bits" are set to 0.
244    pub fn from_bytes(bytes: &[u8]) -> Result<Self> {
245        Self::new(0, bytes)
246    }
247
248    /// Get the number of unused bits in the octet serialization of this
249    /// `BIT STRING`.
250    pub fn unused_bits(&self) -> u8 {
251        self.unused_bits
252    }
253
254    /// Is the number of unused bits a value other than 0?
255    pub fn has_unused_bits(&self) -> bool {
256        self.unused_bits != 0
257    }
258
259    /// Get the length of this `BIT STRING` in bits.
260    pub fn bit_len(&self) -> usize {
261        self.bit_length
262    }
263
264    /// Is the inner byte slice empty?
265    pub fn is_empty(&self) -> bool {
266        self.inner.is_empty()
267    }
268
269    /// Borrow the inner byte slice.
270    ///
271    /// Returns `None` if the number of unused bits is *not* equal to zero,
272    /// i.e. if the `BIT STRING` is not octet aligned.
273    ///
274    /// Use [`BitString::raw_bytes`] to obtain access to the raw value
275    /// regardless of the presence of unused bits.
276    pub fn as_bytes(&self) -> Option<&[u8]> {
277        if self.has_unused_bits() {
278            None
279        } else {
280            Some(self.raw_bytes())
281        }
282    }
283
284    /// Borrow the raw bytes of this `BIT STRING`.
285    pub fn raw_bytes(&self) -> &[u8] {
286        self.inner.as_slice()
287    }
288
289    /// Iterator over the bits of this `BIT STRING`.
290    pub fn bits(&self) -> BitStringIter<'_> {
291        BitStringRef::from(self).bits()
292    }
293}
294
295#[cfg(feature = "alloc")]
296impl<'a> DecodeValue<'a> for BitString {
297    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
298        let inner_len = (header.length - Length::ONE)?;
299        let unused_bits = reader.read_byte()?;
300        let inner = reader.read_vec(inner_len)?;
301        Self::new(unused_bits, inner)
302    }
303}
304
305#[cfg(feature = "alloc")]
306impl EncodeValue for BitString {
307    fn value_len(&self) -> Result<Length> {
308        Length::ONE + Length::try_from(self.inner.len())?
309    }
310
311    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
312        writer.write_byte(self.unused_bits)?;
313        writer.write(&self.inner)
314    }
315}
316
317#[cfg(feature = "alloc")]
318impl FixedTag for BitString {
319    const TAG: Tag = Tag::BitString;
320}
321
322#[cfg(feature = "alloc")]
323impl<'a> From<&'a BitString> for BitStringRef<'a> {
324    fn from(bit_string: &'a BitString) -> BitStringRef<'a> {
325        // Ensured to parse successfully in constructor
326        BitStringRef::new(bit_string.unused_bits, &bit_string.inner).expect("invalid BIT STRING")
327    }
328}
329
330#[cfg(feature = "alloc")]
331impl ValueOrd for BitString {
332    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
333        match self.unused_bits.cmp(&other.unused_bits) {
334            Ordering::Equal => self.inner.der_cmp(&other.inner),
335            ordering => Ok(ordering),
336        }
337    }
338}
339
340/// Iterator over the bits of a [`BitString`].
341pub struct BitStringIter<'a> {
342    /// [`BitString`] being iterated over.
343    bit_string: BitStringRef<'a>,
344
345    /// Current bit position within the iterator.
346    position: usize,
347}
348
349impl<'a> Iterator for BitStringIter<'a> {
350    type Item = bool;
351
352    #[allow(clippy::integer_arithmetic)]
353    fn next(&mut self) -> Option<bool> {
354        if self.position >= self.bit_string.bit_len() {
355            return None;
356        }
357
358        let byte = self.bit_string.raw_bytes().get(self.position / 8)?;
359        let bit = 1u8 << (7 - (self.position % 8));
360        self.position = self.position.checked_add(1)?;
361        Some(byte & bit != 0)
362    }
363}
364
365impl<'a> ExactSizeIterator for BitStringIter<'a> {
366    fn len(&self) -> usize {
367        self.bit_string.bit_len()
368    }
369}
370
371impl<'a> FusedIterator for BitStringIter<'a> {}
372
373#[cfg(feature = "flagset")]
374impl<T: flagset::Flags> FixedTag for flagset::FlagSet<T> {
375    const TAG: Tag = BitStringRef::TAG;
376}
377
378#[cfg(feature = "flagset")]
379impl<T> ValueOrd for flagset::FlagSet<T>
380where
381    T: flagset::Flags,
382    T::Type: Ord,
383{
384    fn value_cmp(&self, other: &Self) -> Result<Ordering> {
385        Ok(self.bits().cmp(&other.bits()))
386    }
387}
388
389#[cfg(feature = "flagset")]
390#[allow(clippy::integer_arithmetic)]
391impl<'a, T> DecodeValue<'a> for flagset::FlagSet<T>
392where
393    T: flagset::Flags,
394    T::Type: From<bool>,
395    T::Type: core::ops::Shl<usize, Output = T::Type>,
396{
397    fn decode_value<R: Reader<'a>>(reader: &mut R, header: Header) -> Result<Self> {
398        let position = reader.position();
399        let bits = BitStringRef::decode_value(reader, header)?;
400
401        let mut flags = T::none().bits();
402
403        if bits.bit_len() > core::mem::size_of_val(&flags) * 8 {
404            return Err(Error::new(ErrorKind::Overlength, position));
405        }
406
407        for (i, bit) in bits.bits().enumerate() {
408            flags |= T::Type::from(bit) << i;
409        }
410
411        Ok(Self::new_truncated(flags))
412    }
413}
414
415#[cfg(feature = "flagset")]
416#[allow(clippy::integer_arithmetic)]
417#[inline(always)]
418fn encode_flagset<T>(set: &flagset::FlagSet<T>) -> (usize, [u8; 16])
419where
420    T: flagset::Flags,
421    u128: From<T::Type>,
422{
423    let bits: u128 = set.bits().into();
424    let mut swap = 0u128;
425
426    for i in 0..128 {
427        let on = bits & (1 << i);
428        swap |= on >> i << (128 - i - 1);
429    }
430
431    (bits.leading_zeros() as usize, swap.to_be_bytes())
432}
433
434#[cfg(feature = "flagset")]
435#[allow(clippy::cast_possible_truncation, clippy::integer_arithmetic)]
436impl<T: flagset::Flags> EncodeValue for flagset::FlagSet<T>
437where
438    T::Type: From<bool>,
439    T::Type: core::ops::Shl<usize, Output = T::Type>,
440    u128: From<T::Type>,
441{
442    fn value_len(&self) -> Result<Length> {
443        let (lead, buff) = encode_flagset(self);
444        let buff = &buff[..buff.len() - lead / 8];
445        BitStringRef::new((lead % 8) as u8, buff)?.value_len()
446    }
447
448    fn encode_value(&self, writer: &mut dyn Writer) -> Result<()> {
449        let (lead, buff) = encode_flagset(self);
450        let buff = &buff[..buff.len() - lead / 8];
451        BitStringRef::new((lead % 8) as u8, buff)?.encode_value(writer)
452    }
453}
454
455#[cfg(test)]
456mod tests {
457    use super::{BitStringRef, Result, Tag};
458    use crate::asn1::AnyRef;
459    use hex_literal::hex;
460
461    /// Parse a `BitString` from an ASN.1 `Any` value to test decoding behaviors.
462    fn parse_bitstring(bytes: &[u8]) -> Result<BitStringRef<'_>> {
463        AnyRef::new(Tag::BitString, bytes)?.try_into()
464    }
465
466    #[test]
467    fn decode_empty_bitstring() {
468        let bs = parse_bitstring(&hex!("00")).unwrap();
469        assert_eq!(bs.as_bytes().unwrap(), &[]);
470    }
471
472    #[test]
473    fn decode_non_empty_bitstring() {
474        let bs = parse_bitstring(&hex!("00010203")).unwrap();
475        assert_eq!(bs.as_bytes().unwrap(), &[0x01, 0x02, 0x03]);
476    }
477
478    #[test]
479    fn decode_bitstring_with_unused_bits() {
480        let bs = parse_bitstring(&hex!("066e5dc0")).unwrap();
481        assert_eq!(bs.unused_bits(), 6);
482        assert_eq!(bs.raw_bytes(), &hex!("6e5dc0"));
483
484        // Expected: 011011100101110111
485        let mut bits = bs.bits();
486        assert_eq!(bits.len(), 18);
487
488        for bit in [0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1] {
489            assert_eq!(bits.next().unwrap() as u8, bit)
490        }
491
492        // Ensure `None` is returned on successive calls
493        assert_eq!(bits.next(), None);
494        assert_eq!(bits.next(), None);
495    }
496
497    #[test]
498    fn reject_unused_bits_in_empty_string() {
499        assert_eq!(
500            parse_bitstring(&[0x03]).err().unwrap().kind(),
501            Tag::BitString.value_error().kind()
502        )
503    }
504}