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