// Copyright (c) 2017 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 "net/cert/internal/revocation_checker.h" #include #include "base/strings/string_piece.h" #include "crypto/sha2.h" #include "net/cert/internal/common_cert_errors.h" #include "net/cert/internal/parsed_certificate.h" namespace net { CRLSet::Result CheckChainRevocationUsingCRLSet( const CRLSet* crl_set, const ParsedCertificateList& certs, CertPathErrors* errors) { // Iterate from the root certificate towards the leaf (the root certificate is // also checked for revocation by CRLSet). std::string issuer_spki_hash; for (size_t reverse_i = 0; reverse_i < certs.size(); ++reverse_i) { size_t i = certs.size() - reverse_i - 1; const ParsedCertificate* cert = certs[i].get(); // True if |cert| is the root of the chain. const bool is_root = reverse_i == 0; // True if |cert| is the leaf certificate of the chain. const bool is_target = i == 0; // Check for revocation using the certificate's SPKI. std::string spki_hash = crypto::SHA256HashString(cert->tbs().spki_tlv.AsStringPiece()); CRLSet::Result result = crl_set->CheckSPKI(spki_hash); // Check for revocation using the certificate's serial number and issuer's // SPKI. if (result != CRLSet::REVOKED && !is_root) { result = crl_set->CheckSerial(cert->tbs().serial_number.AsStringPiece(), issuer_spki_hash); } // Prepare for the next iteration. issuer_spki_hash = std::move(spki_hash); switch (result) { case CRLSet::REVOKED: errors->GetErrorsForCert(i)->AddError(cert_errors::kCertificateRevoked); return CRLSet::Result::REVOKED; case CRLSet::UNKNOWN: // If the status is unknown, advance to the subordinate certificate. break; case CRLSet::GOOD: if (is_target && !crl_set->IsExpired()) { // If the target is covered by the CRLSet and known good, consider // the entire chain to be valid (even though the revocation status // of the intermediates may have been UNKNOWN). // // Only the leaf certificate is considered for coverage because some // intermediates have CRLs with no revocations (after filtering) and // those CRLs are pruned from the CRLSet at generation time. return CRLSet::Result::GOOD; } break; } } // If no certificate was revoked, and the target was not known good, then // the revocation status is still unknown. return CRLSet::Result::UNKNOWN; } } // namespace net