Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /* Parse a signed PE binary
0003  *
0004  * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
0005  * Written by David Howells (dhowells@redhat.com)
0006  */
0007 
0008 #define pr_fmt(fmt) "PEFILE: "fmt
0009 #include <linux/module.h>
0010 #include <linux/kernel.h>
0011 #include <linux/slab.h>
0012 #include <linux/err.h>
0013 #include <linux/pe.h>
0014 #include <linux/asn1.h>
0015 #include <linux/verification.h>
0016 #include <crypto/hash.h>
0017 #include "verify_pefile.h"
0018 
0019 /*
0020  * Parse a PE binary.
0021  */
0022 static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
0023                    struct pefile_context *ctx)
0024 {
0025     const struct mz_hdr *mz = pebuf;
0026     const struct pe_hdr *pe;
0027     const struct pe32_opt_hdr *pe32;
0028     const struct pe32plus_opt_hdr *pe64;
0029     const struct data_directory *ddir;
0030     const struct data_dirent *dde;
0031     const struct section_header *secs, *sec;
0032     size_t cursor, datalen = pelen;
0033 
0034     kenter("");
0035 
0036 #define chkaddr(base, x, s)                     \
0037     do {                                \
0038         if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \
0039             return -ELIBBAD;                \
0040     } while (0)
0041 
0042     chkaddr(0, 0, sizeof(*mz));
0043     if (mz->magic != MZ_MAGIC)
0044         return -ELIBBAD;
0045     cursor = sizeof(*mz);
0046 
0047     chkaddr(cursor, mz->peaddr, sizeof(*pe));
0048     pe = pebuf + mz->peaddr;
0049     if (pe->magic != PE_MAGIC)
0050         return -ELIBBAD;
0051     cursor = mz->peaddr + sizeof(*pe);
0052 
0053     chkaddr(0, cursor, sizeof(pe32->magic));
0054     pe32 = pebuf + cursor;
0055     pe64 = pebuf + cursor;
0056 
0057     switch (pe32->magic) {
0058     case PE_OPT_MAGIC_PE32:
0059         chkaddr(0, cursor, sizeof(*pe32));
0060         ctx->image_checksum_offset =
0061             (unsigned long)&pe32->csum - (unsigned long)pebuf;
0062         ctx->header_size = pe32->header_size;
0063         cursor += sizeof(*pe32);
0064         ctx->n_data_dirents = pe32->data_dirs;
0065         break;
0066 
0067     case PE_OPT_MAGIC_PE32PLUS:
0068         chkaddr(0, cursor, sizeof(*pe64));
0069         ctx->image_checksum_offset =
0070             (unsigned long)&pe64->csum - (unsigned long)pebuf;
0071         ctx->header_size = pe64->header_size;
0072         cursor += sizeof(*pe64);
0073         ctx->n_data_dirents = pe64->data_dirs;
0074         break;
0075 
0076     default:
0077         pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
0078         return -ELIBBAD;
0079     }
0080 
0081     pr_debug("checksum @ %x\n", ctx->image_checksum_offset);
0082     pr_debug("header size = %x\n", ctx->header_size);
0083 
0084     if (cursor >= ctx->header_size || ctx->header_size >= datalen)
0085         return -ELIBBAD;
0086 
0087     if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde))
0088         return -ELIBBAD;
0089 
0090     ddir = pebuf + cursor;
0091     cursor += sizeof(*dde) * ctx->n_data_dirents;
0092 
0093     ctx->cert_dirent_offset =
0094         (unsigned long)&ddir->certs - (unsigned long)pebuf;
0095     ctx->certs_size = ddir->certs.size;
0096 
0097     if (!ddir->certs.virtual_address || !ddir->certs.size) {
0098         pr_debug("Unsigned PE binary\n");
0099         return -ENODATA;
0100     }
0101 
0102     chkaddr(ctx->header_size, ddir->certs.virtual_address,
0103         ddir->certs.size);
0104     ctx->sig_offset = ddir->certs.virtual_address;
0105     ctx->sig_len = ddir->certs.size;
0106     pr_debug("cert = %x @%x [%*ph]\n",
0107          ctx->sig_len, ctx->sig_offset,
0108          ctx->sig_len, pebuf + ctx->sig_offset);
0109 
0110     ctx->n_sections = pe->sections;
0111     if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec))
0112         return -ELIBBAD;
0113     ctx->secs = secs = pebuf + cursor;
0114 
0115     return 0;
0116 }
0117 
0118 /*
0119  * Check and strip the PE wrapper from around the signature and check that the
0120  * remnant looks something like PKCS#7.
0121  */
0122 static int pefile_strip_sig_wrapper(const void *pebuf,
0123                     struct pefile_context *ctx)
0124 {
0125     struct win_certificate wrapper;
0126     const u8 *pkcs7;
0127     unsigned len;
0128 
0129     if (ctx->sig_len < sizeof(wrapper)) {
0130         pr_debug("Signature wrapper too short\n");
0131         return -ELIBBAD;
0132     }
0133 
0134     memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper));
0135     pr_debug("sig wrapper = { %x, %x, %x }\n",
0136          wrapper.length, wrapper.revision, wrapper.cert_type);
0137 
0138     /* Both pesign and sbsign round up the length of certificate table
0139      * (in optional header data directories) to 8 byte alignment.
0140      */
0141     if (round_up(wrapper.length, 8) != ctx->sig_len) {
0142         pr_debug("Signature wrapper len wrong\n");
0143         return -ELIBBAD;
0144     }
0145     if (wrapper.revision != WIN_CERT_REVISION_2_0) {
0146         pr_debug("Signature is not revision 2.0\n");
0147         return -ENOTSUPP;
0148     }
0149     if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
0150         pr_debug("Signature certificate type is not PKCS\n");
0151         return -ENOTSUPP;
0152     }
0153 
0154     /* It looks like the pkcs signature length in wrapper->length and the
0155      * size obtained from the data dir entries, which lists the total size
0156      * of certificate table, are both aligned to an octaword boundary, so
0157      * we may have to deal with some padding.
0158      */
0159     ctx->sig_len = wrapper.length;
0160     ctx->sig_offset += sizeof(wrapper);
0161     ctx->sig_len -= sizeof(wrapper);
0162     if (ctx->sig_len < 4) {
0163         pr_debug("Signature data missing\n");
0164         return -EKEYREJECTED;
0165     }
0166 
0167     /* What's left should be a PKCS#7 cert */
0168     pkcs7 = pebuf + ctx->sig_offset;
0169     if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
0170         goto not_pkcs7;
0171 
0172     switch (pkcs7[1]) {
0173     case 0 ... 0x7f:
0174         len = pkcs7[1] + 2;
0175         goto check_len;
0176     case ASN1_INDEFINITE_LENGTH:
0177         return 0;
0178     case 0x81:
0179         len = pkcs7[2] + 3;
0180         goto check_len;
0181     case 0x82:
0182         len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
0183         goto check_len;
0184     case 0x83 ... 0xff:
0185         return -EMSGSIZE;
0186     default:
0187         goto not_pkcs7;
0188     }
0189 
0190 check_len:
0191     if (len <= ctx->sig_len) {
0192         /* There may be padding */
0193         ctx->sig_len = len;
0194         return 0;
0195     }
0196 not_pkcs7:
0197     pr_debug("Signature data not PKCS#7\n");
0198     return -ELIBBAD;
0199 }
0200 
0201 /*
0202  * Compare two sections for canonicalisation.
0203  */
0204 static int pefile_compare_shdrs(const void *a, const void *b)
0205 {
0206     const struct section_header *shdra = a;
0207     const struct section_header *shdrb = b;
0208     int rc;
0209 
0210     if (shdra->data_addr > shdrb->data_addr)
0211         return 1;
0212     if (shdrb->data_addr > shdra->data_addr)
0213         return -1;
0214 
0215     if (shdra->virtual_address > shdrb->virtual_address)
0216         return 1;
0217     if (shdrb->virtual_address > shdra->virtual_address)
0218         return -1;
0219 
0220     rc = strcmp(shdra->name, shdrb->name);
0221     if (rc != 0)
0222         return rc;
0223 
0224     if (shdra->virtual_size > shdrb->virtual_size)
0225         return 1;
0226     if (shdrb->virtual_size > shdra->virtual_size)
0227         return -1;
0228 
0229     if (shdra->raw_data_size > shdrb->raw_data_size)
0230         return 1;
0231     if (shdrb->raw_data_size > shdra->raw_data_size)
0232         return -1;
0233 
0234     return 0;
0235 }
0236 
0237 /*
0238  * Load the contents of the PE binary into the digest, leaving out the image
0239  * checksum and the certificate data block.
0240  */
0241 static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,
0242                      struct pefile_context *ctx,
0243                      struct shash_desc *desc)
0244 {
0245     unsigned *canon, tmp, loop, i, hashed_bytes;
0246     int ret;
0247 
0248     /* Digest the header and data directory, but leave out the image
0249      * checksum and the data dirent for the signature.
0250      */
0251     ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset);
0252     if (ret < 0)
0253         return ret;
0254 
0255     tmp = ctx->image_checksum_offset + sizeof(uint32_t);
0256     ret = crypto_shash_update(desc, pebuf + tmp,
0257                   ctx->cert_dirent_offset - tmp);
0258     if (ret < 0)
0259         return ret;
0260 
0261     tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent);
0262     ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp);
0263     if (ret < 0)
0264         return ret;
0265 
0266     canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL);
0267     if (!canon)
0268         return -ENOMEM;
0269 
0270     /* We have to canonicalise the section table, so we perform an
0271      * insertion sort.
0272      */
0273     canon[0] = 0;
0274     for (loop = 1; loop < ctx->n_sections; loop++) {
0275         for (i = 0; i < loop; i++) {
0276             if (pefile_compare_shdrs(&ctx->secs[canon[i]],
0277                          &ctx->secs[loop]) > 0) {
0278                 memmove(&canon[i + 1], &canon[i],
0279                     (loop - i) * sizeof(canon[0]));
0280                 break;
0281             }
0282         }
0283         canon[i] = loop;
0284     }
0285 
0286     hashed_bytes = ctx->header_size;
0287     for (loop = 0; loop < ctx->n_sections; loop++) {
0288         i = canon[loop];
0289         if (ctx->secs[i].raw_data_size == 0)
0290             continue;
0291         ret = crypto_shash_update(desc,
0292                       pebuf + ctx->secs[i].data_addr,
0293                       ctx->secs[i].raw_data_size);
0294         if (ret < 0) {
0295             kfree(canon);
0296             return ret;
0297         }
0298         hashed_bytes += ctx->secs[i].raw_data_size;
0299     }
0300     kfree(canon);
0301 
0302     if (pelen > hashed_bytes) {
0303         tmp = hashed_bytes + ctx->certs_size;
0304         ret = crypto_shash_update(desc,
0305                       pebuf + hashed_bytes,
0306                       pelen - tmp);
0307         if (ret < 0)
0308             return ret;
0309     }
0310 
0311     return 0;
0312 }
0313 
0314 /*
0315  * Digest the contents of the PE binary, leaving out the image checksum and the
0316  * certificate data block.
0317  */
0318 static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
0319                 struct pefile_context *ctx)
0320 {
0321     struct crypto_shash *tfm;
0322     struct shash_desc *desc;
0323     size_t digest_size, desc_size;
0324     void *digest;
0325     int ret;
0326 
0327     kenter(",%s", ctx->digest_algo);
0328 
0329     /* Allocate the hashing algorithm we're going to need and find out how
0330      * big the hash operational data will be.
0331      */
0332     tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
0333     if (IS_ERR(tfm))
0334         return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
0335 
0336     desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
0337     digest_size = crypto_shash_digestsize(tfm);
0338 
0339     if (digest_size != ctx->digest_len) {
0340         pr_debug("Digest size mismatch (%zx != %x)\n",
0341              digest_size, ctx->digest_len);
0342         ret = -EBADMSG;
0343         goto error_no_desc;
0344     }
0345     pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size);
0346 
0347     ret = -ENOMEM;
0348     desc = kzalloc(desc_size + digest_size, GFP_KERNEL);
0349     if (!desc)
0350         goto error_no_desc;
0351 
0352     desc->tfm   = tfm;
0353     ret = crypto_shash_init(desc);
0354     if (ret < 0)
0355         goto error;
0356 
0357     ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc);
0358     if (ret < 0)
0359         goto error;
0360 
0361     digest = (void *)desc + desc_size;
0362     ret = crypto_shash_final(desc, digest);
0363     if (ret < 0)
0364         goto error;
0365 
0366     pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest);
0367 
0368     /* Check that the PE file digest matches that in the MSCODE part of the
0369      * PKCS#7 certificate.
0370      */
0371     if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
0372         pr_debug("Digest mismatch\n");
0373         ret = -EKEYREJECTED;
0374     } else {
0375         pr_debug("The digests match!\n");
0376     }
0377 
0378 error:
0379     kfree_sensitive(desc);
0380 error_no_desc:
0381     crypto_free_shash(tfm);
0382     kleave(" = %d", ret);
0383     return ret;
0384 }
0385 
0386 /**
0387  * verify_pefile_signature - Verify the signature on a PE binary image
0388  * @pebuf: Buffer containing the PE binary image
0389  * @pelen: Length of the binary image
0390  * @trust_keys: Signing certificate(s) to use as starting points
0391  * @usage: The use to which the key is being put.
0392  *
0393  * Validate that the certificate chain inside the PKCS#7 message inside the PE
0394  * binary image intersects keys we already know and trust.
0395  *
0396  * Returns, in order of descending priority:
0397  *
0398  *  (*) -ELIBBAD if the image cannot be parsed, or:
0399  *
0400  *  (*) -EKEYREJECTED if a signature failed to match for which we have a valid
0401  *  key, or:
0402  *
0403  *  (*) 0 if at least one signature chain intersects with the keys in the trust
0404  *  keyring, or:
0405  *
0406  *  (*) -ENODATA if there is no signature present.
0407  *
0408  *  (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
0409  *  chain.
0410  *
0411  *  (*) -ENOKEY if we couldn't find a match for any of the signature chains in
0412  *  the message.
0413  *
0414  * May also return -ENOMEM.
0415  */
0416 int verify_pefile_signature(const void *pebuf, unsigned pelen,
0417                 struct key *trusted_keys,
0418                 enum key_being_used_for usage)
0419 {
0420     struct pefile_context ctx;
0421     int ret;
0422 
0423     kenter("");
0424 
0425     memset(&ctx, 0, sizeof(ctx));
0426     ret = pefile_parse_binary(pebuf, pelen, &ctx);
0427     if (ret < 0)
0428         return ret;
0429 
0430     ret = pefile_strip_sig_wrapper(pebuf, &ctx);
0431     if (ret < 0)
0432         return ret;
0433 
0434     ret = verify_pkcs7_signature(NULL, 0,
0435                      pebuf + ctx.sig_offset, ctx.sig_len,
0436                      trusted_keys, usage,
0437                      mscode_parse, &ctx);
0438     if (ret < 0)
0439         goto error;
0440 
0441     pr_debug("Digest: %u [%*ph]\n",
0442          ctx.digest_len, ctx.digest_len, ctx.digest);
0443 
0444     /* Generate the digest and check against the PKCS7 certificate
0445      * contents.
0446      */
0447     ret = pefile_digest_pe(pebuf, pelen, &ctx);
0448 
0449 error:
0450     kfree_sensitive(ctx.digest);
0451     return ret;
0452 }