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:
Paul Crowley 2020-02-12 11:04:05 -08:00
parent 7566e467ab
commit 4eac264727
7 changed files with 82 additions and 55 deletions

View file

@ -64,6 +64,9 @@ using android::fs_mgr::GetEntryForMountPoint;
using android::vold::BuildDataPath; using android::vold::BuildDataPath;
using android::vold::kEmptyAuthentication; using android::vold::kEmptyAuthentication;
using android::vold::KeyBuffer; using android::vold::KeyBuffer;
using android::vold::makeGen;
using android::vold::retrieveKey;
using android::vold::retrieveOrGenerateKey;
using android::vold::writeStringToFile; using android::vold::writeStringToFile;
using namespace android::fscrypt; 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); auto const paths = get_ce_key_paths(directory_path);
for (auto const ce_key_path : paths) { for (auto const ce_key_path : paths) {
LOG(DEBUG) << "Trying user CE key " << ce_key_path; 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"; LOG(DEBUG) << "Successfully retrieved key";
fixate_user_ce_key(directory_path, ce_key_path, paths); fixate_user_ce_key(directory_path, ce_key_path, paths);
return true; return true;
@ -274,8 +277,8 @@ static bool create_and_install_user_keys(userid_t user_id, bool create_ephemeral
EncryptionOptions options; EncryptionOptions options;
if (!get_data_file_encryption_options(&options)) return false; if (!get_data_file_encryption_options(&options)) return false;
KeyBuffer de_key, ce_key; KeyBuffer de_key, ce_key;
if (!generateStorageKey(options, &de_key)) return false; if (!generateStorageKey(makeGen(options), &de_key)) return false;
if (!generateStorageKey(options, &ce_key)) return false; if (!generateStorageKey(makeGen(options), &ce_key)) return false;
if (create_ephemeral) { if (create_ephemeral) {
// If the key should be created as ephemeral, don't store it. // If the key should be created as ephemeral, don't store it.
s_ephemeral_users.insert(user_id); s_ephemeral_users.insert(user_id);
@ -349,7 +352,7 @@ static bool load_all_de_keys() {
if (s_de_policies.count(user_id) == 0) { if (s_de_policies.count(user_id) == 0) {
auto key_path = de_dir + "/" + entry->d_name; auto key_path = de_dir + "/" + entry->d_name;
KeyBuffer de_key; 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; EncryptionPolicy de_policy;
if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false; if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
s_de_policies[user_id] = de_policy; 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; if (!get_data_file_encryption_options(&options)) return false;
KeyBuffer device_key; KeyBuffer device_key;
if (!android::vold::retrieveKey(true, kEmptyAuthentication, device_key_path, device_key_temp, if (!retrieveOrGenerateKey(device_key_path, device_key_temp, kEmptyAuthentication,
options, &device_key)) makeGen(options), &device_key))
return false; return false;
EncryptionPolicy device_policy; EncryptionPolicy device_policy;
@ -392,7 +395,7 @@ bool fscrypt_initialize_systemwide_keys() {
LOG(INFO) << "Wrote system DE key reference to:" << ref_filename; LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
KeyBuffer per_boot_key; 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; EncryptionPolicy per_boot_policy;
if (!install_storage_key(DATA_MNT_POINT, options, per_boot_key, &per_boot_policy)) return false; 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; 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; EncryptionOptions options;
if (!get_volume_file_encryption_options(&options)) return false; if (!get_volume_file_encryption_options(&options)) return false;
KeyBuffer key; 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; return false;
if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false; if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false;
return true; 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); auto const directory_path = get_ce_key_directory_path(user_id);
KeyBuffer ce_key; KeyBuffer ce_key;
std::string ce_key_current_path = get_ce_key_current_path(directory_path); 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"; LOG(DEBUG) << "Successfully retrieved key";
// TODO(147732812): Remove this once Locksettingservice is fixed. // TODO(147732812): Remove this once Locksettingservice is fixed.
// Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is // Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is
// changed from swipe to none or vice-versa // 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"; LOG(DEBUG) << "Successfully retrieved key with empty auth";
} else { } else {
LOG(ERROR) << "Failed to retrieve key for user " << user_id; LOG(ERROR) << "Failed to retrieve key for user " << user_id;

View file

@ -36,8 +36,20 @@
namespace android { namespace android {
namespace vold { namespace vold {
bool randomKey(KeyBuffer* key) { const KeyGeneration makeGen(const EncryptionOptions& options) {
*key = KeyBuffer(FSCRYPT_MAX_KEY_SIZE); 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) { if (ReadRandomBytes(key->size(), key->data()) != 0) {
// TODO status_t plays badly with PLOG, fix it. // TODO status_t plays badly with PLOG, fix it.
LOG(ERROR) << "Random read failed"; LOG(ERROR) << "Random read failed";
@ -46,11 +58,17 @@ bool randomKey(KeyBuffer* key) {
return true; return true;
} }
bool generateStorageKey(const EncryptionOptions& options, KeyBuffer* key) { bool generateStorageKey(const KeyGeneration& gen, KeyBuffer* key) {
if (options.use_hw_wrapped_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); 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 // 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; return true;
} }
bool retrieveKey(bool create_if_absent, const KeyAuthentication& key_authentication, bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
const std::string& key_path, const std::string& tmp_path, const KeyAuthentication& key_authentication, const KeyGeneration& gen,
const EncryptionOptions& options, KeyBuffer* key, bool keepOld) { KeyBuffer* key, bool keepOld) {
if (pathExists(key_path)) { if (pathExists(key_path)) {
LOG(DEBUG) << "Key exists, using: " << key_path; LOG(DEBUG) << "Key exists, using: " << key_path;
if (!retrieveKey(key_path, key_authentication, key, keepOld)) return false; if (!retrieveKey(key_path, key_authentication, key, keepOld)) return false;
} else { } else {
if (!create_if_absent) { if (!gen.allow_gen) {
LOG(ERROR) << "No key found in " << key_path; LOG(ERROR) << "No key found in " << key_path;
return false; return false;
} }
LOG(INFO) << "Creating new key in " << key_path; 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; if (!storeKeyAtomically(key_path, tmp_path, key_authentication, *key)) return false;
} }
return true; return true;

View file

@ -17,6 +17,7 @@
#ifndef ANDROID_VOLD_KEYUTIL_H #ifndef ANDROID_VOLD_KEYUTIL_H
#define ANDROID_VOLD_KEYUTIL_H #define ANDROID_VOLD_KEYUTIL_H
#include "CryptoType.h"
#include "KeyBuffer.h" #include "KeyBuffer.h"
#include "KeyStorage.h" #include "KeyStorage.h"
@ -30,9 +31,26 @@ namespace vold {
using namespace android::fscrypt; 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); 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. // In the latter case, the caller is responsible for dropping caches.
bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy); bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy);
bool retrieveKey(bool create_if_absent, const KeyAuthentication& key_authentication, bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
const std::string& key_path, const std::string& tmp_path, const KeyAuthentication& key_authentication, const KeyGeneration& gen,
const EncryptionOptions& options, KeyBuffer* key, bool keepOld = true); KeyBuffer* key, bool keepOld = true);
} // namespace vold } // namespace vold
} // namespace android } // namespace android

View file

@ -129,24 +129,8 @@ static void commit_key(const std::string& dir) {
LOG(INFO) << "Old Key deleted: " << dir; LOG(INFO) << "Old Key deleted: " << dir;
} }
static bool retrieveMetadataKey(bool create_if_absent, const std::string& key_path, static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& gen,
const std::string& tmp_path, KeyBuffer* key, bool keepOld) { KeyBuffer* key) {
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) {
if (metadata_key_dir.empty()) { if (metadata_key_dir.empty()) {
LOG(ERROR) << "Failed to get metadata_key_dir"; LOG(ERROR) << "Failed to get metadata_key_dir";
return false; return false;
@ -168,14 +152,14 @@ static bool read_key(const std::string& metadata_key_dir, bool create_if_absent,
Keymaster keymaster; Keymaster keymaster;
if (pathExists(newKeyPath)) { if (pathExists(newKeyPath)) {
if (!android::base::ReadFileToString(newKeyPath, &sKey)) 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)) else if (!keymaster.deleteKey(sKey))
LOG(ERROR) << "Old key deletion failed, continuing anyway: " << dir; LOG(ERROR) << "Incomplete key deletion failed, continuing anyway: " << dir;
else else
unlink(newKeyPath.c_str()); unlink(newKeyPath.c_str());
} }
bool needs_cp = cp_needsCheckpoint(); 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(); if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
return true; return true;
} }
@ -283,8 +267,9 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::
return false; return false;
} }
auto gen = needs_encrypt ? makeGen(cipher) : neverGen();
KeyBuffer key; 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; std::string crypto_blkdev;
if (!create_crypto_blk_dev(kDmNameUserdata, data_rec->blk_device, is_legacy, if (!create_crypto_blk_dev(kDmNameUserdata, data_rec->blk_device, is_legacy,

View file

@ -74,6 +74,7 @@ using android::base::StringPrintf;
using android::fs_mgr::GetEntryForMountPoint; using android::fs_mgr::GetEntryForMountPoint;
using android::vold::CryptoType; using android::vold::CryptoType;
using android::vold::KeyBuffer; using android::vold::KeyBuffer;
using android::vold::KeyGeneration;
using namespace android::dm; using namespace android::dm;
using namespace std::chrono_literals; using namespace std::chrono_literals;
@ -320,6 +321,10 @@ static const CryptoType& get_crypto_type() {
return crypto_type; return crypto_type;
} }
const KeyGeneration cryptfs_get_keygen() {
return makeGen(get_crypto_type());
}
/* Should we use keymaster? */ /* Should we use keymaster? */
static int keymaster_check_compatibility() { static int keymaster_check_compatibility() {
return keymaster_compatibility_cryptfs_scrypt(); return keymaster_compatibility_cryptfs_scrypt();
@ -469,10 +474,6 @@ static void get_device_scrypt_params(struct crypt_mnt_ftr* ftr) {
ftr->p_factor = pf; ftr->p_factor = pf;
} }
size_t cryptfs_get_keysize() {
return get_crypto_type().get_keysize();
}
static uint64_t get_fs_size(const char* dev) { static uint64_t get_fs_size(const char* dev) {
int fd, block_size; int fd, block_size;
struct ext4_super_block sb; struct ext4_super_block sb;

View file

@ -26,6 +26,7 @@
#include <cutils/properties.h> #include <cutils/properties.h>
#include "KeyBuffer.h" #include "KeyBuffer.h"
#include "KeyUtil.h"
#define CRYPT_FOOTER_OFFSET 0x4000 #define CRYPT_FOOTER_OFFSET 0x4000
@ -73,7 +74,6 @@ int cryptfs_get_password_type(void);
const char* cryptfs_get_password(void); const char* cryptfs_get_password(void);
void cryptfs_clear_password(void); void cryptfs_clear_password(void);
int cryptfs_isConvertibleToFBE(void); int cryptfs_isConvertibleToFBE(void);
const android::vold::KeyGeneration cryptfs_get_keygen();
size_t cryptfs_get_keysize();
#endif /* ANDROID_VOLD_CRYPTFS_H */ #endif /* ANDROID_VOLD_CRYPTFS_H */

View file

@ -16,6 +16,7 @@
#include "Disk.h" #include "Disk.h"
#include "FsCrypt.h" #include "FsCrypt.h"
#include "KeyUtil.h"
#include "PrivateVolume.h" #include "PrivateVolume.h"
#include "PublicVolume.h" #include "PublicVolume.h"
#include "Utils.h" #include "Utils.h"
@ -505,11 +506,12 @@ status_t Disk::partitionMixed(int8_t ratio) {
return -EIO; return -EIO;
} }
std::string keyRaw; KeyBuffer key;
if (ReadRandomBytes(cryptfs_get_keysize(), keyRaw) != OK) { if (!generateStorageKey(cryptfs_get_keygen(), &key)) {
LOG(ERROR) << "Failed to generate key"; LOG(ERROR) << "Failed to generate key";
return -EIO; return -EIO;
} }
std::string keyRaw(key.begin(), key.end());
std::string partGuid; std::string partGuid;
StrToHex(partGuidRaw, partGuid); StrToHex(partGuidRaw, partGuid);