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