dice: add sign and encode with CoseSign1

Adds APIs to produce CoseSign1 encoded signatures given a message,
aad, and private key. This is implemented with
`DiceCoseSignAndEncodeSign1` from open_dice, which is brought in through
bindgen build rules for soong and trusty.

The driving use case is pvmdice, which needs to implement the hwbcc
interface's sign_data function. This will enable RKP protocols as well
as the implementation of the authmgr frontend in trusty pVMs.

Bug: 390385820
Test: atest libdiced_open_dice.integration_test
Test: atest libdiced_open_dice_nostd.integration_test
Test: build.py qemu-generic-arm64-test-debug \
        --test="boot-test:com.android.trusty.rust.diced_open_dice_tests.test"

Change-Id: Iac77f2f48f5f9ae90d1d08aaa6f34298b7220e40
diff --git a/libs/dice/open_dice/Android.bp b/libs/dice/open_dice/Android.bp
index 1870ab6..75f70c3 100644
--- a/libs/dice/open_dice/Android.bp
+++ b/libs/dice/open_dice/Android.bp
@@ -75,6 +75,7 @@
     defaults: ["libdiced_open_dice_test_defaults"],
     rustlibs: [
         "libdiced_open_dice",
+        "libcoset",
     ],
 }
 
@@ -83,6 +84,7 @@
     defaults: ["libdiced_open_dice_test_defaults"],
     rustlibs: [
         "libdiced_open_dice_nostd",
+        "libcoset_nostd",
     ],
 }
 
@@ -146,6 +148,7 @@
         "--allowlist-function=DiceKdf",
         "--allowlist-function=DiceKeypairFromSeed",
         "--allowlist-function=DiceSign",
+        "--allowlist-function=DiceCoseSignAndEncodeSign1",
         "--allowlist-function=DiceVerify",
         "--allowlist-function=DiceGenerateCertificate",
 
diff --git a/libs/dice/open_dice/bindgen/dice/dice.h b/libs/dice/open_dice/bindgen/dice/dice.h
index 47fe911..e6d5131 100644
--- a/libs/dice/open_dice/bindgen/dice/dice.h
+++ b/libs/dice/open_dice/bindgen/dice/dice.h
@@ -16,3 +16,4 @@
 
 #include <dice/dice.h>
 #include <dice/ops.h>
+#include <dice/ops/trait/cose.h>
diff --git a/libs/dice/open_dice/bindgen/dice/rules.mk b/libs/dice/open_dice/bindgen/dice/rules.mk
index 0ea5c7c..e9c4b81 100644
--- a/libs/dice/open_dice/bindgen/dice/rules.mk
+++ b/libs/dice/open_dice/bindgen/dice/rules.mk
@@ -39,6 +39,7 @@
 	DiceKdf \
 	DiceKeypairFromSeed \
 	DiceSign \
+	DiceCoseSignAndEncodeSign1 \
 	DiceVerify \
 	DiceGenerateCertificate \
 
diff --git a/libs/dice/open_dice/src/lib.rs b/libs/dice/open_dice/src/lib.rs
index 4d05255..33fb65c 100644
--- a/libs/dice/open_dice/src/lib.rs
+++ b/libs/dice/open_dice/src/lib.rs
@@ -43,9 +43,11 @@
 };
 pub use error::{DiceError, Result};
 pub use ops::{
-    derive_cdi_leaf_priv, generate_certificate, hash, kdf, keypair_from_seed, sign, verify,
+    derive_cdi_leaf_priv, generate_certificate, hash, kdf, keypair_from_seed, sign,
+    sign_cose_sign1, sign_cose_sign1_with_cdi_leaf_priv, verify,
 };
 pub use retry::{
     retry_bcc_format_config_descriptor, retry_bcc_main_flow, retry_dice_main_flow,
-    retry_generate_certificate, OwnedDiceArtifacts,
+    retry_generate_certificate, retry_sign_cose_sign1, retry_sign_cose_sign1_with_cdi_leaf_priv,
+    OwnedDiceArtifacts,
 };
