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