15d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// found in the LICENSE file.
45d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/cert/test_root_certs.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "net/cert/x509_certificate.h"
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// NSS doesn't currently define CERT_LIST_TAIL.
115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// See https://bugzilla.mozilla.org/show_bug.cgi?id=962413
125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Can be removed once chrome requires NSS version 3.16 to build.
135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#ifndef CERT_LIST_TAIL
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#define CERT_LIST_TAIL(l) ((CERTCertListNode *)PR_LIST_TAIL(&l->list))
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#endif
165d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace chromeos {
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
195d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)namespace {
205d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)struct ChainVerifyArgs {
225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CertVerifyProcChromeOS* cert_verify_proc;
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  const net::CertificateList& additional_trust_anchors;
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)};
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CertVerifyProcChromeOS::CertVerifyProcChromeOS() {}
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CertVerifyProcChromeOS::CertVerifyProcChromeOS(
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    crypto::ScopedPK11Slot public_slot) {
325f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // Only the software slot is passed, since that is the only one where user
335f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  // trust settings are stored.
345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)  profile_filter_.Init(
355f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)      public_slot.Pass(), crypto::ScopedPK11Slot(), crypto::ScopedPK11Slot());
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)CertVerifyProcChromeOS::~CertVerifyProcChromeOS() {}
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)int CertVerifyProcChromeOS::VerifyInternal(
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    net::X509Certificate* cert,
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const std::string& hostname,
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    int flags,
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    net::CRLSet* crl_set,
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const net::CertificateList& additional_trust_anchors,
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    net::CertVerifyResult* verify_result) {
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ChainVerifyArgs chain_verify_args = {this, additional_trust_anchors};
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CERTChainVerifyCallback chain_verify_callback;
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chain_verify_callback.isChainValid =
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      &CertVerifyProcChromeOS::IsChainValidFunc;
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  chain_verify_callback.isChainValidArg =
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      static_cast<void*>(&chain_verify_args);
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return VerifyInternalImpl(cert,
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            hostname,
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            flags,
585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            crl_set,
595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            additional_trust_anchors,
605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            &chain_verify_callback,
615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                            verify_result);
625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// static
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)SECStatus CertVerifyProcChromeOS::IsChainValidFunc(
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    void* is_chain_valid_arg,
675d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    const CERTCertList* current_chain,
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    PRBool* chain_ok) {
695d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  ChainVerifyArgs* args = static_cast<ChainVerifyArgs*>(is_chain_valid_arg);
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  CERTCertificate* cert = CERT_LIST_TAIL(current_chain)->cert;
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (net::TestRootCerts::HasInstance()) {
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (net::TestRootCerts::GetInstance()->Contains(cert)) {
745d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Certs in the TestRootCerts are not stored in any slot, and thus would
755d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // not be allowed by the profile_filter. This should only be hit in tests.
765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DVLOG(3) << cert->subjectName << " is a TestRootCert";
775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *chain_ok = PR_TRUE;
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return SECSuccess;
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  for (net::CertificateList::const_iterator i =
835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)           args->additional_trust_anchors.begin();
845d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       i != args->additional_trust_anchors.end();
855d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)       ++i) {
865d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    if (net::X509Certificate::IsSameOSCert(cert, (*i)->os_cert_handle())) {
875d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // Certs in the additional_trust_anchors should always be allowed, even if
885d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // they aren't stored in a slot that would be allowed by the
895d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      // profile_filter.
905d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      DVLOG(3) << cert->subjectName << " is an additional_trust_anchor";
915d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      *chain_ok = PR_TRUE;
925d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      return SECSuccess;
935d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    }
945d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  }
955d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // TODO(mattm): If crbug.com/334384 is fixed to allow setting trust
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // properly when the same cert is in multiple slots, this would also need
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  // updating to check the per-slot trust values.
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  *chain_ok = args->cert_verify_proc->profile_filter_.IsCertAllowed(cert)
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  ? PR_TRUE
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                  : PR_FALSE;
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  DVLOG(3) << cert->subjectName << " is " << (*chain_ok ? "ok" : "not ok");
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return SECSuccess;
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}  // namespace chromeos
107