1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/x509_certificate.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <cert.h> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <cryptohi.h> 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <keyhi.h> 10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include <nss.h> 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <pk11pub.h> 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <prerror.h> 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <prtime.h> 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <secder.h> 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <secerr.h> 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sechash.h> 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <sslerr.h> 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 20ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/memory/scoped_ptr.h" 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/pickle.h" 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/time.h" 23ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util.h" 24ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/rsa_private_key.h" 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_status_flags.h" 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/cert_verify_result.h" 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/ev_root_ca_metadata.h" 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace { 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ScopedCERTCertificatePolicies { 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies) 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : policies_(policies) {} 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~ScopedCERTCertificatePolicies() { 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (policies_) 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_DestroyCertificatePoliciesExtension(policies_); 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTCertificatePolicies* policies_; 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificatePolicies); 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// ScopedCERTValOutParam manages destruction of values in the CERTValOutParam 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// array that cvout points to. cvout must be initialized as passed to 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// CERT_PKIXVerifyCert, so that the array must be terminated with 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// cert_po_end type. 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// When it goes out of scope, it destroys values of cert_po_trustAnchor 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and cert_po_certList types, but doesn't release the array itself. 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass ScopedCERTValOutParam { 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott explicit ScopedCERTValOutParam(CERTValOutParam* cvout) 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : cvout_(cvout) {} 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~ScopedCERTValOutParam() { 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cvout_ == NULL) 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (CERTValOutParam *p = cvout_; p->type != cert_po_end; p++) { 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (p->type) { 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case cert_po_trustAnchor: 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p->value.pointer.cert) { 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_DestroyCertificate(p->value.pointer.cert); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott p->value.pointer.cert = NULL; 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case cert_po_certList: 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (p->value.pointer.chain) { 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_DestroyCertList(p->value.pointer.chain); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott p->value.pointer.chain = NULL; 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTValOutParam* cvout_; 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Map PORT_GetError() return values to our network error codes. 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapSecurityError(int err) { 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (err) { 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case PR_DIRECTORY_LOOKUP_ERROR: // DNS lookup error. 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_NAME_NOT_RESOLVED; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_INVALID_ARGS: 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_INVALID_ARGUMENT; 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_ERROR_BAD_CERT_DOMAIN: 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_COMMON_NAME_INVALID; 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_INVALID_TIME: 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_EXPIRED_CERTIFICATE: 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_DATE_INVALID; 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_UNKNOWN_ISSUER: 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_UNTRUSTED_ISSUER: 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CA_CERT_INVALID: 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_AUTHORITY_INVALID; 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_REVOKED_CERTIFICATE: 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_REVOKED; 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_BAD_DER: 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_BAD_SIGNATURE: 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CERT_NOT_VALID: 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(port): add an ERR_CERT_WRONG_USAGE error code. 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CERT_USAGES_INVALID: 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_INADEQUATE_KEY_USAGE: 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_INADEQUATE_CERT_TYPE: 117c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SEC_ERROR_POLICY_VALIDATION_FAILED: 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_EXTENSION_VALUE_INVALID: 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_CERT_INVALID; 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FAILED; 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Map PORT_GetError() return values to our cert status flags. 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint MapCertErrorToCertStatus(int err) { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (err) { 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SSL_ERROR_BAD_CERT_DOMAIN: 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_COMMON_NAME_INVALID; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_INVALID_TIME: 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_EXPIRED_CERTIFICATE: 136ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_DATE_INVALID; 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_UNKNOWN_ISSUER: 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_UNTRUSTED_ISSUER: 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CA_CERT_INVALID: 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_AUTHORITY_INVALID; 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(port): map CERT_STATUS_NO_REVOCATION_MECHANISM. 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE: 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_OCSP_SERVER_ERROR: 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION; 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_REVOKED_CERTIFICATE: 147ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_UNTRUSTED_CERT: // Treat as revoked. 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_REVOKED; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_BAD_DER: 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_BAD_SIGNATURE: 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CERT_NOT_VALID: 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(port): add a CERT_STATUS_WRONG_USAGE error code. 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_ERROR_CERT_USAGES_INVALID: 154ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_INADEQUATE_KEY_USAGE: // Key usage. 155ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_INADEQUATE_CERT_TYPE: // Extended key usage and whether 156ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // the certificate is a CA. 157c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch case SEC_ERROR_POLICY_VALIDATION_FAILED: 158ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: 159ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID: 160ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION: 161ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen case SEC_ERROR_EXTENSION_VALUE_INVALID: 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return CERT_STATUS_INVALID; 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return 0; 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Saves some information about the certificate chain cert_list in 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// *verify_result. The caller MUST initialize *verify_result before calling 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// this function. 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Note that cert_list[0] is the end entity certificate and cert_list doesn't 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// contain the root CA certificate. 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid GetCertChainInfo(CERTCertList* cert_list, 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CertVerifyResult* verify_result) { 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NOTE: Using a NSS library before 3.12.3.1 will crash below. To see the 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // NSS version currently in use: 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*) 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // 2. use ident libnss3.so* for the library's version 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(cert_list); 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int i = 0; 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott !CERT_LIST_END(node, cert_list); 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott node = CERT_LIST_NEXT(node), i++) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECAlgorithmID& signature = node->cert->signature; 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm); 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (oid_tag) { 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION: 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->has_md5 = true; 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i != 0) 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->has_md5_ca = true; 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION: 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->has_md2 = true; 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (i != 0) 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->has_md2_ca = true; 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION: 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->has_md4 = true; 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 202c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 203c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 206ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// IsKnownRoot returns true if the given certificate is one that we believe 207ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// is a standard (as opposed to user-installed) root. 208ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool IsKnownRoot(CERTCertificate* root) { 209ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!root->slot) 210ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 211ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 212ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // This magic name is taken from 213ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/builtins/constants.c&rev=1.13&mark=86,89#79 214ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return 0 == strcmp(PK11_GetSlotName(root->slot), 215ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "NSS Builtin Objects"); 216ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 217ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scotttypedef char* (*CERTGetNameFunc)(CERTName* name); 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ParsePrincipal(CERTName* name, 221c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CertPrincipal* principal) { 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(jcampan): add business_category and serial_number. 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // CERT_GetDomainComponentName functions, but they return only the most 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // general (the first) RDN. NSS doesn't have a function for the street 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // address. 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott static const SECOidTag kOIDs[] = { 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SEC_OID_AVA_STREET_ADDRESS, 229c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SEC_OID_AVA_ORGANIZATION_NAME, 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME, 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SEC_OID_AVA_DC }; 232c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 233c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<std::string>* values[] = { 234c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->street_addresses, 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->organization_names, 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->organization_unit_names, 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->domain_components }; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(arraysize(kOIDs) == arraysize(values)); 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTRDN** rdns = name->rdns; 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t rdn = 0; rdns[rdn]; ++rdn) { 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTAVA** avas = rdns[rdn]->avas; 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t pair = 0; avas[pair] != 0; ++pair) { 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECOidTag tag = CERT_GetAVATag(avas[pair]); 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) { 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (kOIDs[oid] == tag) { 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value); 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!decode_item) 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote. 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value(reinterpret_cast<char*>(decode_item->data), 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott decode_item->len); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott values[oid]->push_back(value); 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECITEM_FreeItem(decode_item, PR_TRUE); 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Get CN, L, S, and C. 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTGetNameFunc get_name_funcs[4] = { 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_GetCommonName, CERT_GetLocalityName, 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_GetStateName, CERT_GetCountryName }; 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string* single_values[4] = { 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->common_name, &principal->locality_name, 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott &principal->state_or_province_name, &principal->country_name }; 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott for (size_t i = 0; i < arraysize(get_name_funcs); ++i) { 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* value = get_name_funcs[i](name); 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value) { 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott single_values[i]->assign(value); 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PORT_Free(value); 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid ParseDate(SECItem* der_date, base::Time* result) { 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRTime prtime; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date); 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv == SECSuccess); 281ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen *result = crypto::PRTimeToBaseTime(prtime); 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid GetCertSubjectAltNamesOfType(X509Certificate::OSCertHandle cert_handle, 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTGeneralNameType name_type, 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::vector<std::string>* result) { 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // For future extension: We only support general names of types 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // RFC822Name, DNSName or URI. 289c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(name_type == certRFC822Name || 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_type == certDNSName || 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name_type == certURI); 292c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 293c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECItem alt_name; 294c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus rv = CERT_FindCertExtension(cert_handle, 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name); 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != SECSuccess) 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(arena != NULL); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTGeneralName* alt_name_list; 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name); 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECITEM_FreeItem(&alt_name, PR_FALSE); 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTGeneralName* name = alt_name_list; 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (name) { 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // All of the general name types we support are encoded as 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // IA5String. In general, we should be switching off 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |name->type| and doing type-appropriate conversions. 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (name->type == name_type) { 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott unsigned char* p = name->name.other.data; 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int len = name->name.other.len; 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::string value = std::string(reinterpret_cast<char*>(p), len); 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->push_back(value); 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 317c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott name = CERT_GetNextGeneralName(name); 318c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (name == alt_name_list) 319c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott break; 320c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 321c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PORT_FreeArena(arena, PR_FALSE); 322c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 323c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Forward declarations. 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSECStatus RetryPKIXVerifyCertWithWorkarounds( 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch X509Certificate::OSCertHandle cert_handle, int num_policy_oids, 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout); 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle); 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 330c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Call CERT_PKIXVerifyCert for the cert_handle. 331c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Verification results are stored in an array of CERTValOutParam. 332c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// If policy_oids is not NULL and num_policy_oids is positive, policies 333c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// are also checked. 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Caller must initialize cvout before calling this function. 335c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottSECStatus PKIXVerifyCert(X509Certificate::OSCertHandle cert_handle, 336c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool check_revocation, 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const SECOidTag* policy_oids, 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int num_policy_oids, 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTValOutParam* cvout) { 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool use_crl = check_revocation; 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool use_ocsp = check_revocation; 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 3433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // These CAs have multiple keys, which trigger two bugs in NSS's CRL code. 3443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // 1. NSS may use one key to verify a CRL signed with another key, 3453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // incorrectly concluding that the CRL's signature is invalid. 3463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Hopefully this bug will be fixed in NSS 3.12.9. 3473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // 2. NSS considers all certificates issued by the CA as revoked when it 3483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // receives a CRL with an invalid signature. This overly strict policy 3493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // has been relaxed in NSS 3.12.7. See 3503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // https://bugzilla.mozilla.org/show_bug.cgi?id=562542. 3513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // So we have to turn off CRL checking for these CAs. See 3523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // http://crbug.com/55695. 3533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick static const char* const kMultipleKeyCA[] = { 3543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "CN=Microsoft Secure Server Authority," 3553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "DC=redmond,DC=corp,DC=microsoft,DC=com", 3563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick "CN=Microsoft Secure Server Authority", 3573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick }; 3583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 3593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!NSS_VersionCheck("3.12.7")) { 3603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (size_t i = 0; i < arraysize(kMultipleKeyCA); ++i) { 3613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (strcmp(cert_handle->issuerName, kMultipleKeyCA[i]) == 0) { 3623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick use_crl = false; 3633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 3643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 3673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 368c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRUint64 revocation_method_flags = 369c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD | 370c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_ALLOW_NETWORK_FETCHING | 371c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE | 372c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_IGNORE_MISSING_FRESH_INFO | 373c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_STOP_TESTING_ON_FRESH_INFO; 374c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRUint64 revocation_method_independent_flags = 375c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST; 376c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (policy_oids && num_policy_oids > 0) { 377c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EV verification requires revocation checking. Consider the certificate 378c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // revoked if we don't have revocation info. 379c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // TODO(wtc): Add a bool parameter to expressly specify we're doing EV 380c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // verification or we want strict revocation flags. 381c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE; 382c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_independent_flags |= 383c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE; 384c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 385c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE; 386c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_independent_flags |= 387c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT; 388c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 389c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott PRUint64 method_flags[2]; 390c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method_flags[cert_revocation_method_crl] = revocation_method_flags; 391c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method_flags[cert_revocation_method_ocsp] = revocation_method_flags; 392c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 393c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (use_crl) { 394c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method_flags[cert_revocation_method_crl] |= 395c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_TEST_USING_THIS_METHOD; 396c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 397c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (use_ocsp) { 398c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott method_flags[cert_revocation_method_ocsp] |= 399c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_REV_M_TEST_USING_THIS_METHOD; 400c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 401c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 402c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTRevocationMethodIndex preferred_revocation_methods[1]; 403c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (use_ocsp) { 404c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott preferred_revocation_methods[0] = cert_revocation_method_ocsp; 405c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 406c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott preferred_revocation_methods[0] = cert_revocation_method_crl; 407c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 408c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 409c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTRevocationFlags revocation_flags; 410c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.leafTests.number_of_defined_methods = 411c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott arraysize(method_flags); 412c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.leafTests.cert_rev_flags_per_method = method_flags; 413c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.leafTests.number_of_preferred_methods = 414c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott arraysize(preferred_revocation_methods); 415c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.leafTests.preferred_methods = preferred_revocation_methods; 416c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.leafTests.cert_rev_method_independent_flags = 417c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_independent_flags; 418c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 419c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.chainTests.number_of_defined_methods = 420c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott arraysize(method_flags); 421c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.chainTests.cert_rev_flags_per_method = method_flags; 422c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.chainTests.number_of_preferred_methods = 423c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott arraysize(preferred_revocation_methods); 424c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.chainTests.preferred_methods = preferred_revocation_methods; 425c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_flags.chainTests.cert_rev_method_independent_flags = 426c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott revocation_method_independent_flags; 427c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 428c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<CERTValInParam> cvin; 429c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin.reserve(5); 430c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTValInParam in_param; 431c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // No need to set cert_pi_trustAnchors here. 432c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_revocationFlags; 433c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.pointer.revocation = &revocation_flags; 434c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin.push_back(in_param); 435c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (policy_oids && num_policy_oids > 0) { 436c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_policyOID; 437c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.arraySize = num_policy_oids; 438c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.array.oids = policy_oids; 439c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin.push_back(in_param); 440c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 441c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_end; 442c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin.push_back(in_param); 443c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 444c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 445c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &cvin[0], cvout, NULL); 446c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (rv != SECSuccess) { 447c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids, 448c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &cvin, cvout); 449c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 450c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 451c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 452c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 453c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// PKIXVerifyCert calls this function to work around some bugs in 454c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CERT_PKIXVerifyCert. All the arguments of this function are either the 455c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// arguments or local variables of PKIXVerifyCert. 456c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSECStatus RetryPKIXVerifyCertWithWorkarounds( 457c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch X509Certificate::OSCertHandle cert_handle, int num_policy_oids, 458c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout) { 459c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // We call this function when the first CERT_PKIXVerifyCert call in 460c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // PKIXVerifyCert failed, so we initialize |rv| to SECFailure. 461c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECStatus rv = SECFailure; 462c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int nss_error = PORT_GetError(); 463c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTValInParam in_param; 464c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 465c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate 466c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // CA certificate, so we retry with cert_pi_useAIACertFetch. 467c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cert_pi_useAIACertFetch has several bugs in its error handling and 468c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // error reporting (NSS bug 528743), so we don't use it by default. 469c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Note: When building a certificate chain, CERT_PKIXVerifyCert may 470c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // incorrectly pick a CA certificate with the same subject name as the 471c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // missing intermediate CA certificate, and fail with the 472c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with 473c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE. 474c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nss_error == SEC_ERROR_UNKNOWN_ISSUER || 475c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nss_error == SEC_ERROR_BAD_SIGNATURE) { 476c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(cvin->back().type, cert_pi_end); 477c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->pop_back(); 478c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_useAIACertFetch; 479c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.scalar.b = PR_TRUE; 480c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->push_back(in_param); 481c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_end; 482c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->push_back(in_param); 483c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 484c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(*cvin)[0], cvout, NULL); 485c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv == SECSuccess) 486c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 487c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int new_nss_error = PORT_GetError(); 488c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (new_nss_error == SEC_ERROR_INVALID_ARGS || 489c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE || 490c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE || 491c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE || 492c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch !IS_SEC_ERROR(new_nss_error)) { 493c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Use the original error code because of cert_pi_useAIACertFetch's 494c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // bad error reporting. 495c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PORT_SetError(nss_error); 496c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 497c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 498c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch nss_error = new_nss_error; 499c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 500c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 501c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // If an intermediate CA certificate has requireExplicitPolicy in its 502c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // policyConstraints extension, CERT_PKIXVerifyCert fails with 503c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any 504c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // certificate policy (NSS bug 552775). So we retry with the certificate 505c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // policy found in the server certificate. 506c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED && 507c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch num_policy_oids == 0) { 508c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECOidTag policy = GetFirstCertPolicy(cert_handle); 509c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (policy != SEC_OID_UNKNOWN) { 510c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK_EQ(cvin->back().type, cert_pi_end); 511c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->pop_back(); 512c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_policyOID; 513c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.arraySize = 1; 514c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.value.array.oids = &policy; 515c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->push_back(in_param); 516c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch in_param.type = cert_pi_end; 517c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch cvin->push_back(in_param); 518c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer, 519c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch &(*cvin)[0], cvout, NULL); 520c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) { 521c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Use the original error code. 522c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch PORT_SetError(nss_error); 523c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 524c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 525c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 526c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 527c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 528c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 529c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 530c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Decodes the certificatePolicies extension of the certificate. Returns 531c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// NULL if the certificate doesn't have the extension or the extension can't 532c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// be decoded. The returned value must be freed with a 533c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// CERT_DestroyCertificatePoliciesExtension call. 534c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochCERTCertificatePolicies* DecodeCertPolicies( 535c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch X509Certificate::OSCertHandle cert_handle) { 536c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECItem policy_ext; 537c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus rv = CERT_FindCertExtension( 538c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cert_handle, SEC_OID_X509_CERTIFICATE_POLICIES, &policy_ext); 539c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (rv != SECSuccess) 540c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 541c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTCertificatePolicies* policies = 542c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_DecodeCertificatePoliciesExtension(&policy_ext); 543c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECITEM_FreeItem(&policy_ext, PR_FALSE); 544c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return policies; 545c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 546c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 547c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Returns the OID tag for the first certificate policy in the certificate's 548c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// certificatePolicies extension. Returns SEC_OID_UNKNOWN if the certificate 549c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// has no certificate policy. 550c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle) { 551c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle); 552c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!policies) 553c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SEC_OID_UNKNOWN; 554c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch ScopedCERTCertificatePolicies scoped_policies(policies); 555c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTPolicyInfo* policy_info = policies->policyInfos[0]; 556c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!policy_info) 557c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SEC_OID_UNKNOWN; 558c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (policy_info->oid != SEC_OID_UNKNOWN) 559c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return policy_info->oid; 560c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 561c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // The certificate policy is unknown to NSS. We need to create a dynamic 562c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // OID tag for the policy. 563c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECOidData od; 564c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.oid.len = policy_info->policyID.len; 565c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.oid.data = policy_info->policyID.data; 566c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.offset = SEC_OID_UNKNOWN; 567c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // NSS doesn't allow us to pass an empty description, so I use a hardcoded, 568c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // default description here. The description doesn't need to be unique for 569c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // each OID. 570c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.desc = "a certificate policy"; 571c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.mechanism = CKM_INVALID_MECHANISM; 572c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch od.supportedExtension = INVALID_CERT_EXTENSION; 573c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return SECOID_AddEntry(&od); 574c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 575c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 576c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochbool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle, 577c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SECOidTag ev_policy_tag) { 578c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle); 579c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!policies) { 580c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch LOG(ERROR) << "Cert has no policies extension or extension couldn't be " 581c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch "decoded."; 582c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 583c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 584c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScopedCERTCertificatePolicies scoped_policies(policies); 585c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTPolicyInfo** policy_infos = policies->policyInfos; 586c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (*policy_infos != NULL) { 587c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTPolicyInfo* policy_info = *policy_infos++; 588c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECOidTag oid_tag = policy_info->oid; 589c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (oid_tag == SEC_OID_UNKNOWN) 590c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott continue; 591c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (oid_tag == ev_policy_tag) 592c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 593c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 594c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "No EV Policy Tag"; 595c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 596c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 597c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5983345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickSECStatus PR_CALLBACK 5993345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickCollectCertsCallback(void* arg, SECItem** certs, int num_certs) { 6003345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate::OSCertHandles* results = 6013345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick reinterpret_cast<X509Certificate::OSCertHandles*>(arg); 6023345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6033345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick for (int i = 0; i < num_certs; ++i) { 6043345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate::OSCertHandle handle = 6053345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick X509Certificate::CreateOSCertHandleFromBytes( 6063345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick reinterpret_cast<char*>(certs[i]->data), certs[i]->len); 6073345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (handle) 6083345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick results->push_back(handle); 6093345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 6103345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 6113345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return SECSuccess; 6123345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 6133345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 614ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenSHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) { 615ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SHA1Fingerprint hash; 616ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data, 617ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cert->derPublicKey.data, cert->derPublicKey.len); 618ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK_EQ(rv, SECSuccess); 619ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return hash; 620ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 621ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 622ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenvoid AppendPublicKeyHashes(CERTCertList* cert_list, 623ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CERTCertificate* root_cert, 624ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen std::vector<SHA1Fingerprint>* hashes) { 625ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list); 626ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen !CERT_LIST_END(node, cert_list); 627ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen node = CERT_LIST_NEXT(node)) { 628ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen hashes->push_back(CertPublicKeyHash(node->cert)); 629ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 630ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen hashes->push_back(CertPublicKeyHash(root_cert)); 631ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 632ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 633c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace 634c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 635c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid X509Certificate::Initialize() { 636c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParsePrincipal(&cert_handle_->subject, &subject_); 637c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParsePrincipal(&cert_handle_->issuer, &issuer_); 638c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 639c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParseDate(&cert_handle_->validity.notBefore, &valid_start_); 640c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_); 641c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 642c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott fingerprint_ = CalculateFingerprint(cert_handle_); 643c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 644ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen serial_number_ = std::string( 645ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen reinterpret_cast<char*>(cert_handle_->serialNumber.data), 646ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cert_handle_->serialNumber.len); 647ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Remove leading zeros. 648ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen while (serial_number_.size() > 1 && serial_number_[0] == 0) 649ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen serial_number_ = serial_number_.substr(1, serial_number_.size() - 1); 650c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 651c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 65221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// static 65321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenX509Certificate* X509Certificate::CreateSelfSigned( 654ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crypto::RSAPrivateKey* key, 65521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen const std::string& subject, 65621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen uint32 serial_number, 65721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen base::TimeDelta valid_duration) { 65821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK(key); 65921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 66021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Create info about public key. 66121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTSubjectPublicKeyInfo* spki = 66221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECKEY_CreateSubjectPublicKeyInfo(key->public_key()); 66321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!spki) 66421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 66521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 66621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Create the certificate request. 66721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTName* subject_name = 66821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_AsciiToName(const_cast<char*>(subject.c_str())); 66921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertificateRequest* cert_request = 67021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_CreateCertificateRequest(subject_name, spki, NULL); 67121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECKEY_DestroySubjectPublicKeyInfo(spki); 67221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 67321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!cert_request) { 67421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PRErrorCode prerr = PR_GetError(); 67521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LOG(ERROR) << "Failed to create certificate request: " << prerr; 67621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyName(subject_name); 67721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 67821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 67921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 68021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PRTime now = PR_Now(); 68121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PRTime not_after = now + valid_duration.InMicroseconds(); 68221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 68321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Note that the time is now in micro-second unit. 68421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTValidity* validity = CERT_CreateValidity(now, not_after); 68521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertificate* cert = CERT_CreateCertificate(serial_number, subject_name, 68621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen validity, cert_request); 68721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!cert) { 68821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PRErrorCode prerr = PR_GetError(); 68921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LOG(ERROR) << "Failed to create certificate: " << prerr; 69021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 69121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 69221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Cleanup for resources used to generate the cert. 69321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyName(subject_name); 69421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyValidity(validity); 69521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificateRequest(cert_request); 69621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 69721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Sign the cert here. The logic of this method references SignCert() in NSS 69821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert. 69921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 70021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // |arena| is used to encode the cert. 70121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen PRArenaPool* arena = cert->arena; 70221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType, 70321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SEC_OID_SHA1); 70421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (algo_id == SEC_OID_UNKNOWN) { 70521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 70621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 70721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 70821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 70921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0); 71021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != SECSuccess) { 71121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 71221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 71321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 71421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 71521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Generate a cert of version 3. 71621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen *(cert->version.data) = 2; 71721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert->version.len = 1; 71821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 71921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECItem der; 72021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen der.len = 0; 72121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen der.data = NULL; 72221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 72321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Use ASN1 DER to encode the cert. 72421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void* encode_result = SEC_ASN1EncodeItem( 72521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate)); 72621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!encode_result) { 72721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 72821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 72921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 73021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 73121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Allocate space to contain the signed cert. 73221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECItem* result = SECITEM_AllocItem(arena, NULL, 0); 73321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!result) { 73421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 73521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 73621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 73721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 73821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Sign the ASN1 encoded cert and save it to |result|. 73921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rv = SEC_DerSignData(arena, result, der.data, der.len, key->key(), algo_id); 74021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != SECSuccess) { 74121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 74221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return NULL; 74321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 74421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 74521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Save the signed result to the cert. 74621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert->derCert = *result; 74721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 74821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen X509Certificate* x509_cert = 74921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CreateFromHandle(cert, SOURCE_LONE_CERT_IMPORT, OSCertHandles()); 75021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(cert); 75121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return x509_cert; 75221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 75321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 754c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const { 755c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dns_names->clear(); 756c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 757c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Compare with CERT_VerifyCertName(). 758c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetCertSubjectAltNamesOfType(cert_handle_, certDNSName, dns_names); 759c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 760c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (dns_names->empty()) 761c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott dns_names->push_back(subject_.common_name); 762c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 763c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 764c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint X509Certificate::Verify(const std::string& hostname, 765c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int flags, 766c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CertVerifyResult* verify_result) const { 767c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->Reset(); 768c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 769ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (IsBlacklisted()) { 770ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verify_result->cert_status |= CERT_STATUS_REVOKED; 771ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ERR_CERT_REVOKED; 772ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } 773ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 774c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure that the hostname matches with the common name of the cert. 775c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str()); 776c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != SECSuccess) 777c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID; 778c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 779c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Make sure that the cert is valid now. 780c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECCertTimeValidity validity = CERT_CheckCertValidTimes( 781c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cert_handle_, PR_Now(), PR_TRUE); 782c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (validity != secCertTimeValid) 783c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->cert_status |= CERT_STATUS_DATE_INVALID; 784c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 785c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTValOutParam cvout[3]; 786c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cvout_index = 0; 787c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].type = cert_po_certList; 788c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].value.pointer.chain = NULL; 789c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cvout_cert_list_index = cvout_index; 790c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout_index++; 791ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cvout[cvout_index].type = cert_po_trustAnchor; 792ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cvout[cvout_index].value.pointer.cert = NULL; 793ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int cvout_trust_anchor_index = cvout_index; 794ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cvout_index++; 795c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].type = cert_po_end; 796c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScopedCERTValOutParam scoped_cvout(cvout); 797c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 798c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED); 799c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (check_revocation) { 800c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED; 801c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 802c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EV requires revocation checking. 803c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott flags &= ~VERIFY_EV_CERT; 804c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 805c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott status = PKIXVerifyCert(cert_handle_, check_revocation, NULL, 0, cvout); 806c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != SECSuccess) { 807c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int err = PORT_GetError(); 808c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname 809c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott << " failed err=" << err; 810c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // CERT_PKIXVerifyCert rerports the wrong error code for 811c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // expired certificates (NSS bug 491174) 812c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (err == SEC_ERROR_CERT_NOT_VALID && 813c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott (verify_result->cert_status & CERT_STATUS_DATE_INVALID) != 0) 814c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott err = SEC_ERROR_EXPIRED_CERTIFICATE; 815c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cert_status = MapCertErrorToCertStatus(err); 816c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cert_status) { 817c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->cert_status |= cert_status; 818c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapCertStatusToNetError(verify_result->cert_status); 819c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 820c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // |err| is not a certificate error. 821c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapSecurityError(err); 822c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 823c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 824c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain, 825c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result); 826c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsCertStatusError(verify_result->cert_status)) 827c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapCertStatusToNetError(verify_result->cert_status); 828c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 829ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain, 830ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cvout[cvout_trust_anchor_index].value.pointer.cert, 831ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen &verify_result->public_key_hashes); 832ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 833ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen verify_result->is_issued_by_known_root = 834ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert); 835ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 836c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if ((flags & VERIFY_EV_CERT) && VerifyEV()) 837c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott verify_result->cert_status |= CERT_STATUS_IS_EV; 83894ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen 83994ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) { 84094ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID; 84194ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen return MapCertStatusToNetError(verify_result->cert_status); 84294ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen } 84394ea77830f08742eaf1760a8ccc858530cb1c36eKristian Monsen 844c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 845c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 846c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 847dc0f95d653279beabeb9817299e2902918ba123eKristian Monsenbool X509Certificate::VerifyNameMatch(const std::string& hostname) const { 848dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return CERT_VerifyCertName(cert_handle_, hostname.c_str()) == SECSuccess; 849dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen} 850dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen 851c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp 852c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// and nsNSSCertHelper.cpp) to learn how to verify EV certificate. 853c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// TODO(wtc): A possible optimization is that we get the trust anchor from 854c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// the first PKIXVerifyCert call. We look up the EV policy for the trust 855c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// anchor. If the trust anchor has no EV policy, we know the cert isn't EV. 856c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Otherwise, we pass just that EV policy (as opposed to all the EV policies) 857c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// to the second PKIXVerifyCert call. 858c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool X509Certificate::VerifyEV() const { 859ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance(); 860c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 861c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTValOutParam cvout[3]; 862c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cvout_index = 0; 863c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].type = cert_po_trustAnchor; 864c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].value.pointer.cert = NULL; 865c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int cvout_trust_anchor_index = cvout_index; 866c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout_index++; 867c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_index].type = cert_po_end; 868c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ScopedCERTValOutParam scoped_cvout(cvout); 869c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 870c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus status = PKIXVerifyCert(cert_handle_, 871c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott true, 872c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metadata->GetPolicyOIDs(), 873c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott metadata->NumPolicyOIDs(), 874c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout); 875c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (status != SECSuccess) 876c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 877c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 878c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERTCertificate* root_ca = 879c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cvout[cvout_trust_anchor_index].value.pointer.cert; 880c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (root_ca == NULL) 881c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 882c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SHA1Fingerprint fingerprint = 883c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott X509Certificate::CalculateFingerprint(root_ca); 884c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECOidTag ev_policy_tag = SEC_OID_UNKNOWN; 885c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!metadata->GetPolicyOID(fingerprint, &ev_policy_tag)) 886c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 887c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 888c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!CheckCertPolicies(cert_handle_, ev_policy_tag)) 889c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 890c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 891c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 892c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 893c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 89421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool X509Certificate::GetDEREncoded(std::string* encoded) { 89521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (!cert_handle_->derCert.len) 89621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 89721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen encoded->clear(); 89821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen encoded->append(reinterpret_cast<char*>(cert_handle_->derCert.data), 89921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen cert_handle_->derCert.len); 90021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 90121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 90221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 903c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 904731df977c0511bca2206b5f333555b1205ff1f43Iain Merrickbool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a, 905731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick X509Certificate::OSCertHandle b) { 906731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick DCHECK(a && b); 907731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (a == b) 908731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return true; 909731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick return a->derCert.len == b->derCert.len && 910731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0; 911731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick} 912731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick 913731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick// static 914c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottX509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes( 915c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* data, int length) { 9163345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (length < 0) 9173345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return NULL; 9183345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 919ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crypto::EnsureNSSInit(); 920c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 921c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!NSS_IsInitialized()) 922c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return NULL; 923c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 9243345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECItem der_cert; 9253345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data)); 9263345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick der_cert.len = length; 9273345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick der_cert.type = siDERCertBuffer; 928c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 929c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch // Parse into a certificate structure. 9303345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL, 9313345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick PR_FALSE, PR_TRUE); 9323345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick} 9333345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9343345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick// static 9353345a6884c488ff3a535c2c9acdd33d74b37e311Iain MerrickX509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes( 9363345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick const char* data, int length, Format format) { 9373345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OSCertHandles results; 9383345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (length < 0) 9393345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return results; 9403345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 941ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crypto::EnsureNSSInit(); 9423345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9433345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (!NSS_IsInitialized()) 9443345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return results; 9453345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9463345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick switch (format) { 9473345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case FORMAT_SINGLE_CERTIFICATE: { 9483345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick OSCertHandle handle = CreateOSCertHandleFromBytes(data, length); 9493345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (handle) 9503345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick results.push_back(handle); 9513345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 9523345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 9533345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick case FORMAT_PKCS7: { 9543345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick // Make a copy since CERT_DecodeCertPackage may modify it 9553345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick std::vector<char> data_copy(data, data + length); 9563345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9573345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick SECStatus result = CERT_DecodeCertPackage(&data_copy[0], 9583345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick length, CollectCertsCallback, &results); 9593345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick if (result != SECSuccess) 9603345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick results.clear(); 9613345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 9623345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 9633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick default: 9643345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick NOTREACHED() << "Certificate format " << format << " unimplemented"; 9653345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick break; 9663345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick } 9673345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick 9683345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick return results; 969c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 970c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 971c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// static 972c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochX509Certificate::OSCertHandle X509Certificate::DupOSCertHandle( 973c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch OSCertHandle cert_handle) { 974c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return CERT_DupCertificate(cert_handle); 975c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 976c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 977c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 978c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) { 979c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CERT_DestroyCertificate(cert_handle); 980c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 981c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 982c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// static 983c407dc5cd9bdc5668497f21b26b09d988ab439deBen MurdochSHA1Fingerprint X509Certificate::CalculateFingerprint( 984c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OSCertHandle cert) { 985c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch SHA1Fingerprint sha1; 986c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memset(sha1.data, 0, sizeof(sha1.data)); 987c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 988c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(NULL != cert->derCert.data); 989c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(0 != cert->derCert.len); 990c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 991c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data, 992c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott cert->derCert.data, cert->derCert.len); 993c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(rv == SECSuccess); 994c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 995c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return sha1; 996c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 997c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 998ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 999ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenX509Certificate::OSCertHandle 1000ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian MonsenX509Certificate::ReadCertHandleFromPickle(const Pickle& pickle, 1001ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen void** pickle_iter) { 1002ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen const char* data; 1003ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int length; 1004ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!pickle.ReadData(pickle_iter, &data, &length)) 1005ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return NULL; 1006ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1007ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return CreateOSCertHandleFromBytes(data, length); 1008ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1009ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1010ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// static 1011ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle, 1012ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen Pickle* pickle) { 1013ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return pickle->WriteData( 1014ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen reinterpret_cast<const char*>(cert_handle->derCert.data), 1015ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen cert_handle->derCert.len); 1016ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 1017ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 1018c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 1019