forked from Pissandshittium/pissandshittium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Kcer-over-NSS: Initial partial implementation
Upload initial interface for Kcer. Partially implement Kcer that relies on the KcerToken abstraction. Partially implement KcerTokenImplNss, which is an implementation of KcerToken that uses NSS as a permanent storage. The focus of this CL is to introduce common infrastructure that will be used by all the other methods. The implemented methods and tests are present primarily as a demonstration that the infrastructure works. The introduced code is not used anywhere yet. Bug: b:244408716 Test: KcerNssTest* Change-Id: I3195d9e77ae8ae7d3610b38fd5d632f5bf4b9923 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4312022 Reviewed-by: Pavol Marko <pmarko@chromium.org> Reviewed-by: Denis Kuznetsov <antrim@chromium.org> Reviewed-by: David Benjamin <davidben@chromium.org> Commit-Queue: Michael Ershov <miersh@google.com> Cr-Commit-Position: refs/heads/main@{#1132464}
- Loading branch information
Michael Ershov
authored and
Chromium LUCI CQ
committed
Apr 19, 2023
1 parent
7538696
commit 008eeab
Showing
29 changed files
with
2,593 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
include_rules = [ | ||
"+chromeos/components/kcer" | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
mixins: "//chromeos/components/kcer/COMMON_METADATA" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
file://chromeos/components/kcer/OWNERS |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
kcer_nss directory contains `KcerNss` - an implementation of `Kcer` | ||
(see `//components/kcer`) that relies on NSS to store keys and client | ||
certificates. | ||
|
||
`KcerNss` is a temporary implementation for the transition period. | ||
The plan is: | ||
* Implement `KcerNss`. | ||
* Refactor existing code that uses NSS to use `KcerNss`. | ||
* Implement Kcer (that has the same interface as `KcerNss`, | ||
but doesn't rely on NSS). | ||
* Switch to using `Kcer` without NSS. | ||
* Remove NSS and `KcerNss`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "chrome/browser/chromeos/kcer_nss/cert_cache_nss.h" | ||
|
||
#include "base/containers/span.h" | ||
#include "base/ranges/algorithm.h" | ||
#include "chromeos/components/kcer/kcer.h" | ||
#include "net/cert/scoped_nss_types.h" | ||
#include "third_party/boringssl/src/include/openssl/pool.h" | ||
|
||
namespace kcer::internal { | ||
|
||
namespace { | ||
|
||
// Extracts a pointer to bytes and length of the certificate itself and compares | ||
// based on them. `cert` from the constructors must remain valid throughout the | ||
// lifetime of CmpAdapter. | ||
class CmpAdapter { | ||
public: | ||
explicit CmpAdapter(const scoped_refptr<const Cert>& cert) | ||
: data_(CRYPTO_BUFFER_data(cert->GetX509Cert()->cert_buffer()), | ||
CRYPTO_BUFFER_len(cert->GetX509Cert()->cert_buffer())) {} | ||
explicit CmpAdapter(const net::ScopedCERTCertificate& cert) | ||
: data_(cert->derCert.data, cert->derCert.len) {} | ||
|
||
bool operator<(const CmpAdapter& other) { | ||
return base::ranges::lexicographical_compare(data_, other.data_); | ||
} | ||
|
||
private: | ||
base::span<const uint8_t> data_; | ||
}; | ||
|
||
} // namespace | ||
|
||
//====================== CertCacheNss ========================================== | ||
|
||
CertCacheNss::CertCacheNss() = default; | ||
CertCacheNss::CertCacheNss(CertCacheNss&&) = default; | ||
CertCacheNss& CertCacheNss::operator=(CertCacheNss&&) = default; | ||
CertCacheNss::~CertCacheNss() = default; | ||
|
||
CertCacheNss::CertCacheNss(base::span<scoped_refptr<const Cert>> certs) | ||
: certs_(certs.begin(), certs.end()) {} | ||
|
||
scoped_refptr<const Cert> CertCacheNss::FindCert( | ||
const net::ScopedCERTCertificate& cert) const { | ||
auto iter = certs_.find(cert); | ||
return (iter != certs_.end()) ? *iter : nullptr; | ||
} | ||
|
||
std::vector<scoped_refptr<const Cert>> CertCacheNss::GetAllCerts() const { | ||
return std::vector<scoped_refptr<const Cert>>(certs_.begin(), certs_.end()); | ||
} | ||
|
||
//====================== CertCacheNss::CertComparator ========================== | ||
|
||
bool CertCacheNss::CertComparator::operator()( | ||
const scoped_refptr<const Cert>& a, | ||
const net::ScopedCERTCertificate& b) const { | ||
return CmpAdapter(a) < CmpAdapter(b); | ||
} | ||
bool CertCacheNss::CertComparator::operator()( | ||
const net::ScopedCERTCertificate& a, | ||
const scoped_refptr<const Cert>& b) const { | ||
return CmpAdapter(a) < CmpAdapter(b); | ||
} | ||
bool CertCacheNss::CertComparator::operator()( | ||
const scoped_refptr<const Cert>& a, | ||
const scoped_refptr<const Cert>& b) const { | ||
return CmpAdapter(a) < CmpAdapter(b); | ||
} | ||
|
||
} // namespace kcer::internal |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#ifndef CHROME_BROWSER_CHROMEOS_KCER_NSS_CERT_CACHE_NSS_H_ | ||
#define CHROME_BROWSER_CHROMEOS_KCER_NSS_CERT_CACHE_NSS_H_ | ||
|
||
#include <set> | ||
|
||
#include "base/containers/span.h" | ||
#include "base/memory/scoped_refptr.h" | ||
#include "net/cert/scoped_nss_types.h" | ||
|
||
namespace kcer { | ||
|
||
class Cert; | ||
|
||
namespace internal { | ||
|
||
// Cache for a collection of scoped_refptr<const Cert>-s. | ||
class CertCacheNss { | ||
public: | ||
// Empty cache. | ||
CertCacheNss(); | ||
// Cache that contains `certs` (`certs` can be unsorted). | ||
explicit CertCacheNss(base::span<scoped_refptr<const Cert>> certs); | ||
CertCacheNss(CertCacheNss&&); | ||
CertCacheNss& operator=(CertCacheNss&&); | ||
~CertCacheNss(); | ||
|
||
// Searches for Cert certificate with the same content as `cert` and returns a | ||
// scoped_refptr<const Cert> on success, a nullptr if `cert` was not found. | ||
scoped_refptr<const Cert> FindCert( | ||
const net::ScopedCERTCertificate& cert) const; | ||
// Returns ref-counting pointers to all certificate from the cache. | ||
std::vector<scoped_refptr<const Cert>> GetAllCerts() const; | ||
|
||
private: | ||
// Comparator for sorting scoped_refptr<const Cert>-s and for enabling | ||
// std::set::find() using the net::ScopedCERTCertificate representation of a | ||
// cert. | ||
struct CertComparator { | ||
using is_transparent = void; | ||
|
||
bool operator()(const scoped_refptr<const Cert>& a, | ||
const net::ScopedCERTCertificate& b) const; | ||
bool operator()(const net::ScopedCERTCertificate& a, | ||
const scoped_refptr<const Cert>& b) const; | ||
bool operator()(const scoped_refptr<const Cert>& a, | ||
const scoped_refptr<const Cert>& b) const; | ||
}; | ||
|
||
std::set<scoped_refptr<const Cert>, CertComparator> certs_; | ||
}; | ||
|
||
} // namespace internal | ||
} // namespace kcer | ||
|
||
#endif // CHROME_BROWSER_CHROMEOS_KCER_NSS_CERT_CACHE_NSS_H_ |
121 changes: 121 additions & 0 deletions
121
chrome/browser/chromeos/kcer_nss/cert_cache_nss_unittest.cc
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
// Copyright 2023 The Chromium Authors | ||
// Use of this source code is governed by a BSD-style license that can be | ||
// found in the LICENSE file. | ||
|
||
#include "chrome/browser/chromeos/kcer_nss/cert_cache_nss.h" | ||
|
||
#include <memory> | ||
#include <string> | ||
|
||
#include "base/files/file_path.h" | ||
#include "base/memory/scoped_refptr.h" | ||
#include "chromeos/components/kcer/kcer.h" | ||
#include "net/cert/x509_util_nss.h" | ||
#include "net/test/cert_builder.h" | ||
#include "net/test/test_data_directory.h" | ||
#include "testing/gmock/include/gmock/gmock.h" | ||
#include "testing/gtest/include/gtest/gtest.h" | ||
|
||
namespace kcer::internal { | ||
namespace { | ||
|
||
std::unique_ptr<net::CertBuilder> MakeCertBuilder() { | ||
return net::CertBuilder::FromFile( | ||
net::GetTestCertsDirectory().AppendASCII("ok_cert.pem"), nullptr); | ||
} | ||
|
||
scoped_refptr<const Cert> MakeKcerCert( | ||
scoped_refptr<net::X509Certificate> cert) { | ||
// CertCacheNss only cares about the `cert`, other fields are can be anything. | ||
return base::MakeRefCounted<Cert>(Token::kUser, Pkcs11Id(), | ||
/*nickname=*/std::string(), | ||
std::move(cert)); | ||
} | ||
|
||
// Test that an empty cache doesn't find an unrelated certificate and doesn't | ||
// return any certs. | ||
TEST(KcerCertCacheNssTest, EmptyCacheThenCertNotFound) { | ||
std::unique_ptr<net::CertBuilder> builder = MakeCertBuilder(); | ||
net::ScopedCERTCertificate nss_cert = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder->GetX509Certificate().get()); | ||
|
||
CertCacheNss empty_cache; | ||
|
||
EXPECT_EQ(empty_cache.FindCert(nss_cert), nullptr); | ||
EXPECT_EQ(empty_cache.GetAllCerts().size(), 0u); | ||
} | ||
|
||
// Test that a cache with one cert can find and return that cert, but not an | ||
// unrelated one. | ||
TEST(KcerCertCacheNssTest, OneCert) { | ||
std::unique_ptr<net::CertBuilder> builder_0 = MakeCertBuilder(); | ||
std::unique_ptr<net::CertBuilder> builder_1 = MakeCertBuilder(); | ||
|
||
net::ScopedCERTCertificate nss_cert_0 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_0->GetX509Certificate().get()); | ||
scoped_refptr<const Cert> kcer_cert_0 = | ||
MakeKcerCert(builder_0->GetX509Certificate()); | ||
|
||
net::ScopedCERTCertificate nss_cert_1 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_1->GetX509Certificate().get()); | ||
|
||
std::vector<scoped_refptr<const Cert>> certs({kcer_cert_0}); | ||
CertCacheNss cache(certs); | ||
|
||
EXPECT_EQ(cache.FindCert(nss_cert_0), kcer_cert_0); | ||
EXPECT_EQ(cache.FindCert(nss_cert_1), nullptr); | ||
EXPECT_THAT(cache.GetAllCerts(), testing::ElementsAre(kcer_cert_0)); | ||
} | ||
|
||
// Test that CertCacheNss can hold, find and return multiple certs. | ||
TEST(KcerCertCacheNssTest, MultipleCerts) { | ||
std::unique_ptr<net::CertBuilder> builder_0 = MakeCertBuilder(); | ||
std::unique_ptr<net::CertBuilder> builder_1 = MakeCertBuilder(); | ||
std::unique_ptr<net::CertBuilder> builder_2 = MakeCertBuilder(); | ||
std::unique_ptr<net::CertBuilder> builder_3 = MakeCertBuilder(); | ||
|
||
net::ScopedCERTCertificate nss_cert_0 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_0->GetX509Certificate().get()); | ||
scoped_refptr<const Cert> kcer_cert_0 = | ||
MakeKcerCert(builder_0->GetX509Certificate()); | ||
|
||
net::ScopedCERTCertificate nss_cert_1 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_1->GetX509Certificate().get()); | ||
scoped_refptr<const Cert> kcer_cert_1 = | ||
MakeKcerCert(builder_1->GetX509Certificate()); | ||
|
||
net::ScopedCERTCertificate nss_cert_2 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_2->GetX509Certificate().get()); | ||
scoped_refptr<const Cert> kcer_cert_2 = | ||
MakeKcerCert(builder_2->GetX509Certificate()); | ||
|
||
net::ScopedCERTCertificate nss_cert_3 = | ||
net::x509_util::CreateCERTCertificateFromX509Certificate( | ||
builder_3->GetX509Certificate().get()); | ||
scoped_refptr<const Cert> kcer_cert_3 = | ||
MakeKcerCert(builder_3->GetX509Certificate()); | ||
|
||
// Add a lot of duplicates in different order to exercise the comparator. | ||
std::vector<scoped_refptr<const Cert>> certs( | ||
{kcer_cert_0, kcer_cert_1, kcer_cert_2, kcer_cert_3, kcer_cert_3, | ||
kcer_cert_2, kcer_cert_1, kcer_cert_0, kcer_cert_0, kcer_cert_2, | ||
kcer_cert_3, kcer_cert_1}); | ||
CertCacheNss cache(certs); | ||
|
||
EXPECT_EQ(cache.FindCert(nss_cert_0), kcer_cert_0); | ||
EXPECT_EQ(cache.FindCert(nss_cert_1), kcer_cert_1); | ||
EXPECT_EQ(cache.FindCert(nss_cert_2), kcer_cert_2); | ||
EXPECT_EQ(cache.FindCert(nss_cert_3), kcer_cert_3); | ||
EXPECT_THAT(cache.GetAllCerts(), | ||
testing::UnorderedElementsAre(kcer_cert_0, kcer_cert_1, | ||
kcer_cert_2, kcer_cert_3)); | ||
} | ||
|
||
} // namespace | ||
} // namespace kcer::internal |
Oops, something went wrong.