Support metadata encryption

Bug: 29189559
Test: Angler, Marlin build and boot
Change-Id: Ia7b070781f5f16ff8bfd934569a2209c80c28385
This commit is contained in:
Paul Lawrence 2017-04-21 12:41:48 -07:00
parent 1395aac313
commit 9dbe97b4d5
5 changed files with 108 additions and 64 deletions

View File

@ -721,6 +721,12 @@ static bool needs_block_encryption(const struct fstab_rec* rec)
return false;
}
static bool should_use_metadata_encryption(const struct fstab_rec* rec) {
if (!(rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE))) return false;
if (!(rec->fs_mgr_flags & MF_KEYDIRECTORY)) return false;
return true;
}
// Check to see if a mountable volume has encryption requirements
static int handle_encryptable(const struct fstab_rec* rec)
{
@ -733,8 +739,14 @@ static int handle_encryptable(const struct fstab_rec* rec)
<< " - allow continue unencrypted";
return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED;
}
} else if (should_use_metadata_encryption(rec)) {
if (umount(rec->mount_point) == 0) {
return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION;
} else {
PERROR << "Could not umount " << rec->mount_point << " - fail since can't encrypt";
return FS_MGR_MNTALL_FAIL;
}
} else if (rec->fs_mgr_flags & (MF_FILEENCRYPTION | MF_FORCEFDEORFBE)) {
// Deal with file level encryption
LINFO << rec->mount_point << " is file encrypted";
return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED;
} else if (fs_mgr_is_encryptable(rec)) {
@ -900,7 +912,6 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
continue;
}
/* mount(2) returned an error, handle the encryptable/formattable case */
bool wiped = partition_wiped(fstab->recs[top_idx].blk_device);
bool crypt_footer = false;
if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
@ -940,6 +951,8 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
continue;
}
}
/* mount(2) returned an error, handle the encryptable/formattable case */
if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
fs_mgr_is_encryptable(&fstab->recs[attempted_idx])) {
if (wiped) {
@ -965,6 +978,9 @@ int fs_mgr_mount_all(struct fstab *fstab, int mount_mode)
}
}
encryptable = FS_MGR_MNTALL_DEV_MIGHT_BE_ENCRYPTED;
} else if (mret && mount_errno != EBUSY && mount_errno != EACCES &&
should_use_metadata_encryption(&fstab->recs[attempted_idx])) {
encryptable = FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED;
} else {
if (fs_mgr_is_nofail(&fstab->recs[attempted_idx])) {
PERROR << "Ignoring failure to mount an un-encryptable or wiped partition on"
@ -1256,48 +1272,46 @@ int fs_mgr_swapon_all(struct fstab *fstab)
return ret;
}
/*
* key_loc must be at least PROPERTY_VALUE_MAX bytes long
*
* real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
*/
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_device, int size)
{
int i = 0;
struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab) {
int i;
if (!fstab) {
return -1;
}
/* Initialize return values to null strings */
if (key_loc) {
*key_loc = '\0';
}
if (real_blk_device) {
*real_blk_device = '\0';
return NULL;
}
/* Look for the encryptable partition to find the data */
for (i = 0; i < fstab->num_entries; i++) {
/* Don't deal with vold managed enryptable partitions here */
if (fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) {
continue;
if (!(fstab->recs[i].fs_mgr_flags & MF_VOLDMANAGED) &&
(fstab->recs[i].fs_mgr_flags &
(MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE | MF_FILEENCRYPTION))) {
return &fstab->recs[i];
}
if (!(fstab->recs[i].fs_mgr_flags
& (MF_CRYPT | MF_FORCECRYPT | MF_FORCEFDEORFBE))) {
continue;
}
/* We found a match */
if (key_loc) {
strlcpy(key_loc, fstab->recs[i].key_loc, size);
}
if (real_blk_device) {
strlcpy(real_blk_device, fstab->recs[i].blk_device, size);
}
break;
}
return NULL;
}
return 0;
/*
* key_loc must be at least PROPERTY_VALUE_MAX bytes long
*
* real_blk_device must be at least PROPERTY_VALUE_MAX bytes long
*/
void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size) {
struct fstab_rec const* rec = fs_mgr_get_crypt_entry(fstab);
if (key_loc) {
if (rec) {
strlcpy(key_loc, rec->key_loc, size);
} else {
*key_loc = '\0';
}
}
if (real_blk_device) {
if (rec) {
strlcpy(real_blk_device, rec->blk_device, size);
} else {
*real_blk_device = '\0';
}
}
}
bool fs_mgr_load_verity_state(int* mode) {

View File

@ -31,6 +31,7 @@
struct fs_mgr_flag_values {
char *key_loc;
char* key_dir;
char *verity_loc;
long long part_length;
char *label;
@ -70,34 +71,35 @@ static struct flag_list mount_flags[] = {
};
static struct flag_list fs_mgr_flags[] = {
{ "wait", MF_WAIT },
{ "check", MF_CHECK },
{ "encryptable=", MF_CRYPT },
{ "forceencrypt=", MF_FORCECRYPT },
{ "fileencryption=", MF_FILEENCRYPTION },
{ "forcefdeorfbe=", MF_FORCEFDEORFBE },
{ "nonremovable", MF_NONREMOVABLE },
{ "voldmanaged=", MF_VOLDMANAGED},
{ "length=", MF_LENGTH },
{ "recoveryonly", MF_RECOVERYONLY },
{ "swapprio=", MF_SWAPPRIO },
{ "zramsize=", MF_ZRAMSIZE },
{ "max_comp_streams=", MF_MAX_COMP_STREAMS },
{ "verifyatboot", MF_VERIFYATBOOT },
{ "verify", MF_VERIFY },
{ "avb", MF_AVB },
{ "noemulatedsd", MF_NOEMULATEDSD },
{ "notrim", MF_NOTRIM },
{ "formattable", MF_FORMATTABLE },
{ "slotselect", MF_SLOTSELECT },
{ "nofail", MF_NOFAIL },
{ "latemount", MF_LATEMOUNT },
{ "reservedsize=", MF_RESERVEDSIZE },
{ "quota", MF_QUOTA },
{ "eraseblk=", MF_ERASEBLKSIZE },
{ "logicalblk=", MF_LOGICALBLKSIZE },
{ "defaults", 0 },
{ 0, 0 },
{"wait", MF_WAIT},
{"check", MF_CHECK},
{"encryptable=", MF_CRYPT},
{"forceencrypt=", MF_FORCECRYPT},
{"fileencryption=", MF_FILEENCRYPTION},
{"forcefdeorfbe=", MF_FORCEFDEORFBE},
{"keydirectory=", MF_KEYDIRECTORY},
{"nonremovable", MF_NONREMOVABLE},
{"voldmanaged=", MF_VOLDMANAGED},
{"length=", MF_LENGTH},
{"recoveryonly", MF_RECOVERYONLY},
{"swapprio=", MF_SWAPPRIO},
{"zramsize=", MF_ZRAMSIZE},
{"max_comp_streams=", MF_MAX_COMP_STREAMS},
{"verifyatboot", MF_VERIFYATBOOT},
{"verify", MF_VERIFY},
{"avb", MF_AVB},
{"noemulatedsd", MF_NOEMULATEDSD},
{"notrim", MF_NOTRIM},
{"formattable", MF_FORMATTABLE},
{"slotselect", MF_SLOTSELECT},
{"nofail", MF_NOFAIL},
{"latemount", MF_LATEMOUNT},
{"reservedsize=", MF_RESERVEDSIZE},
{"quota", MF_QUOTA},
{"eraseblk=", MF_ERASEBLKSIZE},
{"logicalblk=", MF_LOGICALBLKSIZE},
{"defaults", 0},
{0, 0},
};
#define EM_AES_256_XTS 1
@ -266,6 +268,11 @@ static int parse_flags(char *flags, struct flag_list *fl,
} else {
flag_vals->file_names_mode = EM_AES_256_CTS;
}
} else if ((fl[i].flag == MF_KEYDIRECTORY) && flag_vals) {
/* The metadata flag is followed by an = and the
* directory for the keys. Get it and return it.
*/
flag_vals->key_dir = strdup(strchr(p, '=') + 1);
} else if ((fl[i].flag == MF_LENGTH) && flag_vals) {
/* The length flag is followed by an = and the
* size of the partition. Get it and return it.
@ -557,6 +564,7 @@ static struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
fstab->recs[cnt].fs_mgr_flags = parse_flags(p, fs_mgr_flags,
&flag_vals, NULL, 0);
fstab->recs[cnt].key_loc = flag_vals.key_loc;
fstab->recs[cnt].key_dir = flag_vals.key_dir;
fstab->recs[cnt].verity_loc = flag_vals.verity_loc;
fstab->recs[cnt].length = flag_vals.part_length;
fstab->recs[cnt].label = flag_vals.label;
@ -716,6 +724,7 @@ void fs_mgr_free_fstab(struct fstab *fstab)
free(fstab->recs[i].fs_type);
free(fstab->recs[i].fs_options);
free(fstab->recs[i].key_loc);
free(fstab->recs[i].key_dir);
free(fstab->recs[i].label);
}

View File

@ -107,6 +107,7 @@
#define MF_ERASEBLKSIZE 0x800000
#define MF_LOGICALBLKSIZE 0X1000000
#define MF_AVB 0X2000000
#define MF_KEYDIRECTORY 0X4000000
#define DM_BUF_SIZE 4096

View File

@ -72,6 +72,7 @@ struct fstab_rec {
char *fs_options;
int fs_mgr_flags;
char *key_loc;
char* key_dir;
char *verity_loc;
long long length;
char *label;
@ -95,6 +96,8 @@ struct fstab *fs_mgr_read_fstab_dt();
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
void fs_mgr_free_fstab(struct fstab *fstab);
#define FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED 7
#define FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION 6
#define FS_MGR_MNTALL_DEV_FILE_ENCRYPTED 5
#define FS_MGR_MNTALL_DEV_NEEDS_RECOVERY 4
#define FS_MGR_MNTALL_DEV_NEEDS_ENCRYPTION 3
@ -112,8 +115,8 @@ int fs_mgr_do_mount(struct fstab *fstab, const char *n_name, char *n_blk_device,
int fs_mgr_do_mount_one(struct fstab_rec *rec);
int fs_mgr_do_tmpfs_mount(const char *n_name);
int fs_mgr_unmount_all(struct fstab *fstab);
int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc,
char *real_blk_device, int size);
struct fstab_rec const* fs_mgr_get_crypt_entry(struct fstab const* fstab);
void fs_mgr_get_crypt_info(struct fstab* fstab, char* key_loc, char* real_blk_device, size_t size);
bool fs_mgr_load_verity_state(int* mode);
bool fs_mgr_update_verity_state(fs_mgr_verity_state_callback callback);
int fs_mgr_add_entry(struct fstab *fstab,

View File

@ -481,6 +481,23 @@ static int queue_fs_event(int code) {
// Although encrypted, we have device key, so we do not need to
// do anything different from the nonencrypted case.
ActionManager::GetInstance().QueueEventTrigger("nonencrypted");
} else if (code == FS_MGR_MNTALL_DEV_IS_METADATA_ENCRYPTED) {
if (e4crypt_install_keyring()) {
return -1;
}
property_set("ro.crypto.state", "encrypted");
property_set("ro.crypto.type", "file");
// defaultcrypto detects file/block encryption. init flow is same for each.
ActionManager::GetInstance().QueueEventTrigger("defaultcrypto");
} else if (code == FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION) {
if (e4crypt_install_keyring()) {
return -1;
}
property_set("ro.crypto.type", "file");
// encrypt detects file/block encryption. init flow is same for each.
ActionManager::GetInstance().QueueEventTrigger("encrypt");
} else if (code > 0) {
PLOG(ERROR) << "fs_mgr_mount_all returned unexpected error " << code;
}