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