Merge "Fix temporary key deletion after device ID attestation" into oc-dev
diff --git a/keystore/blob.cpp b/keystore/blob.cpp
index 8c8267b..237d896 100644
--- a/keystore/blob.cpp
+++ b/keystore/blob.cpp
@@ -75,6 +75,10 @@
     return mBlob.flags & KEYSTORE_FLAG_SUPER_ENCRYPTED;
 }
 
+bool Blob::isCriticalToDeviceEncryption() const {
+    return mBlob.flags & KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
+}
+
 inline uint8_t setFlag(uint8_t flags, bool set, KeyStoreFlag flag) {
     return set ? (flags | flag) : (flags & ~flag);
 }
@@ -83,11 +87,12 @@
     mBlob.flags = setFlag(mBlob.flags, encrypted, KEYSTORE_FLAG_ENCRYPTED);
 }
 
-void Blob::setSuperEncrypted(__attribute__((unused)) bool superEncrypted) {
-    // Do not enable super encryption yet, as it's clashing with synthetic password flow
-    // TODO: re-enables this once keystore knows about synthetic password keys
+void Blob::setSuperEncrypted(bool superEncrypted) {
+    mBlob.flags = setFlag(mBlob.flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
+}
 
-    //mBlob.flags = setFlag(mBlob.flags, superEncrypted, KEYSTORE_FLAG_SUPER_ENCRYPTED);
+void Blob::setCriticalToDeviceEncryption(bool critical) {
+    mBlob.flags = setFlag(mBlob.flags, critical, KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION);
 }
 
 void Blob::setFallback(bool fallback) {
diff --git a/keystore/blob.h b/keystore/blob.h
index f710641..06f9ea5 100644
--- a/keystore/blob.h
+++ b/keystore/blob.h
@@ -98,6 +98,9 @@
     bool isSuperEncrypted() const;
     void setSuperEncrypted(bool superEncrypted);
 
+    bool isCriticalToDeviceEncryption() const;
+    void setCriticalToDeviceEncryption(bool critical);
+
     bool isFallback() const { return mBlob.flags & KEYSTORE_FLAG_FALLBACK; }
     void setFallback(bool fallback);
 
diff --git a/keystore/include/keystore/keystore.h b/keystore/include/keystore/keystore.h
index 6d67edb..7260363 100644
--- a/keystore/include/keystore/keystore.h
+++ b/keystore/include/keystore/keystore.h
@@ -57,6 +57,11 @@
     // cleared, rather than deleting blobs, and the error returned when attempting to use a
     // super-encrypted blob while keystore is locked is different.
     KEYSTORE_FLAG_SUPER_ENCRYPTED = 1 << 2,
+    // KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION is for blobs that are part of device encryption
+    // flow so it receives special treatment from keystore. For example this blob will not be super
+    // encrypted, and it will be stored separately under an unique UID instead. This flag should
+    // only be available to system uid.
+    KEYSTORE_FLAG_CRITICAL_TO_DEVICE_ENCRYPTION = 1 << 3,
 };
 
 /**
diff --git a/keystore/key_store_service.cpp b/keystore/key_store_service.cpp
index a8b635e..a509eea 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()) {