CredentialStorage.java revision ce10b5edf0ba19b2bf74423c45d6640ab345ced4
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; 258823c3eda28930bcd6c8242bfed15b098d63acd0Robin Leeimport android.content.pm.UserInfo; 260e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.content.res.Resources; 279815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.AsyncTask; 2891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.os.Bundle; 299815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstromimport android.os.RemoteException; 306c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport android.os.Process; 318823c3eda28930bcd6c8242bfed15b098d63acd0Robin Leeimport android.os.UserHandle; 32565653cef1039ab4e34e505185f1c77d847357cdJulia Reynoldsimport android.os.UserManager; 33b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Rootimport android.security.Credentials; 34435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstromimport android.security.KeyChain.KeyChainConnection; 35d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstromimport android.security.KeyChain; 3691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.security.KeyStore; 3791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.Editable; 380e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstromimport android.text.TextUtils; 3991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.text.TextWatcher; 4091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.util.Log; 4191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.view.View; 4291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Button; 4391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.TextView; 4491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yehimport android.widget.Toast; 4591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 46565653cef1039ab4e34e505185f1c77d847357cdJulia Reynoldsimport com.android.internal.widget.LockPatternUtils; 476c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport com.android.org.bouncycastle.asn1.ASN1InputStream; 486c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport com.android.org.bouncycastle.asn1.pkcs.PrivateKeyInfo; 496c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 506c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport org.apache.harmony.security.utils.AlgNameMapper; 516c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 526c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport java.io.ByteArrayInputStream; 536c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapndeimport java.io.IOException; 546c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom/** 560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage handles KeyStore reset, unlock, and install. 570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * CredentialStorage has a pretty convoluted state machine to migrate 590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * from the old style separate keystore password to a new key guard 600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * based password, as well as to deal with setting up the key guard if 610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * necessary. 620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED 640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF 650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action: set up key guard 660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes: factory state 670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNINITALIZED 690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: ON 700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action: confirm key guard 710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes: user had key guard but no keystore and upgraded from pre-ICS 720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * OR user had key guard and pre-ICS keystore password which was then reset 730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: LOCKED 750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF/ON 760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action: old unlock dialog 770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes: assume old password, need to use it to unlock. 780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * if unlock, ensure key guard before install. 790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * if reset, treat as UNINITALIZED/OFF 800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED 820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyGuard: OFF 830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action: set up key guard 840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes: ensure key guard, then proceed 850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * KeyStore: UNLOCKED 870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * keyguard: ON 880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Action: normal unlock/install 890e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Notes: this is the common case 900e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrompublic final class CredentialStorage extends Activity { 9291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 93d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private static final String TAG = "CredentialStorage"; 9491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 9591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh public static final String ACTION_UNLOCK = "com.android.credentials.UNLOCK"; 9691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh public static final String ACTION_INSTALL = "com.android.credentials.INSTALL"; 9791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh public static final String ACTION_RESET = "com.android.credentials.RESET"; 9891d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 99d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom // This is the minimum acceptable password quality. If the current password quality is 100d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom // lower than this, keystore should not be activated. 101d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom static final int MIN_PASSWORD_QUALITY = DevicePolicyManager.PASSWORD_QUALITY_SOMETHING; 10291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 1030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private static final int CONFIRM_KEY_GUARD_REQUEST = 1; 1040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 105d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private final KeyStore mKeyStore = KeyStore.getInstance(); 1060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 1070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 108ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker * The UIDs that are used for system credential storage in keystore. 109ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker */ 110ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker private static final int[] SYSTEM_CREDENTIAL_UIDS = {Process.WIFI_UID, Process.VPN_UID, 111ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker Process.ROOT_UID, Process.SYSTEM_UID}; 112ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker 113ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker /** 1140e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * When non-null, the bundle containing credentials to install. 1150e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 1160e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private Bundle mInstallBundle; 1170e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 1180e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 1190e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * After unsuccessful KeyStore.unlock, the number of unlock 1200e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * attempts remaining before the KeyStore will reset itself. 1210e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 1220e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Reset to -1 on successful unlock or reset. 1230e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 1240e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private int mRetriesRemaining = -1; 12591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 126cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root @Override 127cf008c28b871d4167e5aa19191ca691fb988f8fdKenny Root protected void onResume() { 128d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom super.onResume(); 12991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 13091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh Intent intent = getIntent(); 13191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh String action = intent.getAction(); 132565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 133565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds if (!userManager.hasUserRestriction(UserManager.DISALLOW_CONFIG_CREDENTIALS)) { 134565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds if (ACTION_RESET.equals(action)) { 135565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds new ResetDialog(); 136565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds } else { 1378823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (ACTION_INSTALL.equals(action) && checkCallerIsCertInstallerOrSelfInProfile()) { 138565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds mInstallBundle = intent.getExtras(); 139565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds } 140565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds // ACTION_UNLOCK also handled here in addition to ACTION_INSTALL 141565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds handleUnlockOrInstall(); 1420e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 143565653cef1039ab4e34e505185f1c77d847357cdJulia Reynolds } else { 144a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds // Users can set a screen lock if there is none even if they can't modify the 145a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds // credentials store. 146a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds if (ACTION_UNLOCK.equals(action) && mKeyStore.state() == KeyStore.State.UNINITIALIZED) { 147a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds ensureKeyGuard(); 148a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds } else { 149a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds finish(); 150a12fc84877647499006a3ca4a4599878bb888543Julia Reynolds } 1510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 1540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 1550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Based on the current state of the KeyStore and key guard, try to 1560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * make progress on unlocking or installing to the keystore. 1570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 1580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private void handleUnlockOrInstall() { 1590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // something already decided we are done, do not proceed 1600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (isFinishing()) { 1610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 1620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom switch (mKeyStore.state()) { 1640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom case UNINITIALIZED: { 1650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom ensureKeyGuard(); 1660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 16791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 1680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom case LOCKED: { 1690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom new UnlockDialog(); 1700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 17191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 1720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom case UNLOCKED: { 1730e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (!checkKeyGuardQuality()) { 1740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom new ConfigureKeyGuardDialog(); 1750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 1760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom installIfAvailable(); 1780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom finish(); 1790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 1800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 1830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 1840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 1850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Make sure the user enters the key guard to set or change the 1860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * keystore password. This can be used in UNINITIALIZED to set the 1870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * keystore password or UNLOCKED to change the password (as is the 1880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * case after unlocking with an old-style password). 1890e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 1900e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private void ensureKeyGuard() { 1910e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (!checkKeyGuardQuality()) { 1920e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // key guard not setup, doing so will initialize keystore 1930e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom new ConfigureKeyGuardDialog(); 1940e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // will return to onResume after Activity 1950e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 19691d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 1970e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // force key guard confirmation 1980e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (confirmKeyGuard()) { 1990e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // will return password value via onActivityResult 2000e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 2010e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 2020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom finish(); 20391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 20491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 2050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 2060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Returns true if the currently set key guard matches our minimum quality requirements. 2070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 2080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private boolean checkKeyGuardQuality() { 2095437588abd69bf3eff59684528aaf50e09b6cffcAdrian Roos int quality = new LockPatternUtils(this).getActivePasswordQuality( 2105437588abd69bf3eff59684528aaf50e09b6cffcAdrian Roos UserHandle.myUserId()); 211d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom return (quality >= MIN_PASSWORD_QUALITY); 212d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 213d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 2146c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde private boolean isHardwareBackedKey(byte[] keyData) { 2156c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde try { 2166c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde ASN1InputStream bIn = new ASN1InputStream(new ByteArrayInputStream(keyData)); 2176c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde PrivateKeyInfo pki = PrivateKeyInfo.getInstance(bIn.readObject()); 2186c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde String algId = pki.getAlgorithmId().getAlgorithm().getId(); 2196c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde String algName = AlgNameMapper.map2AlgName(algId); 2206c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 2216c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde return KeyChain.isBoundKeyAlgorithm(algName); 2226c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde } catch (IOException e) { 2236c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde Log.e(TAG, "Failed to parse key data"); 2246c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde return false; 2256c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde } 2266c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde } 2276c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 2280e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 2290e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Install credentials if available, otherwise do nothing. 2300e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 2310e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private void installIfAvailable() { 2328823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (mInstallBundle == null || mInstallBundle.isEmpty()) { 2338823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 2348823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 2356c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 2368823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Bundle bundle = mInstallBundle; 2378823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee mInstallBundle = null; 2388823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 239635426b0a7db8791bc62836921d3b2f22b36aceaRobin Lee final int uid = bundle.getInt(Credentials.EXTRA_INSTALL_AS_UID, KeyStore.UID_SELF); 2408823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 241635426b0a7db8791bc62836921d3b2f22b36aceaRobin Lee if (uid != KeyStore.UID_SELF && !UserHandle.isSameUser(uid, Process.myUid())) { 2428823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee int dstUserId = UserHandle.getUserId(uid); 2438823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee int myUserId = UserHandle.myUserId(); 2448823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 2458823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // Restrict install target to the wifi uid. 2468823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (uid != Process.WIFI_UID) { 2478823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.e(TAG, "Failed to install credentials as uid " + uid + ": cross-user installs" 2488823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee + " may only target wifi uids"); 2498823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 25091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 251b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root 2528823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Intent installIntent = new Intent(ACTION_INSTALL) 2538823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee .setFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT) 2548823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee .putExtras(bundle); 2558823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee startActivityAsUser(installIntent, new UserHandle(dstUserId)); 2568823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 2578823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 2588823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 2598823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (bundle.containsKey(Credentials.EXTRA_USER_PRIVATE_KEY_NAME)) { 2608823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee String key = bundle.getString(Credentials.EXTRA_USER_PRIVATE_KEY_NAME); 2618823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee byte[] value = bundle.getByteArray(Credentials.EXTRA_USER_PRIVATE_KEY_DATA); 2626c0a193050747c760a01934a6c1bb204f933ad3eVinit Deshapnde 2638823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee int flags = KeyStore.FLAG_ENCRYPTED; 2648823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (uid == Process.WIFI_UID && isHardwareBackedKey(value)) { 2658823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // Hardware backed keystore is secure enough to allow for WIFI stack 2668823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // to enable access to secure networks without user intervention 2678823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.d(TAG, "Saving private key with FLAG_NONE for WIFI_UID"); 2688823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee flags = KeyStore.FLAG_NONE; 2698823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 270b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root 2718823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (!mKeyStore.importKey(key, value, uid, flags)) { 2728823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.e(TAG, "Failed to install " + key + " as uid " + uid); 2738823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 274b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root } 2758823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 276b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root 2778823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee int flags = (uid == Process.WIFI_UID) ? KeyStore.FLAG_NONE : KeyStore.FLAG_ENCRYPTED; 278b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root 2798823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (bundle.containsKey(Credentials.EXTRA_USER_CERTIFICATE_NAME)) { 2808823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee String certName = bundle.getString(Credentials.EXTRA_USER_CERTIFICATE_NAME); 2818823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee byte[] certData = bundle.getByteArray(Credentials.EXTRA_USER_CERTIFICATE_DATA); 2828823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 2838823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (!mKeyStore.put(certName, certData, uid, flags)) { 2848823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.e(TAG, "Failed to install " + certName + " as uid " + uid); 2858823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 286b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root } 2878823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 288b50b15cdbed31e35c2c7f3cbaa7ce06a3feb3a6fKenny Root 2898823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (bundle.containsKey(Credentials.EXTRA_CA_CERTIFICATES_NAME)) { 2908823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee String caListName = bundle.getString(Credentials.EXTRA_CA_CERTIFICATES_NAME); 2918823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee byte[] caListData = bundle.getByteArray(Credentials.EXTRA_CA_CERTIFICATES_DATA); 2928823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 2938823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (!mKeyStore.put(caListName, caListData, uid, flags)) { 2948823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.e(TAG, "Failed to install " + caListName + " as uid " + uid); 2958823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return; 2968823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 29791d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 2988823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 2998823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee setResult(RESULT_OK); 30091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 30191d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 3020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 3030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Prompt for reset confirmation, resetting on confirmation, finishing otherwise. 3040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 305d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private class ResetDialog 306d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener 307d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom { 308d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private boolean mResetConfirmed; 309d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 310d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private ResetDialog() { 311d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this) 312d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setTitle(android.R.string.dialog_alert_title) 313d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setMessage(R.string.credentials_reset_hint) 314d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setPositiveButton(android.R.string.ok, this) 315d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setNegativeButton(android.R.string.cancel, this) 316d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .create(); 317d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.setOnDismissListener(this); 318d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.show(); 31991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 32091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 321d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onClick(DialogInterface dialog, int button) { 322d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mResetConfirmed = (button == DialogInterface.BUTTON_POSITIVE); 32391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 32491d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh 325d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onDismiss(DialogInterface dialog) { 326d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom if (mResetConfirmed) { 327d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mResetConfirmed = false; 328d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom new ResetKeyStoreAndKeyChain().execute(); 32991d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh return; 33091d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 331d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom finish(); 33291d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 33391d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh } 3349815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom 3350e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 3360e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Background task to handle reset of both keystore and user installed CAs. 3370e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 3389815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom private class ResetKeyStoreAndKeyChain extends AsyncTask<Void, Void, Boolean> { 3399815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom 3409815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom @Override protected Boolean doInBackground(Void... unused) { 3419815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom 342ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker // Clear all the users credentials could have been installed in for this user. 343ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker final UserManager um = (UserManager) getSystemService(USER_SERVICE); 344ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker for (UserInfo pi : um.getProfiles(UserHandle.getUserId(Process.myUid()))) { 345ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker for (int uid : SYSTEM_CREDENTIAL_UIDS) { 346ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker mKeyStore.clearUid(UserHandle.getUid(pi.id, uid)); 347ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker } 348ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker } 349ce10b5edf0ba19b2bf74423c45d6640ab345ced4Chad Brubaker 3509815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom 3519815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom try { 352435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom KeyChainConnection keyChainConnection = KeyChain.bind(CredentialStorage.this); 353435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom try { 354435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom return keyChainConnection.getService().reset(); 355435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom } catch (RemoteException e) { 356435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom return false; 357435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom } finally { 358435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom keyChainConnection.close(); 359435e45e61610bfa50ca54267a72b9ad74c9f1d41Brian Carlstrom } 3609815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } catch (InterruptedException e) { 3619815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom Thread.currentThread().interrupt(); 3629815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom return false; 3639815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } 3649815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } 3659815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom 3669815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom @Override protected void onPostExecute(Boolean success) { 3679815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom if (success) { 3689815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom Toast.makeText(CredentialStorage.this, 3699815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom R.string.credentials_erased, Toast.LENGTH_SHORT).show(); 3709815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } else { 3719815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom Toast.makeText(CredentialStorage.this, 3729815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom R.string.credentials_not_erased, Toast.LENGTH_SHORT).show(); 3739815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } 3749815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom finish(); 3759815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } 3769815429821832c204eaf8edebb37f4e2ff7636f0Brian Carlstrom } 377d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 3780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 3790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Prompt for key guard configuration confirmation. 3800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 3810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private class ConfigureKeyGuardDialog 382d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom implements DialogInterface.OnClickListener, DialogInterface.OnDismissListener 383d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom { 384d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private boolean mConfigureConfirmed; 385d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 3860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private ConfigureKeyGuardDialog() { 387d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this) 388d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setTitle(android.R.string.dialog_alert_title) 389d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setMessage(R.string.credentials_configure_lock_screen_hint) 390d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setPositiveButton(android.R.string.ok, this) 391d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setNegativeButton(android.R.string.cancel, this) 392d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .create(); 393d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.setOnDismissListener(this); 394d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.show(); 395d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 396d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 397d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onClick(DialogInterface dialog, int button) { 398d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mConfigureConfirmed = (button == DialogInterface.BUTTON_POSITIVE); 399d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 400d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 401d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onDismiss(DialogInterface dialog) { 402d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom if (mConfigureConfirmed) { 403d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mConfigureConfirmed = false; 404d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom Intent intent = new Intent(DevicePolicyManager.ACTION_SET_NEW_PASSWORD); 405d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom intent.putExtra(ChooseLockGeneric.ChooseLockGenericFragment.MINIMUM_QUALITY_KEY, 406d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom MIN_PASSWORD_QUALITY); 407d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom startActivity(intent); 408d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom return; 409d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 410d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom finish(); 411d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 412d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 413d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 4140e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 4158823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee * Check that the caller is either certinstaller or Settings running in a profile of this user. 4168823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee */ 4178823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee private boolean checkCallerIsCertInstallerOrSelfInProfile() { 4188823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (TextUtils.equals("com.android.certinstaller", getCallingPackage())) { 4198823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // CertInstaller is allowed to install credentials 4208823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return true; 4218823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4228823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 4238823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee final int launchedFromUserId; 4248823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee try { 4258823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee int launchedFromUid = android.app.ActivityManagerNative.getDefault() 4268823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee .getLaunchedFromUid(getActivityToken()); 4278823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (launchedFromUid == -1) { 4288823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee Log.e(TAG, ACTION_INSTALL + " must be started with startActivityForResult"); 4298823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return false; 4308823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4318823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (!UserHandle.isSameApp(launchedFromUid, Process.myUid())) { 4328823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // Not the same app 4338823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return false; 4348823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4358823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee launchedFromUserId = UserHandle.getUserId(launchedFromUid); 4368823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } catch (RemoteException re) { 4378823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // Error talking to ActivityManager, just give up 4388823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return false; 4398823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4408823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 4418823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee UserManager userManager = (UserManager) getSystemService(Context.USER_SERVICE); 4428823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee UserInfo parentInfo = userManager.getProfileParent(launchedFromUserId); 4438823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee if (parentInfo == null || parentInfo.id != UserHandle.myUserId()) { 4448823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee // Caller is not running in a profile of this user 4458823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return false; 4468823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4478823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee return true; 4488823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee } 4498823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee 4508823c3eda28930bcd6c8242bfed15b098d63acd0Robin Lee /** 4510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Confirm existing key guard, returning password via onActivityResult. 4520e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 4530e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom private boolean confirmKeyGuard() { 4540e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom Resources res = getResources(); 4550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom boolean launched = new ChooseLockSettingsHelper(this) 4568a09b619aeb233e2aab1919301f162d8acf1f0f0Jorim Jaggi .launchConfirmationActivity(CONFIRM_KEY_GUARD_REQUEST, 4578a09b619aeb233e2aab1919301f162d8acf1f0f0Jorim Jaggi res.getText(R.string.credentials_title), true); 4580e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return launched; 4590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 4600e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 4610e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom @Override 4620e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom public void onActivityResult(int requestCode, int resultCode, Intent data) { 4630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom super.onActivityResult(requestCode, resultCode, data); 4640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 4650e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 4660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Receive key guard password initiated by confirmKeyGuard. 4670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 4680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (requestCode == CONFIRM_KEY_GUARD_REQUEST) { 4690e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (resultCode == Activity.RESULT_OK) { 4700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom String password = data.getStringExtra(ChooseLockSettingsHelper.EXTRA_KEY_PASSWORD); 4710e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (!TextUtils.isEmpty(password)) { 4720e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // success 4737236f2abbabefc08e68226677f51fe2117c8c0a5Chad Brubaker mKeyStore.unlock(password); 4740e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // return to onResume 4750e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 4760e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 4770e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 4780e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // failed confirmation, bail 4790e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom finish(); 4800e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 4810e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 4820e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 4830e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom /** 4840e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * Prompt for unlock with old-style password. 4850e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * 4860e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * On successful unlock, ensure migration to key guard before continuing. 4870e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom * On unsuccessful unlock, retry by calling handleUnlockOrInstall. 4880e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom */ 489d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private class UnlockDialog implements TextWatcher, 490d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom DialogInterface.OnClickListener, DialogInterface.OnDismissListener 491d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom { 492d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private boolean mUnlockConfirmed; 493d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 494d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private final Button mButton; 495d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private final TextView mOldPassword; 496d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private final TextView mError; 497d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 498d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom private UnlockDialog() { 499d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom View view = View.inflate(CredentialStorage.this, R.layout.credentials_dialog, null); 500d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 5010e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom CharSequence text; 5020e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom if (mRetriesRemaining == -1) { 5030e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom text = getResources().getText(R.string.credentials_unlock_hint); 5040e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } else if (mRetriesRemaining > 3) { 5050e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom text = getResources().getText(R.string.credentials_wrong_password); 5060e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } else if (mRetriesRemaining == 1) { 5070e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom text = getResources().getText(R.string.credentials_reset_warning); 5080e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } else { 5090e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom text = getString(R.string.credentials_reset_warning_plural, mRetriesRemaining); 5100e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom } 5110e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom 5120e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom ((TextView) view.findViewById(R.id.hint)).setText(text); 513d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mOldPassword = (TextView) view.findViewById(R.id.old_password); 514d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mOldPassword.setVisibility(View.VISIBLE); 515d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mOldPassword.addTextChangedListener(this); 516d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mError = (TextView) view.findViewById(R.id.error); 517d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 518d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom AlertDialog dialog = new AlertDialog.Builder(CredentialStorage.this) 519d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setView(view) 520d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setTitle(R.string.credentials_unlock) 521d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setPositiveButton(android.R.string.ok, this) 522d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .setNegativeButton(android.R.string.cancel, this) 523d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom .create(); 524d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.setOnDismissListener(this); 525d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom dialog.show(); 526d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mButton = dialog.getButton(DialogInterface.BUTTON_POSITIVE); 527d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mButton.setEnabled(false); 528d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 529d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 530d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void afterTextChanged(Editable editable) { 531d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mButton.setEnabled(mOldPassword == null || mOldPassword.getText().length() > 0); 532d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 533d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 534d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { 535d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 536d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 537d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onTextChanged(CharSequence s,int start, int before, int count) { 538d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 539d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 540d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onClick(DialogInterface dialog, int button) { 541d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mUnlockConfirmed = (button == DialogInterface.BUTTON_POSITIVE); 542d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 543d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom 544d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom @Override public void onDismiss(DialogInterface dialog) { 545d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom if (mUnlockConfirmed) { 546d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mUnlockConfirmed = false; 547d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mError.setVisibility(View.VISIBLE); 548d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom mKeyStore.unlock(mOldPassword.getText().toString()); 549d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom int error = mKeyStore.getLastError(); 550d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom if (error == KeyStore.NO_ERROR) { 5510e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom mRetriesRemaining = -1; 552d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom Toast.makeText(CredentialStorage.this, 553d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom R.string.credentials_enabled, 554d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom Toast.LENGTH_SHORT).show(); 5550e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // aha, now we are unlocked, switch to key guard. 5560e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // we'll end up back in onResume to install 5570e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom ensureKeyGuard(); 558d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } else if (error == KeyStore.UNINITIALIZED) { 5590e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom mRetriesRemaining = -1; 560d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom Toast.makeText(CredentialStorage.this, 561d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom R.string.credentials_erased, 562d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom Toast.LENGTH_SHORT).show(); 5630e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // we are reset, we can now set new password with key guard 5640e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom handleUnlockOrInstall(); 565d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } else if (error >= KeyStore.WRONG_PASSWORD) { 5660e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom // we need to try again 5670e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom mRetriesRemaining = error - KeyStore.WRONG_PASSWORD + 1; 5680e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom handleUnlockOrInstall(); 569d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 5700e88f4dd19a80e9e4d759595439773fb3e1f0c50Brian Carlstrom return; 571d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 572d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom finish(); 573d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 574d4023b7cca11e33e84df39dee9e9a737efab47c2Brian Carlstrom } 57591d65a20af2d1bfb06f32d0bd821e8558afe939dChia-chi Yeh} 576