summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorrkn@chromium.org <rkn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-28 21:39:36 +0000
committerrkn@chromium.org <rkn@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-07-28 21:39:36 +0000
commitde32371658280e962cb595dda3571ef8d98c0dfd (patch)
tree6b6a1044c3849f1a9b21c086f8524fb1933cfb8f /net
parent6e78dfb46a07e5ee38225e0cd32fa8b70ed41558 (diff)
downloadchromium_src-de32371658280e962cb595dda3571ef8d98c0dfd.zip
chromium_src-de32371658280e962cb595dda3571ef8d98c0dfd.tar.gz
chromium_src-de32371658280e962cb595dda3571ef8d98c0dfd.tar.bz2
Provides in memory and persistent storage for origin bound certificates, which are
specified at http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html. The code is based on cookie_monster.{cc,h} and sqlite_persistent_cookie_store.{cc,h}. BUG=88782 TEST=None Review URL: http://codereview.chromium.org/7342021 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@94553 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/default_origin_bound_cert_store.cc137
-rw-r--r--net/base/default_origin_bound_cert_store.h163
-rw-r--r--net/base/default_origin_bound_cert_store_unittest.cc112
-rw-r--r--net/base/origin_bound_cert_service.cc29
-rw-r--r--net/base/origin_bound_cert_service.h23
-rw-r--r--net/base/origin_bound_cert_service_unittest.cc68
-rw-r--r--net/base/origin_bound_cert_store.h25
-rw-r--r--net/net.gyp4
8 files changed, 536 insertions, 25 deletions
diff --git a/net/base/default_origin_bound_cert_store.cc b/net/base/default_origin_bound_cert_store.cc
new file mode 100644
index 0000000..e047af8
--- /dev/null
+++ b/net/base/default_origin_bound_cert_store.cc
@@ -0,0 +1,137 @@
+// Copyright (c) 2011 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/base/default_origin_bound_cert_store.h"
+
+#include "base/message_loop.h"
+
+namespace net {
+
+// static
+const size_t DefaultOriginBoundCertStore::kMaxCerts = 3300;
+
+DefaultOriginBoundCertStore::DefaultOriginBoundCertStore(
+ PersistentStore* store)
+ : initialized_(false),
+ store_(store) {}
+
+void DefaultOriginBoundCertStore::FlushStore(Task* completion_task) {
+ base::AutoLock autolock(lock_);
+
+ if (initialized_ && store_)
+ store_->Flush(completion_task);
+ else if (completion_task)
+ MessageLoop::current()->PostTask(FROM_HERE, completion_task);
+}
+
+bool DefaultOriginBoundCertStore::GetOriginBoundCert(
+ const std::string& origin,
+ std::string* private_key_result,
+ std::string* cert_result) {
+ base::AutoLock autolock(lock_);
+ InitIfNecessary();
+
+ OriginBoundCertMap::iterator it = origin_bound_certs_.find(origin);
+
+ if (it == origin_bound_certs_.end())
+ return false;
+
+ OriginBoundCert* cert = it->second;
+ *private_key_result = cert->private_key();
+ *cert_result = cert->cert();
+
+ return true;
+}
+
+bool DefaultOriginBoundCertStore::SetOriginBoundCert(
+ const std::string& origin,
+ const std::string& private_key,
+ const std::string& cert) {
+ base::AutoLock autolock(lock_);
+ InitIfNecessary();
+
+ InternalDeleteOriginBoundCert(origin);
+ InternalInsertOriginBoundCert(origin,
+ new OriginBoundCert(origin, private_key, cert));
+
+ return true;
+}
+
+int DefaultOriginBoundCertStore::GetCertCount() {
+ base::AutoLock autolock(lock_);
+ InitIfNecessary();
+
+ return origin_bound_certs_.size();
+}
+
+DefaultOriginBoundCertStore::~DefaultOriginBoundCertStore() {
+ DeleteAll();
+}
+
+void DefaultOriginBoundCertStore::DeleteAll() {
+ base::AutoLock autolock(lock_);
+
+ for (OriginBoundCertMap::iterator it = origin_bound_certs_.begin();
+ it != origin_bound_certs_.end(); it++) {
+ delete it->second;
+ }
+ origin_bound_certs_.clear();
+}
+
+void DefaultOriginBoundCertStore::InitStore() {
+ lock_.AssertAcquired();
+
+ DCHECK(store_) << "Store must exist to initialize";
+
+ // Initialize the store and sync in any saved persistent certs.
+ std::vector<OriginBoundCert*> certs;
+ // Reserve space for the maximum amount of certs a database should have.
+ // This prevents multiple vector growth / copies as we append certs.
+ certs.reserve(kMaxCerts);
+ store_->Load(&certs);
+
+ for (std::vector<OriginBoundCert*>::const_iterator it = certs.begin();
+ it != certs.end(); ++it) {
+ origin_bound_certs_[(*it)->origin()] = *it;
+ }
+}
+
+void DefaultOriginBoundCertStore::InternalDeleteOriginBoundCert(
+ const std::string& origin) {
+ lock_.AssertAcquired();
+
+ OriginBoundCertMap::iterator it = origin_bound_certs_.find(origin);
+ if (it == origin_bound_certs_.end())
+ return; // There is nothing to delete.
+
+ OriginBoundCert* cert = it->second;
+ if (store_)
+ store_->DeleteOriginBoundCert(*cert);
+ origin_bound_certs_.erase(it);
+ delete cert;
+}
+
+void DefaultOriginBoundCertStore::InternalInsertOriginBoundCert(
+ const std::string& origin,
+ OriginBoundCert* cert) {
+ lock_.AssertAcquired();
+
+ if (store_)
+ store_->AddOriginBoundCert(*cert);
+ origin_bound_certs_[origin] = cert;
+}
+
+DefaultOriginBoundCertStore::OriginBoundCert::OriginBoundCert() {}
+
+DefaultOriginBoundCertStore::OriginBoundCert::OriginBoundCert(
+ const std::string& origin,
+ const std::string& private_key,
+ const std::string& cert)
+ : origin_(origin),
+ private_key_(private_key),
+ cert_(cert) {}
+
+DefaultOriginBoundCertStore::PersistentStore::PersistentStore() {}
+
+} // namespace net
diff --git a/net/base/default_origin_bound_cert_store.h b/net/base/default_origin_bound_cert_store.h
new file mode 100644
index 0000000..4b8b8a9
--- /dev/null
+++ b/net/base/default_origin_bound_cert_store.h
@@ -0,0 +1,163 @@
+// Copyright (c) 2011 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.
+
+#ifndef NET_BASE_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_
+#define NET_BASE_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_
+#pragma once
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "net/base/origin_bound_cert_store.h"
+
+class Task;
+
+namespace net {
+
+// This class is the system for storing and retrieving origin bound certs.
+// Modelled after the CookieMonster class, it has an in-memory cert store,
+// and synchronizes origin bound certs to an optional permanent storage that
+// implements the PersistentStore interface. The use case is described in
+// http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html
+//
+// This class can be accessed by multiple threads. For example, it can be used
+// by IO and origin bound cert management UI.
+class DefaultOriginBoundCertStore : public OriginBoundCertStore {
+ public:
+ class OriginBoundCert;
+ class PersistentStore;
+
+ // The key for each OriginBoundCert* in OriginBoundCertMap is the
+ // corresponding origin.
+ typedef std::map<std::string, OriginBoundCert*> OriginBoundCertMap;
+
+ // The store passed in should not have had Init() called on it yet. This
+ // class will take care of initializing it. The backing store is NOT owned by
+ // this class, but it must remain valid for the duration of the
+ // DefaultOriginBoundCertStore's existence. If |store| is NULL, then no
+ // backing store will be updated.
+ explicit DefaultOriginBoundCertStore(PersistentStore* store);
+
+ virtual ~DefaultOriginBoundCertStore();
+
+ // Flush the backing store (if any) to disk and post the given task when done.
+ // WARNING: THE CALLBACK WILL RUN ON A RANDOM THREAD. IT MUST BE THREAD SAFE.
+ // It may be posted to the current thread, or it may run on the thread that
+ // actually does the flushing. Your Task should generally post a notification
+ // to the thread you actually want to be notified on.
+ void FlushStore(Task* completion_task);
+
+ // OriginBoundCertStore implementation.
+ virtual bool GetOriginBoundCert(const std::string& origin,
+ std::string* private_key_result,
+ std::string* cert_result) OVERRIDE;
+ virtual bool SetOriginBoundCert(const std::string& origin,
+ const std::string& private_key,
+ const std::string& cert) OVERRIDE;
+ virtual int GetCertCount() OVERRIDE;
+
+ private:
+ static const size_t kMaxCerts;
+
+ // Deletes all of the certs. Does not delete them from |store_|.
+ void DeleteAll();
+
+ // Called by all non-static functions to ensure that the cert store has
+ // been initialized. This is not done during creating so it doesn't block
+ // the window showing.
+ // Note: this method should always be called with lock_ held.
+ void InitIfNecessary() {
+ if (!initialized_) {
+ if (store_)
+ InitStore();
+ initialized_ = true;
+ }
+ }
+
+ // Initializes the backing store and reads existing certs from it.
+ // Should only be called by InitIfNecessary().
+ void InitStore();
+
+ // Deletes the cert for the specified origin, if such a cert exists, from the
+ // in-memory store. Deletes it from |store_| if |store_| is not NULL.
+ void InternalDeleteOriginBoundCert(const std::string& origin);
+
+ // Takes ownership of *cert.
+ // Adds the cert for the specified origin to the in-memory store. Deletes it
+ // from |store_| if |store_| is not NULL.
+ void InternalInsertOriginBoundCert(const std::string& origin,
+ OriginBoundCert* cert);
+
+ // Indicates whether the cert store has been initialized. This happens
+ // Lazily in InitStoreIfNecessary().
+ bool initialized_;
+
+ scoped_refptr<PersistentStore> store_;
+
+ OriginBoundCertMap origin_bound_certs_;
+
+ // Lock for thread-safety
+ base::Lock lock_;
+
+ DISALLOW_COPY_AND_ASSIGN(DefaultOriginBoundCertStore);
+};
+
+// The OriginBoundCert class contains a private key in addition to the origin
+// and the cert.
+class DefaultOriginBoundCertStore::OriginBoundCert {
+ public:
+ OriginBoundCert();
+ OriginBoundCert(const std::string& origin,
+ const std::string& privatekey,
+ const std::string& cert);
+
+ const std::string& origin() const { return origin_; }
+ const std::string& private_key() const { return private_key_; }
+ const std::string& cert() const { return cert_; }
+
+ private:
+ std::string origin_;
+ std::string private_key_;
+ std::string cert_;
+};
+
+typedef base::RefCountedThreadSafe<DefaultOriginBoundCertStore::PersistentStore>
+ RefcountedPersistentStore;
+
+class DefaultOriginBoundCertStore::PersistentStore
+ : public RefcountedPersistentStore {
+ public:
+ virtual ~PersistentStore() {}
+
+ // Initializes the store and retrieves the existing certs. This will be
+ // called only once at startup. Note that the certs are individually allocated
+ // and that ownership is transferred to the caller upon return.
+ virtual bool Load(
+ std::vector<DefaultOriginBoundCertStore::OriginBoundCert*>* certs) = 0;
+
+ virtual void AddOriginBoundCert(const OriginBoundCert& cert) = 0;
+
+ virtual void DeleteOriginBoundCert(const OriginBoundCert& cert) = 0;
+
+ // Sets the value of the user preference whether the persistent storage
+ // must be deleted upon destruction.
+ virtual void SetClearLocalStateOnExit(bool clear_local_state) = 0;
+
+ // Flush the store and post the given Task when complete.
+ virtual void Flush(Task* completion_task) = 0;
+
+ protected:
+ PersistentStore();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(PersistentStore);
+};
+
+} // namespace net
+
+#endif // NET_DEFAULT_ORIGIN_BOUND_CERT_STORE_H_
diff --git a/net/base/default_origin_bound_cert_store_unittest.cc b/net/base/default_origin_bound_cert_store_unittest.cc
new file mode 100644
index 0000000..5fe77ef
--- /dev/null
+++ b/net/base/default_origin_bound_cert_store_unittest.cc
@@ -0,0 +1,112 @@
+// Copyright (c) 2011 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/base/default_origin_bound_cert_store.h"
+
+#include <map>
+#include <string>
+#include <vector>
+
+#include "base/compiler_specific.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+class MockPersistentStore
+ : public DefaultOriginBoundCertStore::PersistentStore {
+ public:
+ MockPersistentStore();
+ virtual ~MockPersistentStore();
+
+ // DefaultOriginBoundCertStore::PersistentStore implementation.
+ virtual bool Load(
+ std::vector<DefaultOriginBoundCertStore::OriginBoundCert*>* certs)
+ OVERRIDE;
+ virtual void AddOriginBoundCert(
+ const DefaultOriginBoundCertStore::OriginBoundCert& cert) OVERRIDE;
+ virtual void DeleteOriginBoundCert(
+ const DefaultOriginBoundCertStore::OriginBoundCert& cert) OVERRIDE;
+ virtual void SetClearLocalStateOnExit(bool clear_local_state) OVERRIDE;
+ virtual void Flush(Task* completion_task) OVERRIDE;
+
+ private:
+ typedef std::map<std::string, DefaultOriginBoundCertStore::OriginBoundCert>
+ OriginBoundCertMap;
+
+ OriginBoundCertMap origin_certs_;
+};
+
+MockPersistentStore::MockPersistentStore() {}
+
+MockPersistentStore::~MockPersistentStore() {}
+
+bool MockPersistentStore::Load(
+ std::vector<DefaultOriginBoundCertStore::OriginBoundCert*>* certs) {
+ OriginBoundCertMap::iterator it;
+
+ for (it = origin_certs_.begin(); it != origin_certs_.end(); ++it) {
+ certs->push_back(
+ new DefaultOriginBoundCertStore::OriginBoundCert(it->second));
+ }
+
+ return true;
+}
+
+void MockPersistentStore::AddOriginBoundCert(
+ const DefaultOriginBoundCertStore::OriginBoundCert& cert) {
+ origin_certs_[cert.origin()] = cert;
+}
+
+void MockPersistentStore::DeleteOriginBoundCert(
+ const DefaultOriginBoundCertStore::OriginBoundCert& cert) {
+ origin_certs_.erase(cert.origin());
+}
+
+void MockPersistentStore::SetClearLocalStateOnExit(bool clear_local_state) {}
+
+void MockPersistentStore::Flush(Task* completion_task) {
+ NOTREACHED();
+}
+
+TEST(DefaultOriginBoundCertStoreTest, TestLoading) {
+ scoped_refptr<MockPersistentStore> persistent_store(new MockPersistentStore);
+
+ persistent_store->AddOriginBoundCert(
+ DefaultOriginBoundCertStore::OriginBoundCert(
+ "https://encrypted.google.com/", "a", "b"));
+ persistent_store->AddOriginBoundCert(
+ DefaultOriginBoundCertStore::OriginBoundCert(
+ "https://www.verisign.com/", "c", "d"));
+
+ // Make sure certs load properly.
+ scoped_ptr<DefaultOriginBoundCertStore> store(
+ new DefaultOriginBoundCertStore(persistent_store));
+ EXPECT_EQ(2, store->GetCertCount());
+ EXPECT_TRUE(store->SetOriginBoundCert("https://www.verisign.com/", "e", "f"));
+ EXPECT_EQ(2, store->GetCertCount());
+ EXPECT_TRUE(store->SetOriginBoundCert("https://www.twitter.com/", "g", "h"));
+ EXPECT_EQ(3, store->GetCertCount());
+}
+
+TEST(DefaultOriginBoundCertStoreTest, TestSettingAndGetting) {
+ scoped_ptr<DefaultOriginBoundCertStore> store(
+ new DefaultOriginBoundCertStore(NULL));
+ std::string private_key, cert;
+ EXPECT_EQ(0, store->GetCertCount());
+ EXPECT_FALSE(store->GetOriginBoundCert("https://www.verisign.com/",
+ &private_key,
+ &cert));
+ EXPECT_TRUE(private_key.empty());
+ EXPECT_TRUE(cert.empty());
+ EXPECT_TRUE(store->SetOriginBoundCert("https://www.verisign.com/", "i", "j"));
+ EXPECT_TRUE(store->GetOriginBoundCert("https://www.verisign.com/",
+ &private_key,
+ &cert));
+ EXPECT_EQ("i", private_key);
+ EXPECT_EQ("j", cert);
+}
+
+} // namespace net
diff --git a/net/base/origin_bound_cert_service.cc b/net/base/origin_bound_cert_service.cc
index 0d706bc..61a80eb 100644
--- a/net/base/origin_bound_cert_service.cc
+++ b/net/base/origin_bound_cert_service.cc
@@ -11,7 +11,6 @@
#include "base/memory/scoped_ptr.h"
#include "base/rand_util.h"
#include "crypto/rsa_private_key.h"
-#include "googleurl/src/gurl.h"
#include "net/base/origin_bound_cert_store.h"
#include "net/base/x509_certificate.h"
@@ -24,19 +23,23 @@ const int kValidityPeriodInDays = 365;
} // namespace
-bool OriginBoundCertService::GetOriginBoundCert(const GURL& url,
+OriginBoundCertService::OriginBoundCertService(
+ OriginBoundCertStore* origin_bound_cert_store)
+ : origin_bound_cert_store_(origin_bound_cert_store) {}
+
+OriginBoundCertService::~OriginBoundCertService() {}
+
+bool OriginBoundCertService::GetOriginBoundCert(const std::string& origin,
std::string* private_key_result,
std::string* cert_result) {
// Check if origin bound cert already exists for this origin.
- if (origin_bound_cert_store_->HasOriginBoundCert(url)) {
- return origin_bound_cert_store_->GetOriginBoundCert(url,
- private_key_result,
- cert_result);
- }
+ if (origin_bound_cert_store_->GetOriginBoundCert(origin,
+ private_key_result,
+ cert_result))
+ return true;
// No origin bound cert exists, we have to create one.
- std::string origin = url.GetOrigin().spec();
- std::string subject = "CN=origin-bound certificate for " + origin;
+ std::string subject = "CN=OBC";
scoped_ptr<crypto::RSAPrivateKey> key(
crypto::RSAPrivateKey::Create(kKeySizeInBits));
if (!key.get()) {
@@ -68,7 +71,9 @@ bool OriginBoundCertService::GetOriginBoundCert(const GURL& url,
return false;
}
- if (!origin_bound_cert_store_->SetOriginBoundCert(url, key_out, der_cert)) {
+ if (!origin_bound_cert_store_->SetOriginBoundCert(origin,
+ key_out,
+ der_cert)) {
LOG(WARNING) << "Unable to set origin bound certificate";
return false;
}
@@ -78,4 +83,8 @@ bool OriginBoundCertService::GetOriginBoundCert(const GURL& url,
return true;
}
+int OriginBoundCertService::GetCertCount() {
+ return origin_bound_cert_store_->GetCertCount();
+}
+
} // namespace net
diff --git a/net/base/origin_bound_cert_service.h b/net/base/origin_bound_cert_service.h
index c1d65b9..9f700b9 100644
--- a/net/base/origin_bound_cert_service.h
+++ b/net/base/origin_bound_cert_service.h
@@ -8,30 +8,39 @@
#include <string>
-class GURL;
+#include "base/memory/ref_counted.h"
+#include "base/memory/scoped_ptr.h"
namespace net {
class OriginBoundCertStore;
// A class for creating and fetching origin bound certs.
-class OriginBoundCertService {
+class OriginBoundCertService
+ : public base::RefCountedThreadSafe<OriginBoundCertService> {
public:
- explicit OriginBoundCertService(OriginBoundCertStore* origin_bound_cert_store)
- : origin_bound_cert_store_(origin_bound_cert_store) {}
+ // This object owns origin_bound_cert_store.
+ explicit OriginBoundCertService(
+ OriginBoundCertStore* origin_bound_cert_store);
+
+ ~OriginBoundCertService();
// TODO(rkn): Specify certificate type (RSA or DSA).
// TODO(rkn): Key generation can be time consuming, so this should have an
// asynchronous interface.
// Fetches the origin bound cert for the specified origin if one exists
// and creates one otherwise. On success, |private_key_result| stores a
- // PrivateKeyInfo struct, and |cert_result| stores a DER-encoded certificate.
- bool GetOriginBoundCert(const GURL& url,
+ // DER-encoded PrivateKeyInfo struct, and |cert_result| stores a DER-encoded
+ // certificate.
+ bool GetOriginBoundCert(const std::string& origin,
std::string* private_key_result,
std::string* cert_result);
+ // Public only for unit testing.
+ int GetCertCount();
+
private:
- OriginBoundCertStore* origin_bound_cert_store_;
+ scoped_ptr<OriginBoundCertStore> origin_bound_cert_store_;
};
} // namespace net
diff --git a/net/base/origin_bound_cert_service_unittest.cc b/net/base/origin_bound_cert_service_unittest.cc
new file mode 100644
index 0000000..59be848
--- /dev/null
+++ b/net/base/origin_bound_cert_service_unittest.cc
@@ -0,0 +1,68 @@
+// Copyright (c) 2011 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/base/origin_bound_cert_service.h"
+
+#include <string>
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "crypto/rsa_private_key.h"
+#include "net/base/default_origin_bound_cert_store.h"
+#include "net/base/x509_certificate.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace net {
+
+TEST(OriginBoundCertServiceTest, DuplicateCertTest) {
+ scoped_refptr<OriginBoundCertService> service(
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
+ std::string origin1("https://encrypted.google.com/");
+ std::string origin2("https://www.verisign.com/");
+
+ // The store should start out empty and should increment appropriately.
+ std::string private_key_info_1a, der_cert_1a;
+ EXPECT_EQ(0, service->GetCertCount());
+ EXPECT_TRUE(service->GetOriginBoundCert(
+ origin1, &private_key_info_1a, &der_cert_1a));
+ EXPECT_EQ(1, service->GetCertCount());
+
+ // We should get the same cert and key for the same origin.
+ std::string private_key_info_1b, der_cert_1b;
+ EXPECT_TRUE(service->GetOriginBoundCert(
+ origin1, &private_key_info_1b, &der_cert_1b));
+ EXPECT_EQ(1, service->GetCertCount());
+ EXPECT_EQ(private_key_info_1a, private_key_info_1b);
+ EXPECT_EQ(der_cert_1a, der_cert_1b);
+
+ // We should get a different cert and key for different origins.
+ std::string private_key_info_2, der_cert_2;
+ EXPECT_TRUE(service->GetOriginBoundCert(
+ origin2, &private_key_info_2, &der_cert_2));
+ EXPECT_EQ(2, service->GetCertCount());
+ EXPECT_NE(private_key_info_1a, private_key_info_2);
+ EXPECT_NE(der_cert_1a, der_cert_2);
+}
+
+TEST(OriginBoundCertServiceTest, ExtractValuesFromBytes) {
+ scoped_refptr<OriginBoundCertService> service(
+ new OriginBoundCertService(new DefaultOriginBoundCertStore(NULL)));
+ std::string origin("https://encrypted.google.com/");
+ std::string private_key_info, der_cert;
+ EXPECT_TRUE(service->GetOriginBoundCert(
+ origin, &private_key_info, &der_cert));
+ std::vector<uint8> key_vec(private_key_info.begin(), private_key_info.end());
+
+ // Check that we can retrieve the key pair from the bytes.
+ scoped_ptr<crypto::RSAPrivateKey> private_key(
+ crypto::RSAPrivateKey::CreateFromPrivateKeyInfo(key_vec));
+ EXPECT_TRUE(private_key != NULL);
+
+ // Check that we can retrieve the cert from the bytes.
+ scoped_refptr<X509Certificate> x509cert(
+ X509Certificate::CreateFromBytes(der_cert.data(), der_cert.size()));
+ EXPECT_TRUE(x509cert != NULL);
+}
+
+} // namespace net
diff --git a/net/base/origin_bound_cert_store.h b/net/base/origin_bound_cert_store.h
index 8529fbd..63989f5 100644
--- a/net/base/origin_bound_cert_store.h
+++ b/net/base/origin_bound_cert_store.h
@@ -8,29 +8,38 @@
#include <string>
-class GURL;
-
namespace net {
// An interface for storing and retrieving origin bound certs. Origin bound
// certificates are specified in
// http://balfanz.github.com/tls-obc-spec/draft-balfanz-tls-obc-00.html.
+// Owned only by a single OriginBoundCertService object, which is responsible
+// for deleting it.
+
class OriginBoundCertStore {
public:
- virtual bool HasOriginBoundCert(const GURL& url) = 0;
+ virtual ~OriginBoundCertStore() {}
// TODO(rkn): Specify certificate type (RSA or DSA).
- // TODO(rkn): Key generation can be time consuming, so this should have an
- // asynchronous interface.
- // The output is stored in |private_key_result| and |cert_result|.
- virtual bool GetOriginBoundCert(const GURL& url,
+ // TODO(rkn): File I/O may be required, so this should have an asynchronous
+ // interface.
+ // Returns true on success. |private_key_result| stores a DER-encoded
+ // PrivateKeyInfo struct and |cert_result| stores a DER-encoded
+ // certificate. Returns false if no origin bound cert exists for the
+ // specified origin.
+ virtual bool GetOriginBoundCert(const std::string& origin,
std::string* private_key_result,
std::string* cert_result) = 0;
- virtual bool SetOriginBoundCert(const GURL& url,
+ // Adds an origin bound cert to the store.
+ virtual bool SetOriginBoundCert(const std::string& origin,
const std::string& private_key,
const std::string& cert) = 0;
+
+ // Returns the number of certs in the store.
+ // Public only for unit testing.
+ virtual int GetCertCount() = 0;
};
} // namespace net
diff --git a/net/net.gyp b/net/net.gyp
index 4ae27c0..de2b4df 100644
--- a/net/net.gyp
+++ b/net/net.gyp
@@ -67,6 +67,8 @@
'base/crypto_module_openssl.cc',
'base/data_url.cc',
'base/data_url.h',
+ 'base/default_origin_bound_cert_store.cc',
+ 'base/default_origin_bound_cert_store.h',
'base/directory_lister.cc',
'base/directory_lister.h',
'base/dns_reload_timer.cc',
@@ -877,6 +879,7 @@
'base/cookie_monster_unittest.cc',
'base/crl_filter_unittest.cc',
'base/data_url_unittest.cc',
+ 'base/default_origin_bound_cert_store_unittest.cc',
'base/directory_lister_unittest.cc',
'base/dnssec_unittest.cc',
'base/dns_util_unittest.cc',
@@ -900,6 +903,7 @@
'base/net_log_unittest.cc',
'base/net_log_unittest.h',
'base/net_util_unittest.cc',
+ 'base/origin_bound_cert_service_unittest.cc',
'base/pem_tokenizer_unittest.cc',
'base/registry_controlled_domain_unittest.cc',
'base/run_all_unittests.cc',