common: Drop log.h from common header
[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 <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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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  */
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 }