xref: /aosp_15_r20/external/open-dice/dpe-rs/src/cbor.rs (revision 60b67249c2e226f42f35cc6cfe66c6048e0bae6b)
1 // Copyright 2024 Google LLC
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://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, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 //! Utilities related to CBOR encode/decode.
16 
17 use crate::error::{DpeResult, ErrCode};
18 use crate::memory::SizedMessage;
19 use log::error;
20 use minicbor::{Decoder, Encoder};
21 
22 // Required in order for minicbor to write into a SizedMessage.
23 impl<const S: usize> minicbor::encode::Write for SizedMessage<S> {
24     type Error = ();
write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error>25     fn write_all(&mut self, buf: &[u8]) -> Result<(), Self::Error> {
26         self.vec.extend_from_slice(buf)
27     }
28 }
29 
30 /// Creates a CBOR [Encoder] which encodes into `output`.
cbor_encoder_from_message<const S: usize>( output: &mut SizedMessage<S>, ) -> Encoder<&mut SizedMessage<S>>31 pub fn cbor_encoder_from_message<const S: usize>(
32     output: &mut SizedMessage<S>,
33 ) -> Encoder<&mut SizedMessage<S>> {
34     Encoder::new(output)
35 }
36 
37 /// Creates a CBOR [Decoder] which decodes from `input`.
cbor_decoder_from_message<const S: usize>( input: &SizedMessage<S>, ) -> Decoder38 pub fn cbor_decoder_from_message<const S: usize>(
39     input: &SizedMessage<S>,
40 ) -> Decoder {
41     Decoder::new(input.as_slice())
42 }
43 
44 /// Extends minicbor::Decoder.
45 pub trait DecoderExt {
46     /// Decodes a byte slice and returns only its position. This is useful when
47     /// the byte slice is the last CBOR item, might be large, and will be
48     /// processed in-place using up to the entire available message buffer.
49     /// This is intended to be used in conjunction with [`remove_prefix`].
50     ///
51     /// # Errors
52     ///
53     /// Returns an InvalidArgument error if a CBOR Bytes item cannot be decoded.
54     ///
55     /// # Example
56     ///
57     /// ```rust
58     /// use dpe_rs::cbor::{
59     ///     cbor_decoder_from_message,
60     ///     cbor_encoder_from_message,
61     ///     DecoderExt,
62     /// };
63     /// use dpe_rs::memory::Message;
64     ///
65     /// let mut message = Message::new();
66     /// cbor_encoder_from_message(&mut message).bytes(&[0; 1000]);
67     /// let mut decoder = cbor_decoder_from_message(&message);
68     /// let position = decoder.decode_bytes_prefix().unwrap();
69     /// assert_eq!(&message.as_slice()[position..], &[0; 1000]);
70     /// ```
71     /// [`remove_prefix`]: SizedMessage::remove_prefix
decode_bytes_prefix(&mut self) -> DpeResult<usize>72     fn decode_bytes_prefix(&mut self) -> DpeResult<usize>;
73 }
74 impl DecoderExt for Decoder<'_> {
decode_bytes_prefix(&mut self) -> DpeResult<usize>75     fn decode_bytes_prefix(&mut self) -> DpeResult<usize> {
76         let bytes_len = self.bytes()?.len();
77         Ok(self.position() - bytes_len)
78     }
79 }
80 
81 /// Encodes a CBOR Bytes prefix for a given `bytes_len` and appends it to
82 /// `buffer`. This must be appended by `bytes_len` bytes to form a valid CBOR
83 /// encoding.
84 ///
85 /// # Errors
86 ///
87 /// Returns an InternalError error if `bytes_len` is too large for the remaining
88 /// capacity of the `buffer`.
89 ///
90 /// # Example
91 ///
92 /// ```rust
93 /// use dpe_rs::cbor::{
94 ///     cbor_decoder_from_message,
95 ///     cbor_encoder_from_message,
96 ///     encode_bytes_prefix,
97 /// };
98 /// use dpe_rs::memory::{
99 ///     Message,
100 ///     SizedMessage,
101 /// };
102 /// type Prefix = SizedMessage<10>;
103 ///
104 /// let mut message = Message::from_slice(&[0; 100]).unwrap();
105 /// let mut prefix = Prefix::new();
106 /// encode_bytes_prefix(&mut prefix, message.len()).unwrap();
107 /// message.insert_prefix(prefix.as_slice()).unwrap();
108 /// let mut decoder = cbor_decoder_from_message(&message);
109 /// assert_eq!(decoder.bytes().unwrap(), &[0; 100]);
110 /// ```
encode_bytes_prefix<const S: usize>( buffer: &mut SizedMessage<S>, bytes_len: usize, ) -> DpeResult<()>111 pub fn encode_bytes_prefix<const S: usize>(
112     buffer: &mut SizedMessage<S>,
113     bytes_len: usize,
114 ) -> DpeResult<()> {
115     // See RFC 8949 sections 3 and 3.1 for how this is encoded.
116     // `CBOR_BYTES_MAJOR_TYPE` is major type 2 in the high-order 3 bits.
117     const CBOR_BYTES_MAJOR_TYPE: u8 = 2 << 5;
118     const CBOR_VALUE_IN_ONE_BYTE: u8 = 24;
119     const CBOR_VALUE_IN_TWO_BYTES: u8 = 25;
120     let initial_byte_value;
121     let mut following_bytes: &[u8] = &[];
122     let mut big_endian_value: [u8; 2] = Default::default();
123     match bytes_len {
124         0..=23 => {
125             // Encode the length in the lower 5 bits of the initial byte.
126             initial_byte_value = bytes_len as u8;
127         }
128         24..=255 => {
129             // Encode the length in a single additional byte.
130             initial_byte_value = CBOR_VALUE_IN_ONE_BYTE;
131             big_endian_value[0] = bytes_len as u8;
132             following_bytes = &big_endian_value[..1];
133         }
134         256..=65535 => {
135             // Encode the length in two additional bytes, big endian.
136             initial_byte_value = CBOR_VALUE_IN_TWO_BYTES;
137             big_endian_value = (bytes_len as u16).to_be_bytes();
138             following_bytes = &big_endian_value;
139         }
140         _ => {
141             error!("Unsupported CBOR length");
142             return Err(ErrCode::InternalError);
143         }
144     }
145     buffer
146         .vec
147         .push(CBOR_BYTES_MAJOR_TYPE + initial_byte_value)
148         .map_err(|_| ErrCode::InternalError)?;
149     buffer
150         .vec
151         .extend_from_slice(following_bytes)
152         .map_err(|_| ErrCode::InternalError)?;
153     Ok(())
154 }
155