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