xref: /OK3568_Linux_fs/kernel/crypto/asymmetric_keys/verify_pefile.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /* Parse a signed PE binary
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved.
5*4882a593Smuzhiyun  * Written by David Howells (dhowells@redhat.com)
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #define pr_fmt(fmt) "PEFILE: "fmt
9*4882a593Smuzhiyun #include <linux/module.h>
10*4882a593Smuzhiyun #include <linux/kernel.h>
11*4882a593Smuzhiyun #include <linux/slab.h>
12*4882a593Smuzhiyun #include <linux/err.h>
13*4882a593Smuzhiyun #include <linux/pe.h>
14*4882a593Smuzhiyun #include <linux/asn1.h>
15*4882a593Smuzhiyun #include <linux/verification.h>
16*4882a593Smuzhiyun #include <crypto/hash.h>
17*4882a593Smuzhiyun #include "verify_pefile.h"
18*4882a593Smuzhiyun 
19*4882a593Smuzhiyun /*
20*4882a593Smuzhiyun  * Parse a PE binary.
21*4882a593Smuzhiyun  */
pefile_parse_binary(const void * pebuf,unsigned int pelen,struct pefile_context * ctx)22*4882a593Smuzhiyun static int pefile_parse_binary(const void *pebuf, unsigned int pelen,
23*4882a593Smuzhiyun 			       struct pefile_context *ctx)
24*4882a593Smuzhiyun {
25*4882a593Smuzhiyun 	const struct mz_hdr *mz = pebuf;
26*4882a593Smuzhiyun 	const struct pe_hdr *pe;
27*4882a593Smuzhiyun 	const struct pe32_opt_hdr *pe32;
28*4882a593Smuzhiyun 	const struct pe32plus_opt_hdr *pe64;
29*4882a593Smuzhiyun 	const struct data_directory *ddir;
30*4882a593Smuzhiyun 	const struct data_dirent *dde;
31*4882a593Smuzhiyun 	const struct section_header *secs, *sec;
32*4882a593Smuzhiyun 	size_t cursor, datalen = pelen;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun 	kenter("");
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun #define chkaddr(base, x, s)						\
37*4882a593Smuzhiyun 	do {								\
38*4882a593Smuzhiyun 		if ((x) < base || (s) >= datalen || (x) > datalen - (s)) \
39*4882a593Smuzhiyun 			return -ELIBBAD;				\
40*4882a593Smuzhiyun 	} while (0)
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	chkaddr(0, 0, sizeof(*mz));
43*4882a593Smuzhiyun 	if (mz->magic != MZ_MAGIC)
44*4882a593Smuzhiyun 		return -ELIBBAD;
45*4882a593Smuzhiyun 	cursor = sizeof(*mz);
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	chkaddr(cursor, mz->peaddr, sizeof(*pe));
48*4882a593Smuzhiyun 	pe = pebuf + mz->peaddr;
49*4882a593Smuzhiyun 	if (pe->magic != PE_MAGIC)
50*4882a593Smuzhiyun 		return -ELIBBAD;
51*4882a593Smuzhiyun 	cursor = mz->peaddr + sizeof(*pe);
52*4882a593Smuzhiyun 
53*4882a593Smuzhiyun 	chkaddr(0, cursor, sizeof(pe32->magic));
54*4882a593Smuzhiyun 	pe32 = pebuf + cursor;
55*4882a593Smuzhiyun 	pe64 = pebuf + cursor;
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	switch (pe32->magic) {
58*4882a593Smuzhiyun 	case PE_OPT_MAGIC_PE32:
59*4882a593Smuzhiyun 		chkaddr(0, cursor, sizeof(*pe32));
60*4882a593Smuzhiyun 		ctx->image_checksum_offset =
61*4882a593Smuzhiyun 			(unsigned long)&pe32->csum - (unsigned long)pebuf;
62*4882a593Smuzhiyun 		ctx->header_size = pe32->header_size;
63*4882a593Smuzhiyun 		cursor += sizeof(*pe32);
64*4882a593Smuzhiyun 		ctx->n_data_dirents = pe32->data_dirs;
65*4882a593Smuzhiyun 		break;
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	case PE_OPT_MAGIC_PE32PLUS:
68*4882a593Smuzhiyun 		chkaddr(0, cursor, sizeof(*pe64));
69*4882a593Smuzhiyun 		ctx->image_checksum_offset =
70*4882a593Smuzhiyun 			(unsigned long)&pe64->csum - (unsigned long)pebuf;
71*4882a593Smuzhiyun 		ctx->header_size = pe64->header_size;
72*4882a593Smuzhiyun 		cursor += sizeof(*pe64);
73*4882a593Smuzhiyun 		ctx->n_data_dirents = pe64->data_dirs;
74*4882a593Smuzhiyun 		break;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	default:
77*4882a593Smuzhiyun 		pr_debug("Unknown PEOPT magic = %04hx\n", pe32->magic);
78*4882a593Smuzhiyun 		return -ELIBBAD;
79*4882a593Smuzhiyun 	}
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	pr_debug("checksum @ %x\n", ctx->image_checksum_offset);
82*4882a593Smuzhiyun 	pr_debug("header size = %x\n", ctx->header_size);
83*4882a593Smuzhiyun 
84*4882a593Smuzhiyun 	if (cursor >= ctx->header_size || ctx->header_size >= datalen)
85*4882a593Smuzhiyun 		return -ELIBBAD;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (ctx->n_data_dirents > (ctx->header_size - cursor) / sizeof(*dde))
88*4882a593Smuzhiyun 		return -ELIBBAD;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun 	ddir = pebuf + cursor;
91*4882a593Smuzhiyun 	cursor += sizeof(*dde) * ctx->n_data_dirents;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun 	ctx->cert_dirent_offset =
94*4882a593Smuzhiyun 		(unsigned long)&ddir->certs - (unsigned long)pebuf;
95*4882a593Smuzhiyun 	ctx->certs_size = ddir->certs.size;
96*4882a593Smuzhiyun 
97*4882a593Smuzhiyun 	if (!ddir->certs.virtual_address || !ddir->certs.size) {
98*4882a593Smuzhiyun 		pr_debug("Unsigned PE binary\n");
99*4882a593Smuzhiyun 		return -ENODATA;
100*4882a593Smuzhiyun 	}
101*4882a593Smuzhiyun 
102*4882a593Smuzhiyun 	chkaddr(ctx->header_size, ddir->certs.virtual_address,
103*4882a593Smuzhiyun 		ddir->certs.size);
104*4882a593Smuzhiyun 	ctx->sig_offset = ddir->certs.virtual_address;
105*4882a593Smuzhiyun 	ctx->sig_len = ddir->certs.size;
106*4882a593Smuzhiyun 	pr_debug("cert = %x @%x [%*ph]\n",
107*4882a593Smuzhiyun 		 ctx->sig_len, ctx->sig_offset,
108*4882a593Smuzhiyun 		 ctx->sig_len, pebuf + ctx->sig_offset);
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	ctx->n_sections = pe->sections;
111*4882a593Smuzhiyun 	if (ctx->n_sections > (ctx->header_size - cursor) / sizeof(*sec))
112*4882a593Smuzhiyun 		return -ELIBBAD;
113*4882a593Smuzhiyun 	ctx->secs = secs = pebuf + cursor;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	return 0;
116*4882a593Smuzhiyun }
117*4882a593Smuzhiyun 
118*4882a593Smuzhiyun /*
119*4882a593Smuzhiyun  * Check and strip the PE wrapper from around the signature and check that the
120*4882a593Smuzhiyun  * remnant looks something like PKCS#7.
121*4882a593Smuzhiyun  */
pefile_strip_sig_wrapper(const void * pebuf,struct pefile_context * ctx)122*4882a593Smuzhiyun static int pefile_strip_sig_wrapper(const void *pebuf,
123*4882a593Smuzhiyun 				    struct pefile_context *ctx)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct win_certificate wrapper;
126*4882a593Smuzhiyun 	const u8 *pkcs7;
127*4882a593Smuzhiyun 	unsigned len;
128*4882a593Smuzhiyun 
129*4882a593Smuzhiyun 	if (ctx->sig_len < sizeof(wrapper)) {
130*4882a593Smuzhiyun 		pr_debug("Signature wrapper too short\n");
131*4882a593Smuzhiyun 		return -ELIBBAD;
132*4882a593Smuzhiyun 	}
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	memcpy(&wrapper, pebuf + ctx->sig_offset, sizeof(wrapper));
135*4882a593Smuzhiyun 	pr_debug("sig wrapper = { %x, %x, %x }\n",
136*4882a593Smuzhiyun 		 wrapper.length, wrapper.revision, wrapper.cert_type);
137*4882a593Smuzhiyun 
138*4882a593Smuzhiyun 	/* Both pesign and sbsign round up the length of certificate table
139*4882a593Smuzhiyun 	 * (in optional header data directories) to 8 byte alignment.
140*4882a593Smuzhiyun 	 */
141*4882a593Smuzhiyun 	if (round_up(wrapper.length, 8) != ctx->sig_len) {
142*4882a593Smuzhiyun 		pr_debug("Signature wrapper len wrong\n");
143*4882a593Smuzhiyun 		return -ELIBBAD;
144*4882a593Smuzhiyun 	}
145*4882a593Smuzhiyun 	if (wrapper.revision != WIN_CERT_REVISION_2_0) {
146*4882a593Smuzhiyun 		pr_debug("Signature is not revision 2.0\n");
147*4882a593Smuzhiyun 		return -ENOTSUPP;
148*4882a593Smuzhiyun 	}
149*4882a593Smuzhiyun 	if (wrapper.cert_type != WIN_CERT_TYPE_PKCS_SIGNED_DATA) {
150*4882a593Smuzhiyun 		pr_debug("Signature certificate type is not PKCS\n");
151*4882a593Smuzhiyun 		return -ENOTSUPP;
152*4882a593Smuzhiyun 	}
153*4882a593Smuzhiyun 
154*4882a593Smuzhiyun 	/* It looks like the pkcs signature length in wrapper->length and the
155*4882a593Smuzhiyun 	 * size obtained from the data dir entries, which lists the total size
156*4882a593Smuzhiyun 	 * of certificate table, are both aligned to an octaword boundary, so
157*4882a593Smuzhiyun 	 * we may have to deal with some padding.
158*4882a593Smuzhiyun 	 */
159*4882a593Smuzhiyun 	ctx->sig_len = wrapper.length;
160*4882a593Smuzhiyun 	ctx->sig_offset += sizeof(wrapper);
161*4882a593Smuzhiyun 	ctx->sig_len -= sizeof(wrapper);
162*4882a593Smuzhiyun 	if (ctx->sig_len < 4) {
163*4882a593Smuzhiyun 		pr_debug("Signature data missing\n");
164*4882a593Smuzhiyun 		return -EKEYREJECTED;
165*4882a593Smuzhiyun 	}
166*4882a593Smuzhiyun 
167*4882a593Smuzhiyun 	/* What's left should be a PKCS#7 cert */
168*4882a593Smuzhiyun 	pkcs7 = pebuf + ctx->sig_offset;
169*4882a593Smuzhiyun 	if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
170*4882a593Smuzhiyun 		goto not_pkcs7;
171*4882a593Smuzhiyun 
172*4882a593Smuzhiyun 	switch (pkcs7[1]) {
173*4882a593Smuzhiyun 	case 0 ... 0x7f:
174*4882a593Smuzhiyun 		len = pkcs7[1] + 2;
175*4882a593Smuzhiyun 		goto check_len;
176*4882a593Smuzhiyun 	case ASN1_INDEFINITE_LENGTH:
177*4882a593Smuzhiyun 		return 0;
178*4882a593Smuzhiyun 	case 0x81:
179*4882a593Smuzhiyun 		len = pkcs7[2] + 3;
180*4882a593Smuzhiyun 		goto check_len;
181*4882a593Smuzhiyun 	case 0x82:
182*4882a593Smuzhiyun 		len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
183*4882a593Smuzhiyun 		goto check_len;
184*4882a593Smuzhiyun 	case 0x83 ... 0xff:
185*4882a593Smuzhiyun 		return -EMSGSIZE;
186*4882a593Smuzhiyun 	default:
187*4882a593Smuzhiyun 		goto not_pkcs7;
188*4882a593Smuzhiyun 	}
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun check_len:
191*4882a593Smuzhiyun 	if (len <= ctx->sig_len) {
192*4882a593Smuzhiyun 		/* There may be padding */
193*4882a593Smuzhiyun 		ctx->sig_len = len;
194*4882a593Smuzhiyun 		return 0;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun not_pkcs7:
197*4882a593Smuzhiyun 	pr_debug("Signature data not PKCS#7\n");
198*4882a593Smuzhiyun 	return -ELIBBAD;
199*4882a593Smuzhiyun }
200*4882a593Smuzhiyun 
201*4882a593Smuzhiyun /*
202*4882a593Smuzhiyun  * Compare two sections for canonicalisation.
203*4882a593Smuzhiyun  */
pefile_compare_shdrs(const void * a,const void * b)204*4882a593Smuzhiyun static int pefile_compare_shdrs(const void *a, const void *b)
205*4882a593Smuzhiyun {
206*4882a593Smuzhiyun 	const struct section_header *shdra = a;
207*4882a593Smuzhiyun 	const struct section_header *shdrb = b;
208*4882a593Smuzhiyun 	int rc;
209*4882a593Smuzhiyun 
210*4882a593Smuzhiyun 	if (shdra->data_addr > shdrb->data_addr)
211*4882a593Smuzhiyun 		return 1;
212*4882a593Smuzhiyun 	if (shdrb->data_addr > shdra->data_addr)
213*4882a593Smuzhiyun 		return -1;
214*4882a593Smuzhiyun 
215*4882a593Smuzhiyun 	if (shdra->virtual_address > shdrb->virtual_address)
216*4882a593Smuzhiyun 		return 1;
217*4882a593Smuzhiyun 	if (shdrb->virtual_address > shdra->virtual_address)
218*4882a593Smuzhiyun 		return -1;
219*4882a593Smuzhiyun 
220*4882a593Smuzhiyun 	rc = strcmp(shdra->name, shdrb->name);
221*4882a593Smuzhiyun 	if (rc != 0)
222*4882a593Smuzhiyun 		return rc;
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	if (shdra->virtual_size > shdrb->virtual_size)
225*4882a593Smuzhiyun 		return 1;
226*4882a593Smuzhiyun 	if (shdrb->virtual_size > shdra->virtual_size)
227*4882a593Smuzhiyun 		return -1;
228*4882a593Smuzhiyun 
229*4882a593Smuzhiyun 	if (shdra->raw_data_size > shdrb->raw_data_size)
230*4882a593Smuzhiyun 		return 1;
231*4882a593Smuzhiyun 	if (shdrb->raw_data_size > shdra->raw_data_size)
232*4882a593Smuzhiyun 		return -1;
233*4882a593Smuzhiyun 
234*4882a593Smuzhiyun 	return 0;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun 
237*4882a593Smuzhiyun /*
238*4882a593Smuzhiyun  * Load the contents of the PE binary into the digest, leaving out the image
239*4882a593Smuzhiyun  * checksum and the certificate data block.
240*4882a593Smuzhiyun  */
pefile_digest_pe_contents(const void * pebuf,unsigned int pelen,struct pefile_context * ctx,struct shash_desc * desc)241*4882a593Smuzhiyun static int pefile_digest_pe_contents(const void *pebuf, unsigned int pelen,
242*4882a593Smuzhiyun 				     struct pefile_context *ctx,
243*4882a593Smuzhiyun 				     struct shash_desc *desc)
244*4882a593Smuzhiyun {
245*4882a593Smuzhiyun 	unsigned *canon, tmp, loop, i, hashed_bytes;
246*4882a593Smuzhiyun 	int ret;
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	/* Digest the header and data directory, but leave out the image
249*4882a593Smuzhiyun 	 * checksum and the data dirent for the signature.
250*4882a593Smuzhiyun 	 */
251*4882a593Smuzhiyun 	ret = crypto_shash_update(desc, pebuf, ctx->image_checksum_offset);
252*4882a593Smuzhiyun 	if (ret < 0)
253*4882a593Smuzhiyun 		return ret;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	tmp = ctx->image_checksum_offset + sizeof(uint32_t);
256*4882a593Smuzhiyun 	ret = crypto_shash_update(desc, pebuf + tmp,
257*4882a593Smuzhiyun 				  ctx->cert_dirent_offset - tmp);
258*4882a593Smuzhiyun 	if (ret < 0)
259*4882a593Smuzhiyun 		return ret;
260*4882a593Smuzhiyun 
261*4882a593Smuzhiyun 	tmp = ctx->cert_dirent_offset + sizeof(struct data_dirent);
262*4882a593Smuzhiyun 	ret = crypto_shash_update(desc, pebuf + tmp, ctx->header_size - tmp);
263*4882a593Smuzhiyun 	if (ret < 0)
264*4882a593Smuzhiyun 		return ret;
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	canon = kcalloc(ctx->n_sections, sizeof(unsigned), GFP_KERNEL);
267*4882a593Smuzhiyun 	if (!canon)
268*4882a593Smuzhiyun 		return -ENOMEM;
269*4882a593Smuzhiyun 
270*4882a593Smuzhiyun 	/* We have to canonicalise the section table, so we perform an
271*4882a593Smuzhiyun 	 * insertion sort.
272*4882a593Smuzhiyun 	 */
273*4882a593Smuzhiyun 	canon[0] = 0;
274*4882a593Smuzhiyun 	for (loop = 1; loop < ctx->n_sections; loop++) {
275*4882a593Smuzhiyun 		for (i = 0; i < loop; i++) {
276*4882a593Smuzhiyun 			if (pefile_compare_shdrs(&ctx->secs[canon[i]],
277*4882a593Smuzhiyun 						 &ctx->secs[loop]) > 0) {
278*4882a593Smuzhiyun 				memmove(&canon[i + 1], &canon[i],
279*4882a593Smuzhiyun 					(loop - i) * sizeof(canon[0]));
280*4882a593Smuzhiyun 				break;
281*4882a593Smuzhiyun 			}
282*4882a593Smuzhiyun 		}
283*4882a593Smuzhiyun 		canon[i] = loop;
284*4882a593Smuzhiyun 	}
285*4882a593Smuzhiyun 
286*4882a593Smuzhiyun 	hashed_bytes = ctx->header_size;
287*4882a593Smuzhiyun 	for (loop = 0; loop < ctx->n_sections; loop++) {
288*4882a593Smuzhiyun 		i = canon[loop];
289*4882a593Smuzhiyun 		if (ctx->secs[i].raw_data_size == 0)
290*4882a593Smuzhiyun 			continue;
291*4882a593Smuzhiyun 		ret = crypto_shash_update(desc,
292*4882a593Smuzhiyun 					  pebuf + ctx->secs[i].data_addr,
293*4882a593Smuzhiyun 					  ctx->secs[i].raw_data_size);
294*4882a593Smuzhiyun 		if (ret < 0) {
295*4882a593Smuzhiyun 			kfree(canon);
296*4882a593Smuzhiyun 			return ret;
297*4882a593Smuzhiyun 		}
298*4882a593Smuzhiyun 		hashed_bytes += ctx->secs[i].raw_data_size;
299*4882a593Smuzhiyun 	}
300*4882a593Smuzhiyun 	kfree(canon);
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (pelen > hashed_bytes) {
303*4882a593Smuzhiyun 		tmp = hashed_bytes + ctx->certs_size;
304*4882a593Smuzhiyun 		ret = crypto_shash_update(desc,
305*4882a593Smuzhiyun 					  pebuf + hashed_bytes,
306*4882a593Smuzhiyun 					  pelen - tmp);
307*4882a593Smuzhiyun 		if (ret < 0)
308*4882a593Smuzhiyun 			return ret;
309*4882a593Smuzhiyun 	}
310*4882a593Smuzhiyun 
311*4882a593Smuzhiyun 	return 0;
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun /*
315*4882a593Smuzhiyun  * Digest the contents of the PE binary, leaving out the image checksum and the
316*4882a593Smuzhiyun  * certificate data block.
317*4882a593Smuzhiyun  */
pefile_digest_pe(const void * pebuf,unsigned int pelen,struct pefile_context * ctx)318*4882a593Smuzhiyun static int pefile_digest_pe(const void *pebuf, unsigned int pelen,
319*4882a593Smuzhiyun 			    struct pefile_context *ctx)
320*4882a593Smuzhiyun {
321*4882a593Smuzhiyun 	struct crypto_shash *tfm;
322*4882a593Smuzhiyun 	struct shash_desc *desc;
323*4882a593Smuzhiyun 	size_t digest_size, desc_size;
324*4882a593Smuzhiyun 	void *digest;
325*4882a593Smuzhiyun 	int ret;
326*4882a593Smuzhiyun 
327*4882a593Smuzhiyun 	kenter(",%s", ctx->digest_algo);
328*4882a593Smuzhiyun 
329*4882a593Smuzhiyun 	/* Allocate the hashing algorithm we're going to need and find out how
330*4882a593Smuzhiyun 	 * big the hash operational data will be.
331*4882a593Smuzhiyun 	 */
332*4882a593Smuzhiyun 	tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0);
333*4882a593Smuzhiyun 	if (IS_ERR(tfm))
334*4882a593Smuzhiyun 		return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm);
335*4882a593Smuzhiyun 
336*4882a593Smuzhiyun 	desc_size = crypto_shash_descsize(tfm) + sizeof(*desc);
337*4882a593Smuzhiyun 	digest_size = crypto_shash_digestsize(tfm);
338*4882a593Smuzhiyun 
339*4882a593Smuzhiyun 	if (digest_size != ctx->digest_len) {
340*4882a593Smuzhiyun 		pr_debug("Digest size mismatch (%zx != %x)\n",
341*4882a593Smuzhiyun 			 digest_size, ctx->digest_len);
342*4882a593Smuzhiyun 		ret = -EBADMSG;
343*4882a593Smuzhiyun 		goto error_no_desc;
344*4882a593Smuzhiyun 	}
345*4882a593Smuzhiyun 	pr_debug("Digest: desc=%zu size=%zu\n", desc_size, digest_size);
346*4882a593Smuzhiyun 
347*4882a593Smuzhiyun 	ret = -ENOMEM;
348*4882a593Smuzhiyun 	desc = kzalloc(desc_size + digest_size, GFP_KERNEL);
349*4882a593Smuzhiyun 	if (!desc)
350*4882a593Smuzhiyun 		goto error_no_desc;
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	desc->tfm   = tfm;
353*4882a593Smuzhiyun 	ret = crypto_shash_init(desc);
354*4882a593Smuzhiyun 	if (ret < 0)
355*4882a593Smuzhiyun 		goto error;
356*4882a593Smuzhiyun 
357*4882a593Smuzhiyun 	ret = pefile_digest_pe_contents(pebuf, pelen, ctx, desc);
358*4882a593Smuzhiyun 	if (ret < 0)
359*4882a593Smuzhiyun 		goto error;
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	digest = (void *)desc + desc_size;
362*4882a593Smuzhiyun 	ret = crypto_shash_final(desc, digest);
363*4882a593Smuzhiyun 	if (ret < 0)
364*4882a593Smuzhiyun 		goto error;
365*4882a593Smuzhiyun 
366*4882a593Smuzhiyun 	pr_debug("Digest calc = [%*ph]\n", ctx->digest_len, digest);
367*4882a593Smuzhiyun 
368*4882a593Smuzhiyun 	/* Check that the PE file digest matches that in the MSCODE part of the
369*4882a593Smuzhiyun 	 * PKCS#7 certificate.
370*4882a593Smuzhiyun 	 */
371*4882a593Smuzhiyun 	if (memcmp(digest, ctx->digest, ctx->digest_len) != 0) {
372*4882a593Smuzhiyun 		pr_debug("Digest mismatch\n");
373*4882a593Smuzhiyun 		ret = -EKEYREJECTED;
374*4882a593Smuzhiyun 	} else {
375*4882a593Smuzhiyun 		pr_debug("The digests match!\n");
376*4882a593Smuzhiyun 	}
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun error:
379*4882a593Smuzhiyun 	kfree_sensitive(desc);
380*4882a593Smuzhiyun error_no_desc:
381*4882a593Smuzhiyun 	crypto_free_shash(tfm);
382*4882a593Smuzhiyun 	kleave(" = %d", ret);
383*4882a593Smuzhiyun 	return ret;
384*4882a593Smuzhiyun }
385*4882a593Smuzhiyun 
386*4882a593Smuzhiyun /**
387*4882a593Smuzhiyun  * verify_pefile_signature - Verify the signature on a PE binary image
388*4882a593Smuzhiyun  * @pebuf: Buffer containing the PE binary image
389*4882a593Smuzhiyun  * @pelen: Length of the binary image
390*4882a593Smuzhiyun  * @trust_keys: Signing certificate(s) to use as starting points
391*4882a593Smuzhiyun  * @usage: The use to which the key is being put.
392*4882a593Smuzhiyun  *
393*4882a593Smuzhiyun  * Validate that the certificate chain inside the PKCS#7 message inside the PE
394*4882a593Smuzhiyun  * binary image intersects keys we already know and trust.
395*4882a593Smuzhiyun  *
396*4882a593Smuzhiyun  * Returns, in order of descending priority:
397*4882a593Smuzhiyun  *
398*4882a593Smuzhiyun  *  (*) -ELIBBAD if the image cannot be parsed, or:
399*4882a593Smuzhiyun  *
400*4882a593Smuzhiyun  *  (*) -EKEYREJECTED if a signature failed to match for which we have a valid
401*4882a593Smuzhiyun  *	key, or:
402*4882a593Smuzhiyun  *
403*4882a593Smuzhiyun  *  (*) 0 if at least one signature chain intersects with the keys in the trust
404*4882a593Smuzhiyun  *	keyring, or:
405*4882a593Smuzhiyun  *
406*4882a593Smuzhiyun  *  (*) -ENODATA if there is no signature present.
407*4882a593Smuzhiyun  *
408*4882a593Smuzhiyun  *  (*) -ENOPKG if a suitable crypto module couldn't be found for a check on a
409*4882a593Smuzhiyun  *	chain.
410*4882a593Smuzhiyun  *
411*4882a593Smuzhiyun  *  (*) -ENOKEY if we couldn't find a match for any of the signature chains in
412*4882a593Smuzhiyun  *	the message.
413*4882a593Smuzhiyun  *
414*4882a593Smuzhiyun  * May also return -ENOMEM.
415*4882a593Smuzhiyun  */
verify_pefile_signature(const void * pebuf,unsigned pelen,struct key * trusted_keys,enum key_being_used_for usage)416*4882a593Smuzhiyun int verify_pefile_signature(const void *pebuf, unsigned pelen,
417*4882a593Smuzhiyun 			    struct key *trusted_keys,
418*4882a593Smuzhiyun 			    enum key_being_used_for usage)
419*4882a593Smuzhiyun {
420*4882a593Smuzhiyun 	struct pefile_context ctx;
421*4882a593Smuzhiyun 	int ret;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 	kenter("");
424*4882a593Smuzhiyun 
425*4882a593Smuzhiyun 	memset(&ctx, 0, sizeof(ctx));
426*4882a593Smuzhiyun 	ret = pefile_parse_binary(pebuf, pelen, &ctx);
427*4882a593Smuzhiyun 	if (ret < 0)
428*4882a593Smuzhiyun 		return ret;
429*4882a593Smuzhiyun 
430*4882a593Smuzhiyun 	ret = pefile_strip_sig_wrapper(pebuf, &ctx);
431*4882a593Smuzhiyun 	if (ret < 0)
432*4882a593Smuzhiyun 		return ret;
433*4882a593Smuzhiyun 
434*4882a593Smuzhiyun 	ret = verify_pkcs7_signature(NULL, 0,
435*4882a593Smuzhiyun 				     pebuf + ctx.sig_offset, ctx.sig_len,
436*4882a593Smuzhiyun 				     trusted_keys, usage,
437*4882a593Smuzhiyun 				     mscode_parse, &ctx);
438*4882a593Smuzhiyun 	if (ret < 0)
439*4882a593Smuzhiyun 		goto error;
440*4882a593Smuzhiyun 
441*4882a593Smuzhiyun 	pr_debug("Digest: %u [%*ph]\n",
442*4882a593Smuzhiyun 		 ctx.digest_len, ctx.digest_len, ctx.digest);
443*4882a593Smuzhiyun 
444*4882a593Smuzhiyun 	/* Generate the digest and check against the PKCS7 certificate
445*4882a593Smuzhiyun 	 * contents.
446*4882a593Smuzhiyun 	 */
447*4882a593Smuzhiyun 	ret = pefile_digest_pe(pebuf, pelen, &ctx);
448*4882a593Smuzhiyun 
449*4882a593Smuzhiyun error:
450*4882a593Smuzhiyun 	kfree_sensitive(ctx.digest);
451*4882a593Smuzhiyun 	return ret;
452*4882a593Smuzhiyun }
453