Home | History | Annotate | Download | only in net
      1 // Copyright 2014 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 "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
      6 
      7 #include "net/cert/test_root_certs.h"
      8 #include "net/cert/x509_certificate.h"
      9 
     10 // NSS doesn't currently define CERT_LIST_TAIL.
     11 // See https://bugzilla.mozilla.org/show_bug.cgi?id=962413
     12 // Can be removed once chrome requires NSS version 3.16 to build.
     13 #ifndef CERT_LIST_TAIL
     14 #define CERT_LIST_TAIL(l) ((CERTCertListNode *)PR_LIST_TAIL(&l->list))
     15 #endif
     16 
     17 namespace chromeos {
     18 
     19 namespace {
     20 
     21 struct ChainVerifyArgs {
     22   CertVerifyProcChromeOS* cert_verify_proc;
     23   const net::CertificateList& additional_trust_anchors;
     24 };
     25 
     26 }  // namespace
     27 
     28 CertVerifyProcChromeOS::CertVerifyProcChromeOS() {}
     29 
     30 CertVerifyProcChromeOS::CertVerifyProcChromeOS(
     31     crypto::ScopedPK11Slot public_slot) {
     32   // Only the software slot is passed, since that is the only one where user
     33   // trust settings are stored.
     34   profile_filter_.Init(
     35       public_slot.Pass(), crypto::ScopedPK11Slot(), crypto::ScopedPK11Slot());
     36 }
     37 
     38 CertVerifyProcChromeOS::~CertVerifyProcChromeOS() {}
     39 
     40 int CertVerifyProcChromeOS::VerifyInternal(
     41     net::X509Certificate* cert,
     42     const std::string& hostname,
     43     int flags,
     44     net::CRLSet* crl_set,
     45     const net::CertificateList& additional_trust_anchors,
     46     net::CertVerifyResult* verify_result) {
     47   ChainVerifyArgs chain_verify_args = {this, additional_trust_anchors};
     48 
     49   CERTChainVerifyCallback chain_verify_callback;
     50   chain_verify_callback.isChainValid =
     51       &CertVerifyProcChromeOS::IsChainValidFunc;
     52   chain_verify_callback.isChainValidArg =
     53       static_cast<void*>(&chain_verify_args);
     54 
     55   return VerifyInternalImpl(cert,
     56                             hostname,
     57                             flags,
     58                             crl_set,
     59                             additional_trust_anchors,
     60                             &chain_verify_callback,
     61                             verify_result);
     62 }
     63 
     64 // static
     65 SECStatus CertVerifyProcChromeOS::IsChainValidFunc(
     66     void* is_chain_valid_arg,
     67     const CERTCertList* current_chain,
     68     PRBool* chain_ok) {
     69   ChainVerifyArgs* args = static_cast<ChainVerifyArgs*>(is_chain_valid_arg);
     70   CERTCertificate* cert = CERT_LIST_TAIL(current_chain)->cert;
     71 
     72   if (net::TestRootCerts::HasInstance()) {
     73     if (net::TestRootCerts::GetInstance()->Contains(cert)) {
     74       // Certs in the TestRootCerts are not stored in any slot, and thus would
     75       // not be allowed by the profile_filter. This should only be hit in tests.
     76       DVLOG(3) << cert->subjectName << " is a TestRootCert";
     77       *chain_ok = PR_TRUE;
     78       return SECSuccess;
     79     }
     80   }
     81 
     82   for (net::CertificateList::const_iterator i =
     83            args->additional_trust_anchors.begin();
     84        i != args->additional_trust_anchors.end();
     85        ++i) {
     86     if (net::X509Certificate::IsSameOSCert(cert, (*i)->os_cert_handle())) {
     87       // Certs in the additional_trust_anchors should always be allowed, even if
     88       // they aren't stored in a slot that would be allowed by the
     89       // profile_filter.
     90       DVLOG(3) << cert->subjectName << " is an additional_trust_anchor";
     91       *chain_ok = PR_TRUE;
     92       return SECSuccess;
     93     }
     94   }
     95 
     96   // TODO(mattm): If crbug.com/334384 is fixed to allow setting trust
     97   // properly when the same cert is in multiple slots, this would also need
     98   // updating to check the per-slot trust values.
     99   *chain_ok = args->cert_verify_proc->profile_filter_.IsCertAllowed(cert)
    100                   ? PR_TRUE
    101                   : PR_FALSE;
    102   DVLOG(3) << cert->subjectName << " is " << (*chain_ok ? "ok" : "not ok");
    103   return SECSuccess;
    104 }
    105 
    106 }  // namespace chromeos
    107