1 // SPDX-License-Identifier: GPL-2.0+
3 * PKCS#7 parser using MbedTLS PKCS#7 library
5 * Copyright (c) 2024 Linaro Limited
10 #include <linux/kernel.h>
11 #include <linux/err.h>
12 #include <crypto/public_key.h>
13 #include <crypto/pkcs7_parser.h>
15 static void pkcs7_free_mbedtls_ctx(struct pkcs7_mbedtls_ctx *ctx)
18 kfree(ctx->content_data);
23 static void pkcs7_free_sinfo_mbedtls_ctx(struct pkcs7_sinfo_mbedtls_ctx *ctx)
26 kfree(ctx->authattrs_data);
27 kfree(ctx->content_data_digest);
33 * Parse Authenticate Attributes
34 * TODO: Shall we consider to integrate decoding of authenticate attribute into
37 * There are two kinds of structure for the Authenticate Attributes being used
40 * Type 1 - contains in a PE/COFF EFI image:
44 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.3 (OID_contentType)
46 * U.P.OBJECTIDENTIFIER 1.3.6.1.4.1.311.2.1.4 (OID_msIndirectData)
50 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.5 (OID_signingTime)
52 * U.P.UTCTime '<siging_time>'
56 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.4 (OID_messageDigest)
58 * U.P.OCTETSTRING <digest>
62 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.15 (OID_smimeCapabilites)
71 * Type 2 - contains in an EFI Capsule:
75 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.3 (OID_contentType)
77 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.7.1 (OID_data)
81 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.5 (OID_signingTime)
83 * U.P.UTCTime '<siging_time>'
87 * U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.4 (OID_messageDigest)
89 * U.P.OCTETSTRING <digest>
95 * They have different Content Type (OID_msIndirectData or OID_data).
96 * OID_smimeCapabilites only exists in a PE/COFF EFI image.
98 static int authattrs_parse(struct pkcs7_message *msg, void *aa, size_t aa_len,
99 struct pkcs7_signed_info *sinfo)
101 unsigned char *p = aa;
102 unsigned char *end = (unsigned char *)aa + aa_len;
105 unsigned char *inner_p;
108 ret = mbedtls_asn1_get_tag(&p, end, &seq_len,
109 MBEDTLS_ASN1_CONTEXT_SPECIFIC |
110 MBEDTLS_ASN1_CONSTRUCTED);
114 while (!mbedtls_asn1_get_tag(&p, end, &seq_len,
115 MBEDTLS_ASN1_CONSTRUCTED |
116 MBEDTLS_ASN1_SEQUENCE)) {
118 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
123 if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_CONTENTTYPE, inner_p, len)) {
125 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
126 MBEDTLS_ASN1_CONSTRUCTED |
131 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
137 * We should only support 1.2.840.113549.1.7.1 (OID_data)
138 * for PKCS7 DATA that is used in EFI Capsule and
139 * 1.3.6.1.4.1.311.2.1.4 (OID_msIndirectData) for
140 * MicroSoft Authentication Code that is used in EFI
143 if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_INDIRECTDATA,
145 MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA,
149 if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
151 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_MESSAGEDIGEST, inner_p,
154 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
155 MBEDTLS_ASN1_CONSTRUCTED |
160 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
161 MBEDTLS_ASN1_OCTET_STRING);
165 sinfo->msgdigest = inner_p;
166 sinfo->msgdigest_len = len;
168 if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
170 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_SIGNINGTIME, inner_p,
172 mbedtls_x509_time st;
175 ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
176 MBEDTLS_ASN1_CONSTRUCTED |
181 ret = mbedtls_x509_get_time(&inner_p, p + seq_len, &st);
184 sinfo->signing_time = x509_get_timestamp(&st);
186 if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
188 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_SMIMECAP, inner_p,
190 if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
193 if (msg->data_type != OID_msIndirectData &&
194 msg->data_type != OID_data)
196 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_SPOPUSINFO, inner_p,
198 if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
200 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_STATETYPE, inner_p,
202 if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
209 msg->have_authattrs = true;
212 * Skip the leading tag byte (MBEDTLS_ASN1_CONTEXT_SPECIFIC |
213 * MBEDTLS_ASN1_CONSTRUCTED) to satisfy pkcs7_digest() when calculating
214 * the digest of authattrs.
216 sinfo->authattrs = aa + 1;
217 sinfo->authattrs_len = aa_len - 1;
222 static int x509_populate_content_data(struct pkcs7_message *msg,
223 mbedtls_pkcs7 *pkcs7_ctx)
225 struct pkcs7_mbedtls_ctx *mctx;
227 if (!pkcs7_ctx->content_data.data ||
228 !pkcs7_ctx->content_data.data_len)
231 mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
235 mctx->content_data = kmemdup(pkcs7_ctx->content_data.data,
236 pkcs7_ctx->content_data.data_len,
238 if (!mctx->content_data) {
239 pkcs7_free_mbedtls_ctx(mctx);
243 msg->data = mctx->content_data;
244 msg->data_len = pkcs7_ctx->content_data.data_len;
245 msg->data_hdrlen = pkcs7_ctx->content_data.data_hdrlen;
246 msg->data_type = pkcs7_ctx->content_data.data_type;
248 msg->mbedtls_ctx = mctx;
252 static int x509_populate_sinfo(struct pkcs7_message *msg,
253 mbedtls_pkcs7_signer_info *mb_sinfo,
254 struct pkcs7_signed_info **sinfo)
256 struct pkcs7_signed_info *signed_info;
257 struct public_key_signature *s;
258 mbedtls_md_type_t md_alg;
259 struct pkcs7_sinfo_mbedtls_ctx *mctx;
262 signed_info = kzalloc(sizeof(*signed_info), GFP_KERNEL);
266 s = kzalloc(sizeof(*s), GFP_KERNEL);
272 mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
281 * alg_identifier = digestAlgorithm (DigestAlgorithmIdentifier)
282 * MbedTLS internally checks this field to ensure
283 * it is the same as digest_alg_identifiers.
284 * sig_alg_identifier = digestEncryptionAlgorithm
285 * (DigestEncryptionAlgorithmIdentifier)
286 * MbedTLS just saves this field without any actions.
287 * See function pkcs7_get_signer_info() for reference.
289 * Public key algorithm:
290 * No information related to public key algorithm under MbedTLS signer
291 * info. Assume that we are using RSA.
293 ret = mbedtls_oid_get_md_alg(&mb_sinfo->alg_identifier, &md_alg);
296 s->pkey_algo = "rsa";
298 /* Translate the hash algorithm */
300 case MBEDTLS_MD_SHA1:
301 s->hash_algo = "sha1";
302 s->digest_size = SHA1_SUM_LEN;
304 case MBEDTLS_MD_SHA256:
305 s->hash_algo = "sha256";
306 s->digest_size = SHA256_SUM_LEN;
308 case MBEDTLS_MD_SHA384:
309 s->hash_algo = "sha384";
310 s->digest_size = SHA384_SUM_LEN;
312 case MBEDTLS_MD_SHA512:
313 s->hash_algo = "sha512";
314 s->digest_size = SHA512_SUM_LEN;
316 /* Unsupported algo */
318 case MBEDTLS_MD_SHA224:
325 * auth_ids holds AuthorityKeyIdentifier, aka akid
327 * [PKCS#7 or CMS ver 1] - generated from "Issuer + Serial number"
328 * [CMS ver 3] - generated from skid (subjectKeyId)
329 * auth_ids[1]: generated from skid (subjectKeyId)
331 * Assume that we are using PKCS#7 (msg->version=1),
332 * not CMS ver 3 (msg->version=3).
334 s->auth_ids[0] = asymmetric_key_generate_id(mb_sinfo->serial.p,
335 mb_sinfo->serial.len,
336 mb_sinfo->issuer_raw.p,
337 mb_sinfo->issuer_raw.len);
338 if (!s->auth_ids[0]) {
343 /* skip s->auth_ids[1], no subjectKeyId in MbedTLS signer info ctx */
346 * Encoding can be pkcs1 or raw, but only pkcs1 is supported.
347 * Set the encoding explicitly to pkcs1.
349 s->encoding = "pkcs1";
351 /* Copy the signature data */
352 s->s = kmemdup(mb_sinfo->sig.p, mb_sinfo->sig.len, GFP_KERNEL);
357 s->s_size = mb_sinfo->sig.len;
358 signed_info->sig = s;
360 /* Save the Authenticate Attributes data if exists */
361 if (!mb_sinfo->authattrs.data || !mb_sinfo->authattrs.data_len) {
366 mctx->authattrs_data = kmemdup(mb_sinfo->authattrs.data,
367 mb_sinfo->authattrs.data_len,
369 if (!mctx->authattrs_data) {
373 signed_info->mbedtls_ctx = mctx;
375 /* If authattrs exists, decode it and parse msgdigest from it */
376 ret = authattrs_parse(msg, mctx->authattrs_data,
377 mb_sinfo->authattrs.data_len,
383 *sinfo = signed_info;
387 pkcs7_free_sinfo_mbedtls_ctx(mctx);
389 public_key_signature_free(s);
396 * Free a signed information block.
398 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
401 public_key_signature_free(sinfo->sig);
402 pkcs7_free_sinfo_mbedtls_ctx(sinfo->mbedtls_ctx);
408 * pkcs7_free_message - Free a PKCS#7 message
409 * @pkcs7: The PKCS#7 message to free
411 void pkcs7_free_message(struct pkcs7_message *pkcs7)
413 struct x509_certificate *cert;
414 struct pkcs7_signed_info *sinfo;
417 while (pkcs7->certs) {
419 pkcs7->certs = cert->next;
420 x509_free_certificate(cert);
424 pkcs7->crl = cert->next;
425 x509_free_certificate(cert);
427 while (pkcs7->signed_infos) {
428 sinfo = pkcs7->signed_infos;
429 pkcs7->signed_infos = sinfo->next;
430 pkcs7_free_signed_info(sinfo);
432 pkcs7_free_mbedtls_ctx(pkcs7->mbedtls_ctx);
437 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
441 mbedtls_pkcs7 pkcs7_ctx;
442 mbedtls_pkcs7_signer_info *mb_sinfos;
443 mbedtls_x509_crt *mb_certs;
444 struct pkcs7_message *msg;
445 struct x509_certificate **cert;
446 struct pkcs7_signed_info **sinfos;
448 msg = kzalloc(sizeof(*msg), GFP_KERNEL);
454 /* Parse the DER encoded PKCS#7 message using MbedTLS */
455 mbedtls_pkcs7_init(&pkcs7_ctx);
456 ret = mbedtls_pkcs7_parse_der(&pkcs7_ctx, data, datalen);
457 /* Check if it is a PKCS#7 message with signed data */
458 if (ret != MBEDTLS_PKCS7_SIGNED_DATA)
461 /* Assume that we are using PKCS#7, not CMS ver 3 */
462 msg->version = 1; /* 1 for [PKCS#7 or CMS ver 1] */
464 /* Populate the certs to msg->certs */
465 for (i = 0, cert = &msg->certs, mb_certs = &pkcs7_ctx.signed_data.certs;
466 i < pkcs7_ctx.signed_data.no_of_certs && mb_certs;
467 i++, cert = &(*cert)->next, mb_certs = mb_certs->next) {
468 ret = x509_populate_cert(mb_certs, cert);
472 (*cert)->index = i + 1;
476 * Skip populating crl, that is not currently in-use.
479 /* Populate content data */
480 ret = x509_populate_content_data(msg, &pkcs7_ctx);
484 /* Populate signed info to msg->signed_infos */
485 for (i = 0, sinfos = &msg->signed_infos,
486 mb_sinfos = &pkcs7_ctx.signed_data.signers;
487 i < pkcs7_ctx.signed_data.no_of_signers && mb_sinfos;
488 i++, sinfos = &(*sinfos)->next, mb_sinfos = mb_sinfos->next) {
489 ret = x509_populate_sinfo(msg, mb_sinfos, sinfos);
493 (*sinfos)->index = i + 1;
496 mbedtls_pkcs7_free(&pkcs7_ctx);
500 mbedtls_pkcs7_free(&pkcs7_ctx);
501 pkcs7_free_message(msg);