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)namespace net { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 40a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef scoped_ptr< 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificatePolicies, 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crypto::NSSDestroyer<CERTCertificatePolicies, 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificatePoliciesExtension> > 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 46a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)typedef scoped_ptr< 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList, 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) crypto::NSSDestroyer<CERTCertList, CERT_DestroyCertList> > 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedCERTCertList; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ScopedCERTValOutParam manages destruction of values in the CERTValOutParam 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// array that cvout points to. cvout must be initialized as passed to 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_PKIXVerifyCert, so that the array must be terminated with 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// cert_po_end type. 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When it goes out of scope, it destroys values of cert_po_trustAnchor 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and cert_po_certList types, but doesn't release the array itself. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ScopedCERTValOutParam { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public: 59558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch explicit ScopedCERTValOutParam(CERTValOutParam* cvout) : cvout_(cvout) {} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ~ScopedCERTValOutParam() { 62558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch Clear(); 63558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 64558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 65558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // Free the internal resources, but do not release the array itself. 66558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch void Clear() { 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cvout_ == NULL) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTValOutParam *p = cvout_; p->type != cert_po_end; p++) { 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (p->type) { 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cert_po_trustAnchor: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->value.pointer.cert) { 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertificate(p->value.pointer.cert); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->value.pointer.cert = NULL; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case cert_po_certList: 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (p->value.pointer.chain) { 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DestroyCertList(p->value.pointer.chain); 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) p->value.pointer.chain = NULL; 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private: 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout_; 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map PORT_GetError() return values to our network error codes. 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int MapSecurityError(int err) { 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (err) { 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case PR_DIRECTORY_LOOKUP_ERROR: // DNS lookup error. 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_NAME_NOT_RESOLVED; 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INVALID_ARGS: 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_INVALID_ARGUMENT; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SSL_ERROR_BAD_CERT_DOMAIN: 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_COMMON_NAME_INVALID; 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INVALID_TIME: 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXPIRED_CERTIFICATE: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_DATE_INVALID; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNKNOWN_ISSUER: 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNTRUSTED_ISSUER: 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CA_CERT_INVALID: 1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SEC_ERROR_APPLICATION_CALLBACK_ERROR: // Rejected by 1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // chain_verify_callback. 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_AUTHORITY_INVALID; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(port): map ERR_CERT_NO_REVOCATION_MECHANISM. 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_OCSP_SERVER_ERROR: 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_REVOKED_CERTIFICATE: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_REVOKED; 1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return ERR_CERT_NAME_CONSTRAINT_VIOLATION; 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_BAD_DER: 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_BAD_SIGNATURE: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_NOT_VALID: 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(port): add an ERR_CERT_WRONG_USAGE error code. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_USAGES_INVALID: 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INADEQUATE_KEY_USAGE: // Key usage. 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the certificate is a CA. 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_POLICY_VALIDATION_FAILED: 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_EXTENSION_VALUE_INVALID: 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_INVALID; 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_ERROR_CERT_SIGNATURE_ALGORITHM_DISABLED: 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_CERT_WEAK_SIGNATURE_ALGORITHM; 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ERR_FAILED; 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Map PORT_GetError() return values to our cert status flags. 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertStatus MapCertErrorToCertStatus(int err) { 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int net_error = MapSecurityError(err); 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapNetErrorToCertStatus(net_error); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Saves some information about the certificate chain cert_list in 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// *verify_result. The caller MUST initialize *verify_result before calling 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// this function. 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that cert_list[0] is the end entity certificate. 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void GetCertChainInfo(CERTCertList* cert_list, 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_cert, 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertVerifyResult* verify_result) { 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_list); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* verified_cert = NULL; 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTCertificate*> verified_chain; 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int i = 0; 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node), ++i) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (i == 0) { 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_cert = node->cert; 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Because of an NSS bug, CERT_PKIXVerifyCert may chain a self-signed 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate of a root CA to another certificate of the same root CA 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // key. Detect that error and ignore the root CA certificate. 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // See https://bugzilla.mozilla.org/show_bug.cgi?id=721288. 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (node->cert->isRoot) { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: isRoot doesn't mean the certificate is a trust anchor. It 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // means the certificate is self-signed. Here we assume isRoot only 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // implies the certificate is self-issued. 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertListNode* next_node = CERT_LIST_NEXT(node); 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* next_cert; 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!CERT_LIST_END(next_node, cert_list)) { 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_cert = next_node->cert; 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_cert = root_cert; 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Test that |node->cert| is actually a self-signed certificate 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // whose key is equal to |next_cert|, and not a self-issued 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate signed by another key of the same CA. 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (next_cert && SECITEM_ItemsAreEqual(&node->cert->derPublicKey, 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &next_cert->derPublicKey)) { 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_chain.push_back(node->cert); 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECAlgorithmID& signature = node->cert->signature; 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (oid_tag) { 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md5 = true; 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: 2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md2 = true; 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->has_md4 = true; 2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 20634680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) case SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION: 20734680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) case SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE: 20834680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) case SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST: 20934680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) case SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE: 21034680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) verify_result->has_sha1 = true; 21134680572440d7894ef8dafce81d8039ed80726a2Torne (Richard Coles) break; 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_cert) 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verified_chain.push_back(root_cert); 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->verified_cert = 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util_ios::CreateCertFromNSSHandles(verified_cert, verified_chain); 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->verified_cert = 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::CreateFromHandle(verified_cert, verified_chain); 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_IOS) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IsKnownRoot returns true if the given certificate is one that we believe 2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is a standard (as opposed to user-installed) root. 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsKnownRoot(CERTCertificate* root) { 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!root || !root->slot) 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This magic name is taken from 2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/builtins/constants.c&rev=1.13&mark=86,89#79 2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return 0 == strcmp(PK11_GetSlotName(root->slot), 2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "NSS Builtin Objects"); 2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns true if the given certificate is one of the additional trust anchors. 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool IsAdditionalTrustAnchor(CERTCertList* additional_trust_anchors, 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* root) { 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!additional_trust_anchors || !root) 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(additional_trust_anchors); 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !CERT_LIST_END(node, additional_trust_anchors); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) node = CERT_LIST_NEXT(node)) { 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (CERT_CompareCerts(node->cert, root)) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum CRLSetResult { 2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kCRLSetOk, 256a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kCRLSetRevoked, 257a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) kCRLSetUnknown, 2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CheckRevocationWithCRLSet attempts to check each element of |cert_list| 2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// against |crl_set|. It returns: 2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// kCRLSetRevoked: if any element of the chain is known to have been revoked. 263116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kCRLSetUnknown: if there is no fresh information about the leaf 264116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// certificate in the chain or if the CRLSet has expired. 265116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// 266116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// Only the leaf certificate is considered for coverage because some 267116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// intermediates have CRLs with no revocations (after filtering) and 268116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// those CRLs are pruned from the CRLSet at generation time. This means 269116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// that some EV sites would otherwise take the hit of an OCSP lookup for 270116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// no reason. 271116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch// kCRLSetOk: otherwise. 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CRLSetResult CheckRevocationWithCRLSet(CERTCertList* cert_list, 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root, 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet* crl_set) { 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTCertificate*> certs; 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_list) { 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs.push_back(node->cert); 2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root) 2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) certs.push_back(root); 2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 287116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // error is set to true if any errors are found. It causes such chains to be 288116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // considered as not covered. 289116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool error = false; 290116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // last_covered is set to the coverage state of the previous certificate. The 291116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // certificates are iterated over backwards thus, after the iteration, 292116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch // |last_covered| contains the coverage state of the leaf certificate. 293116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch bool last_covered = false; 294a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We iterate from the root certificate down to the leaf, keeping track of 2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the issuer's SPKI at each step. 2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string issuer_spki_hash; 2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::vector<CERTCertificate*>::reverse_iterator i = certs.rbegin(); 2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) i != certs.rend(); ++i) { 3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert = *i; 3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece der(reinterpret_cast<char*>(cert->derCert.data), 3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derCert.len); 3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece spki; 3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!asn1::ExtractSPKIFromDERCert(der, &spki)) { 3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 308116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error = true; 309a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string spki_hash = crypto::SHA256HashString(spki); 3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::StringPiece serial_number = base::StringPiece( 3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<char*>(cert->serialNumber.data), 3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->serialNumber.len); 3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet::Result result = crl_set->CheckSPKI(spki_hash); 3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result != CRLSet::REVOKED && !issuer_spki_hash.empty()) 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = crl_set->CheckSerial(serial_number, issuer_spki_hash); 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) issuer_spki_hash = spki_hash; 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (result) { 3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::REVOKED: 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kCRLSetRevoked; 3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::UNKNOWN: 328116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last_covered = false; 329a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case CRLSet::GOOD: 331116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch last_covered = true; 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 335116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch error = true; 336a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) continue; 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 340116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch if (error || !last_covered || crl_set->IsExpired()) 341a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) return kCRLSetUnknown; 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return kCRLSetOk; 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Forward declarations. 3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus RetryPKIXVerifyCertWithWorkarounds( 3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, int num_policy_oids, 3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout); 3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle); 3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Call CERT_PKIXVerifyCert for the cert_handle. 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Verification results are stored in an array of CERTValOutParam. 354558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// If |hard_fail| is true, and no policy_oids are supplied (eg: EV is NOT being 355558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// checked), then the failure to obtain valid CRL/OCSP information for all 356558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// certificates that contain CRL/OCSP URLs will cause the certificate to be 357558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// treated as if it was revoked. Since failures may be caused by transient 358558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// network failures or by malicious attackers, in general, hard_fail should be 359558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch// false. 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If policy_oids is not NULL and num_policy_oids is positive, policies 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// are also checked. 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// additional_trust_anchors is an optional list of certificates that can be 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// trusted as anchors when building a certificate chain. 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Caller must initialize cvout before calling this function. 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus PKIXVerifyCert(CERTCertificate* cert_handle, 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool check_revocation, 367558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch bool hard_fail, 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const SECOidTag* policy_oids, 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int num_policy_oids, 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList* additional_trust_anchors, 3725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTChainVerifyCallback* chain_verify_callback, 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout) { 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_crl = check_revocation; 3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool use_ocsp = check_revocation; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 revocation_method_flags = 3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | 3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_ALLOW_NETWORK_FETCHING | 3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | 3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_IGNORE_MISSING_FRESH_INFO | 3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; 3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 revocation_method_independent_flags = 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check_revocation && policy_oids && num_policy_oids > 0) { 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // EV verification requires revocation checking. Consider the certificate 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // revoked if we don't have revocation info. 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(wtc): Add a bool parameter to expressly specify we're doing EV 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // verification or we want strict revocation flags. 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; 3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags |= 3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 393558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } else if (check_revocation && hard_fail) { 394558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch revocation_method_flags |= CERT_REV_M_FAIL_ON_MISSING_FRESH_INFO; 395558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch revocation_method_independent_flags |= 396558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE; 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags |= 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PRUint64 method_flags[2]; 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_crl] = revocation_method_flags; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_ocsp] = revocation_method_flags; 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_crl) { 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_crl] |= 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_TEST_USING_THIS_METHOD; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_ocsp) { 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) method_flags[cert_revocation_method_ocsp] |= 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_REV_M_TEST_USING_THIS_METHOD; 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTRevocationMethodIndex preferred_revocation_methods[1]; 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (use_ocsp) { 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_revocation_methods[0] = cert_revocation_method_ocsp; 4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preferred_revocation_methods[0] = cert_revocation_method_crl; 4205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTRevocationFlags revocation_flags; 4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.number_of_defined_methods = 4245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(method_flags); 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.cert_rev_flags_per_method = method_flags; 4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.number_of_preferred_methods = 4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(preferred_revocation_methods); 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.preferred_methods = preferred_revocation_methods; 4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.leafTests.cert_rev_method_independent_flags = 4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags; 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.number_of_defined_methods = 4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(method_flags); 4345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.cert_rev_flags_per_method = method_flags; 4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.number_of_preferred_methods = 4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) arraysize(preferred_revocation_methods); 4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.preferred_methods = preferred_revocation_methods; 4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_flags.chainTests.cert_rev_method_independent_flags = 4395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) revocation_method_independent_flags; 4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<CERTValInParam> cvin; 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.reserve(7); 4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValInParam in_param; 4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_revocationFlags; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.pointer.revocation = &revocation_flags; 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_oids && num_policy_oids > 0) { 4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_policyOID; 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.arraySize = num_policy_oids; 4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.array.oids = policy_oids; 4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (additional_trust_anchors) { 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.type = cert_pi_trustAnchors; 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.value.pointer.chain = additional_trust_anchors; 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.push_back(in_param); 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.type = cert_pi_useOnlyTrustAnchors; 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) in_param.value.scalar.b = PR_FALSE; 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvin.push_back(in_param); 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (chain_verify_callback) { 4635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) in_param.type = cert_pi_chainVerifyCallback; 4645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) in_param.value.pointer.chainVerifyCallback = chain_verify_callback; 4655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cvin.push_back(in_param); 4665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 4675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin.push_back(in_param); 4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 4715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &cvin[0], cvout, NULL); 4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, 4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_io_enabled, &cvin, cvout); 4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// PKIXVerifyCert calls this function to work around some bugs in 4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_PKIXVerifyCert. All the arguments of this function are either the 4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// arguments or local variables of PKIXVerifyCert. 4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECStatus RetryPKIXVerifyCertWithWorkarounds( 4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, int num_policy_oids, 4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled, std::vector<CERTValInParam>* cvin, 4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam* cvout) { 4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We call this function when the first CERT_PKIXVerifyCert call in 4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // PKIXVerifyCert failed, so we initialize |rv| to SECFailure. 4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = SECFailure; 4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int nss_error = PORT_GetError(); 4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValInParam in_param; 4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate 4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CA certificate, so we retry with cert_pi_useAIACertFetch. 4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert_pi_useAIACertFetch has several bugs in its error handling and 4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // error reporting (NSS bug 528743), so we don't use it by default. 4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Note: When building a certificate chain, CERT_PKIXVerifyCert may 4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // incorrectly pick a CA certificate with the same subject name as the 4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // missing intermediate CA certificate, and fail with the 4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with 5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE. 5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_io_enabled && 5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (nss_error == SEC_ERROR_UNKNOWN_ISSUER || 5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_error == SEC_ERROR_BAD_SIGNATURE)) { 5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(cvin->back().type, cert_pi_end); 5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->pop_back(); 5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_useAIACertFetch; 5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.scalar.b = PR_TRUE; 5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(*cvin)[0], cvout, NULL); 5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv == SECSuccess) 5145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 5155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int new_nss_error = PORT_GetError(); 5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (new_nss_error == SEC_ERROR_INVALID_ARGS || 5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE || 5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_INFO_ACCESS_LOCATION || 5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE || 5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE || 5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !IS_SEC_ERROR(new_nss_error)) { 5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the original error code because of cert_pi_useAIACertFetch's 5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bad error reporting. 5245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(nss_error); 5255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 5265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) nss_error = new_nss_error; 5285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If an intermediate CA certificate has requireExplicitPolicy in its 5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // policyConstraints extension, CERT_PKIXVerifyCert fails with 5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any 5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // certificate policy (NSS bug 552775). So we retry with the certificate 5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // policy found in the server certificate. 5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED && 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) num_policy_oids == 0) { 5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag policy = GetFirstCertPolicy(cert_handle); 5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy != SEC_OID_UNKNOWN) { 5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(cvin->back().type, cert_pi_end); 5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->pop_back(); 5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_policyOID; 5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.arraySize = 1; 5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.value.array.oids = &policy; 5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) in_param.type = cert_pi_end; 5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvin->push_back(in_param); 5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &(*cvin)[0], cvout, NULL); 5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) { 5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Use the original error code. 5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(nss_error); 5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return rv; 5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Decodes the certificatePolicies extension of the certificate. Returns 5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// NULL if the certificate doesn't have the extension or the extension can't 5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// be decoded. The returned value must be freed with a 5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// CERT_DestroyCertificatePoliciesExtension call. 5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CERTCertificatePolicies* DecodeCertPolicies( 5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle) { 5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECItem policy_ext; 5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = CERT_FindCertExtension(cert_handle, 5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SEC_OID_X509_CERTIFICATE_POLICIES, 5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &policy_ext); 5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (rv != SECSuccess) 5705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificatePolicies* policies = 5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERT_DecodeCertificatePoliciesExtension(&policy_ext); 5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECITEM_FreeItem(&policy_ext, PR_FALSE); 5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return policies; 5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns the OID tag for the first certificate policy in the certificate's 5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificatePolicies extension. Returns SEC_OID_UNKNOWN if the certificate 5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// has no certificate policy. 5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SECOidTag GetFirstCertPolicy(CERTCertificate* cert_handle) { 5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle)); 5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policies.get()) 5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SEC_OID_UNKNOWN; 5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo* policy_info = policies->policyInfos[0]; 5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policy_info) 5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SEC_OID_UNKNOWN; 5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_info->oid != SEC_OID_UNKNOWN) 5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return policy_info->oid; 5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The certificate policy is unknown to NSS. We need to create a dynamic 5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // OID tag for the policy. 5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidData od; 5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.oid.len = policy_info->policyID.len; 5955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.oid.data = policy_info->policyID.data; 5965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.offset = SEC_OID_UNKNOWN; 5975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NSS doesn't allow us to pass an empty description, so I use a hardcoded, 5985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // default description here. The description doesn't need to be unique for 5995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // each OID. 6005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.desc = "a certificate policy"; 6015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.mechanism = CKM_INVALID_MECHANISM; 6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) od.supportedExtension = INVALID_CERT_EXTENSION; 6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SECOID_AddEntry(&od); 6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HashValue CertPublicKeyHashSHA1(CERTCertificate* cert) { 6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValue hash(HASH_VALUE_SHA1); 6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA1(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 6105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 6115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data(), 6125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derPublicKey.data, cert->derPublicKey.len); 6135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(SECSuccess, rv); 6145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash; 6165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)HashValue CertPublicKeyHashSHA256(CERTCertificate* cert) { 6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValue hash(HASH_VALUE_SHA256); 6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 6215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CC_SHA256(cert->derPublicKey.data, cert->derPublicKey.len, hash.data()); 6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus rv = HASH_HashBuf(HASH_AlgSHA256, hash.data(), 6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert->derPublicKey.data, cert->derPublicKey.len); 6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(rv, SECSuccess); 6265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return hash; 6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void AppendPublicKeyHashes(CERTCertList* cert_list, 6315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_cert, 6325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) HashValueVector* hashes) { 6335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 6345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) !CERT_LIST_END(node, cert_list); 6355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node = CERT_LIST_NEXT(node)) { 6365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA1(node->cert)); 6375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA256(node->cert)); 6385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_cert) { 6405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA1(root_cert)); 6415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) hashes->push_back(CertPublicKeyHashSHA256(root_cert)); 6425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if |cert_handle| contains a policy OID that is an EV policy 6465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// OID according to |metadata|, storing the resulting policy OID in 6475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |*ev_policy_oid|. A true return is not sufficient to establish that a 6485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate is EV, but a false return is sufficient to establish the 6495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// certificate cannot be EV. 6505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsEVCandidate(EVRootCAMetadata* metadata, 6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle, 6525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag* ev_policy_oid) { 6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(cert_handle); 6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTCertificatePolicies policies(DecodeCertPolicies(cert_handle)); 6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!policies.get()) 6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo** policy_infos = policies->policyInfos; 6595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (*policy_infos != NULL) { 6605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTPolicyInfo* policy_info = *policy_infos++; 6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // If the Policy OID is unknown, that implicitly means it has not been 6625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // registered as an EV policy. 6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (policy_info->oid == SEC_OID_UNKNOWN) 6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 6655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (metadata->IsEVPolicyOID(policy_info->oid)) { 6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *ev_policy_oid = policy_info->oid; 6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 6685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 6745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp 6755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and nsNSSCertHelper.cpp) to learn how to verify EV certificate. 6765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(wtc): A possible optimization is that we get the trust anchor from 6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the first PKIXVerifyCert call. We look up the EV policy for the trust 6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// anchor. If the trust anchor has no EV policy, we know the cert isn't EV. 6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Otherwise, we pass just that EV policy (as opposed to all the EV policies) 6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// to the second PKIXVerifyCert call. 6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool VerifyEV(CERTCertificate* cert_handle, 6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int flags, 6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSet* crl_set, 684a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) bool rev_checking_enabled, 6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVRootCAMetadata* metadata, 6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SECOidTag ev_policy_oid, 6875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTCertList* additional_trust_anchors, 6885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTChainVerifyCallback* chain_verify_callback) { 6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam cvout[3]; 6905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_index = 0; 6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_certList; 6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.chain = NULL; 6935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_cert_list_index = cvout_index; 6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 6955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_trustAnchor; 6965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.cert = NULL; 6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_trust_anchor_index = cvout_index; 6985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 6995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_end; 7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTValOutParam scoped_cvout(cvout); 7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECStatus status = PKIXVerifyCert( 7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle, 7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rev_checking_enabled, 705558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch true, /* hard fail is implied in EV. */ 7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) flags & CertVerifier::VERIFY_CERT_IO_ENABLED, 7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &ev_policy_oid, 7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1, 7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) additional_trust_anchors, 7105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chain_verify_callback, 7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout); 7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != SECSuccess) 7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* root_ca = 7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert; 7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (root_ca == NULL) 7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This second PKIXVerifyCert call could have found a different certification 7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // path and one or more of the certificates on this new path, that weren't on 7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // the old path, might have been revoked. 7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set) { 7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CRLSetResult crl_set_result = CheckRevocationWithCRLSet( 7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_cert_list_index].value.pointer.chain, 7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 7275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crl_set); 7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set_result == kCRLSetRevoked) 7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue fingerprint = x509_util_ios::CalculateFingerprintNSS(root_ca); 7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SHA1HashValue fingerprint = 7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) X509Certificate::CalculateFingerprint(root_ca); 7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return metadata->HasEVPolicyOID(fingerprint, ev_policy_oid); 7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)CERTCertList* CertificateListToCERTCertList(const CertificateList& list) { 7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertList* result = CERT_NewCertList(); 7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < list.size(); ++i) { 7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if defined(OS_IOS) 7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // X509Certificate::os_cert_handle() on iOS is a SecCertificateRef; convert 7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // it to an NSS CERTCertificate. 7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* cert = x509_util_ios::CreateNSSCertHandleFromOSHandle( 7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) list[i]->os_cert_handle()); 7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#else 7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERTCertificate* cert = list[i]->os_cert_handle(); 7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CERT_AddCertToListTail(result, CERT_DupCertificate(cert)); 7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return result; 7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProcNSS::CertVerifyProcNSS() {} 7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)CertVerifyProcNSS::~CertVerifyProcNSS() {} 7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool CertVerifyProcNSS::SupportsAdditionalTrustAnchors() const { 7645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return true; 7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 7675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int CertVerifyProcNSS::VerifyInternalImpl( 7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) X509Certificate* cert, 7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::string& hostname, 7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int flags, 7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CRLSet* crl_set, 7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const CertificateList& additional_trust_anchors, 7735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CERTChainVerifyCallback* chain_verify_callback, 7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertVerifyResult* verify_result) { 7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_IOS) 7765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // For iOS, the entire chain must be loaded into NSS's in-memory certificate 7775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // store. 7785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) x509_util_ios::NSSCertChain scoped_chain(cert); 7795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle = scoped_chain.cert_handle(); 7805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 7815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTCertificate* cert_handle = cert->os_cert_handle(); 7825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif // defined(OS_IOS) 7835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7841e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) if (!cert->VerifyNameMatch(hostname, 7851e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) &verify_result->common_name_fallback_used)) { 7865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 7871e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 7885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Make sure that the cert is valid now. 7905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECCertTimeValidity validity = CERT_CheckCertValidTimes( 7915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_handle, PR_Now(), PR_TRUE); 7925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (validity != secCertTimeValid) 7935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 7945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CERTValOutParam cvout[3]; 7965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_index = 0; 7975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_certList; 7985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.chain = NULL; 7995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_cert_list_index = cvout_index; 8005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 8015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_trustAnchor; 8025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].value.pointer.cert = NULL; 8035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int cvout_trust_anchor_index = cvout_index; 8045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout_index++; 8055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_index].type = cert_po_end; 8065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ScopedCERTValOutParam scoped_cvout(cvout); 8075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); 8095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SECOidTag ev_policy_oid = SEC_OID_UNKNOWN; 8105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_ev_candidate = 8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (flags & CertVerifier::VERIFY_EV_CERT) && 8125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IsEVCandidate(metadata, cert_handle, &ev_policy_oid); 8135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool cert_io_enabled = flags & CertVerifier::VERIFY_CERT_IO_ENABLED; 8145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool check_revocation = 8155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cert_io_enabled && 816a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED); 8175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (check_revocation) 8185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 8195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ScopedCERTCertList trust_anchors; 8215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (!additional_trust_anchors.empty()) { 8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trust_anchors.reset( 8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CertificateListToCERTCertList(additional_trust_anchors)); 8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) SECStatus status = PKIXVerifyCert(cert_handle, 8275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_revocation, 8285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) false, 8295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cert_io_enabled, 8305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 8315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 8325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trust_anchors.get(), 8335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chain_verify_callback, 8345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cvout); 835558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch 836558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch if (status == SECSuccess && 837558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch (flags & CertVerifier::VERIFY_REV_CHECKING_REQUIRED_LOCAL_ANCHORS) && 838558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch !IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert)) { 839558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // TODO(rsleevi): Optimize this by supplying the constructed chain to 840558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // libpkix via cvin. Omitting for now, due to lack of coverage in upstream 841558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch // NSS tests for that feature. 842558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch scoped_cvout.Clear(); 843558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 8445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) status = PKIXVerifyCert(cert_handle, 8455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 8465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) true, 8475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) cert_io_enabled, 8485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, 8495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 0, 8505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trust_anchors.get(), 8515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chain_verify_callback, 852558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch cvout); 853558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch } 8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (status == SECSuccess) { 8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) &verify_result->public_key_hashes); 8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result->is_issued_by_known_root = 8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result->is_issued_by_additional_trust_anchor = 8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) IsAdditionalTrustAnchor( 8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) trust_anchors.get(), 8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert); 8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) verify_result); 8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 8715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 872a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) CRLSetResult crl_set_result = kCRLSetUnknown; 8735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set) { 874a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) crl_set_result = CheckRevocationWithCRLSet( 8755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_cert_list_index].value.pointer.chain, 8765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) cvout[cvout_trust_anchor_index].value.pointer.cert, 8775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) crl_set); 8785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (crl_set_result == kCRLSetRevoked) { 8795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PORT_SetError(SEC_ERROR_REVOKED_CERTIFICATE); 8805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) status = SECFailure; 8815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 8845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (status != SECSuccess) { 8855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int err = PORT_GetError(); 8865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 8875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << " failed err=" << err; 8885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // CERT_PKIXVerifyCert rerports the wrong error code for 8895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // expired certificates (NSS bug 491174) 8905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (err == SEC_ERROR_CERT_NOT_VALID && 8915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (verify_result->cert_status & CERT_STATUS_DATE_INVALID)) 8925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) err = SEC_ERROR_EXPIRED_CERTIFICATE; 8935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CertStatus cert_status = MapCertErrorToCertStatus(err); 8945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (cert_status) { 8955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) verify_result->cert_status |= cert_status; 8965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapCertStatusToNetError(verify_result->cert_status); 8975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 8985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // |err| is not a certificate error. 8995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapSecurityError(err); 9005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IsCertStatusError(verify_result->cert_status)) 9035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return MapCertStatusToNetError(verify_result->cert_status); 9045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if ((flags & CertVerifier::VERIFY_EV_CERT) && is_ev_candidate) { 906a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) check_revocation |= 907a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) crl_set_result != kCRLSetOk && 908a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) cert_io_enabled && 909a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) (flags & CertVerifier::VERIFY_REV_CHECKING_ENABLED_EV_ONLY); 910a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) if (check_revocation) 911a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 912a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) 9135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (VerifyEV(cert_handle, 9145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags, 9155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) crl_set, 9165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) check_revocation, 9175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) metadata, 9185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ev_policy_oid, 9195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) trust_anchors.get(), 9205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) chain_verify_callback)) { 921a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) verify_result->cert_status |= CERT_STATUS_IS_EV; 922a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles) } 9235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 9245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return OK; 9265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 9275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 9285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int CertVerifyProcNSS::VerifyInternal( 9295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) X509Certificate* cert, 9305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const std::string& hostname, 9315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) int flags, 9325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CRLSet* crl_set, 9335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) const CertificateList& additional_trust_anchors, 9345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) CertVerifyResult* verify_result) { 9355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return VerifyInternalImpl(cert, 9365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) hostname, 9375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) flags, 9385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) crl_set, 9395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) additional_trust_anchors, 9405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) NULL, // chain_verify_callback 9415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) verify_result); 9425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)} 9435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 9445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 945