Merge "Remove host_supported" into main
diff --git a/TEST_MAPPING b/TEST_MAPPING
index 6983fde..4da96c8 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -117,6 +117,9 @@
       "path": "packages/modules/Virtualization/service_vm/requests"
     },
     {
+      "path": "packages/modules/Virtualization/virtualizationservice"
+    },
+    {
       "path": "packages/modules/Virtualization/vm"
     },
     {
diff --git a/libs/bssl/Android.bp b/libs/bssl/Android.bp
index ff45af9..e1f4ffd 100644
--- a/libs/bssl/Android.bp
+++ b/libs/bssl/Android.bp
@@ -46,5 +46,6 @@
     rustlibs: [
         "libbssl_avf_nostd",
         "libcoset_nostd",
+        "libspki_nostd",
     ],
 }
diff --git a/libs/bssl/error/src/lib.rs b/libs/bssl/error/src/lib.rs
index 89865d4..c0dca2e 100644
--- a/libs/bssl/error/src/lib.rs
+++ b/libs/bssl/error/src/lib.rs
@@ -81,6 +81,9 @@
     EVP_AEAD_CTX_new,
     EVP_AEAD_CTX_open,
     EVP_AEAD_CTX_seal,
+    EVP_PKEY_new,
+    EVP_PKEY_set1_EC_KEY,
+    EVP_marshal_public_key,
     HKDF,
     HMAC,
     RAND_bytes,
diff --git a/libs/bssl/src/ec_key.rs b/libs/bssl/src/ec_key.rs
index 7e677c4..6436be3 100644
--- a/libs/bssl/src/ec_key.rs
+++ b/libs/bssl/src/ec_key.rs
@@ -45,7 +45,7 @@
 type Coordinate = [u8; P256_AFFINE_COORDINATE_SIZE];
 
 /// Wrapper of an `EC_KEY` object, representing a public or private EC key.
