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 17namespace chromeos { 18 19namespace { 20 21struct ChainVerifyArgs { 22 CertVerifyProcChromeOS* cert_verify_proc; 23 const net::CertificateList& additional_trust_anchors; 24}; 25 26} // namespace 27 28CertVerifyProcChromeOS::CertVerifyProcChromeOS() {} 29 30CertVerifyProcChromeOS::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 38CertVerifyProcChromeOS::~CertVerifyProcChromeOS() {} 39 40int 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 65SECStatus 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