Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(98)

Unified Diff: net/base/origin_bound_cert_service.temp.cc

Issue 7565023: Gave the GetOriginBoundCertificate an asynchronous interface because certificate (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: net/base/origin_bound_cert_service.temp.cc
===================================================================
--- net/base/origin_bound_cert_service.temp.cc (revision 94628)
+++ net/base/origin_bound_cert_service.temp.cc (working copy)
@@ -2,14 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "net/base/cert_verifier.h"
+#include "net/base/origin_bound_cert_service.h"
+#include <limits>
+
#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
#include "base/message_loop.h"
+#include "base/rand_util.h"
#include "base/stl_util.h"
-#include "base/synchronization/lock.h"
#include "base/threading/worker_pool.h"
+#include "crypto/rsa_private_key.h"
#include "net/base/net_errors.h"
+#include "net/base/origin_bound_cert_store.h"
#include "net/base/x509_certificate.h"
#if defined(USE_NSS)
@@ -18,93 +25,40 @@
namespace net {
-////////////////////////////////////////////////////////////////////////////
-
-// Life of a request:
-//
-// CertVerifier CertVerifierJob CertVerifierWorker Request
-// | (origin loop) (worker loop)
-// |
-// Verify()
-// |---->-------------------<creates>
-// |
-// |---->----<creates>
-// |
-// |---->---------------------------------------------------<creates>
-// |
-// |---->--------------------Start
-// | |
-// | PostTask
-// |
-// | <starts verifying>
-// |---->-----AddRequest |
-// |
-// |
-// |
-// Finish
-// |
-// PostTask
-//
-// |
-// DoReply
-// |----<-----------------------|
-// HandleResult
-// |
-// |---->-----HandleResult
-// |
-// |------>-----------------------------------Post
-//
-//
-//
-// On a cache hit, CertVerifier::Verify() returns synchronously without
-// posting a task to a worker thread.
-
-// The number of CachedCertVerifyResult objects that we'll cache.
-static const unsigned kMaxCacheEntries = 256;
-
-// The number of seconds for which we'll cache a cache entry.
-static const unsigned kTTLSecs = 1800; // 30 minutes.
-
namespace {
-class DefaultTimeService : public CertVerifier::TimeService {
- public:
- // CertVerifier::TimeService methods:
- virtual base::Time Now() { return base::Time::Now(); }
-};
+const int kKeySizeInBits = 1024;
+const int kValidityPeriodInDays = 365;
} // namespace
-CachedCertVerifyResult::CachedCertVerifyResult() : error(ERR_FAILED) {
-}
-
-CachedCertVerifyResult::~CachedCertVerifyResult() {}
-
-bool CachedCertVerifyResult::HasExpired(const base::Time current_time) const {
- return current_time >= expiry;
-}
-
// Represents the output and result callback of a request.
-class CertVerifierRequest {
+class OriginBoundCertServiceRequest {
public:
- CertVerifierRequest(CompletionCallback* callback,
- CertVerifyResult* verify_result)
+ OriginBoundCertServiceRequest(CompletionCallback* callback,
+ std::string* private_key,
+ std::string* cert)
: callback_(callback),
- verify_result_(verify_result) {
+ private_key_(private_key),
+ cert_(cert) {
}
// Ensures that the result callback will never be made.
void Cancel() {
callback_ = NULL;
- verify_result_ = NULL;
+ private_key_ = NULL;
+ cert_ = NULL;
}
- // Copies the contents of |verify_result| to the caller's
- // CertVerifyResult and calls the callback.
- void Post(const CachedCertVerifyResult& verify_result) {
+ // Copies the contents of |private_key| and |cert| to the caller's fields
+ // and calls the callback.
+ void Post(int error,
+ const std::string& private_key,
+ const std::string& cert) {
if (callback_) {
- *verify_result_ = verify_result.result;
- callback_->Run(verify_result.error);
+ *private_key_ = private_key;
+ *cert_ = cert;
+ callback_->Run(error);
}
delete this;
}
@@ -113,24 +67,21 @@
private:
CompletionCallback* callback_;
- CertVerifyResult* verify_result_;
+ std::string* private_key_;
+ std::string* cert_;
};
-
-// CertVerifierWorker runs on a worker thread and takes care of the blocking
-// process of performing the certificate verification. Deletes itself
-// eventually if Start() succeeds.
-class CertVerifierWorker {
+// OriginBoundCertServiceWorker runs on a worker thread and takes care of the
+// blocking process of performing key generation. Deletes itself eventually
+// if Start() succeeds.
+class OriginBoundCertServiceWorker {
public:
- CertVerifierWorker(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CertVerifier* cert_verifier)
- : cert_(cert),
- hostname_(hostname),
- flags_(flags),
+ OriginBoundCertServiceWorker(
+ const std::string& origin,
+ OriginBoundCertService* origin_bound_cert_service)
+ : origin_(origin),
origin_loop_(MessageLoop::current()),
- cert_verifier_(cert_verifier),
+ origin_bound_cert_service_(origin_bound_cert_service),
canceled_(false),
error_(ERR_FAILED) {
}
@@ -139,12 +90,13 @@
DCHECK_EQ(MessageLoop::current(), origin_loop_);
return base::WorkerPool::PostTask(
- FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::Run),
+ FROM_HERE,
+ NewRunnableMethod(this, &OriginBoundCertServiceWorker::Run),
true /* task is slow */);
}
- // Cancel is called from the origin loop when the CertVerifier is getting
- // deleted.
+ // Cancel is called from the origin loop when the OriginBoundCertService is
+ // getting deleted.
void Cancel() {
DCHECK_EQ(MessageLoop::current(), origin_loop_);
base::AutoLock locked(lock_);
@@ -153,8 +105,12 @@
private:
void Run() {
+ uint32 serial_number = base::RandInt(0, std::numeric_limits<int>::max());
// Runs on a worker thread.
- error_ = cert_->Verify(hostname_, flags_, &verify_result_);
+ error_ = origin_bound_cert_service_->GenerateCert(origin_,
+ serial_number,
+ &private_key_,
+ &cert_);
#if defined(USE_NSS)
// Detach the thread from NSPR.
// Calling NSS functions attaches the thread to NSPR, which stores
@@ -178,8 +134,8 @@
// memory leaks or worse errors.
base::AutoLock locked(lock_);
if (!canceled_) {
- cert_verifier_->HandleResult(cert_, hostname_, flags_,
- error_, verify_result_);
+ origin_bound_cert_service_->HandleResult(
+ origin_, error_, private_key_, cert_);
}
}
delete this;
@@ -187,14 +143,14 @@
void Finish() {
// Runs on the worker thread.
- // We assume that the origin loop outlives the CertVerifier. If the
- // CertVerifier is deleted, it will call Cancel on us. If it does so
- // before the Acquire, we'll delete ourselves and return. If it's trying to
- // do so concurrently, then it'll block on the lock and we'll call PostTask
- // while the CertVerifier (and therefore the MessageLoop) is still alive.
- // If it does so after this function, we assume that the MessageLoop will
- // process pending tasks. In which case we'll notice the |canceled_| flag
- // in DoReply.
+ // We assume that the origin loop outlives the OriginBoundCertService. If
+ // the OriginBoundCertService is deleted, it will call Cancel on us. If it
+ // does so before the Acquire, we'll delete ourselves and return. If it's
+ // trying to do so concurrently, then it'll block on the lock and we'll
+ // call PostTask while the OriginBoundCertService (and therefore the
+ // MessageLoop) is still alive. If it does so after this function, we
+ // assume that the MessageLoop will process pending tasks. In which case
+ // we'll notice the |canceled_| flag in DoReply.
bool canceled;
{
@@ -202,141 +158,128 @@
canceled = canceled_;
if (!canceled) {
origin_loop_->PostTask(
- FROM_HERE, NewRunnableMethod(this, &CertVerifierWorker::DoReply));
+ FROM_HERE,
+ NewRunnableMethod(this, &OriginBoundCertServiceWorker::DoReply));
}
}
-
if (canceled)
delete this;
}
- scoped_refptr<X509Certificate> cert_;
- const std::string hostname_;
- const int flags_;
+ const std::string origin_;
MessageLoop* const origin_loop_;
- CertVerifier* const cert_verifier_;
+ OriginBoundCertService* const origin_bound_cert_service_;
// lock_ protects canceled_.
base::Lock lock_;
// If canceled_ is true,
// * origin_loop_ cannot be accessed by the worker thread,
- // * cert_verifier_ cannot be accessed by any thread.
+ // * origin_bound_cert_service_ cannot be accessed by any thread.
bool canceled_;
int error_;
- CertVerifyResult verify_result_;
+ std::string private_key_;
+ std::string cert_;
- DISALLOW_COPY_AND_ASSIGN(CertVerifierWorker);
+ DISALLOW_COPY_AND_ASSIGN(OriginBoundCertServiceWorker);
};
-// A CertVerifierJob is a one-to-one counterpart of a CertVerifierWorker. It
-// lives only on the CertVerifier's origin message loop.
-class CertVerifierJob {
+// An OriginBoundCertServiceJob is a one-to-one counterpart of an
+// OriginBoundCertServiceWorker. It lives only on the OriginBoundCertService's
+// origin message loop.
+class OriginBoundCertServiceJob {
public:
- explicit CertVerifierJob(CertVerifierWorker* worker) : worker_(worker) {
+ explicit OriginBoundCertServiceJob(OriginBoundCertServiceWorker* worker)
+ : worker_(worker) {
}
- ~CertVerifierJob() {
+ ~OriginBoundCertServiceJob() {
if (worker_) {
worker_->Cancel();
DeleteAllCanceled();
}
}
- void AddRequest(CertVerifierRequest* request) {
+ void AddRequest(OriginBoundCertServiceRequest* request) {
requests_.push_back(request);
}
- void HandleResult(const CachedCertVerifyResult& verify_result) {
+ void HandleResult(int error,
+ const std::string& private_key,
+ const std::string& cert) {
worker_ = NULL;
- PostAll(verify_result);
+ PostAll(error, private_key, cert);
}
private:
- void PostAll(const CachedCertVerifyResult& verify_result) {
- std::vector<CertVerifierRequest*> requests;
+ void PostAll(int error,
+ const std::string& private_key,
+ const std::string& cert) {
+ std::vector<OriginBoundCertServiceRequest*> requests;
requests_.swap(requests);
- for (std::vector<CertVerifierRequest*>::iterator
+ for (std::vector<OriginBoundCertServiceRequest*>::iterator
i = requests.begin(); i != requests.end(); i++) {
- (*i)->Post(verify_result);
- // Post() causes the CertVerifierRequest to delete itself.
+ (*i)->Post(error, private_key, cert);
+ // Post() causes the OriginBoundCertServiceRequest to delete itself.
}
}
void DeleteAllCanceled() {
- for (std::vector<CertVerifierRequest*>::iterator
+ for (std::vector<OriginBoundCertServiceRequest*>::iterator
i = requests_.begin(); i != requests_.end(); i++) {
if ((*i)->canceled()) {
delete *i;
} else {
- LOG(DFATAL) << "CertVerifierRequest leaked!";
+ LOG(DFATAL) << "OriginBoundCertServiceRequest leaked!";
}
}
}
- std::vector<CertVerifierRequest*> requests_;
- CertVerifierWorker* worker_;
+ std::vector<OriginBoundCertServiceRequest*> requests_;
+ OriginBoundCertServiceWorker* worker_;
};
-
-CertVerifier::CertVerifier()
- : time_service_(new DefaultTimeService),
+OriginBoundCertService::OriginBoundCertService(
+ OriginBoundCertStore* origin_bound_cert_store)
+ : origin_bound_cert_store_(origin_bound_cert_store),
requests_(0),
cache_hits_(0),
- inflight_joins_(0) {
- CertDatabase::AddObserver(this);
-}
+ inflight_joins_(0) {}
-CertVerifier::CertVerifier(TimeService* time_service)
- : time_service_(time_service),
- requests_(0),
- cache_hits_(0),
- inflight_joins_(0) {
- CertDatabase::AddObserver(this);
-}
-
-CertVerifier::~CertVerifier() {
+OriginBoundCertService::~OriginBoundCertService() {
STLDeleteValues(&inflight_);
-
- CertDatabase::RemoveObserver(this);
}
-int CertVerifier::Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CertVerifyResult* verify_result,
- CompletionCallback* callback,
- RequestHandle* out_req) {
+int OriginBoundCertService::GetOriginBoundCert(const std::string& origin,
+ std::string* private_key,
+ std::string* cert,
+ CompletionCallback* callback,
+ RequestHandle* out_req) {
+
DCHECK(CalledOnValidThread());
- if (!callback || !verify_result || hostname.empty()) {
+ if (!callback || !private_key || !cert || origin.empty()) {
*out_req = NULL;
return ERR_INVALID_ARGUMENT;
}
requests_++;
- const RequestParams key = {cert->fingerprint(), hostname, flags};
- // First check the cache.
- std::map<RequestParams, CachedCertVerifyResult>::iterator i;
- i = cache_.find(key);
- if (i != cache_.end()) {
- if (!i->second.HasExpired(time_service_->Now())) {
- cache_hits_++;
- *out_req = NULL;
- *verify_result = i->second.result;
- return i->second.error;
- }
- // Cache entry has expired.
- cache_.erase(i);
+ // Check if an origin bound cert already exists for this origin.
+ if (origin_bound_cert_store_->GetOriginBoundCert(origin,
+ private_key,
+ cert)) {
+ cache_hits_++;
+ *out_req = NULL;
+ return OK;
}
// No cache hit. See if an identical request is currently in flight.
- CertVerifierJob* job;
- std::map<RequestParams, CertVerifierJob*>::const_iterator j;
- j = inflight_.find(key);
+ OriginBoundCertServiceJob* job;
+ std::map<std::string, OriginBoundCertServiceJob*>::const_iterator j;
+ j = inflight_.find(origin);
if (j != inflight_.end()) {
// An identical request is in flight already. We'll just attach our
// callback.
@@ -344,163 +287,103 @@
job = j->second;
} else {
// Need to make a new request.
- CertVerifierWorker* worker = new CertVerifierWorker(cert, hostname, flags,
- this);
- job = new CertVerifierJob(worker);
+ OriginBoundCertServiceWorker* worker =
+ new OriginBoundCertServiceWorker(origin, this);
+ job = new OriginBoundCertServiceJob(worker);
if (!worker->Start()) {
delete job;
delete worker;
*out_req = NULL;
- // TODO(wtc): log to the NetLog.
- LOG(ERROR) << "CertVerifierWorker couldn't be started.";
+ // TODO(rkn): Log to the NetLog.
+ LOG(ERROR) << "OriginBoundCertServiceWorker couldn't be started.";
return ERR_INSUFFICIENT_RESOURCES; // Just a guess.
}
- inflight_.insert(std::make_pair(key, job));
+ inflight_[origin] = job;
}
- CertVerifierRequest* request =
- new CertVerifierRequest(callback, verify_result);
+ OriginBoundCertServiceRequest* request =
+ new OriginBoundCertServiceRequest(callback, private_key, cert);
job->AddRequest(request);
*out_req = request;
return ERR_IO_PENDING;
}
-void CertVerifier::CancelRequest(RequestHandle req) {
- DCHECK(CalledOnValidThread());
- CertVerifierRequest* request = reinterpret_cast<CertVerifierRequest*>(req);
- request->Cancel();
-}
+int OriginBoundCertService::GenerateCert(const std::string& origin,
+ uint32 serial_number,
+ std::string* private_key,
+ std::string* cert) {
+ std::string subject = "CN=OBC";
+ scoped_ptr<crypto::RSAPrivateKey> key(
+ crypto::RSAPrivateKey::Create(kKeySizeInBits));
+ if (!key.get()) {
+ LOG(WARNING) << "Unable to create key pair for client";
+ return ERR_FAILED;
+ }
-void CertVerifier::ClearCache() {
- DCHECK(CalledOnValidThread());
+ scoped_refptr<X509Certificate> x509_cert = X509Certificate::CreateSelfSigned(
+ key.get(),
+ subject,
+ serial_number,
+ base::TimeDelta::FromDays(kValidityPeriodInDays));
+ if (!x509_cert) {
+ LOG(WARNING) << "Unable to create x509 cert for client";
+ return ERR_FAILED;
+ }
- cache_.clear();
- // Leaves inflight_ alone.
+ std::vector<uint8> private_key_info;
+ if (!key->ExportPrivateKey(&private_key_info)) {
+ LOG(WARNING) << "Unable to export private key";
+ return ERR_FAILED;
+ }
+ // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
+ // std::string* to prevent this copying.
+ std::string key_out(private_key_info.begin(), private_key_info.end());
+
+ std::string der_cert;
+ if (!x509_cert->GetDEREncoded(&der_cert)) {
+ LOG(WARNING) << "Unable to get DER-enconded cert";
+ return ERR_FAILED;
+ }
+
+ private_key->swap(key_out);
+ cert->swap(der_cert);
+ return OK;
}
-size_t CertVerifier::GetCacheSize() const {
+void OriginBoundCertService::CancelRequest(RequestHandle req) {
DCHECK(CalledOnValidThread());
-
- return cache_.size();
+ OriginBoundCertServiceRequest* request =
+ reinterpret_cast<OriginBoundCertServiceRequest*>(req);
+ request->Cancel();
}
-// HandleResult is called by CertVerifierWorker on the origin message loop.
-// It deletes CertVerifierJob.
-void CertVerifier::HandleResult(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- int error,
- const CertVerifyResult& verify_result) {
+// HandleResult is called by OriginBoundCertServiceWorker on the origin message
+// loop. It deletes OriginBoundCertServiceJob.
+void OriginBoundCertService::HandleResult(const std::string& origin,
+ int error,
+ const std::string& private_key,
+ const std::string& cert) {
DCHECK(CalledOnValidThread());
- const base::Time current_time(time_service_->Now());
+ origin_bound_cert_store_->SetOriginBoundCert(origin, private_key, cert);
- CachedCertVerifyResult cached_result;
- cached_result.error = error;
- cached_result.result = verify_result;
- uint32 ttl = kTTLSecs;
- cached_result.expiry = current_time + base::TimeDelta::FromSeconds(ttl);
-
- const RequestParams key = {cert->fingerprint(), hostname, flags};
-
- DCHECK_GE(kMaxCacheEntries, 1u);
- DCHECK_LE(cache_.size(), kMaxCacheEntries);
- if (cache_.size() == kMaxCacheEntries) {
- // Need to remove an element of the cache.
- std::map<RequestParams, CachedCertVerifyResult>::iterator i, cur;
- for (i = cache_.begin(); i != cache_.end(); ) {
- cur = i++;
- if (cur->second.HasExpired(current_time))
- cache_.erase(cur);
- }
- }
- if (cache_.size() == kMaxCacheEntries) {
- // If we didn't clear out any expired entries, we just remove the first
- // element. Crummy but simple.
- cache_.erase(cache_.begin());
- }
-
- cache_.insert(std::make_pair(key, cached_result));
-
- std::map<RequestParams, CertVerifierJob*>::iterator j;
- j = inflight_.find(key);
+ std::map<std::string, OriginBoundCertServiceJob*>::iterator j;
+ j = inflight_.find(origin);
if (j == inflight_.end()) {
NOTREACHED();
return;
}
- CertVerifierJob* job = j->second;
+ OriginBoundCertServiceJob* job = j->second;
inflight_.erase(j);
- job->HandleResult(cached_result);
+ job->HandleResult(error, private_key, cert);
delete job;
}
-void CertVerifier::OnCertTrustChanged(const X509Certificate* cert) {
- DCHECK(CalledOnValidThread());
-
- ClearCache();
+int OriginBoundCertService::GetCertCount() {
+ return origin_bound_cert_store_->GetCertCount();
}
-/////////////////////////////////////////////////////////////////////
-
-SingleRequestCertVerifier::SingleRequestCertVerifier(
- CertVerifier* cert_verifier)
- : cert_verifier_(cert_verifier),
- cur_request_(NULL),
- cur_request_callback_(NULL),
- ALLOW_THIS_IN_INITIALIZER_LIST(
- callback_(this, &SingleRequestCertVerifier::OnVerifyCompletion)) {
- DCHECK(cert_verifier_ != NULL);
-}
-
-SingleRequestCertVerifier::~SingleRequestCertVerifier() {
- if (cur_request_) {
- cert_verifier_->CancelRequest(cur_request_);
- cur_request_ = NULL;
- }
-}
-
-int SingleRequestCertVerifier::Verify(X509Certificate* cert,
- const std::string& hostname,
- int flags,
- CertVerifyResult* verify_result,
- CompletionCallback* callback) {
- // Should not be already in use.
- DCHECK(!cur_request_ && !cur_request_callback_);
-
- // Do a synchronous verification.
- if (!callback)
- return cert->Verify(hostname, flags, verify_result);
-
- CertVerifier::RequestHandle request = NULL;
-
- // We need to be notified of completion before |callback| is called, so that
- // we can clear out |cur_request_*|.
- int rv = cert_verifier_->Verify(
- cert, hostname, flags, verify_result, &callback_, &request);
-
- if (rv == ERR_IO_PENDING) {
- // Cleared in OnVerifyCompletion().
- cur_request_ = request;
- cur_request_callback_ = callback;
- }
-
- return rv;
-}
-
-void SingleRequestCertVerifier::OnVerifyCompletion(int result) {
- DCHECK(cur_request_ && cur_request_callback_);
-
- CompletionCallback* callback = cur_request_callback_;
-
- // Clear the outstanding request information.
- cur_request_ = NULL;
- cur_request_callback_ = NULL;
-
- // Call the user's original callback.
- callback->Run(result);
-}
-
} // namespace net
-DISABLE_RUNNABLE_METHOD_REFCOUNT(net::CertVerifierWorker);
+DISABLE_RUNNABLE_METHOD_REFCOUNT(net::OriginBoundCertServiceWorker);

Powered by Google App Engine
This is Rietveld 408576698