0001
0002
0003
0004
0005
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
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
0120
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
0139
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
0155
0156
0157
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
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
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
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
0239
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
0249
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
0271
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
0316
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
0330
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
0369
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
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
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
0445
0446
0447 ret = pefile_digest_pe(pebuf, pelen, &ctx);
0448
0449 error:
0450 kfree_sensitive(ctx.digest);
0451 return ret;
0452 }