Use raw (R | S) format for COSE keys

We should use COSE format in COSE, but DER format in X.509.

Previously we were using DER everywhere - which worked, since we were
consistently wrong in both the signing and verification so the errors
canceled out.

Also some minor fixes missed from preceding CLs.

Bug: 338745127
Test: atest VmAttestationTestApp libclient_vm_csr.test
Change-Id: I5c955cba5f716c16fd85cc5f9a7270ae0bf5d40b
diff --git a/service_vm/client_vm_csr/src/lib.rs b/service_vm/client_vm_csr/src/lib.rs
index 512ecaf..0babfff 100644
--- a/service_vm/client_vm_csr/src/lib.rs
+++ b/service_vm/client_vm_csr/src/lib.rs
@@ -100,7 +100,7 @@
             sign(message, cdi_leaf_priv.as_array()).map(|v| v.to_vec())
         })?
         .try_add_created_signature(attestation_key_sig_headers, aad, |message| {
-            ecdsa_sign(message, attestation_key)
+            ecdsa_sign_cose(message, attestation_key)
         })?
         .build();
     Ok(signed_data)
@@ -113,12 +113,18 @@
     CoseSignatureBuilder::new().protected(protected).build()
 }
 
-fn ecdsa_sign(message: &[u8], key: &EcKeyRef<Private>) -> Result<Vec<u8>> {
+fn ecdsa_sign_cose(message: &[u8], key: &EcKeyRef<Private>) -> Result<Vec<u8>> {
     let digest = sha256(message);
     // Passes the digest to `ECDSA_do_sign` as recommended in the spec:
     // https://commondatastorage.googleapis.com/chromium-boringssl-docs/ecdsa.h.html#ECDSA_do_sign
     let sig = EcdsaSig::sign::<Private>(&digest, key)?;
-    Ok(sig.to_der()?)
+    ecdsa_sig_to_cose(&sig)
+}
+
+fn ecdsa_sig_to_cose(signature: &EcdsaSig) -> Result<Vec<u8>> {
+    let mut result = signature.r().to_vec_padded(ATTESTATION_KEY_AFFINE_COORDINATE_SIZE)?;
+    result.extend_from_slice(&signature.s().to_vec_padded(ATTESTATION_KEY_AFFINE_COORDINATE_SIZE)?);
+    Ok(result)
 }
 
 fn get_affine_coordinates(key: &EcKeyRef<Private>) -> Result<(Vec<u8>, Vec<u8>)> {
@@ -175,29 +181,38 @@
         let chain = dice::Chain::from_cbor(&session, &csr.dice_cert_chain)?;
         let public_key = chain.leaf().subject_public_key();
         cose_sign
-            .verify_signature(0, aad, |signature, message| public_key.verify(signature, message))?;
+            .verify_signature(0, aad, |signature, message| public_key.verify(signature, message))
+            .context("Verifying CDI_Leaf_Priv signature")?;
 
         // Checks the second signature is signed with attestation key.
         let attestation_public_key = CoseKey::from_slice(&csr_payload.public_key).unwrap();
         let ec_public_key = to_ec_public_key(&attestation_public_key)?;
-        cose_sign.verify_signature(1, aad, |signature, message| {
-            ecdsa_verify(signature, message, &ec_public_key)
-        })?;
+        cose_sign
+            .verify_signature(1, aad, |signature, message| {
+                ecdsa_verify_cose(signature, message, &ec_public_key)
+            })
+            .context("Verifying attestation key signature")?;
 
         // Verifies that private key and the public key form a valid key pair.
         let message = b"test message";
-        let signature = ecdsa_sign(message, &ec_private_key)?;
-        ecdsa_verify(&signature, message, &ec_public_key)?;
+        let signature = ecdsa_sign_cose(message, &ec_private_key)?;
+        ecdsa_verify_cose(&signature, message, &ec_public_key)
+            .context("Verifying signature with attested key")?;
 
         Ok(())
     }
 
-    fn ecdsa_verify(
+    fn ecdsa_verify_cose(
         signature: &[u8],
         message: &[u8],
         ec_public_key: &EcKeyRef<Public>,
     ) -> Result<()> {
-        let sig = EcdsaSig::from_der(signature)?;
+        let coord_bytes = signature.len() / 2;
+        assert_eq!(signature.len(), coord_bytes * 2);
+
+        let r = BigNum::from_slice(&signature[..coord_bytes])?;
+        let s = BigNum::from_slice(&signature[coord_bytes..])?;
+        let sig = EcdsaSig::from_private_components(r, s)?;
         let digest = sha256(message);
         if sig.verify(&digest, ec_public_key)? {
             Ok(())
diff --git a/service_vm/requests/src/client_vm.rs b/service_vm/requests/src/client_vm.rs
index 4f04ced..2aa7113 100644
--- a/service_vm/requests/src/client_vm.rs
+++ b/service_vm/requests/src/client_vm.rs
@@ -66,7 +66,7 @@
     // Verifies the second signature with the public key in the CSR payload.
     let ec_public_key = EcKey::from_cose_public_key_slice(&csr_payload.public_key)?;
     cose_sign.verify_signature(ATTESTATION_KEY_SIGNATURE_INDEX, aad, |signature, message| {
-        ecdsa_verify(&ec_public_key, signature, message)
+        ecdsa_verify_cose(&ec_public_key, signature, message)
     })?;
 
     let subject_public_key_info = PKey::try_from(ec_public_key)?.subject_public_key_info()?;
@@ -110,18 +110,18 @@
                 RequestProcessingError::FailedToDecryptKeyBlob
             })?;
     let ec_private_key = EcKey::from_ec_private_key(private_key.as_slice())?;
-    let signature = ecdsa_sign(&ec_private_key, &tbs_cert.to_der()?)?;
+    let signature = ecdsa_sign_der(&ec_private_key, &tbs_cert.to_der()?)?;
     let certificate = cert::build_certificate(tbs_cert, &signature)?;
     Ok(certificate.to_der()?)
 }
 
-fn ecdsa_verify(key: &EcKey, signature: &[u8], message: &[u8]) -> bssl_avf::Result<()> {
+fn ecdsa_verify_cose(key: &EcKey, signature: &[u8], message: &[u8]) -> bssl_avf::Result<()> {
     // The message was signed with ECDSA with curve P-256 and SHA-256 at the signature generation.
     let digest = sha256(message)?;
-    key.ecdsa_verify_der(signature, &digest)
+    key.ecdsa_verify_cose(signature, &digest)
 }
 
-fn ecdsa_sign(key: &EcKey, message: &[u8]) -> bssl_avf::Result<Vec<u8>> {
+fn ecdsa_sign_der(key: &EcKey, message: &[u8]) -> bssl_avf::Result<Vec<u8>> {
     let digest = sha256(message)?;
     key.ecdsa_sign_der(&digest)
 }
diff --git a/service_vm/requests/src/dice.rs b/service_vm/requests/src/dice.rs
index 7e0118e..247c34e 100644
--- a/service_vm/requests/src/dice.rs
+++ b/service_vm/requests/src/dice.rs
@@ -214,7 +214,7 @@
         if !key_ops.is_empty()
             && !key_ops.contains(&KeyOperation::Assigned(iana::KeyOperation::Verify))
         {
-            error!("Public key does not support verification");
+            error!("Public key does not support verification - key_ops: {key_ops:?}");
             return Err(RequestProcessingError::InvalidDiceChain);
         }
         Ok(Self(key))
@@ -231,7 +231,7 @@
     /// PubKeyEd25519 / PubKeyECDSA256 / PubKeyECDSA384
     ///
     /// The signature should be in the format defined by COSE in RFC 9053 section 2 for the
-    /// specifric algorithm.
+    /// specific algorithm.
     pub(crate) fn verify(&self, signature: &[u8], message: &[u8]) -> Result<()> {
         match &self.0.kty {
             KeyType::Assigned(iana::KeyType::EC2) => {