diff options
author | Rubin Xu <rubinxu@google.com> | 2020-07-17 10:41:58 +0100 |
---|---|---|
committer | Rubin Xu <rubinxu@google.com> | 2020-07-17 10:00:48 +0000 |
commit | 7db029a109026385ff778936383fb813e97f51c7 (patch) | |
tree | 5299885b162a0c658c34427c2fbbec359e93b069 | |
parent | c806b655b91ef19fbf3cf17364c13be7b3a6ec61 (diff) | |
download | Settings-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.java | 117 |
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. */ |