Add code to support keystore certificate post processing.

Adds the AIDL needed for the post processing service.
Also adds the client which would communicate via the post processing
service. The call to post processing depends on the presence of a
boolean system property which is set during build time.

Bug: 361877215
Test: manual testing
Change-Id: Icfc11d0d83187e036902ed1060038fc627512879
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
                 })
             }