On newer devices, use dm-default-key to encrypt SD cards
The dm-crypt solution requires a kernel patch that won't be present in the GKI kernel, while the new metadata encryption system in the GKI kernel solves this problem in a much cleaner way. Test: create private volume on Cuttlefish, setting property both ways. Bug: 147814592 Change-Id: Ie02bd647c38d8101af2bbc47637f65845d312cea
This commit is contained in:
parent
312b7df621
commit
886e572009
7 changed files with 172 additions and 15 deletions
|
@ -144,6 +144,7 @@ cc_library_static {
|
||||||
"model/PublicVolume.cpp",
|
"model/PublicVolume.cpp",
|
||||||
"model/StubVolume.cpp",
|
"model/StubVolume.cpp",
|
||||||
"model/VolumeBase.cpp",
|
"model/VolumeBase.cpp",
|
||||||
|
"model/VolumeEncryption.cpp",
|
||||||
],
|
],
|
||||||
product_variables: {
|
product_variables: {
|
||||||
arc: {
|
arc: {
|
||||||
|
|
|
@ -186,9 +186,11 @@ static bool get_number_of_sectors(const std::string& real_blkdev, uint64_t* nr_s
|
||||||
|
|
||||||
static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device,
|
static bool create_crypto_blk_dev(const std::string& dm_name, const std::string& blk_device,
|
||||||
const KeyBuffer& key, const CryptoOptions& options,
|
const KeyBuffer& key, const CryptoOptions& options,
|
||||||
std::string* crypto_blkdev) {
|
std::string* crypto_blkdev, uint64_t* nr_sec) {
|
||||||
uint64_t nr_sec;
|
if (!get_number_of_sectors(blk_device, nr_sec)) return false;
|
||||||
if (!get_number_of_sectors(blk_device, &nr_sec)) return false;
|
// TODO(paulcrowley): don't hardcode that DmTargetDefaultKey uses 4096-byte
|
||||||
|
// sectors
|
||||||
|
*nr_sec &= ~7;
|
||||||
|
|
||||||
KeyBuffer module_key;
|
KeyBuffer module_key;
|
||||||
if (options.use_hw_wrapped_key) {
|
if (options.use_hw_wrapped_key) {
|
||||||
|
@ -207,7 +209,7 @@ static bool create_crypto_blk_dev(const std::string& dm_name, const std::string&
|
||||||
}
|
}
|
||||||
std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size());
|
std::string hex_key(hex_key_buffer.data(), hex_key_buffer.size());
|
||||||
|
|
||||||
auto target = std::make_unique<DmTargetDefaultKey>(0, nr_sec, options.cipher.get_kernel_name(),
|
auto target = std::make_unique<DmTargetDefaultKey>(0, *nr_sec, options.cipher.get_kernel_name(),
|
||||||
hex_key, blk_device, 0);
|
hex_key, blk_device, 0);
|
||||||
if (options.is_legacy) target->SetIsLegacy();
|
if (options.is_legacy) target->SetIsLegacy();
|
||||||
if (options.set_dun) target->SetSetDun();
|
if (options.set_dun) target->SetSetDun();
|
||||||
|
@ -316,13 +318,13 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::
|
||||||
if (!read_key(data_rec->metadata_key_dir, gen, &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, key, options, &crypto_blkdev))
|
uint64_t nr_sec;
|
||||||
|
if (!create_crypto_blk_dev(kDmNameUserdata, data_rec->blk_device, key, options, &crypto_blkdev,
|
||||||
|
&nr_sec))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// FIXME handle the corrupt case
|
// FIXME handle the corrupt case
|
||||||
if (needs_encrypt) {
|
if (needs_encrypt) {
|
||||||
uint64_t nr_sec;
|
|
||||||
if (!get_number_of_sectors(data_rec->blk_device, &nr_sec)) return false;
|
|
||||||
LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
|
LOG(INFO) << "Beginning inplace encryption, nr_sec: " << nr_sec;
|
||||||
off64_t size_already_done = 0;
|
off64_t size_already_done = 0;
|
||||||
auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), blk_device.data(), nr_sec,
|
auto rc = cryptfs_enable_inplace(crypto_blkdev.data(), blk_device.data(), nr_sec,
|
||||||
|
@ -343,5 +345,27 @@ bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool get_volume_options(CryptoOptions* options) {
|
||||||
|
return parse_options(android::base::GetProperty("ro.crypto.volume.metadata.encryption", ""),
|
||||||
|
options);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool defaultkey_volume_keygen(KeyGeneration* gen) {
|
||||||
|
CryptoOptions options;
|
||||||
|
if (!get_volume_options(&options)) return false;
|
||||||
|
*gen = makeGen(options);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool defaultkey_setup_ext_volume(const std::string& label, const std::string& blk_device,
|
||||||
|
const KeyBuffer& key, std::string* out_crypto_blkdev) {
|
||||||
|
LOG(DEBUG) << "defaultkey_setup_ext_volume: " << label << " " << blk_device;
|
||||||
|
|
||||||
|
CryptoOptions options;
|
||||||
|
if (!get_volume_options(&options)) return false;
|
||||||
|
uint64_t nr_sec;
|
||||||
|
return create_crypto_blk_dev(label, blk_device, key, options, out_crypto_blkdev, &nr_sec);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace vold
|
} // namespace vold
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
@ -19,12 +19,21 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
#include "KeyBuffer.h"
|
||||||
|
#include "KeyUtil.h"
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
namespace vold {
|
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);
|
||||||
|
|
||||||
|
bool defaultkey_volume_keygen(KeyGeneration* gen);
|
||||||
|
|
||||||
|
bool defaultkey_setup_ext_volume(const std::string& label, const std::string& blk_device,
|
||||||
|
const android::vold::KeyBuffer& key,
|
||||||
|
std::string* out_crypto_blkdev);
|
||||||
|
|
||||||
} // namespace vold
|
} // namespace vold
|
||||||
} // namespace android
|
} // namespace android
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -16,11 +16,11 @@
|
||||||
|
|
||||||
#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"
|
||||||
#include "VolumeBase.h"
|
#include "VolumeBase.h"
|
||||||
|
#include "VolumeEncryption.h"
|
||||||
#include "VolumeManager.h"
|
#include "VolumeManager.h"
|
||||||
|
|
||||||
#include <android-base/file.h>
|
#include <android-base/file.h>
|
||||||
|
@ -31,8 +31,6 @@
|
||||||
#include <android-base/strings.h>
|
#include <android-base/strings.h>
|
||||||
#include <fscrypt/fscrypt.h>
|
#include <fscrypt/fscrypt.h>
|
||||||
|
|
||||||
#include "cryptfs.h"
|
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
@ -507,7 +505,7 @@ status_t Disk::partitionMixed(int8_t ratio) {
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyBuffer key;
|
KeyBuffer key;
|
||||||
if (!generateStorageKey(cryptfs_get_keygen(), &key)) {
|
if (!generate_volume_key(&key)) {
|
||||||
LOG(ERROR) << "Failed to generate key";
|
LOG(ERROR) << "Failed to generate key";
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@
|
||||||
#include "PrivateVolume.h"
|
#include "PrivateVolume.h"
|
||||||
#include "EmulatedVolume.h"
|
#include "EmulatedVolume.h"
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
|
#include "VolumeEncryption.h"
|
||||||
#include "VolumeManager.h"
|
#include "VolumeManager.h"
|
||||||
#include "cryptfs.h"
|
|
||||||
#include "fs/Ext4.h"
|
#include "fs/Ext4.h"
|
||||||
#include "fs/F2fs.h"
|
#include "fs/F2fs.h"
|
||||||
|
|
||||||
|
@ -75,9 +75,8 @@ status_t PrivateVolume::doCreate() {
|
||||||
|
|
||||||
// TODO: figure out better SELinux labels for private volumes
|
// TODO: figure out better SELinux labels for private volumes
|
||||||
|
|
||||||
int res = cryptfs_setup_ext_volume(getId().c_str(), mRawDevPath.c_str(), mKeyRaw, &mDmDevPath);
|
if (!setup_ext_volume(getId(), mRawDevPath, mKeyRaw, &mDmDevPath)) {
|
||||||
if (res != 0) {
|
LOG(ERROR) << getId() << " failed to setup metadata encryption";
|
||||||
PLOG(ERROR) << getId() << " failed to setup cryptfs";
|
|
||||||
return -EIO;
|
return -EIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
94
model/VolumeEncryption.cpp
Normal file
94
model/VolumeEncryption.cpp
Normal file
|
@ -0,0 +1,94 @@
|
||||||
|
/*
|
||||||
|
* 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 "VolumeEncryption.h"
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <android-base/logging.h>
|
||||||
|
#include <android-base/properties.h>
|
||||||
|
|
||||||
|
#include "KeyBuffer.h"
|
||||||
|
#include "KeyUtil.h"
|
||||||
|
#include "MetadataCrypt.h"
|
||||||
|
#include "cryptfs.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
|
enum class VolumeMethod { kFailed, kCrypt, kDefaultKey };
|
||||||
|
|
||||||
|
static VolumeMethod lookup_volume_method() {
|
||||||
|
constexpr uint64_t pre_gki_level = 29;
|
||||||
|
auto first_api_level =
|
||||||
|
android::base::GetUintProperty<uint64_t>("ro.product.first_api_level", 0);
|
||||||
|
auto method = android::base::GetProperty("ro.crypto.volume.metadata.method", "default");
|
||||||
|
if (method == "default") {
|
||||||
|
return first_api_level > pre_gki_level ? VolumeMethod::kDefaultKey : VolumeMethod::kCrypt;
|
||||||
|
} else if (method == "dm-default-key") {
|
||||||
|
return VolumeMethod::kDefaultKey;
|
||||||
|
} else if (method == "dm-crypt") {
|
||||||
|
if (first_api_level > pre_gki_level) {
|
||||||
|
LOG(ERROR) << "volume encryption method dm-crypt cannot be used, "
|
||||||
|
"ro.product.first_api_level = "
|
||||||
|
<< first_api_level;
|
||||||
|
return VolumeMethod::kFailed;
|
||||||
|
}
|
||||||
|
return VolumeMethod::kCrypt;
|
||||||
|
} else {
|
||||||
|
LOG(ERROR) << "Unknown volume encryption method: " << method;
|
||||||
|
return VolumeMethod::kFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static VolumeMethod volume_method() {
|
||||||
|
static VolumeMethod method = lookup_volume_method();
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool generate_volume_key(android::vold::KeyBuffer* key) {
|
||||||
|
KeyGeneration gen;
|
||||||
|
switch (volume_method()) {
|
||||||
|
case VolumeMethod::kFailed:
|
||||||
|
LOG(ERROR) << "Volume encryption setup failed";
|
||||||
|
return false;
|
||||||
|
case VolumeMethod::kCrypt:
|
||||||
|
gen = cryptfs_get_keygen();
|
||||||
|
break;
|
||||||
|
case VolumeMethod::kDefaultKey:
|
||||||
|
if (!defaultkey_volume_keygen(&gen)) return false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!generateStorageKey(gen, key)) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setup_ext_volume(const std::string& label, const std::string& blk_device,
|
||||||
|
const android::vold::KeyBuffer& key, std::string* out_crypto_blkdev) {
|
||||||
|
switch (volume_method()) {
|
||||||
|
case VolumeMethod::kFailed:
|
||||||
|
LOG(ERROR) << "Volume encryption setup failed";
|
||||||
|
return false;
|
||||||
|
case VolumeMethod::kCrypt:
|
||||||
|
return cryptfs_setup_ext_volume(label.c_str(), blk_device.c_str(), key,
|
||||||
|
out_crypto_blkdev) == 0;
|
||||||
|
case VolumeMethod::kDefaultKey:
|
||||||
|
return defaultkey_setup_ext_volume(label, blk_device, key, out_crypto_blkdev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
32
model/VolumeEncryption.h
Normal file
32
model/VolumeEncryption.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* 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 <string>
|
||||||
|
|
||||||
|
#include "KeyBuffer.h"
|
||||||
|
|
||||||
|
namespace android {
|
||||||
|
namespace vold {
|
||||||
|
|
||||||
|
bool generate_volume_key(android::vold::KeyBuffer* key);
|
||||||
|
|
||||||
|
bool setup_ext_volume(const std::string& label, const std::string& blk_device,
|
||||||
|
const android::vold::KeyBuffer& key, std::string* out_crypto_blkdev);
|
||||||
|
|
||||||
|
} // namespace vold
|
||||||
|
} // namespace android
|
Loading…
Reference in a new issue