15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_proc_nss.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cert.h> 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <nss.h> 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <prerror.h> 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <secerr.h> 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sechash.h> 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <sslerr.h> 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/nss_util.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/scoped_nss_types.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "crypto/sha2.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h" 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/asn1_util.h" 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_status_flags.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verifier.h" 25c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/cert_verify_result.h" 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/crl_set.h" 27c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/ev_root_ca_metadata.h" 28c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_certificate.h" 29c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_nss.h" 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <CommonCrypto/CommonDigest.h> 33c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "net/cert/x509_util_ios.h" 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_IOS) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define NSS_VERSION_NUM (NSS_VMAJOR * 10000 + NSS_VMINOR * 100 + NSS_VPATCH) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if NSS_VERSION_NUM < 31305 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Added in NSS 3.13.5. 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED -8016 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if NSS_VERSION_NUM < 31402 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Added in NSS 3.14.2. 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#define cert_pi_useOnlyTrustAnchors static_cast<CERTValParamInType>(14) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)typedef scoped_ptr_malloc< 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificatePolicies, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::NSSDestroyer<CERTCertificatePolicies, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificatePoliciesExtension> > 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)typedef scoped_ptr_malloc< 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) crypto::NSSDestroyer<CERTCertList, CERT_DestroyCertList> > 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedCERTCertList; 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ScopedCERTValOutParam manages destruction of values in the CERTValOutParam 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// array that cvout points to. cvout must be initialized as passed to 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_PKIXVerifyCert, so that the array must be terminated with 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cert_po_end type. 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When it goes out of scope, it destroys values of cert_po_trustAnchor 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and cert_po_certList types, but doesn't release the array itself. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedCERTValOutParam { 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 70558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch explicit ScopedCERTValOutParam(CERTValOutParam* cvout) : cvout_(cvout) {} 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedCERTValOutParam() { 73558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Clear(); 74558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 75558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 76558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Free the internal resources, but do not release the array itself. 77558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch void Clear() { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cvout_ == NULL) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTValOutParam *p = cvout_; p->type != cert_po_end; p++) { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (p->type) { 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cert_po_trustAnchor: 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->value.pointer.cert) { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificate(p->value.pointer.cert); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->value.pointer.cert = NULL; 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cert_po_certList: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->value.pointer.chain) { 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertList(p->value.pointer.chain); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->value.pointer.chain = NULL; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout_; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map PORT_GetError() return values to our network error codes. 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapSecurityError(int err) { 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (err) { 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PR_DIRECTORY_LOOKUP_ERROR: // DNS lookup error. 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_NAME_NOT_RESOLVED; 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INVALID_ARGS: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_BAD_CERT_DOMAIN: 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_COMMON_NAME_INVALID; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INVALID_TIME: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXPIRED_CERTIFICATE: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_DATE_INVALID; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNKNOWN_ISSUER: 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNTRUSTED_ISSUER: 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CA_CERT_INVALID: 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_AUTHORITY_INVALID; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_OCSP_SERVER_ERROR: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_REVOKED_CERTIFICATE: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_REVOKED; 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_BAD_DER: 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_BAD_SIGNATURE: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_NOT_VALID: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(port): add an ERR_CERT_WRONG_USAGE error code. 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_USAGES_INVALID: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INADEQUATE_KEY_USAGE: // Key usage. 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the certificate is a CA. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_POLICY_VALIDATION_FAILED: 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXTENSION_VALUE_INVALID: 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_INVALID; 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_WEAK_SIGNATURE_ALGORITHM; 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map PORT_GetError() return values to our cert status flags. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertStatus MapCertErrorToCertStatus(int err) { 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSecurityError(err); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapNetErrorToCertStatus(net_error); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Saves some information about the certificate chain cert_list in 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// *verify_result. The caller MUST initialize *verify_result before calling 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this function. 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that cert_list[0] is the end entity certificate. 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCertChainInfo(CERTCertList* cert_list, 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_cert, 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifyResult* verify_result) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_list); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* verified_cert = NULL; 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTCertificate*> verified_chain; 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node), ++i) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0) { 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_cert = node->cert; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because of an NSS bug, CERT_PKIXVerifyCert may chain a self-signed 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate of a root CA to another certificate of the same root CA 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // key. Detect that error and ignore the root CA certificate. 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See https://bugzilla.mozilla.org/show_bug.cgi?id=721288. 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->cert->isRoot) { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: isRoot doesn't mean the certificate is a trust anchor. It 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // means the certificate is self-signed. Here we assume isRoot only 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implies the certificate is self-issued. 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertListNode* next_node = CERT_LIST_NEXT(node); 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* next_cert; 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CERT_LIST_END(next_node, cert_list)) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_cert = next_node->cert; 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_cert = root_cert; 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that |node->cert| is actually a self-signed certificate 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose key is equal to |next_cert|, and not a self-issued 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate signed by another key of the same CA. 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_cert && SECITEM_ItemsAreEqual(&node->cert->derPublicKey, 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &next_cert->derPublicKey)) { 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_chain.push_back(node->cert); 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECAlgorithmID& signature = node->cert->signature; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (oid_tag) { 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md5 = true; 2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: 2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md2 = true; 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md4 = true; 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_cert) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_chain.push_back(root_cert); 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->verified_cert = 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util_ios::CreateCertFromNSSHandles(verified_cert, verified_chain); 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->verified_cert = 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::CreateFromHandle(verified_cert, verified_chain); 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_IOS) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IsKnownRoot returns true if the given certificate is one that we believe 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is a standard (as opposed to user-installed) root. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsKnownRoot(CERTCertificate* root) { 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root || !root->slot) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This magic name is taken from 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/builtins/constants.c&rev=1.13&mark=86,89#79 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 == strcmp(PK11_GetSlotName(root->slot), 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NSS Builtin Objects"); 2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if the given certificate is one of the additional trust anchors. 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsAdditionalTrustAnchor(CERTCertList* additional_trust_anchors, 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* root) { 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!additional_trust_anchors || !root) 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(additional_trust_anchors); 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !CERT_LIST_END(node, additional_trust_anchors); 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = CERT_LIST_NEXT(node)) { 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (CERT_CompareCerts(node->cert, root)) 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum CRLSetResult { 2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCRLSetOk, 258a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kCRLSetRevoked, 259a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kCRLSetUnknown, 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CheckRevocationWithCRLSet attempts to check each element of |cert_list| 2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// against |crl_set|. It returns: 2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kCRLSetRevoked: if any element of the chain is known to have been revoked. 265a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// kCRLSetUnknown: if there is no fresh information about some element in 266a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// the chain. 267a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// kCRLSetOk: if every element in the chain is covered by a fresh CRLSet and 268a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// is unrevoked. 2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list, 2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root, 2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet* crl_set) { 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTCertificate*> certs; 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_list) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs.push_back(node->cert); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root) 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs.push_back(root); 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 284a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool covered = true; 285a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We iterate from the root certificate down to the leaf, keeping track of 2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the issuer's SPKI at each step. 2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string issuer_spki_hash; 2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<CERTCertificate*>::reverse_iterator i = certs.rbegin(); 2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != certs.rend(); ++i) { 2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert = *i; 2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece der(reinterpret_cast<char*>(cert->derCert.data), 2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derCert.len); 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece spki; 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!asn1::ExtractSPKIFromDERCert(der, &spki)) { 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 299a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) covered = false; 300a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string spki_hash = crypto::SHA256HashString(spki); 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece serial_number = base::StringPiece( 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(cert->serialNumber.data), 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->serialNumber.len); 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet::Result result = crl_set->CheckSPKI(spki_hash); 3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != CRLSet::REVOKED && !issuer_spki_hash.empty()) 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = crl_set->CheckSerial(serial_number, issuer_spki_hash); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issuer_spki_hash = spki_hash; 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::REVOKED: 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kCRLSetRevoked; 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::UNKNOWN: 319a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) covered = false; 320a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::GOOD: 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 325a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) covered = false; 326a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 330a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (!covered || crl_set->IsExpired()) 331a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return kCRLSetUnknown; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kCRLSetOk; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Forward declarations. 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus RetryPKIXVerifyCertWithWorkarounds( 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, int num_policy_oids, 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle); 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Call CERT_PKIXVerifyCert for the cert_handle. 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verification results are stored in an array of CERTValOutParam. 344558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being 345558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// checked), then the failure to obtain valid CRL/OCSP information for all 346558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// certificates that contain CRL/OCSP URLs will cause the certificate to be 347558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// treated as if it was revoked. Since failures may be caused by transient 348558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// network failures or by malicious attackers, in general, hard_fail should be 349558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// false. 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If policy_oids is not NULL and num_policy_oids is positive, policies 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are also checked. 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// additional_trust_anchors is an optional list of certificates that can be 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// trusted as anchors when building a certificate chain. 3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Caller must initialize cvout before calling this function. 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool check_revocation, 357558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool hard_fail, 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SECOidTag* policy_oids, 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_policy_oids, 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList* additional_trust_anchors, 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout) { 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_crl = check_revocation; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_ocsp = check_revocation; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 revocation_method_flags = 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_ALLOW_NETWORK_FETCHING | 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_IGNORE_MISSING_FRESH_INFO | 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 revocation_method_independent_flags = 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check_revocation && policy_oids && num_policy_oids > 0) { 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EV verification requires revocation checking. Consider the certificate 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // revoked if we don't have revocation info. 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(wtc): Add a bool parameter to expressly specify we're doing EV 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // verification or we want strict revocation flags. 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags |= 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 382558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else if (check_revocation && hard_fail) { 383558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch revocation_method_flags |= CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO; 384558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch revocation_method_independent_flags |= 385558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE; 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags |= 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 method_flags[2]; 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_crl] = revocation_method_flags; 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_ocsp] = revocation_method_flags; 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_crl) { 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_crl] |= 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_TEST_USING_THIS_METHOD; 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_ocsp) { 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_ocsp] |= 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_TEST_USING_THIS_METHOD; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTRevocationMethodIndex preferred_revocation_methods[1]; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_ocsp) { 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_revocation_methods[0] = cert_revocation_method_ocsp; 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_revocation_methods[0] = cert_revocation_method_crl; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTRevocationFlags revocation_flags; 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.number_of_defined_methods = 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(method_flags); 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.cert_rev_flags_per_method = method_flags; 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.number_of_preferred_methods = 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(preferred_revocation_methods); 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.preferred_methods = preferred_revocation_methods; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.cert_rev_method_independent_flags = 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.number_of_defined_methods = 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(method_flags); 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.cert_rev_flags_per_method = method_flags; 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.number_of_preferred_methods = 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(preferred_revocation_methods); 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.preferred_methods = preferred_revocation_methods; 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.cert_rev_method_independent_flags = 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTValInParam> cvin; 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.reserve(7); 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValInParam in_param; 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_revocationFlags; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.pointer.revocation = &revocation_flags; 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_oids && num_policy_oids > 0) { 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_policyOID; 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.arraySize = num_policy_oids; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.array.oids = policy_oids; 4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (additional_trust_anchors) { 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.type = cert_pi_trustAnchors; 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.value.pointer.chain = additional_trust_anchors; 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.push_back(in_param); 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.type = cert_pi_useOnlyTrustAnchors; 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.value.scalar.b = PR_FALSE; 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.push_back(in_param); 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cvin[0], cvout, NULL); 4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, 4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_io_enabled, &cvin, cvout); 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PKIXVerifyCert calls this function to work around some bugs in 4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_PKIXVerifyCert. All the arguments of this function are either the 4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arguments or local variables of PKIXVerifyCert. 4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus RetryPKIXVerifyCertWithWorkarounds( 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, int num_policy_oids, 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout) { 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We call this function when the first CERT_PKIXVerifyCert call in 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PKIXVerifyCert failed, so we initialize |rv| to SECFailure. 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = SECFailure; 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nss_error = PORT_GetError(); 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValInParam in_param; 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CA certificate, so we retry with cert_pi_useAIACertFetch. 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert_pi_useAIACertFetch has several bugs in its error handling and 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error reporting (NSS bug 528743), so we don't use it by default. 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: When building a certificate chain, CERT_PKIXVerifyCert may 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // incorrectly pick a CA certificate with the same subject name as the 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // missing intermediate CA certificate, and fail with the 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE. 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_io_enabled && 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nss_error == SEC_ERROR_UNKNOWN_ISSUER || 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_error == SEC_ERROR_BAD_SIGNATURE)) { 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(cvin->back().type, cert_pi_end); 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->pop_back(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_useAIACertFetch; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.scalar.b = PR_TRUE; 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(*cvin)[0], cvout, NULL); 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == SECSuccess) 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_nss_error = PORT_GetError(); 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_nss_error == SEC_ERROR_INVALID_ARGS || 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE || 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_INFO_ACCESS_LOCATION || 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE || 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE || 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IS_SEC_ERROR(new_nss_error)) { 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the original error code because of cert_pi_useAIACertFetch's 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bad error reporting. 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(nss_error); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_error = new_nss_error; 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an intermediate CA certificate has requireExplicitPolicy in its 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // policyConstraints extension, CERT_PKIXVerifyCert fails with 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate policy (NSS bug 552775). So we retry with the certificate 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // policy found in the server certificate. 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED && 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_policy_oids == 0) { 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag policy = GetFirstCertPolicy(cert_handle); 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy != SEC_OID_UNKNOWN) { 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(cvin->back().type, cert_pi_end); 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->pop_back(); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_policyOID; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.arraySize = 1; 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.array.oids = &policy; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(*cvin)[0], cvout, NULL); 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the original error code. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(nss_error); 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the certificatePolicies extension of the certificate. Returns 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NULL if the certificate doesn't have the extension or the extension can't 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be decoded. The returned value must be freed with a 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_DestroyCertificatePoliciesExtension call. 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificatePolicies* DecodeCertPolicies( 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle) { 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem policy_ext; 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_FindCertExtension(cert_handle, 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_OID_X509_CERTIFICATE_POLICIES, 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &policy_ext); 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificatePolicies* policies = 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DecodeCertificatePoliciesExtension(&policy_ext); 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECITEM_FreeItem(&policy_ext, PR_FALSE); 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return policies; 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the OID tag for the first certificate policy in the certificate's 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificatePolicies extension. Returns SEC_OID_UNKNOWN if the certificate 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has no certificate policy. 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle)); 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policies.get()) 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SEC_OID_UNKNOWN; 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo* policy_info = policies->policyInfos[0]; 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policy_info) 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SEC_OID_UNKNOWN; 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_info->oid != SEC_OID_UNKNOWN) 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return policy_info->oid; 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The certificate policy is unknown to NSS. We need to create a dynamic 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OID tag for the policy. 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidData od; 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.oid.len = policy_info->policyID.len; 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.oid.data = policy_info->policyID.data; 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.offset = SEC_OID_UNKNOWN; 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NSS doesn't allow us to pass an empty description, so I use a hardcoded, 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default description here. The description doesn't need to be unique for 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // each OID. 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.desc = "a certificate policy"; 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.mechanism = CKM_INVALID_MECHANISM; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.supportedExtension = INVALID_CERT_EXTENSION; 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SECOID_AddEntry(&od); 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValue hash(HASH_VALUE_SHA1); 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derPublicKey.data, cert->derPublicKey.len); 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SECSuccess, rv); 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash; 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValue hash(HASH_VALUE_SHA256); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA256(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derPublicKey.data, cert->derPublicKey.len); 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(rv, SECSuccess); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash; 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendPublicKeyHashes(CERTCertList* cert_list, 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_cert, 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValueVector* hashes) { 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA1(node->cert)); 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA256(node->cert)); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_cert) { 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA1(root_cert)); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA256(root_cert)); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |cert_handle| contains a policy OID that is an EV policy 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OID according to |metadata|, storing the resulting policy OID in 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |*ev_policy_oid|. A true return is not sufficient to establish that a 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate is EV, but a false return is sufficient to establish the 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate cannot be EV. 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsEVCandidate(EVRootCAMetadata* metadata, 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag* ev_policy_oid) { 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_handle); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle)); 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policies.get()) 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo** policy_infos = policies->policyInfos; 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*policy_infos != NULL) { 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo* policy_info = *policy_infos++; 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the Policy OID is unknown, that implicitly means it has not been 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // registered as an EV policy. 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_info->oid == SEC_OID_UNKNOWN) 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (metadata->IsEVPolicyOID(policy_info->oid)) { 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ev_policy_oid = policy_info->oid; 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and nsNSSCertHelper.cpp) to learn how to verify EV certificate. 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(wtc): A possible optimization is that we get the trust anchor from 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the first PKIXVerifyCert call. We look up the EV policy for the trust 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// anchor. If the trust anchor has no EV policy, we know the cert isn't EV. 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Otherwise, we pass just that EV policy (as opposed to all the EV policies) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the second PKIXVerifyCert call. 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyEV(CERTCertificate* cert_handle, 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet* crl_set, 668a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool rev_checking_enabled, 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVRootCAMetadata* metadata, 6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SECOidTag ev_policy_oid, 6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList* additional_trust_anchors) { 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam cvout[3]; 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_index = 0; 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_certList; 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.chain = NULL; 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_cert_list_index = cvout_index; 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_trustAnchor; 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.cert = NULL; 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_trust_anchor_index = cvout_index; 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_end; 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTValOutParam scoped_cvout(cvout); 6845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus status = PKIXVerifyCert( 6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle, 6875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rev_checking_enabled, 688558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, /* hard fail is implied in EV. */ 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags & CertVerifier::VERIFY_CERT_IO_ENABLED, 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ev_policy_oid, 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) additional_trust_anchors, 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout); 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != SECSuccess) 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_ca = 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_ca == NULL) 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This second PKIXVerifyCert call could have found a different certification 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path and one or more of the certificates on this new path, that weren't on 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the old path, might have been revoked. 7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set) { 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSetResult crl_set_result = CheckRevocationWithCRLSet( 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_cert_list_index].value.pointer.chain, 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crl_set); 7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set_result == kCRLSetRevoked) 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue fingerprint = x509_util_ios::CalculateFingerprintNSS(root_ca); 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue fingerprint = 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::CalculateFingerprint(root_ca); 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid); 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { 7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList* result = CERT_NewCertList(); 7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < list.size(); ++i) { 7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_IOS) 7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // X509Certificate::os_cert_handle() on iOS is a SecCertificateRef; convert 7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it to an NSS CERTCertificate. 7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* cert = x509_util_ios::CreateNSSCertHandleFromOSHandle( 7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) list[i]->os_cert_handle()); 7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* cert = list[i]->os_cert_handle(); 7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); 7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProcNSS::CertVerifyProcNSS() {} 7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProcNSS::~CertVerifyProcNSS() {} 7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // This requires APIs introduced in 3.14.2. 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return NSS_VersionCheck("3.14.2"); 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int CertVerifyProcNSS::VerifyInternal( 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) X509Certificate* cert, 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& hostname, 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags, 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CRLSet* crl_set, 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CertificateList& additional_trust_anchors, 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertVerifyResult* verify_result) { 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For iOS, the entire chain must be loaded into NSS's in-memory certificate 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // store. 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util_ios::NSSCertChain scoped_chain(cert); 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle = scoped_chain.cert_handle(); 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle = cert->os_cert_handle(); 7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_IOS) 7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that the hostname matches with the common name of the cert. 7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus status = CERT_VerifyCertName(cert_handle, hostname.c_str()); 7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != SECSuccess) 7695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that the cert is valid now. 7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECCertTimeValidity validity = CERT_CheckCertValidTimes( 7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle, PR_Now(), PR_TRUE); 7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (validity != secCertTimeValid) 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam cvout[3]; 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_index = 0; 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_certList; 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.chain = NULL; 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_cert_list_index = cvout_index; 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_trustAnchor; 7845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.cert = NULL; 7855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_trust_anchor_index = cvout_index; 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 7875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_end; 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTValOutParam scoped_cvout(cvout); 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag ev_policy_oid = SEC_OID_UNKNOWN; 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_ev_candidate = 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flags & CertVerifier::VERIFY_EV_CERT) && 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsEVCandidate(metadata, cert_handle, &ev_policy_oid); 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled = flags & CertVerifier::VERIFY_CERT_IO_ENABLED; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool check_revocation = 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_io_enabled && 798a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check_revocation) 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedCERTCertList trust_anchors; 8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (SupportsAdditionalTrustAnchors() && !additional_trust_anchors.empty()) { 8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trust_anchors.reset( 8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertificateListToCERTCertList(additional_trust_anchors)); 8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 808558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch status = PKIXVerifyCert(cert_handle, check_revocation, false, 809558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cert_io_enabled, NULL, 0, trust_anchors.get(), 810558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cvout); 811558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 812558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (status == SECSuccess && 813558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && 814558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { 815558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // TODO(rsleevi): Optimize this by supplying the constructed chain to 816558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // libpkix via cvin. Omitting for now, due to lack of coverage in upstream 817558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // NSS tests for that feature. 818558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scoped_cvout.Clear(); 819558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 820558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch status = PKIXVerifyCert(cert_handle, true, true, 821558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cert_io_enabled, NULL, 0, trust_anchors.get(), 822558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cvout); 823558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status == SECSuccess) { 8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 8272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &verify_result->public_key_hashes); 8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result->is_issued_by_known_root = 8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result->is_issued_by_additional_trust_anchor = 8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsAdditionalTrustAnchor( 8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trust_anchors.get(), 8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert); 8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result); 8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 842a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CRLSetResult crl_set_result = kCRLSetUnknown; 8435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set) { 844a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) crl_set_result = CheckRevocationWithCRLSet( 8455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_cert_list_index].value.pointer.chain, 8465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crl_set); 8485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set_result == kCRLSetRevoked) { 8495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 8505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = SECFailure; 8515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != SECSuccess) { 8555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = PORT_GetError(); 8565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 8575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " failed err=" << err; 8585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CERT_PKIXVerifyCert rerports the wrong error code for 8595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expired certificates (NSS bug 491174) 8605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err == SEC_ERROR_CERT_NOT_VALID && 8615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (verify_result->cert_status & CERT_STATUS_DATE_INVALID)) 8625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = SEC_ERROR_EXPIRED_CERTIFICATE; 8635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertStatus cert_status = MapCertErrorToCertStatus(err); 8645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_status) { 8655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= cert_status; 8665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapCertStatusToNetError(verify_result->cert_status); 8675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |err| is not a certificate error. 8695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSecurityError(err); 8705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCertStatusError(verify_result->cert_status)) 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapCertStatusToNetError(verify_result->cert_status); 8745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 876a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) check_revocation |= 877a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) crl_set_result != kCRLSetOk && 878a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) cert_io_enabled && 879a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 880a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (check_revocation) 881a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 882a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 883a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (VerifyEV(cert_handle, flags, crl_set, check_revocation, metadata, 884a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) ev_policy_oid, trust_anchors.get())) { 885a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_IS_EV; 886a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 893