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