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