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