recovery-utils: add support to set the rootfs encryption key
Internal recovery-utils.git SHA1: 283f6e0768c0 https://jira.digi.com/browse/DEL-3857 Signed-off-by: Tatiana Leon <tatiana.leon@digi.com>
This commit is contained in:
parent
d7da8794f1
commit
c4bd0534e2
|
|
@ -47,4 +47,14 @@ int reboot_recovery(unsigned int reboot_timeout);
|
|||
*/
|
||||
int wipe_update_partition(void);
|
||||
|
||||
/*
|
||||
* Configure recovery commands to set a file system encryption key.
|
||||
*
|
||||
* Params:
|
||||
* 'key' (input) Encryption key to use, NULL or empty to generate a random one
|
||||
*
|
||||
* Return: 0 on sucess, -1 on failure
|
||||
*/
|
||||
int set_fs_encryption_key(char *key);
|
||||
|
||||
#endif /* RECOVERY_H */
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
|
||||
#define _GNU_SOURCE /* For GNU version of basename */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
@ -29,6 +30,18 @@
|
|||
|
||||
#define FILE_PREFIX "file://"
|
||||
|
||||
#define OTP_CLOSED_BIT 2
|
||||
|
||||
/* Plain key size */
|
||||
#define KEYSIZE_BYTES 32 /* 256 bits */
|
||||
|
||||
/*
|
||||
* Base64 encoded string size
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Base64#Padding
|
||||
*/
|
||||
#define BASE64_SIZE_BYTES(x) (4 * ((x + (3 - 1)) / 3))
|
||||
|
||||
/*
|
||||
* Function: append_recovery_command
|
||||
* Description: append configuration to the 'recovery_command' variable
|
||||
|
|
@ -75,6 +88,41 @@ err:
|
|||
return ret ? -1 : 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: is_device_closed
|
||||
* Description: check if the device is closed
|
||||
*/
|
||||
static int is_device_closed(void)
|
||||
{
|
||||
const char *path = "/sys/fsl_otp/HW_OCOTP_CFG5";
|
||||
FILE *fd = NULL;
|
||||
unsigned int value = 0;
|
||||
long open = 0;
|
||||
|
||||
if ((fd = fopen(path, "r")) == NULL) {
|
||||
fprintf(stderr, "Cannot check device status. Assuming closed...\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
open = (fscanf(fd, "%x", &value) == 1) && (value & OTP_CLOSED_BIT);
|
||||
|
||||
fclose(fd);
|
||||
|
||||
return open;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: secure_memzero
|
||||
* Description: secure memzero that is not optimized out by the compiler
|
||||
*/
|
||||
void secure_memzero(void *buf, size_t len)
|
||||
{
|
||||
volatile uint8_t *p = (volatile uint8_t *)buf;
|
||||
|
||||
while (len--)
|
||||
*p++ = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: update_firmware
|
||||
* Description: configure recovery commands to update the firmware
|
||||
|
|
@ -153,3 +201,52 @@ int wipe_update_partition(void)
|
|||
{
|
||||
return append_recovery_command("wipe_update");
|
||||
}
|
||||
|
||||
/*
|
||||
* Function: set_fs_encryption_key
|
||||
* Description: configure recovery commands to set a file system encryption key
|
||||
*/
|
||||
int set_fs_encryption_key(char *key)
|
||||
{
|
||||
char *key_cmd = NULL;
|
||||
int generate_random_key = 0;
|
||||
int ret = -1;
|
||||
|
||||
generate_random_key = (!key || strlen(key) == 0);
|
||||
|
||||
if (!generate_random_key &&
|
||||
BASE64_SIZE_BYTES(KEYSIZE_BYTES) != strlen(key)) {
|
||||
fprintf(stderr, "Error: invalid key size\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!is_device_closed()) {
|
||||
printf("\n"
|
||||
" *****************************************************************\n"
|
||||
" * Warning: Use filesystem encryption only on CLOSED devices. *\n"
|
||||
" * Filesystem encryption on open devices is not secure. *\n"
|
||||
" *****************************************************************\n");
|
||||
}
|
||||
|
||||
key_cmd =
|
||||
calloc(1,
|
||||
strlen("encryption_key=") +
|
||||
(generate_random_key ? 0 : strlen(key)) + 1);
|
||||
if (!key_cmd) {
|
||||
fprintf(stderr, "Error: calloc 'key_cmd'\n");
|
||||
goto err;
|
||||
}
|
||||
|
||||
sprintf(key_cmd, "encryption_key=%s", generate_random_key ? "" : key);
|
||||
|
||||
ret = append_recovery_command(key_cmd);
|
||||
|
||||
free(key_cmd);
|
||||
|
||||
err:
|
||||
/* Secure delete the key buffers */
|
||||
if (!generate_random_key)
|
||||
secure_memzero(key, strlen(key));
|
||||
|
||||
return ret ? -1 : 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@
|
|||
|
||||
#include <recovery.h>
|
||||
|
||||
#define VERSION "0.1" GIT_REVISION
|
||||
#define VERSION "0.2" GIT_REVISION
|
||||
|
||||
#define REBOOT_TIMEOUT 10
|
||||
|
||||
|
|
@ -40,10 +40,13 @@
|
|||
"Version: %s\n" \
|
||||
"\n" \
|
||||
"Usage: %s [options] [<SWU-package-path>]\n\n" \
|
||||
" -u --update-firmware Perform firmware update\n" \
|
||||
" -w --wipe-update-partition Wipe 'update' partition\n" \
|
||||
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
||||
" --help Print help and exit\n" \
|
||||
" -u --update-firmware Perform firmware update\n" \
|
||||
" -k[<key>] --encryption-key[=<key>] Set <key> as file system encryption key.\n" \
|
||||
" Empty to generate a random key.\n" \
|
||||
" Use this option along with update firmware option (-u).\n" \
|
||||
" -w --wipe-update-partition Wipe 'update' partition\n" \
|
||||
" -T<N> --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
||||
" --help Print help and exit\n" \
|
||||
"\n" \
|
||||
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
||||
"\n"
|
||||
|
|
@ -55,8 +58,10 @@
|
|||
"Version: %s\n" \
|
||||
"\n" \
|
||||
"Usage: %s [options] <SWU-package-path>\n\n" \
|
||||
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
||||
" --help Print help and exit\n" \
|
||||
" -k[<key>] --encryption-key[=<key>] Set <key> as file system encryption key.\n" \
|
||||
" Empty to generate a random key.\n" \
|
||||
" -T<N> --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
||||
" --help Print help and exit\n" \
|
||||
"\n" \
|
||||
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
||||
"\n"
|
||||
|
|
@ -69,8 +74,10 @@ static char *cmd_name;
|
|||
|
||||
/* Command line options */
|
||||
static char *swu_package;
|
||||
static char *key = NULL;
|
||||
static int wipe_update;
|
||||
static int update_fw;
|
||||
static int set_key;
|
||||
static int reboot_timeout = REBOOT_TIMEOUT;
|
||||
|
||||
/*
|
||||
|
|
@ -96,9 +103,10 @@ static void usage_and_exit(int exitval)
|
|||
static void parse_options(int argc, char *argv[])
|
||||
{
|
||||
static int opt_index, opt;
|
||||
static const char *short_options = "uwT:";
|
||||
static const char *short_options = "uk::wT:";
|
||||
static const struct option long_options[] = {
|
||||
{"update-firmware", no_argument, NULL, 'u'},
|
||||
{"encryption-key", optional_argument, NULL, 'k'},
|
||||
{"wipe-update-partition", no_argument, NULL, 'w'},
|
||||
{"reboot-timeout", required_argument, NULL, 'T'},
|
||||
{"help", no_argument, NULL, 'h'},
|
||||
|
|
@ -123,6 +131,11 @@ static void parse_options(int argc, char *argv[])
|
|||
case 'w':
|
||||
wipe_update = 1;
|
||||
break;
|
||||
case 'k':
|
||||
set_key = 1;
|
||||
if (optarg)
|
||||
key = optarg;
|
||||
break;
|
||||
case 'T':
|
||||
reboot_timeout = (int)strtol(optarg, &endptr, 10);
|
||||
if (*endptr) {
|
||||
|
|
@ -152,6 +165,10 @@ static void parse_options(int argc, char *argv[])
|
|||
printf("Error: missing SWU package argument\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
} else if (set_key) {
|
||||
/* Always need to update firmware when setting a new key */
|
||||
printf("Error: encryption key can only be set while performing a firmware update\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -168,6 +185,15 @@ int main(int argc, char *argv[])
|
|||
/* Read and parse command line */
|
||||
parse_options(argc, argv);
|
||||
|
||||
if (set_key) {
|
||||
/* Configure recovery commands to set a fs encryption key */
|
||||
ret = set_fs_encryption_key(key);
|
||||
if (ret) {
|
||||
printf("Error: set_fs_encryption_key\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (swu_package) {
|
||||
/* Configure recovery commands to update the firmware */
|
||||
ret = update_firmware(swu_package);
|
||||
|
|
|
|||
Loading…
Reference in New Issue