1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * PKCS#7 parser using MbedTLS PKCS#7 library
4  *
5  * Copyright (c) 2024 Linaro Limited
6  * Author: Raymond Mao <raymond.mao@linaro.org>
7  */
8 
9 #include <log.h>
10 #include <linux/kernel.h>
11 #include <linux/err.h>
12 #include <crypto/public_key.h>
13 #include <crypto/pkcs7_parser.h>
14 
pkcs7_free_mbedtls_ctx(struct pkcs7_mbedtls_ctx * ctx)15 static void pkcs7_free_mbedtls_ctx(struct pkcs7_mbedtls_ctx *ctx)
16 {
17 	if (ctx) {
18 		kfree(ctx->content_data);
19 		kfree(ctx);
20 	}
21 }
22 
pkcs7_free_sinfo_mbedtls_ctx(struct pkcs7_sinfo_mbedtls_ctx * ctx)23 static void pkcs7_free_sinfo_mbedtls_ctx(struct pkcs7_sinfo_mbedtls_ctx *ctx)
24 {
25 	if (ctx) {
26 		kfree(ctx->authattrs_data);
27 		kfree(ctx->content_data_digest);
28 		kfree(ctx);
29 	}
30 }
31 
32 /*
33  * Parse Authenticate Attributes
34  * TODO: Shall we consider to integrate decoding of authenticate attribute into
35  *	 MbedTLS library?
36  *
37  * There are two kinds of structure for the Authenticate Attributes being used
38  * in U-Boot.
39  *
40  * Type 1 - contains in a PE/COFF EFI image:
41  *
42  * [C.P.0] {
43  *   U.P.SEQUENCE {
44  *     U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.3 (OID_contentType)
45  *     U.P.SET {
46  *        U.P.OBJECTIDENTIFIER 1.3.6.1.4.1.311.2.1.4 (OID_msIndirectData)
47  *     }
48  *  }
49  *  U.P.SEQUENCE {
50  *     U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.5 (OID_signingTime)
51  *     U.P.SET {
52  *        U.P.UTCTime '<siging_time>'
53  *     }
54  *  }
55  *  U.P.SEQUENCE {
56  *     U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.4 (OID_messageDigest)
57  *     U.P.SET {
58  *        U.P.OCTETSTRING <digest>
59  *     }
60  *  }
61  *    U.P.SEQUENCE {
62  *        U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.15 (OID_smimeCapabilites)
63  *       U.P.SET {
64  *          U.P.SEQUENCE {
65  *             <...>
66  *          }
67  *       }
68  *    }
69  * }
70  *
71  * Type 2 - contains in an EFI Capsule:
72  *
73  * [C.P.0] {
74  *   U.P.SEQUENCE {
75  *      U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.3 (OID_contentType)
76  *      U.P.SET {
77  *         U.P.OBJECTIDENTIFIER 1.2.840.113549.1.7.1 (OID_data)
78  *      }
79  *   }
80  *   U.P.SEQUENCE {
81  *      U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.5 (OID_signingTime)
82  *      U.P.SET {
83  *         U.P.UTCTime '<siging_time>'
84  *      }
85  *   }
86  *   U.P.SEQUENCE {
87  *      U.P.OBJECTIDENTIFIER 1.2.840.113549.1.9.4 (OID_messageDigest)
88  *      U.P.SET {
89  *         U.P.OCTETSTRING <digest>
90  *      }
91  *  }
92  *}
93  *
94  * Note:
95  * They have different Content Type (OID_msIndirectData or OID_data).
96  * OID_smimeCapabilites only exists in a PE/COFF EFI image.
97  */
authattrs_parse(struct pkcs7_message * msg,void * aa,size_t aa_len,struct pkcs7_signed_info * sinfo)98 static int authattrs_parse(struct pkcs7_message *msg, void *aa, size_t aa_len,
99 			   struct pkcs7_signed_info *sinfo)
100 {
101 	unsigned char *p = aa;
102 	unsigned char *end = (unsigned char *)aa + aa_len;
103 	size_t len = 0;
104 	int ret;
105 	unsigned char *inner_p;
106 	size_t seq_len = 0;
107 
108 	ret = mbedtls_asn1_get_tag(&p, end, &seq_len,
109 				   MBEDTLS_ASN1_CONTEXT_SPECIFIC |
110 				   MBEDTLS_ASN1_CONSTRUCTED);
111 	if (ret)
112 		return ret;
113 
114 	while (!mbedtls_asn1_get_tag(&p, end, &seq_len,
115 				     MBEDTLS_ASN1_CONSTRUCTED |
116 				     MBEDTLS_ASN1_SEQUENCE)) {
117 		inner_p = p;
118 		ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
119 					   MBEDTLS_ASN1_OID);
120 		if (ret)
121 			return ret;
122 
123 		if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_CONTENTTYPE, inner_p, len)) {
124 			inner_p += len;
125 			ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
126 						   MBEDTLS_ASN1_CONSTRUCTED |
127 						   MBEDTLS_ASN1_SET);
128 			if (ret)
129 				return ret;
130 
131 			ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
132 						   MBEDTLS_ASN1_OID);
133 			if (ret)
134 				return ret;
135 
136 			/*
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
141 			 * Secure Boot.
142 			 */
143 			if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_INDIRECTDATA,
144 						inner_p, len) &&
145 			    MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA,
146 						inner_p, len))
147 				return -EINVAL;
148 
149 			if (__test_and_set_bit(sinfo_has_content_type, &sinfo->aa_set))
150 				return -EINVAL;
151 		} else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_MESSAGEDIGEST, inner_p,
152 						len)) {
153 			inner_p += len;
154 			ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
155 						   MBEDTLS_ASN1_CONSTRUCTED |
156 						   MBEDTLS_ASN1_SET);
157 			if (ret)
158 				return ret;
159 
160 			ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
161 						   MBEDTLS_ASN1_OCTET_STRING);
162 			if (ret)
163 				return ret;
164 
165 			sinfo->msgdigest = inner_p;
166 			sinfo->msgdigest_len = len;
167 
168 			if (__test_and_set_bit(sinfo_has_message_digest, &sinfo->aa_set))
169 				return -EINVAL;
170 		} else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_SIGNINGTIME, inner_p,
171 						len)) {
172 			mbedtls_x509_time st;
173 
174 			inner_p += len;
175 			ret = mbedtls_asn1_get_tag(&inner_p, p + seq_len, &len,
176 						   MBEDTLS_ASN1_CONSTRUCTED |
177 						   MBEDTLS_ASN1_SET);
178 			if (ret)
179 				return ret;
180 
181 			ret = mbedtls_x509_get_time(&inner_p, p + seq_len, &st);
182 			if (ret)
183 				return ret;
184 			sinfo->signing_time = x509_get_timestamp(&st);
185 
186 			if (__test_and_set_bit(sinfo_has_signing_time, &sinfo->aa_set))
187 				return -EINVAL;
188 		} else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS9_SMIMECAP, inner_p,
189 						len)) {
190 			if (__test_and_set_bit(sinfo_has_smime_caps, &sinfo->aa_set))
191 				return -EINVAL;
192 		} else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_SPOPUSINFO, inner_p,
193 						len)) {
194 			if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
195 				return -EINVAL;
196 		} else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_STATETYPE, inner_p,
197 						len)) {
198 			if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
199 				return -EINVAL;
200 		}
201 
202 		p += seq_len;
203 	}
204 
205 	msg->have_authattrs = true;
206 
207 	/*
208 	 * Skip the leading tag byte (MBEDTLS_ASN1_CONTEXT_SPECIFIC |
209 	 * MBEDTLS_ASN1_CONSTRUCTED) to satisfy pkcs7_digest() when calculating
210 	 * the digest of authattrs.
211 	 */
212 	sinfo->authattrs = aa + 1;
213 	sinfo->authattrs_len = aa_len - 1;
214 
215 	return 0;
216 }
217 
x509_populate_content_data(struct pkcs7_message * msg,mbedtls_pkcs7 * pkcs7_ctx)218 static int x509_populate_content_data(struct pkcs7_message *msg,
219 				      mbedtls_pkcs7 *pkcs7_ctx)
220 {
221 	struct pkcs7_mbedtls_ctx *mctx;
222 
223 	if (!pkcs7_ctx->content_data.data ||
224 	    !pkcs7_ctx->content_data.data_len)
225 		return 0;
226 
227 	mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
228 	if (!mctx)
229 		return -ENOMEM;
230 
231 	mctx->content_data = kmemdup(pkcs7_ctx->content_data.data,
232 				     pkcs7_ctx->content_data.data_len,
233 				     GFP_KERNEL);
234 	if (!mctx->content_data) {
235 		pkcs7_free_mbedtls_ctx(mctx);
236 		return -ENOMEM;
237 	}
238 
239 	msg->data = mctx->content_data;
240 	msg->data_len = pkcs7_ctx->content_data.data_len;
241 	msg->data_hdrlen = pkcs7_ctx->content_data.data_hdrlen;
242 	msg->data_type = pkcs7_ctx->content_data.data_type;
243 
244 	msg->mbedtls_ctx = mctx;
245 	return 0;
246 }
247 
x509_populate_sinfo(struct pkcs7_message * msg,mbedtls_pkcs7_signer_info * mb_sinfo,struct pkcs7_signed_info ** sinfo)248 static int x509_populate_sinfo(struct pkcs7_message *msg,
249 			       mbedtls_pkcs7_signer_info *mb_sinfo,
250 			       struct pkcs7_signed_info **sinfo)
251 {
252 	struct pkcs7_signed_info *signed_info;
253 	struct public_key_signature *s;
254 	mbedtls_md_type_t md_alg;
255 	struct pkcs7_sinfo_mbedtls_ctx *mctx;
256 	int ret;
257 
258 	signed_info = kzalloc(sizeof(*signed_info), GFP_KERNEL);
259 	if (!signed_info)
260 		return -ENOMEM;
261 
262 	s = kzalloc(sizeof(*s), GFP_KERNEL);
263 	if (!s) {
264 		ret = -ENOMEM;
265 		goto out_no_sig;
266 	}
267 
268 	mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
269 	if (!mctx) {
270 		ret = -ENOMEM;
271 		goto out_no_mctx;
272 	}
273 
274 	/*
275 	 * Hash algorithm:
276 	 *
277 	 * alg_identifier =	digestAlgorithm (DigestAlgorithmIdentifier)
278 	 *			MbedTLS internally checks this field to ensure
279 	 *			it is the same as digest_alg_identifiers.
280 	 * sig_alg_identifier =	digestEncryptionAlgorithm
281 	 *			(DigestEncryptionAlgorithmIdentifier)
282 	 *			MbedTLS just saves this field without any actions.
283 	 * See function pkcs7_get_signer_info() for reference.
284 	 *
285 	 * Public key algorithm:
286 	 * No information related to public key algorithm under MbedTLS signer
287 	 * info. Assume that we are using RSA.
288 	 */
289 	ret = mbedtls_oid_get_md_alg(&mb_sinfo->alg_identifier, &md_alg);
290 	if (ret)
291 		goto out_err_sinfo;
292 	s->pkey_algo = "rsa";
293 
294 	/* Translate the hash algorithm */
295 	switch (md_alg) {
296 	case MBEDTLS_MD_SHA1:
297 		s->hash_algo = "sha1";
298 		s->digest_size = SHA1_SUM_LEN;
299 		break;
300 	case MBEDTLS_MD_SHA256:
301 		s->hash_algo = "sha256";
302 		s->digest_size = SHA256_SUM_LEN;
303 		break;
304 	case MBEDTLS_MD_SHA384:
305 		s->hash_algo = "sha384";
306 		s->digest_size = SHA384_SUM_LEN;
307 		break;
308 	case MBEDTLS_MD_SHA512:
309 		s->hash_algo = "sha512";
310 		s->digest_size = SHA512_SUM_LEN;
311 		break;
312 	/* Unsupported algo */
313 	case MBEDTLS_MD_MD5:
314 	case MBEDTLS_MD_SHA224:
315 	default:
316 		ret = -EINVAL;
317 		goto out_err_sinfo;
318 	}
319 
320 	/*
321 	 * auth_ids holds AuthorityKeyIdentifier, aka akid
322 	 * auth_ids[0]:
323 	 *	[PKCS#7 or CMS ver 1] - generated from "Issuer + Serial number"
324 	 *	[CMS ver 3] - generated from skid (subjectKeyId)
325 	 * auth_ids[1]: generated from skid (subjectKeyId)
326 	 *
327 	 * Assume that we are using PKCS#7 (msg->version=1),
328 	 * not CMS ver 3 (msg->version=3).
329 	 */
330 	s->auth_ids[0] = asymmetric_key_generate_id(mb_sinfo->serial.p,
331 						    mb_sinfo->serial.len,
332 						    mb_sinfo->issuer_raw.p,
333 						    mb_sinfo->issuer_raw.len);
334 	if (!s->auth_ids[0]) {
335 		ret = -ENOMEM;
336 		goto out_err_sinfo;
337 	}
338 
339 	/* skip s->auth_ids[1], no subjectKeyId in MbedTLS signer info ctx */
340 
341 	/*
342 	 * Encoding can be pkcs1 or raw, but only pkcs1 is supported.
343 	 * Set the encoding explicitly to pkcs1.
344 	 */
345 	s->encoding = "pkcs1";
346 
347 	/* Copy the signature data */
348 	s->s = kmemdup(mb_sinfo->sig.p, mb_sinfo->sig.len, GFP_KERNEL);
349 	if (!s->s) {
350 		ret = -ENOMEM;
351 		goto out_err_sinfo;
352 	}
353 	s->s_size = mb_sinfo->sig.len;
354 	signed_info->sig = s;
355 
356 	/* Save the Authenticate Attributes data if exists */
357 	if (!mb_sinfo->authattrs.data || !mb_sinfo->authattrs.data_len) {
358 		kfree(mctx);
359 		goto no_authattrs;
360 	}
361 
362 	mctx->authattrs_data = kmemdup(mb_sinfo->authattrs.data,
363 				       mb_sinfo->authattrs.data_len,
364 				       GFP_KERNEL);
365 	if (!mctx->authattrs_data) {
366 		ret = -ENOMEM;
367 		goto out_err_sinfo;
368 	}
369 	signed_info->mbedtls_ctx = mctx;
370 
371 	/* If authattrs exists, decode it and parse msgdigest from it */
372 	ret = authattrs_parse(msg, mctx->authattrs_data,
373 			      mb_sinfo->authattrs.data_len,
374 			      signed_info);
375 	if (ret)
376 		goto out_err_sinfo;
377 
378 no_authattrs:
379 	*sinfo = signed_info;
380 	return 0;
381 
382 out_err_sinfo:
383 	pkcs7_free_sinfo_mbedtls_ctx(mctx);
384 out_no_mctx:
385 	public_key_signature_free(s);
386 out_no_sig:
387 	kfree(signed_info);
388 	return ret;
389 }
390 
391 /*
392  * Free a signed information block.
393  */
pkcs7_free_signed_info(struct pkcs7_signed_info * sinfo)394 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
395 {
396 	if (sinfo) {
397 		public_key_signature_free(sinfo->sig);
398 		pkcs7_free_sinfo_mbedtls_ctx(sinfo->mbedtls_ctx);
399 		kfree(sinfo);
400 	}
401 }
402 
403 /**
404  * pkcs7_free_message - Free a PKCS#7 message
405  * @pkcs7: The PKCS#7 message to free
406  */
pkcs7_free_message(struct pkcs7_message * pkcs7)407 void pkcs7_free_message(struct pkcs7_message *pkcs7)
408 {
409 	struct x509_certificate *cert;
410 	struct pkcs7_signed_info *sinfo;
411 
412 	if (pkcs7) {
413 		while (pkcs7->certs) {
414 			cert = pkcs7->certs;
415 			pkcs7->certs = cert->next;
416 			x509_free_certificate(cert);
417 		}
418 		while (pkcs7->crl) {
419 			cert = pkcs7->crl;
420 			pkcs7->crl = cert->next;
421 			x509_free_certificate(cert);
422 		}
423 		while (pkcs7->signed_infos) {
424 			sinfo = pkcs7->signed_infos;
425 			pkcs7->signed_infos = sinfo->next;
426 			pkcs7_free_signed_info(sinfo);
427 		}
428 		pkcs7_free_mbedtls_ctx(pkcs7->mbedtls_ctx);
429 		kfree(pkcs7);
430 	}
431 }
432 
pkcs7_parse_message(const void * data,size_t datalen)433 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
434 {
435 	int i;
436 	int ret;
437 	mbedtls_pkcs7 pkcs7_ctx;
438 	mbedtls_pkcs7_signer_info *mb_sinfos;
439 	mbedtls_x509_crt *mb_certs;
440 	struct pkcs7_message *msg;
441 	struct x509_certificate **cert;
442 	struct pkcs7_signed_info **sinfos;
443 
444 	msg = kzalloc(sizeof(*msg), GFP_KERNEL);
445 	if (!msg) {
446 		ret = -ENOMEM;
447 		goto out_no_msg;
448 	}
449 
450 	/* Parse the DER encoded PKCS#7 message using MbedTLS */
451 	mbedtls_pkcs7_init(&pkcs7_ctx);
452 	ret = mbedtls_pkcs7_parse_der(&pkcs7_ctx, data, datalen);
453 	/* Check if it is a PKCS#7 message with signed data */
454 	if (ret != MBEDTLS_PKCS7_SIGNED_DATA)
455 		goto parse_fail;
456 
457 	/* Assume that we are using PKCS#7, not CMS ver 3 */
458 	msg->version = 1;	/* 1 for [PKCS#7 or CMS ver 1] */
459 
460 	/* Populate the certs to msg->certs */
461 	for (i = 0, cert = &msg->certs, mb_certs = &pkcs7_ctx.signed_data.certs;
462 	     i < pkcs7_ctx.signed_data.no_of_certs && mb_certs;
463 	     i++, cert = &(*cert)->next, mb_certs = mb_certs->next) {
464 		ret = x509_populate_cert(mb_certs, cert);
465 		if (ret)
466 			goto parse_fail;
467 
468 		(*cert)->index = i + 1;
469 	}
470 
471 	/*
472 	 * Skip populating crl, that is not currently in-use.
473 	 */
474 
475 	/* Populate content data */
476 	ret = x509_populate_content_data(msg, &pkcs7_ctx);
477 	if (ret)
478 		goto parse_fail;
479 
480 	/* Populate signed info to msg->signed_infos */
481 	for (i = 0, sinfos = &msg->signed_infos,
482 	     mb_sinfos = &pkcs7_ctx.signed_data.signers;
483 	     i < pkcs7_ctx.signed_data.no_of_signers && mb_sinfos;
484 	     i++, sinfos = &(*sinfos)->next, mb_sinfos = mb_sinfos->next) {
485 		ret = x509_populate_sinfo(msg, mb_sinfos, sinfos);
486 		if (ret)
487 			goto parse_fail;
488 
489 		(*sinfos)->index = i + 1;
490 	}
491 
492 	mbedtls_pkcs7_free(&pkcs7_ctx);
493 	return msg;
494 
495 parse_fail:
496 	mbedtls_pkcs7_free(&pkcs7_ctx);
497 	pkcs7_free_message(msg);
498 out_no_msg:
499 	msg = ERR_PTR(ret);
500 	return msg;
501 }
502