rimage: add functionality to resign fw image

Add function to resign already signed images. This can
be done with switch "q" as follows:

"rimage -q sof-tgl.ri -o sof-tgl-mod.ri -c tgl.toml -k key.pem"

Signed-off-by: Jaska Uimonen <jaska.uimonen@linux.intel.com>
This commit is contained in:
Jaska Uimonen 2021-11-16 09:50:21 +02:00 committed by Liam Girdwood
parent bcbcec79e5
commit bd51ec1aef
4 changed files with 173 additions and 1 deletions

View File

@ -73,6 +73,7 @@ struct module {
struct image {
const char *out_file;
const char *in_file;
FILE *out_fd;
void *pos;
@ -201,6 +202,9 @@ int pkcs_v1_5_verify_man_v2_5(struct image *image,
void *ptr1, unsigned int size1, void *ptr2,
unsigned int size2);
int resign_image(struct image *image);
int get_key_size(struct image *image);
int elf_parse_module(struct image *image, int module_index, const char *name);
void elf_free_module(struct image *image, int module_index);
int elf_is_rom(struct image *image, Elf32_Shdr *section);

View File

@ -1427,3 +1427,127 @@ out:
fclose(in_file);
return 0;
}
int resign_image(struct image *image)
{
int key_size, key_file_size;
size_t size, read;
FILE *in_file;
void *buffer;
int ret, i;
/* open image for reading */
in_file = fopen(image->in_file, "rb");
if (!in_file) {
fprintf(stderr, "error: unable to open %s for reading %d\n",
image->in_file, errno);
return -errno;
}
/* get file size */
ret = fseek(in_file, 0, SEEK_END);
if (ret < 0) {
fprintf(stderr, "error: unable to seek eof %s for reading %d\n",
image->verify_file, errno);
ret = -errno;
goto out;
}
size = ftell(in_file);
if (size < 0) {
fprintf(stderr, "error: unable to get file size for %s %d\n",
image->verify_file, errno);
ret = -errno;
goto out;
}
ret = fseek(in_file, 0, SEEK_SET);
if (ret < 0) {
fprintf(stderr, "error: unable to seek %s for reading %d\n",
image->verify_file, errno);
ret = -errno;
goto out;
}
/* allocate buffer for parsing */
buffer = malloc(size);
if (!buffer) {
ret = -ENOMEM;
goto out;
}
/* read file into buffer */
read = fread(buffer, 1, size, in_file);
if (read != size) {
fprintf(stderr, "error: unable to read %ld bytes from %s err %d\n",
size, image->in_file, errno);
ret = errno;
goto out;
}
fclose(in_file);
for (i = 0; i < size; i += sizeof(uint32_t)) {
/* find CSE header marker "$CPD" */
if (*(uint32_t *)(buffer + i) == CSE_HEADER_MAKER) {
image->fw_image = buffer + i;
break;
}
}
if (i >= size) {
fprintf(stderr, "error: didn't found header marker %d\n", i);
ret = -EINVAL;
goto out;
}
image->image_end = size;
/* check that key size matches */
if (image->adsp->man_v2_5) {
key_size = 384;
} else {
key_size = 256;
}
key_file_size = get_key_size(image);
if (key_file_size > key_size) {
fprintf(stderr, "error: key size %d is longer than original key %d\n",
key_file_size, key_size);
ret = -EINVAL;
goto out;
}
/* resign */
if (image->adsp->man_v1_5)
ret = ri_manifest_sign_v1_5(image);
else if (image->adsp->man_v1_8)
ret = ri_manifest_sign_v1_8(image);
else if (image->adsp->man_v2_5)
ret = ri_manifest_sign_v2_5(image);
else
ret = -EINVAL;
if (ret < 0) {
fprintf(stderr, "error: unable to sign image\n");
goto out;
}
/* open outfile for writing */
unlink(image->out_file);
image->out_fd = fopen(image->out_file, "wb");
if (!image->out_fd) {
fprintf(stderr, "error: unable to open %s for writing %d\n",
image->out_file, errno);
ret = -EINVAL;
goto out;
}
man_write_fw_mod(image);
out:
free(buffer);
return ret;
}

View File

@ -694,3 +694,38 @@ int ri_manifest_verify_v2_5(struct image *image)
return pkcs_v1_5_verify_man_v2_5(image, man, data1, size1, data2, size2);
}
int get_key_size(struct image *image)
{
RSA *priv_rsa = NULL;
EVP_PKEY *privkey;
FILE *fp;
int key_length;
char path[256];
/* require private key */
if (!image->key_name) {
return -EINVAL;
}
/* load in RSA private key from PEM file */
memset(path, 0, sizeof(path));
strncpy(path, image->key_name, sizeof(path) - 1);
fp = fopen(path, "rb");
if (!fp) {
fprintf(stderr, "error: can't open file %s %d\n",
path, -errno);
return -errno;
}
PEM_read_PrivateKey(fp, &privkey, NULL, NULL);
fclose(fp);
priv_rsa = EVP_PKEY_get1_RSA(privkey);
key_length = RSA_size(priv_rsa);
RSA_free(priv_rsa);
EVP_PKEY_free(privkey);
return key_length;
}

View File

@ -30,6 +30,7 @@ static void usage(char *name)
fprintf(stdout, "\t -b build version\n");
fprintf(stdout, "\t -e build extended manifest\n");
fprintf(stdout, "\t -y verify signed file\n");
fprintf(stdout, "\t -q resign binary\n");
}
int main(int argc, char *argv[])
@ -43,7 +44,7 @@ int main(int argc, char *argv[])
memset(&image, 0, sizeof(image));
while ((opt = getopt(argc, argv, "ho:va:s:k:ri:x:f:b:ec:y:")) != -1) {
while ((opt = getopt(argc, argv, "ho:va:s:k:ri:x:f:b:ec:y:q:")) != -1) {
switch (opt) {
case 'o':
image.out_file = optarg;
@ -84,6 +85,9 @@ int main(int argc, char *argv[])
case 'h':
usage(argv[0]);
return 0;
case 'q':
image.in_file = optarg;
break;
default:
/* getopt's default error message is good enough */
return 1;
@ -152,6 +156,11 @@ int main(int argc, char *argv[])
goto out;
}
if (image.in_file) {
fprintf(stdout, "going to re-sign\n");
return resign_image(&image);
}
/* set IMR Type in found machine definition */
if (image.adsp->man_v1_8)
image.adsp->man_v1_8->adsp_file_ext.imr_type = imr_type;