xref: /linux/crypto/asymmetric_keys/pkcs7_parser.c (revision bf4afc53b77aeaa48b5409da5c8da6bb4eff7f43)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /* PKCS#7 parser
3  *
4  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
5  * Written by David Howells (dhowells@redhat.com)
6  */
7 
8 #define pr_fmt(fmt) "PKCS7: "fmt
9 #include <linux/kernel.h>
10 #include <linux/module.h>
11 #include <linux/export.h>
12 #include <linux/slab.h>
13 #include <linux/err.h>
14 #include <linux/oid_registry.h>
15 #include <crypto/public_key.h>
16 #include "pkcs7_parser.h"
17 #include "pkcs7.asn1.h"
18 
19 MODULE_DESCRIPTION("PKCS#7 parser");
20 MODULE_AUTHOR("Red Hat, Inc.");
21 MODULE_LICENSE("GPL");
22 
23 struct pkcs7_parse_context {
24 	struct pkcs7_message	*msg;		/* Message being constructed */
25 	struct pkcs7_signed_info *sinfo;	/* SignedInfo being constructed */
26 	struct pkcs7_signed_info **ppsinfo;
27 	struct x509_certificate *certs;		/* Certificate cache */
28 	struct x509_certificate **ppcerts;
29 	unsigned long	data;			/* Start of data */
30 	enum OID	last_oid;		/* Last OID encountered */
31 	unsigned	x509_index;
32 	unsigned	sinfo_index;
33 	const void	*raw_serial;
34 	unsigned	raw_serial_size;
35 	unsigned	raw_issuer_size;
36 	const void	*raw_issuer;
37 	const void	*raw_skid;
38 	unsigned	raw_skid_size;
39 	bool		expect_skid;
40 };
41 
42 /*
43  * Free a signed information block.
44  */
pkcs7_free_signed_info(struct pkcs7_signed_info * sinfo)45 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
46 {
47 	if (sinfo) {
48 		public_key_signature_free(sinfo->sig);
49 		kfree(sinfo);
50 	}
51 }
52 
53 /**
54  * pkcs7_free_message - Free a PKCS#7 message
55  * @pkcs7: The PKCS#7 message to free
56  */
pkcs7_free_message(struct pkcs7_message * pkcs7)57 void pkcs7_free_message(struct pkcs7_message *pkcs7)
58 {
59 	struct x509_certificate *cert;
60 	struct pkcs7_signed_info *sinfo;
61 
62 	if (pkcs7) {
63 		while (pkcs7->certs) {
64 			cert = pkcs7->certs;
65 			pkcs7->certs = cert->next;
66 			x509_free_certificate(cert);
67 		}
68 		while (pkcs7->crl) {
69 			cert = pkcs7->crl;
70 			pkcs7->crl = cert->next;
71 			x509_free_certificate(cert);
72 		}
73 		while (pkcs7->signed_infos) {
74 			sinfo = pkcs7->signed_infos;
75 			pkcs7->signed_infos = sinfo->next;
76 			pkcs7_free_signed_info(sinfo);
77 		}
78 		kfree(pkcs7);
79 	}
80 }
81 EXPORT_SYMBOL_GPL(pkcs7_free_message);
82 
83 /*
84  * Check authenticatedAttributes are provided or not provided consistently.
85  */
pkcs7_check_authattrs(struct pkcs7_message * msg)86 static int pkcs7_check_authattrs(struct pkcs7_message *msg)
87 {
88 	struct pkcs7_signed_info *sinfo;
89 	bool want = false;
90 
91 	sinfo = msg->signed_infos;
92 	if (!sinfo)
93 		goto inconsistent;
94 
95 #ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
96 	msg->authattrs_rej_waivable = true;
97 #endif
98 
99 	if (sinfo->authattrs) {
100 		want = true;
101 		msg->have_authattrs = true;
102 #ifdef CONFIG_PKCS7_WAIVE_AUTHATTRS_REJECTION_FOR_MLDSA
103 		if (strncmp(sinfo->sig->pkey_algo, "mldsa", 5) != 0)
104 			msg->authattrs_rej_waivable = false;
105 #endif
106 	} else if (sinfo->sig->algo_takes_data) {
107 		sinfo->sig->hash_algo = "none";
108 	}
109 
110 	for (sinfo = sinfo->next; sinfo; sinfo = sinfo->next) {
111 		if (!!sinfo->authattrs != want)
112 			goto inconsistent;
113 
114 		if (!sinfo->authattrs &&
115 		    sinfo->sig->algo_takes_data)
116 			sinfo->sig->hash_algo = "none";
117 	}
118 	return 0;
119 
120 inconsistent:
121 	pr_warn("Inconsistently supplied authAttrs\n");
122 	return -EINVAL;
123 }
124 
125 /**
126  * pkcs7_parse_message - Parse a PKCS#7 message
127  * @data: The raw binary ASN.1 encoded message to be parsed
128  * @datalen: The size of the encoded message
129  */
pkcs7_parse_message(const void * data,size_t datalen)130 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
131 {
132 	struct pkcs7_parse_context *ctx;
133 	struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
134 	int ret;
135 
136 	ctx = kzalloc_obj(struct pkcs7_parse_context);
137 	if (!ctx)
138 		goto out_no_ctx;
139 	ctx->msg = kzalloc_obj(struct pkcs7_message);
140 	if (!ctx->msg)
141 		goto out_no_msg;
142 	ctx->sinfo = kzalloc_obj(struct pkcs7_signed_info);
143 	if (!ctx->sinfo)
144 		goto out_no_sinfo;
145 	ctx->sinfo->sig = kzalloc_obj(struct public_key_signature);
146 	if (!ctx->sinfo->sig)
147 		goto out_no_sig;
148 
149 	ctx->data = (unsigned long)data;
150 	ctx->ppcerts = &ctx->certs;
151 	ctx->ppsinfo = &ctx->msg->signed_infos;
152 
153 	/* Attempt to decode the signature */
154 	ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
155 	if (ret < 0) {
156 		msg = ERR_PTR(ret);
157 		goto out;
158 	}
159 
160 	ret = pkcs7_check_authattrs(ctx->msg);
161 	if (ret < 0) {
162 		msg = ERR_PTR(ret);
163 		goto out;
164 	}
165 
166 	msg = ctx->msg;
167 	ctx->msg = NULL;
168 
169 out:
170 	while (ctx->certs) {
171 		struct x509_certificate *cert = ctx->certs;
172 		ctx->certs = cert->next;
173 		x509_free_certificate(cert);
174 	}
175 out_no_sig:
176 	pkcs7_free_signed_info(ctx->sinfo);
177 out_no_sinfo:
178 	pkcs7_free_message(ctx->msg);
179 out_no_msg:
180 	kfree(ctx);
181 out_no_ctx:
182 	return msg;
183 }
184 EXPORT_SYMBOL_GPL(pkcs7_parse_message);
185 
186 /**
187  * pkcs7_get_content_data - Get access to the PKCS#7 content
188  * @pkcs7: The preparsed PKCS#7 message to access
189  * @_data: Place to return a pointer to the data
190  * @_data_len: Place to return the data length
191  * @_headerlen: Size of ASN.1 header not included in _data
192  *
193  * Get access to the data content of the PKCS#7 message.  The size of the
194  * header of the ASN.1 object that contains it is also provided and can be used
195  * to adjust *_data and *_data_len to get the entire object.
196  *
197  * Returns -ENODATA if the data object was missing from the message.
198  */
pkcs7_get_content_data(const struct pkcs7_message * pkcs7,const void ** _data,size_t * _data_len,size_t * _headerlen)199 int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
200 			   const void **_data, size_t *_data_len,
201 			   size_t *_headerlen)
202 {
203 	if (!pkcs7->data)
204 		return -ENODATA;
205 
206 	*_data = pkcs7->data;
207 	*_data_len = pkcs7->data_len;
208 	if (_headerlen)
209 		*_headerlen = pkcs7->data_hdrlen;
210 	return 0;
211 }
212 EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
213 
214 /*
215  * Note an OID when we find one for later processing when we know how
216  * to interpret it.
217  */
pkcs7_note_OID(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)218 int pkcs7_note_OID(void *context, size_t hdrlen,
219 		   unsigned char tag,
220 		   const void *value, size_t vlen)
221 {
222 	struct pkcs7_parse_context *ctx = context;
223 
224 	ctx->last_oid = look_up_OID(value, vlen);
225 	if (ctx->last_oid == OID__NR) {
226 		char buffer[50];
227 		sprint_oid(value, vlen, buffer, sizeof(buffer));
228 		printk("PKCS7: Unknown OID: [%lu] %s\n",
229 		       (unsigned long)value - ctx->data, buffer);
230 	}
231 	return 0;
232 }
233 
234 /*
235  * Note the digest algorithm for the signature.
236  */
pkcs7_sig_note_digest_algo(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)237 int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
238 			       unsigned char tag,
239 			       const void *value, size_t vlen)
240 {
241 	struct pkcs7_parse_context *ctx = context;
242 
243 	switch (ctx->last_oid) {
244 	case OID_sha1:
245 		ctx->sinfo->sig->hash_algo = "sha1";
246 		break;
247 	case OID_sha256:
248 		ctx->sinfo->sig->hash_algo = "sha256";
249 		break;
250 	case OID_sha384:
251 		ctx->sinfo->sig->hash_algo = "sha384";
252 		break;
253 	case OID_sha512:
254 		ctx->sinfo->sig->hash_algo = "sha512";
255 		break;
256 	case OID_sha224:
257 		ctx->sinfo->sig->hash_algo = "sha224";
258 		break;
259 	case OID_sm3:
260 		ctx->sinfo->sig->hash_algo = "sm3";
261 		break;
262 	case OID_gost2012Digest256:
263 		ctx->sinfo->sig->hash_algo = "streebog256";
264 		break;
265 	case OID_gost2012Digest512:
266 		ctx->sinfo->sig->hash_algo = "streebog512";
267 		break;
268 	case OID_sha3_256:
269 		ctx->sinfo->sig->hash_algo = "sha3-256";
270 		break;
271 	case OID_sha3_384:
272 		ctx->sinfo->sig->hash_algo = "sha3-384";
273 		break;
274 	case OID_sha3_512:
275 		ctx->sinfo->sig->hash_algo = "sha3-512";
276 		break;
277 	default:
278 		printk("Unsupported digest algo: %u\n", ctx->last_oid);
279 		return -ENOPKG;
280 	}
281 	return 0;
282 }
283 
284 /*
285  * Note the public key algorithm for the signature.
286  */
pkcs7_sig_note_pkey_algo(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)287 int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
288 			     unsigned char tag,
289 			     const void *value, size_t vlen)
290 {
291 	struct pkcs7_parse_context *ctx = context;
292 
293 	switch (ctx->last_oid) {
294 	case OID_rsaEncryption:
295 		ctx->sinfo->sig->pkey_algo = "rsa";
296 		ctx->sinfo->sig->encoding = "pkcs1";
297 		break;
298 	case OID_id_ecdsa_with_sha1:
299 	case OID_id_ecdsa_with_sha224:
300 	case OID_id_ecdsa_with_sha256:
301 	case OID_id_ecdsa_with_sha384:
302 	case OID_id_ecdsa_with_sha512:
303 	case OID_id_ecdsa_with_sha3_256:
304 	case OID_id_ecdsa_with_sha3_384:
305 	case OID_id_ecdsa_with_sha3_512:
306 		ctx->sinfo->sig->pkey_algo = "ecdsa";
307 		ctx->sinfo->sig->encoding = "x962";
308 		break;
309 	case OID_gost2012PKey256:
310 	case OID_gost2012PKey512:
311 		ctx->sinfo->sig->pkey_algo = "ecrdsa";
312 		ctx->sinfo->sig->encoding = "raw";
313 		break;
314 	case OID_id_ml_dsa_44:
315 		ctx->sinfo->sig->pkey_algo = "mldsa44";
316 		ctx->sinfo->sig->encoding = "raw";
317 		ctx->sinfo->sig->algo_takes_data = true;
318 		break;
319 	case OID_id_ml_dsa_65:
320 		ctx->sinfo->sig->pkey_algo = "mldsa65";
321 		ctx->sinfo->sig->encoding = "raw";
322 		ctx->sinfo->sig->algo_takes_data = true;
323 		break;
324 	case OID_id_ml_dsa_87:
325 		ctx->sinfo->sig->pkey_algo = "mldsa87";
326 		ctx->sinfo->sig->encoding = "raw";
327 		ctx->sinfo->sig->algo_takes_data = true;
328 		break;
329 	default:
330 		printk("Unsupported pkey algo: %u\n", ctx->last_oid);
331 		return -ENOPKG;
332 	}
333 	return 0;
334 }
335 
336 /*
337  * We only support signed data [RFC2315 sec 9].
338  */
pkcs7_check_content_type(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)339 int pkcs7_check_content_type(void *context, size_t hdrlen,
340 			     unsigned char tag,
341 			     const void *value, size_t vlen)
342 {
343 	struct pkcs7_parse_context *ctx = context;
344 
345 	if (ctx->last_oid != OID_signed_data) {
346 		pr_warn("Only support pkcs7_signedData type\n");
347 		return -EINVAL;
348 	}
349 
350 	return 0;
351 }
352 
353 /*
354  * Note the SignedData version
355  */
pkcs7_note_signeddata_version(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)356 int pkcs7_note_signeddata_version(void *context, size_t hdrlen,
357 				  unsigned char tag,
358 				  const void *value, size_t vlen)
359 {
360 	struct pkcs7_parse_context *ctx = context;
361 	unsigned version;
362 
363 	if (vlen != 1)
364 		goto unsupported;
365 
366 	ctx->msg->version = version = *(const u8 *)value;
367 	switch (version) {
368 	case 1:
369 		/* PKCS#7 SignedData [RFC2315 sec 9.1]
370 		 * CMS ver 1 SignedData [RFC5652 sec 5.1]
371 		 */
372 		break;
373 	case 3:
374 		/* CMS ver 3 SignedData [RFC2315 sec 5.1] */
375 		break;
376 	default:
377 		goto unsupported;
378 	}
379 
380 	return 0;
381 
382 unsupported:
383 	pr_warn("Unsupported SignedData version\n");
384 	return -EINVAL;
385 }
386 
387 /*
388  * Note the SignerInfo version
389  */
pkcs7_note_signerinfo_version(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)390 int pkcs7_note_signerinfo_version(void *context, size_t hdrlen,
391 				  unsigned char tag,
392 				  const void *value, size_t vlen)
393 {
394 	struct pkcs7_parse_context *ctx = context;
395 	unsigned version;
396 
397 	if (vlen != 1)
398 		goto unsupported;
399 
400 	version = *(const u8 *)value;
401 	switch (version) {
402 	case 1:
403 		/* PKCS#7 SignerInfo [RFC2315 sec 9.2]
404 		 * CMS ver 1 SignerInfo [RFC5652 sec 5.3]
405 		 */
406 		if (ctx->msg->version != 1)
407 			goto version_mismatch;
408 		ctx->expect_skid = false;
409 		break;
410 	case 3:
411 		/* CMS ver 3 SignerInfo [RFC2315 sec 5.3] */
412 		if (ctx->msg->version == 1)
413 			goto version_mismatch;
414 		ctx->expect_skid = true;
415 		break;
416 	default:
417 		goto unsupported;
418 	}
419 
420 	return 0;
421 
422 unsupported:
423 	pr_warn("Unsupported SignerInfo version\n");
424 	return -EINVAL;
425 version_mismatch:
426 	pr_warn("SignedData-SignerInfo version mismatch\n");
427 	return -EBADMSG;
428 }
429 
430 /*
431  * Extract a certificate and store it in the context.
432  */
pkcs7_extract_cert(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)433 int pkcs7_extract_cert(void *context, size_t hdrlen,
434 		       unsigned char tag,
435 		       const void *value, size_t vlen)
436 {
437 	struct pkcs7_parse_context *ctx = context;
438 	struct x509_certificate *x509;
439 
440 	if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
441 		pr_debug("Cert began with tag %02x at %lu\n",
442 			 tag, (unsigned long)ctx - ctx->data);
443 		return -EBADMSG;
444 	}
445 
446 	/* We have to correct for the header so that the X.509 parser can start
447 	 * from the beginning.  Note that since X.509 stipulates DER, there
448 	 * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which
449 	 * stipulates BER).
450 	 */
451 	value -= hdrlen;
452 	vlen += hdrlen;
453 
454 	if (((u8*)value)[1] == 0x80)
455 		vlen += 2; /* Indefinite length - there should be an EOC */
456 
457 	x509 = x509_cert_parse(value, vlen);
458 	if (IS_ERR(x509))
459 		return PTR_ERR(x509);
460 
461 	x509->index = ++ctx->x509_index;
462 	pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
463 	pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
464 
465 	*ctx->ppcerts = x509;
466 	ctx->ppcerts = &x509->next;
467 	return 0;
468 }
469 
470 /*
471  * Save the certificate list
472  */
pkcs7_note_certificate_list(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)473 int pkcs7_note_certificate_list(void *context, size_t hdrlen,
474 				unsigned char tag,
475 				const void *value, size_t vlen)
476 {
477 	struct pkcs7_parse_context *ctx = context;
478 
479 	pr_devel("Got cert list (%02x)\n", tag);
480 
481 	*ctx->ppcerts = ctx->msg->certs;
482 	ctx->msg->certs = ctx->certs;
483 	ctx->certs = NULL;
484 	ctx->ppcerts = &ctx->certs;
485 	return 0;
486 }
487 
488 /*
489  * Note the content type.
490  */
pkcs7_note_content(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)491 int pkcs7_note_content(void *context, size_t hdrlen,
492 		       unsigned char tag,
493 		       const void *value, size_t vlen)
494 {
495 	struct pkcs7_parse_context *ctx = context;
496 
497 	if (ctx->last_oid != OID_data &&
498 	    ctx->last_oid != OID_msIndirectData) {
499 		pr_warn("Unsupported data type %d\n", ctx->last_oid);
500 		return -EINVAL;
501 	}
502 
503 	ctx->msg->data_type = ctx->last_oid;
504 	return 0;
505 }
506 
507 /*
508  * Extract the data from the message and store that and its content type OID in
509  * the context.
510  */
pkcs7_note_data(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)511 int pkcs7_note_data(void *context, size_t hdrlen,
512 		    unsigned char tag,
513 		    const void *value, size_t vlen)
514 {
515 	struct pkcs7_parse_context *ctx = context;
516 
517 	pr_debug("Got data\n");
518 
519 	ctx->msg->data = value;
520 	ctx->msg->data_len = vlen;
521 	ctx->msg->data_hdrlen = hdrlen;
522 	return 0;
523 }
524 
525 /*
526  * Parse authenticated attributes.
527  */
pkcs7_sig_note_authenticated_attr(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)528 int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
529 				      unsigned char tag,
530 				      const void *value, size_t vlen)
531 {
532 	struct pkcs7_parse_context *ctx = context;
533 	struct pkcs7_signed_info *sinfo = ctx->sinfo;
534 	enum OID content_type;
535 
536 	pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
537 
538 	switch (ctx->last_oid) {
539 	case OID_contentType:
540 		if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
541 			goto repeated;
542 		content_type = look_up_OID(value, vlen);
543 		if (content_type != ctx->msg->data_type) {
544 			pr_warn("Mismatch between global data type (%d) and sinfo %u (%d)\n",
545 				ctx->msg->data_type, sinfo->index,
546 				content_type);
547 			return -EBADMSG;
548 		}
549 		return 0;
550 
551 	case OID_signingTime:
552 		if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
553 			goto repeated;
554 		/* Should we check that the signing time is consistent
555 		 * with the signer's X.509 cert?
556 		 */
557 		return x509_decode_time(&sinfo->signing_time,
558 					hdrlen, tag, value, vlen);
559 
560 	case OID_messageDigest:
561 		if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
562 			goto repeated;
563 		if (tag != ASN1_OTS)
564 			return -EBADMSG;
565 		sinfo->msgdigest = value;
566 		sinfo->msgdigest_len = vlen;
567 		return 0;
568 
569 	case OID_smimeCapabilites:
570 		if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
571 			goto repeated;
572 		if (ctx->msg->data_type != OID_msIndirectData) {
573 			pr_warn("S/MIME Caps only allowed with Authenticode\n");
574 			return -EKEYREJECTED;
575 		}
576 		return 0;
577 
578 		/* Microsoft SpOpusInfo seems to be contain cont[0] 16-bit BE
579 		 * char URLs and cont[1] 8-bit char URLs.
580 		 *
581 		 * Microsoft StatementType seems to contain a list of OIDs that
582 		 * are also used as extendedKeyUsage types in X.509 certs.
583 		 */
584 	case OID_msSpOpusInfo:
585 		if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
586 			goto repeated;
587 		goto authenticode_check;
588 	case OID_msStatementType:
589 		if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
590 			goto repeated;
591 	authenticode_check:
592 		if (ctx->msg->data_type != OID_msIndirectData) {
593 			pr_warn("Authenticode AuthAttrs only allowed with Authenticode\n");
594 			return -EKEYREJECTED;
595 		}
596 		/* I'm not sure how to validate these */
597 		return 0;
598 	default:
599 		return 0;
600 	}
601 
602 repeated:
603 	/* We permit max one item per AuthenticatedAttribute and no repeats */
604 	pr_warn("Repeated/multivalue AuthAttrs not permitted\n");
605 	return -EKEYREJECTED;
606 }
607 
608 /*
609  * Note the set of auth attributes for digestion purposes [RFC2315 sec 9.3]
610  */
pkcs7_sig_note_set_of_authattrs(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)611 int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
612 				    unsigned char tag,
613 				    const void *value, size_t vlen)
614 {
615 	struct pkcs7_parse_context *ctx = context;
616 	struct pkcs7_signed_info *sinfo = ctx->sinfo;
617 
618 	if (!test_bit(sinfo_has_content_type, &sinfo->aa_set) ||
619 	    !test_bit(sinfo_has_message_digest, &sinfo->aa_set)) {
620 		pr_warn("Missing required AuthAttr\n");
621 		return -EBADMSG;
622 	}
623 
624 	if (ctx->msg->data_type != OID_msIndirectData &&
625 	    test_bit(sinfo_has_ms_opus_info, &sinfo->aa_set)) {
626 		pr_warn("Unexpected Authenticode AuthAttr\n");
627 		return -EBADMSG;
628 	}
629 
630 	/* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
631 	sinfo->authattrs = value - hdrlen;
632 	sinfo->authattrs_len = vlen + hdrlen;
633 	return 0;
634 }
635 
636 /*
637  * Note the issuing certificate serial number
638  */
pkcs7_sig_note_serial(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)639 int pkcs7_sig_note_serial(void *context, size_t hdrlen,
640 			  unsigned char tag,
641 			  const void *value, size_t vlen)
642 {
643 	struct pkcs7_parse_context *ctx = context;
644 	ctx->raw_serial = value;
645 	ctx->raw_serial_size = vlen;
646 	return 0;
647 }
648 
649 /*
650  * Note the issuer's name
651  */
pkcs7_sig_note_issuer(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)652 int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
653 			  unsigned char tag,
654 			  const void *value, size_t vlen)
655 {
656 	struct pkcs7_parse_context *ctx = context;
657 	ctx->raw_issuer = value;
658 	ctx->raw_issuer_size = vlen;
659 	return 0;
660 }
661 
662 /*
663  * Note the issuing cert's subjectKeyIdentifier
664  */
pkcs7_sig_note_skid(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)665 int pkcs7_sig_note_skid(void *context, size_t hdrlen,
666 			unsigned char tag,
667 			const void *value, size_t vlen)
668 {
669 	struct pkcs7_parse_context *ctx = context;
670 
671 	pr_devel("SKID: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
672 
673 	ctx->raw_skid = value;
674 	ctx->raw_skid_size = vlen;
675 	return 0;
676 }
677 
678 /*
679  * Note the signature data
680  */
pkcs7_sig_note_signature(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)681 int pkcs7_sig_note_signature(void *context, size_t hdrlen,
682 			     unsigned char tag,
683 			     const void *value, size_t vlen)
684 {
685 	struct pkcs7_parse_context *ctx = context;
686 
687 	ctx->sinfo->sig->s = kmemdup(value, vlen, GFP_KERNEL);
688 	if (!ctx->sinfo->sig->s)
689 		return -ENOMEM;
690 
691 	ctx->sinfo->sig->s_size = vlen;
692 	return 0;
693 }
694 
695 /*
696  * Note a signature information block
697  */
pkcs7_note_signed_info(void * context,size_t hdrlen,unsigned char tag,const void * value,size_t vlen)698 int pkcs7_note_signed_info(void *context, size_t hdrlen,
699 			   unsigned char tag,
700 			   const void *value, size_t vlen)
701 {
702 	struct pkcs7_parse_context *ctx = context;
703 	struct pkcs7_signed_info *sinfo = ctx->sinfo;
704 	struct asymmetric_key_id *kid;
705 
706 	if (ctx->msg->data_type == OID_msIndirectData && !sinfo->authattrs) {
707 		pr_warn("Authenticode requires AuthAttrs\n");
708 		return -EBADMSG;
709 	}
710 
711 	/* Generate cert issuer + serial number key ID */
712 	if (!ctx->expect_skid) {
713 		kid = asymmetric_key_generate_id(ctx->raw_serial,
714 						 ctx->raw_serial_size,
715 						 ctx->raw_issuer,
716 						 ctx->raw_issuer_size);
717 	} else {
718 		kid = asymmetric_key_generate_id(ctx->raw_skid,
719 						 ctx->raw_skid_size,
720 						 "", 0);
721 	}
722 	if (IS_ERR(kid))
723 		return PTR_ERR(kid);
724 
725 	pr_devel("SINFO KID: %u [%*phN]\n", kid->len, kid->len, kid->data);
726 
727 	sinfo->sig->auth_ids[0] = kid;
728 	sinfo->index = ++ctx->sinfo_index;
729 	*ctx->ppsinfo = sinfo;
730 	ctx->ppsinfo = &sinfo->next;
731 	ctx->sinfo = kzalloc_obj(struct pkcs7_signed_info);
732 	if (!ctx->sinfo)
733 		return -ENOMEM;
734 	ctx->sinfo->sig = kzalloc_obj(struct public_key_signature);
735 	if (!ctx->sinfo->sig)
736 		return -ENOMEM;
737 	return 0;
738 }
739