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());