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