From 32984efc9026a0d482b2584c65b2bb1112a622f9 Mon Sep 17 00:00:00 2001 From: Gabriel Valcazar Date: Thu, 20 May 2021 13:19:54 +0200 Subject: [PATCH] recovery-utils: ask for confirmation when changing the encryption key If we trigger a key change while there are partitions that are encrypted, print a warning and ask for confirmation so users know that the operation will erase the contents of said partitions. Like in the partition (un)encryption mechanism, add the possibility to skip both the warning message and the confirmation prompt. Signed-off-by: Gabriel Valcazar --- .../recovery-utils/include/recovery.h | 5 +- .../recovery-utils/lib/recovery.c | 59 +++++++++++++++++-- .../recovery-reboot/recovery-reboot.c | 19 ++++-- 3 files changed, 72 insertions(+), 11 deletions(-) diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h index 0e29522b3..e73a86951 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/include/recovery.h @@ -52,10 +52,11 @@ int wipe_update_partition(void); * * Params: * 'key' (input) Encryption key to use, NULL or empty to generate a random one + * 'force' (input) Skips warning and confirmation prompt if non-zero * - * Return: 0 on sucess, -1 on failure + * Return: 0 on sucess, -1 on failure and 1 on success with no recovery command set */ -int set_encryption_key(char *key); +int set_encryption_key(char *key, unsigned char force); /* * Configure recovery commands to encrypt/un-encrypt provided partitions. diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c index ce1762341..b1c013b1a 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/lib/recovery.c @@ -70,6 +70,8 @@ static char *emmc_parts_blacklist[] = { NULL }; +static char *rootfs[] = { "rootfs", NULL }; + /* * Function: append_recovery_command * Description: append configuration to the 'recovery_command' variable @@ -640,11 +642,19 @@ int wipe_update_partition(void) * Function: set_encryption_key * Description: configure recovery commands to set a partition encryption key */ -int set_encryption_key(char *key) +int set_encryption_key(char *key, unsigned char force) { + char *parts[MAX_PARTITIONS]; + char *encrypted[MAX_PARTITIONS]; char *key_cmd = NULL; + char confirmation; int generate_random_key = 0; int ret = -1; + unsigned char i = 0; + + /* Initialize arrays */ + parts[0] = NULL; + encrypted[0] = NULL; generate_random_key = (!key || strlen(key) == 0); @@ -656,6 +666,46 @@ int set_encryption_key(char *key) print_open_device_warning(); + if (!force) { + /* Check if there are any currently encrypted partitions */ + ret = PARSE_PARTITION_INFO(parts, encrypted, MAX_PARTITIONS); + if (ret) { + fprintf(stderr, "Error: parse_partition_info\n"); + goto err; + } + + /* + * Key changes with an encrypted rootfs are only possible if + * an update package is provided, in which case, we're already + * substituting the current rootfs image with another one. + * Because of this, there's no need to print the warning if the + * rootfs is the only encrypted partition in the system. + */ + subtract_array(rootfs, encrypted); + + /* + * If we have at least one encrypted partition, ask for + * confirmation before continuing. + */ + if (encrypted[0]) { + printf("\n" + " *****************************************************************\n" + " * Warning: Changing the encryption key will erase the contents *\n" + " * of all currently encrypted partitions. *\n" + " *****************************************************************\n" + " Affected partitions:\n"); + while (encrypted[i]) + printf(" %s\n", encrypted[i++]); + printf("\n Continue? (y/n): "); + confirmation = getchar(); + if (confirmation != 'y' && confirmation != 'Y') { + printf("\nSkipping encryption key change\n"); + ret = 1; + goto err; + } + } + } + key_cmd = calloc(1, strlen("encryption_key=") + @@ -676,7 +726,10 @@ err: if (!generate_random_key) secure_memzero(key, strlen(key)); - return ret ? -1 : 0; + free_array(encrypted); + free_array(parts); + + return ret < 0 ? -1 : ret; } /* @@ -685,8 +738,6 @@ err: */ int encrypt_partitions(char *to_encrypt, char *to_unencrypt, unsigned char force) { - char *rootfs[] = { "rootfs", NULL }; - char *parts[MAX_PARTITIONS]; char *encrypted[MAX_PARTITIONS]; char *new_encrypted[MAX_PARTITIONS]; diff --git a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c index 2ba2f80b6..142b2338a 100644 --- a/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c +++ b/meta-digi-dey/recipes-core/recovery/recovery-utils/recovery-utils/recovery-reboot/recovery-reboot.c @@ -48,7 +48,7 @@ " Empty to generate a random key.\n" \ " -w --wipe-update-partition Wipe 'update' partition\n" \ " -T --reboot-timeout= Reboot after N seconds (default %d)\n" \ - " -f --force Force (un)encryption operations.\n" \ + " -f --force Force (un)encryption and key change operations.\n" \ " --help Print help and exit\n" \ "\n" \ " Absolute path to the firmware update package\n" \ @@ -64,6 +64,7 @@ " -k [] --encryption-key[=] Set as file system encryption key.\n" \ " Empty to generate a random key.\n" \ " -T --reboot-timeout= Reboot after N seconds (default %d)\n" \ + " -f --force Force (un)encryption and key change operations.\n" \ " --help Print help and exit\n" \ "\n" \ " Absolute path to the firmware update package\n" \ @@ -81,7 +82,7 @@ " -k [] --encryption-key[=] Set as file system encryption key.\n" \ " Empty to generate a random key.\n" \ " -T --reboot-timeout= Reboot after N seconds (default %d)\n" \ - " -f --force Force (un)encryption operations.\n" \ + " -f --force Force (un)encryption and key change operations.\n" \ " --help Print help and exit\n" \ "\n" @@ -227,12 +228,20 @@ int main(int argc, char *argv[]) if (set_key) { /* Configure recovery commands to set a fs encryption key */ - ret = set_encryption_key(key); - if (ret) { + ret = set_encryption_key(key, force); + if (ret < 0) { printf("Error: set_encryption_key\n"); goto out; + } else if (ret == 0) { + /* + * Only reboot if strictly necessary, since the function + * might succeed without setting a recovery command + * (for example, if a user cancels the operation). + */ + need_reboot++; + } else { + ret = 0; } - need_reboot++; } if (swu_package) {