keystore2: Support for RKPD attestation keys

Bug: 261214100
Test: TODO
Change-Id: I2234fb01179aec212811b864d68e5f94772c2538
diff --git a/keystore2/src/attestation_key_utils.rs b/keystore2/src/attestation_key_utils.rs
index 94f3e4c..d01cf86 100644
--- a/keystore2/src/attestation_key_utils.rs
+++ b/keystore2/src/attestation_key_utils.rs
@@ -40,6 +40,10 @@
         attestation_key: AttestationKey,
         attestation_certs: Certificate,
     },
+    RkpdProvisioned {
+        attestation_key: AttestationKey,
+        attestation_certs: Certificate,
+    },
     UserGenerated {
         key_id_guard: KeyIdGuard,
         blob: Vec<u8>,
@@ -48,6 +52,12 @@
     },
 }
 
+fn use_rkpd() -> bool {
+    let property_name = "persist.device_config.remote_key_provisioning_native.enable_rkpd";
+    let default_value = false;
+    rustutils::system_properties::read_bool(property_name, default_value).unwrap_or(default_value)
+}
+
 /// This function loads and, optionally, assigns the caller's remote provisioned
 /// attestation key if a challenge is present. Alternatively, if `attest_key_descriptor` is given,
 /// it loads the user generated attestation key from the database.
@@ -64,18 +74,34 @@
         params.iter().any(|kp| kp.tag == Tag::DEVICE_UNIQUE_ATTESTATION);
     match attest_key_descriptor {
         // Do not select an RKP key if DEVICE_UNIQUE_ATTESTATION is present.
-        None if challenge_present && !is_device_unique_attestation => rem_prov_state
-            .get_remotely_provisioned_attestation_key_and_certs(key, caller_uid, params, db)
-            .context(ks_err!("Trying to get remotely provisioned attestation key."))
-            .map(|result| {
-                result.map(|(key_id_guard, attestation_key, attestation_certs)| {
-                    AttestationKeyInfo::RemoteProvisioned {
-                        key_id_guard,
-                        attestation_key,
-                        attestation_certs,
-                    }
-                })
-            }),
+        None if challenge_present && !is_device_unique_attestation => {
+            if use_rkpd() {
+                rem_prov_state
+                    .get_rkpd_attestation_key_and_certs(key, caller_uid, params)
+                    .context(ks_err!("Trying to get attestation key from RKPD."))
+                    .map(|result| {
+                        result.map(|(attestation_key, attestation_certs)| {
+                            AttestationKeyInfo::RkpdProvisioned {
+                                attestation_key,
+                                attestation_certs,
+                            }
+                        })
+                    })
+            } else {
+                rem_prov_state
+                    .get_remotely_provisioned_attestation_key_and_certs(key, caller_uid, params, db)
+                    .context(ks_err!("Trying to get remotely provisioned attestation key."))
+                    .map(|result| {
+                        result.map(|(key_id_guard, attestation_key, attestation_certs)| {
+                            AttestationKeyInfo::RemoteProvisioned {
+                                key_id_guard,
+                                attestation_key,
+                                attestation_certs,
+                            }
+                        })
+                    })
+            }
+        }
         None => Ok(None),
         Some(attest_key) => get_user_generated_attestation_key(attest_key, caller_uid, db)
             .context(ks_err!("Trying to load attest key"))
diff --git a/keystore2/src/remote_provisioning.rs b/keystore2/src/remote_provisioning.rs
index fec1b92..cb2962a 100644
--- a/keystore2/src/remote_provisioning.rs
+++ b/keystore2/src/remote_provisioning.rs
@@ -53,6 +53,7 @@
 use crate::ks_err;
 use crate::metrics_store::log_rkp_error_stats;
 use crate::permission::KeystorePerm;
+use crate::rkpd_client::get_rkpd_attestation_key;
 use crate::utils::{check_keystore_permission, watchdog as wd};
 use android_security_metrics::aidl::android::security::metrics::RkpError::RkpError as MetricsRkpError;
 
@@ -184,7 +185,47 @@
             }
         }
     }
