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