Merge changes Ia1ea17f6,I7c04464c,Id10efe4e into main

* changes:
  Add and use run_as::run_as_app helper
  Add and use run_as::run_as_root helper
  Minimize unsafe blocks
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 88b674e..4da0b6a 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -13,6 +13,7 @@
 // limitations under the License.
 
 package {
+    default_team: "trendy_team_android_hardware_backed_security",
     // See: http://go/android-license-faq
     // A large-scale-change added 'default_applicable_licenses' to import
     // all of the 'license_kinds' from "system_security_license"
@@ -59,6 +60,7 @@
         "liblibc",
         "liblog_rust",
         "libmessage_macro",
+        "libpostprocessor_client",
         "librand",
         "librkpd_client",
         "librustutils",
diff --git a/keystore2/OWNERS b/keystore2/OWNERS
index bf9d61b..aeb8390 100644
--- a/keystore2/OWNERS
+++ b/keystore2/OWNERS
@@ -1,6 +1,5 @@
 set noparent
 # Bug component: 1084732
-eranm@google.com
 drysdale@google.com
 hasinitg@google.com
 jbires@google.com
diff --git a/keystore2/aidl/Android.bp b/keystore2/aidl/Android.bp
index ae3fb18..afc2743 100644
--- a/keystore2/aidl/Android.bp
+++ b/keystore2/aidl/Android.bp
@@ -123,6 +123,26 @@
 }
 
 aidl_interface {
+    name: "android.security.postprocessor",
+    srcs: ["android/security/postprocessor/*.aidl"],
+    unstable: true,
+    backend: {
+        java: {
+            enabled: false,
+        },
+        cpp: {
+            enabled: false,
+        },
+        ndk: {
+            enabled: false,
+        },
+        rust: {
+            enabled: true,
+        },
+    },
+}
+
+aidl_interface {
     name: "android.security.metrics",
     srcs: ["android/security/metrics/*.aidl"],
     imports: [
diff --git a/keystore2/aidl/android/security/postprocessor/CertificateChain.aidl b/keystore2/aidl/android/security/postprocessor/CertificateChain.aidl
new file mode 100644
index 0000000..8d9daad
--- /dev/null
+++ b/keystore2/aidl/android/security/postprocessor/CertificateChain.aidl
@@ -0,0 +1,34 @@
+// Copyright 2024, 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.
+
+package android.security.postprocessor;
+
+/**
+ * General parcelable for holding the encoded certificates to be used in Keystore. This parcelable
+ * is returned by `IKeystoreCertificatePostProcessor::processKeystoreCertificates`.
+ * @hide
+ */
+@RustDerive(Clone=true)
+parcelable CertificateChain {
+    /**
+     * Holds the DER-encoded representation of the leaf certificate.
+     */
+    byte[] leafCertificate;
+    /**
+     * Holds a byte array containing the concatenation of all the remaining elements of the
+     * certificate chain with root certificate as the last with each certificate represented in
+     * DER-encoded format.
+     */
+    byte[] remainingChain;
+}
diff --git a/keystore2/aidl/android/security/postprocessor/IKeystoreCertificatePostProcessor.aidl b/keystore2/aidl/android/security/postprocessor/IKeystoreCertificatePostProcessor.aidl
new file mode 100644
index 0000000..0ceaacb
--- /dev/null
+++ b/keystore2/aidl/android/security/postprocessor/IKeystoreCertificatePostProcessor.aidl
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2024 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.
+ */
+
+package android.security.postprocessor;
+
+import android.security.postprocessor.CertificateChain;
+
+interface IKeystoreCertificatePostProcessor {
+    /**
+     * Allows implementing services to process the keystore certificates after the certificate
+     * chain has been generated.
+     *
+     * certificateChain holds the chain associated with a newly generated Keystore asymmetric
+     * keypair, where the leafCertificate is the certificate for the public key of generated key.
+     * The remaining attestation certificates are stored as a concatenated byte array of the
+     * encoded certificates with root certificate as the last element.
+     *
+     * Successful calls would get the processed certificate chain which then replaces the original
+     * certificate chain. In case of any failures/exceptions, keystore would fallback to the
+     * original certificate chain.
+     *
+     * @hide
+     */
+    CertificateChain processKeystoreCertificates(in CertificateChain certificateChain);
+}
diff --git a/keystore2/postprocessor_client/Android.bp b/keystore2/postprocessor_client/Android.bp
new file mode 100644
index 0000000..7f0194a
--- /dev/null
+++ b/keystore2/postprocessor_client/Android.bp
@@ -0,0 +1,47 @@
+//
+// Copyright 2024, 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.
+
+package {
+    // See: http://go/android-license-faq
+    // A large-scale-change added 'default_applicable_licenses' to import
+    // all of the 'license_kinds' from "system_security_license"
+    // to get the below license kinds:
+    //   SPDX-license-identifier-Apache-2.0
+    default_applicable_licenses: ["system_security_license"],
+}
+
+rust_defaults {
+    name: "libpostprocessor_client_defaults",
+    crate_name: "postprocessor_client",
+    srcs: ["src/lib.rs"],
+    rustlibs: [
+        "android.security.postprocessor-rust",
+        "libanyhow",
+        "libbinder_rs",
+        "liblog_rust",
+        "libmessage_macro",
+        "libthiserror",
+    ],
+    defaults: [
+        "keymint_use_latest_hal_aidl_rust",
+    ],
+}
+
+rust_library {
+    name: "libpostprocessor_client",
+    defaults: [
+        "libpostprocessor_client_defaults",
+    ],
+}
diff --git a/keystore2/postprocessor_client/src/lib.rs b/keystore2/postprocessor_client/src/lib.rs
new file mode 100644
index 0000000..8b347f9
--- /dev/null
+++ b/keystore2/postprocessor_client/src/lib.rs
@@ -0,0 +1,109 @@
+// Copyright 2024, 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.
+
+//! Helper wrapper around PostProcessor interface.
+
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::Certificate::Certificate;
+use android_security_postprocessor::aidl::android::security::postprocessor::{
+    CertificateChain::CertificateChain,
+    IKeystoreCertificatePostProcessor::IKeystoreCertificatePostProcessor,
+};
+use anyhow::{Context, Result};
+use binder::{StatusCode, Strong};
+use log::{error, info, warn};
+use message_macro::source_location_msg;
+use std::sync::atomic::{AtomicBool, Ordering};
+use std::sync::mpsc;
+use std::thread;
+use std::time::Duration;
+
+/// Errors occurred during the interaction with Certificate Processor
+#[derive(Debug, Clone, Copy, thiserror::Error, PartialEq, Eq)]
+#[error("Binder transaction error {0:?}")]
+pub struct Error(pub StatusCode);
+
+static CERT_PROCESSOR_FAILURE: AtomicBool = AtomicBool::new(false);
+
+fn send_certificate_chain_to_processor(
+    attestation_chain: CertificateChain,
+) -> Result<CertificateChain> {
+    let cert_processing_server: Strong<dyn IKeystoreCertificatePostProcessor> = wait_for_interface(
+        "rkp_cert_processor.service".to_string(),
+    )
+    .context(source_location_msg!("While trying to connect to the post processor service."))?;
+    cert_processing_server
+        .processKeystoreCertificates(&attestation_chain)
+        .context(source_location_msg!("While trying to post process certificates."))
+}
+
+/// Processes the keystore certificates after the certificate chain has been generated by Keystore.
+/// More details about this function provided in IKeystoreCertificatePostProcessor.aidl
+pub fn process_certificate_chain(
+    mut certificates: Vec<Certificate>,
+    attestation_certs: Vec<u8>,
+) -> Vec<Certificate> {
+    // If no certificates are provided from keymint, return the original chain.
+    if certificates.is_empty() {
+        error!("No leaf certificate provided.");
+        return vec![Certificate { encodedCertificate: attestation_certs }];
+    }
+
+    if certificates.len() > 1 {
+        warn!("dropping {} unexpected extra certificates after the leaf", certificates.len() - 1);
+    }
+
+    let attestation_chain = CertificateChain {
+        leafCertificate: certificates[0].encodedCertificate.clone(),
+        remainingChain: attestation_certs.clone(),
+    };
+    let result = send_certificate_chain_to_processor(attestation_chain);
+    match result {
+        Ok(certificate_chain) => {
+            info!("Post processing successful. Replacing certificates.");
+            vec![
+                Certificate { encodedCertificate: certificate_chain.leafCertificate },
+                Certificate { encodedCertificate: certificate_chain.remainingChain },
+            ]
+        }
+        Err(err) => {
+            error!("Failed to replace certificates ({err:#?}), falling back to original chain.");
+            certificates.push(Certificate { encodedCertificate: attestation_certs });
+            certificates
+        }
+    }
+}
+
+fn wait_for_interface(
+    service_name: String,
+) -> Result<Strong<dyn IKeystoreCertificatePostProcessor>> {
+    if CERT_PROCESSOR_FAILURE.load(Ordering::Relaxed) {
+        return Err(Error(StatusCode::INVALID_OPERATION).into());
+    }
+    let (sender, receiver) = mpsc::channel();
+    let _t = thread::spawn(move || {
+        if let Err(e) = sender.send(binder::wait_for_interface(&service_name)) {
+            error!("failed to send result of wait_for_interface({service_name}), likely due to timeout: {e:?}");
+        }
+    });
+
+    match receiver.recv_timeout(Duration::from_secs(5)) {
+        Ok(service_binder) => Ok(service_binder?),
+        Err(e) => {
+            error!("Timed out while connecting to post processor service: {e:#?}");
+            // Cert processor has failed. Retry only after reboot.
+            CERT_PROCESSOR_FAILURE.store(true, Ordering::Relaxed);
+            Err(e.into())
+        }
+    }
+}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index 5e80266..d57ba0c 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -34,6 +34,7 @@
     ExceptionCode, Result as BinderResult, Status as BinderStatus, StatusCode,
 };
 use keystore2_selinux as selinux;
+use postprocessor_client::Error as PostProcessorError;
 use rkpd_client::Error as RkpdError;
 use std::cmp::PartialEq;
 use std::ffi::CString;
@@ -103,6 +104,14 @@
     }
 }
 
