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 */ 35void mbedtls_pkcs7_init(mbedtls_pkcs7 *pkcs7) 36{ 37 memset(pkcs7, 0, sizeof(*pkcs7)); 38} 39 40static 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 **/ 61static 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 **/ 84static 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 **/ 118static 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 **/ 133static 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 **/ 170static 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 **/ 223static 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 243static 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 **/ 277static 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 361out: 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 **/ 377static 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 426cleanup: 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 */ 451static 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 553int 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 626try_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 634out: 635 if (ret < 0) { 636 mbedtls_pkcs7_free(pkcs7); 637 } 638 639 return ret; 640} 641 642static 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 722int 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 733int 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 */ 747void 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 774