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