Merge "Do not use RKP for DEVICE_UNIQUE_ATTESTATION."
diff --git a/keystore2/src/database.rs b/keystore2/src/database.rs
index a3979bd..baa3b12 100644
--- a/keystore2/src/database.rs
+++ b/keystore2/src/database.rs
@@ -2581,7 +2581,7 @@
 
                 Ok((key_id, access_key, access_vector))
             }
-            _ => Err(anyhow!(KsError::sys())),
+            _ => Err(anyhow!(KsError::Rc(ResponseCode::INVALID_ARGUMENT))),
         }
     }
 
diff --git a/keystore2/src/shared_secret_negotiation.rs b/keystore2/src/shared_secret_negotiation.rs
index 1862f73..42d38d2 100644
--- a/keystore2/src/shared_secret_negotiation.rs
+++ b/keystore2/src/shared_secret_negotiation.rs
@@ -15,6 +15,7 @@
 //! This module implements the shared secret negotiation.
 
 use crate::error::{map_binder_status, map_binder_status_code, Error};
+use crate::globals::get_keymint_device;
 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
 use android_hardware_security_keymint::binder::Strong;
 use android_hardware_security_sharedsecret::aidl::android::hardware::security::sharedsecret::{
@@ -43,6 +44,10 @@
         let connected = connect_participants(participants);
         negotiate_shared_secret(connected);
         log::info!("Shared secret negotiation concluded successfully.");
+
+        // Once shared secret negotiation is done, the StrongBox and TEE have a common key that
+        // can be used to authenticate a possible RootOfTrust transfer.
+        transfer_root_of_trust();
     });
 }
 
@@ -278,3 +283,48 @@
         }
     }
 }
+
+/// Perform RootOfTrust transfer from TEE to StrongBox (if available).
+pub fn transfer_root_of_trust() {
+    let strongbox = match get_keymint_device(&SecurityLevel::STRONGBOX) {
+        Ok((s, _, _)) => s,
+        Err(_e) => {
+            log::info!("No StrongBox Keymint available, so no RoT transfer");
+            return;
+        }
+    };
+    // Ask the StrongBox KeyMint for a challenge.
+    let challenge = match strongbox.getRootOfTrustChallenge() {
+        Ok(data) => data,
+        Err(e) => {
+            // If StrongBox doesn't provide a challenge, it might be because:
+            // - it already has RootOfTrust information
+            // - it's a KeyMint v1 implementation that doesn't understand the method.
+            // In either case, we're done.
+            log::info!("StrongBox does not provide a challenge, so no RoT transfer: {:?}", e);
+            return;
+        }
+    };
+    // Get the RoT info from the TEE
+    let tee = match get_keymint_device(&SecurityLevel::TRUSTED_ENVIRONMENT) {
+        Ok((s, _, _)) => s,
+        Err(e) => {
+            log::error!("No TEE KeyMint implementation found! {:?}", e);
+            return;
+        }
+    };
+    let root_of_trust = match tee.getRootOfTrust(&challenge) {
+        Ok(rot) => rot,
+        Err(e) => {
+            log::error!("TEE KeyMint failed to return RootOfTrust info: {:?}", e);
+            return;
+        }
+    };
+    // The RootOfTrust information is CBOR-serialized data, but we don't need to parse it.
+    // Just pass it on to the StrongBox KeyMint instance.
+    let result = strongbox.sendRootOfTrust(&root_of_trust);
+    if let Err(e) = result {
+        log::error!("Failed to send RootOfTrust to StrongBox: {:?}", e);
+    }
+    log::info!("RootOfTrust transfer process complete");
+}
diff --git a/keystore2/tests/keystore2_client_tests.rs b/keystore2/tests/keystore2_client_tests.rs
index cfb8a41..f027d88 100644
--- a/keystore2/tests/keystore2_client_tests.rs
+++ b/keystore2/tests/keystore2_client_tests.rs
@@ -321,3 +321,143 @@
         .count();
     assert!(busy_count > 0);
 }
