Refactor key generation to handle both normal and metadata encryption.
Bug: 147733587 Test: Treehugger Change-Id: Iee176037dec2621c84da325c2627f988fcebbc8d Merged-In: Iee176037dec2621c84da325c2627f988fcebbc8d
This commit is contained in:
parent
7566e467ab
commit
4eac264727
7 changed files with 82 additions and 55 deletions
23
FsCrypt.cpp
23
FsCrypt.cpp
|
@ -64,6 +64,9 @@ using android::fs_mgr::GetEntryForMountPoint;
|
|||
using android::vold::BuildDataPath;
|
||||
using android::vold::kEmptyAuthentication;
|
||||
using android::vold::KeyBuffer;
|
||||
using android::vold::makeGen;
|
||||
using android::vold::retrieveKey;
|
||||
using android::vold::retrieveOrGenerateKey;
|
||||
using android::vold::writeStringToFile;
|
||||
using namespace android::fscrypt;
|
||||
|
||||
|
@ -183,7 +186,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 (android::vold::retrieveKey(ce_key_path, auth, ce_key)) {
|
||||
if (retrieveKey(ce_key_path, auth, ce_key)) {
|
||||
LOG(DEBUG) << "Successfully retrieved key";
|
||||
fixate_user_ce_key(directory_path, ce_key_path, paths);
|
||||
return true;
|
||||
|
@ -274,8 +277,8 @@ static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral
|
|||
EncryptionOptions options;
|
||||
if (!get_data_file_encryption_options(&options)) return false;
|
||||
KeyBuffer de_key, ce_key;
|
||||
if (!generateStorageKey(options, &de_key)) return false;
|
||||
if (!generateStorageKey(options, &ce_key)) return false;
|
||||
if (!generateStorageKey(makeGen(options), &de_key)) return false;
|
||||
if (!generateStorageKey(makeGen(options), &ce_key)) return false;
|
||||
if (create_ephemeral) {
|
||||
// If the key should be created as ephemeral, don't store it.
|
||||
s_ephemeral_users.insert(user_id);
|
||||
|
@ -349,7 +352,7 @@ static bool load_all_de_keys() {
|
|||
if (s_de_policies.count(user_id) == 0) {
|
||||
auto key_path = de_dir + "/" + entry->d_name;
|
||||
KeyBuffer de_key;
|
||||
if (!android::vold::retrieveKey(key_path, kEmptyAuthentication, &de_key)) return false;
|
||||
if (!retrieveKey(key_path, kEmptyAuthentication, &de_key)) return false;
|
||||
EncryptionPolicy de_policy;
|
||||
if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
|
||||
s_de_policies[user_id] = de_policy;
|
||||
|
@ -372,8 +375,8 @@ bool fscrypt_initialize_systemwide_keys() {
|
|||
if (!get_data_file_encryption_options(&options)) return false;
|
||||
|
||||
KeyBuffer device_key;
|
||||
if (!android::vold::retrieveKey(true, kEmptyAuthentication, device_key_path, device_key_temp,
|
||||
options, &device_key))
|
||||
if (!retrieveOrGenerateKey(device_key_path, device_key_temp, kEmptyAuthentication,
|
||||
makeGen(options), &device_key))
|
||||
return false;
|
||||
|
||||
EncryptionPolicy device_policy;
|
||||
|
@ -392,7 +395,7 @@ bool fscrypt_initialize_systemwide_keys() {
|
|||
LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
|
||||
|
||||
KeyBuffer per_boot_key;
|
||||
if (!generateStorageKey(options, &per_boot_key)) return false;
|
||||
if (!generateStorageKey(makeGen(options), &per_boot_key)) return false;
|
||||
EncryptionPolicy per_boot_policy;
|
||||
if (!install_storage_key(DATA_MNT_POINT, options, per_boot_key, &per_boot_policy)) return false;
|
||||
std::string per_boot_ref_filename = std::string("/data") + fscrypt_key_per_boot_ref;
|
||||
|
@ -601,7 +604,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 (!android::vold::retrieveKey(true, auth, key_path, key_path + "_tmp", options, &key))
|
||||
if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key))
|
||||
return false;
|
||||
if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false;
|
||||
return true;
|
||||
|
@ -620,12 +623,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 (android::vold::retrieveKey(ce_key_current_path, retrieve_auth, &ce_key)) {
|
||||
if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key)) {
|
||||
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 (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
|
||||
} else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
|
||||
LOG(DEBUG) << "Successfully retrieved key with empty auth";
|
||||
} else {
|
||||
LOG(ERROR) << "Failed to retrieve key for user " << user_id;
|
||||
|
|
38
KeyUtil.cpp
38
KeyUtil.cpp
|
@ -36,8 +36,20 @@
|
|||
namespace android {
|
||||
namespace vold {
|
||||
|
||||
bool randomKey(KeyBuffer* key) {
|
||||
*key = KeyBuffer(FSCRYPT_MAX_KEY_SIZE);
|
||||
const KeyGeneration makeGen(const EncryptionOptions& options) {
|
||||
return KeyGeneration{FSCRYPT_MAX_KEY_SIZE, true, options.use_hw_wrapped_key};
|
||||
}
|
||||
|
||||
const KeyGeneration makeGen(const CryptoType& crypto) {
|
||||
return KeyGeneration{crypto.get_keysize(), true, false};
|
||||
}
|
||||
|
||||
const KeyGeneration neverGen() {
|
||||
return KeyGeneration{0, false, false};
|
||||
}
|
||||
|
||||
static bool randomKey(size_t size, KeyBuffer* key) {
|
||||
*key = KeyBuffer(size);
|
||||
if (ReadRandomBytes(key->size(), key->data()) != 0) {
|
||||
// TODO status_t plays badly with PLOG, fix it.
|
||||
LOG(ERROR) << "Random read failed";
|
||||
|
@ -46,11 +58,17 @@ bool randomKey(KeyBuffer* key) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool generateStorageKey(const EncryptionOptions& options, KeyBuffer* key) {
|
||||
if (options.use_hw_wrapped_key) {
|
||||
bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key) {
|
||||
if (!gen.allow_gen) return false;
|
||||
if (gen.use_hw_wrapped_key) {
|
||||
if (gen.keysize != FSCRYPT_MAX_KEY_SIZE) {
|
||||
LOG(ERROR) << "Cannot generate a wrapped key " << gen.keysize << " bytes long";
|
||||
return false;
|
||||
}
|
||||
return generateWrappedStorageKey(key);
|
||||
} else {
|
||||
return randomKey(gen.keysize, key);
|
||||
}
|
||||
return randomKey(key);
|
||||
}
|
||||
|
||||
// Return true if the kernel supports the ioctls to add/remove fscrypt keys
|
||||
|
@ -315,19 +333,19 @@ bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool retrieveKey(bool create_if_absent, const KeyAuthentication& key_authentication,
|
||||
const std::string& key_path, const std::string& tmp_path,
|
||||
const EncryptionOptions& options, KeyBuffer* key, bool keepOld) {
|
||||
bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
|
||||
const KeyAuthentication& key_authentication, const KeyGeneration& gen,
|
||||
KeyBuffer* key, bool keepOld) {
|
||||
if (pathExists(key_path)) {
|
||||
LOG(DEBUG) << "Key exists, using: " << key_path;
|
||||
if (!retrieveKey(key_path, key_authentication, key, keepOld)) return false;
|
||||
} else {
|
||||
if (!create_if_absent) {
|
||||
if (!gen.allow_gen) {
|
||||
LOG(ERROR) << "No key found in " << key_path;
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "Creating new key in " << key_path;
|
||||
if (!generateStorageKey(options, key)) return false;
|
||||
if (!generateStorageKey(gen, key)) return false;
|
||||
if (!storeKeyAtomically(key_path, tmp_path, key_authentication, *key)) return false;
|
||||
}
|
||||
return true;
|
||||
|
|
28
KeyUtil.h
28
KeyUtil.h
|
@ -17,6 +17,7 @@
|
|||
#ifndef ANDROID_VOLD_KEYUTIL_H
|
||||
#define ANDROID_VOLD_KEYUTIL_H
|
||||
|
||||
#include "CryptoType.h"
|
||||
#include "KeyBuffer.h"
|
||||
#include "KeyStorage.h"
|
||||
|
||||
|
@ -30,9 +31,26 @@ namespace vold {
|
|||
|
||||
using namespace android::fscrypt;
|
||||
|
||||
bool randomKey(KeyBuffer* key);
|
||||
// Description of how to generate a key when needed.
|
||||
struct KeyGeneration {
|
||||
size_t keysize;
|
||||
bool allow_gen;
|
||||
bool use_hw_wrapped_key;
|
||||
};
|
||||
|
||||
bool generateStorageKey(const EncryptionOptions& options, KeyBuffer* key);
|
||||
// Generate a key as specified in KeyGeneration
|
||||
bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key);
|
||||
|
||||
// Returns KeyGeneration suitable for key as described in EncryptionOptions
|
||||
const KeyGeneration makeGen(const EncryptionOptions& options);
|
||||
|
||||
// Returns KeyGeneration suitable for key as described in CryptoType
|
||||
const KeyGeneration makeGen(const CryptoType& crypto);
|
||||
|
||||
// Returns a key with allow_gen false so generateStorageKey returns false;
|
||||
// this is used to indicate to retrieveOrGenerateKey that a key should not
|
||||
// be generated.
|
||||
const KeyGeneration neverGen();
|
||||
|
||||
bool isFsKeyringSupported(void);
|
||||
|
||||
|
@ -58,9 +76,9 @@ bool installKey(const std::string& mountpoint, const EncryptionOptions& options,
|
|||
// In the latter case, the caller is responsible for dropping caches.
|
||||
bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy);
|
||||
|
||||
bool retrieveKey(bool create_if_absent, const KeyAuthentication& key_authentication,
|
||||
const std::string& key_path, const std::string& tmp_path,
|
||||
const EncryptionOptions& options, KeyBuffer* key, bool keepOld = true);
|
||||
bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
|
||||
const KeyAuthentication& key_authentication, const KeyGeneration& gen,
|
||||
KeyBuffer* key, bool keepOld = true);
|
||||
|
||||
} // namespace vold
|
||||
} // namespace android
|
||||
|
|
|
@ -129,24 +129,8 @@ static void commit_key(const std::string& dir) {
|
|||
LOG(INFO) << "Old Key deleted: " << dir;
|
||||
}
|
||||
|
||||
static bool retrieveMetadataKey(bool create_if_absent, const std::string& key_path,
|
||||
const std::string& tmp_path, KeyBuffer* key, bool keepOld) {
|
||||
if (pathExists(key_path)) {
|
||||
LOG(DEBUG) << "Key exists, using: " << key_path;
|
||||
if (!retrieveKey(key_path, kEmptyAuthentication, key, keepOld)) return false;
|
||||
} else {
|
||||
if (!create_if_absent) {
|
||||
LOG(ERROR) << "No key found in " << key_path;
|
||||
return false;
|
||||
}
|
||||
LOG(INFO) << "Creating new key in " << key_path;
|
||||
if (!randomKey(key)) return false;
|
||||
if (!storeKeyAtomically(key_path, tmp_path, kEmptyAuthentication, *key)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool read_key(const std::string& metadata_key_dir, bool create_if_absent, KeyBuffer* key) {
|
||||
static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& gen,
|
||||
KeyBuffer* key) {
|
||||
if (metadata_key_dir.empty()) {
|
||||
LOG(ERROR) << "Failed to get metadata_key_dir";
|
||||
return false;
|
||||
|
@ -168,14 +152,14 @@ static bool read_key(const std::string& metadata_key_dir, bool create_if_absent,
|
|||
Keymaster keymaster;
|
||||
if (pathExists(newKeyPath)) {
|
||||
if (!android::base::ReadFileToString(newKeyPath, &sKey))
|
||||
LOG(ERROR) << "Failed to read old key: " << dir;
|
||||
LOG(ERROR) << "Failed to read incomplete key: " << dir;
|
||||
else if (!keymaster.deleteKey(sKey))
|
||||
LOG(ERROR) << "Old key deletion failed, continuing anyway: " << dir;
|
||||
LOG(ERROR) << "Incomplete key deletion failed, continuing anyway: " << dir;
|
||||
else
|
||||
unlink(newKeyPath.c_str());
|
||||
}
|
||||
bool needs_cp = cp_needsCheckpoint();
|
||||
if (!retrieveMetadataKey(create_if_absent, dir, temp, key, needs_cp)) return false;
|
||||
if (!retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key, needs_cp)) return false;
|
||||
if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
|
||||
return true;
|
||||
}
|
||||
|
@ -283,8 +267,9 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::
|
|||
return false;
|
||||
}
|
||||
|
||||
auto gen = needs_encrypt ? makeGen(cipher) : neverGen();
|
||||
KeyBuffer key;
|
||||
if (!read_key(data_rec->metadata_key_dir, needs_encrypt, &key)) return false;
|
||||
if (!read_key(data_rec->metadata_key_dir, gen, &key)) return false;
|
||||
|
||||
std::string crypto_blkdev;
|
||||
if (!create_crypto_blk_dev(kDmNameUserdata, data_rec->blk_device, is_legacy,
|
||||
|
|
|
@ -74,6 +74,7 @@ using android::base::StringPrintf;
|
|||
using android::fs_mgr::GetEntryForMountPoint;
|
||||
using android::vold::CryptoType;
|
||||
using android::vold::KeyBuffer;
|
||||
using android::vold::KeyGeneration;
|
||||
using namespace android::dm;
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
|
@ -320,6 +321,10 @@ static const CryptoType& get_crypto_type() {
|
|||
return crypto_type;
|
||||
}
|
||||
|
||||
const KeyGeneration cryptfs_get_keygen() {
|
||||
return makeGen(get_crypto_type());
|
||||
}
|
||||
|
||||
/* Should we use keymaster? */
|
||||
static int keymaster_check_compatibility() {
|
||||
return keymaster_compatibility_cryptfs_scrypt();
|
||||
|
@ -469,10 +474,6 @@ static void get_device_scrypt_params(struct crypt_mnt_ftr* ftr) {
|
|||
ftr->p_factor = pf;
|
||||
}
|
||||
|
||||
size_t cryptfs_get_keysize() {
|
||||
return get_crypto_type().get_keysize();
|
||||
}
|
||||
|
||||
static uint64_t get_fs_size(const char* dev) {
|
||||
int fd, block_size;
|
||||
struct ext4_super_block sb;
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <cutils/properties.h>
|
||||
|
||||
#include "KeyBuffer.h"
|
||||
#include "KeyUtil.h"
|
||||
|
||||
#define CRYPT_FOOTER_OFFSET 0x4000
|
||||
|
||||
|
@ -73,7 +74,6 @@ int cryptfs_get_password_type(void);
|
|||
const char* cryptfs_get_password(void);
|
||||
void cryptfs_clear_password(void);
|
||||
int cryptfs_isConvertibleToFBE(void);
|
||||
|
||||
size_t cryptfs_get_keysize();
|
||||
const android::vold::KeyGeneration cryptfs_get_keygen();
|
||||
|
||||
#endif /* ANDROID_VOLD_CRYPTFS_H */
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "Disk.h"
|
||||
#include "FsCrypt.h"
|
||||
#include "KeyUtil.h"
|
||||
#include "PrivateVolume.h"
|
||||
#include "PublicVolume.h"
|
||||
#include "Utils.h"
|
||||
|
@ -505,11 +506,12 @@ status_t Disk::partitionMixed(int8_t ratio) {
|
|||
return -EIO;
|
||||
}
|
||||
|
||||
std::string keyRaw;
|
||||
if (ReadRandomBytes(cryptfs_get_keysize(), keyRaw) != OK) {
|
||||
KeyBuffer key;
|
||||
if (!generateStorageKey(cryptfs_get_keygen(), &key)) {
|
||||
LOG(ERROR) << "Failed to generate key";
|
||||
return -EIO;
|
||||
}
|
||||
std::string keyRaw(key.begin(), key.end());
|
||||
|
||||
std::string partGuid;
|
||||
StrToHex(partGuidRaw, partGuid);
|
||||
|
|
Loading…
Reference in a new issue