quickjs-tart

quickjs-based runtime for wallet-core logic
Log | Files | Refs | README | LICENSE

pkcs7.c (22729B)


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