+
+/// This test will verify the use case with the same owner(UID) requesting `n` number of operations.
+/// This test confirms that when all operation slots are full and a new operation is requested,
+/// an operation which is least recently used and lived longest will be pruned to make a room
+/// for a new operation. Pruning strategy should prevent the operations of the other owners(UID)
+/// from being pruned.
+///
+/// 1. Create an operation in a child process with `untrusted_app` context and wait for parent
+///    notification to complete the operation.
+/// 2. Let parent process create `n` number of operations such that there are enough operations
+///    outstanding to trigger cannibalizing their own sibling operations.
+/// 3. Sequentially try to use above created `n` number of operations and also add a new operation,
+///    so that it should trigger cannibalizing one of their own sibling operations.
+///    3.1 While trying to use these pruned operations an `INVALID_OPERATION_HANDLE` error is
+///        expected as they are already pruned.
+/// 4. Notify the child process to resume and complete the operation. It is expected to complete the
+///    operation successfully.
+/// 5. Try to use the latest operation of parent. It is expected to complete the operation
+///    successfully.
+#[test]
+fn keystore2_ops_prune_test() {
+    const MAX_OPS: usize = 40; // This should be at least 32 with sec_level TEE.
+
+    static TARGET_CTX: &str = "u:r:untrusted_app:s0";
+    const USER_ID: u32 = 99;
+    const APPLICATION_ID: u32 = 10601;
+
+    let uid = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+    let gid = USER_ID * AID_USER_OFFSET + APPLICATION_ID;
+
+    // Create an operation in an untrusted_app context. Wait until the parent notifies to continue.
+    // Once the parent notifies, this operation is expected to be completed successfully.
+    let alias = format!("ks_reg_op_key_{}", getuid());
+    let mut child_handle = execute_op_run_as_child(
+        TARGET_CTX,
+        Domain::APP,
+        -1,
+        Some(alias),
+        Uid::from_raw(uid),
+        Gid::from_raw(gid),
+        ForcedOp(false),
+    );
+
+    // Wait until child process notifies us to continue, so that an operation from child process is
+    // outstanding to complete the operation.
+    child_handle.recv();
+
+    // Generate a key to use in below operations.
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+    let alias = format!("ks_prune_op_test_key_{}", getuid());
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::SELINUX,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        Some(alias),
+        None,
+        None,
+    )
+    .unwrap();
+
+    // Create multiple operations in this process to trigger cannibalizing sibling operations.
+    let mut ops: Vec<binder::Result<CreateOperationResponse>> = (0..MAX_OPS)
+        .into_iter()
+        .map(|_| {
+            sec_level.createOperation(
+                &key_metadata.key,
+                &authorizations::AuthSetBuilder::new()
+                    .purpose(KeyPurpose::SIGN)
+                    .digest(Digest::SHA_2_256),
+                false,
+            )
+        })
+        .collect();
+
+    // Sequentially try to use operation handles created above and also add a new operation.
+    for vec_index in 0..MAX_OPS {
+        match &ops[vec_index] {
+            Ok(CreateOperationResponse { iOperation: Some(op), .. }) => {
+                // Older operation handle is pruned, if we try to use that an error is expected.
+                assert_eq!(
+                    Err(Error::Km(ErrorCode::INVALID_OPERATION_HANDLE)),
+                    key_generations::map_ks_error(op.update(b"my message"))
+                );
+            }
+            _ => panic!("Operation should have created successfully."),
+        }
+
+        // Create a new operation, it should trigger to cannibalize one of their own sibling
+        // operations.
+        ops.push(
+            sec_level.createOperation(
+                &key_metadata.key,
+                &authorizations::AuthSetBuilder::new()
+                    .purpose(KeyPurpose::SIGN)
+                    .digest(Digest::SHA_2_256),
+                false,
+            ),
+        );
+    }
+
+    // Notify child process to continue the operation.
+    child_handle.send(&BarrierReached {});
+    assert!((child_handle.get_result() == TestOutcome::Ok), "Failed to perform an operation");
+
+    // Try to use the latest operation created by parent, should be able to use it successfully.
+    match ops.last() {
+        Some(Ok(CreateOperationResponse { iOperation: Some(op), .. })) => {
+            assert_eq!(Ok(()), key_generations::map_ks_error(perform_sample_sign_operation(op)));
+        }
+        _ => panic!("Operation should have created successfully."),
+    }
+}
+
+/// This test will try to load the key with Domain::BLOB.
+/// INVALID_ARGUMENT error is expected.
+#[test]
+fn keystore2_get_key_entry_blob_fail() {
+    let keystore2 = get_keystore_service();
+    let sec_level = keystore2.getSecurityLevel(SecurityLevel::TRUSTED_ENVIRONMENT).unwrap();
+
+    // Generate a key with domain as BLOB.
+    let key_metadata = key_generations::generate_ec_p256_signing_key(
+        &sec_level,
+        Domain::BLOB,
+        key_generations::SELINUX_SHELL_NAMESPACE,
+        None,
+        None,
+        None,
+    )
+    .unwrap();
+
+    // Try to load the key using above generated KeyDescriptor.
+    let result = key_generations::map_ks_error(keystore2.getKeyEntry(&key_metadata.key));
+    assert!(result.is_err());
+    assert_eq!(Error::Rc(ResponseCode::INVALID_ARGUMENT), result.unwrap_err());
+
+    // Delete the generated key blob.
+    sec_level.deleteKey(&key_metadata.key).unwrap();
+}