-pub struct EcKey(NonNull<EC_KEY>);
+pub struct EcKey(pub(crate) NonNull<EC_KEY>);
 
 impl Drop for EcKey {
     fn drop(&mut self) {
diff --git a/libs/bssl/src/evp.rs b/libs/bssl/src/evp.rs
new file mode 100644
index 0000000..30bfc21
--- /dev/null
+++ b/libs/bssl/src/evp.rs
@@ -0,0 +1,90 @@
+// Copyright 2023, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Wrappers of the EVP functions in BoringSSL evp.h.
+
+use crate::cbb::CbbFixed;
+use crate::ec_key::EcKey;
+use crate::util::{check_int_result, to_call_failed_error};
+use alloc::vec::Vec;
+use bssl_avf_error::{ApiName, Result};
+use bssl_ffi::{
+    CBB_flush, CBB_len, EVP_PKEY_free, EVP_PKEY_new, EVP_PKEY_set1_EC_KEY, EVP_marshal_public_key,
+    EVP_PKEY,
+};
+use core::ptr::NonNull;
+
+/// Wrapper of an `EVP_PKEY` object, representing a public or private key.
+pub struct EvpPKey {
+    pkey: NonNull<EVP_PKEY>,
+    /// Since this struct owns the inner key, the inner key remains valid as
+    /// long as the pointer to `EVP_PKEY` is valid.
+    _inner_key: EcKey,
+}
+
+impl Drop for EvpPKey {
+    fn drop(&mut self) {
+        // SAFETY: It is safe because `EVP_PKEY` has been allocated by BoringSSL and isn't
+        // used after this.
+        unsafe { EVP_PKEY_free(self.pkey.as_ptr()) }
+    }
+}
+
+/// Creates a new empty `EVP_PKEY`.
+fn new_pkey() -> Result<NonNull<EVP_PKEY>> {
+    // SAFETY: The returned pointer is checked below.
+    let key = unsafe { EVP_PKEY_new() };
+    NonNull::new(key).ok_or(to_call_failed_error(ApiName::EVP_PKEY_new))
+}
+
+impl TryFrom<EcKey> for EvpPKey {
+    type Error = bssl_avf_error::Error;
+
+    fn try_from(key: EcKey) -> Result<Self> {
+        let pkey = new_pkey()?;
+        // SAFETY: The function only sets the inner key of the initialized and
+        // non-null `EVP_PKEY` to point to the given `EC_KEY`. It only reads from
+        // and writes to the initialized `EVP_PKEY`.
+        // Since this struct owns the inner key, the inner key remains valid as
+        // long as `EVP_PKEY` is valid.
+        let ret = unsafe { EVP_PKEY_set1_EC_KEY(pkey.as_ptr(), key.0.as_ptr()) };
+        check_int_result(ret, ApiName::EVP_PKEY_set1_EC_KEY)?;
+        Ok(Self { pkey, _inner_key: key })
+    }
+}
+
+impl EvpPKey {
+    /// Returns a DER-encoded SubjectPublicKeyInfo structure as specified
+    /// in RFC 5280 s4.1.2.7:
+    ///
+    /// https://www.rfc-editor.org/rfc/rfc5280.html#section-4.1.2.7
+    pub fn subject_public_key_info(&self) -> Result<Vec<u8>> {
+        const CAPACITY: usize = 256;
+        let mut buf = [0u8; CAPACITY];
+        let mut cbb = CbbFixed::new(buf.as_mut());
+        // SAFETY: The function only write bytes to the buffer managed by the valid `CBB`.
+        // The inner key in `EVP_PKEY` was set to a valid key when the object was created.
+        // As this struct owns the inner key, the inner key is guaranteed to be valid
+        // throughout the execution of the function.
+        let ret = unsafe { EVP_marshal_public_key(cbb.as_mut(), self.pkey.as_ptr()) };
+        check_int_result(ret, ApiName::EVP_marshal_public_key)?;
+        // SAFETY: This is safe because the CBB pointer is a valid pointer initialized with
+        // `CBB_init_fixed()`.
+        check_int_result(unsafe { CBB_flush(cbb.as_mut()) }, ApiName::CBB_flush)?;
+        // SAFETY: This is safe because the CBB pointer is initialized with `CBB_init_fixed()`,
+        // and it has been flushed, thus it has no active children.
+        let len = unsafe { CBB_len(cbb.as_ref()) };
+        Ok(buf.get(0..len).ok_or(to_call_failed_error(ApiName::CBB_len))?.to_vec())
+    }
+}
diff --git a/libs/bssl/src/lib.rs b/libs/bssl/src/lib.rs
index 8e3abcf..e378386 100644
--- a/libs/bssl/src/lib.rs
+++ b/libs/bssl/src/lib.rs
@@ -24,6 +24,7 @@
 mod digest;
 mod ec_key;
 mod err;
+mod evp;
 mod hkdf;
 mod hmac;
 mod rand;
@@ -37,6 +38,7 @@
 pub use cbs::Cbs;
 pub use digest::Digester;
 pub use ec_key::{EcKey, ZVec};
+pub use evp::EvpPKey;
 pub use hkdf::hkdf;
 pub use hmac::hmac_sha256;
 pub use rand::rand_bytes;
diff --git a/libs/bssl/tests/eckey_test.rs b/libs/bssl/tests/eckey_test.rs
index 3dd243c..968af63 100644
--- a/libs/bssl/tests/eckey_test.rs
+++ b/libs/bssl/tests/eckey_test.rs
@@ -12,8 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-use bssl_avf::{sha256, ApiName, EcKey, EcdsaError, Error, Result};
+use bssl_avf::{sha256, ApiName, EcKey, EcdsaError, Error, EvpPKey, Result};
 use coset::CborSerializable;
+use spki::{
+    der::{AnyRef, Decode},
+    AlgorithmIdentifier, ObjectIdentifier, SubjectPublicKeyInfo,
+};
+
+/// OID value for general-use NIST EC keys held in PKCS#8 and X.509; see RFC 5480 s2.1.1.
+const X509_NIST_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.2.1");
+
+/// OID value in `AlgorithmIdentifier.parameters` for P-256; see RFC 5480 s2.1.1.1.
+const ALGO_PARAM_P256_OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.10045.3.1.7");
 
 const MESSAGE1: &[u8] = b"test message 1";
 const MESSAGE2: &[u8] = b"test message 2";
@@ -30,6 +40,23 @@
 }
 
 #[test]
+fn subject_public_key_info_serialization() -> Result<()> {
+    let mut ec_key = EcKey::new_p256()?;
+    ec_key.generate_key()?;
+    let pkey: EvpPKey = ec_key.try_into()?;
+    let subject_public_key_info = pkey.subject_public_key_info()?;
+
+    let subject_public_key_info = SubjectPublicKeyInfo::from_der(&subject_public_key_info).unwrap();
+    let expected_algorithm = AlgorithmIdentifier {
+        oid: X509_NIST_OID,
+        parameters: Some(AnyRef::from(&ALGO_PARAM_P256_OID)),
+    };
+    assert_eq!(expected_algorithm, subject_public_key_info.algorithm);
+    assert!(!subject_public_key_info.subject_public_key.to_vec().is_empty());
+    Ok(())
+}
+
+#[test]
 fn cose_public_key_serialization() -> Result<()> {
     let mut ec_key = EcKey::new_p256()?;
     ec_key.generate_key()?;
diff --git a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
index 51796f1..4813b35 100644
--- a/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
+++ b/microdroid_manager/aidl/android/system/virtualization/payload/IVmPayloadService.aidl
@@ -59,8 +59,8 @@
          * Sequence of DER-encoded X.509 certificates that make up the attestation
          * key's certificate chain.
          *
-         * The certificate chain starts with a root certificate and ends with a leaf
-         * certificate covering the attested public key.
+         * The certificate chain starts with a leaf certificate covering the attested
+         * public key and ends with a root certificate.
          */
         Certificate[] certificateChain;
     }
diff --git a/virtualizationservice/Android.bp b/virtualizationservice/Android.bp
index 5cf2a39..3f8d193 100644
--- a/virtualizationservice/Android.bp
+++ b/virtualizationservice/Android.bp
@@ -2,8 +2,8 @@
     default_applicable_licenses: ["Android-Apache-2.0"],
 }
 
