Merge "Add support for binding storage encryption to a seed" am: 6207c9cde4 am: 4c110af013 am: 0bdfada404

Original change: https://android-review.googlesource.com/c/platform/system/vold/+/1553317

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I496422108eedcb352d2fb45181ba4fc035c59e19
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 8147827..89844aa 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -22,6 +22,8 @@
 #include "Utils.h"
 
 #include <algorithm>
+#include <memory>
+#include <mutex>
 #include <thread>
 #include <vector>
 
@@ -82,6 +84,31 @@
 static const char* kFn_stretching = "stretching";
 static const char* kFn_version = "version";
 
+namespace {
+
+// Storage binding info for ensuring key encryption keys include a
+// platform-provided seed in their derivation.
+struct StorageBindingInfo {
+    enum class State {
+        UNINITIALIZED,
+        IN_USE,    // key storage keys are bound to seed
+        NOT_USED,  // key storage keys are NOT bound to seed
+    };
+
+    // Binding seed mixed into all key storage keys.
+    std::vector<uint8_t> seed;
+
+    // State tracker for the key storage key binding.
+    State state = State::UNINITIALIZED;
+
+    std::mutex guard;
+};
+
+// Never freed as the dtor is non-trivial.
+StorageBindingInfo& storage_binding_info = *new StorageBindingInfo;
+
+}  // namespace
+
 static bool checkSize(const std::string& kind, size_t actual, size_t expected) {
     if (actual != expected) {
         LOG(ERROR) << "Wrong number of bytes in " << kind << ", expected " << expected << " got "
@@ -456,6 +483,20 @@
     std::string stretched;
     if (!stretchSecret(stretching, auth.secret, salt, &stretched)) return false;
     *appId = secdiscardable_hash + stretched;
+
+    const std::lock_guard<std::mutex> scope_lock(storage_binding_info.guard);
+    switch (storage_binding_info.state) {
+        case StorageBindingInfo::State::UNINITIALIZED:
+            storage_binding_info.state = StorageBindingInfo::State::NOT_USED;
+            break;
+        case StorageBindingInfo::State::IN_USE:
+            appId->append(storage_binding_info.seed.begin(), storage_binding_info.seed.end());
+            break;
+        case StorageBindingInfo::State::NOT_USED:
+            // noop
+            break;
+    }
+
     return true;
 }
 
@@ -715,5 +756,22 @@
     return success;
 }
 
+bool setKeyStorageBindingSeed(const std::vector<uint8_t>& seed) {
+    const std::lock_guard<std::mutex> scope_lock(storage_binding_info.guard);
+    switch (storage_binding_info.state) {
+        case StorageBindingInfo::State::UNINITIALIZED:
+            storage_binding_info.state = StorageBindingInfo::State::IN_USE;
+            storage_binding_info.seed = seed;
+            return true;
+        case StorageBindingInfo::State::IN_USE:
+            LOG(ERROR) << "key storage binding seed already set";
+            return false;
+        case StorageBindingInfo::State::NOT_USED:
+            LOG(ERROR) << "key storage already in use without binding";
+            return false;
+    }
+    return false;
+}
+
 }  // namespace vold
 }  // namespace android
diff --git a/KeyStorage.h b/KeyStorage.h
index 1eb26ae..a69dbf7 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -19,7 +19,9 @@
 
 #include "KeyBuffer.h"
 
+#include <cstdint>
 #include <string>
+#include <vector>
 
 namespace android {
 namespace vold {
@@ -72,6 +74,9 @@
 bool generateWrappedStorageKey(KeyBuffer* key);
 // Export the per-boot boot wrapped storage key using keymaster.
 bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key);
+
+// Set a seed to be mixed into all key storage encryption keys.
+bool setKeyStorageBindingSeed(const std::vector<uint8_t>& seed);
 }  // namespace vold
 }  // namespace android
 
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index bdfcdf3..c143041 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -33,6 +33,7 @@
 #include "Checkpoint.h"
 #include "FsCrypt.h"
 #include "IdleMaint.h"
+#include "KeyStorage.h"
 #include "Keymaster.h"
 #include "MetadataCrypt.h"
 #include "MoveStorage.h"
@@ -699,6 +700,13 @@
             fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, fsType));
 }
 
+binder::Status VoldNativeService::setStorageBindingSeed(const std::vector<uint8_t>& seed) {
+    ENFORCE_SYSTEM_OR_ROOT;
+    ACQUIRE_CRYPT_LOCK;
+
+    return translateBool(setKeyStorageBindingSeed(seed));
+}
+
 binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial,
                                                 bool ephemeral) {
     ENFORCE_SYSTEM_OR_ROOT;
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 47991c2..123f127 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -116,6 +116,8 @@
     binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint,
                                 bool shouldFormat, const std::string& fsType);
 
+    binder::Status setStorageBindingSeed(const std::vector<uint8_t>& seed);
+
     binder::Status createUserKey(int32_t userId, int32_t userSerial, bool ephemeral);
     binder::Status destroyUserKey(int32_t userId);
 
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 19ce9ba..24a3b38 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -91,6 +91,8 @@
     void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
     void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType);
 
+    void setStorageBindingSeed(in byte[] seed);
+
     void createUserKey(int userId, int userSerial, boolean ephemeral);
     void destroyUserKey(int userId);