[cbor] Separate cbor conversion functions in an independent lib

This allows callers from both std and nostd environment to
convert to/from CBOR-encoded data.

Bug: 303807447
Test: atest libservice_vm_requests.test
Change-Id: Ib2052f28779290165941cb2cf7ecc9ca566472af
diff --git a/libs/cborutil/Android.bp b/libs/cborutil/Android.bp
new file mode 100644
index 0000000..4758c4b
--- /dev/null
+++ b/libs/cborutil/Android.bp
@@ -0,0 +1,42 @@
+package {
+    default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
+rust_defaults {
+    name: "libcbor_util_defaults",
+    crate_name: "cbor_util",
+    srcs: ["src/lib.rs"],
+    defaults: ["avf_build_flags_rust"],
+    prefer_rlib: true,
+    apex_available: [
+        "com.android.virt",
+    ],
+}
+
+rust_library_rlib {
+    name: "libcbor_util_nostd",
+    defaults: ["libcbor_util_defaults"],
+    no_stdlibs: true,
+    stdlibs: [
+        "libcompiler_builtins.rust_sysroot",
+        "libcore.rust_sysroot",
+    ],
+    rustlibs: [
+        "libciborium_nostd",
+        "libcoset_nostd",
+        "libserde_nostd",
+    ],
+}
+
+rust_library {
+    name: "libcbor_util",
+    defaults: ["libcbor_util_defaults"],
+    features: [
+        "std",
+    ],
+    rustlibs: [
+        "libciborium",
+        "libcoset",
+        "libserde",
+    ],
+}
diff --git a/service_vm/requests/src/cbor.rs b/libs/cborutil/src/lib.rs
similarity index 84%
rename from service_vm/requests/src/cbor.rs
rename to libs/cborutil/src/lib.rs
index 36492e5..2ec5af4 100644
--- a/service_vm/requests/src/cbor.rs
+++ b/libs/cborutil/src/lib.rs
@@ -14,12 +14,16 @@
 
 //! Utility functions for CBOR serialization/deserialization.
 
+#![cfg_attr(not(feature = "std"), no_std)]
+
+extern crate alloc;
+
 use alloc::vec::Vec;
 use coset::{CoseError, Result};
 use serde::{de::DeserializeOwned, Serialize};
 
 /// Serializes the given data to a CBOR-encoded byte vector.
-pub(crate) fn serialize<T: ?Sized + Serialize>(v: &T) -> Result<Vec<u8>> {
+pub fn serialize<T: ?Sized + Serialize>(v: &T) -> Result<Vec<u8>> {
     let mut data = Vec::new();
     ciborium::into_writer(v, &mut data)?;
     Ok(data)
@@ -27,7 +31,7 @@
 
 /// Deserializes the given type from a CBOR-encoded byte slice, failing if any extra
 /// data remains after the type has been read.
-pub(crate) fn deserialize<T: DeserializeOwned>(mut data: &[u8]) -> Result<T> {
+pub fn deserialize<T: DeserializeOwned>(mut data: &[u8]) -> Result<T> {
     let res = ciborium::from_reader(&mut data)?;
     if data.is_empty() {
         Ok(res)
diff --git a/service_vm/requests/Android.bp b/service_vm/requests/Android.bp
index f85064a..ecede8b 100644
--- a/service_vm/requests/Android.bp
+++ b/service_vm/requests/Android.bp
@@ -18,6 +18,7 @@
     rustlibs: [
         "libbssl_avf_error_nostd",
         "libbssl_avf_nostd",
+        "libcbor_util_nostd",
         "libciborium_nostd",
         "libcoset_nostd",
         "libdiced_open_dice_nostd",
diff --git a/service_vm/requests/src/keyblob.rs b/service_vm/requests/src/keyblob.rs
index a714edd..456c879 100644
--- a/service_vm/requests/src/keyblob.rs
+++ b/service_vm/requests/src/keyblob.rs
@@ -14,7 +14,6 @@
 
 //! Handles the encryption and decryption of the key blob.
 
-use crate::cbor;
 use alloc::vec;
 use alloc::vec::Vec;
 use bssl_avf::{hkdf, rand_bytes, Aead, AeadContext, Digester, AES_GCM_NONCE_LENGTH};
@@ -70,16 +69,6 @@
             Self::V1(blob) => blob.decrypt_private_key(kek_secret),
         }
     }
-
-    // TODO(b/241428146): This function will be used once the retrieval mechanism is available.
-    #[cfg(test)]
-    pub(crate) fn from_cbor_slice(slice: &[u8]) -> coset::Result<Self> {
-        cbor::deserialize(slice)
-    }
-
-    pub(crate) fn to_cbor_vec(&self) -> coset::Result<Vec<u8>> {
-        cbor::serialize(&self)
-    }
 }
 
 impl EncryptedKeyBlobV1 {
@@ -136,8 +125,9 @@
 
     #[test]
     fn decrypting_keyblob_succeeds_with_the_same_kek() -> Result<()> {
-        let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
-        let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+        let encrypted_key_blob =
+            cbor_util::serialize(&EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?)?;
+        let encrypted_key_blob: EncryptedKeyBlob = cbor_util::deserialize(&encrypted_key_blob)?;
         let decrypted_key = encrypted_key_blob.decrypt_private_key(&TEST_SECRET1)?;
 
         assert_eq!(TEST_KEY, decrypted_key.as_slice());
@@ -146,8 +136,9 @@
 
     #[test]
     fn decrypting_keyblob_fails_with_a_different_kek() -> Result<()> {
-        let encrypted_key_blob = EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?.to_cbor_vec()?;
-        let encrypted_key_blob = EncryptedKeyBlob::from_cbor_slice(&encrypted_key_blob)?;
+        let encrypted_key_blob =
+            cbor_util::serialize(&EncryptedKeyBlob::new(&TEST_KEY, &TEST_SECRET1)?)?;
+        let encrypted_key_blob: EncryptedKeyBlob = cbor_util::deserialize(&encrypted_key_blob)?;
         let err = encrypted_key_blob.decrypt_private_key(&TEST_SECRET2).unwrap_err();
 
         let expected_err: RequestProcessingError =
diff --git a/service_vm/requests/src/lib.rs b/service_vm/requests/src/lib.rs
index 6fa6e0b..e3c5794 100644
--- a/service_vm/requests/src/lib.rs
+++ b/service_vm/requests/src/lib.rs
@@ -19,7 +19,6 @@
 extern crate alloc;
 
 mod api;
-mod cbor;
 mod keyblob;
 mod pub_key;
 mod rkp;
diff --git a/service_vm/requests/src/rkp.rs b/service_vm/requests/src/rkp.rs
index 933737c..8d7d771 100644
--- a/service_vm/requests/src/rkp.rs
+++ b/service_vm/requests/src/rkp.rs
@@ -15,7 +15,6 @@
 //! This module contains functions related to the attestation of the
 //! service VM via the RKP (Remote Key Provisioning) server.
 
-use crate::cbor;
 use crate::keyblob::EncryptedKeyBlob;
 use crate::pub_key::{build_maced_public_key, validate_public_key};
 use alloc::string::String;
@@ -51,7 +50,8 @@
     let key_blob =
         EncryptedKeyBlob::new(ec_key.private_key()?.as_slice(), dice_artifacts.cdi_seal())?;
 
-    let key_pair = EcdsaP256KeyPair { maced_public_key, key_blob: key_blob.to_cbor_vec()? };
+    let key_pair =
+        EcdsaP256KeyPair { maced_public_key, key_blob: cbor_util::serialize(&key_blob)? };
     Ok(key_pair)
 }
 
@@ -81,7 +81,7 @@
         // TODO(b/299256925): Add device info in CBOR format here.
         Value::Array(public_keys),
     ])?;
-    let csr_payload = cbor::serialize(&csr_payload)?;
+    let csr_payload = cbor_util::serialize(&csr_payload)?;
 
     // Builds `SignedData`.
     let signed_data_payload =
@@ -93,14 +93,14 @@
     // Check http://b/301574013#comment3 for more information.
     let uds_certs = Value::Map(Vec::new());
     let dice_cert_chain = dice_artifacts.bcc().ok_or(RequestProcessingError::MissingDiceChain)?;
-    let dice_cert_chain: Value = cbor::deserialize(dice_cert_chain)?;
+    let dice_cert_chain: Value = cbor_util::deserialize(dice_cert_chain)?;
     let auth_req = cbor!([
         Value::Integer(AUTH_REQ_SCHEMA_V1.into()),
         uds_certs,
         dice_cert_chain,
         signed_data,
     ])?;
-    Ok(cbor::serialize(&auth_req)?)
+    Ok(cbor_util::serialize(&auth_req)?)
 }
 
 fn derive_hmac_key(dice_artifacts: &dyn DiceArtifacts) -> Result<Zeroizing<[u8; HMAC_KEY_LENGTH]>> {
@@ -122,7 +122,7 @@
     let protected = HeaderBuilder::new().algorithm(signing_algorithm).build();
     let signed_data = CoseSign1Builder::new()
         .protected(protected)
-        .payload(cbor::serialize(payload)?)
+        .payload(cbor_util::serialize(payload)?)
         .try_create_signature(&[], |message| sign_message(message, &cdi_leaf_priv))?
         .build();
     Ok(signed_data)