xref: /linux/crypto/asymmetric_keys/pkcs7_parser.c (revision aeb8f932080d62cdc305a7ccca9d60de34908b30)
12e3fadbfSDavid Howells /* PKCS#7 parser
22e3fadbfSDavid Howells  *
32e3fadbfSDavid Howells  * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved.
42e3fadbfSDavid Howells  * Written by David Howells (dhowells@redhat.com)
52e3fadbfSDavid Howells  *
62e3fadbfSDavid Howells  * This program is free software; you can redistribute it and/or
72e3fadbfSDavid Howells  * modify it under the terms of the GNU General Public Licence
82e3fadbfSDavid Howells  * as published by the Free Software Foundation; either version
92e3fadbfSDavid Howells  * 2 of the Licence, or (at your option) any later version.
102e3fadbfSDavid Howells  */
112e3fadbfSDavid Howells 
122e3fadbfSDavid Howells #define pr_fmt(fmt) "PKCS7: "fmt
132e3fadbfSDavid Howells #include <linux/kernel.h>
142e3fadbfSDavid Howells #include <linux/export.h>
152e3fadbfSDavid Howells #include <linux/slab.h>
162e3fadbfSDavid Howells #include <linux/err.h>
172e3fadbfSDavid Howells #include <linux/oid_registry.h>
182e3fadbfSDavid Howells #include "public_key.h"
192e3fadbfSDavid Howells #include "pkcs7_parser.h"
202e3fadbfSDavid Howells #include "pkcs7-asn1.h"
212e3fadbfSDavid Howells 
222e3fadbfSDavid Howells struct pkcs7_parse_context {
232e3fadbfSDavid Howells 	struct pkcs7_message	*msg;		/* Message being constructed */
242e3fadbfSDavid Howells 	struct pkcs7_signed_info *sinfo;	/* SignedInfo being constructed */
252e3fadbfSDavid Howells 	struct pkcs7_signed_info **ppsinfo;
262e3fadbfSDavid Howells 	struct x509_certificate *certs;		/* Certificate cache */
272e3fadbfSDavid Howells 	struct x509_certificate **ppcerts;
282e3fadbfSDavid Howells 	unsigned long	data;			/* Start of data */
292e3fadbfSDavid Howells 	enum OID	last_oid;		/* Last OID encountered */
302e3fadbfSDavid Howells 	unsigned	x509_index;
312e3fadbfSDavid Howells 	unsigned	sinfo_index;
32*46963b77SDavid Howells 	const void	*raw_serial;
33*46963b77SDavid Howells 	unsigned	raw_serial_size;
34*46963b77SDavid Howells 	unsigned	raw_issuer_size;
35*46963b77SDavid Howells 	const void	*raw_issuer;
362e3fadbfSDavid Howells };
372e3fadbfSDavid Howells 
383cd0920cSDavid Howells /*
393cd0920cSDavid Howells  * Free a signed information block.
403cd0920cSDavid Howells  */
413cd0920cSDavid Howells static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
423cd0920cSDavid Howells {
433cd0920cSDavid Howells 	if (sinfo) {
443cd0920cSDavid Howells 		mpi_free(sinfo->sig.mpi[0]);
453cd0920cSDavid Howells 		kfree(sinfo->sig.digest);
46*46963b77SDavid Howells 		kfree(sinfo->signing_cert_id);
473cd0920cSDavid Howells 		kfree(sinfo);
483cd0920cSDavid Howells 	}
493cd0920cSDavid Howells }
503cd0920cSDavid Howells 
512e3fadbfSDavid Howells /**
522e3fadbfSDavid Howells  * pkcs7_free_message - Free a PKCS#7 message
532e3fadbfSDavid Howells  * @pkcs7: The PKCS#7 message to free
542e3fadbfSDavid Howells  */
552e3fadbfSDavid Howells void pkcs7_free_message(struct pkcs7_message *pkcs7)
562e3fadbfSDavid Howells {
572e3fadbfSDavid Howells 	struct x509_certificate *cert;
582e3fadbfSDavid Howells 	struct pkcs7_signed_info *sinfo;
592e3fadbfSDavid Howells 
602e3fadbfSDavid Howells 	if (pkcs7) {
612e3fadbfSDavid Howells 		while (pkcs7->certs) {
622e3fadbfSDavid Howells 			cert = pkcs7->certs;
632e3fadbfSDavid Howells 			pkcs7->certs = cert->next;
642e3fadbfSDavid Howells 			x509_free_certificate(cert);
652e3fadbfSDavid Howells 		}
662e3fadbfSDavid Howells 		while (pkcs7->crl) {
672e3fadbfSDavid Howells 			cert = pkcs7->crl;
682e3fadbfSDavid Howells 			pkcs7->crl = cert->next;
692e3fadbfSDavid Howells 			x509_free_certificate(cert);
702e3fadbfSDavid Howells 		}
712e3fadbfSDavid Howells 		while (pkcs7->signed_infos) {
722e3fadbfSDavid Howells 			sinfo = pkcs7->signed_infos;
732e3fadbfSDavid Howells 			pkcs7->signed_infos = sinfo->next;
743cd0920cSDavid Howells 			pkcs7_free_signed_info(sinfo);
752e3fadbfSDavid Howells 		}
762e3fadbfSDavid Howells 		kfree(pkcs7);
772e3fadbfSDavid Howells 	}
782e3fadbfSDavid Howells }
792e3fadbfSDavid Howells EXPORT_SYMBOL_GPL(pkcs7_free_message);
802e3fadbfSDavid Howells 
812e3fadbfSDavid Howells /**
822e3fadbfSDavid Howells  * pkcs7_parse_message - Parse a PKCS#7 message
832e3fadbfSDavid Howells  * @data: The raw binary ASN.1 encoded message to be parsed
842e3fadbfSDavid Howells  * @datalen: The size of the encoded message
852e3fadbfSDavid Howells  */
862e3fadbfSDavid Howells struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
872e3fadbfSDavid Howells {
882e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx;
89cecf5d2eSDavid Howells 	struct pkcs7_message *msg = ERR_PTR(-ENOMEM);
90cecf5d2eSDavid Howells 	int ret;
912e3fadbfSDavid Howells 
922e3fadbfSDavid Howells 	ctx = kzalloc(sizeof(struct pkcs7_parse_context), GFP_KERNEL);
932e3fadbfSDavid Howells 	if (!ctx)
94cecf5d2eSDavid Howells 		goto out_no_ctx;
95cecf5d2eSDavid Howells 	ctx->msg = kzalloc(sizeof(struct pkcs7_message), GFP_KERNEL);
96cecf5d2eSDavid Howells 	if (!ctx->msg)
97cecf5d2eSDavid Howells 		goto out_no_msg;
982e3fadbfSDavid Howells 	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
992e3fadbfSDavid Howells 	if (!ctx->sinfo)
100cecf5d2eSDavid Howells 		goto out_no_sinfo;
1012e3fadbfSDavid Howells 
1022e3fadbfSDavid Howells 	ctx->data = (unsigned long)data;
1032e3fadbfSDavid Howells 	ctx->ppcerts = &ctx->certs;
1042e3fadbfSDavid Howells 	ctx->ppsinfo = &ctx->msg->signed_infos;
1052e3fadbfSDavid Howells 
1062e3fadbfSDavid Howells 	/* Attempt to decode the signature */
1072e3fadbfSDavid Howells 	ret = asn1_ber_decoder(&pkcs7_decoder, ctx, data, datalen);
108cecf5d2eSDavid Howells 	if (ret < 0) {
109cecf5d2eSDavid Howells 		msg = ERR_PTR(ret);
110cecf5d2eSDavid Howells 		goto out;
111cecf5d2eSDavid Howells 	}
1122e3fadbfSDavid Howells 
113cecf5d2eSDavid Howells 	msg = ctx->msg;
114cecf5d2eSDavid Howells 	ctx->msg = NULL;
115cecf5d2eSDavid Howells 
116cecf5d2eSDavid Howells out:
1172e3fadbfSDavid Howells 	while (ctx->certs) {
1182e3fadbfSDavid Howells 		struct x509_certificate *cert = ctx->certs;
1192e3fadbfSDavid Howells 		ctx->certs = cert->next;
1202e3fadbfSDavid Howells 		x509_free_certificate(cert);
1212e3fadbfSDavid Howells 	}
1223cd0920cSDavid Howells 	pkcs7_free_signed_info(ctx->sinfo);
123cecf5d2eSDavid Howells out_no_sinfo:
124cecf5d2eSDavid Howells 	pkcs7_free_message(ctx->msg);
125cecf5d2eSDavid Howells out_no_msg:
1262e3fadbfSDavid Howells 	kfree(ctx);
127cecf5d2eSDavid Howells out_no_ctx:
1282e3fadbfSDavid Howells 	return msg;
1292e3fadbfSDavid Howells }
1302e3fadbfSDavid Howells EXPORT_SYMBOL_GPL(pkcs7_parse_message);
1312e3fadbfSDavid Howells 
1322e3fadbfSDavid Howells /**
1332e3fadbfSDavid Howells  * pkcs7_get_content_data - Get access to the PKCS#7 content
1342e3fadbfSDavid Howells  * @pkcs7: The preparsed PKCS#7 message to access
1352e3fadbfSDavid Howells  * @_data: Place to return a pointer to the data
1362e3fadbfSDavid Howells  * @_data_len: Place to return the data length
1372e3fadbfSDavid Howells  * @want_wrapper: True if the ASN.1 object header should be included in the data
1382e3fadbfSDavid Howells  *
1392e3fadbfSDavid Howells  * Get access to the data content of the PKCS#7 message, including, optionally,
1402e3fadbfSDavid Howells  * the header of the ASN.1 object that contains it.  Returns -ENODATA if the
1412e3fadbfSDavid Howells  * data object was missing from the message.
1422e3fadbfSDavid Howells  */
1432e3fadbfSDavid Howells int pkcs7_get_content_data(const struct pkcs7_message *pkcs7,
1442e3fadbfSDavid Howells 			   const void **_data, size_t *_data_len,
1452e3fadbfSDavid Howells 			   bool want_wrapper)
1462e3fadbfSDavid Howells {
1472e3fadbfSDavid Howells 	size_t wrapper;
1482e3fadbfSDavid Howells 
1492e3fadbfSDavid Howells 	if (!pkcs7->data)
1502e3fadbfSDavid Howells 		return -ENODATA;
1512e3fadbfSDavid Howells 
1522e3fadbfSDavid Howells 	wrapper = want_wrapper ? pkcs7->data_hdrlen : 0;
1532e3fadbfSDavid Howells 	*_data = pkcs7->data - wrapper;
1542e3fadbfSDavid Howells 	*_data_len = pkcs7->data_len + wrapper;
1552e3fadbfSDavid Howells 	return 0;
1562e3fadbfSDavid Howells }
1572e3fadbfSDavid Howells EXPORT_SYMBOL_GPL(pkcs7_get_content_data);
1582e3fadbfSDavid Howells 
1592e3fadbfSDavid Howells /*
1602e3fadbfSDavid Howells  * Note an OID when we find one for later processing when we know how
1612e3fadbfSDavid Howells  * to interpret it.
1622e3fadbfSDavid Howells  */
1632e3fadbfSDavid Howells int pkcs7_note_OID(void *context, size_t hdrlen,
1642e3fadbfSDavid Howells 		   unsigned char tag,
1652e3fadbfSDavid Howells 		   const void *value, size_t vlen)
1662e3fadbfSDavid Howells {
1672e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
1682e3fadbfSDavid Howells 
1692e3fadbfSDavid Howells 	ctx->last_oid = look_up_OID(value, vlen);
1702e3fadbfSDavid Howells 	if (ctx->last_oid == OID__NR) {
1712e3fadbfSDavid Howells 		char buffer[50];
1722e3fadbfSDavid Howells 		sprint_oid(value, vlen, buffer, sizeof(buffer));
1732e3fadbfSDavid Howells 		printk("PKCS7: Unknown OID: [%lu] %s\n",
1742e3fadbfSDavid Howells 		       (unsigned long)value - ctx->data, buffer);
1752e3fadbfSDavid Howells 	}
1762e3fadbfSDavid Howells 	return 0;
1772e3fadbfSDavid Howells }
1782e3fadbfSDavid Howells 
1792e3fadbfSDavid Howells /*
1802e3fadbfSDavid Howells  * Note the digest algorithm for the signature.
1812e3fadbfSDavid Howells  */
1822e3fadbfSDavid Howells int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen,
1832e3fadbfSDavid Howells 			       unsigned char tag,
1842e3fadbfSDavid Howells 			       const void *value, size_t vlen)
1852e3fadbfSDavid Howells {
1862e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
1872e3fadbfSDavid Howells 
1882e3fadbfSDavid Howells 	switch (ctx->last_oid) {
1892e3fadbfSDavid Howells 	case OID_md4:
1902e3fadbfSDavid Howells 		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4;
1912e3fadbfSDavid Howells 		break;
1922e3fadbfSDavid Howells 	case OID_md5:
1932e3fadbfSDavid Howells 		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5;
1942e3fadbfSDavid Howells 		break;
1952e3fadbfSDavid Howells 	case OID_sha1:
1962e3fadbfSDavid Howells 		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1;
1972e3fadbfSDavid Howells 		break;
1982e3fadbfSDavid Howells 	case OID_sha256:
1992e3fadbfSDavid Howells 		ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256;
2002e3fadbfSDavid Howells 		break;
2012e3fadbfSDavid Howells 	default:
2022e3fadbfSDavid Howells 		printk("Unsupported digest algo: %u\n", ctx->last_oid);
2032e3fadbfSDavid Howells 		return -ENOPKG;
2042e3fadbfSDavid Howells 	}
2052e3fadbfSDavid Howells 	return 0;
2062e3fadbfSDavid Howells }
2072e3fadbfSDavid Howells 
2082e3fadbfSDavid Howells /*
2092e3fadbfSDavid Howells  * Note the public key algorithm for the signature.
2102e3fadbfSDavid Howells  */
2112e3fadbfSDavid Howells int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen,
2122e3fadbfSDavid Howells 			     unsigned char tag,
2132e3fadbfSDavid Howells 			     const void *value, size_t vlen)
2142e3fadbfSDavid Howells {
2152e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
2162e3fadbfSDavid Howells 
2172e3fadbfSDavid Howells 	switch (ctx->last_oid) {
2182e3fadbfSDavid Howells 	case OID_rsaEncryption:
2192e3fadbfSDavid Howells 		ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA;
2202e3fadbfSDavid Howells 		break;
2212e3fadbfSDavid Howells 	default:
2222e3fadbfSDavid Howells 		printk("Unsupported pkey algo: %u\n", ctx->last_oid);
2232e3fadbfSDavid Howells 		return -ENOPKG;
2242e3fadbfSDavid Howells 	}
2252e3fadbfSDavid Howells 	return 0;
2262e3fadbfSDavid Howells }
2272e3fadbfSDavid Howells 
2282e3fadbfSDavid Howells /*
2292e3fadbfSDavid Howells  * Extract a certificate and store it in the context.
2302e3fadbfSDavid Howells  */
2312e3fadbfSDavid Howells int pkcs7_extract_cert(void *context, size_t hdrlen,
2322e3fadbfSDavid Howells 		       unsigned char tag,
2332e3fadbfSDavid Howells 		       const void *value, size_t vlen)
2342e3fadbfSDavid Howells {
2352e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
2362e3fadbfSDavid Howells 	struct x509_certificate *x509;
2372e3fadbfSDavid Howells 
2382e3fadbfSDavid Howells 	if (tag != ((ASN1_UNIV << 6) | ASN1_CONS_BIT | ASN1_SEQ)) {
2392e3fadbfSDavid Howells 		pr_debug("Cert began with tag %02x at %lu\n",
2402e3fadbfSDavid Howells 			 tag, (unsigned long)ctx - ctx->data);
2412e3fadbfSDavid Howells 		return -EBADMSG;
2422e3fadbfSDavid Howells 	}
2432e3fadbfSDavid Howells 
2442e3fadbfSDavid Howells 	/* We have to correct for the header so that the X.509 parser can start
2452e3fadbfSDavid Howells 	 * from the beginning.  Note that since X.509 stipulates DER, there
2462e3fadbfSDavid Howells 	 * probably shouldn't be an EOC trailer - but it is in PKCS#7 (which
2472e3fadbfSDavid Howells 	 * stipulates BER).
2482e3fadbfSDavid Howells 	 */
2492e3fadbfSDavid Howells 	value -= hdrlen;
2502e3fadbfSDavid Howells 	vlen += hdrlen;
2512e3fadbfSDavid Howells 
2522e3fadbfSDavid Howells 	if (((u8*)value)[1] == 0x80)
2532e3fadbfSDavid Howells 		vlen += 2; /* Indefinite length - there should be an EOC */
2542e3fadbfSDavid Howells 
2552e3fadbfSDavid Howells 	x509 = x509_cert_parse(value, vlen);
2562e3fadbfSDavid Howells 	if (IS_ERR(x509))
2572e3fadbfSDavid Howells 		return PTR_ERR(x509);
2582e3fadbfSDavid Howells 
2592e3fadbfSDavid Howells 	x509->index = ++ctx->x509_index;
260*46963b77SDavid Howells 	pr_debug("Got cert %u for %s\n", x509->index, x509->subject);
261*46963b77SDavid Howells 	pr_debug("- fingerprint %*phN\n", x509->id->len, x509->id->data);
262*46963b77SDavid Howells 
2632e3fadbfSDavid Howells 	*ctx->ppcerts = x509;
2642e3fadbfSDavid Howells 	ctx->ppcerts = &x509->next;
2652e3fadbfSDavid Howells 	return 0;
2662e3fadbfSDavid Howells }
2672e3fadbfSDavid Howells 
2682e3fadbfSDavid Howells /*
2692e3fadbfSDavid Howells  * Save the certificate list
2702e3fadbfSDavid Howells  */
2712e3fadbfSDavid Howells int pkcs7_note_certificate_list(void *context, size_t hdrlen,
2722e3fadbfSDavid Howells 				unsigned char tag,
2732e3fadbfSDavid Howells 				const void *value, size_t vlen)
2742e3fadbfSDavid Howells {
2752e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
2762e3fadbfSDavid Howells 
2772e3fadbfSDavid Howells 	pr_devel("Got cert list (%02x)\n", tag);
2782e3fadbfSDavid Howells 
2792e3fadbfSDavid Howells 	*ctx->ppcerts = ctx->msg->certs;
2802e3fadbfSDavid Howells 	ctx->msg->certs = ctx->certs;
2812e3fadbfSDavid Howells 	ctx->certs = NULL;
2822e3fadbfSDavid Howells 	ctx->ppcerts = &ctx->certs;
2832e3fadbfSDavid Howells 	return 0;
2842e3fadbfSDavid Howells }
2852e3fadbfSDavid Howells 
2862e3fadbfSDavid Howells /*
2872e3fadbfSDavid Howells  * Extract the data from the message and store that and its content type OID in
2882e3fadbfSDavid Howells  * the context.
2892e3fadbfSDavid Howells  */
2902e3fadbfSDavid Howells int pkcs7_note_data(void *context, size_t hdrlen,
2912e3fadbfSDavid Howells 		    unsigned char tag,
2922e3fadbfSDavid Howells 		    const void *value, size_t vlen)
2932e3fadbfSDavid Howells {
2942e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
2952e3fadbfSDavid Howells 
2962e3fadbfSDavid Howells 	pr_debug("Got data\n");
2972e3fadbfSDavid Howells 
2982e3fadbfSDavid Howells 	ctx->msg->data = value;
2992e3fadbfSDavid Howells 	ctx->msg->data_len = vlen;
3002e3fadbfSDavid Howells 	ctx->msg->data_hdrlen = hdrlen;
3012e3fadbfSDavid Howells 	ctx->msg->data_type = ctx->last_oid;
3022e3fadbfSDavid Howells 	return 0;
3032e3fadbfSDavid Howells }
3042e3fadbfSDavid Howells 
3052e3fadbfSDavid Howells /*
3062e3fadbfSDavid Howells  * Parse authenticated attributes
3072e3fadbfSDavid Howells  */
3082e3fadbfSDavid Howells int pkcs7_sig_note_authenticated_attr(void *context, size_t hdrlen,
3092e3fadbfSDavid Howells 				      unsigned char tag,
3102e3fadbfSDavid Howells 				      const void *value, size_t vlen)
3112e3fadbfSDavid Howells {
3122e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
3132e3fadbfSDavid Howells 
3142e3fadbfSDavid Howells 	pr_devel("AuthAttr: %02x %zu [%*ph]\n", tag, vlen, (unsigned)vlen, value);
3152e3fadbfSDavid Howells 
3162e3fadbfSDavid Howells 	switch (ctx->last_oid) {
3172e3fadbfSDavid Howells 	case OID_messageDigest:
3182e3fadbfSDavid Howells 		if (tag != ASN1_OTS)
3192e3fadbfSDavid Howells 			return -EBADMSG;
3202e3fadbfSDavid Howells 		ctx->sinfo->msgdigest = value;
3212e3fadbfSDavid Howells 		ctx->sinfo->msgdigest_len = vlen;
3222e3fadbfSDavid Howells 		return 0;
3232e3fadbfSDavid Howells 	default:
3242e3fadbfSDavid Howells 		return 0;
3252e3fadbfSDavid Howells 	}
3262e3fadbfSDavid Howells }
3272e3fadbfSDavid Howells 
3282e3fadbfSDavid Howells /*
3292e3fadbfSDavid Howells  * Note the set of auth attributes for digestion purposes [RFC2315 9.3]
3302e3fadbfSDavid Howells  */
3312e3fadbfSDavid Howells int pkcs7_sig_note_set_of_authattrs(void *context, size_t hdrlen,
3322e3fadbfSDavid Howells 				    unsigned char tag,
3332e3fadbfSDavid Howells 				    const void *value, size_t vlen)
3342e3fadbfSDavid Howells {
3352e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
3362e3fadbfSDavid Howells 
3372e3fadbfSDavid Howells 	/* We need to switch the 'CONT 0' to a 'SET OF' when we digest */
3382e3fadbfSDavid Howells 	ctx->sinfo->authattrs = value - (hdrlen - 1);
3392e3fadbfSDavid Howells 	ctx->sinfo->authattrs_len = vlen + (hdrlen - 1);
3402e3fadbfSDavid Howells 	return 0;
3412e3fadbfSDavid Howells }
3422e3fadbfSDavid Howells 
3432e3fadbfSDavid Howells /*
3442e3fadbfSDavid Howells  * Note the issuing certificate serial number
3452e3fadbfSDavid Howells  */
3462e3fadbfSDavid Howells int pkcs7_sig_note_serial(void *context, size_t hdrlen,
3472e3fadbfSDavid Howells 			  unsigned char tag,
3482e3fadbfSDavid Howells 			  const void *value, size_t vlen)
3492e3fadbfSDavid Howells {
3502e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
351*46963b77SDavid Howells 	ctx->raw_serial = value;
352*46963b77SDavid Howells 	ctx->raw_serial_size = vlen;
3532e3fadbfSDavid Howells 	return 0;
3542e3fadbfSDavid Howells }
3552e3fadbfSDavid Howells 
3562e3fadbfSDavid Howells /*
3572e3fadbfSDavid Howells  * Note the issuer's name
3582e3fadbfSDavid Howells  */
3592e3fadbfSDavid Howells int pkcs7_sig_note_issuer(void *context, size_t hdrlen,
3602e3fadbfSDavid Howells 			  unsigned char tag,
3612e3fadbfSDavid Howells 			  const void *value, size_t vlen)
3622e3fadbfSDavid Howells {
3632e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
364*46963b77SDavid Howells 	ctx->raw_issuer = value;
365*46963b77SDavid Howells 	ctx->raw_issuer_size = vlen;
3662e3fadbfSDavid Howells 	return 0;
3672e3fadbfSDavid Howells }
3682e3fadbfSDavid Howells 
3692e3fadbfSDavid Howells /*
3702e3fadbfSDavid Howells  * Note the signature data
3712e3fadbfSDavid Howells  */
3722e3fadbfSDavid Howells int pkcs7_sig_note_signature(void *context, size_t hdrlen,
3732e3fadbfSDavid Howells 			     unsigned char tag,
3742e3fadbfSDavid Howells 			     const void *value, size_t vlen)
3752e3fadbfSDavid Howells {
3762e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
3772e3fadbfSDavid Howells 	MPI mpi;
3782e3fadbfSDavid Howells 
3792e3fadbfSDavid Howells 	BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA);
3802e3fadbfSDavid Howells 
3812e3fadbfSDavid Howells 	mpi = mpi_read_raw_data(value, vlen);
3822e3fadbfSDavid Howells 	if (!mpi)
3832e3fadbfSDavid Howells 		return -ENOMEM;
3842e3fadbfSDavid Howells 
3852e3fadbfSDavid Howells 	ctx->sinfo->sig.mpi[0] = mpi;
3862e3fadbfSDavid Howells 	ctx->sinfo->sig.nr_mpi = 1;
3872e3fadbfSDavid Howells 	return 0;
3882e3fadbfSDavid Howells }
3892e3fadbfSDavid Howells 
3902e3fadbfSDavid Howells /*
3912e3fadbfSDavid Howells  * Note a signature information block
3922e3fadbfSDavid Howells  */
3932e3fadbfSDavid Howells int pkcs7_note_signed_info(void *context, size_t hdrlen,
3942e3fadbfSDavid Howells 			   unsigned char tag,
3952e3fadbfSDavid Howells 			   const void *value, size_t vlen)
3962e3fadbfSDavid Howells {
3972e3fadbfSDavid Howells 	struct pkcs7_parse_context *ctx = context;
398*46963b77SDavid Howells 	struct pkcs7_signed_info *sinfo = ctx->sinfo;
399*46963b77SDavid Howells 	struct asymmetric_key_id *kid;
4002e3fadbfSDavid Howells 
401*46963b77SDavid Howells 	/* Generate cert issuer + serial number key ID */
402*46963b77SDavid Howells 	kid = asymmetric_key_generate_id(ctx->raw_serial,
403*46963b77SDavid Howells 					 ctx->raw_serial_size,
404*46963b77SDavid Howells 					 ctx->raw_issuer,
405*46963b77SDavid Howells 					 ctx->raw_issuer_size);
406*46963b77SDavid Howells 	if (IS_ERR(kid))
407*46963b77SDavid Howells 		return PTR_ERR(kid);
408*46963b77SDavid Howells 
409*46963b77SDavid Howells 	sinfo->signing_cert_id = kid;
410*46963b77SDavid Howells 	sinfo->index = ++ctx->sinfo_index;
411*46963b77SDavid Howells 	*ctx->ppsinfo = sinfo;
412*46963b77SDavid Howells 	ctx->ppsinfo = &sinfo->next;
4132e3fadbfSDavid Howells 	ctx->sinfo = kzalloc(sizeof(struct pkcs7_signed_info), GFP_KERNEL);
4142e3fadbfSDavid Howells 	if (!ctx->sinfo)
4152e3fadbfSDavid Howells 		return -ENOMEM;
4162e3fadbfSDavid Howells 	return 0;
4172e3fadbfSDavid Howells }
418