No double encryption on FDE+FBE SD cards
On FBE systems, adoptable storage uses both file-based encryption (for
per-user protection) and full disk encryption (for metadata
protection). For performance/battery reasons, we don't want to encrypt
the same data twice; to that end, ensure that the
allow_encrypt_override flag is sent to dm_crypt.
Bug: 25861755
Test: see ag/3247969
Change-Id: Ib0c5891ab2d2ee9007e27a50254d29fc867d7bc5
diff --git a/cryptfs.cpp b/cryptfs.cpp
index af7fda3..207f08c 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -96,6 +96,8 @@
#define RETRY_MOUNT_ATTEMPTS 10
#define RETRY_MOUNT_DELAY_SECONDS 1
+#define CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE (1)
+
static int put_crypt_ftr_and_key(struct crypt_mnt_ftr* crypt_ftr);
static unsigned char saved_master_key[KEY_LEN_BYTES];
@@ -864,6 +866,7 @@
convert_key_to_hex_ascii(master_key, crypt_ftr->keysize, master_key_ascii);
buff_offset = crypt_params - buffer;
+ SLOGI("Extra parameters for dm_crypt: %s\n", extra_params);
snprintf(crypt_params, sizeof(buffer) - buff_offset, "%s %s 0 %s 0 %s",
crypt_ftr->crypto_type_name, master_key_ascii, real_blk_name,
extra_params);
@@ -919,71 +922,80 @@
return -1;
}
-static int create_crypto_blk_dev(struct crypt_mnt_ftr *crypt_ftr,
- const unsigned char *master_key, const char *real_blk_name,
- char *crypto_blk_name, const char *name) {
- char buffer[DM_CRYPT_BUF_SIZE];
- struct dm_ioctl *io;
- unsigned int minor;
- int fd=0;
- int err;
- int retval = -1;
- int version[3];
- const char *extra_params;
- int load_count;
+static std::string extra_params_as_string(const std::vector<std::string>& extra_params_vec) {
+ if (extra_params_vec.empty()) return "";
+ std::string extra_params = std::to_string(extra_params_vec.size());
+ for (const auto& p : extra_params_vec) {
+ extra_params.append(" ");
+ extra_params.append(p);
+ }
+ return extra_params;
+}
- if ((fd = open("/dev/device-mapper", O_RDWR|O_CLOEXEC)) < 0 ) {
- SLOGE("Cannot open device-mapper\n");
- goto errout;
- }
+static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key,
+ const char* real_blk_name, char* crypto_blk_name, const char* name,
+ uint32_t flags) {
+ char buffer[DM_CRYPT_BUF_SIZE];
+ struct dm_ioctl* io;
+ unsigned int minor;
+ int fd = 0;
+ int err;
+ int retval = -1;
+ int version[3];
+ int load_count;
+ std::vector<std::string> extra_params_vec;
- io = (struct dm_ioctl *) buffer;
+ if ((fd = open("/dev/device-mapper", O_RDWR | O_CLOEXEC)) < 0) {
+ SLOGE("Cannot open device-mapper\n");
+ goto errout;
+ }
- ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
- err = ioctl(fd, DM_DEV_CREATE, io);
- if (err) {
- SLOGE("Cannot create dm-crypt device %s: %s\n", name, strerror(errno));
- goto errout;
- }
+ io = (struct dm_ioctl*)buffer;
- /* Get the device status, in particular, the name of it's device file */
- ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
- if (ioctl(fd, DM_DEV_STATUS, io)) {
- SLOGE("Cannot retrieve dm-crypt device status\n");
- goto errout;
- }
- minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
- snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+ err = ioctl(fd, DM_DEV_CREATE, io);
+ if (err) {
+ SLOGE("Cannot create dm-crypt device %s: %s\n", name, strerror(errno));
+ goto errout;
+ }
- extra_params = "";
- if (! get_dm_crypt_version(fd, name, version)) {
- /* Support for allow_discards was added in version 1.11.0 */
- if ((version[0] >= 2) ||
- ((version[0] == 1) && (version[1] >= 11))) {
- extra_params = "1 allow_discards";
- SLOGI("Enabling support for allow_discards in dmcrypt.\n");
- }
- }
+ /* Get the device status, in particular, the name of it's device file */
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+ if (ioctl(fd, DM_DEV_STATUS, io)) {
+ SLOGE("Cannot retrieve dm-crypt device status\n");
+ goto errout;
+ }
+ minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00);
+ snprintf(crypto_blk_name, MAXPATHLEN, "/dev/block/dm-%u", minor);
- load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name,
- fd, extra_params);
- if (load_count < 0) {
- SLOGE("Cannot load dm-crypt mapping table.\n");
- goto errout;
- } else if (load_count > 1) {
- SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
- }
+ if (!get_dm_crypt_version(fd, name, version)) {
+ /* Support for allow_discards was added in version 1.11.0 */
+ if ((version[0] >= 2) || ((version[0] == 1) && (version[1] >= 11))) {
+ extra_params_vec.emplace_back("allow_discards");
+ }
+ }
+ if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) {
+ extra_params_vec.emplace_back("allow_encrypt_override");
+ }
+ load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, fd,
+ extra_params_as_string(extra_params_vec).c_str());
+ if (load_count < 0) {
+ SLOGE("Cannot load dm-crypt mapping table.\n");
+ goto errout;
+ } else if (load_count > 1) {
+ SLOGI("Took %d tries to load dmcrypt table.\n", load_count);
+ }
- /* Resume this device to activate it */
- ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
+ /* Resume this device to activate it */
+ ioctl_init(io, DM_CRYPT_BUF_SIZE, name, 0);
- if (ioctl(fd, DM_DEV_SUSPEND, io)) {
- SLOGE("Cannot resume the dm-crypt device\n");
- goto errout;
- }
+ if (ioctl(fd, DM_DEV_SUSPEND, io)) {
+ SLOGE("Cannot resume the dm-crypt device\n");
+ goto errout;
+ }
- /* We made it here with no errors. Woot! */
- retval = 0;
+ /* We made it here with no errors. Woot! */
+ retval = 0;
errout:
close(fd); /* If fd is <0 from a failed open call, it's safe to just ignore the close error */
@@ -1612,11 +1624,10 @@
// Create crypto block device - all (non fatal) code paths
// need it
- if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key,
- real_blkdev, crypto_blkdev, label)) {
- SLOGE("Error creating decrypted block device\n");
- rc = -1;
- goto errout;
+ if (create_crypto_blk_dev(crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev, label, 0)) {
+ SLOGE("Error creating decrypted block device\n");
+ rc = -1;
+ goto errout;
}
/* Work out if the problem is the password or the data */
@@ -1744,8 +1755,9 @@
strlcpy((char*) ext_crypt_ftr.crypto_type_name, "aes-cbc-essiv:sha256",
MAX_CRYPTO_TYPE_NAME_LEN);
- return create_crypto_blk_dev(&ext_crypt_ftr, key, real_blkdev,
- out_crypto_blkdev, label);
+ return create_crypto_blk_dev(
+ &ext_crypt_ftr, key, real_blkdev, out_crypto_blkdev, label,
+ e4crypt_is_native() ? CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE : 0);
}
/*
@@ -2313,7 +2325,7 @@
decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
create_crypto_blk_dev(&crypt_ftr, decrypted_master_key, real_blkdev, crypto_blkdev,
- CRYPTO_BLOCK_DEVICE);
+ CRYPTO_BLOCK_DEVICE, 0);
/* If we are continuing, check checksums match */
rc = 0;