diff --git a/FsCrypt.cpp b/FsCrypt.cpp index 4a3cb6e..fd42cbe 100644 --- a/FsCrypt.cpp +++ b/FsCrypt.cpp @@ -198,7 +198,7 @@ static bool read_and_fixate_user_ce_key(userid_t user_id, auto const paths = get_ce_key_paths(directory_path); for (auto const ce_key_path : paths) { LOG(DEBUG) << "Trying user CE key " << ce_key_path; - if (retrieveKey(ce_key_path, auth, ce_key)) { + if (retrieveKey(ce_key_path, auth, ce_key, false)) { LOG(DEBUG) << "Successfully retrieved key"; fixate_user_ce_key(directory_path, ce_key_path, paths); return true; @@ -407,7 +407,7 @@ static bool load_all_de_keys() { userid_t user_id = std::stoi(entry->d_name); auto key_path = de_dir + "/" + entry->d_name; KeyBuffer de_key; - if (!retrieveKey(key_path, kEmptyAuthentication, &de_key)) return false; + if (!retrieveKey(key_path, kEmptyAuthentication, &de_key, false)) return false; EncryptionPolicy de_policy; if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false; auto ret = s_de_policies.insert({user_id, de_policy}); @@ -441,7 +441,7 @@ bool fscrypt_initialize_systemwide_keys() { KeyBuffer device_key; if (!retrieveOrGenerateKey(device_key_path, device_key_temp, kEmptyAuthentication, - makeGen(options), &device_key)) + makeGen(options), &device_key, false)) return false; EncryptionPolicy device_policy; @@ -675,7 +675,7 @@ static bool read_or_create_volkey(const std::string& misc_path, const std::strin EncryptionOptions options; if (!get_volume_file_encryption_options(&options)) return false; KeyBuffer key; - if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key)) + if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key, false)) return false; if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false; return true; @@ -694,12 +694,12 @@ static bool fscrypt_rewrap_user_key(userid_t user_id, int serial, auto const directory_path = get_ce_key_directory_path(user_id); KeyBuffer ce_key; std::string ce_key_current_path = get_ce_key_current_path(directory_path); - if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key)) { + if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key, false)) { LOG(DEBUG) << "Successfully retrieved key"; // TODO(147732812): Remove this once Locksettingservice is fixed. // Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is // changed from swipe to none or vice-versa - } else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) { + } else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key, false)) { LOG(DEBUG) << "Successfully retrieved key with empty auth"; } else { LOG(ERROR) << "Failed to retrieve key for user " << user_id; diff --git a/KeyStorage.h b/KeyStorage.h index f9d3ec6..5228f08 100644 --- a/KeyStorage.h +++ b/KeyStorage.h @@ -61,8 +61,20 @@ bool storeKeyAtomically(const std::string& key_path, const std::string& tmp_path const KeyAuthentication& auth, const KeyBuffer& key); // Retrieve the key from the named directory. +// +// If the key is wrapped by a Keymaster key that requires an upgrade, then that +// Keymaster key is upgraded. If |keepOld| is false, then the upgraded +// Keymaster key replaces the original one. As part of this, the original is +// deleted from Keymaster; however, if a user data checkpoint is active, this +// part is delayed until the checkpoint is committed. +// +// If instead |keepOld| is true, then the upgraded key doesn't actually replace +// the original one. This is needed *only* if |dir| isn't located in /data and +// a user data checkpoint is active. In this case the caller must handle +// replacing the original key if the checkpoint is committed, and deleting the +// upgraded key if the checkpoint is rolled back. bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key, - bool keepOld = false); + bool keepOld); // Securely destroy the key stored in the named directory and delete the directory. bool destroyKey(const std::string& dir); diff --git a/KeyUtil.h b/KeyUtil.h index 23278c1..0f5bc93 100644 --- a/KeyUtil.h +++ b/KeyUtil.h @@ -74,9 +74,11 @@ bool installKey(const std::string& mountpoint, const EncryptionOptions& options, // responsible for dropping caches. bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy); +// Retrieves the key from the named directory, or generates it if it doesn't +// exist. In most cases |keepOld| must be false; see retrieveKey() for details. bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path, const KeyAuthentication& key_authentication, const KeyGeneration& gen, - KeyBuffer* key, bool keepOld = true); + KeyBuffer* key, bool keepOld); // Re-installs a file-based encryption key of fscrypt-provisioning type from the // global session keyring back into fs keyring of the mountpoint. diff --git a/VolumeManager.cpp b/VolumeManager.cpp index a543573..585d2d5 100644 --- a/VolumeManager.cpp +++ b/VolumeManager.cpp @@ -1066,8 +1066,42 @@ int VolumeManager::createObb(const std::string& sourcePath, const std::string& s int32_t ownerGid, std::string* outVolId) { int id = mNextObbId++; + std::string lowerSourcePath; + + // Convert to lower filesystem path + if (StartsWith(sourcePath, "/storage/")) { + auto filter_fn = [&](const VolumeBase& vol) { + if (vol.getState() != VolumeBase::State::kMounted) { + // The volume must be mounted + return false; + } + if ((vol.getMountFlags() & VolumeBase::MountFlags::kVisible) == 0) { + // and visible + return false; + } + if (vol.getInternalPath().empty()) { + return false; + } + if (!sourcePath.empty() && StartsWith(sourcePath, vol.getPath())) { + return true; + } + + return false; + }; + auto volume = findVolumeWithFilter(filter_fn); + if (volume == nullptr) { + LOG(ERROR) << "Failed to find mounted volume for " << sourcePath; + return -EINVAL; + } else { + lowerSourcePath = + volume->getInternalPath() + sourcePath.substr(volume->getPath().length()); + } + } else { + lowerSourcePath = sourcePath; + } + auto vol = std::shared_ptr( - new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid)); + new android::vold::ObbVolume(id, lowerSourcePath, sourceKey, ownerGid)); vol->create(); mObbVolumes.push_back(vol);