| Index: net/cert/internal/trust_store_nss.cc
|
| diff --git a/net/cert/internal/trust_store_nss.cc b/net/cert/internal/trust_store_nss.cc
|
| index 0a67939ce47d12d7b4b9ed5c9969fadd0845979f..fb43321e27ba823eb4ade5835f38e7feda8a5681 100644
|
| --- a/net/cert/internal/trust_store_nss.cc
|
| +++ b/net/cert/internal/trust_store_nss.cc
|
| @@ -11,6 +11,7 @@
|
| #include "crypto/nss_util.h"
|
| #include "net/cert/internal/cert_errors.h"
|
| #include "net/cert/internal/parsed_certificate.h"
|
| +#include "net/cert/scoped_nss_types.h"
|
| #include "net/cert/x509_util.h"
|
|
|
| // TODO(mattm): structure so that supporting ChromeOS multi-profile stuff is
|
| @@ -24,9 +25,8 @@ TrustStoreNSS::TrustStoreNSS(SECTrustType trust_type)
|
|
|
| TrustStoreNSS::~TrustStoreNSS() = default;
|
|
|
| -void TrustStoreNSS::FindTrustAnchorsForCert(
|
| - const scoped_refptr<ParsedCertificate>& cert,
|
| - TrustAnchors* out_anchors) const {
|
| +void TrustStoreNSS::SyncGetIssuersOf(const ParsedCertificate* cert,
|
| + ParsedCertificateList* issuers) {
|
| crypto::EnsureNSSInit();
|
|
|
| SECItem name;
|
| @@ -46,31 +46,71 @@ void TrustStoreNSS::FindTrustAnchorsForCert(
|
|
|
| for (CERTCertListNode* node = CERT_LIST_HEAD(found_certs);
|
| !CERT_LIST_END(node, found_certs); node = CERT_LIST_NEXT(node)) {
|
| - CERTCertTrust trust;
|
| - if (CERT_GetCertTrust(node->cert, &trust) != SECSuccess)
|
| - continue;
|
| -
|
| - // TODO(mattm): handle explicit distrust (blacklisting)?
|
| - const int ca_trust = CERTDB_TRUSTED_CA;
|
| - if ((SEC_GET_TRUST_FLAGS(&trust, trust_type_) & ca_trust) != ca_trust)
|
| - continue;
|
| -
|
| - CertErrors errors;
|
| - scoped_refptr<ParsedCertificate> anchor_cert = ParsedCertificate::Create(
|
| + CertErrors parse_errors;
|
| + scoped_refptr<ParsedCertificate> cur_cert = ParsedCertificate::Create(
|
| x509_util::CreateCryptoBuffer(node->cert->derCert.data,
|
| node->cert->derCert.len),
|
| - {}, &errors);
|
| - if (!anchor_cert) {
|
| + {}, &parse_errors);
|
| +
|
| + if (!cur_cert) {
|
| // TODO(crbug.com/634443): return errors better.
|
| LOG(ERROR) << "Error parsing issuer certificate:\n"
|
| - << errors.ToDebugString();
|
| + << parse_errors.ToDebugString();
|
| continue;
|
| }
|
|
|
| - out_anchors->push_back(TrustAnchor::CreateFromCertificateNoConstraints(
|
| - std::move(anchor_cert)));
|
| + issuers->push_back(std::move(cur_cert));
|
| }
|
| CERT_DestroyCertList(found_certs);
|
| }
|
|
|
| +void TrustStoreNSS::GetTrust(const scoped_refptr<ParsedCertificate>& cert,
|
| + CertificateTrust* out_trust) const {
|
| + // TODO(eroman): Inefficient -- path building will convert between
|
| + // CERTCertificate and ParsedCertificate representations multiple times
|
| + // (when getting the issuers, and again here).
|
| +
|
| + // Lookup the certificate by Issuer + Serial number. Note that
|
| + // CERT_FindCertByDERCert() doesn't check for equal DER, just matching issuer
|
| + // + serial number.
|
| + SECItem der_cert;
|
| + der_cert.data = const_cast<uint8_t*>(cert->der_cert().UnsafeData());
|
| + der_cert.len = cert->der_cert().Length();
|
| + der_cert.type = siDERCertBuffer;
|
| + ScopedCERTCertificate nss_matched_cert(
|
| + CERT_FindCertByDERCert(CERT_GetDefaultCertDB(), &der_cert));
|
| + if (!nss_matched_cert) {
|
| + *out_trust = CertificateTrust::ForUnspecified();
|
| + return;
|
| + }
|
| +
|
| + // Determine the trustedness of the matched certificate.
|
| + CERTCertTrust trust;
|
| + if (CERT_GetCertTrust(nss_matched_cert.get(), &trust) != SECSuccess) {
|
| + *out_trust = CertificateTrust::ForUnspecified();
|
| + return;
|
| + }
|
| +
|
| + // TODO(eroman): Determine if |nss_matched_cert| is distrusted.
|
| +
|
| + // Determine if the certificate is a trust anchor.
|
| + const int ca_trust = CERTDB_TRUSTED_CA;
|
| + bool is_trusted =
|
| + (SEC_GET_TRUST_FLAGS(&trust, trust_type_) & ca_trust) == ca_trust;
|
| +
|
| + // To consider |cert| trusted, need to additionally check that
|
| + // |cert| is the same as |nss_matched_cert|. This is because the lookup in NSS
|
| + // was only by issuer + serial number, so could be for a different
|
| + // SPKI.
|
| + if (is_trusted &&
|
| + (cert->der_cert() == der::Input(nss_matched_cert->derCert.data,
|
| + nss_matched_cert->derCert.len))) {
|
| + *out_trust = CertificateTrust::ForTrustAnchor();
|
| + return;
|
| + }
|
| +
|
| + *out_trust = CertificateTrust::ForUnspecified();
|
| + return;
|
| +}
|
| +
|
| } // namespace net
|
|
|