• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Handling for data represented as CBOR. Cryptographic objects are encoded following COSE.
2 
3 mod dice;
4 mod field_value;
5 mod publickey;
6 pub(crate) mod rkp;
7 
8 use ciborium::value::CanonicalValue;
9 use ciborium::{de::from_reader, value::Value};
10 use std::collections::BTreeMap;
11 use std::io::Read;
12 
13 type CiboriumError = ciborium::de::Error<std::io::Error>;
14 
15 /// Decodes the provided binary CBOR-encoded value and returns a
16 /// ciborium::Value struct wrapped in Result.
value_from_bytes(mut bytes: &[u8]) -> Result<Value, CiboriumError>17 fn value_from_bytes(mut bytes: &[u8]) -> Result<Value, CiboriumError> {
18     let value = from_reader(bytes.by_ref())?;
19     // Ciborium tries to read one Value, but doesn't care if there is trailing data. We do.
20     if !bytes.is_empty() {
21         return Err(CiboriumError::Semantic(Some(0), "unexpected trailing data".to_string()));
22     }
23     Ok(value)
24 }
25 
serialize(value: Value) -> Vec<u8>26 fn serialize(value: Value) -> Vec<u8> {
27     let mut data = Vec::new();
28     ciborium::ser::into_writer(&value, &mut data).unwrap();
29     data
30 }
31 
canonicalize_map(value: Value) -> Result<Vec<u8>, CiboriumError>32 fn canonicalize_map(value: Value) -> Result<Vec<u8>, CiboriumError> {
33     match value {
34         Value::Map(map) => {
35             let btree: BTreeMap<CanonicalValue, Value> =
36                 map.into_iter().map(|(k, v)| (CanonicalValue::from(k), v)).collect();
37 
38             let mut data = Vec::new();
39             ciborium::ser::into_writer(&btree, &mut data).unwrap();
40             Ok(data)
41         }
42         _ => Err(CiboriumError::Semantic(None, format!("expected map, got {:?}", &value))),
43     }
44 }
45 
46 #[cfg(test)]
47 mod tests {
48     use super::*;
49     use anyhow::Result;
50 
51     #[test]
value_from_bytes_valid_succeeds() -> Result<()>52     fn value_from_bytes_valid_succeeds() -> Result<()> {
53         let bytes = [0x82, 0x04, 0x02]; // [4, 2]
54         let val = value_from_bytes(&bytes)?;
55         let array = val.as_array().unwrap();
56         assert_eq!(array.len(), 2);
57         Ok(())
58     }
59 
60     #[test]
value_from_bytes_truncated_fails()61     fn value_from_bytes_truncated_fails() {
62         let bytes = [0x82, 0x04];
63         assert!(value_from_bytes(&bytes).is_err());
64     }
65 
66     #[test]
value_from_bytes_trailing_bytes_fails()67     fn value_from_bytes_trailing_bytes_fails() {
68         let bytes = [0x82, 0x04, 0x02, 0x00];
69         assert!(value_from_bytes(&bytes).is_err());
70     }
71 
72     #[test]
integers_and_lengths_are_canonicalized()73     fn integers_and_lengths_are_canonicalized() {
74         // Both are encodings of the following.
75         // [1, "12", {2 : 1, 1 : 2}]
76         let noncanonical_bytes = [
77             0x83, // array with size 3
78             0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, // integer 1
79             0x7a, 0x00, 0x00, 0x00, 0x02, 0x31, 0x32, // string "12"
80             0xa2, // map with size 2
81             0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x01, // 2 : 1
82             0x01, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, // 1 : 2
83         ];
84         // This is almost canonical because the keys of the map are not sorted.
85         // In order to be canonical, the entries of the map should be swapped.
86         let almost_canonical_bytes = [
87             0x83, // array with size 3
88             0x01, // integer 1
89             0x62, 0x31, 0x32, // string "12"
90             0xa2, // map with size 2
91             0x02, 0x01, // 2 : 1
92             0x01, 0x02, // 1 : 2
93         ];
94 
95         let value = value_from_bytes(noncanonical_bytes.as_slice()).unwrap();
96         let serialized = serialize(value);
97 
98         assert_eq!(serialized.as_slice(), almost_canonical_bytes);
99     }
100 
101     #[test]
canonicalization_works()102     fn canonicalization_works() {
103         let bytes = [0xa2, 0x03, 0x04, 0x01, 0x02];
104         let value = value_from_bytes(&bytes).unwrap();
105         let canonicalized = canonicalize_map(value.clone()).unwrap();
106         assert_eq!(&hex::encode(canonicalized), "a201020304");
107     }
108 }
109