Introduce KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION

This flag is used by system server to mark keys used during the
synthetic password auth flow. keys marked with this flag will not
be super encrypted because super encryption requires knowledge of
the synthetic password, causing a chicken-and-egg problem.

Bug: 35849499
Bug: 34600579
Test: cts-tradefed run cts-dev -m CtsDevicePolicyManagerTestCases -t com.android.cts.devicepolicy.MixedProfileOwnerTest#testResetPasswordWithToken
Change-Id: Ibd900e3ede1f51c476d462085caaf216d911d693
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index a28a35a..d5923b5 100644
--- a/keystore/key_store_service.cpp
+++ b/keystore/key_store_service.cpp
@@ -658,6 +658,10 @@
     if (!rc.isOk()) {
         return rc;
     }
+    if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
+        return ResponseCode::PERMISSION_DENIED;
+    }
 
     if (containsTag(params, Tag::INCLUDE_UNIQUE_ID)) {
         if (!checkBinderPermission(P_GEN_UNIQUE_ID)) return ResponseCode::PERMISSION_DENIED;
@@ -688,7 +692,8 @@
 
         Blob keyBlob(&hidlKeyBlob[0], hidlKeyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
         keyBlob.setFallback(usingFallback);
-        if (isAuthenticationBound(params)) {
+        keyBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
+        if (isAuthenticationBound(params) && !keyBlob.isCriticalToDeviceEncryption()) {
             keyBlob.setSuperEncrypted(true);
         }
         keyBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -813,6 +818,10 @@
     if (!rc.isOk()) {
         return rc;
     }
+    if ((flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION) && get_app_id(uid) != AID_SYSTEM) {
+        ALOGE("Non-system uid %d cannot set FLAG_CRITICAL_TO_DEVICE_ENCRYPTION", uid);
+        return ResponseCode::PERMISSION_DENIED;
+    }
 
     bool usingFallback = false;
     auto& dev = mKeyStore->getDevice();
@@ -835,7 +844,8 @@
 
         Blob ksBlob(&keyBlob[0], keyBlob.size(), NULL, 0, ::TYPE_KEYMASTER_10);
         ksBlob.setFallback(usingFallback);
-        if (isAuthenticationBound(params)) {
+        ksBlob.setCriticalToDeviceEncryption(flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
+        if (isAuthenticationBound(params) && !ksBlob.isCriticalToDeviceEncryption()) {
             ksBlob.setSuperEncrypted(true);
         }
         ksBlob.setEncrypted(flags & KEYSTORE_FLAG_ENCRYPTED);
@@ -1787,6 +1797,8 @@
                      0 /* infoLength */, ::TYPE_KEYMASTER_10);
         newBlob.setFallback(blob->isFallback());
         newBlob.setEncrypted(blob->isEncrypted());
+        newBlob.setSuperEncrypted(blob->isSuperEncrypted());
+        newBlob.setCriticalToDeviceEncryption(blob->isCriticalToDeviceEncryption());
 
         error = mKeyStore->put(filename.string(), &newBlob, get_user_id(uid));
         if (!error.isOk()) {