From d957e0368b8671ca52fed422ffe9384e8f899de8 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Tue, 27 Sep 2022 08:36:00 +0300 Subject: [PATCH] rimage: make ace15 signing to support openssl3 Ace signing is currently missing openssl3 support, so let's add it. Signed-off-by: Jaska Uimonen --- src/include/rimage/rimage.h | 10 +- src/pkcs1_5.c | 236 +++++++++++++++++++----------------- 2 files changed, 129 insertions(+), 117 deletions(-) diff --git a/src/include/rimage/rimage.h b/src/include/rimage/rimage.h index 0f719dc5b..e4117f3f3 100644 --- a/src/include/rimage/rimage.h +++ b/src/include/rimage/rimage.h @@ -190,9 +190,9 @@ int pkcs_v1_5_sign_man_v2_5(struct image *image, void *ptr1, unsigned int size1, void *ptr2, unsigned int size2); int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, - struct fw_image_manifest_ace_v1_5 *man, - void *ptr1, unsigned int size1, void *ptr2, - unsigned int size2); + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); int verify_image(struct image *image); int ri_manifest_verify_v1_5(struct image *image); @@ -209,6 +209,10 @@ int pkcs_v1_5_verify_man_v2_5(struct image *image, struct fw_image_manifest_v2_5 *man, void *ptr1, unsigned int size1, void *ptr2, unsigned int size2); +int pkcs_v1_5_verify_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2); int resign_image(struct image *image); int get_key_size(struct image *image); diff --git a/src/pkcs1_5.c b/src/pkcs1_5.c index 23bb0f4a6..2f58b8720 100644 --- a/src/pkcs1_5.c +++ b/src/pkcs1_5.c @@ -29,7 +29,8 @@ enum manver { V15 = 0, V18 = 1, - V25 = 2 + V25 = 2, + VACE15 = 3 }; static void bytes_swap(uint8_t *ptr, uint32_t size) @@ -183,6 +184,8 @@ static int rimage_sign(EVP_PKEY *privkey, struct image *image, enum manver ver, signature, &siglen, priv_rsa); break; case V25: + /* fallthrough */ + case VACE15: ret = RSA_padding_add_PKCS1_PSS(priv_rsa, sig, digest, image->md, /* salt length */ 32); if (ret > 0) @@ -212,7 +215,7 @@ static int rimage_sign(EVP_PKEY *privkey, struct image *image, enum manver ver, if (ret <= 0) goto out; - if (ver == V25) { + if (ver == V25 || ver == VACE15) { ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); if (ret <= 0) { fprintf(stderr, "error: failed to set rsa padding\n"); @@ -281,6 +284,8 @@ static int rimage_verify(EVP_PKEY *privkey, struct image *image, enum manver ver } break; case V25: + /* fallthrough */ + case VACE15: /* decrypt signature */ ret = RSA_public_decrypt(RSA_size(priv_rsa), signature, sig, priv_rsa, RSA_NO_PADDING); @@ -339,6 +344,8 @@ static int rimage_verify(EVP_PKEY *privkey, struct image *image, enum manver ver break; case V25: + /* fallthrough */ + case VACE15: ret = EVP_PKEY_CTX_set_rsa_padding(ctx, RSA_PKCS1_PSS_PADDING); if (ret <= 0) goto out; @@ -523,118 +530,6 @@ int pkcs_v1_5_sign_man_v1_8(struct image *image, return ret; } -/* - * RSA signature of manifest. The signature is an RSA PSS - * of the entire manifest structure, including all - * extensions, and excluding the last 3 fields of the - * manifest header (Public Key, Exponent and Signature). - */ -#if OPENSSL_VERSION_NUMBER < 0x30000000L -int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, - struct fw_image_manifest_ace_v1_5 *man, - void *ptr1, unsigned int size1, void *ptr2, - unsigned int size2) -{ - RSA *priv_rsa = NULL; - EVP_PKEY *privkey; - FILE *fp; - const BIGNUM *n, *e, *d; - unsigned char digest[SHA384_DIGEST_LENGTH]; - unsigned char mod[MAN_RSA_KEY_MODULUS_LEN_2_5]; - unsigned char sig[MAN_RSA_SIGNATURE_LEN_2_5]; - char path[256]; - int ret = -EINVAL, i; - -#if DEBUG_PKCS - fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", - ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); -#endif - - /* require private key */ - if (!image->key_name) { - return -EINVAL; - } - - /* create new PSS key */ - privkey = EVP_PKEY_new(); - if (!privkey) - return -ENOMEM; - - /* load in RSA private key from PEM file */ - memset(path, 0, sizeof(path)); - strncpy(path, image->key_name, sizeof(path) - 1); - - fprintf(stdout, " pkcs: PSS signing with key %s\n", path); - 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); - - /* validate RSA private key */ - priv_rsa = EVP_PKEY_get1_RSA(privkey); - if (RSA_check_key(priv_rsa)) { - fprintf(stdout, " pkcs: RSA private key is valid.\n"); - } else { - fprintf(stderr, "error: validating RSA private key.\n"); - return -EINVAL; - } - - /* calculate the digest - SHA384 on CAVS2_5+ */ - module_sha384_create(image); - module_sha_update(image, ptr1, size1); - module_sha_update(image, ptr2, size2); - module_sha_complete(image, digest); - - fprintf(stdout, " pkcs: digest for manifest is "); - for (i = 0; i < SHA384_DIGEST_LENGTH; i++) - fprintf(stdout, "%02x", digest[i]); - fprintf(stdout, "\n"); - - /* sign the manifest */ - ret = RSA_padding_add_PKCS1_PSS(priv_rsa, sig, - digest, image->md, /* salt length */ 32); - if (ret <= 0) { - ERR_error_string(ERR_get_error(), path); - fprintf(stderr, "error: failed to sign manifest %s\n", path); - } - - /* encrypt the signature using the private key */ - ret = RSA_private_encrypt(RSA_size(priv_rsa), sig, - (unsigned char *)man->css.signature, priv_rsa, RSA_NO_PADDING); - if (ret <= 0) { - ERR_error_string(ERR_get_error(), path); - fprintf(stderr, "error: failed to encrypt signature %s\n", path); - } - - /* copy public key modulus and exponent to manifest */ - RSA_get0_key(priv_rsa, &n, &e, &d); - BN_bn2bin(n, mod); - BN_bn2bin(e, (unsigned char *)man->css.exponent); - - /* modulus is reversed */ - for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN_2_5; i++) - man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN_2_5 - (1 + i)]; - - /* signature is reversed, swap it */ - bytes_swap(man->css.signature, sizeof(man->css.signature)); - - EVP_PKEY_free(privkey); - return ret; -} -#else -int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, - struct fw_image_manifest_ace_v1_5 *man, - void *ptr1, unsigned int size1, void *ptr2, - unsigned int size2) -{ - return -EINVAL; -} -#endif - int pkcs_v1_5_sign_man_v2_5(struct image *image, struct fw_image_manifest_v2_5 *man, void *ptr1, unsigned int size1, void *ptr2, @@ -695,6 +590,66 @@ int pkcs_v1_5_sign_man_v2_5(struct image *image, return ret; } +int pkcs_v1_5_sign_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + unsigned char digest[SHA384_DIGEST_LENGTH]; + unsigned char mod[MAN_RSA_KEY_MODULUS_LEN_2_5]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + module_sha384_create(image); + module_sha_update(image, ptr1, size1); + module_sha_update(image, ptr2, size2); + module_sha_complete(image, digest); + + fprintf(stdout, " pkcs: digest for manifest is "); + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) + fprintf(stdout, "%02x", digest[i]); + fprintf(stdout, "\n"); + + /* sign the manifest */ + ret = rimage_sign(privkey, image, VACE15, digest, + (unsigned char *)man->css.signature); + if (ret <= 0) { + fprintf(stderr, "error: failed to sign manifest\n"); + return ret; + } + + /* copy public key modulus and exponent to manifest */ + rimage_set_modexp(privkey, mod, (unsigned char *)man->css.exponent); + + /* modulus is reversed */ + for (i = 0; i < MAN_RSA_KEY_MODULUS_LEN_2_5; i++) + man->css.modulus[i] = mod[MAN_RSA_KEY_MODULUS_LEN_2_5 - (1 + i)]; + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + + EVP_PKEY_free(privkey); + return ret; +} + int ri_manifest_sign_v1_5(struct image *image) { struct fw_image_manifest_v1_5 *man = image->fw_image; @@ -935,6 +890,59 @@ int pkcs_v1_5_verify_man_v2_5(struct image *image, return ret; } +int pkcs_v1_5_verify_man_ace_v1_5(struct image *image, + struct fw_image_manifest_ace_v1_5 *man, + void *ptr1, unsigned int size1, void *ptr2, + unsigned int size2) +{ + EVP_PKEY *privkey; + unsigned char digest[SHA384_DIGEST_LENGTH]; + int ret = -EINVAL, i; + +#if DEBUG_PKCS + fprintf(stdout, "offsets 0x%lx size 0x%x offset 0x%lx size 0x%x\n", + ptr1 - (void *)man, size1, ptr2 - (void *)man, size2); +#endif + + ret = rimage_read_key(&privkey, image); + if (ret < 0) + return ret; + + /* validate RSA private key */ + if (rimage_check_key(privkey) > 0) { + fprintf(stdout, " pkcs: RSA private key is valid.\n"); + } else { + fprintf(stderr, "error: validating RSA private key.\n"); + return -EINVAL; + } + + /* calculate the digest - SHA384 on CAVS2_5+ */ + module_sha384_create(image); + module_sha_update(image, ptr1, size1); + module_sha_update(image, ptr2, size2); + module_sha_complete(image, digest); + + fprintf(stdout, " pkcs: digest for manifest is "); + for (i = 0; i < SHA384_DIGEST_LENGTH; i++) + fprintf(stdout, "%02x", digest[i]); + fprintf(stdout, "\n"); + + /* signature is reversed, swap it */ + bytes_swap(man->css.signature, sizeof(man->css.signature)); + + /* verify */ + ret = rimage_verify(privkey, image, VACE15, digest, + (unsigned char *)man->css.signature); + + if (ret <= 0) + fprintf(stderr, "error: failed to verify manifest\n"); + else + fprintf(stdout, "pkcs: signature is valid !\n"); + + EVP_PKEY_free(privkey); + return ret; +} + int ri_manifest_verify_v1_5(struct image *image) { struct fw_image_manifest_v1_5 *man = image->fw_image;