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