diff --git a/libs/dice/open_dice/src/ops.rs b/libs/dice/open_dice/src/ops.rs
index 41951bf..2014118 100644
--- a/libs/dice/open_dice/src/ops.rs
+++ b/libs/dice/open_dice/src/ops.rs
@@ -23,8 +23,8 @@
 use crate::error::{check_result, DiceError, Result};
 use alloc::{vec, vec::Vec};
 use open_dice_cbor_bindgen::{
-    DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed, DicePrincipal, DiceSign,
-    DiceVerify,
+    DiceCoseSignAndEncodeSign1, DiceGenerateCertificate, DiceHash, DiceKdf, DiceKeypairFromSeed,
+    DicePrincipal, DiceSign, DiceVerify,
 };
 use std::ptr;
 
@@ -114,7 +114,7 @@
     Ok(private_key)
 }
 
-/// Signs the `message` with the give `private_key` using `DiceSign`.
+/// Signs the `message` with the given `private_key` using `DiceSign`.
 pub fn sign(message: &[u8], private_key: &[u8; PRIVATE_KEY_SIZE]) -> Result<Vec<u8>> {
     let mut signature = vec![0u8; VM_KEY_ALGORITHM.signature_size()];
     check_result(
@@ -136,6 +136,58 @@
     Ok(signature)
 }
 
+/// Signs the `message` with the given `private_key` and places a `CoseSign1` encoded
+/// object in `encoded_signature`. Uses `DiceCoseSignAndEncodeSign1`.
+///
+/// Returns the actual size of encoded_signature on success.
+pub fn sign_cose_sign1(
+    message: &[u8],
+    aad: &[u8],
+    private_key: &[u8; PRIVATE_KEY_SIZE],
+    encoded_signature: &mut [u8],
+) -> Result<usize> {
+    let mut encoded_signature_actual_size = 0;
+
+    check_result(
+        // SAFETY: The function writes to `encoded_signature` and `encoded_signature_actual_size`
+        // within the given bounds. It only reads `message`, `aad`, and `private_key` within their
+        // given bounds.
+        //
+        // The first argument is a pointer to a valid |DiceContext_| object for multi-alg open-dice
+        // and a null pointer otherwise.
+        unsafe {
+            DiceCoseSignAndEncodeSign1(
+                context(),
+                message.as_ptr(),
+                message.len(),
+                aad.as_ptr(),
+                aad.len(),
+                private_key.as_ptr(),
+                encoded_signature.len(),
+                encoded_signature.as_mut_ptr(),
+                &mut encoded_signature_actual_size,
+            )
+        },
+        encoded_signature_actual_size,
+    )?;
+    Ok(encoded_signature_actual_size)
+}
+
+/// Signs the `message` with a private key derived from the given `dice_artifacts`
+/// CDI Attest. On success, places a `CoseSign1` encoded object in `encoded_signature`.
+/// Uses `DiceCoseSignAndEncodeSign1`.
+///
+/// Returns the actual size of encoded_signature on success.
+pub fn sign_cose_sign1_with_cdi_leaf_priv(
+    message: &[u8],
+    aad: &[u8],
+    dice_artifacts: &dyn DiceArtifacts,
+    encoded_signature: &mut [u8],
+) -> Result<usize> {
+    let private_key = derive_cdi_leaf_priv(dice_artifacts)?;
+    sign_cose_sign1(message, aad, private_key.as_array(), encoded_signature)
+}
+
 /// Verifies the `signature` of the `message` with the given `public_key` using `DiceVerify`.
 pub fn verify(message: &[u8], signature: &[u8], public_key: &[u8]) -> Result<()> {
     if signature.len() != VM_KEY_ALGORITHM.signature_size()
diff --git a/libs/dice/open_dice/src/retry.rs b/libs/dice/open_dice/src/retry.rs
index 803673d..cf36bc0 100644
--- a/libs/dice/open_dice/src/retry.rs
+++ b/libs/dice/open_dice/src/retry.rs
@@ -20,9 +20,10 @@
 use crate::bcc::{bcc_format_config_descriptor, bcc_main_flow, DiceConfigValues};
 use crate::dice::{
     dice_main_flow, Cdi, CdiValues, DiceArtifacts, InputValues, CDI_SIZE, PRIVATE_KEY_SEED_SIZE,
+    PRIVATE_KEY_SIZE,
 };
 use crate::error::{DiceError, Result};
-use crate::ops::generate_certificate;
+use crate::ops::{generate_certificate, sign_cose_sign1, sign_cose_sign1_with_cdi_leaf_priv};
 use alloc::vec::Vec;
 #[cfg(feature = "serde_derive")]
 use serde_derive::{Deserialize, Serialize};
@@ -144,3 +145,28 @@
         )
     })
 }
