[PATCH 1/4] tools: mkeficapsule: add firmwware image signing

Masami Hiramatsu masami.hiramatsu at linaro.org
Thu May 13 08:44:24 CEST 2021


Hi Heinrich,

2021年5月13日(木) 14:50 Heinrich Schuchardt <xypron.glpk at gmx.de>:
>
> On 5/13/21 7:12 AM, Masami Hiramatsu wrote:
> > Hi Heinrich,
> >
> > 2021年5月13日(木) 13:22 Heinrich Schuchardt <xypron.glpk at gmx.de>:
> >>
> >> On 5/13/21 5:08 AM, AKASHI Takahiro wrote:
> >>> On Wed, May 12, 2021 at 10:56:41AM +0200, Heinrich Schuchardt wrote:
> >>>> On 12.05.21 06:57, AKASHI Takahiro wrote:
> >>>>> With this enhancement, mkeficapsule will be able to create a capsule
> >>>>> file with a signature which will be verified later by FMP's SetImage().
> >>>>>
> >>>>> We will have to specify addtional command parameters:
> >>>>>     -monotonic-cout <count> : monotonic count
> >>>>>     -private-key <private key file> : private key file
> >>>>>     -certificate <certificate file> : certificate file
> >>>>> Only when those parameters are given, a signature will be added
> >>>>> to a capsule file.
> >>>>>
> >>>>> Users are expected to maintain the monotonic count for each firmware
> >>>>> image.
> >>>>>
> >>>>> Signed-off-by: AKASHI Takahiro <takahiro.akashi at linaro.org>
> >>>>> ---
> >>>>>    tools/Makefile       |   4 +
> >>>>>    tools/mkeficapsule.c | 324 +++++++++++++++++++++++++++++++++++++++----
> >>>>>    2 files changed, 303 insertions(+), 25 deletions(-)
> >>>>>
> >>>>> diff --git a/tools/Makefile b/tools/Makefile
> >>>>> index d020c55d6644..02eae0286e20 100644
> >>>>> --- a/tools/Makefile
> >>>>> +++ b/tools/Makefile
> >>>>> @@ -231,6 +231,10 @@ hostprogs-$(CONFIG_MIPS) += mips-relocs
> >>>>>    hostprogs-$(CONFIG_ASN1_COMPILER) += asn1_compiler
> >>>>>    HOSTCFLAGS_asn1_compiler.o = -idirafter $(srctree)/include
> >>>>>
> >>>>> +ifneq ($(CONFIG_EFI_CAPSULE_AUTHENTICATE),)
> >>>>> +HOSTLDLIBS_mkeficapsule += \
> >>>>> +   $(shell pkg-config --libs libssl libcrypto 2> /dev/null || echo "-lssl -lcrypto")
> >>>>
> >>>> I don't expect any user wants to install two tool versions in parallel.
> >>>>
> >>>> The tool should always be able to add a signature.
> >>>> Adding a signature must be optional.
> >>>
> >>> It seems to me that those two statements mutually contradict.
> >>> Or do you intend to say that we should have a separate kconfig
> >>> option to enable/disable signing feature in mkeficapsule?
> >>>
> >>> If so, I can agree.
> >>>
> >>> In either way, we should have an option to turn on/off this functionality
> >>> as not all users use signed capsules.
> >>
> >> I want to have a single binary to distribute with Linux distros (e.g.
> >> Debian/Ubuntu package u-boot-tools).
> >
> > I couldn't catch your point. If so, the distros can build u-boot with
> > CONFIG_EFI_CAPSULE_AUTHENTICATE=y...
>
> Why should the tool depend on board configuration?

Yeah, at this point I agreed. I think there should be a separated CONFIG
for tools or forcibly link those libraries. (I think most people don't
mind if it requires new libraries to be built, that usually happens.)

> Who would want capsule updates without authentication?

Hm, so you think even CONFIG_EFI_CAPSULE_AUTHENTICATE is
only for development. Capsule must be signed, right?
Then, all distro should build u-boot with
CONFIG_EFI_CAPSULE_AUTHENTICATE=y, isn't it?

> > BTW, IMHO, if u-boot.bin can not find the ESL in the device tree,
> > it should skip authentication too.
>
> In this case the capsule should be rejected (if
> CONFIG_EFI_CAPSULE_AUTHENTICATE=y).

