summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Eric Biggers <ebiggers@google.com> 2023-06-29 18:17:00 +0000
committer Eric Biggers <ebiggers@google.com> 2023-10-10 22:52:36 +0000
commit73d7a1bf415a89cb4944afc07a2ff16c2fd58d00 (patch)
treeb55ccbfb6ca9bd654ad3d846b6fbb658c775dc36
parent0ebf8d8d74ab51b3094b32a67cda05026d7a763f (diff)
Replace isWeaverAvailable() with getWeaverService()
isWeaverAvailable() has to be called before weaverVerify() and weaverEnroll(); otherwise mWeaver might still be null. However, this was not enforced and was easy to forget to do. This CL therefore changes the design slightly to make weaverVerify() and weaverEnroll() take IWeaver as an argument. To get the IWeaver, getWeaverService() is called, taking the place of isWeaverAvailable(). Note that this is analogous to LockSettingsService#getGateKeeperService. Bug: 287705522 Test: Treehugger Change-Id: I70c26232a9b300a7e6e2c815db6c143836c42ec3 Merged-In: I70c26232a9b300a7e6e2c815db6c143836c42ec3 (cherry picked from commit 922aaa24fac9be3c62439d9ad1faa81e38b5a1b3)
-rw-r--r--services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java68
1 files changed, 40 insertions, 28 deletions
diff --git a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
index 7fec377b3e9e..131e365e2362 100644
--- a/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
+++ b/services/core/java/com/android/server/locksettings/SyntheticPasswordManager.java
@@ -531,7 +531,7 @@ class SyntheticPasswordManager {
}
}
- private IWeaver getWeaverService() {
+ private @Nullable IWeaver getWeaverServiceInternal() {
// Try to get the AIDL service first
try {
IWeaver aidlWeaver = IWeaver.Stub.asInterface(
@@ -563,15 +563,20 @@ class SyntheticPasswordManager {
return LockPatternUtils.isAutoPinConfirmFeatureAvailable();
}
- private synchronized boolean isWeaverAvailable() {
- if (mWeaver != null) {
- return true;
+ /**
+ * Returns a handle to the Weaver service, or null if Weaver is unavailable. Note that not all
+ * devices support Weaver.
+ */
+ private synchronized @Nullable IWeaver getWeaverService() {
+ IWeaver weaver = mWeaver;
+ if (weaver != null) {
+ return weaver;
}
// Re-initialize weaver in case there was a transient error preventing access to it.
- IWeaver weaver = getWeaverService();
+ weaver = getWeaverServiceInternal();
if (weaver == null) {
- return false;
+ return null;
}
final WeaverConfig weaverConfig;
@@ -579,19 +584,18 @@ class SyntheticPasswordManager {
weaverConfig = weaver.getConfig();
} catch (RemoteException | ServiceSpecificException e) {
Slog.e(TAG, "Failed to get weaver config", e);
- return false;
+ return null;
}
if (weaverConfig == null || weaverConfig.slots <= 0) {
Slog.e(TAG, "Invalid weaver config");
- return false;
+ return null;
}
mWeaver = weaver;
mWeaverConfig = weaverConfig;
mPasswordSlotManager.refreshActiveSlots(getUsedWeaverSlots());
Slog.i(TAG, "Weaver service initialized");
-
- return true;
+ return weaver;
}
/**
@@ -601,7 +605,7 @@ class SyntheticPasswordManager {
*
* @return the value stored in the weaver slot, or null if the operation fails
*/
- private byte[] weaverEnroll(int slot, byte[] key, @Nullable byte[] value) {
+ private byte[] weaverEnroll(IWeaver weaver, int slot, byte[] key, @Nullable byte[] value) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
throw new IllegalArgumentException("Invalid slot for weaver");
}
@@ -614,7 +618,7 @@ class SyntheticPasswordManager {
value = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize);
}
try {
- mWeaver.write(slot, key, value);
+ weaver.write(slot, key, value);
} catch (RemoteException e) {
Slog.e(TAG, "weaver write binder call failed, slot: " + slot, e);
return null;
@@ -643,7 +647,7 @@ class SyntheticPasswordManager {
* the verification is successful, throttled or failed. If successful, the bound secret
* is also returned.
*/
- private VerifyCredentialResponse weaverVerify(int slot, byte[] key) {
+ private VerifyCredentialResponse weaverVerify(IWeaver weaver, int slot, byte[] key) {
if (slot == INVALID_WEAVER_SLOT || slot >= mWeaverConfig.slots) {
throw new IllegalArgumentException("Invalid slot for weaver");
}
@@ -654,7 +658,7 @@ class SyntheticPasswordManager {
}
final WeaverReadResponse readResponse;
try {
- readResponse = mWeaver.read(slot, key);
+ readResponse = weaver.read(slot, key);
} catch (RemoteException e) {
Slog.e(TAG, "weaver read failed, slot: " + slot, e);
return VerifyCredentialResponse.ERROR;
@@ -846,14 +850,15 @@ class SyntheticPasswordManager {
int slot = loadWeaverSlot(protectorId, userId);
destroyState(WEAVER_SLOT_NAME, protectorId, userId);
if (slot != INVALID_WEAVER_SLOT) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Cannot erase Weaver slot because Weaver is unavailable");
return;
}
Set<Integer> usedSlots = getUsedWeaverSlots();
if (!usedSlots.contains(slot)) {
Slogf.i(TAG, "Erasing Weaver slot %d", slot);
- weaverEnroll(slot, null, null);
+ weaverEnroll(weaver, slot, null, null);
mPasswordSlotManager.markSlotDeleted(slot);
} else {
Slogf.i(TAG, "Weaver slot %d was already reused; not erasing it", slot);
@@ -931,13 +936,14 @@ class SyntheticPasswordManager {
Slogf.i(TAG, "Creating LSKF-based protector %016x for user %d", protectorId, userId);
- if (isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver != null) {
// Weaver is available, so make the protector use it to verify the LSKF. Do this even
// if the LSKF is empty, as that gives us support for securely deleting the protector.
int weaverSlot = getNextAvailableWeaverSlot();
Slogf.i(TAG, "Enrolling LSKF for user %d into Weaver slot %d", userId, weaverSlot);
- byte[] weaverSecret = weaverEnroll(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf),
- null);
+ byte[] weaverSecret = weaverEnroll(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf), null);
if (weaverSecret == null) {
throw new IllegalStateException(
"Fail to enroll user password under weaver " + userId);
@@ -1024,7 +1030,8 @@ class SyntheticPasswordManager {
}
return VerifyCredentialResponse.fromGateKeeperResponse(response);
} else if (persistentData.type == PersistentData.TYPE_SP_WEAVER) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "No weaver service to verify SP-based FRP credential");
return VerifyCredentialResponse.ERROR;
}
@@ -1032,7 +1039,8 @@ class SyntheticPasswordManager {
byte[] stretchedLskf = stretchLskf(userCredential, pwd);
int weaverSlot = persistentData.userId;
- return weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf)).stripPayload();
+ return weaverVerify(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf)).stripPayload();
} else {
Slog.e(TAG, "persistentData.type must be TYPE_SP_GATEKEEPER or TYPE_SP_WEAVER, but is "
+ persistentData.type);
@@ -1134,7 +1142,7 @@ class SyntheticPasswordManager {
TokenData tokenData = new TokenData();
tokenData.mType = type;
final byte[] secdiscardable = SecureRandomUtils.randomBytes(SECDISCARDABLE_LENGTH);
- if (isWeaverAvailable()) {
+ if (getWeaverService() != null) {
tokenData.weaverSecret = SecureRandomUtils.randomBytes(mWeaverConfig.valueSize);
tokenData.secdiscardableOnDisk = SyntheticPasswordCrypto.encrypt(tokenData.weaverSecret,
PERSONALIZATION_WEAVER_TOKEN, secdiscardable);
@@ -1177,10 +1185,11 @@ class SyntheticPasswordManager {
return false;
}
Slogf.i(TAG, "Creating token-based protector %016x for user %d", tokenHandle, userId);
- if (isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver != null) {
int slot = getNextAvailableWeaverSlot();
Slogf.i(TAG, "Using Weaver slot %d for new token-based protector", slot);
- if (weaverEnroll(slot, null, tokenData.weaverSecret) == null) {
+ if (weaverEnroll(weaver, slot, null, tokenData.weaverSecret) == null) {
Slog.e(TAG, "Failed to enroll weaver secret when activating token");
return false;
}
@@ -1269,12 +1278,14 @@ class SyntheticPasswordManager {
int weaverSlot = loadWeaverSlot(protectorId, userId);
if (weaverSlot != INVALID_WEAVER_SLOT) {
// Protector uses Weaver to verify the LSKF
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable");
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
- result.gkResponse = weaverVerify(weaverSlot, stretchedLskfToWeaverKey(stretchedLskf));
+ result.gkResponse = weaverVerify(weaver, weaverSlot,
+ stretchedLskfToWeaverKey(stretchedLskf));
if (result.gkResponse.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK) {
return result;
}
@@ -1442,12 +1453,13 @@ class SyntheticPasswordManager {
}
int slotId = loadWeaverSlot(protectorId, userId);
if (slotId != INVALID_WEAVER_SLOT) {
- if (!isWeaverAvailable()) {
+ final IWeaver weaver = getWeaverService();
+ if (weaver == null) {
Slog.e(TAG, "Protector uses Weaver, but Weaver is unavailable");
result.gkResponse = VerifyCredentialResponse.ERROR;
return result;
}
- VerifyCredentialResponse response = weaverVerify(slotId, null);
+ VerifyCredentialResponse response = weaverVerify(weaver, slotId, null);
if (response.getResponseCode() != VerifyCredentialResponse.RESPONSE_OK ||
response.getGatekeeperHAT() == null) {
Slog.e(TAG,