| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/x509_chain.h" | 5 #include "net/base/x509_chain.h" |
| 6 | 6 |
| 7 #include <cert.h> | 7 #include <cert.h> |
| 8 #include <nss.h> | 8 #include <nss.h> |
| 9 #include <prerror.h> | 9 #include <prerror.h> |
| 10 #include <secerr.h> | 10 #include <secerr.h> |
| (...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 135 case SEC_ERROR_POLICY_VALIDATION_FAILED: | 135 case SEC_ERROR_POLICY_VALIDATION_FAILED: |
| 136 return CERT_STATUS_INVALID; | 136 return CERT_STATUS_INVALID; |
| 137 default: | 137 default: |
| 138 return 0; | 138 return 0; |
| 139 } | 139 } |
| 140 } | 140 } |
| 141 | 141 |
| 142 // Saves some information about the certificate chain cert_list in | 142 // Saves some information about the certificate chain cert_list in |
| 143 // *verify_result. The caller MUST initialize *verify_result before calling | 143 // *verify_result. The caller MUST initialize *verify_result before calling |
| 144 // this function. | 144 // this function. |
| 145 // Note that cert_list[0] is the end entity certificate and cert_list doesn't | 145 // Note that cert_list[0] is the end entity certificate |
| 146 // contain the root CA certificate. | 146 void GetCertChainInfo(int flags, |
| 147 void GetCertChainInfo(CERTCertList* cert_list, | 147 CERTCertList* cert_list, |
| 148 CERTCertificate* trust_anchor, |
| 148 CertVerifyResult* verify_result) { | 149 CertVerifyResult* verify_result) { |
| 149 // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the | 150 // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the |
| 150 // NSS version currently in use: | 151 // NSS version currently in use: |
| 151 // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*) | 152 // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*) |
| 152 // 2. use ident libnss3.so* for the library's version | 153 // 2. use ident libnss3.so* for the library's version |
| 153 DCHECK(cert_list); | 154 DCHECK(cert_list); |
| 155 bool return_chain = !!(flags & x509_chain::VERIFY_RETURN_CHAIN); |
| 156 X509Certificate::OSCertHandles intermediates; |
| 154 int i = 0; | 157 int i = 0; |
| 155 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); | 158 for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); |
| 156 !CERT_LIST_END(node, cert_list); | 159 !CERT_LIST_END(node, cert_list); |
| 157 node = CERT_LIST_NEXT(node), i++) { | 160 node = CERT_LIST_NEXT(node), i++) { |
| 158 SECAlgorithmID& signature = node->cert->signature; | 161 SECAlgorithmID& signature = node->cert->signature; |
| 159 SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); | 162 SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); |
| 160 switch (oid_tag) { | 163 switch (oid_tag) { |
| 161 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: | 164 case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: |
| 162 verify_result->has_md5 = true; | 165 verify_result->has_md5 = true; |
| 163 if (i != 0) | 166 if (i != 0) |
| 164 verify_result->has_md5_ca = true; | 167 verify_result->has_md5_ca = true; |
| 165 break; | 168 break; |
| 166 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: | 169 case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: |
| 167 verify_result->has_md2 = true; | 170 verify_result->has_md2 = true; |
| 168 if (i != 0) | 171 if (i != 0) |
| 169 verify_result->has_md2_ca = true; | 172 verify_result->has_md2_ca = true; |
| 170 break; | 173 break; |
| 171 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: | 174 case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: |
| 172 verify_result->has_md4 = true; | 175 verify_result->has_md4 = true; |
| 173 break; | 176 break; |
| 174 default: | 177 default: |
| 175 break; | 178 break; |
| 176 } | 179 } |
| 180 |
| 181 if (return_chain && i != 0) |
| 182 intermediates.push_back(node->cert); |
| 183 } |
| 184 |
| 185 if (return_chain) { |
| 186 if (trust_anchor) |
| 187 intermediates.push_back(trust_anchor); |
| 188 verify_result->certificate = X509Certificate::CreateFromHandle( |
| 189 CERT_LIST_HEAD(cert_list)->cert, intermediates); |
| 177 } | 190 } |
| 178 } | 191 } |
| 179 | 192 |
| 180 // Forward declarations. | 193 // Forward declarations. |
| 181 SECStatus RetryPKIXVerifyCertWithWorkarounds( | 194 SECStatus RetryPKIXVerifyCertWithWorkarounds( |
| 182 X509Certificate::OSCertHandle cert_handle, int num_policy_oids, | 195 X509Certificate::OSCertHandle cert_handle, int num_policy_oids, |
| 183 std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout); | 196 std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout); |
| 184 SECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle); | 197 SECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle); |
| 185 | 198 |
| 186 // Call CERT_PKIXVerifyCert for the cert_handle. | 199 // Call CERT_PKIXVerifyCert for the cert_handle. |
| (...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 484 hostname.c_str()); | 497 hostname.c_str()); |
| 485 if (status != SECSuccess) | 498 if (status != SECSuccess) |
| 486 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; | 499 verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; |
| 487 | 500 |
| 488 // Make sure that the cert is valid now. | 501 // Make sure that the cert is valid now. |
| 489 SECCertTimeValidity validity = CERT_CheckCertValidTimes( | 502 SECCertTimeValidity validity = CERT_CheckCertValidTimes( |
| 490 certificate->os_cert_handle(), PR_Now(), PR_TRUE); | 503 certificate->os_cert_handle(), PR_Now(), PR_TRUE); |
| 491 if (validity != secCertTimeValid) | 504 if (validity != secCertTimeValid) |
| 492 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; | 505 verify_result->cert_status |= CERT_STATUS_DATE_INVALID; |
| 493 | 506 |
| 494 CERTValOutParam cvout[3]; | 507 CERTValOutParam cvout[4]; |
| 495 int cvout_index = 0; | 508 int cvout_index = 0; |
| 496 // We don't need the trust anchor for the first PKIXVerifyCert call. | |
| 497 cvout[cvout_index].type = cert_po_certList; | 509 cvout[cvout_index].type = cert_po_certList; |
| 498 cvout[cvout_index].value.pointer.chain = NULL; | 510 cvout[cvout_index].value.pointer.chain = NULL; |
| 499 int cvout_cert_list_index = cvout_index; | 511 int cvout_cert_list_index = cvout_index; |
| 500 cvout_index++; | 512 cvout_index++; |
| 513 cvout[cvout_index].type = cert_po_trustAnchor; |
| 514 cvout[cvout_index].value.pointer.cert = NULL; |
| 515 int cvout_trust_anchor_index = cvout_index; |
| 516 cvout_index++; |
| 501 cvout[cvout_index].type = cert_po_end; | 517 cvout[cvout_index].type = cert_po_end; |
| 502 ScopedCERTValOutParam scoped_cvout(cvout); | 518 ScopedCERTValOutParam scoped_cvout(cvout); |
| 503 | 519 |
| 504 bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED); | 520 bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED); |
| 505 if (check_revocation) { | 521 if (check_revocation) { |
| 506 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; | 522 verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; |
| 507 } else { | 523 } else { |
| 508 // EV requires revocation checking. | 524 // EV requires revocation checking. |
| 509 flags &= ~VERIFY_EV_CERT; | 525 flags &= ~VERIFY_EV_CERT; |
| 510 } | 526 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 521 err = SEC_ERROR_EXPIRED_CERTIFICATE; | 537 err = SEC_ERROR_EXPIRED_CERTIFICATE; |
| 522 int cert_status = MapCertErrorToCertStatus(err); | 538 int cert_status = MapCertErrorToCertStatus(err); |
| 523 if (cert_status) { | 539 if (cert_status) { |
| 524 verify_result->cert_status |= cert_status; | 540 verify_result->cert_status |= cert_status; |
| 525 return MapCertStatusToNetError(verify_result->cert_status); | 541 return MapCertStatusToNetError(verify_result->cert_status); |
| 526 } | 542 } |
| 527 // |err| is not a certificate error. | 543 // |err| is not a certificate error. |
| 528 return MapSecurityError(err); | 544 return MapSecurityError(err); |
| 529 } | 545 } |
| 530 | 546 |
| 531 GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, | 547 GetCertChainInfo(flags, cvout[cvout_cert_list_index].value.pointer.chain, |
| 548 cvout[cvout_trust_anchor_index].value.pointer.cert, |
| 532 verify_result); | 549 verify_result); |
| 533 if (IsCertStatusError(verify_result->cert_status)) | 550 if (IsCertStatusError(verify_result->cert_status)) |
| 534 return MapCertStatusToNetError(verify_result->cert_status); | 551 return MapCertStatusToNetError(verify_result->cert_status); |
| 535 | 552 |
| 536 if ((flags & VERIFY_EV_CERT) && VerifyEV(certificate)) | 553 if ((flags & VERIFY_EV_CERT) && VerifyEV(certificate)) |
| 537 verify_result->cert_status |= CERT_STATUS_IS_EV; | 554 verify_result->cert_status |= CERT_STATUS_IS_EV; |
| 538 return OK; | 555 return OK; |
| 539 } | 556 } |
| 540 | 557 |
| 541 } // namespace x509_chain | 558 } // namespace x509_chain |
| 542 | 559 |
| 543 } // namespace net | 560 } // namespace net |
| OLD | NEW |