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