+
+    /// Fetches attestation key and corresponding certificates from RKPD.
+    pub fn get_rkpd_attestation_key_and_certs(
+        &self,
+        key: &KeyDescriptor,
+        caller_uid: u32,
+        params: &[KeyParameter],
+    ) -> Result<Option<(AttestationKey, Certificate)>> {
+        if !self.is_asymmetric_key(params) || key.domain != Domain::APP {
+            Ok(None)
+        } else {
+            match get_rkpd_attestation_key(&self.security_level, caller_uid) {
+                Err(e) => {
+                    if self.is_rkp_only() {
+                        log::error!("Error occurred: {:?}", e);
+                        return Err(e);
+                    }
+                    log::warn!("Error occurred: {:?}", e);
+                    log_rkp_error_stats(
+                        MetricsRkpError::FALL_BACK_DURING_HYBRID,
+                        &self.security_level,
+                    );
+                    Ok(None)
+                }
+                Ok(rkpd_key) => Ok(Some((
+                    AttestationKey {
+                        keyBlob: rkpd_key.keyBlob,
+                        attestKeyParams: vec![],
+                        // Batch certificate is at the beginning of the certificate chain.
+                        issuerSubjectName: parse_subject_from_certificate(
+                            &rkpd_key.encodedCertChain,
+                        )
+                        .context(ks_err!("Failed to parse subject."))?,
+                    },
+                    Certificate { encodedCertificate: rkpd_key.encodedCertChain },
+                ))),
+            }
+        }
+    }
 }
+
 /// Implementation of the IRemoteProvisioning service.
 #[derive(Default)]
 pub struct RemoteProvisioningService {
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 66fcb26..b928fb0 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -26,6 +26,7 @@
 use crate::ks_err;
 use crate::metrics_store::log_key_creation_event_stats;
 use crate::remote_provisioning::RemProvState;
+use crate::rkpd_client::store_rkpd_attestation_key;
 use crate::super_key::{KeyBlob, SuperKeyManager};
 use crate::utils::{
     check_device_attestation_permissions, check_key_permission,
@@ -616,6 +617,30 @@
                     result.certificateChain.push(attestation_certs);
                     result
                 }),
+            Some(AttestationKeyInfo::RkpdProvisioned { attestation_key, attestation_certs }) => {
+                self.upgrade_rkpd_keyblob_if_required_with(&attestation_key.keyBlob, &[], |blob| {
+                    map_km_error({
+                        let _wp = self.watch_millis(
+                            concat!(
+                                "In KeystoreSecurityLevel::generate_key (RkpdProvisioned): ",
+                                "calling generate_key.",
+                            ),
+                            5000, // Generate can take a little longer.
+                        );
+                        let dynamic_attest_key = Some(AttestationKey {
+                            keyBlob: blob.to_vec(),
+                            attestKeyParams: vec![],
+                            issuerSubjectName: attestation_key.issuerSubjectName.clone(),
+                        });
+                        self.keymint.generateKey(&params, dynamic_attest_key.as_ref())
+                    })
+                })
+                .context("While generating Key with remote provisioned attestation key.")
+                .map(|(mut result, _)| {
+                    result.certificateChain.push(attestation_certs);
+                    result
+                })
+            }
             None => map_km_error({
                 let _wp = self.watch_millis(
                     concat!(
@@ -888,6 +913,28 @@
         Ok((v, upgraded_blob))
     }
 
+    fn upgrade_rkpd_keyblob_if_required_with<T, F>(
+        &self,
+        key_blob: &[u8],
+        params: &[KeyParameter],
+        f: F,
+    ) -> Result<(T, Option<Vec<u8>>)>
+    where
+        F: Fn(&[u8]) -> Result<T, Error>,
+    {
+        crate::utils::upgrade_keyblob_if_required_with(
+            &*self.keymint,
+            key_blob,
+            params,
+            f,
+            |upgraded_blob| {
+                store_rkpd_attestation_key(&self.security_level, key_blob, upgraded_blob)
+                    .context(ks_err!("Failed store_rkpd_attestation_key()."))
+            },
+        )
+        .context(ks_err!())
+    }
+
     fn convert_storage_key_to_ephemeral(
         &self,
         storage_key: &KeyDescriptor,