From 7d6210e4b1fd5ed16a671a07aaa14a98a9f7c33c Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Thu, 4 Jun 2020 16:50:22 +0900 Subject: [PATCH] sbsign: allow for adding intermediate certificates SignedData can have multiple certificates, but the current implementation of sbsign only allows a single one (as a signer). With this patch, "-addcert" options will be available on command line to specify a file in which any number of intermediate certificates in PEM format can be concatenated. $ sign --key --cert --addcert [...] image_file Background: I'm working on implementing UEFI secure boot on U-Boot and want to test my code against PE images with intermediate certificates in certificate chain. As far as I know, the only tool that supports it in signing is Microsoft's signtool.exe. So I'd like to have some corresponding tool on linux. Signed-off-by: AKASHI Takahiro Signed-off-by: James Bottomley --- src/sbsign.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) diff --git a/src/sbsign.c b/src/sbsign.c index ff1fdfd..92607a7 100644 --- a/src/sbsign.c +++ b/src/sbsign.c @@ -49,6 +49,8 @@ #include #include #include +#include +#include #include @@ -75,6 +77,7 @@ static struct option options[] = { { "help", no_argument, NULL, 'h' }, { "version", no_argument, NULL, 'V' }, { "engine", required_argument, NULL, 'e'}, + { "addcert", required_argument, NULL, 'a'}, { NULL, 0, NULL, 0 }, }; @@ -88,6 +91,7 @@ static void usage(void) "\t--key signing key (PEM-encoded RSA " "private key)\n" "\t--cert certificate (x509 certificate)\n" + "\t--addcert additional intermediate certificates in a file\n" "\t--detached write a detached signature, instead of\n" "\t a signed binary\n" "\t--output write signed data to \n" @@ -112,9 +116,43 @@ static void set_default_outfilename(struct sign_context *ctx) ctx->infilename, extension); } +static int add_intermediate_certs(PKCS7 *p7, const char *filename) +{ + STACK_OF(X509_INFO) *certs; + X509_INFO *cert; + BIO *bio = NULL; + int i; + + bio = BIO_new(BIO_s_file()); + if (!bio || BIO_read_filename(bio, filename) <=0) { + fprintf(stderr, + "error in reading intermediate certificates file\n"); + ERR_print_errors_fp(stderr); + return -1; + } + + certs = PEM_X509_INFO_read_bio(bio, NULL, NULL, NULL); + if (!certs) { + fprintf(stderr, + "error in parsing intermediate certificates file\n"); + ERR_print_errors_fp(stderr); + return -1; + } + + for (i = 0; i < sk_X509_INFO_num(certs); i++) { + cert = sk_X509_INFO_value(certs, i); + PKCS7_add_certificate(p7, cert->x509); + } + + sk_X509_INFO_pop_free(certs, X509_INFO_free); + BIO_free_all(bio); + + return 0; +} + int main(int argc, char **argv) { - const char *keyfilename, *certfilename, *engine; + const char *keyfilename, *certfilename, *addcertfilename, *engine; struct sign_context *ctx; uint8_t *buf, *tmp; int rc, c, sigsize; @@ -124,11 +162,12 @@ int main(int argc, char **argv) keyfilename = NULL; certfilename = NULL; + addcertfilename = NULL; engine = NULL; for (;;) { int idx; - c = getopt_long(argc, argv, "o:c:k:dvVhe:", options, &idx); + c = getopt_long(argc, argv, "o:c:k:dvVhe:a:", options, &idx); if (c == -1) break; @@ -157,6 +196,9 @@ int main(int argc, char **argv) case 'e': engine = optarg; break; + case 'a': + addcertfilename = optarg; + break; } } @@ -189,6 +231,7 @@ int main(int argc, char **argv) talloc_steal(ctx, ctx->image); ERR_load_crypto_strings(); + ERR_load_BIO_strings(); OpenSSL_add_all_digests(); OpenSSL_add_all_ciphers(); OPENSSL_config(NULL); @@ -228,6 +271,9 @@ int main(int argc, char **argv) if (rc) return EXIT_FAILURE; + if (addcertfilename && add_intermediate_certs(p7, addcertfilename)) + return EXIT_FAILURE; + sigsize = i2d_PKCS7(p7, NULL); tmp = buf = talloc_array(ctx->image, uint8_t, sigsize); i2d_PKCS7(p7, &tmp);