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