+
+/// Signs a message with the given private key and returns the signature
+/// as an encoded CoseSign1 object.
+pub fn retry_sign_cose_sign1(
+    message: &[u8],
+    aad: &[u8],
+    private_key: &[u8; PRIVATE_KEY_SIZE],
+) -> Result<Vec<u8>> {
+    retry_with_measured_buffer(|encoded_signature| {
+        sign_cose_sign1(message, aad, private_key, encoded_signature)
+    })
+}
+
+/// Signs a message with the given the private key derived from the
+/// CDI Attest of the given `dice_artifacts` and returns the signature
+/// as an encoded CoseSign1 object.
+pub fn retry_sign_cose_sign1_with_cdi_leaf_priv(
+    message: &[u8],
+    aad: &[u8],
+    dice_artifacts: &dyn DiceArtifacts,
+) -> Result<Vec<u8>> {
+    retry_with_measured_buffer(|encoded_signature| {
+        sign_cose_sign1_with_cdi_leaf_priv(message, aad, dice_artifacts, encoded_signature)
+    })
+}
diff --git a/libs/dice/open_dice/tests/api_test.rs b/libs/dice/open_dice/tests/api_test.rs
index d3a91ff..b0c2ca7 100644
--- a/libs/dice/open_dice/tests/api_test.rs
+++ b/libs/dice/open_dice/tests/api_test.rs
@@ -17,10 +17,13 @@
 #[cfg(test)]
 mod tests {
     use diced_open_dice::{
-        derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed, sign,
-        verify, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
+        derive_cdi_certificate_id, derive_cdi_private_key_seed, hash, kdf, keypair_from_seed,
+        retry_sign_cose_sign1, retry_sign_cose_sign1_with_cdi_leaf_priv, sign, verify,
+        DiceArtifacts, PrivateKey, CDI_SIZE, HASH_SIZE, ID_SIZE, PRIVATE_KEY_SEED_SIZE,
     };
 
+    use coset::{CborSerializable, CoseSign1};
+
     // This test initialization is only required for the trusty test harness.
     #[cfg(feature = "trusty")]
     test::init!();
@@ -66,7 +69,7 @@
         0x94, 0xd8, 0x8c, 0xa8,
     ];
 
