]> Git Repo - u-boot.git/blob - lib/mbedtls/pkcs7_parser.c
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sh
[u-boot.git] / lib / mbedtls / pkcs7_parser.c
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 <[email protected]>
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
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
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  */
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
193                         if (msg->data_type != OID_msIndirectData &&
194                             msg->data_type != OID_data)
195                                 return -EINVAL;
196                 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_SPOPUSINFO, inner_p,
197                                                 len)) {
198                         if (__test_and_set_bit(sinfo_has_ms_opus_info, &sinfo->aa_set))
199                                 return -EINVAL;
200                 } else if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_MICROSOFT_STATETYPE, inner_p,
201                                                 len)) {
202                         if (__test_and_set_bit(sinfo_has_ms_statement_type, &sinfo->aa_set))
203                                 return -EINVAL;
204                 }
205
206                 p += seq_len;
207         }
208
209         msg->have_authattrs = true;
210
211         /*
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.
215          */
216         sinfo->authattrs = aa + 1;
217         sinfo->authattrs_len = aa_len - 1;
218
219         return 0;
220 }
221
222 static int x509_populate_content_data(struct pkcs7_message *msg,
223                                       mbedtls_pkcs7 *pkcs7_ctx)
224 {
225         struct pkcs7_mbedtls_ctx *mctx;
226
227         if (!pkcs7_ctx->content_data.data ||
228             !pkcs7_ctx->content_data.data_len)
229                 return 0;
230
231         mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
232         if (!mctx)
233                 return -ENOMEM;
234
235         mctx->content_data = kmemdup(pkcs7_ctx->content_data.data,
236                                      pkcs7_ctx->content_data.data_len,
237                                      GFP_KERNEL);
238         if (!mctx->content_data) {
239                 pkcs7_free_mbedtls_ctx(mctx);
240                 return -ENOMEM;
241         }
242
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;
247
248         msg->mbedtls_ctx = mctx;
249         return 0;
250 }
251
252 static int x509_populate_sinfo(struct pkcs7_message *msg,
253                                mbedtls_pkcs7_signer_info *mb_sinfo,
254                                struct pkcs7_signed_info **sinfo)
255 {
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;
260         int ret;
261
262         signed_info = kzalloc(sizeof(*signed_info), GFP_KERNEL);
263         if (!signed_info)
264                 return -ENOMEM;
265
266         s = kzalloc(sizeof(*s), GFP_KERNEL);
267         if (!s) {
268                 ret = -ENOMEM;
269                 goto out_no_sig;
270         }
271
272         mctx = kzalloc(sizeof(*mctx), GFP_KERNEL);
273         if (!mctx) {
274                 ret = -ENOMEM;
275                 goto out_no_mctx;
276         }
277
278         /*
279          * Hash algorithm:
280          *
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.
288          *
289          * Public key algorithm:
290          * No information related to public key algorithm under MbedTLS signer
291          * info. Assume that we are using RSA.
292          */
293         ret = mbedtls_oid_get_md_alg(&mb_sinfo->alg_identifier, &md_alg);
294         if (ret)
295                 goto out_err_sinfo;
296         s->pkey_algo = "rsa";
297
298         /* Translate the hash algorithm */
299         switch (md_alg) {
300         case MBEDTLS_MD_SHA1:
301                 s->hash_algo = "sha1";
302                 s->digest_size = SHA1_SUM_LEN;
303                 break;
304         case MBEDTLS_MD_SHA256:
305                 s->hash_algo = "sha256";
306                 s->digest_size = SHA256_SUM_LEN;
307                 break;
308         case MBEDTLS_MD_SHA384:
309                 s->hash_algo = "sha384";
310                 s->digest_size = SHA384_SUM_LEN;
311                 break;
312         case MBEDTLS_MD_SHA512:
313                 s->hash_algo = "sha512";
314                 s->digest_size = SHA512_SUM_LEN;
315                 break;
316         /* Unsupported algo */
317         case MBEDTLS_MD_MD5:
318         case MBEDTLS_MD_SHA224:
319         default:
320                 ret = -EINVAL;
321                 goto out_err_sinfo;
322         }
323
324         /*
325          * auth_ids holds AuthorityKeyIdentifier, aka akid
326          * auth_ids[0]:
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)
330          *
331          * Assume that we are using PKCS#7 (msg->version=1),
332          * not CMS ver 3 (msg->version=3).
333          */
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]) {
339                 ret = -ENOMEM;
340                 goto out_err_sinfo;
341         }
342
343         /* skip s->auth_ids[1], no subjectKeyId in MbedTLS signer info ctx */
344
345         /*
346          * Encoding can be pkcs1 or raw, but only pkcs1 is supported.
347          * Set the encoding explicitly to pkcs1.
348          */
349         s->encoding = "pkcs1";
350
351         /* Copy the signature data */
352         s->s = kmemdup(mb_sinfo->sig.p, mb_sinfo->sig.len, GFP_KERNEL);
353         if (!s->s) {
354                 ret = -ENOMEM;
355                 goto out_err_sinfo;
356         }
357         s->s_size = mb_sinfo->sig.len;
358         signed_info->sig = s;
359
360         /* Save the Authenticate Attributes data if exists */
361         if (!mb_sinfo->authattrs.data || !mb_sinfo->authattrs.data_len) {
362                 kfree(mctx);
363                 goto no_authattrs;
364         }
365
366         mctx->authattrs_data = kmemdup(mb_sinfo->authattrs.data,
367                                        mb_sinfo->authattrs.data_len,
368                                        GFP_KERNEL);
369         if (!mctx->authattrs_data) {
370                 ret = -ENOMEM;
371                 goto out_err_sinfo;
372         }
373         signed_info->mbedtls_ctx = mctx;
374
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,
378                               signed_info);
379         if (ret)
380                 goto out_err_sinfo;
381
382 no_authattrs:
383         *sinfo = signed_info;
384         return 0;
385
386 out_err_sinfo:
387         pkcs7_free_sinfo_mbedtls_ctx(mctx);
388 out_no_mctx:
389         public_key_signature_free(s);
390 out_no_sig:
391         kfree(signed_info);
392         return ret;
393 }
394
395 /*
396  * Free a signed information block.
397  */
398 static void pkcs7_free_signed_info(struct pkcs7_signed_info *sinfo)
399 {
400         if (sinfo) {
401                 public_key_signature_free(sinfo->sig);
402                 pkcs7_free_sinfo_mbedtls_ctx(sinfo->mbedtls_ctx);
403                 kfree(sinfo);
404         }
405 }
406
407 /**
408  * pkcs7_free_message - Free a PKCS#7 message
409  * @pkcs7: The PKCS#7 message to free
410  */
411 void pkcs7_free_message(struct pkcs7_message *pkcs7)
412 {
413         struct x509_certificate *cert;
414         struct pkcs7_signed_info *sinfo;
415
416         if (pkcs7) {
417                 while (pkcs7->certs) {
418                         cert = pkcs7->certs;
419                         pkcs7->certs = cert->next;
420                         x509_free_certificate(cert);
421                 }
422                 while (pkcs7->crl) {
423                         cert = pkcs7->crl;
424                         pkcs7->crl = cert->next;
425                         x509_free_certificate(cert);
426                 }
427                 while (pkcs7->signed_infos) {
428                         sinfo = pkcs7->signed_infos;
429                         pkcs7->signed_infos = sinfo->next;
430                         pkcs7_free_signed_info(sinfo);
431                 }
432                 pkcs7_free_mbedtls_ctx(pkcs7->mbedtls_ctx);
433                 kfree(pkcs7);
434         }
435 }
436
437 struct pkcs7_message *pkcs7_parse_message(const void *data, size_t datalen)
438 {
439         int i;
440         int ret;
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;
447
448         msg = kzalloc(sizeof(*msg), GFP_KERNEL);
449         if (!msg) {
450                 ret = -ENOMEM;
451                 goto out_no_msg;
452         }
453
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)
459                 goto parse_fail;
460
461         /* Assume that we are using PKCS#7, not CMS ver 3 */
462         msg->version = 1;       /* 1 for [PKCS#7 or CMS ver 1] */
463
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);
469                 if (ret)
470                         goto parse_fail;
471
472                 (*cert)->index = i + 1;
473         }
474
475         /*
476          * Skip populating crl, that is not currently in-use.
477          */
478
479         /* Populate content data */
480         ret = x509_populate_content_data(msg, &pkcs7_ctx);
481         if (ret)
482                 goto parse_fail;
483
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);
490                 if (ret)
491                         goto parse_fail;
492
493                 (*sinfos)->index = i + 1;
494         }
495
496         mbedtls_pkcs7_free(&pkcs7_ctx);
497         return msg;
498
499 parse_fail:
500         mbedtls_pkcs7_free(&pkcs7_ctx);
501         pkcs7_free_message(msg);
502 out_no_msg:
503         msg = ERR_PTR(ret);
504         return msg;
505 }
This page took 0.053217 seconds and 4 git commands to generate.