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 +#include +#include #include #include @@ -82,6 +84,31 @@ static const char* kFn_secdiscardable = "secdiscardable"; 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 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 @@ static bool generateAppId(const KeyAuthentication& auth, const std::string& stre std::string stretched; if (!stretchSecret(stretching, auth.secret, salt, &stretched)) return false; *appId = secdiscardable_hash + stretched; + + const std::lock_guard 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 @@ bool destroyKey(const std::string& dir) { return success; } +bool setKeyStorageBindingSeed(const std::vector& seed) { + const std::lock_guard 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 #include +#include namespace android { namespace vold { @@ -72,6 +74,9 @@ bool runSecdiscardSingle(const std::string& file); 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& seed); } // namespace vold } // namespace android diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp index 9f4f7b0..49bf4da 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 @@ binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice, fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, fsType)); } +binder::Status VoldNativeService::setStorageBindingSeed(const std::vector& 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 @@ class VoldNativeService : public BinderService, public os::Bn binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint, bool shouldFormat, const std::string& fsType); + binder::Status setStorageBindingSeed(const std::vector& 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 @@ interface IVold { 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);