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);
|
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 */
|
#endif /* RECOVERY_H */
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#define _GNU_SOURCE /* For GNU version of basename */
|
#define _GNU_SOURCE /* For GNU version of basename */
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
@ -29,6 +30,18 @@
|
||||||
|
|
||||||
#define FILE_PREFIX "file://"
|
#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
|
* Function: append_recovery_command
|
||||||
* Description: append configuration to the 'recovery_command' variable
|
* Description: append configuration to the 'recovery_command' variable
|
||||||
|
|
@ -75,6 +88,41 @@ err:
|
||||||
return ret ? -1 : 0;
|
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
|
* Function: update_firmware
|
||||||
* Description: configure recovery commands to update the firmware
|
* Description: configure recovery commands to update the firmware
|
||||||
|
|
@ -153,3 +201,52 @@ int wipe_update_partition(void)
|
||||||
{
|
{
|
||||||
return append_recovery_command("wipe_update");
|
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>
|
#include <recovery.h>
|
||||||
|
|
||||||
#define VERSION "0.1" GIT_REVISION
|
#define VERSION "0.2" GIT_REVISION
|
||||||
|
|
||||||
#define REBOOT_TIMEOUT 10
|
#define REBOOT_TIMEOUT 10
|
||||||
|
|
||||||
|
|
@ -40,10 +40,13 @@
|
||||||
"Version: %s\n" \
|
"Version: %s\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Usage: %s [options] [<SWU-package-path>]\n\n" \
|
"Usage: %s [options] [<SWU-package-path>]\n\n" \
|
||||||
" -u --update-firmware Perform firmware update\n" \
|
" -u --update-firmware Perform firmware update\n" \
|
||||||
" -w --wipe-update-partition Wipe 'update' partition\n" \
|
" -k[<key>] --encryption-key[=<key>] Set <key> as file system encryption key.\n" \
|
||||||
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
" Empty to generate a random key.\n" \
|
||||||
" --help Print help and exit\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" \
|
"\n" \
|
||||||
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -55,8 +58,10 @@
|
||||||
"Version: %s\n" \
|
"Version: %s\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Usage: %s [options] <SWU-package-path>\n\n" \
|
"Usage: %s [options] <SWU-package-path>\n\n" \
|
||||||
" -T --reboot-timeout=<N> Reboot after N seconds (default %d)\n" \
|
" -k[<key>] --encryption-key[=<key>] Set <key> as file system encryption key.\n" \
|
||||||
" --help Print help and exit\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" \
|
"\n" \
|
||||||
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
"<SWU-package-path> Absolute path to the firmware update package\n" \
|
||||||
"\n"
|
"\n"
|
||||||
|
|
@ -69,8 +74,10 @@ static char *cmd_name;
|
||||||
|
|
||||||
/* Command line options */
|
/* Command line options */
|
||||||
static char *swu_package;
|
static char *swu_package;
|
||||||
|
static char *key = NULL;
|
||||||
static int wipe_update;
|
static int wipe_update;
|
||||||
static int update_fw;
|
static int update_fw;
|
||||||
|
static int set_key;
|
||||||
static int reboot_timeout = REBOOT_TIMEOUT;
|
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 void parse_options(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
static int opt_index, opt;
|
static int opt_index, opt;
|
||||||
static const char *short_options = "uwT:";
|
static const char *short_options = "uk::wT:";
|
||||||
static const struct option long_options[] = {
|
static const struct option long_options[] = {
|
||||||
{"update-firmware", no_argument, NULL, 'u'},
|
{"update-firmware", no_argument, NULL, 'u'},
|
||||||
|
{"encryption-key", optional_argument, NULL, 'k'},
|
||||||
{"wipe-update-partition", no_argument, NULL, 'w'},
|
{"wipe-update-partition", no_argument, NULL, 'w'},
|
||||||
{"reboot-timeout", required_argument, NULL, 'T'},
|
{"reboot-timeout", required_argument, NULL, 'T'},
|
||||||
{"help", no_argument, NULL, 'h'},
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
|
@ -123,6 +131,11 @@ static void parse_options(int argc, char *argv[])
|
||||||
case 'w':
|
case 'w':
|
||||||
wipe_update = 1;
|
wipe_update = 1;
|
||||||
break;
|
break;
|
||||||
|
case 'k':
|
||||||
|
set_key = 1;
|
||||||
|
if (optarg)
|
||||||
|
key = optarg;
|
||||||
|
break;
|
||||||
case 'T':
|
case 'T':
|
||||||
reboot_timeout = (int)strtol(optarg, &endptr, 10);
|
reboot_timeout = (int)strtol(optarg, &endptr, 10);
|
||||||
if (*endptr) {
|
if (*endptr) {
|
||||||
|
|
@ -152,6 +165,10 @@ static void parse_options(int argc, char *argv[])
|
||||||
printf("Error: missing SWU package argument\n");
|
printf("Error: missing SWU package argument\n");
|
||||||
exit(EXIT_FAILURE);
|
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 */
|
/* Read and parse command line */
|
||||||
parse_options(argc, argv);
|
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) {
|
if (swu_package) {
|
||||||
/* Configure recovery commands to update the firmware */
|
/* Configure recovery commands to update the firmware */
|
||||||
ret = update_firmware(swu_package);
|
ret = update_firmware(swu_package);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue