1// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/x509_certificate.h"
6
7#include <cert.h>
8#include <cryptohi.h>
9#include <keyhi.h>
10#include <nss.h>
11#include <pk11pub.h>
12#include <prerror.h>
13#include <prtime.h>
14#include <secder.h>
15#include <secerr.h>
16#include <sechash.h>
17#include <sslerr.h>
18
19#include "base/logging.h"
20#include "base/memory/scoped_ptr.h"
21#include "base/pickle.h"
22#include "base/time.h"
23#include "crypto/nss_util.h"
24#include "crypto/rsa_private_key.h"
25#include "net/base/cert_status_flags.h"
26#include "net/base/cert_verify_result.h"
27#include "net/base/ev_root_ca_metadata.h"
28#include "net/base/net_errors.h"
29
30namespace net {
31
32namespace {
33
34class ScopedCERTCertificatePolicies {
35 public:
36  explicit ScopedCERTCertificatePolicies(CERTCertificatePolicies* policies)
37      : policies_(policies) {}
38
39  ~ScopedCERTCertificatePolicies() {
40    if (policies_)
41      CERT_DestroyCertificatePoliciesExtension(policies_);
42  }
43
44 private:
45  CERTCertificatePolicies* policies_;
46
47  DISALLOW_COPY_AND_ASSIGN(ScopedCERTCertificatePolicies);
48};
49
50// ScopedCERTValOutParam manages destruction of values in the CERTValOutParam
51// array that cvout points to.  cvout must be initialized as passed to
52// CERT_PKIXVerifyCert, so that the array must be terminated with
53// cert_po_end type.
54// When it goes out of scope, it destroys values of cert_po_trustAnchor
55// and cert_po_certList types, but doesn't release the array itself.
56class ScopedCERTValOutParam {
57 public:
58  explicit ScopedCERTValOutParam(CERTValOutParam* cvout)
59      : cvout_(cvout) {}
60
61  ~ScopedCERTValOutParam() {
62    if (cvout_ == NULL)
63      return;
64    for (CERTValOutParam *p = cvout_; p->type != cert_po_end; p++) {
65      switch (p->type) {
66        case cert_po_trustAnchor:
67          if (p->value.pointer.cert) {
68            CERT_DestroyCertificate(p->value.pointer.cert);
69            p->value.pointer.cert = NULL;
70          }
71          break;
72        case cert_po_certList:
73          if (p->value.pointer.chain) {
74            CERT_DestroyCertList(p->value.pointer.chain);
75            p->value.pointer.chain = NULL;
76          }
77          break;
78        default:
79          break;
80      }
81    }
82  }
83
84 private:
85  CERTValOutParam* cvout_;
86
87  DISALLOW_COPY_AND_ASSIGN(ScopedCERTValOutParam);
88};
89
90// Map PORT_GetError() return values to our network error codes.
91int MapSecurityError(int err) {
92  switch (err) {
93    case PR_DIRECTORY_LOOKUP_ERROR:  // DNS lookup error.
94      return ERR_NAME_NOT_RESOLVED;
95    case SEC_ERROR_INVALID_ARGS:
96      return ERR_INVALID_ARGUMENT;
97    case SSL_ERROR_BAD_CERT_DOMAIN:
98      return ERR_CERT_COMMON_NAME_INVALID;
99    case SEC_ERROR_INVALID_TIME:
100    case SEC_ERROR_EXPIRED_CERTIFICATE:
101    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
102      return ERR_CERT_DATE_INVALID;
103    case SEC_ERROR_UNKNOWN_ISSUER:
104    case SEC_ERROR_UNTRUSTED_ISSUER:
105    case SEC_ERROR_CA_CERT_INVALID:
106      return ERR_CERT_AUTHORITY_INVALID;
107    case SEC_ERROR_REVOKED_CERTIFICATE:
108    case SEC_ERROR_UNTRUSTED_CERT:  // Treat as revoked.
109      return ERR_CERT_REVOKED;
110    case SEC_ERROR_BAD_DER:
111    case SEC_ERROR_BAD_SIGNATURE:
112    case SEC_ERROR_CERT_NOT_VALID:
113    // TODO(port): add an ERR_CERT_WRONG_USAGE error code.
114    case SEC_ERROR_CERT_USAGES_INVALID:
115    case SEC_ERROR_INADEQUATE_KEY_USAGE:
116    case SEC_ERROR_INADEQUATE_CERT_TYPE:
117    case SEC_ERROR_POLICY_VALIDATION_FAILED:
118    case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
119    case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
120    case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
121    case SEC_ERROR_EXTENSION_VALUE_INVALID:
122      return ERR_CERT_INVALID;
123    default:
124      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
125      return ERR_FAILED;
126  }
127}
128
129// Map PORT_GetError() return values to our cert status flags.
130int MapCertErrorToCertStatus(int err) {
131  switch (err) {
132    case SSL_ERROR_BAD_CERT_DOMAIN:
133      return CERT_STATUS_COMMON_NAME_INVALID;
134    case SEC_ERROR_INVALID_TIME:
135    case SEC_ERROR_EXPIRED_CERTIFICATE:
136    case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
137      return CERT_STATUS_DATE_INVALID;
138    case SEC_ERROR_UNKNOWN_ISSUER:
139    case SEC_ERROR_UNTRUSTED_ISSUER:
140    case SEC_ERROR_CA_CERT_INVALID:
141      return CERT_STATUS_AUTHORITY_INVALID;
142    // TODO(port): map CERT_STATUS_NO_REVOCATION_MECHANISM.
143    case SEC_ERROR_OCSP_BAD_HTTP_RESPONSE:
144    case SEC_ERROR_OCSP_SERVER_ERROR:
145      return CERT_STATUS_UNABLE_TO_CHECK_REVOCATION;
146    case SEC_ERROR_REVOKED_CERTIFICATE:
147    case SEC_ERROR_UNTRUSTED_CERT:  // Treat as revoked.
148      return CERT_STATUS_REVOKED;
149    case SEC_ERROR_BAD_DER:
150    case SEC_ERROR_BAD_SIGNATURE:
151    case SEC_ERROR_CERT_NOT_VALID:
152    // TODO(port): add a CERT_STATUS_WRONG_USAGE error code.
153    case SEC_ERROR_CERT_USAGES_INVALID:
154    case SEC_ERROR_INADEQUATE_KEY_USAGE:  // Key usage.
155    case SEC_ERROR_INADEQUATE_CERT_TYPE:  // Extended key usage and whether
156                                          // the certificate is a CA.
157    case SEC_ERROR_POLICY_VALIDATION_FAILED:
158    case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
159    case SEC_ERROR_PATH_LEN_CONSTRAINT_INVALID:
160    case SEC_ERROR_UNKNOWN_CRITICAL_EXTENSION:
161    case SEC_ERROR_EXTENSION_VALUE_INVALID:
162      return CERT_STATUS_INVALID;
163    default:
164      return 0;
165  }
166}
167
168// Saves some information about the certificate chain cert_list in
169// *verify_result.  The caller MUST initialize *verify_result before calling
170// this function.
171// Note that cert_list[0] is the end entity certificate and cert_list doesn't
172// contain the root CA certificate.
173void GetCertChainInfo(CERTCertList* cert_list,
174                      CertVerifyResult* verify_result) {
175  // NOTE: Using a NSS library before 3.12.3.1 will crash below.  To see the
176  // NSS version currently in use:
177  // 1. use ldd on the chrome executable for NSS's location (ie. libnss3.so*)
178  // 2. use ident libnss3.so* for the library's version
179  DCHECK(cert_list);
180  int i = 0;
181  for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
182       !CERT_LIST_END(node, cert_list);
183       node = CERT_LIST_NEXT(node), i++) {
184    SECAlgorithmID& signature = node->cert->signature;
185    SECOidTag oid_tag = SECOID_FindOIDTag(&signature.algorithm);
186    switch (oid_tag) {
187      case SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION:
188        verify_result->has_md5 = true;
189        if (i != 0)
190          verify_result->has_md5_ca = true;
191        break;
192      case SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION:
193        verify_result->has_md2 = true;
194        if (i != 0)
195          verify_result->has_md2_ca = true;
196        break;
197      case SEC_OID_PKCS1_MD4_WITH_RSA_ENCRYPTION:
198        verify_result->has_md4 = true;
199        break;
200      default:
201        break;
202    }
203  }
204}
205
206// IsKnownRoot returns true if the given certificate is one that we believe
207// is a standard (as opposed to user-installed) root.
208bool IsKnownRoot(CERTCertificate* root) {
209  if (!root->slot)
210    return false;
211
212  // This magic name is taken from
213  // http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/nss/lib/ckfw/builtins/constants.c&rev=1.13&mark=86,89#79
214  return 0 == strcmp(PK11_GetSlotName(root->slot),
215                     "NSS Builtin Objects");
216}
217
218typedef char* (*CERTGetNameFunc)(CERTName* name);
219
220void ParsePrincipal(CERTName* name,
221                    CertPrincipal* principal) {
222  // TODO(jcampan): add business_category and serial_number.
223  // TODO(wtc): NSS has the CERT_GetOrgName, CERT_GetOrgUnitName, and
224  // CERT_GetDomainComponentName functions, but they return only the most
225  // general (the first) RDN.  NSS doesn't have a function for the street
226  // address.
227  static const SECOidTag kOIDs[] = {
228      SEC_OID_AVA_STREET_ADDRESS,
229      SEC_OID_AVA_ORGANIZATION_NAME,
230      SEC_OID_AVA_ORGANIZATIONAL_UNIT_NAME,
231      SEC_OID_AVA_DC };
232
233  std::vector<std::string>* values[] = {
234      &principal->street_addresses,
235      &principal->organization_names,
236      &principal->organization_unit_names,
237      &principal->domain_components };
238  DCHECK(arraysize(kOIDs) == arraysize(values));
239
240  CERTRDN** rdns = name->rdns;
241  for (size_t rdn = 0; rdns[rdn]; ++rdn) {
242    CERTAVA** avas = rdns[rdn]->avas;
243    for (size_t pair = 0; avas[pair] != 0; ++pair) {
244      SECOidTag tag = CERT_GetAVATag(avas[pair]);
245      for (size_t oid = 0; oid < arraysize(kOIDs); ++oid) {
246        if (kOIDs[oid] == tag) {
247          SECItem* decode_item = CERT_DecodeAVAValue(&avas[pair]->value);
248          if (!decode_item)
249            break;
250          // TODO(wtc): Pass decode_item to CERT_RFC1485_EscapeAndQuote.
251          std::string value(reinterpret_cast<char*>(decode_item->data),
252                            decode_item->len);
253          values[oid]->push_back(value);
254          SECITEM_FreeItem(decode_item, PR_TRUE);
255          break;
256        }
257      }
258    }
259  }
260
261  // Get CN, L, S, and C.
262  CERTGetNameFunc get_name_funcs[4] = {
263      CERT_GetCommonName, CERT_GetLocalityName,
264      CERT_GetStateName, CERT_GetCountryName };
265  std::string* single_values[4] = {
266      &principal->common_name, &principal->locality_name,
267      &principal->state_or_province_name, &principal->country_name };
268  for (size_t i = 0; i < arraysize(get_name_funcs); ++i) {
269    char* value = get_name_funcs[i](name);
270    if (value) {
271      single_values[i]->assign(value);
272      PORT_Free(value);
273    }
274  }
275}
276
277void ParseDate(SECItem* der_date, base::Time* result) {
278  PRTime prtime;
279  SECStatus rv = DER_DecodeTimeChoice(&prtime, der_date);
280  DCHECK(rv == SECSuccess);
281  *result = crypto::PRTimeToBaseTime(prtime);
282}
283
284void GetCertSubjectAltNamesOfType(X509Certificate::OSCertHandle cert_handle,
285                                  CERTGeneralNameType name_type,
286                                  std::vector<std::string>* result) {
287  // For future extension: We only support general names of types
288  // RFC822Name, DNSName or URI.
289  DCHECK(name_type == certRFC822Name ||
290         name_type == certDNSName ||
291         name_type == certURI);
292
293  SECItem alt_name;
294  SECStatus rv = CERT_FindCertExtension(cert_handle,
295      SEC_OID_X509_SUBJECT_ALT_NAME, &alt_name);
296  if (rv != SECSuccess)
297    return;
298
299  PRArenaPool* arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
300  DCHECK(arena != NULL);
301
302  CERTGeneralName* alt_name_list;
303  alt_name_list = CERT_DecodeAltNameExtension(arena, &alt_name);
304  SECITEM_FreeItem(&alt_name, PR_FALSE);
305
306  CERTGeneralName* name = alt_name_list;
307  while (name) {
308    // All of the general name types we support are encoded as
309    // IA5String. In general, we should be switching off
310    // |name->type| and doing type-appropriate conversions.
311    if (name->type == name_type) {
312      unsigned char* p = name->name.other.data;
313      int len = name->name.other.len;
314      std::string value = std::string(reinterpret_cast<char*>(p), len);
315      result->push_back(value);
316    }
317    name = CERT_GetNextGeneralName(name);
318    if (name == alt_name_list)
319      break;
320  }
321  PORT_FreeArena(arena, PR_FALSE);
322}
323
324// Forward declarations.
325SECStatus RetryPKIXVerifyCertWithWorkarounds(
326    X509Certificate::OSCertHandle cert_handle, int num_policy_oids,
327    std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout);
328SECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle);
329
330// Call CERT_PKIXVerifyCert for the cert_handle.
331// Verification results are stored in an array of CERTValOutParam.
332// If policy_oids is not NULL and num_policy_oids is positive, policies
333// are also checked.
334// Caller must initialize cvout before calling this function.
335SECStatus PKIXVerifyCert(X509Certificate::OSCertHandle cert_handle,
336                         bool check_revocation,
337                         const SECOidTag* policy_oids,
338                         int num_policy_oids,
339                         CERTValOutParam* cvout) {
340  bool use_crl = check_revocation;
341  bool use_ocsp = check_revocation;
342
343  // These CAs have multiple keys, which trigger two bugs in NSS's CRL code.
344  // 1. NSS may use one key to verify a CRL signed with another key,
345  //    incorrectly concluding that the CRL's signature is invalid.
346  //    Hopefully this bug will be fixed in NSS 3.12.9.
347  // 2. NSS considers all certificates issued by the CA as revoked when it
348  //    receives a CRL with an invalid signature.  This overly strict policy
349  //    has been relaxed in NSS 3.12.7.  See
350  //    https://bugzilla.mozilla.org/show_bug.cgi?id=562542.
351  // So we have to turn off CRL checking for these CAs.  See
352  // http://crbug.com/55695.
353  static const char* const kMultipleKeyCA[] = {
354    "CN=Microsoft Secure Server Authority,"
355    "DC=redmond,DC=corp,DC=microsoft,DC=com",
356    "CN=Microsoft Secure Server Authority",
357  };
358
359  if (!NSS_VersionCheck("3.12.7")) {
360    for (size_t i = 0; i < arraysize(kMultipleKeyCA); ++i) {
361      if (strcmp(cert_handle->issuerName, kMultipleKeyCA[i]) == 0) {
362        use_crl = false;
363        break;
364      }
365    }
366  }
367
368  PRUint64 revocation_method_flags =
369      CERT_REV_M_DO_NOT_TEST_USING_THIS_METHOD |
370      CERT_REV_M_ALLOW_NETWORK_FETCHING |
371      CERT_REV_M_IGNORE_IMPLICIT_DEFAULT_SOURCE |
372      CERT_REV_M_IGNORE_MISSING_FRESH_INFO |
373      CERT_REV_M_STOP_TESTING_ON_FRESH_INFO;
374  PRUint64 revocation_method_independent_flags =
375      CERT_REV_MI_TEST_ALL_LOCAL_INFORMATION_FIRST;
376  if (policy_oids && num_policy_oids > 0) {
377    // EV verification requires revocation checking.  Consider the certificate
378    // revoked if we don't have revocation info.
379    // TODO(wtc): Add a bool parameter to expressly specify we're doing EV
380    // verification or we want strict revocation flags.
381    revocation_method_flags |= CERT_REV_M_REQUIRE_INFO_ON_MISSING_SOURCE;
382    revocation_method_independent_flags |=
383        CERT_REV_MI_REQUIRE_SOME_FRESH_INFO_AVAILABLE;
384  } else {
385    revocation_method_flags |= CERT_REV_M_SKIP_TEST_ON_MISSING_SOURCE;
386    revocation_method_independent_flags |=
387        CERT_REV_MI_NO_OVERALL_INFO_REQUIREMENT;
388  }
389  PRUint64 method_flags[2];
390  method_flags[cert_revocation_method_crl] = revocation_method_flags;
391  method_flags[cert_revocation_method_ocsp] = revocation_method_flags;
392
393  if (use_crl) {
394    method_flags[cert_revocation_method_crl] |=
395        CERT_REV_M_TEST_USING_THIS_METHOD;
396  }
397  if (use_ocsp) {
398    method_flags[cert_revocation_method_ocsp] |=
399        CERT_REV_M_TEST_USING_THIS_METHOD;
400  }
401
402  CERTRevocationMethodIndex preferred_revocation_methods[1];
403  if (use_ocsp) {
404    preferred_revocation_methods[0] = cert_revocation_method_ocsp;
405  } else {
406    preferred_revocation_methods[0] = cert_revocation_method_crl;
407  }
408
409  CERTRevocationFlags revocation_flags;
410  revocation_flags.leafTests.number_of_defined_methods =
411      arraysize(method_flags);
412  revocation_flags.leafTests.cert_rev_flags_per_method = method_flags;
413  revocation_flags.leafTests.number_of_preferred_methods =
414      arraysize(preferred_revocation_methods);
415  revocation_flags.leafTests.preferred_methods = preferred_revocation_methods;
416  revocation_flags.leafTests.cert_rev_method_independent_flags =
417      revocation_method_independent_flags;
418
419  revocation_flags.chainTests.number_of_defined_methods =
420      arraysize(method_flags);
421  revocation_flags.chainTests.cert_rev_flags_per_method = method_flags;
422  revocation_flags.chainTests.number_of_preferred_methods =
423      arraysize(preferred_revocation_methods);
424  revocation_flags.chainTests.preferred_methods = preferred_revocation_methods;
425  revocation_flags.chainTests.cert_rev_method_independent_flags =
426      revocation_method_independent_flags;
427
428  std::vector<CERTValInParam> cvin;
429  cvin.reserve(5);
430  CERTValInParam in_param;
431  // No need to set cert_pi_trustAnchors here.
432  in_param.type = cert_pi_revocationFlags;
433  in_param.value.pointer.revocation = &revocation_flags;
434  cvin.push_back(in_param);
435  if (policy_oids && num_policy_oids > 0) {
436    in_param.type = cert_pi_policyOID;
437    in_param.value.arraySize = num_policy_oids;
438    in_param.value.array.oids = policy_oids;
439    cvin.push_back(in_param);
440  }
441  in_param.type = cert_pi_end;
442  cvin.push_back(in_param);
443
444  SECStatus rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer,
445                                     &cvin[0], cvout, NULL);
446  if (rv != SECSuccess) {
447    rv = RetryPKIXVerifyCertWithWorkarounds(cert_handle, num_policy_oids,
448                                            &cvin, cvout);
449  }
450  return rv;
451}
452
453// PKIXVerifyCert calls this function to work around some bugs in
454// CERT_PKIXVerifyCert.  All the arguments of this function are either the
455// arguments or local variables of PKIXVerifyCert.
456SECStatus RetryPKIXVerifyCertWithWorkarounds(
457    X509Certificate::OSCertHandle cert_handle, int num_policy_oids,
458    std::vector<CERTValInParam>* cvin, CERTValOutParam* cvout) {
459  // We call this function when the first CERT_PKIXVerifyCert call in
460  // PKIXVerifyCert failed,  so we initialize |rv| to SECFailure.
461  SECStatus rv = SECFailure;
462  int nss_error = PORT_GetError();
463  CERTValInParam in_param;
464
465  // If we get SEC_ERROR_UNKNOWN_ISSUER, we may be missing an intermediate
466  // CA certificate, so we retry with cert_pi_useAIACertFetch.
467  // cert_pi_useAIACertFetch has several bugs in its error handling and
468  // error reporting (NSS bug 528743), so we don't use it by default.
469  // Note: When building a certificate chain, CERT_PKIXVerifyCert may
470  // incorrectly pick a CA certificate with the same subject name as the
471  // missing intermediate CA certificate, and  fail with the
472  // SEC_ERROR_BAD_SIGNATURE error (NSS bug 524013), so we also retry with
473  // cert_pi_useAIACertFetch on SEC_ERROR_BAD_SIGNATURE.
474  if (nss_error == SEC_ERROR_UNKNOWN_ISSUER ||
475      nss_error == SEC_ERROR_BAD_SIGNATURE) {
476    DCHECK_EQ(cvin->back().type,  cert_pi_end);
477    cvin->pop_back();
478    in_param.type = cert_pi_useAIACertFetch;
479    in_param.value.scalar.b = PR_TRUE;
480    cvin->push_back(in_param);
481    in_param.type = cert_pi_end;
482    cvin->push_back(in_param);
483    rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer,
484                             &(*cvin)[0], cvout, NULL);
485    if (rv == SECSuccess)
486      return rv;
487    int new_nss_error = PORT_GetError();
488    if (new_nss_error == SEC_ERROR_INVALID_ARGS ||
489        new_nss_error == SEC_ERROR_UNKNOWN_AIA_LOCATION_TYPE ||
490        new_nss_error == SEC_ERROR_BAD_HTTP_RESPONSE ||
491        new_nss_error == SEC_ERROR_BAD_LDAP_RESPONSE ||
492        !IS_SEC_ERROR(new_nss_error)) {
493      // Use the original error code because of cert_pi_useAIACertFetch's
494      // bad error reporting.
495      PORT_SetError(nss_error);
496      return rv;
497    }
498    nss_error = new_nss_error;
499  }
500
501  // If an intermediate CA certificate has requireExplicitPolicy in its
502  // policyConstraints extension, CERT_PKIXVerifyCert fails with
503  // SEC_ERROR_POLICY_VALIDATION_FAILED because we didn't specify any
504  // certificate policy (NSS bug 552775).  So we retry with the certificate
505  // policy found in the server certificate.
506  if (nss_error == SEC_ERROR_POLICY_VALIDATION_FAILED &&
507      num_policy_oids == 0) {
508    SECOidTag policy = GetFirstCertPolicy(cert_handle);
509    if (policy != SEC_OID_UNKNOWN) {
510      DCHECK_EQ(cvin->back().type,  cert_pi_end);
511      cvin->pop_back();
512      in_param.type = cert_pi_policyOID;
513      in_param.value.arraySize = 1;
514      in_param.value.array.oids = &policy;
515      cvin->push_back(in_param);
516      in_param.type = cert_pi_end;
517      cvin->push_back(in_param);
518      rv = CERT_PKIXVerifyCert(cert_handle, certificateUsageSSLServer,
519                               &(*cvin)[0], cvout, NULL);
520      if (rv != SECSuccess) {
521        // Use the original error code.
522        PORT_SetError(nss_error);
523      }
524    }
525  }
526
527  return rv;
528}
529
530// Decodes the certificatePolicies extension of the certificate.  Returns
531// NULL if the certificate doesn't have the extension or the extension can't
532// be decoded.  The returned value must be freed with a
533// CERT_DestroyCertificatePoliciesExtension call.
534CERTCertificatePolicies* DecodeCertPolicies(
535    X509Certificate::OSCertHandle cert_handle) {
536  SECItem policy_ext;
537  SECStatus rv = CERT_FindCertExtension(
538      cert_handle, SEC_OID_X509_CERTIFICATE_POLICIES, &policy_ext);
539  if (rv != SECSuccess)
540    return NULL;
541  CERTCertificatePolicies* policies =
542      CERT_DecodeCertificatePoliciesExtension(&policy_ext);
543  SECITEM_FreeItem(&policy_ext, PR_FALSE);
544  return policies;
545}
546
547// Returns the OID tag for the first certificate policy in the certificate's
548// certificatePolicies extension.  Returns SEC_OID_UNKNOWN if the certificate
549// has no certificate policy.
550SECOidTag GetFirstCertPolicy(X509Certificate::OSCertHandle cert_handle) {
551  CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle);
552  if (!policies)
553    return SEC_OID_UNKNOWN;
554  ScopedCERTCertificatePolicies scoped_policies(policies);
555  CERTPolicyInfo* policy_info = policies->policyInfos[0];
556  if (!policy_info)
557    return SEC_OID_UNKNOWN;
558  if (policy_info->oid != SEC_OID_UNKNOWN)
559    return policy_info->oid;
560
561  // The certificate policy is unknown to NSS.  We need to create a dynamic
562  // OID tag for the policy.
563  SECOidData od;
564  od.oid.len = policy_info->policyID.len;
565  od.oid.data = policy_info->policyID.data;
566  od.offset = SEC_OID_UNKNOWN;
567  // NSS doesn't allow us to pass an empty description, so I use a hardcoded,
568  // default description here.  The description doesn't need to be unique for
569  // each OID.
570  od.desc = "a certificate policy";
571  od.mechanism = CKM_INVALID_MECHANISM;
572  od.supportedExtension = INVALID_CERT_EXTENSION;
573  return SECOID_AddEntry(&od);
574}
575
576bool CheckCertPolicies(X509Certificate::OSCertHandle cert_handle,
577                       SECOidTag ev_policy_tag) {
578  CERTCertificatePolicies* policies = DecodeCertPolicies(cert_handle);
579  if (!policies) {
580    LOG(ERROR) << "Cert has no policies extension or extension couldn't be "
581                  "decoded.";
582    return false;
583  }
584  ScopedCERTCertificatePolicies scoped_policies(policies);
585  CERTPolicyInfo** policy_infos = policies->policyInfos;
586  while (*policy_infos != NULL) {
587    CERTPolicyInfo* policy_info = *policy_infos++;
588    SECOidTag oid_tag = policy_info->oid;
589    if (oid_tag == SEC_OID_UNKNOWN)
590      continue;
591    if (oid_tag == ev_policy_tag)
592      return true;
593  }
594  LOG(ERROR) << "No EV Policy Tag";
595  return false;
596}
597
598SECStatus PR_CALLBACK
599CollectCertsCallback(void* arg, SECItem** certs, int num_certs) {
600  X509Certificate::OSCertHandles* results =
601      reinterpret_cast<X509Certificate::OSCertHandles*>(arg);
602
603  for (int i = 0; i < num_certs; ++i) {
604    X509Certificate::OSCertHandle handle =
605        X509Certificate::CreateOSCertHandleFromBytes(
606            reinterpret_cast<char*>(certs[i]->data), certs[i]->len);
607    if (handle)
608      results->push_back(handle);
609  }
610
611  return SECSuccess;
612}
613
614SHA1Fingerprint CertPublicKeyHash(CERTCertificate* cert) {
615  SHA1Fingerprint hash;
616  SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, hash.data,
617                              cert->derPublicKey.data, cert->derPublicKey.len);
618  DCHECK_EQ(rv, SECSuccess);
619  return hash;
620}
621
622void AppendPublicKeyHashes(CERTCertList* cert_list,
623                           CERTCertificate* root_cert,
624                           std::vector<SHA1Fingerprint>* hashes) {
625  for (CERTCertListNode* node = CERT_LIST_HEAD(cert_list);
626       !CERT_LIST_END(node, cert_list);
627       node = CERT_LIST_NEXT(node)) {
628    hashes->push_back(CertPublicKeyHash(node->cert));
629  }
630  hashes->push_back(CertPublicKeyHash(root_cert));
631}
632
633}  // namespace
634
635void X509Certificate::Initialize() {
636  ParsePrincipal(&cert_handle_->subject, &subject_);
637  ParsePrincipal(&cert_handle_->issuer, &issuer_);
638
639  ParseDate(&cert_handle_->validity.notBefore, &valid_start_);
640  ParseDate(&cert_handle_->validity.notAfter, &valid_expiry_);
641
642  fingerprint_ = CalculateFingerprint(cert_handle_);
643
644  serial_number_ = std::string(
645      reinterpret_cast<char*>(cert_handle_->serialNumber.data),
646      cert_handle_->serialNumber.len);
647  // Remove leading zeros.
648  while (serial_number_.size() > 1 && serial_number_[0] == 0)
649    serial_number_ = serial_number_.substr(1, serial_number_.size() - 1);
650}
651
652// static
653X509Certificate* X509Certificate::CreateSelfSigned(
654    crypto::RSAPrivateKey* key,
655    const std::string& subject,
656    uint32 serial_number,
657    base::TimeDelta valid_duration) {
658  DCHECK(key);
659
660  // Create info about public key.
661  CERTSubjectPublicKeyInfo* spki =
662      SECKEY_CreateSubjectPublicKeyInfo(key->public_key());
663  if (!spki)
664    return NULL;
665
666  // Create the certificate request.
667  CERTName* subject_name =
668      CERT_AsciiToName(const_cast<char*>(subject.c_str()));
669  CERTCertificateRequest* cert_request =
670      CERT_CreateCertificateRequest(subject_name, spki, NULL);
671  SECKEY_DestroySubjectPublicKeyInfo(spki);
672
673  if (!cert_request) {
674    PRErrorCode prerr = PR_GetError();
675    LOG(ERROR) << "Failed to create certificate request: " << prerr;
676    CERT_DestroyName(subject_name);
677    return NULL;
678  }
679
680  PRTime now = PR_Now();
681  PRTime not_after = now + valid_duration.InMicroseconds();
682
683  // Note that the time is now in micro-second unit.
684  CERTValidity* validity = CERT_CreateValidity(now, not_after);
685  CERTCertificate* cert = CERT_CreateCertificate(serial_number, subject_name,
686                                                 validity, cert_request);
687  if (!cert) {
688    PRErrorCode prerr = PR_GetError();
689    LOG(ERROR) << "Failed to create certificate: " << prerr;
690  }
691
692  // Cleanup for resources used to generate the cert.
693  CERT_DestroyName(subject_name);
694  CERT_DestroyValidity(validity);
695  CERT_DestroyCertificateRequest(cert_request);
696
697  // Sign the cert here. The logic of this method references SignCert() in NSS
698  // utility certutil: http://mxr.mozilla.org/security/ident?i=SignCert.
699
700  // |arena| is used to encode the cert.
701  PRArenaPool* arena = cert->arena;
702  SECOidTag algo_id = SEC_GetSignatureAlgorithmOidTag(key->key()->keyType,
703                                                      SEC_OID_SHA1);
704  if (algo_id == SEC_OID_UNKNOWN) {
705    CERT_DestroyCertificate(cert);
706    return NULL;
707  }
708
709  SECStatus rv = SECOID_SetAlgorithmID(arena, &cert->signature, algo_id, 0);
710  if (rv != SECSuccess) {
711    CERT_DestroyCertificate(cert);
712    return NULL;
713  }
714
715  // Generate a cert of version 3.
716  *(cert->version.data) = 2;
717  cert->version.len = 1;
718
719  SECItem der;
720  der.len = 0;
721  der.data = NULL;
722
723  // Use ASN1 DER to encode the cert.
724  void* encode_result = SEC_ASN1EncodeItem(
725      arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate));
726  if (!encode_result) {
727    CERT_DestroyCertificate(cert);
728    return NULL;
729  }
730
731  // Allocate space to contain the signed cert.
732  SECItem* result = SECITEM_AllocItem(arena, NULL, 0);
733  if (!result) {
734    CERT_DestroyCertificate(cert);
735    return NULL;
736  }
737
738  // Sign the ASN1 encoded cert and save it to |result|.
739  rv = SEC_DerSignData(arena, result, der.data, der.len, key->key(), algo_id);
740  if (rv != SECSuccess) {
741    CERT_DestroyCertificate(cert);
742    return NULL;
743  }
744
745  // Save the signed result to the cert.
746  cert->derCert = *result;
747
748  X509Certificate* x509_cert =
749      CreateFromHandle(cert, SOURCE_LONE_CERT_IMPORT, OSCertHandles());
750  CERT_DestroyCertificate(cert);
751  return x509_cert;
752}
753
754void X509Certificate::GetDNSNames(std::vector<std::string>* dns_names) const {
755  dns_names->clear();
756
757  // Compare with CERT_VerifyCertName().
758  GetCertSubjectAltNamesOfType(cert_handle_, certDNSName, dns_names);
759
760  if (dns_names->empty())
761    dns_names->push_back(subject_.common_name);
762}
763
764int X509Certificate::Verify(const std::string& hostname,
765                            int flags,
766                            CertVerifyResult* verify_result) const {
767  verify_result->Reset();
768
769  if (IsBlacklisted()) {
770    verify_result->cert_status |= CERT_STATUS_REVOKED;
771    return ERR_CERT_REVOKED;
772  }
773
774  // Make sure that the hostname matches with the common name of the cert.
775  SECStatus status = CERT_VerifyCertName(cert_handle_, hostname.c_str());
776  if (status != SECSuccess)
777    verify_result->cert_status |= CERT_STATUS_COMMON_NAME_INVALID;
778
779  // Make sure that the cert is valid now.
780  SECCertTimeValidity validity = CERT_CheckCertValidTimes(
781      cert_handle_, PR_Now(), PR_TRUE);
782  if (validity != secCertTimeValid)
783    verify_result->cert_status |= CERT_STATUS_DATE_INVALID;
784
785  CERTValOutParam cvout[3];
786  int cvout_index = 0;
787  cvout[cvout_index].type = cert_po_certList;
788  cvout[cvout_index].value.pointer.chain = NULL;
789  int cvout_cert_list_index = cvout_index;
790  cvout_index++;
791  cvout[cvout_index].type = cert_po_trustAnchor;
792  cvout[cvout_index].value.pointer.cert = NULL;
793  int cvout_trust_anchor_index = cvout_index;
794  cvout_index++;
795  cvout[cvout_index].type = cert_po_end;
796  ScopedCERTValOutParam scoped_cvout(cvout);
797
798  bool check_revocation = (flags & VERIFY_REV_CHECKING_ENABLED);
799  if (check_revocation) {
800    verify_result->cert_status |= CERT_STATUS_REV_CHECKING_ENABLED;
801  } else {
802    // EV requires revocation checking.
803    flags &= ~VERIFY_EV_CERT;
804  }
805  status = PKIXVerifyCert(cert_handle_, check_revocation, NULL, 0, cvout);
806  if (status != SECSuccess) {
807    int err = PORT_GetError();
808    LOG(ERROR) << "CERT_PKIXVerifyCert for " << hostname
809               << " failed err=" << err;
810    // CERT_PKIXVerifyCert rerports the wrong error code for
811    // expired certificates (NSS bug 491174)
812    if (err == SEC_ERROR_CERT_NOT_VALID &&
813        (verify_result->cert_status & CERT_STATUS_DATE_INVALID) != 0)
814      err = SEC_ERROR_EXPIRED_CERTIFICATE;
815    int cert_status = MapCertErrorToCertStatus(err);
816    if (cert_status) {
817      verify_result->cert_status |= cert_status;
818      return MapCertStatusToNetError(verify_result->cert_status);
819    }
820    // |err| is not a certificate error.
821    return MapSecurityError(err);
822  }
823
824  GetCertChainInfo(cvout[cvout_cert_list_index].value.pointer.chain,
825                   verify_result);
826  if (IsCertStatusError(verify_result->cert_status))
827    return MapCertStatusToNetError(verify_result->cert_status);
828
829  AppendPublicKeyHashes(cvout[cvout_cert_list_index].value.pointer.chain,
830                        cvout[cvout_trust_anchor_index].value.pointer.cert,
831                        &verify_result->public_key_hashes);
832
833  verify_result->is_issued_by_known_root =
834      IsKnownRoot(cvout[cvout_trust_anchor_index].value.pointer.cert);
835
836  if ((flags & VERIFY_EV_CERT) && VerifyEV())
837    verify_result->cert_status |= CERT_STATUS_IS_EV;
838
839  if (IsPublicKeyBlacklisted(verify_result->public_key_hashes)) {
840    verify_result->cert_status |= CERT_STATUS_AUTHORITY_INVALID;
841    return MapCertStatusToNetError(verify_result->cert_status);
842  }
843
844  return OK;
845}
846
847bool X509Certificate::VerifyNameMatch(const std::string& hostname) const {
848  return CERT_VerifyCertName(cert_handle_, hostname.c_str()) == SECSuccess;
849}
850
851// Studied Mozilla's code (esp. security/manager/ssl/src/nsIdentityChecking.cpp
852// and nsNSSCertHelper.cpp) to learn how to verify EV certificate.
853// TODO(wtc): A possible optimization is that we get the trust anchor from
854// the first PKIXVerifyCert call.  We look up the EV policy for the trust
855// anchor.  If the trust anchor has no EV policy, we know the cert isn't EV.
856// Otherwise, we pass just that EV policy (as opposed to all the EV policies)
857// to the second PKIXVerifyCert call.
858bool X509Certificate::VerifyEV() const {
859  EVRootCAMetadata* metadata = EVRootCAMetadata::GetInstance();
860
861  CERTValOutParam cvout[3];
862  int cvout_index = 0;
863  cvout[cvout_index].type = cert_po_trustAnchor;
864  cvout[cvout_index].value.pointer.cert = NULL;
865  int cvout_trust_anchor_index = cvout_index;
866  cvout_index++;
867  cvout[cvout_index].type = cert_po_end;
868  ScopedCERTValOutParam scoped_cvout(cvout);
869
870  SECStatus status = PKIXVerifyCert(cert_handle_,
871                                    true,
872                                    metadata->GetPolicyOIDs(),
873                                    metadata->NumPolicyOIDs(),
874                                    cvout);
875  if (status != SECSuccess)
876    return false;
877
878  CERTCertificate* root_ca =
879      cvout[cvout_trust_anchor_index].value.pointer.cert;
880  if (root_ca == NULL)
881    return false;
882  SHA1Fingerprint fingerprint =
883      X509Certificate::CalculateFingerprint(root_ca);
884  SECOidTag ev_policy_tag = SEC_OID_UNKNOWN;
885  if (!metadata->GetPolicyOID(fingerprint, &ev_policy_tag))
886    return false;
887
888  if (!CheckCertPolicies(cert_handle_, ev_policy_tag))
889    return false;
890
891  return true;
892}
893
894bool X509Certificate::GetDEREncoded(std::string* encoded) {
895  if (!cert_handle_->derCert.len)
896    return false;
897  encoded->clear();
898  encoded->append(reinterpret_cast<char*>(cert_handle_->derCert.data),
899                  cert_handle_->derCert.len);
900  return true;
901}
902
903// static
904bool X509Certificate::IsSameOSCert(X509Certificate::OSCertHandle a,
905                                   X509Certificate::OSCertHandle b) {
906  DCHECK(a && b);
907  if (a == b)
908    return true;
909  return a->derCert.len == b->derCert.len &&
910      memcmp(a->derCert.data, b->derCert.data, a->derCert.len) == 0;
911}
912
913// static
914X509Certificate::OSCertHandle X509Certificate::CreateOSCertHandleFromBytes(
915    const char* data, int length) {
916  if (length < 0)
917    return NULL;
918
919  crypto::EnsureNSSInit();
920
921  if (!NSS_IsInitialized())
922    return NULL;
923
924  SECItem der_cert;
925  der_cert.data = reinterpret_cast<unsigned char*>(const_cast<char*>(data));
926  der_cert.len  = length;
927  der_cert.type = siDERCertBuffer;
928
929  // Parse into a certificate structure.
930  return CERT_NewTempCertificate(CERT_GetDefaultCertDB(), &der_cert, NULL,
931                                 PR_FALSE, PR_TRUE);
932}
933
934// static
935X509Certificate::OSCertHandles X509Certificate::CreateOSCertHandlesFromBytes(
936    const char* data, int length, Format format) {
937  OSCertHandles results;
938  if (length < 0)
939    return results;
940
941  crypto::EnsureNSSInit();
942
943  if (!NSS_IsInitialized())
944    return results;
945
946  switch (format) {
947    case FORMAT_SINGLE_CERTIFICATE: {
948      OSCertHandle handle = CreateOSCertHandleFromBytes(data, length);
949      if (handle)
950        results.push_back(handle);
951      break;
952    }
953    case FORMAT_PKCS7: {
954      // Make a copy since CERT_DecodeCertPackage may modify it
955      std::vector<char> data_copy(data, data + length);
956
957      SECStatus result = CERT_DecodeCertPackage(&data_copy[0],
958          length, CollectCertsCallback, &results);
959      if (result != SECSuccess)
960        results.clear();
961      break;
962    }
963    default:
964      NOTREACHED() << "Certificate format " << format << " unimplemented";
965      break;
966  }
967
968  return results;
969}
970
971// static
972X509Certificate::OSCertHandle X509Certificate::DupOSCertHandle(
973    OSCertHandle cert_handle) {
974  return CERT_DupCertificate(cert_handle);
975}
976
977// static
978void X509Certificate::FreeOSCertHandle(OSCertHandle cert_handle) {
979  CERT_DestroyCertificate(cert_handle);
980}
981
982// static
983SHA1Fingerprint X509Certificate::CalculateFingerprint(
984    OSCertHandle cert) {
985  SHA1Fingerprint sha1;
986  memset(sha1.data, 0, sizeof(sha1.data));
987
988  DCHECK(NULL != cert->derCert.data);
989  DCHECK(0 != cert->derCert.len);
990
991  SECStatus rv = HASH_HashBuf(HASH_AlgSHA1, sha1.data,
992                              cert->derCert.data, cert->derCert.len);
993  DCHECK(rv == SECSuccess);
994
995  return sha1;
996}
997
998// static
999X509Certificate::OSCertHandle
1000X509Certificate::ReadCertHandleFromPickle(const Pickle& pickle,
1001                                          void** pickle_iter) {
1002  const char* data;
1003  int length;
1004  if (!pickle.ReadData(pickle_iter, &data, &length))
1005    return NULL;
1006
1007  return CreateOSCertHandleFromBytes(data, length);
1008}
1009
1010// static
1011bool X509Certificate::WriteCertHandleToPickle(OSCertHandle cert_handle,
1012                                              Pickle* pickle) {
1013  return pickle->WriteData(
1014      reinterpret_cast<const char*>(cert_handle->derCert.data),
1015      cert_handle->derCert.len);
1016}
1017
1018}  // namespace net
1019