xref: /optee_os/lib/libmbedtls/mbedtls/library/pkcs7.c (revision b0563631928755fe864b97785160fb3088e9efdc)
132b31808SJens Wiklander /*
232b31808SJens Wiklander  *  Copyright The Mbed TLS Contributors
3*b0563631STom Van Eyck  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
432b31808SJens Wiklander  */
532b31808SJens Wiklander #include "common.h"
632b31808SJens Wiklander 
732b31808SJens Wiklander #include "mbedtls/build_info.h"
832b31808SJens Wiklander #if defined(MBEDTLS_PKCS7_C)
932b31808SJens Wiklander #include "mbedtls/pkcs7.h"
10*b0563631STom Van Eyck #include "x509_internal.h"
1132b31808SJens Wiklander #include "mbedtls/asn1.h"
1232b31808SJens Wiklander #include "mbedtls/x509_crt.h"
1332b31808SJens Wiklander #include "mbedtls/x509_crl.h"
1432b31808SJens Wiklander #include "mbedtls/oid.h"
1532b31808SJens Wiklander #include "mbedtls/error.h"
1632b31808SJens Wiklander 
1732b31808SJens Wiklander #if defined(MBEDTLS_FS_IO)
1832b31808SJens Wiklander #include <sys/types.h>
1932b31808SJens Wiklander #include <sys/stat.h>
2032b31808SJens Wiklander #endif
2132b31808SJens Wiklander 
2232b31808SJens Wiklander #include "mbedtls/platform.h"
2332b31808SJens Wiklander #include "mbedtls/platform_util.h"
2432b31808SJens Wiklander 
2532b31808SJens Wiklander #if defined(MBEDTLS_HAVE_TIME)
2632b31808SJens Wiklander #include "mbedtls/platform_time.h"
2732b31808SJens Wiklander #endif
2832b31808SJens Wiklander #if defined(MBEDTLS_HAVE_TIME_DATE)
2932b31808SJens Wiklander #include <time.h>
3032b31808SJens Wiklander #endif
3132b31808SJens Wiklander 
3232b31808SJens Wiklander /**
3332b31808SJens Wiklander  * Initializes the mbedtls_pkcs7 structure.
3432b31808SJens Wiklander  */
mbedtls_pkcs7_init(mbedtls_pkcs7 * pkcs7)3532b31808SJens Wiklander void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7)
3632b31808SJens Wiklander {
3732b31808SJens Wiklander     memset(pkcs7, 0, sizeof(*pkcs7));
3832b31808SJens Wiklander }
3932b31808SJens Wiklander 
pkcs7_get_next_content_len(unsigned char ** p,unsigned char * end,size_t * len)4032b31808SJens Wiklander static int pkcs7_get_next_content_len(unsigned char **p, unsigned char *end,
4132b31808SJens Wiklander                                       size_t *len)
4232b31808SJens Wiklander {
4332b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
4432b31808SJens Wiklander 
4532b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, len, MBEDTLS_ASN1_CONSTRUCTED
4632b31808SJens Wiklander                                | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
4732b31808SJens Wiklander     if (ret != 0) {
4832b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
4932b31808SJens Wiklander     } else if ((size_t) (end - *p) != *len) {
5032b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO,
5132b31808SJens Wiklander                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
5232b31808SJens Wiklander     }
5332b31808SJens Wiklander 
5432b31808SJens Wiklander     return ret;
5532b31808SJens Wiklander }
5632b31808SJens Wiklander 
5732b31808SJens Wiklander /**
5832b31808SJens Wiklander  * version Version
5932b31808SJens Wiklander  * Version ::= INTEGER
6032b31808SJens Wiklander  **/
pkcs7_get_version(unsigned char ** p,unsigned char * end,int * ver)6132b31808SJens Wiklander static int pkcs7_get_version(unsigned char **p, unsigned char *end, int *ver)
6232b31808SJens Wiklander {
6332b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
6432b31808SJens Wiklander 
6532b31808SJens Wiklander     ret = mbedtls_asn1_get_int(p, end, ver);
6632b31808SJens Wiklander     if (ret != 0) {
6732b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_VERSION, ret);
6832b31808SJens Wiklander     }
6932b31808SJens Wiklander 
7032b31808SJens Wiklander     /* If version != 1, return invalid version */
7132b31808SJens Wiklander     if (*ver != MBEDTLS_PKCS7_SUPPORTED_VERSION) {
7232b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_INVALID_VERSION;
7332b31808SJens Wiklander     }
7432b31808SJens Wiklander 
7532b31808SJens Wiklander     return ret;
7632b31808SJens Wiklander }
7732b31808SJens Wiklander 
7832b31808SJens Wiklander /**
7932b31808SJens Wiklander  * ContentInfo ::= SEQUENCE {
8032b31808SJens Wiklander  *      contentType ContentType,
8132b31808SJens Wiklander  *      content
8232b31808SJens Wiklander  *              [0] EXPLICIT ANY DEFINED BY contentType OPTIONAL }
8332b31808SJens Wiklander  **/
pkcs7_get_content_info_type(unsigned char ** p,unsigned char * end,unsigned char ** seq_end,mbedtls_pkcs7_buf * pkcs7)8432b31808SJens Wiklander static int pkcs7_get_content_info_type(unsigned char **p, unsigned char *end,
8532b31808SJens Wiklander                                        unsigned char **seq_end,
8632b31808SJens Wiklander                                        mbedtls_pkcs7_buf *pkcs7)
8732b31808SJens Wiklander {
8832b31808SJens Wiklander     size_t len = 0;
8932b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
9032b31808SJens Wiklander     unsigned char *start = *p;
9132b31808SJens Wiklander 
9232b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
9332b31808SJens Wiklander                                | MBEDTLS_ASN1_SEQUENCE);
9432b31808SJens Wiklander     if (ret != 0) {
9532b31808SJens Wiklander         *p = start;
9632b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
9732b31808SJens Wiklander     }
9832b31808SJens Wiklander     *seq_end = *p + len;
9932b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, *seq_end, &len, MBEDTLS_ASN1_OID);
10032b31808SJens Wiklander     if (ret != 0) {
10132b31808SJens Wiklander         *p = start;
10232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
10332b31808SJens Wiklander     }
10432b31808SJens Wiklander 
10532b31808SJens Wiklander     pkcs7->tag = MBEDTLS_ASN1_OID;
10632b31808SJens Wiklander     pkcs7->len = len;
10732b31808SJens Wiklander     pkcs7->p = *p;
10832b31808SJens Wiklander     *p += len;
10932b31808SJens Wiklander 
11032b31808SJens Wiklander     return ret;
11132b31808SJens Wiklander }
11232b31808SJens Wiklander 
11332b31808SJens Wiklander /**
11432b31808SJens Wiklander  * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
11532b31808SJens Wiklander  *
11632b31808SJens Wiklander  * This is from x509.h
11732b31808SJens Wiklander  **/
pkcs7_get_digest_algorithm(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)11832b31808SJens Wiklander static int pkcs7_get_digest_algorithm(unsigned char **p, unsigned char *end,
11932b31808SJens Wiklander                                       mbedtls_x509_buf *alg)
12032b31808SJens Wiklander {
12132b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
12232b31808SJens Wiklander 
12332b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_alg_null(p, end, alg)) != 0) {
12432b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
12532b31808SJens Wiklander     }
12632b31808SJens Wiklander 
12732b31808SJens Wiklander     return ret;
12832b31808SJens Wiklander }
12932b31808SJens Wiklander 
13032b31808SJens Wiklander /**
13132b31808SJens Wiklander  * DigestAlgorithmIdentifiers :: SET of DigestAlgorithmIdentifier
13232b31808SJens Wiklander  **/
pkcs7_get_digest_algorithm_set(unsigned char ** p,unsigned char * end,mbedtls_x509_buf * alg)13332b31808SJens Wiklander static int pkcs7_get_digest_algorithm_set(unsigned char **p,
13432b31808SJens Wiklander                                           unsigned char *end,
13532b31808SJens Wiklander                                           mbedtls_x509_buf *alg)
13632b31808SJens Wiklander {
13732b31808SJens Wiklander     size_t len = 0;
13832b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
13932b31808SJens Wiklander 
14032b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
14132b31808SJens Wiklander                                | MBEDTLS_ASN1_SET);
14232b31808SJens Wiklander     if (ret != 0) {
14332b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
14432b31808SJens Wiklander     }
14532b31808SJens Wiklander 
14632b31808SJens Wiklander     end = *p + len;
14732b31808SJens Wiklander 
14832b31808SJens Wiklander     ret = mbedtls_asn1_get_alg_null(p, end, alg);
14932b31808SJens Wiklander     if (ret != 0) {
15032b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_ALG, ret);
15132b31808SJens Wiklander     }
15232b31808SJens Wiklander 
15332b31808SJens Wiklander     /** For now, it assumes there is only one digest algorithm specified **/
15432b31808SJens Wiklander     if (*p != end) {
15532b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
15632b31808SJens Wiklander     }
15732b31808SJens Wiklander 
15832b31808SJens Wiklander     return 0;
15932b31808SJens Wiklander }
16032b31808SJens Wiklander 
16132b31808SJens Wiklander /**
16232b31808SJens Wiklander  * certificates :: SET OF ExtendedCertificateOrCertificate,
16332b31808SJens Wiklander  * ExtendedCertificateOrCertificate ::= CHOICE {
16432b31808SJens Wiklander  *      certificate Certificate -- x509,
16532b31808SJens Wiklander  *      extendedCertificate[0] IMPLICIT ExtendedCertificate }
16632b31808SJens Wiklander  * Return number of certificates added to the signed data,
16732b31808SJens Wiklander  * 0 or higher is valid.
16832b31808SJens Wiklander  * Return negative error code for failure.
16932b31808SJens Wiklander  **/
pkcs7_get_certificates(unsigned char ** p,unsigned char * end,mbedtls_x509_crt * certs)17032b31808SJens Wiklander static int pkcs7_get_certificates(unsigned char **p, unsigned char *end,
17132b31808SJens Wiklander                                   mbedtls_x509_crt *certs)
17232b31808SJens Wiklander {
17332b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
17432b31808SJens Wiklander     size_t len1 = 0;
17532b31808SJens Wiklander     size_t len2 = 0;
17632b31808SJens Wiklander     unsigned char *end_set, *end_cert, *start;
17732b31808SJens Wiklander 
17832b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, &len1, MBEDTLS_ASN1_CONSTRUCTED
17932b31808SJens Wiklander                                | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
18032b31808SJens Wiklander     if (ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
18132b31808SJens Wiklander         return 0;
18232b31808SJens Wiklander     }
18332b31808SJens Wiklander     if (ret != 0) {
18432b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
18532b31808SJens Wiklander     }
18632b31808SJens Wiklander     start = *p;
18732b31808SJens Wiklander     end_set = *p + len1;
18832b31808SJens Wiklander 
18932b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end_set, &len2, MBEDTLS_ASN1_CONSTRUCTED
19032b31808SJens Wiklander                                | MBEDTLS_ASN1_SEQUENCE);
19132b31808SJens Wiklander     if (ret != 0) {
19232b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CERT, ret);
19332b31808SJens Wiklander     }
19432b31808SJens Wiklander 
19532b31808SJens Wiklander     end_cert = *p + len2;
19632b31808SJens Wiklander 
19732b31808SJens Wiklander     /*
19832b31808SJens Wiklander      * This is to verify that there is only one signer certificate. It seems it is
19932b31808SJens Wiklander      * not easy to differentiate between the chain vs different signer's certificate.
20032b31808SJens Wiklander      * So, we support only the root certificate and the single signer.
20132b31808SJens Wiklander      * The behaviour would be improved with addition of multiple signer support.
20232b31808SJens Wiklander      */
20332b31808SJens Wiklander     if (end_cert != end_set) {
20432b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
20532b31808SJens Wiklander     }
20632b31808SJens Wiklander 
20732b31808SJens Wiklander     if ((ret = mbedtls_x509_crt_parse_der(certs, start, len1)) < 0) {
20832b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_INVALID_CERT;
20932b31808SJens Wiklander     }
21032b31808SJens Wiklander 
21132b31808SJens Wiklander     *p = end_cert;
21232b31808SJens Wiklander 
21332b31808SJens Wiklander     /*
21432b31808SJens Wiklander      * Since in this version we strictly support single certificate, and reaching
21532b31808SJens Wiklander      * here implies we have parsed successfully, we return 1.
21632b31808SJens Wiklander      */
21732b31808SJens Wiklander     return 1;
21832b31808SJens Wiklander }
21932b31808SJens Wiklander 
22032b31808SJens Wiklander /**
22132b31808SJens Wiklander  * EncryptedDigest ::= OCTET STRING
22232b31808SJens Wiklander  **/
pkcs7_get_signature(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_buf * signature)22332b31808SJens Wiklander static int pkcs7_get_signature(unsigned char **p, unsigned char *end,
22432b31808SJens Wiklander                                mbedtls_pkcs7_buf *signature)
22532b31808SJens Wiklander {
22632b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
22732b31808SJens Wiklander     size_t len = 0;
22832b31808SJens Wiklander 
22932b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_OCTET_STRING);
23032b31808SJens Wiklander     if (ret != 0) {
23132b31808SJens Wiklander         return ret;
23232b31808SJens Wiklander     }
23332b31808SJens Wiklander 
23432b31808SJens Wiklander     signature->tag = MBEDTLS_ASN1_OCTET_STRING;
23532b31808SJens Wiklander     signature->len = len;
23632b31808SJens Wiklander     signature->p = *p;
23732b31808SJens Wiklander 
23832b31808SJens Wiklander     *p = *p + len;
23932b31808SJens Wiklander 
24032b31808SJens Wiklander     return 0;
24132b31808SJens Wiklander }
24232b31808SJens Wiklander 
pkcs7_free_signer_info(mbedtls_pkcs7_signer_info * signer)24332b31808SJens Wiklander static void pkcs7_free_signer_info(mbedtls_pkcs7_signer_info *signer)
24432b31808SJens Wiklander {
24532b31808SJens Wiklander     mbedtls_x509_name *name_cur;
24632b31808SJens Wiklander     mbedtls_x509_name *name_prv;
24732b31808SJens Wiklander 
24832b31808SJens Wiklander     if (signer == NULL) {
24932b31808SJens Wiklander         return;
25032b31808SJens Wiklander     }
25132b31808SJens Wiklander 
25232b31808SJens Wiklander     name_cur = signer->issuer.next;
25332b31808SJens Wiklander     while (name_cur != NULL) {
25432b31808SJens Wiklander         name_prv = name_cur;
25532b31808SJens Wiklander         name_cur = name_cur->next;
25632b31808SJens Wiklander         mbedtls_free(name_prv);
25732b31808SJens Wiklander     }
25832b31808SJens Wiklander     signer->issuer.next = NULL;
25932b31808SJens Wiklander }
26032b31808SJens Wiklander 
26132b31808SJens Wiklander /**
26232b31808SJens Wiklander  * SignerInfo ::= SEQUENCE {
26332b31808SJens Wiklander  *      version Version;
26432b31808SJens Wiklander  *      issuerAndSerialNumber   IssuerAndSerialNumber,
26532b31808SJens Wiklander  *      digestAlgorithm DigestAlgorithmIdentifier,
26632b31808SJens Wiklander  *      authenticatedAttributes
26732b31808SJens Wiklander  *              [0] IMPLICIT Attributes OPTIONAL,
26832b31808SJens Wiklander  *      digestEncryptionAlgorithm DigestEncryptionAlgorithmIdentifier,
26932b31808SJens Wiklander  *      encryptedDigest EncryptedDigest,
27032b31808SJens Wiklander  *      unauthenticatedAttributes
27132b31808SJens Wiklander  *              [1] IMPLICIT Attributes OPTIONAL,
27232b31808SJens Wiklander  * Returns 0 if the signerInfo is valid.
27332b31808SJens Wiklander  * Return negative error code for failure.
27432b31808SJens Wiklander  * Structure must not contain vales for authenticatedAttributes
27532b31808SJens Wiklander  * and unauthenticatedAttributes.
27632b31808SJens Wiklander  **/
pkcs7_get_signer_info(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signer,mbedtls_x509_buf * alg)27732b31808SJens Wiklander static int pkcs7_get_signer_info(unsigned char **p, unsigned char *end,
27832b31808SJens Wiklander                                  mbedtls_pkcs7_signer_info *signer,
27932b31808SJens Wiklander                                  mbedtls_x509_buf *alg)
28032b31808SJens Wiklander {
28132b31808SJens Wiklander     unsigned char *end_signer, *end_issuer_and_sn;
28232b31808SJens Wiklander     int asn1_ret = 0, ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
28332b31808SJens Wiklander     size_t len = 0;
28432b31808SJens Wiklander 
28532b31808SJens Wiklander     asn1_ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
28632b31808SJens Wiklander                                     | MBEDTLS_ASN1_SEQUENCE);
28732b31808SJens Wiklander     if (asn1_ret != 0) {
28832b31808SJens Wiklander         goto out;
28932b31808SJens Wiklander     }
29032b31808SJens Wiklander 
29132b31808SJens Wiklander     end_signer = *p + len;
29232b31808SJens Wiklander 
29332b31808SJens Wiklander     ret = pkcs7_get_version(p, end_signer, &signer->version);
29432b31808SJens Wiklander     if (ret != 0) {
29532b31808SJens Wiklander         goto out;
29632b31808SJens Wiklander     }
29732b31808SJens Wiklander 
29832b31808SJens Wiklander     asn1_ret = mbedtls_asn1_get_tag(p, end_signer, &len,
29932b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
30032b31808SJens Wiklander     if (asn1_ret != 0) {
30132b31808SJens Wiklander         goto out;
30232b31808SJens Wiklander     }
30332b31808SJens Wiklander 
30432b31808SJens Wiklander     end_issuer_and_sn = *p + len;
30532b31808SJens Wiklander     /* Parsing IssuerAndSerialNumber */
30632b31808SJens Wiklander     signer->issuer_raw.p = *p;
30732b31808SJens Wiklander 
30832b31808SJens Wiklander     asn1_ret = mbedtls_asn1_get_tag(p, end_issuer_and_sn, &len,
30932b31808SJens Wiklander                                     MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE);
31032b31808SJens Wiklander     if (asn1_ret != 0) {
31132b31808SJens Wiklander         goto out;
31232b31808SJens Wiklander     }
31332b31808SJens Wiklander 
31432b31808SJens Wiklander     ret  = mbedtls_x509_get_name(p, *p + len, &signer->issuer);
31532b31808SJens Wiklander     if (ret != 0) {
31632b31808SJens Wiklander         goto out;
31732b31808SJens Wiklander     }
31832b31808SJens Wiklander 
319*b0563631STom Van Eyck     signer->issuer_raw.len =  (size_t) (*p - signer->issuer_raw.p);
32032b31808SJens Wiklander 
32132b31808SJens Wiklander     ret = mbedtls_x509_get_serial(p, end_issuer_and_sn, &signer->serial);
32232b31808SJens Wiklander     if (ret != 0) {
32332b31808SJens Wiklander         goto out;
32432b31808SJens Wiklander     }
32532b31808SJens Wiklander 
32632b31808SJens Wiklander     /* ensure no extra or missing bytes */
32732b31808SJens Wiklander     if (*p != end_issuer_and_sn) {
32832b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
32932b31808SJens Wiklander         goto out;
33032b31808SJens Wiklander     }
33132b31808SJens Wiklander 
33232b31808SJens Wiklander     ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->alg_identifier);
33332b31808SJens Wiklander     if (ret != 0) {
33432b31808SJens Wiklander         goto out;
33532b31808SJens Wiklander     }
33632b31808SJens Wiklander 
33732b31808SJens Wiklander     /* Check that the digest algorithm used matches the one provided earlier */
33832b31808SJens Wiklander     if (signer->alg_identifier.tag != alg->tag ||
33932b31808SJens Wiklander         signer->alg_identifier.len != alg->len ||
34032b31808SJens Wiklander         memcmp(signer->alg_identifier.p, alg->p, alg->len) != 0) {
34132b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
34232b31808SJens Wiklander         goto out;
34332b31808SJens Wiklander     }
34432b31808SJens Wiklander 
34532b31808SJens Wiklander     /* Assume authenticatedAttributes is nonexistent */
34632b31808SJens Wiklander     ret = pkcs7_get_digest_algorithm(p, end_signer, &signer->sig_alg_identifier);
34732b31808SJens Wiklander     if (ret != 0) {
34832b31808SJens Wiklander         goto out;
34932b31808SJens Wiklander     }
35032b31808SJens Wiklander 
35132b31808SJens Wiklander     ret = pkcs7_get_signature(p, end_signer, &signer->sig);
35232b31808SJens Wiklander     if (ret != 0) {
35332b31808SJens Wiklander         goto out;
35432b31808SJens Wiklander     }
35532b31808SJens Wiklander 
35632b31808SJens Wiklander     /* Do not permit any unauthenticated attributes */
35732b31808SJens Wiklander     if (*p != end_signer) {
35832b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO;
35932b31808SJens Wiklander     }
36032b31808SJens Wiklander 
36132b31808SJens Wiklander out:
36232b31808SJens Wiklander     if (asn1_ret != 0 || ret != 0) {
36332b31808SJens Wiklander         pkcs7_free_signer_info(signer);
36432b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO,
36532b31808SJens Wiklander                                 asn1_ret);
36632b31808SJens Wiklander     }
36732b31808SJens Wiklander 
36832b31808SJens Wiklander     return ret;
36932b31808SJens Wiklander }
37032b31808SJens Wiklander 
37132b31808SJens Wiklander /**
37232b31808SJens Wiklander  * SignerInfos ::= SET of SignerInfo
37332b31808SJens Wiklander  * Return number of signers added to the signed data,
37432b31808SJens Wiklander  * 0 or higher is valid.
37532b31808SJens Wiklander  * Return negative error code for failure.
37632b31808SJens Wiklander  **/
pkcs7_get_signers_info_set(unsigned char ** p,unsigned char * end,mbedtls_pkcs7_signer_info * signers_set,mbedtls_x509_buf * digest_alg)37732b31808SJens Wiklander static int pkcs7_get_signers_info_set(unsigned char **p, unsigned char *end,
37832b31808SJens Wiklander                                       mbedtls_pkcs7_signer_info *signers_set,
37932b31808SJens Wiklander                                       mbedtls_x509_buf *digest_alg)
38032b31808SJens Wiklander {
38132b31808SJens Wiklander     unsigned char *end_set;
38232b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
38332b31808SJens Wiklander     int count = 0;
38432b31808SJens Wiklander     size_t len = 0;
38532b31808SJens Wiklander 
38632b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
38732b31808SJens Wiklander                                | MBEDTLS_ASN1_SET);
38832b31808SJens Wiklander     if (ret != 0) {
38932b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_SIGNER_INFO, ret);
39032b31808SJens Wiklander     }
39132b31808SJens Wiklander 
39232b31808SJens Wiklander     /* Detect zero signers */
39332b31808SJens Wiklander     if (len == 0) {
39432b31808SJens Wiklander         return 0;
39532b31808SJens Wiklander     }
39632b31808SJens Wiklander 
39732b31808SJens Wiklander     end_set = *p + len;
39832b31808SJens Wiklander 
39932b31808SJens Wiklander     ret = pkcs7_get_signer_info(p, end_set, signers_set, digest_alg);
40032b31808SJens Wiklander     if (ret != 0) {
40132b31808SJens Wiklander         return ret;
40232b31808SJens Wiklander     }
40332b31808SJens Wiklander     count++;
40432b31808SJens Wiklander 
40532b31808SJens Wiklander     mbedtls_pkcs7_signer_info *prev = signers_set;
40632b31808SJens Wiklander     while (*p != end_set) {
40732b31808SJens Wiklander         mbedtls_pkcs7_signer_info *signer =
40832b31808SJens Wiklander             mbedtls_calloc(1, sizeof(mbedtls_pkcs7_signer_info));
40932b31808SJens Wiklander         if (!signer) {
41032b31808SJens Wiklander             ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
41132b31808SJens Wiklander             goto cleanup;
41232b31808SJens Wiklander         }
41332b31808SJens Wiklander 
41432b31808SJens Wiklander         ret = pkcs7_get_signer_info(p, end_set, signer, digest_alg);
41532b31808SJens Wiklander         if (ret != 0) {
41632b31808SJens Wiklander             mbedtls_free(signer);
41732b31808SJens Wiklander             goto cleanup;
41832b31808SJens Wiklander         }
41932b31808SJens Wiklander         prev->next = signer;
42032b31808SJens Wiklander         prev = signer;
42132b31808SJens Wiklander         count++;
42232b31808SJens Wiklander     }
42332b31808SJens Wiklander 
42432b31808SJens Wiklander     return count;
42532b31808SJens Wiklander 
42632b31808SJens Wiklander cleanup:
42732b31808SJens Wiklander     pkcs7_free_signer_info(signers_set);
42832b31808SJens Wiklander     mbedtls_pkcs7_signer_info *signer = signers_set->next;
42932b31808SJens Wiklander     while (signer != NULL) {
43032b31808SJens Wiklander         prev = signer;
43132b31808SJens Wiklander         signer = signer->next;
43232b31808SJens Wiklander         pkcs7_free_signer_info(prev);
43332b31808SJens Wiklander         mbedtls_free(prev);
43432b31808SJens Wiklander     }
43532b31808SJens Wiklander     signers_set->next = NULL;
43632b31808SJens Wiklander     return ret;
43732b31808SJens Wiklander }
43832b31808SJens Wiklander 
43932b31808SJens Wiklander /**
44032b31808SJens Wiklander  * SignedData ::= SEQUENCE {
44132b31808SJens Wiklander  *      version Version,
44232b31808SJens Wiklander  *      digestAlgorithms DigestAlgorithmIdentifiers,
44332b31808SJens Wiklander  *      contentInfo ContentInfo,
44432b31808SJens Wiklander  *      certificates
44532b31808SJens Wiklander  *              [0] IMPLICIT ExtendedCertificatesAndCertificates
44632b31808SJens Wiklander  *                  OPTIONAL,
44732b31808SJens Wiklander  *      crls
44832b31808SJens Wiklander  *              [0] IMPLICIT CertificateRevocationLists OPTIONAL,
44932b31808SJens Wiklander  *      signerInfos SignerInfos }
45032b31808SJens Wiklander  */
pkcs7_get_signed_data(unsigned char * buf,size_t buflen,mbedtls_pkcs7_signed_data * signed_data)45132b31808SJens Wiklander static int pkcs7_get_signed_data(unsigned char *buf, size_t buflen,
45232b31808SJens Wiklander                                  mbedtls_pkcs7_signed_data *signed_data)
45332b31808SJens Wiklander {
45432b31808SJens Wiklander     unsigned char *p = buf;
45532b31808SJens Wiklander     unsigned char *end = buf + buflen;
45632b31808SJens Wiklander     unsigned char *end_content_info = NULL;
45732b31808SJens Wiklander     size_t len = 0;
45832b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
45932b31808SJens Wiklander     mbedtls_md_type_t md_alg;
46032b31808SJens Wiklander 
46132b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
46232b31808SJens Wiklander                                | MBEDTLS_ASN1_SEQUENCE);
46332b31808SJens Wiklander     if (ret != 0) {
46432b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
46532b31808SJens Wiklander     }
46632b31808SJens Wiklander 
46732b31808SJens Wiklander     if (p + len != end) {
46832b31808SJens Wiklander         return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
46932b31808SJens Wiklander                                  MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
47032b31808SJens Wiklander     }
47132b31808SJens Wiklander 
47232b31808SJens Wiklander     /* Get version of signed data */
47332b31808SJens Wiklander     ret = pkcs7_get_version(&p, end, &signed_data->version);
47432b31808SJens Wiklander     if (ret != 0) {
47532b31808SJens Wiklander         return ret;
47632b31808SJens Wiklander     }
47732b31808SJens Wiklander 
47832b31808SJens Wiklander     /* Get digest algorithm */
47932b31808SJens Wiklander     ret = pkcs7_get_digest_algorithm_set(&p, end,
48032b31808SJens Wiklander                                          &signed_data->digest_alg_identifiers);
48132b31808SJens Wiklander     if (ret != 0) {
48232b31808SJens Wiklander         return ret;
48332b31808SJens Wiklander     }
48432b31808SJens Wiklander 
48532b31808SJens Wiklander     ret = mbedtls_oid_get_md_alg(&signed_data->digest_alg_identifiers, &md_alg);
48632b31808SJens Wiklander     if (ret != 0) {
48732b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_INVALID_ALG;
48832b31808SJens Wiklander     }
48932b31808SJens Wiklander 
49032b31808SJens Wiklander     mbedtls_pkcs7_buf content_type;
49132b31808SJens Wiklander     memset(&content_type, 0, sizeof(content_type));
49232b31808SJens Wiklander     ret = pkcs7_get_content_info_type(&p, end, &end_content_info, &content_type);
49332b31808SJens Wiklander     if (ret != 0) {
49432b31808SJens Wiklander         return ret;
49532b31808SJens Wiklander     }
49632b31808SJens Wiklander     if (MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS7_DATA, &content_type)) {
49732b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO;
49832b31808SJens Wiklander     }
49932b31808SJens Wiklander 
50032b31808SJens Wiklander     if (p != end_content_info) {
50132b31808SJens Wiklander         /* Determine if valid content is present */
50232b31808SJens Wiklander         ret = mbedtls_asn1_get_tag(&p,
50332b31808SJens Wiklander                                    end_content_info,
50432b31808SJens Wiklander                                    &len,
50532b31808SJens Wiklander                                    MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_CONTEXT_SPECIFIC);
50632b31808SJens Wiklander         if (ret != 0) {
50732b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
50832b31808SJens Wiklander         }
50932b31808SJens Wiklander         p += len;
51032b31808SJens Wiklander         if (p != end_content_info) {
51132b31808SJens Wiklander             return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_CONTENT_INFO, ret);
51232b31808SJens Wiklander         }
51332b31808SJens Wiklander         /* Valid content is present - this is not supported */
51432b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
51532b31808SJens Wiklander     }
51632b31808SJens Wiklander 
51732b31808SJens Wiklander     /* Look for certificates, there may or may not be any */
51832b31808SJens Wiklander     mbedtls_x509_crt_init(&signed_data->certs);
51932b31808SJens Wiklander     ret = pkcs7_get_certificates(&p, end, &signed_data->certs);
52032b31808SJens Wiklander     if (ret < 0) {
52132b31808SJens Wiklander         return ret;
52232b31808SJens Wiklander     }
52332b31808SJens Wiklander 
52432b31808SJens Wiklander     signed_data->no_of_certs = ret;
52532b31808SJens Wiklander 
52632b31808SJens Wiklander     /*
52732b31808SJens Wiklander      * Currently CRLs are not supported. If CRL exist, the parsing will fail
52832b31808SJens Wiklander      * at next step of getting signers info and return error as invalid
52932b31808SJens Wiklander      * signer info.
53032b31808SJens Wiklander      */
53132b31808SJens Wiklander 
53232b31808SJens Wiklander     signed_data->no_of_crls = 0;
53332b31808SJens Wiklander 
53432b31808SJens Wiklander     /* Get signers info */
53532b31808SJens Wiklander     ret = pkcs7_get_signers_info_set(&p,
53632b31808SJens Wiklander                                      end,
53732b31808SJens Wiklander                                      &signed_data->signers,
53832b31808SJens Wiklander                                      &signed_data->digest_alg_identifiers);
53932b31808SJens Wiklander     if (ret < 0) {
54032b31808SJens Wiklander         return ret;
54132b31808SJens Wiklander     }
54232b31808SJens Wiklander 
54332b31808SJens Wiklander     signed_data->no_of_signers = ret;
54432b31808SJens Wiklander 
54532b31808SJens Wiklander     /* Don't permit trailing data */
54632b31808SJens Wiklander     if (p != end) {
54732b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_INVALID_FORMAT;
54832b31808SJens Wiklander     }
54932b31808SJens Wiklander 
55032b31808SJens Wiklander     return 0;
55132b31808SJens Wiklander }
55232b31808SJens Wiklander 
mbedtls_pkcs7_parse_der(mbedtls_pkcs7 * pkcs7,const unsigned char * buf,const size_t buflen)55332b31808SJens Wiklander int mbedtls_pkcs7_parse_der(mbedtls_pkcs7 *pkcs7, const unsigned char *buf,
55432b31808SJens Wiklander                             const size_t buflen)
55532b31808SJens Wiklander {
55632b31808SJens Wiklander     unsigned char *p;
55732b31808SJens Wiklander     unsigned char *end;
55832b31808SJens Wiklander     size_t len = 0;
55932b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
56032b31808SJens Wiklander 
56132b31808SJens Wiklander     if (pkcs7 == NULL) {
56232b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
56332b31808SJens Wiklander     }
56432b31808SJens Wiklander 
56532b31808SJens Wiklander     /* make an internal copy of the buffer for parsing */
56632b31808SJens Wiklander     pkcs7->raw.p = p = mbedtls_calloc(1, buflen);
56732b31808SJens Wiklander     if (pkcs7->raw.p == NULL) {
56832b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
56932b31808SJens Wiklander         goto out;
57032b31808SJens Wiklander     }
57132b31808SJens Wiklander     memcpy(p, buf, buflen);
57232b31808SJens Wiklander     pkcs7->raw.len = buflen;
57332b31808SJens Wiklander     end = p + buflen;
57432b31808SJens Wiklander 
57532b31808SJens Wiklander     ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED
57632b31808SJens Wiklander                                | MBEDTLS_ASN1_SEQUENCE);
57732b31808SJens Wiklander     if (ret != 0) {
57832b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT, ret);
57932b31808SJens Wiklander         goto out;
58032b31808SJens Wiklander     }
58132b31808SJens Wiklander 
58232b31808SJens Wiklander     if ((size_t) (end - p) != len) {
58332b31808SJens Wiklander         ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS7_INVALID_FORMAT,
58432b31808SJens Wiklander                                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
58532b31808SJens Wiklander         goto out;
58632b31808SJens Wiklander     }
58732b31808SJens Wiklander 
58832b31808SJens Wiklander     if ((ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID)) != 0) {
58932b31808SJens Wiklander         if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
59032b31808SJens Wiklander             goto out;
59132b31808SJens Wiklander         }
59232b31808SJens Wiklander         p = pkcs7->raw.p;
59332b31808SJens Wiklander         len = buflen;
59432b31808SJens Wiklander         goto try_data;
59532b31808SJens Wiklander     }
59632b31808SJens Wiklander 
59732b31808SJens Wiklander     if (MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_DATA, p, len)) {
59832b31808SJens Wiklander         /* OID is not MBEDTLS_OID_PKCS7_SIGNED_DATA, which is the only supported feature */
59932b31808SJens Wiklander         if (!MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DATA, p, len)
60032b31808SJens Wiklander             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENCRYPTED_DATA, p, len)
60132b31808SJens Wiklander             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_ENVELOPED_DATA, p, len)
60232b31808SJens Wiklander             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_SIGNED_AND_ENVELOPED_DATA, p, len)
60332b31808SJens Wiklander             || !MBEDTLS_OID_CMP_RAW(MBEDTLS_OID_PKCS7_DIGESTED_DATA, p, len)) {
60432b31808SJens Wiklander             /* OID is valid according to the spec, but unsupported */
60532b31808SJens Wiklander             ret =  MBEDTLS_ERR_PKCS7_FEATURE_UNAVAILABLE;
60632b31808SJens Wiklander         } else {
60732b31808SJens Wiklander             /* OID is invalid according to the spec */
60832b31808SJens Wiklander             ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
60932b31808SJens Wiklander         }
61032b31808SJens Wiklander         goto out;
61132b31808SJens Wiklander     }
61232b31808SJens Wiklander 
61332b31808SJens Wiklander     p += len;
61432b31808SJens Wiklander 
61532b31808SJens Wiklander     ret = pkcs7_get_next_content_len(&p, end, &len);
61632b31808SJens Wiklander     if (ret != 0) {
61732b31808SJens Wiklander         goto out;
61832b31808SJens Wiklander     }
61932b31808SJens Wiklander 
62032b31808SJens Wiklander     /* ensure no extra/missing data */
62132b31808SJens Wiklander     if (p + len != end) {
62232b31808SJens Wiklander         ret = MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
62332b31808SJens Wiklander         goto out;
62432b31808SJens Wiklander     }
62532b31808SJens Wiklander 
62632b31808SJens Wiklander try_data:
62732b31808SJens Wiklander     ret = pkcs7_get_signed_data(p, len, &pkcs7->signed_data);
62832b31808SJens Wiklander     if (ret != 0) {
62932b31808SJens Wiklander         goto out;
63032b31808SJens Wiklander     }
63132b31808SJens Wiklander 
63232b31808SJens Wiklander     ret = MBEDTLS_PKCS7_SIGNED_DATA;
63332b31808SJens Wiklander 
63432b31808SJens Wiklander out:
63532b31808SJens Wiklander     if (ret < 0) {
63632b31808SJens Wiklander         mbedtls_pkcs7_free(pkcs7);
63732b31808SJens Wiklander     }
63832b31808SJens Wiklander 
63932b31808SJens Wiklander     return ret;
64032b31808SJens Wiklander }
64132b31808SJens Wiklander 
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)64232b31808SJens Wiklander static int mbedtls_pkcs7_data_or_hash_verify(mbedtls_pkcs7 *pkcs7,
64332b31808SJens Wiklander                                              const mbedtls_x509_crt *cert,
64432b31808SJens Wiklander                                              const unsigned char *data,
64532b31808SJens Wiklander                                              size_t datalen,
64632b31808SJens Wiklander                                              const int is_data_hash)
64732b31808SJens Wiklander {
64832b31808SJens Wiklander     int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
64932b31808SJens Wiklander     unsigned char *hash;
65032b31808SJens Wiklander     mbedtls_pk_context pk_cxt = cert->pk;
65132b31808SJens Wiklander     const mbedtls_md_info_t *md_info;
65232b31808SJens Wiklander     mbedtls_md_type_t md_alg;
65332b31808SJens Wiklander     mbedtls_pkcs7_signer_info *signer;
65432b31808SJens Wiklander 
65532b31808SJens Wiklander     if (pkcs7->signed_data.no_of_signers == 0) {
65632b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_INVALID_CERT;
65732b31808SJens Wiklander     }
65832b31808SJens Wiklander 
65932b31808SJens Wiklander     if (mbedtls_x509_time_is_past(&cert->valid_to) ||
66032b31808SJens Wiklander         mbedtls_x509_time_is_future(&cert->valid_from)) {
66132b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_CERT_DATE_INVALID;
66232b31808SJens Wiklander     }
66332b31808SJens Wiklander 
66432b31808SJens Wiklander     ret = mbedtls_oid_get_md_alg(&pkcs7->signed_data.digest_alg_identifiers, &md_alg);
66532b31808SJens Wiklander     if (ret != 0) {
66632b31808SJens Wiklander         return ret;
66732b31808SJens Wiklander     }
66832b31808SJens Wiklander 
66932b31808SJens Wiklander     md_info = mbedtls_md_info_from_type(md_alg);
67032b31808SJens Wiklander     if (md_info == NULL) {
67132b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
67232b31808SJens Wiklander     }
67332b31808SJens Wiklander 
67432b31808SJens Wiklander     hash = mbedtls_calloc(mbedtls_md_get_size(md_info), 1);
67532b31808SJens Wiklander     if (hash == NULL) {
67632b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_ALLOC_FAILED;
67732b31808SJens Wiklander     }
67832b31808SJens Wiklander 
67932b31808SJens Wiklander     /* BEGIN must free hash before jumping out */
68032b31808SJens Wiklander     if (is_data_hash) {
68132b31808SJens Wiklander         if (datalen != mbedtls_md_get_size(md_info)) {
68232b31808SJens Wiklander             ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
68332b31808SJens Wiklander         } else {
68432b31808SJens Wiklander             memcpy(hash, data, datalen);
68532b31808SJens Wiklander         }
68632b31808SJens Wiklander     } else {
68732b31808SJens Wiklander         ret = mbedtls_md(md_info, data, datalen, hash);
68832b31808SJens Wiklander     }
68932b31808SJens Wiklander     if (ret != 0) {
69032b31808SJens Wiklander         mbedtls_free(hash);
69132b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
69232b31808SJens Wiklander     }
69332b31808SJens Wiklander 
69432b31808SJens Wiklander     /* assume failure */
69532b31808SJens Wiklander     ret = MBEDTLS_ERR_PKCS7_VERIFY_FAIL;
69632b31808SJens Wiklander 
69732b31808SJens Wiklander     /*
69832b31808SJens Wiklander      * Potential TODOs
69932b31808SJens Wiklander      * Currently we iterate over all signers and return success if any of them
70032b31808SJens Wiklander      * verify.
70132b31808SJens Wiklander      *
70232b31808SJens Wiklander      * However, we could make this better by checking against the certificate's
70332b31808SJens Wiklander      * identification and SignerIdentifier fields first. That would also allow
70432b31808SJens Wiklander      * us to distinguish between 'no signature for key' and 'signature for key
70532b31808SJens Wiklander      * failed to validate'.
70632b31808SJens Wiklander      */
70732b31808SJens Wiklander     for (signer = &pkcs7->signed_data.signers; signer; signer = signer->next) {
70832b31808SJens Wiklander         ret = mbedtls_pk_verify(&pk_cxt, md_alg, hash,
70932b31808SJens Wiklander                                 mbedtls_md_get_size(md_info),
71032b31808SJens Wiklander                                 signer->sig.p, signer->sig.len);
71132b31808SJens Wiklander 
71232b31808SJens Wiklander         if (ret == 0) {
71332b31808SJens Wiklander             break;
71432b31808SJens Wiklander         }
71532b31808SJens Wiklander     }
71632b31808SJens Wiklander 
71732b31808SJens Wiklander     mbedtls_free(hash);
71832b31808SJens Wiklander     /* END must free hash before jumping out */
71932b31808SJens Wiklander     return ret;
72032b31808SJens Wiklander }
72132b31808SJens Wiklander 
mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * data,size_t datalen)72232b31808SJens Wiklander int mbedtls_pkcs7_signed_data_verify(mbedtls_pkcs7 *pkcs7,
72332b31808SJens Wiklander                                      const mbedtls_x509_crt *cert,
72432b31808SJens Wiklander                                      const unsigned char *data,
72532b31808SJens Wiklander                                      size_t datalen)
72632b31808SJens Wiklander {
72732b31808SJens Wiklander     if (data == NULL) {
72832b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
72932b31808SJens Wiklander     }
73032b31808SJens Wiklander     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, data, datalen, 0);
73132b31808SJens Wiklander }
73232b31808SJens Wiklander 
mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 * pkcs7,const mbedtls_x509_crt * cert,const unsigned char * hash,size_t hashlen)73332b31808SJens Wiklander int mbedtls_pkcs7_signed_hash_verify(mbedtls_pkcs7 *pkcs7,
73432b31808SJens Wiklander                                      const mbedtls_x509_crt *cert,
73532b31808SJens Wiklander                                      const unsigned char *hash,
73632b31808SJens Wiklander                                      size_t hashlen)
73732b31808SJens Wiklander {
73832b31808SJens Wiklander     if (hash == NULL) {
73932b31808SJens Wiklander         return MBEDTLS_ERR_PKCS7_BAD_INPUT_DATA;
74032b31808SJens Wiklander     }
74132b31808SJens Wiklander     return mbedtls_pkcs7_data_or_hash_verify(pkcs7, cert, hash, hashlen, 1);
74232b31808SJens Wiklander }
74332b31808SJens Wiklander 
74432b31808SJens Wiklander /*
74532b31808SJens Wiklander  * Unallocate all pkcs7 data
74632b31808SJens Wiklander  */
mbedtls_pkcs7_free(mbedtls_pkcs7 * pkcs7)74732b31808SJens Wiklander void mbedtls_pkcs7_free(mbedtls_pkcs7 *pkcs7)
74832b31808SJens Wiklander {
74932b31808SJens Wiklander     mbedtls_pkcs7_signer_info *signer_cur;
75032b31808SJens Wiklander     mbedtls_pkcs7_signer_info *signer_prev;
75132b31808SJens Wiklander 
75232b31808SJens Wiklander     if (pkcs7 == NULL || pkcs7->raw.p == NULL) {
75332b31808SJens Wiklander         return;
75432b31808SJens Wiklander     }
75532b31808SJens Wiklander 
75632b31808SJens Wiklander     mbedtls_free(pkcs7->raw.p);
75732b31808SJens Wiklander 
75832b31808SJens Wiklander     mbedtls_x509_crt_free(&pkcs7->signed_data.certs);
75932b31808SJens Wiklander     mbedtls_x509_crl_free(&pkcs7->signed_data.crl);
76032b31808SJens Wiklander 
76132b31808SJens Wiklander     signer_cur = pkcs7->signed_data.signers.next;
76232b31808SJens Wiklander     pkcs7_free_signer_info(&pkcs7->signed_data.signers);
76332b31808SJens Wiklander     while (signer_cur != NULL) {
76432b31808SJens Wiklander         signer_prev = signer_cur;
76532b31808SJens Wiklander         signer_cur = signer_prev->next;
76632b31808SJens Wiklander         pkcs7_free_signer_info(signer_prev);
76732b31808SJens Wiklander         mbedtls_free(signer_prev);
76832b31808SJens Wiklander     }
76932b31808SJens Wiklander 
77032b31808SJens Wiklander     pkcs7->raw.p = NULL;
77132b31808SJens Wiklander }
77232b31808SJens Wiklander 
77332b31808SJens Wiklander #endif
774