Generalize CryptoType infrastructure
More consistency between MetadataCrypt and cryptfs, and steps towards supporting Adiantum properly in MetadataCrypt. Test: create private volume on Cuttlefish Bug: 147814592 Change-Id: Ic3993c1fde11b4f5a9e6cc8ee588a7d92241c6ab
This commit is contained in:
parent
a661fb659b
commit
220567c33a
7 changed files with 231 additions and 146 deletions
|
@ -111,6 +111,7 @@ cc_library_static {
|
||||||
"Benchmark.cpp",
|
"Benchmark.cpp",
|
||||||
"CheckEncryption.cpp",
|
"CheckEncryption.cpp",
|
||||||
"Checkpoint.cpp",
|
"Checkpoint.cpp",
|
||||||
|
"CryptoType.cpp",
|
||||||
"Devmapper.cpp",
|
"Devmapper.cpp",
|
||||||
"EncryptInplace.cpp",
|
"EncryptInplace.cpp",
|
||||||
"FileDeviceUtils.cpp",
|
"FileDeviceUtils.cpp",
|
||||||
|
@ -141,8 +142,8 @@ cc_library_static {
|
||||||
"model/ObbVolume.cpp",
|
"model/ObbVolume.cpp",
|
||||||
"model/PrivateVolume.cpp",
|
"model/PrivateVolume.cpp",
|
||||||
"model/PublicVolume.cpp",
|
"model/PublicVolume.cpp",
|
||||||
"model/VolumeBase.cpp",
|
|
||||||
"model/StubVolume.cpp",
|
"model/StubVolume.cpp",
|
||||||
|
"model/VolumeBase.cpp",
|
||||||
],
|
],
|
||||||
product_variables: {
|
product_variables: {
|
||||||
arc: {
|
arc: {
|
||||||
|
|
43
CryptoType.cpp
Normal file
43
CryptoType.cpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "CryptoType.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <cutils/properties.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
|
const CryptoType& lookup_crypto_algorithm(const CryptoType table[], int table_len,
|
||||||
|
const CryptoType& default_alg, const char* property) {
|
||||||
|
char paramstr[PROPERTY_VALUE_MAX];
|
||||||
|
|
||||||
|
property_get(property, paramstr, default_alg.get_config_name());
|
||||||
|
for (int i = 0; i < table_len; i++) {
|
||||||
|
if (strcmp(paramstr, table[i].get_config_name()) == 0) {
|
||||||
|
return table[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
LOG(ERROR) << "Invalid name (" << paramstr << ") for " << property << ". Defaulting to "
|
||||||
|
<< default_alg.get_config_name() << ".";
|
||||||
|
return default_alg;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
103
CryptoType.h
Normal file
103
CryptoType.h
Normal file
|
@ -0,0 +1,103 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2020 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
|
// Struct representing an encryption algorithm supported by vold.
|
||||||
|
// "config_name" represents the name we give the algorithm in
|
||||||
|
// read-only properties and fstab files
|
||||||
|
// "kernel_name" is the name we present to the Linux kernel
|
||||||
|
// "keysize" is the size of the key in bytes.
|
||||||
|
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(size_t size) const {
|
||||||
|
return CryptoType(this->config_name, this->kernel_name, size);
|
||||||
|
}
|
||||||
|
constexpr CryptoType set_config_name(const char* property) const {
|
||||||
|
return CryptoType(property, this->kernel_name, this->keysize);
|
||||||
|
}
|
||||||
|
constexpr CryptoType set_kernel_name(const char* crypto) const {
|
||||||
|
return CryptoType(this->config_name, crypto, this->keysize);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const char* get_config_name() const { return config_name; }
|
||||||
|
constexpr const char* get_kernel_name() const { return kernel_name; }
|
||||||
|
constexpr size_t get_keysize() const { return keysize; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
const char* config_name;
|
||||||
|
const char* kernel_name;
|
||||||
|
size_t keysize;
|
||||||
|
|
||||||
|
constexpr CryptoType(const char* property, const char* crypto, size_t ksize)
|
||||||
|
: config_name(property), kernel_name(crypto), keysize(ksize) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Use the named android property to look up a type from the table
|
||||||
|
// If the property is not set or matches no table entry, return the default.
|
||||||
|
const CryptoType& lookup_crypto_algorithm(const CryptoType table[], int table_len,
|
||||||
|
const CryptoType& default_alg, const char* property);
|
||||||
|
|
||||||
|
// Some useful types
|
||||||
|
|
||||||
|
constexpr CryptoType invalid_crypto_type = CryptoType();
|
||||||
|
|
||||||
|
constexpr CryptoType aes_256_xts = CryptoType()
|
||||||
|
.set_config_name("aes-256-xts")
|
||||||
|
.set_kernel_name("aes-xts-plain64")
|
||||||
|
.set_keysize(64);
|
||||||
|
|
||||||
|
constexpr CryptoType adiantum = CryptoType()
|
||||||
|
.set_config_name("adiantum")
|
||||||
|
.set_kernel_name("xchacha12,aes-adiantum-plain64")
|
||||||
|
.set_keysize(32);
|
||||||
|
|
||||||
|
// Support compile-time validation of a crypto type table
|
||||||
|
|
||||||
|
template <typename T, size_t N>
|
||||||
|
constexpr size_t array_length(T (&)[N]) {
|
||||||
|
return N;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool isValidCryptoType(size_t max_keylen, const CryptoType& crypto_type) {
|
||||||
|
return ((crypto_type.get_config_name() != nullptr) &&
|
||||||
|
(crypto_type.get_kernel_name() != nullptr) &&
|
||||||
|
(crypto_type.get_keysize() <= max_keylen));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirms that all supported_crypto_types have a small enough keysize and
|
||||||
|
// had both set_config_name() and set_kernel_name() called.
|
||||||
|
// 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 max_keylen, const CryptoType types[],
|
||||||
|
size_t len) {
|
||||||
|
return len == 0 || (isValidCryptoType(max_keylen, types[len - 1]) &&
|
||||||
|
validateSupportedCryptoTypes(max_keylen, types, len - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
|
@ -36,6 +36,7 @@
|
||||||
#include <libdm/dm.h>
|
#include <libdm/dm.h>
|
||||||
|
|
||||||
#include "Checkpoint.h"
|
#include "Checkpoint.h"
|
||||||
|
#include "CryptoType.h"
|
||||||
#include "EncryptInplace.h"
|
#include "EncryptInplace.h"
|
||||||
#include "KeyStorage.h"
|
#include "KeyStorage.h"
|
||||||
#include "KeyUtil.h"
|
#include "KeyUtil.h"
|
||||||
|
@ -45,6 +46,9 @@
|
||||||
|
|
||||||
#define TABLE_LOAD_RETRIES 10
|
#define TABLE_LOAD_RETRIES 10
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
using android::fs_mgr::FstabEntry;
|
using android::fs_mgr::FstabEntry;
|
||||||
using android::fs_mgr::GetEntryForMountPoint;
|
using android::fs_mgr::GetEntryForMountPoint;
|
||||||
using android::vold::KeyBuffer;
|
using android::vold::KeyBuffer;
|
||||||
|
@ -55,6 +59,21 @@ static const std::string kDmNameUserdata = "userdata";
|
||||||
static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
|
static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
|
||||||
static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
|
static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
|
||||||
|
|
||||||
|
constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum};
|
||||||
|
|
||||||
|
static_assert(validateSupportedCryptoTypes(64, supported_crypto_types,
|
||||||
|
array_length(supported_crypto_types)),
|
||||||
|
"We have a CryptoType which was incompletely constructed.");
|
||||||
|
|
||||||
|
constexpr CryptoType legacy_aes_256_xts =
|
||||||
|
CryptoType().set_config_name("aes-256-xts").set_kernel_name("AES-256-XTS").set_keysize(64);
|
||||||
|
|
||||||
|
constexpr CryptoType legacy_crypto_types[] = {legacy_aes_256_xts};
|
||||||
|
|
||||||
|
static_assert(validateSupportedCryptoTypes(64, legacy_crypto_types,
|
||||||
|
array_length(legacy_crypto_types)),
|
||||||
|
"We have a CryptoType which was incompletely constructed.");
|
||||||
|
|
||||||
static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
|
static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
|
||||||
// We're about to mount data not verified by verified boot. Tell Keymaster that early boot has
|
// We're about to mount data not verified by verified boot. Tell Keymaster that early boot has
|
||||||
// ended.
|
// ended.
|
||||||
|
@ -85,9 +104,6 @@ static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace android {
|
|
||||||
namespace vold {
|
|
||||||
|
|
||||||
// Note: It is possible to orphan a key if it is removed before deleting
|
// Note: It is possible to orphan a key if it is removed before deleting
|
||||||
// Update this once keymaster APIs change, and we have a proper commit.
|
// Update this once keymaster APIs change, and we have a proper commit.
|
||||||
static void commit_key(const std::string& dir) {
|
static void commit_key(const std::string& dir) {
|
||||||
|
@ -165,9 +181,6 @@ static bool read_key(const FstabEntry& data_rec, bool create_if_absent, KeyBuffe
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace vold
|
|
||||||
} // namespace android
|
|
||||||
|
|
||||||
static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
|
static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_sec) {
|
||||||
if (android::vold::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
|
if (android::vold::GetBlockDev512Sectors(real_blkdev, nr_sec) != android::OK) {
|
||||||
PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
|
PLOG(ERROR) << "Unable to measure size of " << real_blkdev;
|
||||||
|
@ -176,21 +189,26 @@ static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_s
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string lookup_cipher(const std::string& cipher_name, bool is_legacy) {
|
static const CryptoType& lookup_cipher_in_table(const CryptoType table[], int table_len,
|
||||||
|
const std::string& cipher_name) {
|
||||||
|
if (cipher_name.empty()) return table[0];
|
||||||
|
for (int i = 0; i < table_len; i++) {
|
||||||
|
if (cipher_name == table[i].get_config_name()) {
|
||||||
|
return table[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return invalid_crypto_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const CryptoType& lookup_cipher(const std::string& cipher_name, bool is_legacy) {
|
||||||
if (is_legacy) {
|
if (is_legacy) {
|
||||||
if (cipher_name.empty() || cipher_name == "aes-256-xts") {
|
return lookup_cipher_in_table(legacy_crypto_types, array_length(legacy_crypto_types),
|
||||||
return "AES-256-XTS";
|
cipher_name);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (cipher_name.empty() || cipher_name == "aes-256-xts") {
|
return lookup_cipher_in_table(supported_crypto_types, array_length(supported_crypto_types),
|
||||||
return "aes-xts-plain64";
|
cipher_name);
|
||||||
} else if (cipher_name == "adiantum") {
|
|
||||||
return "xchacha12,aes-adiantum-plain64";
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LOG(ERROR) << "No metadata cipher named " << cipher_name << " found, is_legacy=" << is_legacy;
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool create_crypto_blk_dev(const std::string& dm_name, const FstabEntry* data_rec,
|
static bool create_crypto_blk_dev(const std::string& dm_name, const FstabEntry* data_rec,
|
||||||
const KeyBuffer& key, std::string* crypto_blkdev) {
|
const KeyBuffer& key, std::string* crypto_blkdev) {
|
||||||
|
@ -201,7 +219,11 @@ static bool create_crypto_blk_dev(const std::string& dm_name, const FstabEntry*
|
||||||
if (!DmTargetDefaultKey::IsLegacy(&is_legacy)) return false;
|
if (!DmTargetDefaultKey::IsLegacy(&is_legacy)) return false;
|
||||||
|
|
||||||
auto cipher = lookup_cipher(data_rec->metadata_cipher, is_legacy);
|
auto cipher = lookup_cipher(data_rec->metadata_cipher, is_legacy);
|
||||||
if (cipher.empty()) return false;
|
if (cipher.get_kernel_name() == nullptr) {
|
||||||
|
LOG(ERROR) << "No metadata cipher named " << data_rec->metadata_cipher
|
||||||
|
<< " found, is_legacy=" << is_legacy;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
KeyBuffer hex_key_buffer;
|
KeyBuffer hex_key_buffer;
|
||||||
if (android::vold::StrToHex(key, hex_key_buffer) != android::OK) {
|
if (android::vold::StrToHex(key, hex_key_buffer) != android::OK) {
|
||||||
|
@ -218,8 +240,8 @@ static bool create_crypto_blk_dev(const std::string& dm_name, const FstabEntry*
|
||||||
}
|
}
|
||||||
|
|
||||||
DmTable table;
|
DmTable table;
|
||||||
table.Emplace<DmTargetDefaultKey>(0, nr_sec, cipher, hex_key, data_rec->blk_device, 0,
|
table.Emplace<DmTargetDefaultKey>(0, nr_sec, cipher.get_kernel_name(), hex_key,
|
||||||
is_legacy, set_dun);
|
data_rec->blk_device, 0, is_legacy, set_dun);
|
||||||
|
|
||||||
auto& dm = DeviceMapper::Instance();
|
auto& dm = DeviceMapper::Instance();
|
||||||
for (int i = 0;; i++) {
|
for (int i = 0;; i++) {
|
||||||
|
@ -289,3 +311,6 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::
|
||||||
mount_via_fs_mgr(data_rec->mount_point.c_str(), crypto_blkdev.c_str());
|
mount_via_fs_mgr(data_rec->mount_point.c_str(), crypto_blkdev.c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
||||||
|
|
|
@ -19,7 +19,12 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
|
bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
|
||||||
const std::string& mount_point, bool needs_encrypt);
|
const std::string& mount_point, bool needs_encrypt);
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
||||||
#endif
|
#endif
|
||||||
|
|
155
cryptfs.cpp
155
cryptfs.cpp
|
@ -19,6 +19,7 @@
|
||||||
#include "cryptfs.h"
|
#include "cryptfs.h"
|
||||||
|
|
||||||
#include "Checkpoint.h"
|
#include "Checkpoint.h"
|
||||||
|
#include "CryptoType.h"
|
||||||
#include "EncryptInplace.h"
|
#include "EncryptInplace.h"
|
||||||
#include "FsCrypt.h"
|
#include "FsCrypt.h"
|
||||||
#include "Keymaster.h"
|
#include "Keymaster.h"
|
||||||
|
@ -71,6 +72,7 @@ extern "C" {
|
||||||
using android::base::ParseUint;
|
using android::base::ParseUint;
|
||||||
using android::base::StringPrintf;
|
using android::base::StringPrintf;
|
||||||
using android::fs_mgr::GetEntryForMountPoint;
|
using android::fs_mgr::GetEntryForMountPoint;
|
||||||
|
using android::vold::CryptoType;
|
||||||
using android::vold::KeyBuffer;
|
using android::vold::KeyBuffer;
|
||||||
using namespace android::dm;
|
using namespace android::dm;
|
||||||
using namespace std::chrono_literals;
|
using namespace std::chrono_literals;
|
||||||
|
@ -296,6 +298,28 @@ static char* saved_mount_point;
|
||||||
static int master_key_saved = 0;
|
static int master_key_saved = 0;
|
||||||
static struct crypt_persist_data* persist_data = NULL;
|
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? */
|
/* Should we use keymaster? */
|
||||||
static int keymaster_check_compatibility() {
|
static int keymaster_check_compatibility() {
|
||||||
return keymaster_compatibility_cryptfs_scrypt();
|
return keymaster_compatibility_cryptfs_scrypt();
|
||||||
|
@ -426,118 +450,6 @@ static void cryptfs_reboot(RebootType rt) {
|
||||||
return;
|
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(size_t keysize) const {
|
|
||||||
return CryptoType(this->config_name, this->kernel_name, keysize);
|
|
||||||
}
|
|
||||||
constexpr CryptoType set_config_name(const char* config_name) const {
|
|
||||||
return CryptoType(config_name, this->kernel_name, this->keysize);
|
|
||||||
}
|
|
||||||
constexpr CryptoType set_kernel_name(const char* kernel_name) const {
|
|
||||||
return CryptoType(this->config_name, kernel_name, this->keysize);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr const char* get_config_name() const { return config_name; }
|
|
||||||
constexpr const char* get_kernel_name() const { return kernel_name; }
|
|
||||||
constexpr size_t get_keysize() const { return keysize; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
const char* config_name;
|
|
||||||
const char* kernel_name;
|
|
||||||
size_t keysize;
|
|
||||||
|
|
||||||
constexpr CryptoType(const char* config, const char* crypto, size_t ksize)
|
|
||||||
: config_name(config), kernel_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_config_name("AES-128-CBC")
|
|
||||||
.set_kernel_name("aes-cbc-essiv:sha256")
|
|
||||||
.set_keysize(16);
|
|
||||||
|
|
||||||
constexpr CryptoType supported_crypto_types[] = {
|
|
||||||
default_crypto_type,
|
|
||||||
CryptoType()
|
|
||||||
.set_config_name("adiantum")
|
|
||||||
.set_kernel_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_config_name() and set_kernel_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_config_name() != nullptr) &&
|
|
||||||
(crypto_type.get_kernel_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_config_name());
|
|
||||||
for (auto const& ctype : supported_crypto_types) {
|
|
||||||
if (strcmp(paramstr, ctype.get_config_name()) == 0) {
|
|
||||||
return ctype;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ALOGE("Invalid name (%s) for %s. Defaulting to %s\n", paramstr, CRYPT_ALGO_PROP,
|
|
||||||
default_crypto_type.get_config_name());
|
|
||||||
return default_crypto_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the default device scrypt parameters for key derivation time tuning.
|
* Gets the default device scrypt parameters for key derivation time tuning.
|
||||||
* The parameters should lead to about one second derivation time for the
|
* The parameters should lead to about one second derivation time for the
|
||||||
|
@ -561,10 +473,6 @@ size_t cryptfs_get_keysize() {
|
||||||
return get_crypto_type().get_keysize();
|
return get_crypto_type().get_keysize();
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* cryptfs_get_kernel_name() {
|
|
||||||
return get_crypto_type().get_kernel_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
||||||
|
@ -1913,9 +1821,10 @@ errout:
|
||||||
*/
|
*/
|
||||||
int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
|
int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const KeyBuffer& key,
|
||||||
std::string* out_crypto_blkdev) {
|
std::string* out_crypto_blkdev) {
|
||||||
if (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(),
|
SLOGE("Raw keysize %zu does not match crypt keysize %zu", key.size(),
|
||||||
cryptfs_get_keysize());
|
crypto_type.get_keysize());
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
uint64_t nr_sec = 0;
|
uint64_t nr_sec = 0;
|
||||||
|
@ -1927,8 +1836,8 @@ int cryptfs_setup_ext_volume(const char* label, const char* real_blkdev, const K
|
||||||
struct crypt_mnt_ftr ext_crypt_ftr;
|
struct crypt_mnt_ftr ext_crypt_ftr;
|
||||||
memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
|
memset(&ext_crypt_ftr, 0, sizeof(ext_crypt_ftr));
|
||||||
ext_crypt_ftr.fs_size = nr_sec;
|
ext_crypt_ftr.fs_size = nr_sec;
|
||||||
ext_crypt_ftr.keysize = cryptfs_get_keysize();
|
ext_crypt_ftr.keysize = crypto_type.get_keysize();
|
||||||
strlcpy((char*)ext_crypt_ftr.crypto_type_name, cryptfs_get_kernel_name(),
|
strlcpy((char*)ext_crypt_ftr.crypto_type_name, crypto_type.get_kernel_name(),
|
||||||
MAX_CRYPTO_TYPE_NAME_LEN);
|
MAX_CRYPTO_TYPE_NAME_LEN);
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
if (fscrypt_is_native() &&
|
if (fscrypt_is_native() &&
|
||||||
|
@ -2062,7 +1971,7 @@ int cryptfs_verify_passwd(const char* passwd) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize a crypt_mnt_ftr structure. The keysize is
|
/* 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
|
* Presumably, at a minimum, the caller will update the
|
||||||
* filesystem size and crypto_type_name after calling this function.
|
* filesystem size and crypto_type_name after calling this function.
|
||||||
*/
|
*/
|
||||||
|
@ -2074,7 +1983,7 @@ static int cryptfs_init_crypt_mnt_ftr(struct crypt_mnt_ftr* ftr) {
|
||||||
ftr->major_version = CURRENT_MAJOR_VERSION;
|
ftr->major_version = CURRENT_MAJOR_VERSION;
|
||||||
ftr->minor_version = CURRENT_MINOR_VERSION;
|
ftr->minor_version = CURRENT_MINOR_VERSION;
|
||||||
ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
|
ftr->ftr_size = sizeof(struct crypt_mnt_ftr);
|
||||||
ftr->keysize = cryptfs_get_keysize();
|
ftr->keysize = get_crypto_type().get_keysize();
|
||||||
|
|
||||||
switch (keymaster_check_compatibility()) {
|
switch (keymaster_check_compatibility()) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -2318,7 +2227,7 @@ int cryptfs_enable_internal(int crypt_type, const char* passwd, int no_ui) {
|
||||||
crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
|
crypt_ftr.flags |= CRYPT_INCONSISTENT_STATE;
|
||||||
}
|
}
|
||||||
crypt_ftr.crypt_type = crypt_type;
|
crypt_ftr.crypt_type = crypt_type;
|
||||||
strlcpy((char*)crypt_ftr.crypto_type_name, cryptfs_get_kernel_name(),
|
strlcpy((char*)crypt_ftr.crypto_type_name, get_crypto_type().get_kernel_name(),
|
||||||
MAX_CRYPTO_TYPE_NAME_LEN);
|
MAX_CRYPTO_TYPE_NAME_LEN);
|
||||||
|
|
||||||
/* Make an encrypted master key */
|
/* Make an encrypted master key */
|
||||||
|
|
|
@ -75,6 +75,5 @@ void cryptfs_clear_password(void);
|
||||||
int cryptfs_isConvertibleToFBE(void);
|
int cryptfs_isConvertibleToFBE(void);
|
||||||
|
|
||||||
size_t cryptfs_get_keysize();
|
size_t cryptfs_get_keysize();
|
||||||
const char* cryptfs_get_crypto_name();
|
|
||||||
|
|
||||||
#endif /* ANDROID_VOLD_CRYPTFS_H */
|
#endif /* ANDROID_VOLD_CRYPTFS_H */
|
||||||
|
|
Loading…
Reference in a new issue