-rust_binary {
-    name: "virtualizationservice",
+rust_defaults {
+    name: "virtualizationservice_defaults",
     crate_name: "virtualizationservice",
     defaults: ["avf_build_flags_rust"],
     edition: "2021",
@@ -45,13 +45,39 @@
         "libserde_xml_rs",
         "libservice_vm_comm",
         "libservice_vm_manager",
+        "libx509_parser",
     ],
     apex_available: ["com.android.virt"],
 }
 
+rust_binary {
+    name: "virtualizationservice",
+    defaults: ["virtualizationservice_defaults"],
+}
+
 xsd_config {
     name: "assignable_devices",
     srcs: ["assignable_devices.xsd"],
     api_dir: "schema",
     package_name: "android.system.virtualizationservice",
 }
+
+rust_test {
+    name: "virtualizationservice_test",
+    defaults: ["virtualizationservice_defaults"],
+    test_suites: ["general-tests"],
+    data: [
+        ":test_rkp_cert_chain",
+    ],
+}
+
+// The chain originates from a CTS test for Keymint, with the Keymint certificate
+// (leaf certificate) truncated.
+//
+// The certificate chain begins with a leaf certificate obtained from RKP and ends
+// with a root certificate. Each certificate in the chain possesses a signature that
+// is signed by the private key of the subsequent certificate in the chain.
+filegroup {
+    name: "test_rkp_cert_chain",
+    srcs: ["testdata/rkp_cert_chain.der"],
+}
diff --git a/virtualizationservice/TEST_MAPPING b/virtualizationservice/TEST_MAPPING
new file mode 100644
index 0000000..4fef83c
--- /dev/null
+++ b/virtualizationservice/TEST_MAPPING
@@ -0,0 +1,9 @@
+// When adding or removing tests here, don't forget to amend _all_modules list in
+// wireless/android/busytown/ath_config/configs/prod/avf/tests.gcl
+{
+  "avf-presubmit" : [
+    {
+      "name" : "virtualizationservice_test"
+    }
+  ]
+}
diff --git a/virtualizationservice/src/aidl.rs b/virtualizationservice/src/aidl.rs
index 7cdfdc6..d1f7291 100644
--- a/virtualizationservice/src/aidl.rs
+++ b/virtualizationservice/src/aidl.rs
@@ -52,6 +52,7 @@
 use tombstoned_client::{DebuggerdDumpType, TombstonedConnection};
 use vsock::{VsockListener, VsockStream};
 use nix::unistd::{chown, Uid};
+use x509_parser::{traits::FromDer, certificate::X509Certificate};
 
 /// The unique ID of a VM used (together with a port number) for vsock communication.
 pub type Cid = u32;
