cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

pkcs7_parser.c (16890B)


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