diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-09-11 17:23:30 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-09-11 17:23:30 +0200 |
commit | be22bb4527e3be70718dfee414e08b17c399f9fd (patch) | |
tree | 4031527cb850203102daf8bc80531d384e7452fe /scripts | |
parent | f00f9f52163dbb7847326e5edfa969d12f63be20 (diff) | |
parent | 6f56b955bdc6f072687f56a1c851d419512bc056 (diff) | |
download | barebox-be22bb4527e3be70718dfee414e08b17c399f9fd.tar.gz barebox-be22bb4527e3be70718dfee414e08b17c399f9fd.tar.xz |
Merge branch 'for-next/imx-hab'
Diffstat (limited to 'scripts')
-rw-r--r-- | scripts/imx/imx-image.c | 50 | ||||
-rw-r--r-- | scripts/imx/imx.c | 183 |
2 files changed, 221 insertions, 12 deletions
diff --git a/scripts/imx/imx-image.c b/scripts/imx/imx-image.c index 558dacfbb2..88e2cb955f 100644 --- a/scripts/imx/imx-image.c +++ b/scripts/imx/imx-image.c @@ -43,7 +43,6 @@ * HEADER_SIZE */ #define MAX_DCD ((HEADER_LEN - FLASH_HEADER_OFFSET - sizeof(struct imx_flash_header_v2)) / sizeof(u32)) -#define CSF_LEN 0x2000 /* length of the CSF (needed for HAB) */ static uint32_t dcdtable[MAX_DCD]; static int curdcd; @@ -533,6 +532,7 @@ static int hab_sign(struct config_data *data) struct stat s; char *cst; void *buf; + size_t csf_space = CSF_LEN; cst = getenv("CST"); if (!cst) @@ -558,7 +558,28 @@ static int hab_sign(struct config_data *data) } } - ret = asprintf(&command, "%s -o %s", cst, csffile); + /* + * Older versions of "cst" want to read the CSF from STDIN, + * while newer versions want to read the CSF from a + * file. Sadly, the "-i" option doesn't understand "-i -" to + * read from STDIN, so we give it "/dev/stdin" instead. + */ + ret = asprintf(&command, + "%s | grep 'Input CSF text filename'", + cst); + if (ret < 0) + return -ENOMEM; + + ret = system(command); + free(command); + if (ret == -1) + return -EINVAL; + else if (ret == 0) + ret = asprintf(&command, "%s -o %s -i /dev/stdin", + cst, csffile); + else + ret = asprintf(&command, "%s -o %s;", + cst, csffile); if (ret < 0) return -ENOMEM; @@ -613,15 +634,23 @@ static int hab_sign(struct config_data *data) return -errno; } - buf = malloc(CSF_LEN); + /* + * DEK blob needs to be part of CSF area, in order to properly + * load by ROM code. Make space to simply concatenate DEK blob + * to the end of image during device flashing procedure. + */ + if (data->encrypt_image) + csf_space -= (data->dek_size + DEK_BLOB_OVERHEAD); + + buf = malloc(csf_space); if (!buf) return -ENOMEM; - memset(buf, 0x5a, CSF_LEN); + memset(buf, 0x5a, csf_space); - if (s.st_size > CSF_LEN) { - fprintf(stderr, "CSF file size exceeds maximum CSF len of %d bytes\n", - CSF_LEN); + if (s.st_size > csf_space) { + fprintf(stderr, "CSF file size exceeds maximum CSF space of %zu bytes\n", + csf_space); } ret = xread(fd, buf, s.st_size); @@ -632,7 +661,7 @@ static int hab_sign(struct config_data *data) outfd = open(data->outfile, O_WRONLY | O_APPEND); - ret = xwrite(outfd, buf, CSF_LEN); + ret = xwrite(outfd, buf, csf_space); if (ret < 0) { fprintf(stderr, "write failed: %s\n", strerror(errno)); return -errno; @@ -709,7 +738,7 @@ int main(int argc, char *argv[]) prgname = argv[0]; - while ((opt = getopt(argc, argv, "c:hf:o:bdus")) != -1) { + while ((opt = getopt(argc, argv, "c:hf:o:bduse")) != -1) { switch (opt) { case 'c': configfile = optarg; @@ -732,6 +761,9 @@ int main(int argc, char *argv[]) case 'u': create_usb_image = 1; break; + case 'e': + data.encrypt_image = 1; + break; case 'h': usage(argv[0]); default: diff --git a/scripts/imx/imx.c b/scripts/imx/imx.c index 7d2a5c5b8f..2341732b2f 100644 --- a/scripts/imx/imx.c +++ b/scripts/imx/imx.c @@ -22,6 +22,7 @@ #include <string.h> #include <stdint.h> #include <errno.h> +#include <sys/stat.h> #include <linux/kernel.h> #include <mach/imx_cpu_types.h> @@ -29,6 +30,12 @@ #define MAXARGS 32 +/* + * First word of bootloader image should be authenticated, + * encrypt the rest. + */ +#define ENCRYPT_OFFSET (HEADER_LEN + 0x10) + static int parse_line(char *line, char *argv[]) { int nargs = 0; @@ -317,15 +324,170 @@ static int do_hab(struct config_data *data, int argc, char *argv[]) static int do_hab_blocks(struct config_data *data, int argc, char *argv[]) { + const char *type; + char *str; + int ret; + uint32_t signed_size = data->load_size; + + if (!data->csf) + return -EINVAL; + + if (argc < 2) + type = "full"; + else + type = argv[1]; + + /* + * In case of encrypted image we reduce signed area to beginning + * of encrypted area. + */ + if (data->encrypt_image) + signed_size = ENCRYPT_OFFSET; + + if (!strcmp(type, "full")) { + ret = asprintf(&str, "Blocks = 0x%08x 0 %d \"%s\"\n", + data->image_load_addr, signed_size, + data->outfile); + } else if (!strcmp(type, "from-dcdofs")) { + ret = asprintf(&str, "Blocks = 0x%08x 0x%x %d \"%s\"\n", + data->image_load_addr + data->image_dcd_offset, + data->image_dcd_offset, + signed_size - data->image_dcd_offset, + data->outfile); + } else if (!strcmp(type, "skip-mbr")) { + ret = asprintf(&str, + "Blocks = 0x%08x 0 440 \"%s\", \\\n" + " 0x%08x 512 %d \"%s\"\n", + data->image_load_addr, data->outfile, + data->image_load_addr + 512, + signed_size - 512, data->outfile); + } else { + fprintf(stderr, "Invalid hab_blocks option: %s\n", type); + return -EINVAL; + } + + if (ret < 0) + return -ENOMEM; + + ret = hab_add_str(data, str); + if (ret) + return ret; + + return 0; +} + +static int do_hab_encrypt(struct config_data *data, int argc, char *argv[]) +{ + if (!data->encrypt_image) + return 0; + + return do_hab(data, argc, argv); +} + +static int do_hab_encrypt_key(struct config_data *data, int argc, char *argv[]) +{ + char *str; + char *dekfile; + int ret; + + if (!data->csf) + return -EINVAL; + + if (!data->encrypt_image) + return 0; + + ret = asprintf(&dekfile, "%s.dek", data->outfile); + if (ret < 0) + return -ENOMEM; + + ret = asprintf(&str, "Key = \"%s\"\n", dekfile); + if (ret < 0) + return -ENOMEM; + + ret = hab_add_str(data, str); + if (ret) + return ret; + + return 0; +} + +static int do_hab_encrypt_key_length(struct config_data *data, int argc, + char *argv[]) +{ + unsigned int dek_bits; + char *str; + int ret; + + if (!data->csf) + return -EINVAL; + + if (!data->encrypt_image) + return 0; + + if (argc < 2) + return -EINVAL; + + dek_bits = strtoul(argv[1], NULL, 0); + + if (dek_bits != 128 && dek_bits != 192 && dek_bits != 256) { + fprintf(stderr, "wrong dek size (%u)\n", dek_bits); + return -EINVAL; + } + + data->dek_size = dek_bits / 8; + + ret = asprintf(&str, "Key Length = %u\n", dek_bits); + if (ret < 0) + return -ENOMEM; + + ret = hab_add_str(data, str); + if (ret) + return ret; + + return 0; +} + +static int do_hab_encrypt_blob_address(struct config_data *data, int argc, + char *argv[]) +{ char *str; int ret; if (!data->csf) return -EINVAL; - ret = asprintf(&str, "Blocks = 0x%08x 0 %d \"%s\"\n", - data->image_load_addr, - data->load_size, data->outfile); + if (!data->encrypt_image) + return 0; + + ret = asprintf(&str, + "Blob address = 0x%08zx\n", + data->image_load_addr + data->load_size + CSF_LEN - + (DEK_BLOB_OVERHEAD + data->dek_size)); + if (ret < 0) + return -ENOMEM; + + ret = hab_add_str(data, str); + if (ret) + return ret; + + return 0; +} + +static int do_hab_encrypt_blocks(struct config_data *data, int argc, + char *argv[]) +{ + char *str; + int ret; + + if (!data->csf) + return -EINVAL; + + if (!data->encrypt_image) + return 0; + + ret = asprintf(&str, "Blocks = 0x%08x 0x%x %d \"%s\"\n", + data->image_load_addr + ENCRYPT_OFFSET, ENCRYPT_OFFSET, + data->load_size - ENCRYPT_OFFSET, data->outfile); if (ret < 0) return -ENOMEM; @@ -435,6 +597,21 @@ struct command cmds[] = { .name = "hab_blocks", .parse = do_hab_blocks, }, { + .name = "hab_encrypt", + .parse = do_hab_encrypt, + }, { + .name = "hab_encrypt_key", + .parse = do_hab_encrypt_key, + }, { + .name = "hab_encrypt_key_length", + .parse = do_hab_encrypt_key_length, + }, { + .name = "hab_encrypt_blob_address", + .parse = do_hab_encrypt_blob_address, + }, { + .name = "hab_encrypt_blocks", + .parse = do_hab_encrypt_blocks, + }, { .name = "super_root_key", .parse = do_super_root_key, }, { |