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

Unified Diff: net/ssl/channel_id_service.cc

Issue 1076063002: Remove certificates from Channel ID (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix some small style/formatting issues Created 5 years, 8 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/ssl/channel_id_service.cc
diff --git a/net/ssl/channel_id_service.cc b/net/ssl/channel_id_service.cc
index 9bc21794a9c11b70f066fe60ad09aefb3a183587..9ac7c3249a35b4c429304ccc92368f06dc7bc6a9 100644
--- a/net/ssl/channel_id_service.cc
+++ b/net/ssl/channel_id_service.cc
@@ -88,45 +88,27 @@ void RecordGetChannelIDTime(base::TimeDelta request_time) {
// unjoined thread, due to relying on a non-leaked LazyInstance
scoped_ptr<ChannelIDStore::ChannelID> GenerateChannelID(
const std::string& server_identifier,
- uint32 serial_number,
int* error) {
scoped_ptr<ChannelIDStore::ChannelID> result;
base::TimeTicks start = base::TimeTicks::Now();
base::Time not_valid_before = base::Time::Now();
- base::Time not_valid_after =
- not_valid_before + base::TimeDelta::FromDays(kValidityPeriodInDays);
- std::string der_cert;
- std::vector<uint8> private_key_info;
- scoped_ptr<crypto::ECPrivateKey> key;
- if (!x509_util::CreateKeyAndChannelIDEC(server_identifier,
- serial_number,
- not_valid_before,
- not_valid_after,
- &key,
- &der_cert)) {
- DLOG(ERROR) << "Unable to create x509 cert for client";
- *error = ERR_ORIGIN_BOUND_CERT_GENERATION_FAILED;
- return result.Pass();
- }
+ scoped_ptr<crypto::ECPrivateKey> key(crypto::ECPrivateKey::Create());
- if (!key->ExportEncryptedPrivateKey(ChannelIDService::kEPKIPassword,
- 1, &private_key_info)) {
- DLOG(ERROR) << "Unable to export private key";
- *error = ERR_PRIVATE_KEY_EXPORT_FAILED;
+ if (!key) {
+ DLOG(ERROR) << "Unable to create channel ID key pair";
+ *error = ERR_KEY_GENERATION_FAILED;
return result.Pass();
}
- // 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 private_key_out;
+ std::string public_key_out;
+ *error = ExportKeypair(key, &public_key_out, &private_key_out);
+ if (*error != OK)
+ return result.Pass();
result.reset(new ChannelIDStore::ChannelID(
- server_identifier,
- not_valid_before,
- not_valid_after,
- key_out,
- der_cert));
+ server_identifier, not_valid_before, private_key_out, public_key_out));
UMA_HISTOGRAM_CUSTOM_TIMES("DomainBoundCerts.GenerateCertTime",
base::TimeTicks::Now() - start,
base::TimeDelta::FromMilliseconds(1),
@@ -138,32 +120,71 @@ scoped_ptr<ChannelIDStore::ChannelID> GenerateChannelID(
} // namespace
+int CreateECPrivateKeyFromSerializedKey(
+ const std::string& public_key,
+ const std::string& private_key,
+ scoped_ptr<crypto::ECPrivateKey>* key_out) {
+ if (public_key.empty() || private_key.empty())
+ return ERR_UNEXPECTED;
+
+ std::vector<uint8> public_key_vector(public_key.size());
+ memcpy(&public_key_vector[0], public_key.data(), public_key.size());
Ryan Sleevi 2015/04/15 22:50:02 DANGER: What if |public_key| is .empty()? This wou
nharper 2015/04/25 02:59:19 If public_key or private_key is .empty(), then thi
+ std::vector<uint8> private_key_vector(private_key.size());
+ memcpy(&private_key_vector[0], private_key.data(), private_key.size());
+ crypto::ECPrivateKey* key =
+ crypto::ECPrivateKey::CreateFromEncryptedPrivateKeyInfo(
+ ChannelIDService::kEPKIPassword, private_key_vector,
+ public_key_vector);
+ if (key == nullptr)
+ return ERR_UNEXPECTED;
+ key_out->reset(key);
+ return OK;
+}
+
+int ExportKeypair(scoped_ptr<crypto::ECPrivateKey>& key,
Ryan Sleevi 2015/04/15 22:50:02 pass as const-ref But really, you should be sendi
nharper 2015/04/25 02:59:19 Changed to const-ref. Does the style guide have in
+ std::string* public_key,
+ std::string* private_key) {
+ std::vector<uint8> public_key_vector;
+ std::vector<uint8> private_key_vector;
+
+ if (!key)
+ return ERR_UNEXPECTED;
+
+ if (!key->ExportEncryptedPrivateKey(ChannelIDService::kEPKIPassword, 1,
+ &private_key_vector) ||
+ !key->ExportPublicKey(&public_key_vector)) {
+ DLOG(ERROR) << "Unable to export key";
+ return ERR_PRIVATE_KEY_EXPORT_FAILED;
+ }
+
+ // TODO(rkn): Perhaps ExportPrivateKey should be changed to output a
+ // std::string* to prevent this copying.
+ *public_key = std::string(public_key_vector.begin(), public_key_vector.end());
Ryan Sleevi 2015/04/15 22:50:02 Does this work across platforms without throwing c
nharper 2015/04/25 02:59:20 This code was copied from the lhs of this diff (se
+ *private_key =
+ std::string(private_key_vector.begin(), private_key_vector.end());
+ return OK;
+}
Ryan Sleevi 2015/04/15 22:50:02 Should match order in .h
nharper 2015/04/25 02:59:19 Done.
+
// Represents the output and result callback of a request.
class ChannelIDServiceRequest {
public:
ChannelIDServiceRequest(base::TimeTicks request_start,
const CompletionCallback& callback,
- std::string* private_key,
- std::string* cert)
- : request_start_(request_start),
- callback_(callback),
- private_key_(private_key),
- cert_(cert) {
- }
+ scoped_ptr<crypto::ECPrivateKey>* key)
+ : request_start_(request_start), callback_(callback), key_(key) {}
// Ensures that the result callback will never be made.
void Cancel() {
RecordGetChannelIDResult(ASYNC_CANCELLED);
callback_.Reset();
- private_key_ = NULL;
- cert_ = NULL;
+ key_->reset();
}
// Copies the contents of |private_key| and |cert| to the caller's output
// arguments and calls the callback.
void Post(int error,
const std::string& private_key,
- const std::string& cert) {
+ const std::string& public_key) {
switch (error) {
case OK: {
base::TimeDelta request_time = base::TimeTicks::Now() - request_start_;
@@ -193,8 +214,10 @@ class ChannelIDServiceRequest {
break;
}
if (!callback_.is_null()) {
- *private_key_ = private_key;
- *cert_ = cert;
+ int err =
+ CreateECPrivateKeyFromSerializedKey(public_key, private_key, key_);
+ if (error == OK && err != OK)
+ error = err;
callback_.Run(error);
}
delete this;
@@ -205,8 +228,7 @@ class ChannelIDServiceRequest {
private:
base::TimeTicks request_start_;
CompletionCallback callback_;
- std::string* private_key_;
- std::string* cert_;
+ scoped_ptr<crypto::ECPrivateKey>* key_;
};
// ChannelIDServiceWorker runs on a worker thread and takes care of the
@@ -223,7 +245,6 @@ class ChannelIDServiceWorker {
const std::string& server_identifier,
const WorkerDoneCallback& callback)
: server_identifier_(server_identifier),
- serial_number_(base::RandInt(0, std::numeric_limits<int>::max())),
origin_loop_(base::MessageLoopProxy::current()),
callback_(callback) {
}
@@ -244,7 +265,7 @@ class ChannelIDServiceWorker {
// Runs on a worker thread.
int error = ERR_FAILED;
scoped_ptr<ChannelIDStore::ChannelID> cert =
- GenerateChannelID(server_identifier_, serial_number_, &error);
+ GenerateChannelID(server_identifier_, &error);
DVLOG(1) << "GenerateCert " << server_identifier_ << " returned " << error;
#if defined(USE_NSS)
// Detach the thread from NSPR.
@@ -262,9 +283,6 @@ class ChannelIDServiceWorker {
}
const std::string server_identifier_;
- // Note that serial_number_ must be initialized on a non-worker thread
- // (see documentation for GenerateCert).
- uint32 serial_number_;
scoped_refptr<base::SequencedTaskRunner> origin_loop_;
WorkerDoneCallback callback_;
@@ -293,8 +311,8 @@ class ChannelIDServiceJob {
void HandleResult(int error,
const std::string& private_key,
- const std::string& cert) {
- PostAll(error, private_key, cert);
+ const std::string& public_key) {
+ PostAll(error, private_key, public_key);
}
bool CreateIfMissing() const { return create_if_missing_; }
@@ -302,13 +320,13 @@ class ChannelIDServiceJob {
private:
void PostAll(int error,
const std::string& private_key,
- const std::string& cert) {
+ const std::string& public_key) {
std::vector<ChannelIDServiceRequest*> requests;
requests_.swap(requests);
for (std::vector<ChannelIDServiceRequest*>::iterator
i = requests.begin(); i != requests.end(); i++) {
- (*i)->Post(error, private_key, cert);
+ (*i)->Post(error, private_key, public_key);
// Post() causes the ChannelIDServiceRequest to delete itself.
}
}
@@ -370,7 +388,7 @@ ChannelIDService::ChannelIDService(
: channel_id_store_(channel_id_store),
task_runner_(task_runner),
requests_(0),
- cert_store_hits_(0),
+ key_store_hits_(0),
inflight_joins_(0),
workers_created_(0),
weak_ptr_factory_(this) {
@@ -396,15 +414,14 @@ std::string ChannelIDService::GetDomainForHost(const std::string& host) {
int ChannelIDService::GetOrCreateChannelID(
const std::string& host,
- std::string* private_key,
- std::string* cert,
+ scoped_ptr<crypto::ECPrivateKey>* key,
const CompletionCallback& callback,
RequestHandle* out_req) {
DVLOG(1) << __FUNCTION__ << " " << host;
DCHECK(CalledOnValidThread());
base::TimeTicks request_start = base::TimeTicks::Now();
- if (callback.is_null() || !private_key || !cert || host.empty()) {
+ if (callback.is_null() || !key || host.empty()) {
RecordGetChannelIDResult(INVALID_ARGUMENT);
return ERR_INVALID_ARGUMENT;
}
@@ -417,15 +434,18 @@ int ChannelIDService::GetOrCreateChannelID(
requests_++;
+ std::string public_key;
+ std::string private_key;
Ryan Sleevi 2015/04/15 22:50:02 These two are unused, right?
nharper 2015/04/25 02:59:19 Correct. Removed.
+
// See if a request for the same domain is currently in flight.
bool create_if_missing = true;
- if (JoinToInFlightRequest(request_start, domain, private_key, cert,
- create_if_missing, callback, out_req)) {
+ if (JoinToInFlightRequest(request_start, domain, key, create_if_missing,
+ callback, out_req)) {
return ERR_IO_PENDING;
}
- int err = LookupChannelID(request_start, domain, private_key, cert,
- create_if_missing, callback, out_req);
+ int err = LookupChannelID(request_start, domain, key, create_if_missing,
+ callback, out_req);
if (err == ERR_FILE_NOT_FOUND) {
// Sync lookup did not find a valid cert. Start generating a new one.
workers_created_++;
@@ -444,11 +464,9 @@ int ChannelIDService::GetOrCreateChannelID(
inflight_[domain] = job;
ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
- request_start,
- base::Bind(&RequestHandle::OnRequestComplete,
- base::Unretained(out_req)),
- private_key,
- cert);
+ request_start, base::Bind(&RequestHandle::OnRequestComplete,
+ base::Unretained(out_req)),
+ key);
job->AddRequest(request);
out_req->RequestStarted(this, request, callback);
return ERR_IO_PENDING;
@@ -457,17 +475,15 @@ int ChannelIDService::GetOrCreateChannelID(
return err;
}
-int ChannelIDService::GetChannelID(
- const std::string& host,
- std::string* private_key,
- std::string* cert,
- const CompletionCallback& callback,
- RequestHandle* out_req) {
+int ChannelIDService::GetChannelID(const std::string& host,
+ scoped_ptr<crypto::ECPrivateKey>* key,
+ const CompletionCallback& callback,
+ RequestHandle* out_req) {
DVLOG(1) << __FUNCTION__ << " " << host;
DCHECK(CalledOnValidThread());
base::TimeTicks request_start = base::TimeTicks::Now();
- if (callback.is_null() || !private_key || !cert || host.empty()) {
+ if (callback.is_null() || !key || host.empty()) {
RecordGetChannelIDResult(INVALID_ARGUMENT);
return ERR_INVALID_ARGUMENT;
}
@@ -482,22 +498,20 @@ int ChannelIDService::GetChannelID(
// See if a request for the same domain currently in flight.
bool create_if_missing = false;
- if (JoinToInFlightRequest(request_start, domain, private_key, cert,
- create_if_missing, callback, out_req)) {
+ if (JoinToInFlightRequest(request_start, domain, key, create_if_missing,
+ callback, out_req)) {
return ERR_IO_PENDING;
}
- int err = LookupChannelID(request_start, domain, private_key, cert,
- create_if_missing, callback, out_req);
+ int err = LookupChannelID(request_start, domain, key, create_if_missing,
+ callback, out_req);
return err;
}
-void ChannelIDService::GotChannelID(
- int err,
- const std::string& server_identifier,
- base::Time expiration_time,
- const std::string& key,
- const std::string& cert) {
+void ChannelIDService::GotChannelID(int err,
+ const std::string& server_identifier,
+ const std::string& private_key,
+ const std::string& public_key) {
DCHECK(CalledOnValidThread());
std::map<std::string, ChannelIDServiceJob*>::iterator j;
@@ -509,17 +523,17 @@ void ChannelIDService::GotChannelID(
if (err == OK) {
// Async DB lookup found a valid cert.
- DVLOG(1) << "Cert store had valid cert for " << server_identifier;
- cert_store_hits_++;
+ DVLOG(1) << "Cert store had valid key for " << server_identifier;
+ key_store_hits_++;
// ChannelIDServiceRequest::Post will do the histograms and stuff.
- HandleResult(OK, server_identifier, key, cert);
+ HandleResult(OK, server_identifier, private_key, public_key);
return;
}
// Async lookup failed or the certificate was missing. Return the error
// directly, unless the certificate was missing and a request asked to create
// one.
if (err != ERR_FILE_NOT_FOUND || !j->second->CreateIfMissing()) {
- HandleResult(err, server_identifier, key, cert);
+ HandleResult(err, server_identifier, private_key, public_key);
return;
}
// At least one request asked to create a cert => start generating a new one.
@@ -556,24 +570,21 @@ void ChannelIDService::GeneratedChannelID(
if (error == OK) {
// TODO(mattm): we should just Pass() the cert object to
// SetChannelID().
- channel_id_store_->SetChannelID(
- cert->server_identifier(),
- cert->creation_time(),
- cert->expiration_time(),
- cert->private_key(),
- cert->cert());
-
- HandleResult(error, server_identifier, cert->private_key(), cert->cert());
+ channel_id_store_->SetChannelID(cert->server_identifier(),
+ cert->creation_time(), cert->private_key(),
+ cert->public_key());
+
+ HandleResult(error, server_identifier, cert->private_key(),
+ cert->public_key());
} else {
HandleResult(error, server_identifier, std::string(), std::string());
}
}
-void ChannelIDService::HandleResult(
- int error,
- const std::string& server_identifier,
- const std::string& private_key,
- const std::string& cert) {
+void ChannelIDService::HandleResult(int error,
+ const std::string& server_identifier,
+ const std::string& private_key,
+ const std::string& public_key) {
DCHECK(CalledOnValidThread());
std::map<std::string, ChannelIDServiceJob*>::iterator j;
@@ -585,15 +596,14 @@ void ChannelIDService::HandleResult(
ChannelIDServiceJob* job = j->second;
inflight_.erase(j);
- job->HandleResult(error, private_key, cert);
+ job->HandleResult(error, private_key, public_key);
delete job;
}
bool ChannelIDService::JoinToInFlightRequest(
const base::TimeTicks& request_start,
const std::string& domain,
- std::string* private_key,
- std::string* cert,
+ scoped_ptr<crypto::ECPrivateKey>* key,
bool create_if_missing,
const CompletionCallback& callback,
RequestHandle* out_req) {
@@ -607,11 +617,9 @@ bool ChannelIDService::JoinToInFlightRequest(
inflight_joins_++;
ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
- request_start,
- base::Bind(&RequestHandle::OnRequestComplete,
- base::Unretained(out_req)),
- private_key,
- cert);
+ request_start, base::Bind(&RequestHandle::OnRequestComplete,
+ base::Unretained(out_req)),
+ key);
job->AddRequest(request, create_if_missing);
out_req->RequestStarted(this, request, callback);
return true;
@@ -619,29 +627,29 @@ bool ChannelIDService::JoinToInFlightRequest(
return false;
}
-int ChannelIDService::LookupChannelID(
- const base::TimeTicks& request_start,
- const std::string& domain,
- std::string* private_key,
- std::string* cert,
- bool create_if_missing,
- const CompletionCallback& callback,
- RequestHandle* out_req) {
+int ChannelIDService::LookupChannelID(const base::TimeTicks& request_start,
+ const std::string& domain,
+ scoped_ptr<crypto::ECPrivateKey>* key,
+ bool create_if_missing,
+ const CompletionCallback& callback,
+ RequestHandle* out_req) {
// Check if a domain bound cert already exists for this domain. Note that
// |expiration_time| is ignored, and expired certs are considered valid.
- base::Time expiration_time;
+ std::string public_key;
+ std::string private_key;
int err = channel_id_store_->GetChannelID(
- domain,
- &expiration_time /* ignored */,
- private_key,
- cert,
+ domain, &private_key, &public_key,
base::Bind(&ChannelIDService::GotChannelID,
weak_ptr_factory_.GetWeakPtr()));
if (err == OK) {
+ err = CreateECPrivateKeyFromSerializedKey(public_key, private_key, key);
+ if (err != OK) {
+ return err;
+ }
// Sync lookup found a valid cert.
- DVLOG(1) << "Cert store had valid cert for " << domain;
- cert_store_hits_++;
+ DVLOG(1) << "Cert store had valid key for " << domain;
+ key_store_hits_++;
RecordGetChannelIDResult(SYNC_SUCCESS);
base::TimeDelta request_time = base::TimeTicks::Now() - request_start;
UMA_HISTOGRAM_TIMES("DomainBoundCerts.GetCertTimeSync", request_time);
@@ -655,11 +663,9 @@ int ChannelIDService::LookupChannelID(
inflight_[domain] = job;
ChannelIDServiceRequest* request = new ChannelIDServiceRequest(
- request_start,
- base::Bind(&RequestHandle::OnRequestComplete,
- base::Unretained(out_req)),
- private_key,
- cert);
+ request_start, base::Bind(&RequestHandle::OnRequestComplete,
+ base::Unretained(out_req)),
+ key);
job->AddRequest(request);
out_req->RequestStarted(this, request, callback);
return ERR_IO_PENDING;

Powered by Google App Engine
This is Rietveld 408576698