[test][fix] Sort the keys of device info map in CBOR order

As required in 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.

This is aligned with the libcppbor CBOR ordering
implementation.

Bug: 325906414
Test: atest rialto_test libservice_vm_requests.test
Test: atest VtsHalRemotelyProvisionedComponentTargetTest
Change-Id: I3a775d6915e5fc3d4d50c4f4242cef3c8b17c1d1
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);
+    }
+}