191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh/*
291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Copyright (C) 2011 The Android Open Source Project
391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Licensed under the Apache License, Version 2.0 (the "License");
591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * you may not use this file except in compliance with the License.
691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * You may obtain a copy of the License at
791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *      http://www.apache.org/licenses/LICENSE-2.0
991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh *
1091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * Unless required by applicable law or agreed to in writing, software
1191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * distributed under the License is distributed on an "AS IS" BASIS,
1291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * See the License for the specific language governing permissions and
1491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh * limitations under the License.
1591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh */
1691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehpackage com.android.settings;
1891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.app.Activity;
2091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.app.AlertDialog;
21d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport android.app.admin.DevicePolicyManager;
22565653cef1039ab4e34e505185f1c77d847357cdJulia Reynoldsimport android.content.Context;
2391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.DialogInterface;
2491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.content.Intent;
25307e3d048d6e89bc8419ac5d3f480841c84fc5a2Zoltan Szatmary-Banimport android.content.pm.PackageManager;
268823c3eda28930bcd6c8242bfed15b098d63acd0Robin Leeimport android.content.pm.UserInfo;
270e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.content.res.Resources;
289815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.AsyncTask;
2991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.os.Bundle;
309815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.RemoteException;
316c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport android.os.Process;
328823c3eda28930bcd6c8242bfed15b098d63acd0Robin Leeimport android.os.UserHandle;
33565653cef1039ab4e34e505185f1c77d847357cdJulia Reynoldsimport android.os.UserManager;
34b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Rootimport android.security.Credentials;
35435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstromimport android.security.KeyChain.KeyChainConnection;
36d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport android.security.KeyChain;
3791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.security.KeyStore;
3891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.Editable;
390e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.text.TextUtils;
4091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.TextWatcher;
4191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.util.Log;
4291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.view.View;
4391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Button;
4491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.TextView;
4591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Toast;
4691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
47565653cef1039ab4e34e505185f1c77d847357cdJulia Reynoldsimport com.android.internal.widget.LockPatternUtils;
486c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport com.android.org.bouncycastle.asn1.ASN1InputStream;
496c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
506c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
516c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport org.apache.harmony.security.utils.AlgNameMapper;
526c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
536c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport java.io.ByteArrayInputStream;
546c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport java.io.IOException;
556c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom/**
570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage handles KeyStore reset, unlock, and install.
580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage has a pretty convoluted state machine to migrate
600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * from the old style separate keystore password to a new key guard
610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * based password, as well as to deal with setting up the key guard if
620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * necessary.
630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED
650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF
660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   set up key guard
670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    factory state
680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED
700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: ON
710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   confirm key guard
720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    user had key guard but no keystore and upgraded from pre-ICS
730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           OR user had key guard and pre-ICS keystore password which was then reset
740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: LOCKED
760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF/ON
770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   old unlock dialog
780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    assume old password, need to use it to unlock.
790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           if unlock, ensure key guard before install.
800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *           if reset, treat as UNINITALIZED/OFF
810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED
830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF
840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   set up key guard
850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    ensure key guard, then proceed
860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom *
870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED
880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * keyguard: ON
890e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action:   normal unlock/install
900e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes:    this is the common case
910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */
920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrompublic final class CredentialStorage extends Activity {
9391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
94d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private static final String TAG = "CredentialStorage";
9591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
9691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK";
9791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_INSTALL = "com.android.credentials.INSTALL";
9891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    public static final String ACTION_RESET = "com.android.credentials.RESET";
9991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
100d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    // This is the minimum acceptable password quality.  If the current password quality is
101d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    // lower than this, keystore should not be activated.
102d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING;
10391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
1040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private static final int CONFIRM_KEY_GUARD_REQUEST = 1;
1050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
106d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private final KeyStore mKeyStore = KeyStore.getInstance();
1070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
109ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker     * The UIDs that are used for system credential storage in keystore.
110ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker     */
111ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker    private static final int[] SYSTEM_CREDENTIAL_UIDS = {Process.WIFI_UID, Process.VPN_UID,
112ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker        Process.ROOT_UID, Process.SYSTEM_UID};
113ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker
114ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker    /**
1150e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * When non-null, the bundle containing credentials to install.
1160e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1170e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private Bundle mInstallBundle;
1180e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1190e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1200e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * After unsuccessful KeyStore.unlock, the number of unlock
1210e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * attempts remaining before the KeyStore will reset itself.
1220e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     *
1230e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Reset to -1 on successful unlock or reset.
1240e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1250e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private int mRetriesRemaining = -1;
12691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
127cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root    @Override
128cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root    protected void onResume() {
129d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        super.onResume();
13091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
13191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        Intent intent = getIntent();
13291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        String action = intent.getAction();
133565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
134565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds        if (!userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) {
135565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds            if (ACTION_RESET.equals(action)) {
136565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds                new ResetDialog();
137565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds            } else {
1388823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) {
139565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds                    mInstallBundle = intent.getExtras();
140565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds                }
141565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds                // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL
142565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds                handleUnlockOrInstall();
1430e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
144565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds        } else {
145a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds            // Users can set a screen lock if there is none even if they can't modify the
146a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds            // credentials store.
147a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds            if (ACTION_UNLOCK.equals(action) && mKeyStore.state() == KeyStore.State.UNINITIALIZED) {
148a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds                ensureKeyGuard();
149a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds            } else {
150a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds                finish();
151a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds            }
1520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
1540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Based on the current state of the KeyStore and key guard, try to
1570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * make progress on unlocking or installing to the keystore.
1580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void handleUnlockOrInstall() {
1600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        // something already decided we are done, do not proceed
1610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (isFinishing()) {
1620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
1630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        switch (mKeyStore.state()) {
1650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case UNINITIALIZED: {
1660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                ensureKeyGuard();
1670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
16891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
1690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case LOCKED: {
1700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                new UnlockDialog();
1710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
17291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
1730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            case UNLOCKED: {
1740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                if (!checkKeyGuardQuality()) {
1750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    new ConfigureKeyGuardDialog();
1760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    return;
1770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                }
1780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                installIfAvailable();
1790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                finish();
1800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
1810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
1820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
1830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
1840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
1850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
1860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Make sure the user enters the key guard to set or change the
1870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * keystore password. This can be used in UNINITIALIZED to set the
1880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * keystore password or UNLOCKED to change the password (as is the
1890e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * case after unlocking with an old-style password).
1900e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
1910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void ensureKeyGuard() {
1920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (!checkKeyGuardQuality()) {
1930e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // key guard not setup, doing so will initialize keystore
1940e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            new ConfigureKeyGuardDialog();
1950e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // will return to onResume after Activity
1960e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
19791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
1980e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        // force key guard confirmation
1990e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (confirmKeyGuard()) {
2000e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // will return password value via onActivityResult
2010e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            return;
2020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
2030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        finish();
20491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
20591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
2060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
2070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Returns true if the currently set key guard matches our minimum quality requirements.
2080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
2090e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private boolean checkKeyGuardQuality() {
2101e7b8f86d8aa46d2ed24b75adb453833ef2d1a88Jorim Jaggi        UserInfo parent = UserManager.get(this).getProfileParent(UserHandle.myUserId());
2115437588abd69bf3eff59684528aaf50e09b6cffcAdrian Roos        int quality = new LockPatternUtils(this).getActivePasswordQuality(
2121e7b8f86d8aa46d2ed24b75adb453833ef2d1a88Jorim Jaggi                parent != null ? parent.id : UserHandle.myUserId());
213d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        return (quality >= MIN_PASSWORD_QUALITY);
214d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
215d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
2166c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde    private boolean isHardwareBackedKey(byte[] keyData) {
2176c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde        try {
2186c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData));
2196c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject());
2206c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            String algId = pki.getAlgorithmId().getAlgorithm().getId();
2216c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            String algName = AlgNameMapper.map2AlgName(algId);
2226c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
2236c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            return KeyChain.isBoundKeyAlgorithm(algName);
2246c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde        } catch (IOException e) {
2256c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            Log.e(TAG, "Failed to parse key data");
2266c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde            return false;
2276c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde        }
2286c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde    }
2296c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
2300e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
2310e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Install credentials if available, otherwise do nothing.
2320e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
2330e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private void installIfAvailable() {
2348823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (mInstallBundle == null || mInstallBundle.isEmpty()) {
2358823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            return;
2368823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
2376c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
2388823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        Bundle bundle = mInstallBundle;
2398823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        mInstallBundle = null;
2408823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
241635426b0a7db8791bc62836921d3b2f22b36aceaRobin Lee        final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyStore.UID_SELF);
2428823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
243635426b0a7db8791bc62836921d3b2f22b36aceaRobin Lee        if (uid != KeyStore.UID_SELF && !UserHandle.isSameUser(uid, Process.myUid())) {
2448823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            int dstUserId = UserHandle.getUserId(uid);
2458823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            int myUserId = UserHandle.myUserId();
2468823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
2478823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            // Restrict install target to the wifi uid.
2488823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (uid != Process.WIFI_UID) {
2498823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs"
2508823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                        + " may only target wifi uids");
2518823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return;
25291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
253b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2548823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            Intent installIntent = new Intent(ACTION_INSTALL)
2558823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                    .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT)
2568823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                    .putExtras(bundle);
2578823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            startActivityAsUser(installIntent, new UserHandle(dstUserId));
2588823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            return;
2598823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
2608823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
2618823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) {
2628823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME);
2638823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA);
2646c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde
2658823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            int flags = KeyStore.FLAG_ENCRYPTED;
2668823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) {
2678823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                // Hardware backed keystore is secure enough to allow for WIFI stack
2688823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                // to enable access to secure networks without user intervention
2698823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID");
2708823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                flags = KeyStore.FLAG_NONE;
2718823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            }
272b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2738823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (!mKeyStore.importKey(key, value, uid, flags)) {
2748823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.e(TAG, "Failed to install " + key + " as uid " + uid);
2758823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return;
276b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            }
2778823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
278b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2798823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED;
280b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2818823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) {
2828823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME);
2838823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA);
2848823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
2858823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (!mKeyStore.put(certName, certData, uid, flags)) {
2868823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.e(TAG, "Failed to install " + certName + " as uid " + uid);
2878823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return;
288b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root            }
2898823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
290b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root
2918823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) {
2928823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME);
2938823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA);
2948823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
2958823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (!mKeyStore.put(caListName, caListData, uid, flags)) {
2968823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.e(TAG, "Failed to install " + caListName + " as uid " + uid);
2978823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return;
2988823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            }
29991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
3008823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
3018823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        setResult(RESULT_OK);
30291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
30391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
3040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for reset confirmation, resetting on confirmation, finishing otherwise.
3060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
307d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private class ResetDialog
308d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
309d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
310d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mResetConfirmed;
311d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
312d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private ResetDialog() {
313d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
314d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(android.R.string.dialog_alert_title)
315d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setMessage(R.string.credentials_reset_hint)
316d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
317d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
318d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
319d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
320d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
32191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
32291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
323d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
324d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
32591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
32691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh
327d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
328d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mResetConfirmed) {
329d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mResetConfirmed = false;
330d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                new ResetKeyStoreAndKeyChain().execute();
33191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh                return;
33291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh            }
333d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
33491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh        }
33591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh    }
3369815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
3370e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3380e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Background task to handle reset of both keystore and user installed CAs.
3390e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
3409815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> {
3419815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
3429815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected Boolean doInBackground(Void... unused) {
3439815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
344ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker            // Clear all the users credentials could have been installed in for this user.
345ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker            final UserManager um = (UserManager) getSystemService(USER_SERVICE);
346ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker            for (UserInfo pi : um.getProfiles(UserHandle.getUserId(Process.myUid()))) {
347ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker                for (int uid : SYSTEM_CREDENTIAL_UIDS) {
348ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker                    mKeyStore.clearUid(UserHandle.getUid(pi.id, uid));
349ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker                }
350ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker            }
351ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker
3529815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
3539815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            try {
354435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this);
355435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                try {
356435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    return keyChainConnection.getService().reset();
357435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                } catch (RemoteException e) {
358435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    return false;
359435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                } finally {
360435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                    keyChainConnection.close();
361435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom                }
3629815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } catch (InterruptedException e) {
3639815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Thread.currentThread().interrupt();
3649815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                return false;
3659815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
3669815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
3679815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom
3689815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        @Override protected void onPostExecute(Boolean success) {
3699815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            if (success) {
3709815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
3719815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_erased, Toast.LENGTH_SHORT).show();
3729815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            } else {
3739815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                Toast.makeText(CredentialStorage.this,
3749815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom                               R.string.credentials_not_erased, Toast.LENGTH_SHORT).show();
3759815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            }
3769815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom            finish();
3779815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom        }
3789815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom    }
379d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
3810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for key guard configuration confirmation.
3820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
3830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private class ConfigureKeyGuardDialog
384d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener
385d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
386d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mConfigureConfirmed;
387d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
3880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        private ConfigureKeyGuardDialog() {
389d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
390d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(android.R.string.dialog_alert_title)
391d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setMessage(R.string.credentials_configure_lock_screen_hint)
392d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
393d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
394d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
395d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
396d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
397d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
398d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
399d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
400d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
401d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
402d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
403d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
404d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mConfigureConfirmed) {
405d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mConfigureConfirmed = false;
406d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD);
407d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY,
408d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                MIN_PASSWORD_QUALITY);
409d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                startActivity(intent);
410d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                return;
411d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            }
412d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
413d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
414d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
415d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
4160e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
4178823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee     * Check that the caller is either certinstaller or Settings running in a profile of this user.
4188823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee     */
4198823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee    private boolean checkCallerIsCertInstallerOrSelfInProfile() {
4208823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (TextUtils.equals("com.android.certinstaller", getCallingPackage())) {
421307e3d048d6e89bc8419ac5d3f480841c84fc5a2Zoltan Szatmary-Ban            // CertInstaller is allowed to install credentials if it has the same signature as
422307e3d048d6e89bc8419ac5d3f480841c84fc5a2Zoltan Szatmary-Ban            // Settings package.
423307e3d048d6e89bc8419ac5d3f480841c84fc5a2Zoltan Szatmary-Ban            return getPackageManager().checkSignatures(
424307e3d048d6e89bc8419ac5d3f480841c84fc5a2Zoltan Szatmary-Ban                    getCallingPackage(), getPackageName()) == PackageManager.SIGNATURE_MATCH;
4258823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
4268823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
4278823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        final int launchedFromUserId;
4288823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        try {
4298823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            int launchedFromUid = android.app.ActivityManagerNative.getDefault()
4308823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                    .getLaunchedFromUid(getActivityToken());
4318823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (launchedFromUid == -1) {
4328823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                Log.e(TAG, ACTION_INSTALL + " must be started with startActivityForResult");
4338823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return false;
4348823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            }
4358823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            if (!UserHandle.isSameApp(launchedFromUid, Process.myUid())) {
4368823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                // Not the same app
4378823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee                return false;
4388823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            }
4398823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            launchedFromUserId = UserHandle.getUserId(launchedFromUid);
4408823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        } catch (RemoteException re) {
4418823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            // Error talking to ActivityManager, just give up
4428823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            return false;
4438823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
4448823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
4458823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE);
4468823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        UserInfo parentInfo = userManager.getProfileParent(launchedFromUserId);
4478823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        if (parentInfo == null || parentInfo.id != UserHandle.myUserId()) {
4488823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            // Caller is not running in a profile of this user
4498823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee            return false;
4508823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        }
4518823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee        return true;
4528823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee    }
4538823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee
4548823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee    /**
4550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Confirm existing key guard, returning password via onActivityResult.
4560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
4570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    private boolean confirmKeyGuard() {
4580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        Resources res = getResources();
4590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        boolean launched = new ChooseLockSettingsHelper(this)
4608a09b619aeb233e2aab1919301f162d8acf1f0f0Jorim Jaggi                .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST,
4618a09b619aeb233e2aab1919301f162d8acf1f0f0Jorim Jaggi                        res.getText(R.string.credentials_title), true);
4620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        return launched;
4630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
4640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
4650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    @Override
4660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    public void onActivityResult(int requestCode, int resultCode, Intent data) {
4670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        super.onActivityResult(requestCode, resultCode, data);
4680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
4690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        /**
4700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom         * Receive key guard password initiated by confirmKeyGuard.
4710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom         */
4720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        if (requestCode == CONFIRM_KEY_GUARD_REQUEST) {
4730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            if (resultCode == Activity.RESULT_OK) {
4740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD);
4750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                if (!TextUtils.isEmpty(password)) {
4760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // success
4777236f2abbabefc08e68226677f51fe2117c8c0a5Chad Brubaker                    mKeyStore.unlock(password);
4780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // return to onResume
4790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    return;
4800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                }
4810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
4820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            // failed confirmation, bail
4830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            finish();
4840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom        }
4850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    }
4860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
4870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom    /**
4880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * Prompt for unlock with old-style password.
4890e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     *
4900e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * On successful unlock, ensure migration to key guard before continuing.
4910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     * On unsuccessful unlock, retry by calling handleUnlockOrInstall.
4920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom     */
493d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    private class UnlockDialog implements TextWatcher,
494d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            DialogInterface.OnClickListener, DialogInterface.OnDismissListener
495d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    {
496d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private boolean mUnlockConfirmed;
497d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
498d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final Button mButton;
499d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final TextView mOldPassword;
500d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private final TextView mError;
501d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
502d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        private UnlockDialog() {
503d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            View view = View.inflate(CredentialStorage.this, R.layout.credentials_dialog, null);
504d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
5050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            CharSequence text;
5060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            if (mRetriesRemaining == -1) {
5070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_unlock_hint);
5080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else if (mRetriesRemaining > 3) {
5090e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_wrong_password);
5100e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else if (mRetriesRemaining == 1) {
5110e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getResources().getText(R.string.credentials_reset_warning);
5120e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            } else {
5130e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                text = getString(R.string.credentials_reset_warning_plural, mRetriesRemaining);
5140e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            }
5150e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom
5160e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom            ((TextView) view.findViewById(R.id.hint)).setText(text);
517d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword = (TextView) view.findViewById(R.id.old_password);
518d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword.setVisibility(View.VISIBLE);
519d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mOldPassword.addTextChangedListener(this);
520d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mError = (TextView) view.findViewById(R.id.error);
521d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
522d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this)
523d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setView(view)
524d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setTitle(R.string.credentials_unlock)
525d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setPositiveButton(android.R.string.ok, this)
526d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .setNegativeButton(android.R.string.cancel, this)
527d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    .create();
528d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.setOnDismissListener(this);
529d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            dialog.show();
530d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE);
531d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton.setEnabled(false);
532d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
533d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
534d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void afterTextChanged(Editable editable) {
535d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0);
536d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
537d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
538d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) {
539d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
540d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
541d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onTextChanged(CharSequence s,int start, int before, int count) {
542d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
543d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
544d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onClick(DialogInterface dialog, int button) {
545d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE);
546d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
547d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom
548d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        @Override public void onDismiss(DialogInterface dialog) {
549d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            if (mUnlockConfirmed) {
550d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mUnlockConfirmed = false;
551d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mError.setVisibility(View.VISIBLE);
552d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                mKeyStore.unlock(mOldPassword.getText().toString());
553d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                int error = mKeyStore.getLastError();
554d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                if (error == KeyStore.NO_ERROR) {
5550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = -1;
556d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    Toast.makeText(CredentialStorage.this,
557d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   R.string.credentials_enabled,
558d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   Toast.LENGTH_SHORT).show();
5590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // aha, now we are unlocked, switch to key guard.
5600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we'll end up back in onResume to install
5610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    ensureKeyGuard();
562d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                } else if (error == KeyStore.UNINITIALIZED) {
5630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = -1;
564d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                    Toast.makeText(CredentialStorage.this,
565d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   R.string.credentials_erased,
566d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                                   Toast.LENGTH_SHORT).show();
5670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we are reset, we can now set new password with key guard
5680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    handleUnlockOrInstall();
569d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                } else if (error >= KeyStore.WRONG_PASSWORD) {
5700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    // we need to try again
5710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    mRetriesRemaining = error - KeyStore.WRONG_PASSWORD + 1;
5720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                    handleUnlockOrInstall();
573d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom                }
5740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom                return;
575d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            }
576d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom            finish();
577d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom        }
578d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom    }
57991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh}
580