summaryrefslogtreecommitdiff
path: root/keystore
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2024-01-17 22:51:04 +0000
committerEric Biggers <ebiggers@google.com>2024-01-17 22:51:04 +0000
commitcd7f4fada9cd5b3e4be2518b8c6ab6fb4dd95996 (patch)
tree05bc8fe41b474fba01a79d7a333691bef317c06a /keystore
parent31fd707aed3a7fd0253905d5c8b4ca87ba5b7a57 (diff)
downloadbase-cd7f4fada9cd5b3e4be2518b8c6ab6fb4dd95996.tar.gz
Fix UnlockedDeviceRequired with weak unlock methods
Starting in Android 12, unlocking the device with a class 1 ("convenience") biometric, class 2 ("weak") biometric, or a trust agent unexpectedly doesn't allow the use of UnlockedDeviceRequired keys. The cause of this bug is that the cryptographic protection that Keystore now applies to UnlockedDeviceRequired keys incorrectly assumes that the device can only be unlocked using LSKF or via a biometric that participates in Keystore (has a SID and uses HardwareAuthTokens). Actually, Keyguard also allows the device to be unlocked using weaker biometrics that do not particiate in Keystore, if they are enrolled. Similarly, there are also cases where a trust agent can actively unlock the device, e.g. unlocking a phone using a paired watch. In combination with the Keystore changes in I1b0d9ec4f9e31dc91642e865045766bd17e34cad, this CL fixes the bug by making Keystore retain the UnlockedDeviceRequired super keys in memory if a weak unlock method is enabled at device lock time. This does mean that UnlockedDeviceRequired is enforced only logically when a weak unlock method is enabled, but this is the best we can do in this case. Note: a future CL will take into account the progressive expiration of unlock methods while the device is locked and upgrade the security of UnlockedDeviceRequired accordingly. The present CL focuses just on choosing the correct protection at lock time, fixing a user-visible bug. Test: Ran the following automated tests with and without the fix_unlocked_device_required_keys_v2 flag enabled: atest com.android.server.locksettings \ && atest TrustManagerServiceTest \ && atest TrustTests \ && atest -p --include-subdirs system/security/keystore2 \ && atest CtsKeystoreTestCases Test: Manually tested each combination of biometric setup: none, fingerprint, face, and fingerprint+face. Locked the device, then verified via logcat that Keystore protected the UnlockedDeviceRequired keys in the expected way, then verified that UnlockedDeviceRequired keys cannot be used (even in the case where the super keys were not protected). Unlocked device using weakest method available, then verified that UnlockedDeviceRequired keys can be used. To check whether UnlockedDeviceRequired keys can be used or not, used the CTS method mentioned in the Test of https://r.android.com/2878769. Also, enabled Extend Unlock with a bluetooth device, and verified that it's not counted as an unlock method. Also, verified that if Lockdown mode is triggered, the UnlockedDeviceRequired keys are fully protected. Bug: 296464083 Change-Id: I34dc49f1338e94755e96c1cf84de0638dc70d311
Diffstat (limited to 'keystore')
-rw-r--r--keystore/java/android/security/Authorization.java6
1 files changed, 4 insertions, 2 deletions
diff --git a/keystore/java/android/security/Authorization.java b/keystore/java/android/security/Authorization.java
index 4ec5e1b67c5d..6404c4bc33d6 100644
--- a/keystore/java/android/security/Authorization.java
+++ b/keystore/java/android/security/Authorization.java
@@ -100,12 +100,14 @@ public class Authorization {
*
* @param userId - the user's Android user ID
* @param unlockingSids - list of biometric SIDs with which the device may be unlocked again
+ * @param weakUnlockEnabled - true if non-strong biometric or trust agent unlock is enabled
* @return 0 if successful or a {@code ResponseCode}.
*/
- public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids) {
+ public static int onDeviceLocked(int userId, @NonNull long[] unlockingSids,
+ boolean weakUnlockEnabled) {
StrictMode.noteDiskWrite();
try {
- getService().onDeviceLocked(userId, unlockingSids);
+ getService().onDeviceLocked(userId, unlockingSids, weakUnlockEnabled);
return 0;
} catch (RemoteException | NullPointerException e) {
Log.w(TAG, "Can not connect to keystore", e);