1ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// Use of this source code is governed by a BSD-style license that can be 321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// found in the LICENSE file. 421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/test_root_certs.h" 621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include <cert.h> 821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/logging.h" 1021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "base/stl_util-inl.h" 11ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "crypto/nss_util.h" 1221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "net/base/x509_certificate.h" 1321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsennamespace net { 1521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 1621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// TrustEntry is used to store the original CERTCertificate and CERTCertTrust 1721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// for a certificate whose trust status has been changed by the 1821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen// TestRootCerts. 1921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenclass TestRootCerts::TrustEntry { 2021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen public: 2121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Creates a new TrustEntry by incrementing the reference to |certificate| 2221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // and copying |trust|. 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen TrustEntry(CERTCertificate* certificate, CERTCertTrust trust); 2421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen ~TrustEntry(); 2521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertificate* certificate() const { return certificate_; } 2721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust trust() const { return trust_; } 2821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen private: 3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The temporary root certificate. 3121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertificate* certificate_; 3221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // The original trust settings, before |certificate_| was manipulated to 3421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // be a temporarily trusted root. 3521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust trust_; 3621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 3721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DISALLOW_COPY_AND_ASSIGN(TrustEntry); 3821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen}; 3921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTestRootCerts::TrustEntry::TrustEntry(CERTCertificate* certificate, 4121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust trust) 4221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen : certificate_(CERT_DupCertificate(certificate)), 4321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen trust_(trust) { 4421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 4621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTestRootCerts::TrustEntry::~TrustEntry() { 4721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERT_DestroyCertificate(certificate_); 4821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 4921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 5021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::Add(X509Certificate* certificate) { 5121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Preserve the original trust bits so that they can be restored when 5221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // the certificate is removed. 5321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust original_trust; 5421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECStatus rv = CERT_GetCertTrust(certificate->os_cert_handle(), 5521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &original_trust); 5621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != SECSuccess) { 5721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // CERT_GetCertTrust will fail if the certificate does not have any 5821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // particular trust settings associated with it, and attempts to use 5921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // |original_trust| later to restore the original trust settings will not 6021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // cause the trust settings to be revoked. If the certificate has no 6121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // particular trust settings associated with it, mark the certificate as 6221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // a valid CA certificate with no specific trust. 6321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rv = CERT_DecodeTrustString(&original_trust, "c,c,c"); 6421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 6521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 6621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Change the trust bits to unconditionally trust this certificate. 6721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust new_trust; 6821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rv = CERT_DecodeTrustString(&new_trust, "TCu,Cu,Tu"); 6921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != SECSuccess) { 7021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LOG(ERROR) << "Cannot decode certificate trust string."; 7121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 7221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 7421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 7521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen certificate->os_cert_handle(), 7621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &new_trust); 7721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen if (rv != SECSuccess) { 7821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen LOG(ERROR) << "Cannot change certificate trust."; 7921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return false; 8021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 8121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen trust_cache_.push_back(new TrustEntry(certificate->os_cert_handle(), 8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen original_trust)); 8421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return true; 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 8621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 8721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Clear() { 8821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Restore the certificate trusts to what they were originally, before 8921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // Add() was called. Work from the rear first, since if a certificate was 9021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // added twice, the second entry's original trust status will be that of 9121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // the first entry, while the first entry contains the desired resultant 9221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // status. 9321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen for (std::list<TrustEntry*>::reverse_iterator it = trust_cache_.rbegin(); 9421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen it != trust_cache_.rend(); ++it) { 9521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen CERTCertTrust original_trust = (*it)->trust(); 9621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen SECStatus rv = CERT_ChangeCertTrust(CERT_GetDefaultCertDB(), 9721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen (*it)->certificate(), 9821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen &original_trust); 9921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // DCHECK(), rather than LOG(), as a failure to restore the original 10021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // trust can cause flake or hard-to-trace errors in any unit tests that 10121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen // occur after Clear() has been called. 10221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DCHECK_EQ(SECSuccess, rv) << "Cannot restore certificate trust."; 10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen } 10421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen STLDeleteElements(&trust_cache_); 10521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 10621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 10721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenbool TestRootCerts::IsEmpty() const { 10821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen return trust_cache_.empty(); 10921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian MonsenTestRootCerts::~TestRootCerts() { 11221d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen Clear(); 11321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11421d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid TestRootCerts::Init() { 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen crypto::EnsureNSSInit(); 11721d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} 11821d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen 11921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen} // namespace net 120