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