I meant U-Boot has NO key to authenticate the capsule. I think in that
case U-Boot build process must require the key (ESL) and if user doesn't
provide it, the build should fail (if it doesn't skip capsule authentication.)
Or, we have no way to update U-Boot anymore.

> > Then, user can choose whether enabling capsule authentication or not
> > by embedding ESL into their devicetree.
>
> The user shall not be able to decide anything that might hamper
> security. The U-Boot binary must dictate if a capsule is safe.

Hmm, I think the root issue is that the ESL embedding process is not
integrated into the build process yet. For the safe capsule update,
we must enable capsule authentication with keys. (unsafe one is only
for testing/development)
Moreover, the key is stored in the U-Boot itself OR, in the secure storage
outside of U-Boot (Hardware OTP or TPM/HSM are preferable.)

Thus,
CONFIG_EFI_CAPSULE_AUTHENTICATE must depend on (or select)
a new config which points the path for the ESL file (this is embedded while
the build process), OR, the platform driver provides key from its hardware
secure storage.

What would you think about this idea?

Thank you,

>
> Best regards
>
> Heinrich
>
> >
> > Thank you
> >
> >>
> >> This should allow both
> >>
> >> - create signed capsules
> >> - create unsigned capsules
> >>
> >> The user shall select signing via command line parameters.
> >>
> >> Support for signing via the tool shall not depend on board Kconfig
> >> parameters.
> >>
> >> Best regards
> >>
> >> Heinrich
> >>
> >>>
> >>>>> +endif
> >>>>>    mkeficapsule-objs := mkeficapsule.o $(LIBFDT_OBJS)
> >>>>>    hostprogs-$(CONFIG_EFI_HAVE_CAPSULE_SUPPORT) += mkeficapsule
> >>>>>
> >>>>> diff --git a/tools/mkeficapsule.c b/tools/mkeficapsule.c
> >>>>> index de0a62898886..34ff1bdd82eb 100644
> >>>>> --- a/tools/mkeficapsule.c
> >>>>> +++ b/tools/mkeficapsule.c
> >>>>> @@ -18,7 +18,17 @@
> >>>>>    #include <sys/stat.h>
> >>>>>    #include <sys/types.h>
> >>>>>
> >>>>> -#include "fdt_host.h"
> >>>>> +#include <linux/kconfig.h>
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>>> +#include <openssl/asn1.h>
> >>>>> +#include <openssl/bio.h>
> >>>>> +#include <openssl/evp.h>
> >>>>> +#include <openssl/err.h>
> >>>>> +#include <openssl/pem.h>
> >>>>> +#include <openssl/pkcs7.h>
> >>>>> +#endif
> >>>>> +
> >>>>> +#include <linux/libfdt.h>
> >>>>>
> >>>>>    typedef __u8 u8;
> >>>>>    typedef __u16 u16;
> >>>>> @@ -46,6 +56,13 @@ efi_guid_t efi_guid_image_type_uboot_fit =
> >>>>>              EFI_FIRMWARE_IMAGE_TYPE_UBOOT_FIT_GUID;
> >>>>>    efi_guid_t efi_guid_image_type_uboot_raw =
> >>>>>              EFI_FIRMWARE_IMAGE_TYPE_UBOOT_RAW_GUID;
> >>>>> +efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
> >>>>> +
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>>> +static const char *opts_short = "f:r:i:I:v:D:K:P:C:m:dOh";
> >>>>> +#else
> >>>>> +static const char *opts_short = "f:r:i:I:v:D:K:Oh";
> >>>>> +#endif
> >>>>>
> >>>>>    static struct option options[] = {
> >>>>>      {"fit", required_argument, NULL, 'f'},
> >>>>> @@ -54,6 +71,12 @@ static struct option options[] = {
> >>>>>      {"instance", required_argument, NULL, 'I'},
> >>>>>      {"dtb", required_argument, NULL, 'D'},
> >>>>>      {"public key", required_argument, NULL, 'K'},
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>> +   {"private-key", required_argument, NULL, 'P'},
> >>>>> +   {"certificate", required_argument, NULL, 'C'},
> >>>>> +   {"monotonic-count", required_argument, NULL, 'm'},
> >>>>
> >>>> These options should not be required.
> >>>
> >>> I don't get you. What do you mean?
> >>>
> >>>>> +   {"dump-sig", no_argument, NULL, 'd'},
> >>>>> +#endif
> >>>>>      {"overlay", no_argument, NULL, 'O'},
> >>>>>      {"help", no_argument, NULL, 'h'},
> >>>>>      {NULL, 0, NULL, 0},
> >>>>> @@ -70,6 +93,12 @@ static void print_usage(void)
> >>>>>             "\t-I, --instance <instance>   update hardware instance\n"
> >>>>>             "\t-K, --public-key <key file> public key esl file\n"
> >>>>>             "\t-D, --dtb <dtb file>        dtb file\n"
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>>> +          "\t-P, --private-key <privkey file>  private key file\n"
> >>>>> +          "\t-C, --certificate <cert file>     signer's certificate file\n"
> >>>>> +          "\t-m, --monotonic-count <count>     monotonic count\n"
> >>>>> +          "\t-d, --dump_sig              dump signature (*.p7)\n"
> >>>>> +#endif
> >>>>>             "\t-O, --overlay               the dtb file is an overlay\n"
> >>>>>             "\t-h, --help                  print a help message\n",
> >>>>>             tool_name);
> >>>>> @@ -249,12 +278,167 @@ err:
> >>>>>      return ret;
> >>>>>    }
> >>>>>
> >>>>> +struct auth_context {
> >>>>> +   char *key_file;
> >>>>> +   char *cert_file;
> >>>>> +   u8 *image_data;
> >>>>> +   size_t image_size;
> >>>>> +   struct efi_firmware_image_authentication auth;
> >>>>> +   u8 *sig_data;
> >>>>> +   size_t sig_size;
> >>>>> +};
> >>>>> +
> >>>>> +static int dump_sig;
> >>>>> +
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>>> +static EVP_PKEY *fileio_read_pkey(const char *filename)
> >>>>> +{
> >>>>> +   EVP_PKEY *key = NULL;
> >>>>> +   BIO *bio;
> >>>>> +
> >>>>> +   bio = BIO_new_file(filename, "r");
> >>>>> +   if (!bio)
> >>>>> +           goto out;
> >>>>> +
> >>>>> +   key = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
> >>>>> +
> >>>>> +out:
> >>>>> +   BIO_free_all(bio);
> >>>>> +   if (!key) {
> >>>>> +           printf("Can't load key from file '%s'\n", filename);
> >>>>
> >>>> Please, you use fprintf(stderr,) for error messages.
> >>>>
> >>>>> +           ERR_print_errors_fp(stderr);
> >>>>> +   }
> >>>>> +
> >>>>> +   return key;
> >>>>> +}
> >>>>> +
> >>>>> +static X509 *fileio_read_cert(const char *filename)
> >>>>> +{
> >>>>> +   X509 *cert = NULL;
> >>>>> +   BIO *bio;
> >>>>> +
> >>>>> +   bio = BIO_new_file(filename, "r");
> >>>>> +   if (!bio)
> >>>>> +           goto out;
> >>>>> +
> >>>>> +   cert = PEM_read_bio_X509(bio, NULL, NULL, NULL);
> >>>>> +
> >>>>> +out:
> >>>>> +   BIO_free_all(bio);
> >>>>> +   if (!cert) {
> >>>>> +           printf("Can't load certificate from file '%s'\n", filename);
> >>>>
> >>>> fprintf(stderr,)
> >>>>
> >>>>> +           ERR_print_errors_fp(stderr);
> >>>>> +   }
> >>>>> +
> >>>>> +   return cert;
> >>>>> +}
> >>>>> +
> >>>>> +static int create_auth_data(struct auth_context *ctx)
> >>>>> +{
> >>>>> +   EVP_PKEY *key = NULL;
> >>>>> +   X509 *cert = NULL;
> >>>>> +   BIO *data_bio = NULL;
> >>>>> +   const EVP_MD *md;
> >>>>> +   PKCS7 *p7;
> >>>>> +   int flags, ret = -1;
> >>>>> +
> >>>>> +   OpenSSL_add_all_digests();
> >>>>> +   OpenSSL_add_all_ciphers();
> >>>>> +   ERR_load_crypto_strings();
> >>>>> +
> >>>>> +   key = fileio_read_pkey(ctx->key_file);
> >>>>> +   if (!key)
> >>>>> +           goto err;
> >>>>> +   cert = fileio_read_cert(ctx->cert_file);
> >>>>> +   if (!cert)
> >>>>> +           goto err;
> >>>>> +
> >>>>> +   /*
> >>>>> +    * create a BIO, containing:
> >>>>> +    *  * firmware image
> >>>>> +    *  * monotonic count
> >>>>> +    * in this order!
> >>>>> +    * See EDK2's FmpAuthenticatedHandlerRsa2048Sha256()
> >>>>> +    */
> >>>>> +   data_bio = BIO_new(BIO_s_mem());
> >>>>> +   BIO_write(data_bio, ctx->image_data, ctx->image_size);
> >>>>> +   BIO_write(data_bio, &ctx->auth.monotonic_count,
> >>>>> +             sizeof(ctx->auth.monotonic_count));
> >>>>> +
> >>>>> +   md = EVP_get_digestbyname("SHA256");
> >>>>> +   if (!md)
> >>>>> +           goto err;
> >>>>> +
> >>>>> +   /* create signature */
> >>>>> +   /* TODO: maybe add PKCS7_NOATTR and PKCS7_NOSMIMECAP */
> >>>>
> >>>> PKCS7_NOATTR is a value without any documentation in the code.
> >>>
> >>> Nak.
> >>> Those macros are part of openssl library. See openssl/pkcs7.h.
> >>>
> >>>> Please, replace variable names by a long text describing what it missing.
> >>>>
> >>>>> +   flags = PKCS7_BINARY | PKCS7_DETACHED;
> >>>>
> >>>> Those constants lack documentation in the code.
> >>>
> >>> Nak again.
> >>>
> >>>>> +   p7 = PKCS7_sign(NULL, NULL, NULL, data_bio, flags | PKCS7_PARTIAL);
> >>>>> +   if (!p7)
> >>>>> +           goto err;
> >>>>> +   if (!PKCS7_sign_add_signer(p7, cert, key, md, flags))
> >>>>> +           goto err;
> >>>>> +   if (!PKCS7_final(p7, data_bio, flags))
> >>>>> +           goto err;
> >>>>> +
> >>>>> +   /* convert pkcs7 into DER */
> >>>>> +   ctx->sig_data = NULL;
> >>>>> +   ctx->sig_size = ASN1_item_i2d((ASN1_VALUE *)p7, &ctx->sig_data,
> >>>>> +                                 ASN1_ITEM_rptr(PKCS7));
> >>>>> +   if (!ctx->sig_size)
> >>>>> +           goto err;
> >>>>> +
> >>>>> +   /* fill auth_info */
> >>>>> +   ctx->auth.auth_info.hdr.dwLength = sizeof(ctx->auth.auth_info)
> >>>>> +                                           + ctx->sig_size;
> >>>>> +   ctx->auth.auth_info.hdr.wRevision = WIN_CERT_REVISION_2_0;
> >>>>> +   ctx->auth.auth_info.hdr.wCertificateType = WIN_CERT_TYPE_EFI_GUID;
> >>>>> +   memcpy(&ctx->auth.auth_info.cert_type, &efi_guid_cert_type_pkcs7,
> >>>>> +          sizeof(efi_guid_cert_type_pkcs7));
> >>>>> +
> >>>>> +   ret = 0;
> >>>>> +err:
> >>>>> +   BIO_free_all(data_bio);
> >>>>> +   EVP_PKEY_free(key);
> >>>>> +   X509_free(cert);
> >>>>> +
> >>>>> +   return ret;
> >>>>> +}
> >>>>> +
> >>>>> +static int dump_signature(const char *path, u8 *signature, size_t sig_size)
> >>>>> +{
> >>>>> +   char *sig_path;
> >>>>> +   FILE *f;
> >>>>> +   size_t size;
> >>>>> +   int ret = -1;
> >>>>> +
> >>>>> +   sig_path = malloc(strlen(path) + 3 + 1);
> >>>>> +   if (!sig_path)
> >>>>> +           return ret;
> >>>>> +
> >>>>> +   sprintf(sig_path, "%s.p7", path);
> >>>>> +   f = fopen(sig_path, "w");
> >>>>> +   if (!f)
> >>>>> +           goto err;
> >>>>> +
> >>>>> +   size = fwrite(signature, 1, sig_size, f);
> >>>>> +   if (size == sig_size)
> >>>>> +           ret = 0;
> >>>>> +
> >>>>> +   fclose(f);
> >>>>> +err:
> >>>>> +   free(sig_path);
> >>>>> +   return ret;
> >>>>> +}
> >>>>> +#endif
> >>>>> +
> >>>>>    static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>> -                   unsigned long index, unsigned long instance)
> >>>>> +                   unsigned long index, unsigned long instance,
> >>>>> +                   uint64_t mcount, char *privkey_file, char *cert_file)
> >>>>>    {
> >>>>>      struct efi_capsule_header header;
> >>>>>      struct efi_firmware_management_capsule_header capsule;
> >>>>>      struct efi_firmware_management_capsule_image_header image;
> >>>>> +   struct auth_context auth_context;
> >>>>>      FILE *f, *g;
> >>>>>      struct stat bin_stat;
> >>>>>      u8 *data;
> >>>>> @@ -266,6 +450,7 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>>      printf("\tbin: %s\n\ttype: %pUl\n", bin, guid);
> >>>>>      printf("\tindex: %ld\n\tinstance: %ld\n", index, instance);
> >>>>>    #endif
> >>>>> +   auth_context.sig_size = 0;
> >>>>>
> >>>>>      g = fopen(bin, "r");
> >>>>>      if (!g) {
> >>>>> @@ -281,11 +466,36 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>>              printf("cannot allocate memory: %zx\n", (size_t)bin_stat.st_size);
> >>>>>              goto err_1;
> >>>>>      }
> >>>>> -   f = fopen(path, "w");
> >>>>> -   if (!f) {
> >>>>> -           printf("cannot open %s\n", path);
> >>>>> +
> >>>>> +   size = fread(data, 1, bin_stat.st_size, g);
> >>>>> +   if (size < bin_stat.st_size) {
> >>>>> +           printf("read failed (%zx)\n", size);
> >>>>>              goto err_2;
> >>>>>      }
> >>>>> +
> >>>>> +   /* first, calculate signature to determine its size */
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>>> +   if (privkey_file && cert_file) {
> >>>>> +           auth_context.key_file = privkey_file;
> >>>>> +           auth_context.cert_file = cert_file;
> >>>>> +           auth_context.auth.monotonic_count = mcount;
> >>>>> +           auth_context.image_data = data;
> >>>>> +           auth_context.image_size = bin_stat.st_size;
> >>>>> +
> >>>>> +           if (create_auth_data(&auth_context)) {
> >>>>> +                   printf("Signing firmware image failed\n");
> >>>>> +                   goto err_3;
> >>>>> +           }
> >>>>> +
> >>>>> +           if (dump_sig &&
> >>>>> +               dump_signature(path, auth_context.sig_data,
> >>>>> +                              auth_context.sig_size)) {
> >>>>> +                   printf("Creating signature file failed\n");
> >>>>> +                   goto err_3;
> >>>>> +           }
> >>>>> +   }
> >>>>> +#endif
> >>>>> +
> >>>>>      header.capsule_guid = efi_guid_fm_capsule;
> >>>>>      header.header_size = sizeof(header);
> >>>>>      /* TODO: The current implementation ignores flags */
> >>>>> @@ -294,11 +504,20 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>>                                      + sizeof(capsule) + sizeof(u64)
> >>>>>                                      + sizeof(image)
> >>>>>                                      + bin_stat.st_size;
> >>>>> +   if (auth_context.sig_size)
> >>>>> +           header.capsule_image_size += sizeof(auth_context.auth)
> >>>>> +                           + auth_context.sig_size;
> >>>>> +
> >>>>> +   f = fopen(path, "w");
> >>>>> +   if (!f) {
> >>>>> +           printf("cannot open %s\n", path);
> >>>>> +           goto err_3;
> >>>>> +   }
> >>>>>
> >>>>>      size = fwrite(&header, 1, sizeof(header), f);
> >>>>>      if (size < sizeof(header)) {
> >>>>>              printf("write failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +           goto err_4;
> >>>>>      }
> >>>>>
> >>>>>      capsule.version = 0x00000001;
> >>>>> @@ -307,13 +526,13 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>>      size = fwrite(&capsule, 1, sizeof(capsule), f);
> >>>>>      if (size < (sizeof(capsule))) {
> >>>>>              printf("write failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +           goto err_4;
> >>>>>      }
> >>>>>      offset = sizeof(capsule) + sizeof(u64);
> >>>>>      size = fwrite(&offset, 1, sizeof(offset), f);
> >>>>>      if (size < sizeof(offset)) {
> >>>>>              printf("write failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +           goto err_4;
> >>>>>      }
> >>>>>
> >>>>>      image.version = 0x00000003;
> >>>>> @@ -323,34 +542,61 @@ static int create_fwbin(char *path, char *bin, efi_guid_t *guid,
> >>>>>      image.reserved[1] = 0;
> >>>>>      image.reserved[2] = 0;
> >>>>>      image.update_image_size = bin_stat.st_size;
> >>>>> +   if (auth_context.sig_size)
> >>>>> +           image.update_image_size += sizeof(auth_context.auth)
> >>>>> +                           + auth_context.sig_size;
> >>>>>      image.update_vendor_code_size = 0; /* none */
> >>>>>      image.update_hardware_instance = instance;
> >>>>>      image.image_capsule_support = 0;
> >>>>> +   if (auth_context.sig_size)
> >>>>> +           image.image_capsule_support |= CAPSULE_SUPPORT_AUTHENTICATION;
> >>>>>
> >>>>>      size = fwrite(&image, 1, sizeof(image), f);
> >>>>>      if (size < sizeof(image)) {
> >>>>>              printf("write failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +           goto err_4;
> >>>>>      }
> >>>>> -   size = fread(data, 1, bin_stat.st_size, g);
> >>>>> -   if (size < bin_stat.st_size) {
> >>>>> -           printf("read failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> We don't want to use #if if avoidable.
> >>>
> >>> For this specific chunk of code, we can remove #ifdef,
> >>> but we should not remove #ifdef elsewhere.
> >>>
> >>> -Takahiro Akashi
> >>>
> >>>
> >>>>> +   if (auth_context.sig_size) {
> >>>>> +           size = fwrite(&auth_context.auth, 1,
> >>>>> +                         sizeof(auth_context.auth), f);
> >>>>> +           if (size < sizeof(auth_context.auth)) {
> >>>>> +                   printf("write failed (%zx)\n", size);
> >>>>> +                   goto err_4;
> >>>>> +           }
> >>>>> +           size = fwrite(auth_context.sig_data, 1,
> >>>>> +                         auth_context.sig_size, f);
> >>>>> +           if (size < auth_context.sig_size) {
> >>>>> +                   printf("write failed (%zx)\n", size);
> >>>>> +                   goto err_4;
> >>>>> +           }
> >>>>>      }
> >>>>> +#endif
> >>>>> +
> >>>>>      size = fwrite(data, 1, bin_stat.st_size, f);
> >>>>>      if (size < bin_stat.st_size) {
> >>>>>              printf("write failed (%zx)\n", size);
> >>>>> -           goto err_3;
> >>>>> +           goto err_4;
> >>>>>      }
> >>>>>
> >>>>>      fclose(f);
> >>>>>      fclose(g);
> >>>>>      free(data);
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>> +   if (auth_context.sig_size)
> >>>>> +           OPENSSL_free(auth_context.sig_data);
> >>>>> +#endif
> >>>>>
> >>>>>      return 0;
> >>>>>
> >>>>> -err_3:
> >>>>> +err_4:
> >>>>>      fclose(f);
> >>>>> +err_3:
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>> +   if (auth_context.sig_size)
> >>>>> +           OPENSSL_free(auth_context.sig_data);
> >>>>> +#endif
> >>>>>    err_2:
> >>>>>      free(data);
> >>>>>    err_1:
> >>>>> @@ -359,10 +605,6 @@ err_1:
> >>>>>      return -1;
> >>>>>    }
> >>>>>
> >>>>> -/*
> >>>>> - * Usage:
> >>>>> - *   $ mkeficapsule -f <firmware binary> <output file>
> >>>>> - */
> >>>>>    int main(int argc, char **argv)
> >>>>>    {
> >>>>>      char *file;
> >>>>> @@ -370,6 +612,8 @@ int main(int argc, char **argv)
> >>>>>      char *dtb_file;
> >>>>>      efi_guid_t *guid;
> >>>>>      unsigned long index, instance;
> >>>>> +   uint64_t mcount;
> >>>>> +   char *privkey_file, *cert_file;
> >>>>>      int c, idx;
> >>>>>      int ret;
> >>>>>      bool overlay = false;
> >>>>> @@ -380,8 +624,12 @@ int main(int argc, char **argv)
> >>>>>      guid = NULL;
> >>>>>      index = 0;
> >>>>>      instance = 0;
> >>>>> +   mcount = 0;
> >>>>> +   privkey_file = NULL;
> >>>>> +   cert_file = NULL;
> >>>>> +   dump_sig = 0;
> >>>>>      for (;;) {
> >>>>> -           c = getopt_long(argc, argv, "f:r:i:I:v:D:K:Oh", options, &idx);
> >>>>> +           c = getopt_long(argc, argv, opts_short, options, &idx);
> >>>>>              if (c == -1)
> >>>>>                      break;
> >>>>>
> >>>>> @@ -422,6 +670,28 @@ int main(int argc, char **argv)
> >>>>>                      }
> >>>>>                      dtb_file = optarg;
> >>>>>                      break;
> >>>>> +#if IS_ENABLED(CONFIG_EFI_CAPSULE_AUTHENTICATE)
> >>>>
> >>>> see above
> >>>>
> >>>> Best regards
> >>>>
> >>>> Heinrich
> >>>>
> >>>>> +           case 'P':
> >>>>> +                   if (privkey_file) {
> >>>>> +                           printf("Private Key already specified\n");
> >>>>> +                           return -1;
> >>>>> +                   }
> >>>>> +                   privkey_file = optarg;
> >>>>> +                   break;
> >>>>> +           case 'C':
> >>>>> +                   if (cert_file) {
> >>>>> +                           printf("Certificate file already specified\n");
> >>>>> +                           return -1;
> >>>>> +                   }
> >>>>> +                   cert_file = optarg;
> >>>>> +                   break;
> >>>>> +           case 'm':
> >>>>> +                   mcount = strtoul(optarg, NULL, 0);
> >>>>> +                   break;
> >>>>> +           case 'd':
> >>>>> +                   dump_sig = 1;
> >>>>> +                   break;
> >>>>> +#endif
> >>>>>              case 'O':
> >>>>>                      overlay = true;
> >>>>>                      break;
> >>>>> @@ -431,8 +701,12 @@ int main(int argc, char **argv)
> >>>>>              }
> >>>>>      }
> >>>>>
> >>>>> -   /* need a fit image file or raw image file */
> >>>>> -   if (!file && !pkey_file && !dtb_file) {
> >>>>> +   /* check necessary parameters */
> >>>>> +   if ((file && (!(optind < argc) ||
> >>>>> +                 (privkey_file && !cert_file) ||
> >>>>> +                 (!privkey_file && cert_file))) ||
> >>>>> +       ((pkey_file && !dtb_file) ||
> >>>>> +        (!pkey_file && dtb_file))) {
> >>>>>              print_usage();
> >>>>>              exit(EXIT_FAILURE);
> >>>>>      }
> >>>>> @@ -442,12 +716,12 @@ int main(int argc, char **argv)
> >>>>>              if (ret == -1) {
> >>>>>                      printf("Adding public key to the dtb failed\n");
> >>>>>                      exit(EXIT_FAILURE);
> >>>>> -           } else {
> >>>>> -                   exit(EXIT_SUCCESS);
> >>>>>              }
> >>>>>      }
> >>>>>
> >>>>> -   if (create_fwbin(argv[optind], file, guid, index, instance)
> >>>>> +   if (optind < argc &&
> >>>>> +       create_fwbin(argv[optind], file, guid, index, instance,
> >>>>> +                    mcount, privkey_file, cert_file)
> >>>>>                      < 0) {
> >>>>>              printf("Creating firmware capsule failed\n");
> >>>>>              exit(EXIT_FAILURE);
> >>>>>
> >>>>
> >>
> >
> >
>


-- 
Masami Hiramatsu


More information about the U-Boot mailing list