-    const EXPECTED_CDI_ATTEST: &[u8] = &[
+    const EXPECTED_CDI_ATTEST: &[u8; CDI_SIZE] = &[
         0xfa, 0x3c, 0x2f, 0x58, 0x37, 0xf5, 0x8e, 0x96, 0x16, 0x09, 0xf5, 0x22, 0xa1, 0xf1, 0xba,
         0xaa, 0x19, 0x95, 0x01, 0x79, 0x2e, 0x60, 0x56, 0xaf, 0xf6, 0x41, 0xe7, 0xff, 0x48, 0xf5,
         0x3a, 0x08,
@@ -101,6 +104,85 @@
 
     #[test]
     fn hash_derive_sign_verify() {
+        let (pub_key, priv_key) = get_test_key_pair();
+
+        let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap();
+        assert_eq!(&signature, EXPECTED_SIGNATURE);
+        assert!(verify(b"MyMessage", &signature, &pub_key).is_ok());
+        assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err());
+        signature[0] += 1;
+        assert!(verify(b"MyMessage", &signature, &pub_key).is_err());
+    }
+
+    #[test]
+    fn sign_cose_sign1_verify() {
+        let (pub_key, priv_key) = get_test_key_pair();
+
+        let signature_res = retry_sign_cose_sign1(b"MyMessage", b"MyAad", priv_key.as_array());
+        assert!(signature_res.is_ok());
+        let signature = signature_res.unwrap();
+        let cose_sign1_res = CoseSign1::from_slice(&signature);
+        assert!(cose_sign1_res.is_ok());
+        let mut cose_sign1 = cose_sign1_res.unwrap();
+
+        let mut verify_result =
+            cose_sign1.verify_signature(b"MyAad", |sign, data| verify(data, sign, &pub_key));
+        assert!(verify_result.is_ok());
+
+        verify_result =
+            cose_sign1.verify_signature(b"BadAad", |sign, data| verify(data, sign, &pub_key));
+        assert!(verify_result.is_err());
+
+        // if we modify the signature, the payload should no longer verify
+        cose_sign1.signature.push(0xAA);
+        verify_result =
+            cose_sign1.verify_signature(b"MyAad", |sign, data| verify(data, sign, &pub_key));
+        assert!(verify_result.is_err());
+    }
+
+    struct TestArtifactsForSigning {}
+
+    impl DiceArtifacts for TestArtifactsForSigning {
+        fn cdi_attest(&self) -> &[u8; CDI_SIZE] {
+            EXPECTED_CDI_ATTEST
+        }
+
+        fn cdi_seal(&self) -> &[u8; CDI_SIZE] {
+            unimplemented!("no test functionality depends on this")
+        }
+
+        fn bcc(&self) -> Option<&[u8]> {
+            unimplemented!("no test functionality depends on this")
+        }
+    }
+
+    #[test]
+    fn sign_cose_sign1_with_cdi_leaf_priv_verify() {
+        let dice = TestArtifactsForSigning {};
+
+        let signature_res = retry_sign_cose_sign1_with_cdi_leaf_priv(b"MyMessage", b"MyAad", &dice);
+        assert!(signature_res.is_ok());
+        let signature = signature_res.unwrap();
+        let cose_sign1_res = CoseSign1::from_slice(&signature);
+        assert!(cose_sign1_res.is_ok());
+        let mut cose_sign1 = cose_sign1_res.unwrap();
+
+        let mut verify_result = cose_sign1
+            .verify_signature(b"MyAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY));
+        assert!(verify_result.is_ok());
+
+        verify_result = cose_sign1
+            .verify_signature(b"BadAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY));
+        assert!(verify_result.is_err());
+
+        // if we modify the signature, the payload should no longer verify
+        cose_sign1.signature.push(0xAA);
+        verify_result = cose_sign1
+            .verify_signature(b"MyAad", |sign, data| verify(data, sign, EXPECTED_PUB_KEY));
+        assert!(verify_result.is_err());
+    }
+
+    fn get_test_key_pair() -> (Vec<u8>, PrivateKey) {
         let seed = hash(b"MySeedString").unwrap();
         assert_eq!(seed, EXPECTED_SEED);
         let cdi_attest = &seed[..CDI_SIZE];
@@ -111,11 +193,7 @@
         let (pub_key, priv_key) = keypair_from_seed(cdi_private_key_seed.as_array()).unwrap();
         assert_eq!(&pub_key, EXPECTED_PUB_KEY);
         assert_eq!(priv_key.as_array(), EXPECTED_PRIV_KEY);
-        let mut signature = sign(b"MyMessage", priv_key.as_array()).unwrap();
-        assert_eq!(&signature, EXPECTED_SIGNATURE);
-        assert!(verify(b"MyMessage", &signature, &pub_key).is_ok());
-        assert!(verify(b"MyMessage_fail", &signature, &pub_key).is_err());
-        signature[0] += 1;
-        assert!(verify(b"MyMessage", &signature, &pub_key).is_err());
+
+        (pub_key, priv_key)
     }
 }
diff --git a/libs/dice/open_dice/tests/rules.mk b/libs/dice/open_dice/tests/rules.mk
index a9d332c..83a6bff 100644
--- a/libs/dice/open_dice/tests/rules.mk
+++ b/libs/dice/open_dice/tests/rules.mk
@@ -23,6 +23,7 @@
 
 MODULE_LIBRARY_DEPS += \
 	packages/modules/Virtualization/libs/dice/open_dice \
+	$(call FIND_CRATE,coset) \
 
 MODULE_RUST_TESTS := true