1 /*
2  *  Copyright The Mbed TLS Contributors
3  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
4  */
5 #include "common.h"
6 
7 #include "mbedtls/build_info.h"
8 #if defined(MBEDTLS_PKCS7_C)
9 #include "mbedtls/pkcs7.h"
10 #include "x509_internal.h"
11 #include "mbedtls/asn1.h"
12 #include "mbedtls/x509_crt.h"
13 #include "mbedtls/x509_crl.h"
14 #include "mbedtls/oid.h"
15 #include "mbedtls/error.h"
16 
17 #if defined(MBEDTLS_FS_IO)
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 #endif
21 
22 #include "mbedtls/platform.h"
23 #include "mbedtls/platform_util.h"
24 
25 #if defined(MBEDTLS_HAVE_TIME)
26 #include "mbedtls/platform_time.h"
27 #endif
28 #if defined(MBEDTLS_HAVE_TIME_DATE)
29 #include <time.h>
30 #endif
31 
32 enum OID {
33     /* PKCS#7 {iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) pkcs-7(7)} */
34     MBEDTLS_OID_DATA = 13,          /* 1.2.840.113549.1.7.1 */
35     /* Microsoft Authenticode & Software Publishing */
36     MBEDTLS_OID_MS_INDIRECTDATA = 24,        /* 1.3.6.1.4.1.311.2.1.4 */
37 };
38 
39 /**
40  * Initializes the mbedtls_pkcs7 structure.
41  */
mbedtls_pkcs7_init(mbedtls_pkcs7 * pkcs7)42 void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
43 {
44     memset(pkcs7, 0, sizeof(*pkcs7));
45 }
46 
pkcs7_get_next_content_len(unsigned char ** p,unsigned char * end,size_t * len)47 static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
48                                       size_t *len)
49 {
50     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
51 
52     ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
53                                | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
54     if (ret != 0) {
55         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
56     } else if ((size_t) (end - *p) != *len) {
57         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
58                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
59     }
60 
61     return ret;
62 }
63 
64 /**
65  * Get and decode one cert from a sequence.
66  * Return 0 for success,
67  * Return negative error code for failure.
68  **/
pkcs7_get_one_cert(unsigned char ** p,unsigned char * end,mbedtls_x509_crt * certs)69 static int pkcs7_get_one_cert(unsigned char **p, unsigned char *end,
70                               mbedtls_x509_crt *certs)
71 {
72     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
73     size_t len = 0;
74     unsigned char *start = *p;
75     unsigned char *end_cert;
76 
77     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
78                                | MBEDTLS_ASN1_SEQUENCE);
79     if (ret != 0) {
80         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
81     }
82 
83     end_cert = *p + len;
84 
85     if ((ret = mbedtls_x509_crt_parse_der(certs, start, end_cert - start)) < 0) {
86         return MBEDTLS_ERR_PKCS7_INVALID_CERT;
87     }
88 
89     *p = end_cert;
90 
91     return 0;
92 }
93 
94 /**
95  * version Version
96  * Version ::= INTEGER
97  **/
pkcs7_get_version(unsigned char ** p,unsigned char * end,int * ver)98 static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
99 {
100     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101 
102     ret = mbedtls_asn1_get_int(p, end, ver);
103     if (ret != 0) {
104         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
105     }
106 
107     /* If version != 1, return invalid version */
108     if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
109         ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
110     }
111 
112     return ret;
113 }
114 
115 /**
116  * ContentInfo ::= SEQUENCE {
117  *      contentType ContentType,
118  *      content
119  *              [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
120  **/
pkcs7_get_content_info_type(unsigned char ** p,unsigned char * end,unsigned char ** seq_end,mbedtls_pkcs7_buf * pkcs7)121 static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
122                                        unsigned char **seq_end,
123                                        mbedtls_pkcs7_buf *pkcs7)
124 {
125     size_t len = 0;
126     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
127     unsigned char *start = *p;
128 
129     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
130                                | MBEDTLS_ASN1_SEQUENCE);
131     if (ret != 0) {
132         *p = start;
133         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
134     }
135     *seq_end = *p + len;
136     ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
137     if (ret != 0) {
138         *p = start;
139         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
140     }
141 
142     pkcs7->tag = MBEDTLS_ASN1_OID;
143     pkcs7->len = len;
144     pkcs7->p = *p;
145     *p += len;
146 
147     return ret;
148 }
149 
150 /**
151  * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
152  *
153  * This is from x509.h
154  **/
pkcs7_get_digest_algorithm(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)155 static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
156                                       mbedtls_x509_buf *alg)
157 {
158     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
159 
160     if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
161         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
162     }
163 
164     return ret;
165 }
166 
167 /**
168  * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
169  **/
pkcs7_get_digest_algorithm_set(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)170 static int pkcs7_get_digest_algorithm_set(unsigned char **p,
171                                           unsigned char *end,
172                                           mbedtls_x509_buf *alg)
173 {
174     size_t len = 0;
175     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
176 
177     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
178                                | MBEDTLS_ASN1_SET);
179     if (ret != 0) {
180         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
181     }
182 
183     end = *p + len;
184 
185     ret = mbedtls_asn1_get_alg_null(p, end, alg);
186     if (ret != 0) {
187         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
188     }
189 
190     /** For now, it assumes there is only one digest algorithm specified **/
191     if (*p != end) {
192         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
193     }
194 
195     return 0;
196 }
197 
198 /**
199  * certificates :: SET OF ExtendedCertificateOrCertificate,
200  * ExtendedCertificateOrCertificate ::= CHOICE {
201  *      certificate Certificate -- x509,
202  *      extendedCertificate[0] IMPLICIT ExtendedCertificate }
203  * Return number of certificates added to the signed data,
204  * 0 or higher is valid.
205  * Return negative error code for failure.
206  **/
pkcs7_get_certificates(unsigned char ** p,unsigned char * end,mbedtls_x509_crt * certs)207 static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
208                                   mbedtls_x509_crt *certs)
209 {
210     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
211     size_t len = 0;
212     unsigned char *end_set;
213     int num_of_certs = 0;
214 
215     /* Get the set of certs */
216     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
217                                | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
218     if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
219         return 0;
220     }
221     if (ret != 0) {
222         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
223     }
224     end_set = *p + len;
225 
226     ret = pkcs7_get_one_cert(p, end_set, certs);
227     if (ret != 0) {
228         return ret;
229     }
230 
231     num_of_certs++;
232 
233     while (*p != end_set) {
234         ret = pkcs7_get_one_cert(p, end_set, certs);
235         if (ret != 0) {
236             return ret;
237         }
238         num_of_certs++;
239     }
240 
241     *p = end_set;
242 
243     return num_of_certs;
244 }
245 
246 /**
247  * EncryptedDigest ::= OCTET STRING
248  **/
pkcs7_get_signature(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_buf * signature)249 static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
250                                mbedtls_pkcs7_buf *signature)
251 {
252     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
253     size_t len = 0;
254 
255     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
256     if (ret != 0) {
257         return ret;
258     }
259 
260     signature->tag = MBEDTLS_ASN1_OCTET_STRING;
261     signature->len = len;
262     signature->p = *p;
263 
264     *p = *p + len;
265 
266     return 0;
267 }
268 
pkcs7_free_signer_info(mbedtls_pkcs7_signer_info * signer)269 static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
270 {
271     mbedtls_x509_name *name_cur;
272     mbedtls_x509_name *name_prv;
273 
274     if (signer == NULL) {
275         return;
276     }
277 
278     name_cur = signer->issuer.next;
279     while (name_cur != NULL) {
280         name_prv = name_cur;
281         name_cur = name_cur->next;
282         mbedtls_free(name_prv);
283     }
284     signer->issuer.next = NULL;
285 }
286 
287 /**
288  * SignerInfo ::= SEQUENCE {
289  *      version Version;
290  *      issuerAndSerialNumber   IssuerAndSerialNumber,
291  *      digestAlgorithm DigestAlgorithmIdentifier,
292  *      authenticatedAttributes
293  *              [0] IMPLICIT Attributes OPTIONAL,
294  *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
295  *      encryptedDigest EncryptedDigest,
296  *      unauthenticatedAttributes
297  *              [1] IMPLICIT Attributes OPTIONAL,
298  * Returns 0 if the signerInfo is valid.
299  * Return negative error code for failure.
300  * Structure must not contain vales for authenticatedAttributes
301  * and unauthenticatedAttributes.
302  **/
pkcs7_get_signer_info(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signer,mbedtls_x509_buf * alg)303 static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
304                                  mbedtls_pkcs7_signer_info *signer,
305                                  mbedtls_x509_buf *alg)
306 {
307     unsigned char *end_signer, *end_issuer_and_sn;
308     int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
309     size_t len = 0;
310     unsigned char *tmp_p;
311 
312     asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
313                                     | MBEDTLS_ASN1_SEQUENCE);
314     if (asn1_ret != 0) {
315         goto out;
316     }
317 
318     end_signer = *p + len;
319 
320     ret = pkcs7_get_version(p, end_signer, &signer->version);
321     if (ret != 0) {
322         goto out;
323     }
324 
325     asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
326                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
327     if (asn1_ret != 0) {
328         goto out;
329     }
330 
331     end_issuer_and_sn = *p + len;
332     /* Parsing IssuerAndSerialNumber */
333     signer->issuer_raw.p = *p;
334 
335     asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
336                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
337     if (asn1_ret != 0) {
338         goto out;
339     }
340 
341     ret  = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
342     if (ret != 0) {
343         goto out;
344     }
345 
346     signer->issuer_raw.len =  (size_t) (*p - signer->issuer_raw.p);
347 
348     ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
349     if (ret != 0) {
350         goto out;
351     }
352 
353     /* ensure no extra or missing bytes */
354     if (*p != end_issuer_and_sn) {
355         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
356         goto out;
357     }
358 
359     ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
360     if (ret != 0) {
361         goto out;
362     }
363 
364     /* Check that the digest algorithm used matches the one provided earlier */
365     if (signer->alg_identifier.tag != alg->tag ||
366         signer->alg_identifier.len != alg->len ||
367         memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
368         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
369         goto out;
370     }
371 
372     /* Save authenticatedAttributes if present */
373     if (*p < end_signer &&
374         **p == (MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0)) {
375         tmp_p = *p;
376 
377         ret = mbedtls_asn1_get_tag(p, end_signer, &len,
378                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC |
379                                    MBEDTLS_ASN1_CONSTRUCTED | 0);
380         if (ret != 0) {
381             goto out;
382         }
383 
384         signer->authattrs.data = tmp_p;
385         signer->authattrs.data_len = len + *p - tmp_p;
386         *p += len;
387     }
388 
389     ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
390     if (ret != 0) {
391         goto out;
392     }
393 
394     ret = pkcs7_get_signature(p, end_signer, &signer->sig);
395     if (ret != 0) {
396         goto out;
397     }
398 
399     /* Do not permit any unauthenticated attributes */
400     if (*p != end_signer) {
401         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
402     }
403 
404 out:
405     if (asn1_ret != 0 || ret != 0) {
406         pkcs7_free_signer_info(signer);
407         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
408                                 asn1_ret);
409     }
410 
411     return ret;
412 }
413 
414 /**
415  * SignerInfos ::= SET of SignerInfo
416  * Return number of signers added to the signed data,
417  * 0 or higher is valid.
418  * Return negative error code for failure.
419  **/
pkcs7_get_signers_info_set(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signers_set,mbedtls_x509_buf * digest_alg)420 static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
421                                       mbedtls_pkcs7_signer_info *signers_set,
422                                       mbedtls_x509_buf *digest_alg)
423 {
424     unsigned char *end_set;
425     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
426     int count = 0;
427     size_t len = 0;
428 
429     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
430                                | MBEDTLS_ASN1_SET);
431     if (ret != 0) {
432         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
433     }
434 
435     /* Detect zero signers */
436     if (len == 0) {
437         return 0;
438     }
439 
440     end_set = *p + len;
441 
442     ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
443     if (ret != 0) {
444         return ret;
445     }
446     count++;
447 
448     mbedtls_pkcs7_signer_info *prev = signers_set;
449     while (*p != end_set) {
450         mbedtls_pkcs7_signer_info *signer =
451             mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
452         if (!signer) {
453             ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
454             goto cleanup;
455         }
456 
457         ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
458         if (ret != 0) {
459             mbedtls_free(signer);
460             goto cleanup;
461         }
462         prev->next = signer;
463         prev = signer;
464         count++;
465     }
466 
467     return count;
468 
469 cleanup:
470     pkcs7_free_signer_info(signers_set);
471     mbedtls_pkcs7_signer_info *signer = signers_set->next;
472     while (signer != NULL) {
473         prev = signer;
474         signer = signer->next;
475         pkcs7_free_signer_info(prev);
476         mbedtls_free(prev);
477     }
478     signers_set->next = NULL;
479     return ret;
480 }
481 
482 /**
483  * SignedData ::= SEQUENCE {
484  *      version Version,
485  *      digestAlgorithms DigestAlgorithmIdentifiers,
486  *      contentInfo ContentInfo,
487  *      certificates
488  *              [0] IMPLICIT ExtendedCertificatesAndCertificates
489  *                  OPTIONAL,
490  *      crls
491  *              [0] IMPLICIT CertificateRevocationLists OPTIONAL,
492  *      signerInfos SignerInfos }
493  */
pkcs7_get_signed_data(unsigned char * buf,size_t buflen,mbedtls_pkcs7 * pkcs7)494 static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
495                                  mbedtls_pkcs7 *pkcs7)
496 {
497     unsigned char *p = buf;
498     unsigned char *end = buf + buflen;
499     unsigned char *end_content_info = NULL;
500     size_t len = 0;
501     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502     mbedtls_md_type_t md_alg;
503     mbedtls_pkcs7_signed_data *signed_data = &pkcs7->signed_data;
504 
505     ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
506                                | MBEDTLS_ASN1_SEQUENCE);
507     if (ret != 0) {
508         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
509     }
510 
511     if (p + len != end) {
512         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
513                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
514     }
515 
516     /* Get version of signed data */
517     ret = pkcs7_get_version(&p, end, &signed_data->version);
518     if (ret != 0) {
519         return ret;
520     }
521 
522     /* Get digest algorithm */
523     ret = pkcs7_get_digest_algorithm_set(&p, end,
524                                          &signed_data->digest_alg_identifiers);
525     if (ret != 0) {
526         return ret;
527     }
528 
529     ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
530     if (ret != 0) {
531         return MBEDTLS_ERR_PKCS7_INVALID_ALG;
532     }
533 
534     mbedtls_pkcs7_buf content_type;
535     memset(&content_type, 0, sizeof(content_type));
536     ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
537     if (ret != 0) {
538         return ret;
539     }
540 
541     /*
542      * We should only support 1.2.840.113549.1.7.1 (PKCS7 DATA) and
543      * 1.3.6.1.4.1.311.2.1.4 (MicroSoft Authentication Code) that is for
544      * U-Boot Secure Boot
545      */
546     if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
547         pkcs7->content_data.data_type = MBEDTLS_OID_DATA;
548     } else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_MICROSOFT_INDIRECTDATA,
549                                 &content_type)) {
550         pkcs7->content_data.data_type = MBEDTLS_OID_MS_INDIRECTDATA;
551     } else {
552         return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
553     }
554 
555     if (p != end_content_info) {
556         unsigned char *tmp_p = p;
557 
558         /* Determine if valid content is present */
559         ret = mbedtls_asn1_get_tag(&p,
560                                    end_content_info,
561                                    &len,
562                                    MBEDTLS_ASN1_CONSTRUCTED |
563                                    MBEDTLS_ASN1_CONTEXT_SPECIFIC);
564         if (ret != 0 || p + len != end_content_info) {
565             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
566                                      ret);
567         }
568 
569         /*
570          * U-Boot Secure Boot needs to calculate the digest of MicroSoft
571          * Authentication Code during verifying an EFI image.
572          * Thus we need to save the context of Content Data.
573          */
574         pkcs7->content_data.data_hdrlen = p - tmp_p;
575         /* Parse the content data from a sequence */
576         ret = mbedtls_asn1_get_tag(&p, end_content_info, &len,
577                                    MBEDTLS_ASN1_CONSTRUCTED |
578                                    MBEDTLS_ASN1_SEQUENCE);
579         if (ret != 0) {
580             /* TODO: Other Content Data formats are not supported at the moment */
581             return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
582         } else if (p + len != end_content_info) {
583             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
584                                      ret);
585         }
586 
587         pkcs7->content_data.data = p;
588         pkcs7->content_data.data_len = len;
589 
590         p += len;
591     }
592 
593     /* Look for certificates, there may or may not be any */
594     mbedtls_x509_crt_init(&signed_data->certs);
595     ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
596     if (ret < 0) {
597         return ret;
598     }
599 
600     signed_data->no_of_certs = ret;
601 
602     /*
603      * Currently CRLs are not supported. If CRL exist, the parsing will fail
604      * at next step of getting signers info and return error as invalid
605      * signer info.
606      */
607 
608     signed_data->no_of_crls = 0;
609 
610     /* Get signers info */
611     ret = pkcs7_get_signers_info_set(&p,
612                                      end,
613                                      &signed_data->signers,
614                                      &signed_data->digest_alg_identifiers);
615     if (ret < 0) {
616         return ret;
617     }
618 
619     signed_data->no_of_signers = ret;
620 
621     /* Don't permit trailing data */
622     if (p != end) {
623         return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
624     }
625 
626     return 0;
627 }
628 
mbedtls_pkcs7_parse_der(mbedtls_pkcs7 * pkcs7,const unsigned char * buf,const size_t buflen)629 int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
630                             const size_t buflen)
631 {
632     unsigned char *p;
633     unsigned char *end;
634     size_t len = 0;
635     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
636 
637     if (pkcs7 == NULL) {
638         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
639     }
640 
641     /* make an internal copy of the buffer for parsing */
642     pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
643     if (pkcs7->raw.p == NULL) {
644         ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
645         goto out;
646     }
647     memcpy(p, buf, buflen);
648     pkcs7->raw.len = buflen;
649     end = p + buflen;
650 
651     ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
652                                | MBEDTLS_ASN1_SEQUENCE);
653     if (ret != 0) {
654         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
655         goto out;
656     }
657 
658     if ((size_t) (end - p) != len) {
659         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
660                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
661         goto out;
662     }
663 
664     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
665         if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
666             goto out;
667         }
668         p = pkcs7->raw.p;
669         len = buflen;
670         goto try_data;
671     }
672 
673     if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
674         /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
675         if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
676             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
677             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
678             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
679             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
680             /* OID is valid according to the spec, but unsupported */
681             ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
682         } else {
683             /* OID is invalid according to the spec */
684             ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
685         }
686         goto out;
687     }
688 
689     p += len;
690 
691     ret = pkcs7_get_next_content_len(&p, end, &len);
692     if (ret != 0) {
693         goto out;
694     }
695 
696     /* ensure no extra/missing data */
697     if (p + len != end) {
698         ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
699         goto out;
700     }
701 
702 try_data:
703     ret = pkcs7_get_signed_data(p, len, pkcs7);
704     if (ret != 0) {
705         goto out;
706     }
707 
708     ret = MBEDTLS_PKCS7_SIGNED_DATA;
709 
710 out:
711     if (ret < 0) {
712         mbedtls_pkcs7_free(pkcs7);
713     }
714 
715     return ret;
716 }
717 
mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * data,size_t datalen,const int is_data_hash)718 static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
719                                              const mbedtls_x509_crt *cert,
720                                              const unsigned char *data,
721                                              size_t datalen,
722                                              const int is_data_hash)
723 {
724     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
725     unsigned char *hash;
726     mbedtls_pk_context pk_cxt = cert->pk;
727     const mbedtls_md_info_t *md_info;
728     mbedtls_md_type_t md_alg;
729     mbedtls_pkcs7_signer_info *signer;
730 
731     if (pkcs7->signed_data.no_of_signers == 0) {
732         return MBEDTLS_ERR_PKCS7_INVALID_CERT;
733     }
734 
735     if (mbedtls_x509_time_is_past(&cert->valid_to) ||
736         mbedtls_x509_time_is_future(&cert->valid_from)) {
737         return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
738     }
739 
740     ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
741     if (ret != 0) {
742         return ret;
743     }
744 
745     md_info = mbedtls_md_info_from_type(md_alg);
746     if (md_info == NULL) {
747         return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
748     }
749 
750     hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
751     if (hash == NULL) {
752         return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
753     }
754 
755     /* BEGIN must free hash before jumping out */
756     if (is_data_hash) {
757         if (datalen != mbedtls_md_get_size(md_info)) {
758             ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
759         } else {
760             memcpy(hash, data, datalen);
761         }
762     } else {
763         ret = mbedtls_md(md_info, data, datalen, hash);
764     }
765     if (ret != 0) {
766         mbedtls_free(hash);
767         return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
768     }
769 
770     /* assume failure */
771     ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
772 
773     /*
774      * Potential TODOs
775      * Currently we iterate over all signers and return success if any of them
776      * verify.
777      *
778      * However, we could make this better by checking against the certificate's
779      * identification and SignerIdentifier fields first. That would also allow
780      * us to distinguish between 'no signature for key' and 'signature for key
781      * failed to validate'.
782      */
783     for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
784         ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
785                                 mbedtls_md_get_size(md_info),
786                                 signer->sig.p, signer->sig.len);
787 
788         if (ret == 0) {
789             break;
790         }
791     }
792 
793     mbedtls_free(hash);
794     /* END must free hash before jumping out */
795     return ret;
796 }
797 
mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * data,size_t datalen)798 int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
799                                      const mbedtls_x509_crt *cert,
800                                      const unsigned char *data,
801                                      size_t datalen)
802 {
803     if (data == NULL) {
804         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
805     }
806     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
807 }
808 
mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * hash,size_t hashlen)809 int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
810                                      const mbedtls_x509_crt *cert,
811                                      const unsigned char *hash,
812                                      size_t hashlen)
813 {
814     if (hash == NULL) {
815         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
816     }
817     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
818 }
819 
820 /*
821  * Unallocate all pkcs7 data
822  */
mbedtls_pkcs7_free(mbedtls_pkcs7 * pkcs7)823 void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
824 {
825     mbedtls_pkcs7_signer_info *signer_cur;
826     mbedtls_pkcs7_signer_info *signer_prev;
827 
828     if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
829         return;
830     }
831 
832     mbedtls_free(pkcs7->raw.p);
833 
834     mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
835     mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
836 
837     signer_cur = pkcs7->signed_data.signers.next;
838     pkcs7_free_signer_info(&pkcs7->signed_data.signers);
839     while (signer_cur != NULL) {
840         signer_prev = signer_cur;
841         signer_cur = signer_prev->next;
842         pkcs7_free_signer_info(signer_prev);
843         mbedtls_free(signer_prev);
844     }
845 
846     pkcs7->raw.p = NULL;
847 }
848 
849 #endif
850