This source file includes following definitions.
- pefile_parse_binary
- pefile_strip_sig_wrapper
- pefile_compare_shdrs
- pefile_digest_pe_contents
- pefile_digest_pe
- verify_pefile_signature
1
2
3
4
5
6
7
8 #define pr_fmt(fmt) "PEFILE: "fmt
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/slab.h>
12 #include <linux/err.h>
13 #include <linux/pe.h>
14 #include <linux/asn1.h>
15 #include <linux/verification.h>
16 #include <crypto/hash.h>
17 #include "verify_pefile.h"
18
19
20
21
22 static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
23 struct pefile_context *ctx)
24 {
25 const struct mz_hdr *mz = pebuf;
26 const struct pe_hdr *pe;
27 const struct pe32_opt_hdr *pe32;
28 const struct pe32plus_opt_hdr *pe64;
29 const struct data_directory *ddir;
30 const struct data_dirent *dde;
31 const struct section_header *secs, *sec;
32 size_t cursor, datalen = pelen;
33
34 kenter("");
35
36 #define chkaddr(base, x, s) \
37 do { \
38 if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \
39 return -ELIBBAD; \
40 } while (0)
41
42 chkaddr(0, 0, sizeof(*mz));
43 if (mz->magic != MZ_MAGIC)
44 return -ELIBBAD;
45 cursor = sizeof(*mz);
46
47 chkaddr(cursor, mz->peaddr, sizeof(*pe));
48 pe = pebuf + mz->peaddr;
49 if (pe->magic != PE_MAGIC)
50 return -ELIBBAD;
51 cursor = mz->peaddr + sizeof(*pe);
52
53 chkaddr(0, cursor, sizeof(pe32->magic));
54 pe32 = pebuf + cursor;
55 pe64 = pebuf + cursor;
56
57 switch (pe32->magic) {
58 case PE_OPT_MAGIC_PE32:
59 chkaddr(0, cursor, sizeof(*pe32));
60 ctx->image_checksum_offset =
61 (unsigned long)&pe32->csum - (unsigned long)pebuf;
62 ctx->header_size = pe32->header_size;
63 cursor += sizeof(*pe32);
64 ctx->n_data_dirents = pe32->data_dirs;
65 break;
66
67 case PE_OPT_MAGIC_PE32PLUS:
68 chkaddr(0, cursor, sizeof(*pe64));
69 ctx->image_checksum_offset =
70 (unsigned long)&pe64->csum - (unsigned long)pebuf;
71 ctx->header_size = pe64->header_size;
72 cursor += sizeof(*pe64);
73 ctx->n_data_dirents = pe64->data_dirs;
74 break;
75
76 default:
77 pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
78 return -ELIBBAD;
79 }
80
81 pr_debug("checksum @ %x\n", ctx->image_checksum_offset);
82 pr_debug("header size = %x\n", ctx->header_size);
83
84 if (cursor >= ctx->header_size || ctx->header_size >= datalen)
85 return -ELIBBAD;
86
87 if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde))
88 return -ELIBBAD;
89
90 ddir = pebuf + cursor;
91 cursor += sizeof(*dde) * ctx->n_data_dirents;
92
93 ctx->cert_dirent_offset =
94 (unsigned long)&ddir->certs - (unsigned long)pebuf;
95 ctx->certs_size = ddir->certs.size;
96
97 if (!ddir->certs.virtual_address || !ddir->certs.size) {
98 pr_debug("Unsigned PE binary\n");
99 return -ENODATA;
100 }
101
102 chkaddr(ctx->header_size, ddir->certs.virtual_address,
103 ddir->certs.size);
104 ctx->sig_offset = ddir->certs.virtual_address;
105 ctx->sig_len = ddir->certs.size;
106 pr_debug("cert = %x @%x [%*ph]\n",
107 ctx->sig_len, ctx->sig_offset,
108 ctx->sig_len, pebuf + ctx->sig_offset);
109
110 ctx->n_sections = pe->sections;
111 if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec))
112 return -ELIBBAD;
113 ctx->secs = secs = pebuf + cursor;
114
115 return 0;
116 }
117
118
119
120
121
122 static int pefile_strip_sig_wrapper(const void *pebuf,
123 struct pefile_context *ctx)
124 {
125 struct win_certificate wrapper;
126 const u8 *pkcs7;
127 unsigned len;
128
129 if (ctx->sig_len < sizeof(wrapper)) {
130 pr_debug("Signature wrapper too short\n");
131 return -ELIBBAD;
132 }
133
134 memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper));
135 pr_debug("sig wrapper = { %x, %x, %x }\n",
136 wrapper.length, wrapper.revision, wrapper.cert_type);
137
138
139
140
141 if (round_up(wrapper.length, 8) != ctx->sig_len) {
142 pr_debug("Signature wrapper len wrong\n");
143 return -ELIBBAD;
144 }
145 if (wrapper.revision != WIN_CERT_REVISION_2_0) {
146 pr_debug("Signature is not revision 2.0\n");
147 return -ENOTSUPP;
148 }
149 if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
150 pr_debug("Signature certificate type is not PKCS\n");
151 return -ENOTSUPP;
152 }
153
154
155
156
157
158
159 ctx->sig_len = wrapper.length;
160 ctx->sig_offset += sizeof(wrapper);
161 ctx->sig_len -= sizeof(wrapper);
162 if (ctx->sig_len < 4) {
163 pr_debug("Signature data missing\n");
164 return -EKEYREJECTED;
165 }
166
167
168 pkcs7 = pebuf + ctx->sig_offset;
169 if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
170 goto not_pkcs7;
171
172 switch (pkcs7[1]) {
173 case 0 ... 0x7f:
174 len = pkcs7[1] + 2;
175 goto check_len;
176 case ASN1_INDEFINITE_LENGTH:
177 return 0;
178 case 0x81:
179 len = pkcs7[2] + 3;
180 goto check_len;
181 case 0x82:
182 len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
183 goto check_len;
184 case 0x83 ... 0xff:
185 return -EMSGSIZE;
186 default:
187 goto not_pkcs7;
188 }
189
190 check_len:
191 if (len <= ctx->sig_len) {
192
193 ctx->sig_len = len;
194 return 0;
195 }
196 not_pkcs7:
197 pr_debug("Signature data not PKCS#7\n");
198 return -ELIBBAD;
199 }
200
201
202
203
204 static int pefile_compare_shdrs(const void *a, const void *b)
205 {
206 const struct section_header *shdra = a;
207 const struct section_header *shdrb = b;
208 int rc;
209
210 if (shdra->data_addr > shdrb->data_addr)
211 return 1;
212 if (shdrb->data_addr > shdra->data_addr)
213 return -1;
214
215 if (shdra->virtual_address > shdrb->virtual_address)
216 return 1;
217 if (shdrb->virtual_address > shdra->virtual_address)
218 return -1;
219
220 rc = strcmp(shdra->name, shdrb->name);
221 if (rc != 0)
222 return rc;
223
224 if (shdra->virtual_size > shdrb->virtual_size)
225 return 1;
226 if (shdrb->virtual_size > shdra->virtual_size)
227 return -1;
228
229 if (shdra->raw_data_size > shdrb->raw_data_size)
230 return 1;
231 if (shdrb->raw_data_size > shdra->raw_data_size)
232 return -1;
233
234 return 0;
235 }
236
237
238
239
240
241 static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,
242 struct pefile_context *ctx,
243 struct shash_desc *desc)
244 {
245 unsigned *canon, tmp, loop, i, hashed_bytes;
246 int ret;
247
248
249
250
251 ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset);
252 if (ret < 0)
253 return ret;
254
255 tmp = ctx->image_checksum_offset + sizeof(uint32_t);
256 ret = crypto_shash_update(desc, pebuf + tmp,
257 ctx->cert_dirent_offset - tmp);
258 if (ret < 0)
259 return ret;
260
261 tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent);
262 ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp);
263 if (ret < 0)
264 return ret;
265
266 canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL);
267 if (!canon)
268 return -ENOMEM;
269
270
271
272
273 canon[0] = 0;
274 for (loop = 1; loop < ctx->n_sections; loop++) {
275 for (i = 0; i < loop; i++) {
276 if (pefile_compare_shdrs(&ctx->secs[canon[i]],
277 &ctx->secs[loop]) > 0) {
278 memmove(&canon[i + 1], &canon[i],
279 (loop - i) * sizeof(canon[0]));
280 break;
281 }
282 }
283 canon[i] = loop;
284 }
285
286 hashed_bytes = ctx->header_size;
287 for (loop = 0; loop < ctx->n_sections; loop++) {
288 i = canon[loop];
289 if (ctx->secs[i].raw_data_size == 0)
290 continue;
291 ret = crypto_shash_update(desc,
292 pebuf + ctx->secs[i].data_addr,
293 ctx->secs[i].raw_data_size);
294 if (ret < 0) {
295 kfree(canon);
296 return ret;
297 }
298 hashed_bytes += ctx->secs[i].raw_data_size;
299 }
300 kfree(canon);
301
302 if (pelen > hashed_bytes) {
303 tmp = hashed_bytes + ctx->certs_size;
304 ret = crypto_shash_update(desc,
305 pebuf + hashed_bytes,
306 pelen - tmp);
307 if (ret < 0)
308 return ret;
309 }
310
311 return 0;
312 }
313
314
315
316
317
318 static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
319 struct pefile_context *ctx)
320 {
321 struct crypto_shash *tfm;
322 struct shash_desc *desc;
323 size_t digest_size, desc_size;
324 void *digest;
325 int ret;
326
327 kenter(",%s", ctx->digest_algo);
328
329
330
331
332 tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
333 if (IS_ERR(tfm))
334 return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
335
336 desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
337 digest_size = crypto_shash_digestsize(tfm);
338
339 if (digest_size != ctx->digest_len) {
340 pr_debug("Digest size mismatch (%zx != %x)\n",
341 digest_size, ctx->digest_len);
342 ret = -EBADMSG;
343 goto error_no_desc;
344 }
345 pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size);
346
347 ret = -ENOMEM;
348 desc = kzalloc(desc_size + digest_size, GFP_KERNEL);
349 if (!desc)
350 goto error_no_desc;
351
352 desc->tfm = tfm;
353 ret = crypto_shash_init(desc);
354 if (ret < 0)
355 goto error;
356
357 ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc);
358 if (ret < 0)
359 goto error;
360
361 digest = (void *)desc + desc_size;
362 ret = crypto_shash_final(desc, digest);
363 if (ret < 0)
364 goto error;
365
366 pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest);
367
368
369
370
371 if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
372 pr_debug("Digest mismatch\n");
373 ret = -EKEYREJECTED;
374 } else {
375 pr_debug("The digests match!\n");
376 }
377
378 error:
379 kzfree(desc);
380 error_no_desc:
381 crypto_free_shash(tfm);
382 kleave(" = %d", ret);
383 return ret;
384 }
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416 int verify_pefile_signature(const void *pebuf, unsigned pelen,
417 struct key *trusted_keys,
418 enum key_being_used_for usage)
419 {
420 struct pefile_context ctx;
421 int ret;
422
423 kenter("");
424
425 memset(&ctx, 0, sizeof(ctx));
426 ret = pefile_parse_binary(pebuf, pelen, &ctx);
427 if (ret < 0)
428 return ret;
429
430 ret = pefile_strip_sig_wrapper(pebuf, &ctx);
431 if (ret < 0)
432 return ret;
433
434 ret = verify_pkcs7_signature(NULL, 0,
435 pebuf + ctx.sig_offset, ctx.sig_len,
436 trusted_keys, usage,
437 mscode_parse, &ctx);
438 if (ret < 0)
439 goto error;
440
441 pr_debug("Digest: %u [%*ph]\n",
442 ctx.digest_len, ctx.digest_len, ctx.digest);
443
444
445
446
447 ret = pefile_digest_pe(pebuf, pelen, &ctx);
448
449 error:
450 kzfree(ctx.digest);
451 return ret;
452 }