+impl From<PostProcessorError> for Error {
+    fn from(e: PostProcessorError) -> Self {
+        match e {
+            PostProcessorError(s) => Error::BinderTransaction(s),
+        }
+    }
+}
+
 /// Maps an `rkpd_client::Error` that is wrapped with an `anyhow::Error` to a keystore2 `Error`.
 pub fn wrapped_rkpd_error_to_ks_error(e: &anyhow::Error) -> Error {
     match e.downcast_ref::<RkpdError>() {
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 89c0e97..233f2ae 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -64,7 +64,9 @@
     KeyMetadata::KeyMetadata, KeyParameters::KeyParameters, ResponseCode::ResponseCode,
 };
 use anyhow::{anyhow, Context, Result};
+use postprocessor_client::process_certificate_chain;
 use rkpd_client::store_rkpd_attestation_key;
+use rustutils::system_properties::read_bool;
 use std::convert::TryInto;
 use std::time::SystemTime;
 
@@ -632,14 +634,30 @@
                     log_security_safe_params(&params)
                 ))
                 .map(|(mut result, _)| {
-                    // The `certificateChain` in a `KeyCreationResult` should normally have one
-                    // `Certificate` for each certificate in the chain. To avoid having to
-                    // unnecessarily parse the RKP chain (which is concatenated DER-encoded certs),
-                    // stuff the whole concatenated chain into a single `Certificate`.
-                    // This is untangled by `store_new_key()`.
-                    result
-                        .certificateChain
-                        .push(Certificate { encodedCertificate: attestation_certs });
+                    if read_bool("remote_provisioning.use_cert_processor", false).unwrap_or(false) {
+                        let _wp = self.watch_millis(
+                            concat!(
+                                "KeystoreSecurityLevel::generate_key (RkpdProvisioned): ",
+                                "calling KeystorePostProcessor::process_certificate_chain",
+                            ),
+                            1000, // Post processing may take a little while due to network call.
+                        );
+                        // process_certificate_chain would either replace the certificate chain if
+                        // post-processing is successful or it would fallback to the original chain
+                        // on failure. In either case, we should get back the certificate chain
+                        // that is fit for storing with the newly generated key.
+                        result.certificateChain =
+                            process_certificate_chain(result.certificateChain, attestation_certs);
+                    } else {
+                        // The `certificateChain` in a `KeyCreationResult` should normally have one
+                        // `Certificate` for each certificate in the chain. To avoid having to
+                        // unnecessarily parse the RKP chain (which is concatenated DER-encoded
+                        // certs), stuff the whole concatenated chain into a single `Certificate`.
+                        // This is untangled by `store_new_key()`.
+                        result
+                            .certificateChain
+                            .push(Certificate { encodedCertificate: attestation_certs });
+                    }
                     result
                 })
             }
