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