Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0f7721a authored by Eran Messeri's avatar Eran Messeri
Browse files

CredentialStorage: Fix manual key installation.

Since the introduction of user-selectability of keys into KeyChain,
keys installed in KeyChain, by default, cannot be granted access
by the user. This is a secure default, and means keys manually
installed by the user should be explicitly marked as user-selectable.

This change marks the user-added alias as user-selectable, so it can be
selected, later on, by the user, from the Certificate Selection prompt.

Bug: 65624467
Test: Manually with CtsVerifier (KeyChainTest).
Change-Id: I618a06270a127a38b2aa3098fddfa518515bc1b1
parent 03b2d4c4
Loading
Loading
Loading
Loading
+37 −0
Original line number Diff line number Diff line
@@ -275,6 +275,16 @@ public final class CredentialStorage extends Activity {
                Log.e(TAG, "Failed to install " + key + " as uid " + uid);
                return;
            }
            // 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(
                        key.replaceFirst("^" + Credentials.USER_PRIVATE_KEY, "")).execute();
            }
        }

        int flags = KeyStore.FLAG_NONE;
@@ -390,6 +400,33 @@ public final class CredentialStorage extends Activity {
        }
    }

    /**
     * Background task to mark a given key alias as user-selectable, so that
     * it can be selected by users from the Certificate Selection prompt.
     */
    private class MarkKeyAsUserSelectable extends AsyncTask<Void, Void, Boolean> {
        final String mAlias;

        public MarkKeyAsUserSelectable(String alias) {
            mAlias = alias;
        }

        @Override
        protected Boolean doInBackground(Void... unused) {
            try (KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this)) {
                keyChainConnection.getService().setUserSelectable(mAlias, true);
                return true;
            } catch (RemoteException e) {
                Log.w(TAG, "Failed to mark key " + mAlias + " as user-selectable.");
                return false;
            } catch (InterruptedException e) {
                Log.w(TAG, "Failed to mark key " + mAlias + " as user-selectable.");
                Thread.currentThread().interrupt();
                return false;
            }
        }
    }

    /**
     * Check that the caller is either certinstaller or Settings running in a profile of this user.
     */