byte[] hash = credentialUtil.toHash(credential, userId);
if (Arrays.equals(hash, storedHash.hash)) {
unlockKeystore(credentialUtil.adjustForKeystore(credential), userId);
- unlockUser(userId, null);
+
+ // TODO: pass through a meaningful token from gatekeeper to
+ // unlock credential keys; for now pass through a stub value to
+ // indicate that we came from a user challenge.
+ final byte[] token = String.valueOf(userId).getBytes();
+ unlockUser(userId, token);
+
// migrate credential to GateKeeper
credentialUtil.setCredential(credential, null, userId);
if (!hasChallenge) {
if (response.getResponseCode() == VerifyCredentialResponse.RESPONSE_OK) {
// credential has matched
unlockKeystore(credential, userId);
- unlockUser(userId, null);
+
+ // TODO: pass through a meaningful token from gatekeeper to
+ // unlock credential keys; for now pass through a stub value to
+ // indicate that we came from a user challenge.
+ final byte[] token = String.valueOf(userId).getBytes();
+ unlockUser(userId, token);
+
UserInfo info = UserManager.get(mContext).getUserInfo(userId);
if (LockPatternUtils.isSeparateWorkChallengeEnabled() && info.isManagedProfile()) {
TrustManager trustManager =
import com.android.internal.util.HexDump;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.Preconditions;
+import com.android.internal.widget.LockPatternUtils;
import com.android.server.NativeDaemonConnector.Command;
import com.android.server.NativeDaemonConnector.SensitiveArg;
import com.android.server.pm.PackageManagerService;
private PackageManagerService mPms;
private final Callbacks mCallbacks;
+ private final LockPatternUtils mLockPatternUtils;
// Two connectors - mConnector & mCryptConnector
private final CountDownLatch mConnectedSignal = new CountDownLatch(2);
mContext = context;
mCallbacks = new Callbacks(FgThread.get().getLooper());
+ mLockPatternUtils = new LockPatternUtils(mContext);
// XXX: This will go away soon in favor of IMountServiceObserver
mPms = (PackageManagerService) ServiceManager.getService("package");
enforcePermission(android.Manifest.permission.STORAGE_INTERNAL);
waitForReady();
+ // When a user has secure lock screen, require a challenge token to
+ // actually unlock. This check is mostly in place for emulation mode.
+ if (mLockPatternUtils.isSecure(userId) && ArrayUtils.isEmpty(token)) {
+ throw new IllegalStateException("Token required to unlock secure user " + userId);
+ }
+
final String encodedToken;
if (ArrayUtils.isEmpty(token)) {
encodedToken = "!";
import java.util.List;
import java.util.Set;
-import libcore.util.EmptyArray;
-
/**
* Helper class for {@link ActivityManagerService} responsible for multi-user functionality.
*/
AppOpsManager.OP_NONE, null, true, false, MY_PID, SYSTEM_UID, userId);
}
- maybeFinishUserUnlock(uss);
+ maybeUnlockUser(userId);
}
}
* {@link UserState#STATE_RUNNING}, which only occurs if the user storage is
* actually unlocked.
*/
- void maybeFinishUserUnlock(UserState uss) {
+ void finishUserUnlock(UserState uss) {
final int userId = uss.mHandle.getIdentifier();
synchronized (mService) {
// Bail if we ended up with a stale user
return userManager;
}
+ private IMountService getMountService() {
+ return IMountService.Stub.asInterface(ServiceManager.getService("mount"));
+ }
+
private boolean isUserKeyUnlocked(int userId) {
- final IMountService mountService = IMountService.Stub
- .asInterface(ServiceManager.getService("mount"));
+ final IMountService mountService = getMountService();
if (mountService != null) {
try {
return mountService.isUserKeyUnlocked(userId);
}
}
+ /**
+ * Attempt to unlock user without a credential token. This typically
+ * succeeds when the device doesn't have credential-encrypted storage, or
+ * when the the credential-encrypted storage isn't tied to a user-provided
+ * PIN or pattern.
+ */
+ boolean maybeUnlockUser(final int userId) {
+ // Try unlocking storage using empty token
+ return unlockUserCleared(userId, null);
+ }
+
boolean unlockUserCleared(final int userId, byte[] token) {
synchronized (mService) {
// Bail if already running unlocked
if (uss.state == UserState.STATE_RUNNING) return true;
}
- final UserInfo userInfo = getUserInfo(userId);
- final IMountService mountService = IMountService.Stub
- .asInterface(ServiceManager.getService("mount"));
- try {
- mountService.unlockUserKey(userId, userInfo.serialNumber, token);
- } catch (RemoteException e) {
- Slog.w(TAG, "Failed to unlock: " + e.getMessage());
- return false;
+ if (!isUserKeyUnlocked(userId)) {
+ final UserInfo userInfo = getUserInfo(userId);
+ final IMountService mountService = getMountService();
+ try {
+ mountService.unlockUserKey(userId, userInfo.serialNumber, token);
+ } catch (RemoteException | RuntimeException e) {
+ Slog.w(TAG, "Failed to unlock: " + e.getMessage());
+ return false;
+ }
}
synchronized (mService) {
final UserState uss = mStartedUsers.get(userId);
- maybeFinishUserUnlock(uss);
+ finishUserUnlock(uss);
}
return true;