uboot/lib/efi_loader/efi_signature.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2018 Patrick Wildt <patrick@blueri.se>
   4 * Copyright (c) 2019 Linaro Limited, Author: AKASHI Takahiro
   5 */
   6
   7#include <common.h>
   8#include <charset.h>
   9#include <efi_loader.h>
  10#include <image.h>
  11#include <hexdump.h>
  12#include <malloc.h>
  13#include <crypto/pkcs7.h>
  14#include <crypto/pkcs7_parser.h>
  15#include <crypto/public_key.h>
  16#include <linux/compat.h>
  17#include <linux/oid_registry.h>
  18#include <u-boot/hash-checksum.h>
  19#include <u-boot/rsa.h>
  20#include <u-boot/sha256.h>
  21
  22const efi_guid_t efi_guid_sha256 = EFI_CERT_SHA256_GUID;
  23const efi_guid_t efi_guid_cert_rsa2048 = EFI_CERT_RSA2048_GUID;
  24const efi_guid_t efi_guid_cert_x509 = EFI_CERT_X509_GUID;
  25const efi_guid_t efi_guid_cert_x509_sha256 = EFI_CERT_X509_SHA256_GUID;
  26const efi_guid_t efi_guid_cert_type_pkcs7 = EFI_CERT_TYPE_PKCS7_GUID;
  27
  28static u8 pkcs7_hdr[] = {
  29        /* SEQUENCE */
  30        0x30, 0x82, 0x05, 0xc7,
  31        /* OID: pkcs7-signedData */
  32        0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x07, 0x02,
  33        /* Context Structured? */
  34        0xa0, 0x82, 0x05, 0xb8,
  35};
  36
  37/**
  38 * efi_parse_pkcs7_header - parse a signature in payload
  39 * @buf:        Pointer to payload's value
  40 * @buflen:     Length of @buf
  41 * @tmpbuf:     Pointer to temporary buffer
  42 *
  43 * Parse a signature embedded in payload's value and instantiate
  44 * a pkcs7_message structure. Since pkcs7_parse_message() accepts only
  45 * pkcs7's signedData, some header needed be prepended for correctly
  46 * parsing authentication data
  47 * A temporary buffer will be allocated if needed, and it should be
  48 * kept valid during the authentication because some data in the buffer
  49 * will be referenced by efi_signature_verify().
  50 *
  51 * Return:      Pointer to pkcs7_message structure on success, NULL on error
  52 */
  53struct pkcs7_message *efi_parse_pkcs7_header(const void *buf,
  54                                             size_t buflen,
  55                                             u8 **tmpbuf)
  56{
  57        u8 *ebuf;
  58        size_t ebuflen, len;
  59        struct pkcs7_message *msg;
  60
  61        /*
  62         * This is the best assumption to check if the binary is
  63         * already in a form of pkcs7's signedData.
  64         */
  65        if (buflen > sizeof(pkcs7_hdr) &&
  66            !memcmp(&((u8 *)buf)[4], &pkcs7_hdr[4], 11)) {
  67                msg = pkcs7_parse_message(buf, buflen);
  68                if (IS_ERR(msg))
  69                        return NULL;
  70                return msg;
  71        }
  72
  73        /*
  74         * Otherwise, we should add a dummy prefix sequence for pkcs7
  75         * message parser to be able to process.
  76         * NOTE: EDK2 also uses similar hack in WrapPkcs7Data()
  77         * in CryptoPkg/Library/BaseCryptLib/Pk/CryptPkcs7VerifyCommon.c
  78         * TODO:
  79         * The header should be composed in a more refined manner.
  80         */
  81        EFI_PRINT("Makeshift prefix added to authentication data\n");
  82        ebuflen = sizeof(pkcs7_hdr) + buflen;
  83        if (ebuflen <= 0x7f) {
  84                EFI_PRINT("Data is too short\n");
  85                return NULL;
  86        }
  87
  88        ebuf = malloc(ebuflen);
  89        if (!ebuf) {
  90                EFI_PRINT("Out of memory\n");
  91                return NULL;
  92        }
  93
  94        memcpy(ebuf, pkcs7_hdr, sizeof(pkcs7_hdr));
  95        memcpy(ebuf + sizeof(pkcs7_hdr), buf, buflen);
  96        len = ebuflen - 4;
  97        ebuf[2] = (len >> 8) & 0xff;
  98        ebuf[3] = len & 0xff;
  99        len = ebuflen - 0x13;
 100        ebuf[0x11] = (len >> 8) & 0xff;
 101        ebuf[0x12] = len & 0xff;
 102
 103        msg = pkcs7_parse_message(ebuf, ebuflen);
 104
 105        if (IS_ERR(msg)) {
 106                free(ebuf);
 107                return NULL;
 108        }
 109
 110        *tmpbuf = ebuf;
 111        return msg;
 112}
 113
 114/**
 115 * efi_hash_regions - calculate a hash value
 116 * @regs:       Array of regions
 117 * @count:      Number of regions
 118 * @hash:       Pointer to a pointer to buffer holding a hash value
 119 * @size:       Size of buffer to be returned
 120 *
 121 * Calculate a sha256 value of @regs and return a value in @hash.
 122 *
 123 * Return:      true on success, false on error
 124 */
 125static bool efi_hash_regions(struct image_region *regs, int count,
 126                             void **hash, size_t *size)
 127{
 128        if (!*hash) {
 129                *hash = calloc(1, SHA256_SUM_LEN);
 130                if (!*hash) {
 131                        EFI_PRINT("Out of memory\n");
 132                        return false;
 133                }
 134        }
 135        if (size)
 136                *size = SHA256_SUM_LEN;
 137
 138        hash_calculate("sha256", regs, count, *hash);
 139#ifdef DEBUG
 140        EFI_PRINT("hash calculated:\n");
 141        print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 142                       *hash, SHA256_SUM_LEN, false);
 143#endif
 144
 145        return true;
 146}
 147
 148/**
 149 * efi_signature_lookup_digest - search for an image's digest in sigdb
 150 * @regs:       List of regions to be authenticated
 151 * @db:         Signature database for trusted certificates
 152 *
 153 * A message digest of image pointed to by @regs is calculated and
 154 * its hash value is compared to entries in signature database pointed
 155 * to by @db.
 156 *
 157 * Return:      true if found, false if not
 158 */
 159bool efi_signature_lookup_digest(struct efi_image_regions *regs,
 160                                 struct efi_signature_store *db)
 161{
 162        struct efi_signature_store *siglist;
 163        struct efi_sig_data *sig_data;
 164        void *hash = NULL;
 165        size_t size = 0;
 166        bool found = false;
 167
 168        EFI_PRINT("%s: Enter, %p, %p\n", __func__, regs, db);
 169
 170        if (!regs || !db || !db->sig_data_list)
 171                goto out;
 172
 173        for (siglist = db; siglist; siglist = siglist->next) {
 174                /* TODO: support other hash algorithms */
 175                if (guidcmp(&siglist->sig_type, &efi_guid_sha256)) {
 176                        EFI_PRINT("Digest algorithm is not supported: %pUl\n",
 177                                  &siglist->sig_type);
 178                        break;
 179                }
 180
 181                if (!efi_hash_regions(regs->reg, regs->num, &hash, &size)) {
 182                        EFI_PRINT("Digesting an image failed\n");
 183                        break;
 184                }
 185
 186                for (sig_data = siglist->sig_data_list; sig_data;
 187                     sig_data = sig_data->next) {
 188#ifdef DEBUG
 189                        EFI_PRINT("Msg digest in database:\n");
 190                        print_hex_dump("    ", DUMP_PREFIX_OFFSET, 16, 1,
 191                                       sig_data->data, sig_data->size, false);
 192#endif
 193                        if (sig_data->size == size &&
 194                            !memcmp(sig_data->data, hash, size)) {
 195                                found = true;
 196                                free(hash);
 197                                goto out;
 198                        }
 199                }
 200
 201                free(hash);
 202                hash = NULL;
 203        }
 204
 205out:
 206        EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
 207        return found;
 208}
 209
 210/**
 211 * efi_lookup_certificate - find a certificate within db
 212 * @msg:        Signature
 213 * @db:         Signature database
 214 *
 215 * Search signature database pointed to by @db and find a certificate
 216 * pointed to by @cert.
 217 *
 218 * Return:      true if found, false otherwise.
 219 */
 220static bool efi_lookup_certificate(struct x509_certificate *cert,
 221                                   struct efi_signature_store *db)
 222{
 223        struct efi_signature_store *siglist;
 224        struct efi_sig_data *sig_data;
 225        struct image_region reg[1];
 226        void *hash = NULL, *hash_tmp = NULL;
 227        size_t size = 0;
 228        bool found = false;
 229
 230        EFI_PRINT("%s: Enter, %p, %p\n", __func__, cert, db);
 231
 232        if (!cert || !db || !db->sig_data_list)
 233                goto out;
 234
 235        /*
 236         * TODO: identify a certificate using sha256 digest
 237         * Is there any better way?
 238         */
 239        /* calculate hash of TBSCertificate */
 240        reg[0].data = cert->tbs;
 241        reg[0].size = cert->tbs_size;
 242        if (!efi_hash_regions(reg, 1, &hash, &size))
 243                goto out;
 244
 245        EFI_PRINT("%s: searching for %s\n", __func__, cert->subject);
 246        for (siglist = db; siglist; siglist = siglist->next) {
 247                /* only with x509 certificate */
 248                if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
 249                        continue;
 250
 251                for (sig_data = siglist->sig_data_list; sig_data;
 252                     sig_data = sig_data->next) {
 253                        struct x509_certificate *cert_tmp;
 254
 255                        cert_tmp = x509_cert_parse(sig_data->data,
 256                                                   sig_data->size);
 257                        if (IS_ERR_OR_NULL(cert_tmp))
 258                                continue;
 259
 260                        EFI_PRINT("%s: against %s\n", __func__,
 261                                  cert_tmp->subject);
 262                        reg[0].data = cert_tmp->tbs;
 263                        reg[0].size = cert_tmp->tbs_size;
 264                        if (!efi_hash_regions(reg, 1, &hash_tmp, NULL))
 265                                goto out;
 266
 267                        x509_free_certificate(cert_tmp);
 268
 269                        if (!memcmp(hash, hash_tmp, size)) {
 270                                found = true;
 271                                goto out;
 272                        }
 273                }
 274        }
 275out:
 276        free(hash);
 277        free(hash_tmp);
 278
 279        EFI_PRINT("%s: Exit, found: %d\n", __func__, found);
 280        return found;
 281}
 282
 283/**
 284 * efi_verify_certificate - verify certificate's signature with database
 285 * @signer:     Certificate
 286 * @db:         Signature database
 287 * @root:       Certificate to verify @signer
 288 *
 289 * Determine if certificate pointed to by @signer may be verified
 290 * by one of certificates in signature database pointed to by @db.
 291 *
 292 * Return:      true if certificate is verified, false otherwise.
 293 */
 294static bool efi_verify_certificate(struct x509_certificate *signer,
 295                                   struct efi_signature_store *db,
 296                                   struct x509_certificate **root)
 297{
 298        struct efi_signature_store *siglist;
 299        struct efi_sig_data *sig_data;
 300        struct x509_certificate *cert;
 301        bool verified = false;
 302        int ret;
 303
 304        EFI_PRINT("%s: Enter, %p, %p\n", __func__, signer, db);
 305
 306        if (!signer || !db || !db->sig_data_list)
 307                goto out;
 308
 309        for (siglist = db; siglist; siglist = siglist->next) {
 310                /* only with x509 certificate */
 311                if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509))
 312                        continue;
 313
 314                for (sig_data = siglist->sig_data_list; sig_data;
 315                     sig_data = sig_data->next) {
 316                        cert = x509_cert_parse(sig_data->data, sig_data->size);
 317                        if (IS_ERR_OR_NULL(cert)) {
 318                                EFI_PRINT("Cannot parse x509 certificate\n");
 319                                continue;
 320                        }
 321
 322                        ret = public_key_verify_signature(cert->pub,
 323                                                          signer->sig);
 324                        if (!ret) {
 325                                verified = true;
 326                                if (root)
 327                                        *root = cert;
 328                                else
 329                                        x509_free_certificate(cert);
 330                                goto out;
 331                        }
 332                        x509_free_certificate(cert);
 333                }
 334        }
 335
 336out:
 337        EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
 338        return verified;
 339}
 340
 341/**
 342 * efi_signature_check_revocation - check revocation with dbx
 343 * @sinfo:      Signer's info
 344 * @cert:       x509 certificate
 345 * @dbx:        Revocation signature database
 346 *
 347 * Search revocation signature database pointed to by @dbx and find
 348 * an entry matching to certificate pointed to by @cert.
 349 *
 350 * While this entry contains revocation time, we don't support timestamp
 351 * protocol at this time and any image will be unconditionally revoked
 352 * when this match occurs.
 353 *
 354 * Return:      true if check passed (not found), false otherwise.
 355 */
 356static bool efi_signature_check_revocation(struct pkcs7_signed_info *sinfo,
 357                                           struct x509_certificate *cert,
 358                                           struct efi_signature_store *dbx)
 359{
 360        struct efi_signature_store *siglist;
 361        struct efi_sig_data *sig_data;
 362        struct image_region reg[1];
 363        void *hash = NULL;
 364        size_t size = 0;
 365        time64_t revoc_time;
 366        bool revoked = false;
 367
 368        EFI_PRINT("%s: Enter, %p, %p, %p\n", __func__, sinfo, cert, dbx);
 369
 370        if (!sinfo || !cert || !dbx || !dbx->sig_data_list)
 371                goto out;
 372
 373        EFI_PRINT("Checking revocation against %s\n", cert->subject);
 374        for (siglist = dbx; siglist; siglist = siglist->next) {
 375                if (guidcmp(&siglist->sig_type, &efi_guid_cert_x509_sha256))
 376                        continue;
 377
 378                /* calculate hash of TBSCertificate */
 379                reg[0].data = cert->tbs;
 380                reg[0].size = cert->tbs_size;
 381                if (!efi_hash_regions(reg, 1, &hash, &size))
 382                        goto out;
 383
 384                for (sig_data = siglist->sig_data_list; sig_data;
 385                     sig_data = sig_data->next) {
 386                        /*
 387                         * struct efi_cert_x509_sha256 {
 388                         *      u8 tbs_hash[256/8];
 389                         *      time64_t revocation_time;
 390                         * };
 391                         */
 392#ifdef DEBUG
 393                        if (sig_data->size >= size) {
 394                                EFI_PRINT("hash in db:\n");
 395                                print_hex_dump("    ", DUMP_PREFIX_OFFSET,
 396                                               16, 1,
 397                                               sig_data->data, size, false);
 398                        }
 399#endif
 400                        if ((sig_data->size < size + sizeof(time64_t)) ||
 401                            memcmp(sig_data->data, hash, size))
 402                                continue;
 403
 404                        memcpy(&revoc_time, sig_data->data + size,
 405                               sizeof(revoc_time));
 406                        EFI_PRINT("revocation time: 0x%llx\n", revoc_time);
 407                        /*
 408                         * TODO: compare signing timestamp in sinfo
 409                         * with revocation time
 410                         */
 411
 412                        revoked = true;
 413                        free(hash);
 414                        goto out;
 415                }
 416                free(hash);
 417                hash = NULL;
 418        }
 419out:
 420        EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
 421        return !revoked;
 422}
 423
 424/*
 425 * efi_signature_verify - verify signatures with db and dbx
 426 * @regs:       List of regions to be authenticated
 427 * @msg:        Signature
 428 * @db:         Signature database for trusted certificates
 429 * @dbx:        Revocation signature database
 430 *
 431 * All the signature pointed to by @msg against image pointed to by @regs
 432 * will be verified by signature database pointed to by @db and @dbx.
 433 *
 434 * Return:      true if verification for all signatures passed, false otherwise
 435 */
 436bool efi_signature_verify(struct efi_image_regions *regs,
 437                          struct pkcs7_message *msg,
 438                          struct efi_signature_store *db,
 439                          struct efi_signature_store *dbx)
 440{
 441        struct pkcs7_signed_info *sinfo;
 442        struct x509_certificate *signer, *root;
 443        bool verified = false;
 444        int ret;
 445
 446        EFI_PRINT("%s: Enter, %p, %p, %p, %p\n", __func__, regs, msg, db, dbx);
 447
 448        if (!regs || !msg || !db || !db->sig_data_list)
 449                goto out;
 450
 451        for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
 452                EFI_PRINT("Signed Info: digest algo: %s, pkey algo: %s\n",
 453                          sinfo->sig->hash_algo, sinfo->sig->pkey_algo);
 454
 455                /*
 456                 * only for authenticated variable.
 457                 *
 458                 * If this function is called for image,
 459                 * hash calculation will be done in
 460                 * pkcs7_verify_one().
 461                 */
 462                if (!msg->data &&
 463                    !efi_hash_regions(regs->reg, regs->num,
 464                                      (void **)&sinfo->sig->digest, NULL)) {
 465                        EFI_PRINT("Digesting an image failed\n");
 466                        goto out;
 467                }
 468
 469                EFI_PRINT("Verifying certificate chain\n");
 470                signer = NULL;
 471                ret = pkcs7_verify_one(msg, sinfo, &signer);
 472                if (ret == -ENOPKG)
 473                        continue;
 474
 475                if (ret < 0 || !signer)
 476                        goto out;
 477
 478                if (sinfo->blacklisted)
 479                        goto out;
 480
 481                EFI_PRINT("Verifying last certificate in chain\n");
 482                if (signer->self_signed) {
 483                        if (efi_lookup_certificate(signer, db))
 484                                if (efi_signature_check_revocation(sinfo,
 485                                                                   signer, dbx))
 486                                        break;
 487                } else if (efi_verify_certificate(signer, db, &root)) {
 488                        bool check;
 489
 490                        check = efi_signature_check_revocation(sinfo, root,
 491                                                               dbx);
 492                        x509_free_certificate(root);
 493                        if (check)
 494                                break;
 495                }
 496
 497                EFI_PRINT("Certificate chain didn't reach trusted CA\n");
 498        }
 499        if (sinfo)
 500                verified = true;
 501out:
 502        EFI_PRINT("%s: Exit, verified: %d\n", __func__, verified);
 503        return verified;
 504}
 505
 506/**
 507 * efi_signature_check_signers - check revocation against all signers with dbx
 508 * @msg:        Signature
 509 * @dbx:        Revocation signature database
 510 *
 511 * Determine if none of signers' certificates in @msg are revoked
 512 * by signature database pointed to by @dbx.
 513 *
 514 * Return:      true if all signers passed, false otherwise.
 515 */
 516bool efi_signature_check_signers(struct pkcs7_message *msg,
 517                                 struct efi_signature_store *dbx)
 518{
 519        struct pkcs7_signed_info *sinfo;
 520        bool revoked = false;
 521
 522        EFI_PRINT("%s: Enter, %p, %p\n", __func__, msg, dbx);
 523
 524        if (!msg || !dbx)
 525                goto out;
 526
 527        for (sinfo = msg->signed_infos; sinfo; sinfo = sinfo->next) {
 528                if (sinfo->signer &&
 529                    !efi_signature_check_revocation(sinfo, sinfo->signer,
 530                                                    dbx)) {
 531                        revoked = true;
 532                        break;
 533                }
 534        }
 535out:
 536        EFI_PRINT("%s: Exit, revoked: %d\n", __func__, revoked);
 537        return !revoked;
 538}
 539
 540/**
 541 * efi_sigstore_free - free signature store
 542 * @sigstore:   Pointer to signature store structure
 543 *
 544 * Feee all the memories held in signature store and itself,
 545 * which were allocated by efi_sigstore_parse_sigdb().
 546 */
 547void efi_sigstore_free(struct efi_signature_store *sigstore)
 548{
 549        struct efi_signature_store *sigstore_next;
 550        struct efi_sig_data *sig_data, *sig_data_next;
 551
 552        while (sigstore) {
 553                sigstore_next = sigstore->next;
 554
 555                sig_data = sigstore->sig_data_list;
 556                while (sig_data) {
 557                        sig_data_next = sig_data->next;
 558                        free(sig_data->data);
 559                        free(sig_data);
 560                        sig_data = sig_data_next;
 561                }
 562
 563                free(sigstore);
 564                sigstore = sigstore_next;
 565        }
 566}
 567
 568/**
 569 * efi_sigstore_parse_siglist - parse a signature list
 570 * @name:       Pointer to signature list
 571 *
 572 * Parse signature list and instantiate a signature store structure.
 573 * Signature database is a simple concatenation of one or more
 574 * signature list(s).
 575 *
 576 * Return:      Pointer to signature store on success, NULL on error
 577 */
 578static struct efi_signature_store *
 579efi_sigstore_parse_siglist(struct efi_signature_list *esl)
 580{
 581        struct efi_signature_store *siglist = NULL;
 582        struct efi_sig_data *sig_data, *sig_data_next;
 583        struct efi_signature_data *esd;
 584        size_t left;
 585
 586        /*
 587         * UEFI specification defines certificate types:
 588         *   for non-signed images,
 589         *      EFI_CERT_SHA256_GUID
 590         *      EFI_CERT_RSA2048_GUID
 591         *      EFI_CERT_RSA2048_SHA256_GUID
 592         *      EFI_CERT_SHA1_GUID
 593         *      EFI_CERT_RSA2048_SHA_GUID
 594         *      EFI_CERT_SHA224_GUID
 595         *      EFI_CERT_SHA384_GUID
 596         *      EFI_CERT_SHA512_GUID
 597         *
 598         *   for signed images,
 599         *      EFI_CERT_X509_GUID
 600         *      NOTE: Each certificate will normally be in a separate
 601         *      EFI_SIGNATURE_LIST as the size may vary depending on
 602         *      its algo's.
 603         *
 604         *   for timestamp revocation of certificate,
 605         *      EFI_CERT_X509_SHA512_GUID
 606         *      EFI_CERT_X509_SHA256_GUID
 607         *      EFI_CERT_X509_SHA384_GUID
 608         */
 609
 610        if (esl->signature_list_size
 611                        <= (sizeof(*esl) + esl->signature_header_size)) {
 612                EFI_PRINT("Siglist in wrong format\n");
 613                return NULL;
 614        }
 615
 616        /* Create a head */
 617        siglist = calloc(sizeof(*siglist), 1);
 618        if (!siglist) {
 619                EFI_PRINT("Out of memory\n");
 620                goto err;
 621        }
 622        memcpy(&siglist->sig_type, &esl->signature_type, sizeof(efi_guid_t));
 623
 624        /* Go through the list */
 625        sig_data_next = NULL;
 626        left = esl->signature_list_size
 627                        - (sizeof(*esl) + esl->signature_header_size);
 628        esd = (struct efi_signature_data *)
 629                        ((u8 *)esl + sizeof(*esl) + esl->signature_header_size);
 630
 631        while (left > 0) {
 632                /* Signature must exist if there is remaining data. */
 633                if (left < esl->signature_size) {
 634                        EFI_PRINT("Certificate is too small\n");
 635                        goto err;
 636                }
 637
 638                sig_data = calloc(esl->signature_size
 639                                        - sizeof(esd->signature_owner), 1);
 640                if (!sig_data) {
 641                        EFI_PRINT("Out of memory\n");
 642                        goto err;
 643                }
 644
 645                /* Append signature data */
 646                memcpy(&sig_data->owner, &esd->signature_owner,
 647                       sizeof(efi_guid_t));
 648                sig_data->size = esl->signature_size
 649                                        - sizeof(esd->signature_owner);
 650                sig_data->data = malloc(sig_data->size);
 651                if (!sig_data->data) {
 652                        EFI_PRINT("Out of memory\n");
 653                        goto err;
 654                }
 655                memcpy(sig_data->data, esd->signature_data, sig_data->size);
 656
 657                sig_data->next = sig_data_next;
 658                sig_data_next = sig_data;
 659
 660                /* Next */
 661                esd = (struct efi_signature_data *)
 662                                ((u8 *)esd + esl->signature_size);
 663                left -= esl->signature_size;
 664        }
 665        siglist->sig_data_list = sig_data_next;
 666
 667        return siglist;
 668
 669err:
 670        efi_sigstore_free(siglist);
 671
 672        return NULL;
 673}
 674
 675/**
 676 * efi_sigstore_parse_sigdb - parse the signature list and populate
 677 * the signature store
 678 *
 679 * @sig_list:   Pointer to the signature list
 680 * @size:       Size of the signature list
 681 *
 682 * Parse the efi signature list and instantiate a signature store
 683 * structure.
 684 *
 685 * Return:      Pointer to signature store on success, NULL on error
 686 */
 687struct efi_signature_store *efi_build_signature_store(void *sig_list,
 688                                                      efi_uintn_t size)
 689{
 690        struct efi_signature_list *esl;
 691        struct efi_signature_store *sigstore = NULL, *siglist;
 692
 693        esl = sig_list;
 694        while (size > 0) {
 695                /* List must exist if there is remaining data. */
 696                if (size < sizeof(*esl)) {
 697                        EFI_PRINT("Signature list in wrong format\n");
 698                        goto err;
 699                }
 700
 701                if (size < esl->signature_list_size) {
 702                        EFI_PRINT("Signature list in wrong format\n");
 703                        goto err;
 704                }
 705
 706                /* Parse a single siglist. */
 707                siglist = efi_sigstore_parse_siglist(esl);
 708                if (!siglist) {
 709                        EFI_PRINT("Parsing of signature list of failed\n");
 710                        goto err;
 711                }
 712
 713                /* Append siglist */
 714                siglist->next = sigstore;
 715                sigstore = siglist;
 716
 717                /* Next */
 718                size -= esl->signature_list_size;
 719                esl = (void *)esl + esl->signature_list_size;
 720        }
 721        free(sig_list);
 722
 723        return sigstore;
 724
 725err:
 726        efi_sigstore_free(sigstore);
 727        free(sig_list);
 728
 729        return NULL;
 730}
 731
 732/**
 733 * efi_sigstore_parse_sigdb - parse a signature database variable
 734 * @name:       Variable's name
 735 *
 736 * Read in a value of signature database variable pointed to by
 737 * @name, parse it and instantiate a signature store structure.
 738 *
 739 * Return:      Pointer to signature store on success, NULL on error
 740 */
 741struct efi_signature_store *efi_sigstore_parse_sigdb(u16 *name)
 742{
 743        struct efi_signature_store *sigstore = NULL;
 744        const efi_guid_t *vendor;
 745        void *db;
 746        efi_uintn_t db_size;
 747        efi_status_t ret;
 748
 749        if (!u16_strcmp(name, L"PK") || !u16_strcmp(name, L"KEK")) {
 750                vendor = &efi_global_variable_guid;
 751        } else if (!u16_strcmp(name, L"db") || !u16_strcmp(name, L"dbx")) {
 752                vendor = &efi_guid_image_security_database;
 753        } else {
 754                EFI_PRINT("unknown signature database, %ls\n", name);
 755                return NULL;
 756        }
 757
 758        /* retrieve variable data */
 759        db_size = 0;
 760        ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, NULL));
 761        if (ret == EFI_NOT_FOUND) {
 762                EFI_PRINT("variable, %ls, not found\n", name);
 763                sigstore = calloc(sizeof(*sigstore), 1);
 764                return sigstore;
 765        } else if (ret != EFI_BUFFER_TOO_SMALL) {
 766                EFI_PRINT("Getting variable, %ls, failed\n", name);
 767                return NULL;
 768        }
 769
 770        db = malloc(db_size);
 771        if (!db) {
 772                EFI_PRINT("Out of memory\n");
 773                return NULL;
 774        }
 775
 776        ret = EFI_CALL(efi_get_variable(name, vendor, NULL, &db_size, db));
 777        if (ret != EFI_SUCCESS) {
 778                EFI_PRINT("Getting variable, %ls, failed\n", name);
 779                free(db);
 780                return NULL;
 781        }
 782
 783        return efi_build_signature_store(db, db_size);
 784}
 785