Keystore 2.0: Add Pure Certificate Entry suport.

Allow storing certificates without keys.
Also allow deleting subcomponents by setting corresponding arguments to
None.

Test: KeyStore CTS and keystore2_test
Change-Id: Ie3c937941c6dd6d4a43cd86273cce4f0d7880ca6
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index f8650e6..e57a9b7 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -111,21 +111,26 @@
             })
             .context("In get_key_entry, while trying to load key info.")?;
 
-        let i_sec_level = self
-            .get_security_level_internal(key_entry.sec_level())
-            .context("In get_key_entry.")?
-            .ok_or_else(|| {
-                anyhow!(error::Error::sys()).context(format!(
-                    concat!(
-                        "Found key with security level {:?} ",
-                        "but no KeyMint instance of that security level."
-                    ),
-                    key_entry.sec_level()
-                ))
-            })?;
+        let i_sec_level = if !key_entry.pure_cert() {
+            Some(
+                self.get_security_level_internal(key_entry.sec_level())
+                    .context("In get_key_entry.")?
+                    .ok_or_else(|| {
+                        anyhow!(error::Error::sys()).context(format!(
+                            concat!(
+                                "Found key with security level {:?} ",
+                                "but no KeyMint instance of that security level."
+                            ),
+                            key_entry.sec_level()
+                        ))
+                    })?,
+            )
+        } else {
+            None
+        };
 
         Ok(KeyEntryResponse {
-            iSecurityLevel: Some(i_sec_level),
+            iSecurityLevel: i_sec_level,
             metadata: KeyMetadata {
                 key: KeyDescriptor {
                     domain: Domain::KEY_ID,
@@ -154,28 +159,61 @@
     ) -> Result<()> {
         DB.with::<_, Result<()>>(|db| {
             let mut db = db.borrow_mut();
-            let (key_id_guard, key_entry) = db
-                .load_key_entry(
-                    key.clone(),
-                    KeyType::Client,
-                    KeyEntryLoadBits::NONE,
-                    ThreadState::get_calling_uid(),
-                    |k, av| {
-                        check_key_permission(KeyPerm::update(), k, &av)
-                            .context("In update_subcomponent.")
-                    },
-                )
-                .context("Failed to load key_entry.")?;
+            let entry = match db.load_key_entry(
+                key.clone(),
+                KeyType::Client,
+                KeyEntryLoadBits::NONE,
+                ThreadState::get_calling_uid(),
+                |k, av| {
+                    check_key_permission(KeyPerm::update(), k, &av)
+                        .context("In update_subcomponent.")
+                },
+            ) {
+                Err(e) => match e.root_cause().downcast_ref::<Error>() {
+                    Some(Error::Rc(ResponseCode::KEY_NOT_FOUND)) => Ok(None),
+                    _ => Err(e),
+                },
+                Ok(v) => Ok(Some(v)),
+            }
+            .context("Failed to load key entry.")?;
 
-            if let Some(cert) = public_cert {
-                db.insert_blob(&key_id_guard, SubComponentType::CERT, cert)
+            if let Some((key_id_guard, key_entry)) = entry {
+                db.set_blob(&key_id_guard, SubComponentType::CERT, public_cert)
                     .context("Failed to update cert subcomponent.")?;
+
+                db.set_blob(&key_id_guard, SubComponentType::CERT_CHAIN, certificate_chain)
+                    .context("Failed to update cert chain subcomponent.")?;
+                return Ok(());
             }
 
-            if let Some(cert_chain) = certificate_chain {
-                db.insert_blob(&key_id_guard, SubComponentType::CERT_CHAIN, cert_chain)
-                    .context("Failed to update cert chain subcomponent.")?;
+            // If we reach this point we have to check the special condition where a certificate
+            // entry may be made.
+            if !(public_cert.is_none() && certificate_chain.is_some()) {
+                return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND)).context("No key to update.");
             }
+
+            // So we know that we have a certificate chain and no public cert.
+            // Now check that we have everything we need to make a new certificate entry.
+            let key = match (key.domain, &key.alias) {
+                (Domain::APP, Some(ref alias)) => KeyDescriptor {
+                    domain: Domain::APP,
+                    nspace: ThreadState::get_calling_uid() as i64,
+                    alias: Some(alias.clone()),
+                    blob: None,
+                },
+                (Domain::SELINUX, Some(_)) => key.clone(),
+                _ => {
+                    return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT))
+                        .context("Domain must be APP or SELINUX to insert a certificate.")
+                }
+            };
+
+            // Security critical: This must return on failure. Do not remove the `?`;
+            check_key_permission(KeyPerm::rebind(), &key, &None)
+                .context("Caller does not have permission to insert this certificate.")?;
+
+            db.store_new_certificate(key, certificate_chain.unwrap())
+                .context("Failed to insert new certificate.")?;
             Ok(())
         })
         .context("In update_subcomponent.")