Merge "[test][fix] Sort the keys of device info map in CBOR order" into main
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index 569ab01..08ee08e 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -21,7 +21,10 @@
use alloc::vec;
use alloc::vec::Vec;
use bssl_avf::EcKey;
-use ciborium::{cbor, value::Value};
+use ciborium::{
+ cbor,
+ value::{CanonicalValue, Value},
+};
use core::result;
use coset::{iana, AsCborValue, CoseSign1, CoseSign1Builder, HeaderBuilder};
use diced_open_dice::{derive_cdi_leaf_priv, kdf, sign, DiceArtifacts, PrivateKey};
@@ -106,18 +109,24 @@
/// Generates the device info required by the RKP server as a temporary placeholder.
/// More details in b/301592917.
-fn device_info() -> Value {
- cbor!({"brand" => "aosp-avf",
- "manufacturer" => "aosp-avf",
- "product" => "avf",
- "model" => "avf",
- "device" => "avf",
- "vbmeta_digest" => Value::Bytes(vec![0u8; 0]),
- "system_patch_level" => 202402,
- "boot_patch_level" => 20240202,
- "vendor_patch_level" => 20240202,
- "fused" => 1})
+///
+/// The keys of the map should be in the length-first core deterministic encoding order
+/// as per RFC8949.
+fn device_info() -> CanonicalValue {
+ cbor!({
+ "brand" => "aosp-avf",
+ "fused" => 1,
+ "model" => "avf",
+ "device" => "avf",
+ "product" => "avf",
+ "manufacturer" => "aosp-avf",
+ "vbmeta_digest" => Value::Bytes(vec![0u8; 0]),
+ "boot_patch_level" => 20240202,
+ "system_patch_level" => 202402,
+ "vendor_patch_level" => 20240202,
+ })
.unwrap()
+ .into()
}
fn derive_hmac_key(dice_artifacts: &dyn DiceArtifacts) -> Result<Zeroizing<[u8; HMAC_KEY_LENGTH]>> {
@@ -153,3 +162,25 @@
})?
.to_vec())
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ /// The keys of device info map should be in the length-first core deterministic encoding
+ /// order as per RFC8949.
+ /// The CBOR ordering rules are:
+ /// 1. If two keys have different lengths, the shorter one sorts earlier;
+ /// 2. If two keys have the same length, the one with the lower value in
+ /// (bytewise) lexical order sorts earlier.
+ #[test]
+ fn device_info_is_in_length_first_deterministic_order() {
+ let device_info = cbor!(device_info()).unwrap();
+ let device_info_map = device_info.as_map().unwrap();
+ let device_info_keys: Vec<&str> =
+ device_info_map.iter().map(|k| k.0.as_text().unwrap()).collect();
+ let mut sorted_keys = device_info_keys.clone();
+ sorted_keys.sort_by(|a, b| a.len().cmp(&b.len()).then(a.cmp(b)));
+ assert_eq!(device_info_keys, sorted_keys);
+ }
+}