@@ -166,35 +167,42 @@
         requester_uid: i32,
     ) -> binder::Result<Vec<Certificate>> {
         check_manage_access()?;
-        info!("Received csr. Requestting attestation...");
-        if cfg!(remote_attestation) {
-            let attestation_key = get_rkpd_attestation_key(
-                REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
-                requester_uid as u32,
-            )
-            .context("Failed to retrieve the remotely provisioned keys")
-            .with_log()
-            .or_service_specific_exception(-1)?;
-            let certificate = request_attestation(csr, &attestation_key.keyBlob)
-                .context("Failed to request attestation")
-                .with_log()
-                .or_service_specific_exception(-1)?;
-            // TODO(b/309780089): Parse the remotely provisioned certificate chain into
-            // individual certificates.
-            let mut certificate_chain =
-                vec![Certificate { encodedCertificate: attestation_key.encodedCertChain }];
-            certificate_chain.push(Certificate { encodedCertificate: certificate });
-            Ok(certificate_chain)
-        } else {
-            Err(Status::new_exception_str(
+        if !cfg!(remote_attestation) {
+            return Err(Status::new_exception_str(
                 ExceptionCode::UNSUPPORTED_OPERATION,
                 Some(
                     "requestAttestation is not supported with the remote_attestation feature \
                      disabled",
                 ),
             ))
-            .with_log()
+            .with_log();
         }
+        info!("Received csr. Requestting attestation...");
+        let attestation_key = get_rkpd_attestation_key(
+            REMOTELY_PROVISIONED_COMPONENT_SERVICE_NAME,
+            requester_uid as u32,
+        )
+        .context("Failed to retrieve the remotely provisioned keys")
+        .with_log()
+        .or_service_specific_exception(-1)?;
+        let mut certificate_chain = split_x509_certificate_chain(&attestation_key.encodedCertChain)
+            .context("Failed to split the remotely provisioned certificate chain")
+            .with_log()
+            .or_service_specific_exception(-1)?;
+        if certificate_chain.is_empty() {
+            return Err(Status::new_service_specific_error_str(
+                -1,
+                Some("The certificate chain should contain at least 1 certificate"),
+            ))
+            .with_log();
+        }
+        let certificate = request_attestation(csr, &attestation_key.keyBlob)
+            .context("Failed to request attestation")
+            .with_log()
+            .or_service_specific_exception(-1)?;
+        certificate_chain.insert(0, Certificate { encodedCertificate: certificate });
+
+        Ok(certificate_chain)
     }
 
     fn getAssignableDevices(&self) -> binder::Result<Vec<AssignableDevice>> {
@@ -288,6 +296,17 @@
     Ok(devices)
 }
 
+fn split_x509_certificate_chain(mut cert_chain: &[u8]) -> Result<Vec<Certificate>> {
+    let mut out = Vec::new();
+    while !cert_chain.is_empty() {
+        let (remaining, _) = X509Certificate::from_der(cert_chain)?;
+        let end = cert_chain.len() - remaining.len();
+        out.push(Certificate { encodedCertificate: cert_chain[..end].to_vec() });
+        cert_chain = remaining;
+    }
+    Ok(out)
+}
+
 #[derive(Debug, Default)]
 struct GlobalVmInstance {
     /// The unique CID assigned to the VM for vsock communication.
@@ -561,3 +580,24 @@
 fn check_use_custom_virtual_machine() -> binder::Result<()> {
     check_permission("android.permission.USE_CUSTOM_VIRTUAL_MACHINE")
 }
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use std::fs;
+
+    const TEST_RKP_CERT_CHAIN_PATH: &str = "testdata/rkp_cert_chain.der";
+
+    #[test]
+    fn splitting_x509_certificate_chain_succeeds() -> Result<()> {
+        let bytes = fs::read(TEST_RKP_CERT_CHAIN_PATH)?;
+        let cert_chain = split_x509_certificate_chain(&bytes)?;
+
+        assert_eq!(4, cert_chain.len());
+        for cert in cert_chain {
+            let (remaining, _) = X509Certificate::from_der(&cert.encodedCertificate)?;
+            assert!(remaining.is_empty());
+        }
+        Ok(())
+    }
+}
diff --git a/virtualizationservice/testdata/rkp_cert_chain.der b/virtualizationservice/testdata/rkp_cert_chain.der
new file mode 100644
index 0000000..f32065d
--- /dev/null
+++ b/virtualizationservice/testdata/rkp_cert_chain.der
Binary files differ
diff --git a/vm_payload/include/vm_payload.h b/vm_payload/include/vm_payload.h
index 78cd80d..3483e1d 100644
--- a/vm_payload/include/vm_payload.h
+++ b/vm_payload/include/vm_payload.h
@@ -224,8 +224,8 @@
  * Gets the number of certificates in the certificate chain.
  *
  * The certificate chain consists of a sequence of DER-encoded X.509 certificates that form
- * the attestation key's certificate chain. It starts with a root certificate and ends with a
- * leaf certificate covering the attested public key.
+ * the attestation key's certificate chain. It starts with a leaf certificate covering the attested
+ * public key and ends with a root certificate.
  *
  * \param result A pointer to the attestation result obtained from `AVmPayload_requestAttestation`
  *               when the attestation succeeds.
@@ -240,8 +240,8 @@
  * attestation result.
  *
  * The certificate chain consists of a sequence of DER-encoded X.509 certificates that form
- * the attestation key's certificate chain. It starts with a root certificate and ends with a
- * leaf certificate covering the attested public key.
+ * the attestation key's certificate chain. It starts with a leaf certificate covering the attested
+ * public key and ends with a root certificate.
  *
  * \param result A pointer to the attestation result obtained from `AVmPayload_requestAttestation`
  *               when the attestation succeeds.