Merge "Introduce KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION" into oc-dev
diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java
index 00d786a..244d6e5 100644
--- a/keystore/java/android/security/KeyStore.java
+++ b/keystore/java/android/security/KeyStore.java
@@ -93,6 +93,16 @@
*/
public static final int FLAG_ENCRYPTED = 1;
+ /**
+ * A private flag that's only available to system server to indicate that this key is part of
+ * device encryption flow so it receives special treatment from keystore. For example this key
+ * will not be super encrypted, and it will be stored separately under an unique UID instead
+ * of the caller UID i.e. SYSTEM.
+ *
+ * Need to be in sync with KeyStoreFlag in system/security/keystore/include/keystore/keystore.h
+ */
+ public static final int FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3;
+
// States
public enum State { UNLOCKED, LOCKED, UNINITIALIZED };
diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
index 64b10ab..bab4010 100644
--- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java
@@ -351,6 +351,9 @@
}
} else if (param instanceof KeyProtection) {
spec = (KeyProtection) param;
+ if (spec.isCriticalToDeviceEncryption()) {
+ flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+ }
} else {
throw new KeyStoreException(
"Unsupported protection parameter class:" + param.getClass().getName()
@@ -719,6 +722,10 @@
} catch (IllegalArgumentException | IllegalStateException e) {
throw new KeyStoreException(e);
}
+ int flags = 0;
+ if (params.isCriticalToDeviceEncryption()) {
+ flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+ }
Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
@@ -728,7 +735,7 @@
KeymasterDefs.KM_KEY_FORMAT_RAW,
keyMaterial,
mUid,
- 0, // flags
+ flags,
new KeyCharacteristics());
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to import secret key. Keystore error code: "
diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java
index 2592a97..2eb0663 100644
--- a/keystore/java/android/security/keystore/KeyProtection.java
+++ b/keystore/java/android/security/keystore/KeyProtection.java
@@ -227,6 +227,7 @@
private final boolean mUserAuthenticationValidWhileOnBody;
private final boolean mInvalidatedByBiometricEnrollment;
private final long mBoundToSecureUserId;
+ private final boolean mCriticalToDeviceEncryption;
private KeyProtection(
Date keyValidityStart,
@@ -242,7 +243,8 @@
int userAuthenticationValidityDurationSeconds,
boolean userAuthenticationValidWhileOnBody,
boolean invalidatedByBiometricEnrollment,
- long boundToSecureUserId) {
+ long boundToSecureUserId,
+ boolean criticalToDeviceEncryption) {
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
@@ -259,6 +261,7 @@
mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody;
mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
mBoundToSecureUserId = boundToSecureUserId;
+ mCriticalToDeviceEncryption = criticalToDeviceEncryption;
}
/**
@@ -458,6 +461,16 @@
}
/**
+ * Return whether this key is critical to the device encryption flow.
+ *
+ * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
+ * @hide
+ */
+ public boolean isCriticalToDeviceEncryption() {
+ return mCriticalToDeviceEncryption;
+ }
+
+ /**
* Builder of {@link KeyProtection} instances.
*/
public final static class Builder {
@@ -477,6 +490,7 @@
private boolean mInvalidatedByBiometricEnrollment = true;
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
+ private boolean mCriticalToDeviceEncryption = false;
/**
* Creates a new instance of the {@code Builder}.
*
@@ -817,6 +831,20 @@
}
/**
+ * Set whether this key is critical to the device encryption flow
+ *
+ * This is a special flag only available to system servers to indicate the current key
+ * is part of the device encryption flow.
+ *
+ * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
+ * @hide
+ */
+ public Builder setCriticalToDeviceEncryption(boolean critical) {
+ mCriticalToDeviceEncryption = critical;
+ return this;
+ }
+
+ /**
* Builds an instance of {@link KeyProtection}.
*
* @throws IllegalArgumentException if a required field is missing
@@ -837,7 +865,8 @@
mUserAuthenticationValidityDurationSeconds,
mUserAuthenticationValidWhileOnBody,
mInvalidatedByBiometricEnrollment,
- mBoundToSecureUserId);
+ mBoundToSecureUserId,
+ mCriticalToDeviceEncryption);
}
}
}
diff --git a/services/core/java/com/android/server/SyntheticPasswordCrypto.java b/services/core/java/com/android/server/SyntheticPasswordCrypto.java
index 12d91c5..71ab2a5 100644
--- a/services/core/java/com/android/server/SyntheticPasswordCrypto.java
+++ b/services/core/java/com/android/server/SyntheticPasswordCrypto.java
@@ -139,12 +139,14 @@
keyStore.load(null);
KeyProtection.Builder builder = new KeyProtection.Builder(KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
- .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE);
+ .setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
+ .setCriticalToDeviceEncryption(true);
if (sid != 0) {
builder.setUserAuthenticationRequired(true)
.setBoundToSpecificSecureUserId(sid)
.setUserAuthenticationValidityDurationSeconds(USER_AUTHENTICATION_VALIDITY);
}
+
keyStore.setEntry(keyAlias,
new KeyStore.SecretKeyEntry(secretKey),
builder.build());