diff --git a/keystore2/tests/keystore2_client_authorizations_tests.rs b/keystore2/tests/keystore2_client_authorizations_tests.rs
index 4e83f73..bd9dab9 100644
--- a/keystore2/tests/keystore2_client_authorizations_tests.rs
+++ b/keystore2/tests/keystore2_client_authorizations_tests.rs
@@ -13,7 +13,7 @@
 // limitations under the License.
 
 use crate::keystore2_client_test_utils::{
-    app_attest_key_feature_exists, delete_app_key,
+    app_attest_key_feature_exists, delete_app_key, get_vsr_api_level,
     perform_sample_asym_sign_verify_op, perform_sample_hmac_sign_verify_op,
     perform_sample_sym_key_decrypt_op, perform_sample_sym_key_encrypt_op,
     verify_certificate_serial_num, verify_certificate_subject_name, SAMPLE_PLAIN_TEXT,
@@ -638,6 +638,11 @@
 #[test]
 fn keystore2_gen_key_auth_app_data_app_id_test_success() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     let gen_params = authorizations::AuthSetBuilder::new()
         .no_auth_required()
@@ -669,6 +674,11 @@
 #[test]
 fn keystore2_op_auth_invalid_app_data_app_id_test_fail() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     let gen_params = authorizations::AuthSetBuilder::new()
         .no_auth_required()
@@ -701,6 +711,11 @@
 #[test]
 fn keystore2_op_auth_missing_app_data_test_fail() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     let gen_params = authorizations::AuthSetBuilder::new()
         .no_auth_required()
@@ -733,6 +748,11 @@
 #[test]
 fn keystore2_op_auth_missing_app_id_test_fail() {
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     let gen_params = authorizations::AuthSetBuilder::new()
         .no_auth_required()
@@ -766,6 +786,11 @@
 fn keystore2_gen_attested_key_auth_app_id_app_data_test_success() {
     skip_test_if_no_app_attest_key_feature!();
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     // Generate attestation key.
     let attest_gen_params = authorizations::AuthSetBuilder::new()
@@ -822,6 +847,11 @@
 fn keystore2_gen_attestation_key_with_auth_app_id_app_data_test_fail() {
     skip_test_if_no_app_attest_key_feature!();
     let sl = SecLevel::tee();
+    if sl.is_keymaster() && get_vsr_api_level() < 35 {
+        // `APPLICATION_DATA` key-parameter is causing the error on older devices, so skipping this
+        // test to run on older devices.
+        return;
+    }
 
     // Generate attestation key.
     let attest_gen_params = authorizations::AuthSetBuilder::new()