Skip to content

Commit

Permalink
NSS Cros multiprofile: trust roots added by a profile shouldn't apply…
Browse files Browse the repository at this point in the history
… to other profiles.

BUG=218627

Review URL: https://codereview.chromium.org/137553004

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@249928 0039d316-1c4b-4281-b951-d872f2087c98
  • Loading branch information
mattm@chromium.org committed Feb 8, 2014
1 parent 4809dd9 commit f46f6d5
Show file tree
Hide file tree
Showing 25 changed files with 1,578 additions and 63 deletions.
103 changes: 103 additions & 0 deletions chrome/browser/chromeos/net/cert_verify_proc_chromeos.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/chromeos/net/cert_verify_proc_chromeos.h"

#include "net/cert/test_root_certs.h"
#include "net/cert/x509_certificate.h"

// NSS doesn't currently define CERT_LIST_TAIL.
// See https://bugzilla.mozilla.org/show_bug.cgi?id=962413
// Can be removed once chrome requires NSS version 3.16 to build.
#ifndef CERT_LIST_TAIL
#define CERT_LIST_TAIL(l) ((CERTCertListNode *)PR_LIST_TAIL(&l->list))
#endif

namespace chromeos {

namespace {

struct ChainVerifyArgs {
CertVerifyProcChromeOS* cert_verify_proc;
const net::CertificateList& additional_trust_anchors;
};

} // namespace

CertVerifyProcChromeOS::CertVerifyProcChromeOS() {}

CertVerifyProcChromeOS::CertVerifyProcChromeOS(
crypto::ScopedPK11Slot public_slot) {
profile_filter_.Init(public_slot.Pass(), crypto::ScopedPK11Slot());
}

CertVerifyProcChromeOS::~CertVerifyProcChromeOS() {}

int CertVerifyProcChromeOS::VerifyInternal(
net::X509Certificate* cert,
const std::string& hostname,
int flags,
net::CRLSet* crl_set,
const net::CertificateList& additional_trust_anchors,
net::CertVerifyResult* verify_result) {
ChainVerifyArgs chain_verify_args = {this, additional_trust_anchors};

CERTChainVerifyCallback chain_verify_callback;
chain_verify_callback.isChainValid =
&CertVerifyProcChromeOS::IsChainValidFunc;
chain_verify_callback.isChainValidArg =
static_cast<void*>(&chain_verify_args);

return VerifyInternalImpl(cert,
hostname,
flags,
crl_set,
additional_trust_anchors,
&chain_verify_callback,
verify_result);
}

// static
SECStatus CertVerifyProcChromeOS::IsChainValidFunc(
void* is_chain_valid_arg,
const CERTCertList* current_chain,
PRBool* chain_ok) {
ChainVerifyArgs* args = static_cast<ChainVerifyArgs*>(is_chain_valid_arg);
CERTCertificate* cert = CERT_LIST_TAIL(current_chain)->cert;

if (net::TestRootCerts::HasInstance()) {
if (net::TestRootCerts::GetInstance()->Contains(cert)) {
// Certs in the TestRootCerts are not stored in any slot, and thus would
// not be allowed by the profile_filter. This should only be hit in tests.
DVLOG(3) << cert->subjectName << " is a TestRootCert";
*chain_ok = PR_TRUE;
return SECSuccess;
}
}

for (net::CertificateList::const_iterator i =
args->additional_trust_anchors.begin();
i != args->additional_trust_anchors.end();
++i) {
if (net::X509Certificate::IsSameOSCert(cert, (*i)->os_cert_handle())) {
// Certs in the additional_trust_anchors should always be allowed, even if
// they aren't stored in a slot that would be allowed by the
// profile_filter.
DVLOG(3) << cert->subjectName << " is an additional_trust_anchor";
*chain_ok = PR_TRUE;
return SECSuccess;
}
}

// TODO(mattm): If crbug.com/334384 is fixed to allow setting trust
// properly when the same cert is in multiple slots, this would also need
// updating to check the per-slot trust values.
*chain_ok = args->cert_verify_proc->profile_filter_.IsCertAllowed(cert)
? PR_TRUE
: PR_FALSE;
DVLOG(3) << cert->subjectName << " is " << (*chain_ok ? "ok" : "not ok");
return SECSuccess;
}

} // namespace chromeos
59 changes: 59 additions & 0 deletions chrome/browser/chromeos/net/cert_verify_proc_chromeos.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef CHROME_BROWSER_CHROMEOS_NET_CERT_VERIFY_PROC_CHROMEOS_H_
#define CHROME_BROWSER_CHROMEOS_NET_CERT_VERIFY_PROC_CHROMEOS_H_

#include "crypto/scoped_nss_types.h"
#include "net/cert/cert_verify_proc_nss.h"
#include "net/cert/nss_profile_filter_chromeos.h"

namespace chromeos {

// Wrapper around CertVerifyProcNSS which allows filtering trust decisions on a
// per-slot basis.
//
// Note that only the simple case is currently handled (if a slot contains a new
// trust root, that root should not be trusted by CertVerifyProcChromeOS
// instances using other slots). More complicated cases are not handled (like
// two slots adding the same root cert but with different trust values).
class CertVerifyProcChromeOS : public net::CertVerifyProcNSS {
public:
// Creates a CertVerifyProc that doesn't allow any user-provided trust roots.
CertVerifyProcChromeOS();

// Creates a CertVerifyProc that doesn't allow trust roots provided by
// users other than the specified slot.
explicit CertVerifyProcChromeOS(crypto::ScopedPK11Slot public_slot);

protected:
virtual ~CertVerifyProcChromeOS();

private:
// net::CertVerifyProcNSS implementation:
virtual int VerifyInternal(
net::X509Certificate* cert,
const std::string& hostname,
int flags,
net::CRLSet* crl_set,
const net::CertificateList& additional_trust_anchors,
net::CertVerifyResult* verify_result) OVERRIDE;

// Check if the trust root of |current_chain| is allowed.
// |is_chain_valid_arg| is actually a ChainVerifyArgs*, which is used to pass
// state through the NSS CERTChainVerifyCallback.isChainValidArg parameter.
// If the chain is allowed, |*chain_ok| will be set to PR_TRUE.
// If the chain is not allowed, |*chain_ok| is set to PR_FALSE, and this
// function may be called again during a single certificate verification if
// there are multiple possible valid chains.
static SECStatus IsChainValidFunc(void* is_chain_valid_arg,
const CERTCertList* current_chain,
PRBool* chain_ok);

net::NSSProfileFilterChromeOS profile_filter_;
};

} // namespace chromeos

#endif // CHROME_BROWSER_CHROMEOS_NET_CERT_VERIFY_PROC_CHROMEOS_H_
Loading

0 comments on commit f46f6d5

Please sign in to comment.