diff options
author | Paul Crowley <paulcrowley@google.com> | 2020-02-14 18:57:33 +0000 |
---|---|---|
committer | Paul Crowley <paulcrowley@google.com> | 2020-02-14 18:57:33 +0000 |
commit | 85d1c77ff63f8ef583753b53cea296deb4ba4ad0 (patch) | |
tree | 2f5de412fb664d3c7fae468427fb8f75a1c2e3f4 /cryptfs.cpp | |
parent | 8b3181092275f5850d5b74ff4ef8af74662a244b (diff) | |
parent | 54d05de7983b49dfb98a8c545be5d14bcbde70e0 (diff) | |
download | vold-85d1c77ff63f8ef583753b53cea296deb4ba4ad0.tar.gz |
Merge changes Ic3993c1f,I06645bb4 am: ac34e9aa3e am: b62afed286 am: 54d05de798
Change-Id: Ib122e011bb7be162b76b94a31885863d2aff6d1e
Diffstat (limited to 'cryptfs.cpp')
-rw-r--r-- | cryptfs.cpp | 159 |
1 files changed, 34 insertions, 125 deletions
diff --git a/cryptfs.cpp b/cryptfs.cpp index def306da..530d78e2 100644 --- a/cryptfs.cpp +++ b/cryptfs.cpp @@ -19,6 +19,7 @@ #include "cryptfs.h" #include "Checkpoint.h" +#include "CryptoType.h" #include "EncryptInplace.h" #include "FsCrypt.h" #include "Keymaster.h" @@ -74,6 +75,7 @@ extern "C" { using android::base::ParseUint; using android::base::StringPrintf; using android::fs_mgr::GetEntryForMountPoint; +using android::vold::CryptoType; using android::vold::KeyBuffer; using namespace android::dm; using namespace std::chrono_literals; @@ -299,6 +301,28 @@ static char* saved_mount_point; static int master_key_saved = 0; static struct crypt_persist_data* persist_data = NULL; +constexpr CryptoType aes_128_cbc = CryptoType() + .set_config_name("AES-128-CBC") + .set_kernel_name("aes-cbc-essiv:sha256") + .set_keysize(16); + +constexpr CryptoType supported_crypto_types[] = {aes_128_cbc, android::vold::adiantum}; + +static_assert(validateSupportedCryptoTypes(MAX_KEY_LEN, supported_crypto_types, + array_length(supported_crypto_types)), + "We have a CryptoType with keysize > MAX_KEY_LEN or which was " + "incompletely constructed."); + +static const CryptoType& get_crypto_type() { + // We only want to parse this read-only property once. But we need to wait + // until the system is initialized before we can read it. So we use a static + // scoped within this function to get it only once. + static CryptoType crypto_type = + lookup_crypto_algorithm(supported_crypto_types, array_length(supported_crypto_types), + aes_128_cbc, "ro.crypto.fde_algorithm"); + return crypto_type; +} + /* Should we use keymaster? */ static int keymaster_check_compatibility() { return keymaster_compatibility_cryptfs_scrypt(); @@ -429,118 +453,6 @@ static void cryptfs_reboot(RebootType rt) { return; } -namespace { - -struct CryptoType; - -// Use to get the CryptoType in use on this device. -const CryptoType& get_crypto_type(); - -struct CryptoType { - // We should only be constructing CryptoTypes as part of - // supported_crypto_types[]. We do it via this pseudo-builder pattern, - // which isn't pure or fully protected as a concession to being able to - // do it all at compile time. Add new CryptoTypes in - // supported_crypto_types[] below. - constexpr CryptoType() : CryptoType(nullptr, nullptr, 0xFFFFFFFF) {} - constexpr CryptoType set_keysize(uint32_t size) const { - return CryptoType(this->property_name, this->crypto_name, size); - } - constexpr CryptoType set_property_name(const char* property) const { - return CryptoType(property, this->crypto_name, this->keysize); - } - constexpr CryptoType set_crypto_name(const char* crypto) const { - return CryptoType(this->property_name, crypto, this->keysize); - } - - constexpr const char* get_property_name() const { return property_name; } - constexpr const char* get_crypto_name() const { return crypto_name; } - constexpr uint32_t get_keysize() const { return keysize; } - - private: - const char* property_name; - const char* crypto_name; - uint32_t keysize; - - constexpr CryptoType(const char* property, const char* crypto, uint32_t ksize) - : property_name(property), crypto_name(crypto), keysize(ksize) {} - friend const CryptoType& get_crypto_type(); - static const CryptoType& get_device_crypto_algorithm(); -}; - -// We only want to parse this read-only property once. But we need to wait -// until the system is initialized before we can read it. So we use a static -// scoped within this function to get it only once. -const CryptoType& get_crypto_type() { - static CryptoType crypto_type = CryptoType::get_device_crypto_algorithm(); - return crypto_type; -} - -constexpr CryptoType default_crypto_type = CryptoType() - .set_property_name("AES-128-CBC") - .set_crypto_name("aes-cbc-essiv:sha256") - .set_keysize(16); - -constexpr CryptoType supported_crypto_types[] = { - default_crypto_type, - CryptoType() - .set_property_name("adiantum") - .set_crypto_name("xchacha12,aes-adiantum-plain64") - .set_keysize(32), - // Add new CryptoTypes here. Order is not important. -}; - -// ---------- START COMPILE-TIME SANITY CHECK BLOCK ------------------------- -// We confirm all supported_crypto_types have a small enough keysize and -// had both set_property_name() and set_crypto_name() called. - -template <typename T, size_t N> -constexpr size_t array_length(T (&)[N]) { - return N; -} - -constexpr bool indexOutOfBoundsForCryptoTypes(size_t index) { - return (index >= array_length(supported_crypto_types)); -} - -constexpr bool isValidCryptoType(const CryptoType& crypto_type) { - return ((crypto_type.get_property_name() != nullptr) && - (crypto_type.get_crypto_name() != nullptr) && - (crypto_type.get_keysize() <= MAX_KEY_LEN)); -} - -// Note in C++11 that constexpr functions can only have a single line. -// So our code is a bit convoluted (using recursion instead of a loop), -// but it's asserting at compile time that all of our key lengths are valid. -constexpr bool validateSupportedCryptoTypes(size_t index) { - return indexOutOfBoundsForCryptoTypes(index) || - (isValidCryptoType(supported_crypto_types[index]) && - validateSupportedCryptoTypes(index + 1)); -} - -static_assert(validateSupportedCryptoTypes(0), - "We have a CryptoType with keysize > MAX_KEY_LEN or which was " - "incompletely constructed."); -// ---------- END COMPILE-TIME SANITY CHECK BLOCK ------------------------- - -// Don't call this directly, use get_crypto_type(), which caches this result. -const CryptoType& CryptoType::get_device_crypto_algorithm() { - constexpr char CRYPT_ALGO_PROP[] = "ro.crypto.fde_algorithm"; - char paramstr[PROPERTY_VALUE_MAX]; - - property_get(CRYPT_ALGO_PROP, paramstr, default_crypto_type.get_property_name()); - for (auto const& ctype : supported_crypto_types) { - if (strcmp(paramstr, ctype.get_property_name()) == 0) { - return ctype; - } - } - ALOGE("Invalid name (%s) for %s. Defaulting to %s\n", paramstr, CRYPT_ALGO_PROP, - default_crypto_type.get_property_name()); - return default_crypto_type; -} - -} // namespace - /** * Gets the default device scrypt parameters for key derivation time tuning. * The parameters should lead to about one second derivation time for the @@ -560,14 +472,10 @@ static void get_device_scrypt_params(struct crypt_mnt_ftr* ftr) { ftr->p_factor = pf; } -uint32_t cryptfs_get_keysize() { +size_t cryptfs_get_keysize() { return get_crypto_type().get_keysize(); } -const char* cryptfs_get_crypto_name() { - return get_crypto_type().get_crypto_name(); -} - static uint64_t get_fs_size(const char* dev) { int fd, block_size; struct ext4_super_block sb; @@ -1929,9 +1837,10 @@ errout: */ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key, std::string* out_crypto_blkdev) { - if (key.size() != cryptfs_get_keysize()) { - SLOGE("Raw keysize %zu does not match crypt keysize %" PRIu32, key.size(), - cryptfs_get_keysize()); + auto crypto_type = get_crypto_type(); + if (key.size() != crypto_type.get_keysize()) { + SLOGE("Raw keysize %zu does not match crypt keysize %zu", key.size(), + crypto_type.get_keysize()); return -1; } uint64_t nr_sec = 0; @@ -1943,8 +1852,8 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const K struct crypt_mnt_ftr ext_crypt_ftr; memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr)); ext_crypt_ftr.fs_size = nr_sec; - ext_crypt_ftr.keysize = cryptfs_get_keysize(); - strlcpy((char*)ext_crypt_ftr.crypto_type_name, cryptfs_get_crypto_name(), + ext_crypt_ftr.keysize = crypto_type.get_keysize(); + strlcpy((char*)ext_crypt_ftr.crypto_type_name, crypto_type.get_kernel_name(), MAX_CRYPTO_TYPE_NAME_LEN); uint32_t flags = 0; if (fscrypt_is_native() && @@ -2078,7 +1987,7 @@ int cryptfs_verify_passwd(const char* passwd) { } /* Initialize a crypt_mnt_ftr structure. The keysize is - * defaulted to cryptfs_get_keysize() bytes, and the filesystem size to 0. + * defaulted to get_crypto_type().get_keysize() bytes, and the filesystem size to 0. * Presumably, at a minimum, the caller will update the * filesystem size and crypto_type_name after calling this function. */ @@ -2090,7 +1999,7 @@ static int cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr* ftr) { ftr->major_version = CURRENT_MAJOR_VERSION; ftr->minor_version = CURRENT_MINOR_VERSION; ftr->ftr_size = sizeof(struct crypt_mnt_ftr); - ftr->keysize = cryptfs_get_keysize(); + ftr->keysize = get_crypto_type().get_keysize(); switch (keymaster_check_compatibility()) { case 1: @@ -2334,7 +2243,7 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) { crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE; } crypt_ftr.crypt_type = crypt_type; - strlcpy((char*)crypt_ftr.crypto_type_name, cryptfs_get_crypto_name(), + strlcpy((char*)crypt_ftr.crypto_type_name, get_crypto_type().get_kernel_name(), MAX_CRYPTO_TYPE_NAME_LEN); /* Make an encrypted master key */ |