summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRubin Xu <rubinxu@google.com>2020-07-17 10:41:58 +0100
committerRubin Xu <rubinxu@google.com>2020-07-17 10:00:48 +0000
commit7db029a109026385ff778936383fb813e97f51c7 (patch)
tree5299885b162a0c658c34427c2fbbec359e93b069
parentc806b655b91ef19fbf3cf17364c13be7b3a6ec61 (diff)
downloadSettings-7db029a109026385ff778936383fb813e97f51c7.tar.gz
[DO NOT MERGE] Unify manual and programmatic key installation flows.
This code seems to be an adaptation of CredentialStorage. Adopt it to reflect the changes in CredentialStorage to use KeyChainService for installing keys. (Cherry-picked from d630c6005a3c3a9297b27c9c2032889da4a737af) Test: Manual CtsVerifier tests: KeyChain Storage Test, CA Cert Notification Test Test: cts-tradefed run commandAndExit cts-dev -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.MixedDeviceOwnerTest#testKeyManagement Bug: 161347472 Bug: 161517132 Change-Id: I064c85dea48f09e75237edf6dff627850afac766
-rw-r--r--src/com/android/car/settings/security/CredentialStorageActivity.java117
1 files changed, 73 insertions, 44 deletions
diff --git a/src/com/android/car/settings/security/CredentialStorageActivity.java b/src/com/android/car/settings/security/CredentialStorageActivity.java
index e9d49d7de..1f26083b9 100644
--- a/src/com/android/car/settings/security/CredentialStorageActivity.java
+++ b/src/com/android/car/settings/security/CredentialStorageActivity.java
@@ -195,53 +195,20 @@ public class CredentialStorageActivity extends FragmentActivity {
return true;
}
- boolean shouldFinish = true;
- if (installBundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
- String key = installBundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
- byte[] value = installBundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
-
- if (!mKeyStore.importKey(key, value, uid, KeyStore.FLAG_NONE)) {
- LOG.e("Failed to install " + key + " as uid " + uid);
- return true;
- }
- // The key was prepended USER_PRIVATE_KEY by the CredentialHelper. However,
- // KeyChain internally uses the raw alias name and only prepends USER_PRIVATE_KEY
- // to the key name when interfacing with KeyStore.
- // This is generally a symptom of CredentialStorage and CredentialHelper relying
- // on internal implementation details of KeyChain and imitating its functionality
- // rather than delegating to KeyChain for the certificate installation.
- if (uid == Process.SYSTEM_UID || uid == KeyStore.UID_SELF) {
- new MarkKeyAsUserSelectable(this,
- key.replaceFirst("^" + Credentials.USER_PRIVATE_KEY, "")).execute();
- shouldFinish = false;
- }
- }
-
- int flags = KeyStore.FLAG_NONE;
-
- if (installBundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
- String certName = installBundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
- byte[] certData = installBundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
-
- if (!mKeyStore.put(certName, certData, uid, flags)) {
- LOG.e("Failed to install " + certName + " as uid " + uid);
- return shouldFinish;
- }
+ String alias = installBundle.getString(Credentials.EXTRA_USER_KEY_ALIAS, null);
+ if (TextUtils.isEmpty(alias)) {
+ LOG.e("Cannot install key without an alias");
+ return true;
}
- if (installBundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) {
- String caListName = installBundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
- byte[] caListData = installBundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
+ final byte[] privateKeyData = installBundle.getByteArray(
+ Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
+ final byte[] certData = installBundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
+ final byte[] caListData = installBundle.getByteArray(
+ Credentials.EXTRA_CA_CERTIFICATES_DATA);
+ new InstallKeyInKeyChain(alias, privateKeyData, certData, caListData, uid).execute();
- if (!mKeyStore.put(caListName, caListData, uid, flags)) {
- LOG.e("Failed to install " + caListName + " as uid " + uid);
- return shouldFinish;
- }
- }
-
- sendBroadcast(new Intent(KeyChain.ACTION_KEYCHAIN_CHANGED));
- setResult(RESULT_OK);
- return shouldFinish;
+ return false;
}
/**
@@ -302,6 +269,68 @@ public class CredentialStorageActivity extends FragmentActivity {
}
/**
+ * Background task to install a certificate into KeyChain.
+ */
+ private class InstallKeyInKeyChain extends AsyncTask<Void, Void, Boolean> {
+ final String mAlias;
+ private final byte[] mKeyData;
+ private final byte[] mCertData;
+ private final byte[] mCaListData;
+ private final int mUid;
+
+ InstallKeyInKeyChain(String alias, byte[] keyData, byte[] certData, byte[] caListData,
+ int uid) {
+ mAlias = alias;
+ mKeyData = keyData;
+ mCertData = certData;
+ mCaListData = caListData;
+ mUid = uid;
+ }
+
+ @Override
+ protected Boolean doInBackground(Void... unused) {
+ try (KeyChain.KeyChainConnection keyChainConnection = KeyChain.bind(
+ CredentialStorageActivity.this)) {
+ return keyChainConnection.getService()
+ .installKeyPair(mKeyData, mCertData, mCaListData, mAlias, mUid);
+ } catch (RemoteException e) {
+ LOG.w(String.format("Failed to install key %s to uid %d", mAlias, mUid), e);
+ return false;
+ } catch (InterruptedException e) {
+ LOG.w(String.format("Interrupted while installing key %s", mAlias), e);
+ Thread.currentThread().interrupt();
+ return false;
+ }
+ }
+
+ @Override
+ protected void onPostExecute(Boolean result) {
+ LOG.i(String.format("Marked alias %s as selectable, success? %s",
+ mAlias, result));
+ CredentialStorageActivity.this.onKeyInstalled(mAlias, mUid, result);
+ }
+ }
+
+ private void onKeyInstalled(String alias, int uid, boolean result) {
+ if (!result) {
+ LOG.w(String.format("Error installing alias %s for uid %d", alias, uid));
+ finish();
+ return;
+ }
+
+ // Send the broadcast.
+ final Intent broadcast = new Intent(KeyChain.ACTION_KEYCHAIN_CHANGED);
+ sendBroadcast(broadcast);
+ setResult(RESULT_OK);
+
+ if (uid == Process.SYSTEM_UID || uid == KeyStore.UID_SELF) {
+ new MarkKeyAsUserSelectable(this, alias).execute();
+ } else {
+ finish();
+ }
+ }
+
+ /**
* Background task to mark a given key alias as user-selectable so that it can be selected by
* users from the Certificate Selection prompt.
*/