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