diff options
Diffstat (limited to 'chromium/net/ssl/server_bound_cert_service.h')
-rw-r--r-- | chromium/net/ssl/server_bound_cert_service.h | 214 |
1 files changed, 214 insertions, 0 deletions
diff --git a/chromium/net/ssl/server_bound_cert_service.h b/chromium/net/ssl/server_bound_cert_service.h new file mode 100644 index 00000000000..0dc7f4ae390 --- /dev/null +++ b/chromium/net/ssl/server_bound_cert_service.h @@ -0,0 +1,214 @@ +// Copyright (c) 2012 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_SSL_SERVER_BOUND_CERT_SERVICE_H_ +#define NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ + +#include <map> +#include <string> +#include <vector> + +#include "base/basictypes.h" +#include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" +#include "base/threading/non_thread_safe.h" +#include "base/time/time.h" +#include "net/base/completion_callback.h" +#include "net/base/net_export.h" +#include "net/ssl/server_bound_cert_store.h" + +namespace base { +class TaskRunner; +} + +namespace net { + +class ServerBoundCertServiceJob; +class ServerBoundCertServiceRequest; +class ServerBoundCertServiceWorker; + +// A class for creating and fetching server bound certs. These certs are used +// to identify users' machines; their public keys are used as channel IDs in +// http://tools.ietf.org/html/draft-balfanz-tls-channelid-00. +// As a result although certs are set to be invalid after one year, we don't +// actually expire them. Once generated, certs are valid as long as the users +// want. Users can delete existing certs, and new certs will be generated +// automatically. + +// Inherits from NonThreadSafe in order to use the function +// |CalledOnValidThread|. +class NET_EXPORT ServerBoundCertService + : NON_EXPORTED_BASE(public base::NonThreadSafe) { + public: + class NET_EXPORT RequestHandle { + public: + RequestHandle(); + ~RequestHandle(); + + // Cancel the request. Does nothing if the request finished or was already + // cancelled. + void Cancel(); + + bool is_active() const { return request_ != NULL; } + + private: + friend class ServerBoundCertService; + + void RequestStarted(ServerBoundCertService* service, + ServerBoundCertServiceRequest* request, + const CompletionCallback& callback); + + void OnRequestComplete(int result); + + ServerBoundCertService* service_; + ServerBoundCertServiceRequest* request_; + CompletionCallback callback_; + }; + + // Password used on EncryptedPrivateKeyInfo data stored in EC private_key + // values. (This is not used to provide any security, but to workaround NSS + // being unable to import unencrypted PrivateKeyInfo for EC keys.) + static const char kEPKIPassword[]; + + // This object owns |server_bound_cert_store|. |task_runner| will + // be used to post certificate generation worker tasks. The tasks are + // safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN. + ServerBoundCertService( + ServerBoundCertStore* server_bound_cert_store, + const scoped_refptr<base::TaskRunner>& task_runner); + + ~ServerBoundCertService(); + + // Returns the domain to be used for |host|. The domain is the + // "registry controlled domain", or the "ETLD + 1" where one exists, or + // the origin otherwise. + static std::string GetDomainForHost(const std::string& host); + + // Tests whether the system time is within the supported range for + // certificate generation. This value is cached when ServerBoundCertService + // is created, so if the system time is changed by a huge amount, this may no + // longer hold. + bool IsSystemTimeValid() const { return is_system_time_valid_; } + + // Fetches the domain bound cert for the specified host if one exists and + // creates one otherwise. Returns OK if successful or an error code upon + // failure. + // + // On successful completion, |private_key| stores a DER-encoded + // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. + // The PrivateKeyInfo is always an ECDSA private key. + // + // |callback| must not be null. ERR_IO_PENDING is returned if the operation + // could not be completed immediately, in which case the result code will + // be passed to the callback when available. + // + // |*out_req| will be initialized with a handle to the async request. This + // RequestHandle object must be cancelled or destroyed before the + // ServerBoundCertService is destroyed. + int GetOrCreateDomainBoundCert( + const std::string& host, + std::string* private_key, + std::string* cert, + const CompletionCallback& callback, + RequestHandle* out_req); + + // Fetches the domain bound cert for the specified host if one exists. + // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error + // code upon failure. + // + // On successful completion, |private_key| stores a DER-encoded + // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. + // The PrivateKeyInfo is always an ECDSA private key. + // + // |callback| must not be null. ERR_IO_PENDING is returned if the operation + // could not be completed immediately, in which case the result code will + // be passed to the callback when available. If an in-flight + // GetDomainBoundCert is pending, and a new GetOrCreateDomainBoundCert + // request arrives for the same domain, the GetDomainBoundCert request will + // not complete until a new cert is created. + // + // |*out_req| will be initialized with a handle to the async request. This + // RequestHandle object must be cancelled or destroyed before the + // ServerBoundCertService is destroyed. + int GetDomainBoundCert( + const std::string& host, + std::string* private_key, + std::string* cert, + const CompletionCallback& callback, + RequestHandle* out_req); + + // Returns the backing ServerBoundCertStore. + ServerBoundCertStore* GetCertStore(); + + // Public only for unit testing. + int cert_count(); + uint64 requests() const { return requests_; } + uint64 cert_store_hits() const { return cert_store_hits_; } + uint64 inflight_joins() const { return inflight_joins_; } + uint64 workers_created() const { return workers_created_; } + + private: + // Cancels the specified request. |req| is the handle stored by + // GetDomainBoundCert(). After a request is canceled, its completion + // callback will not be called. + void CancelRequest(ServerBoundCertServiceRequest* req); + + void GotServerBoundCert(int err, + const std::string& server_identifier, + base::Time expiration_time, + const std::string& key, + const std::string& cert); + void GeneratedServerBoundCert( + const std::string& server_identifier, + int error, + scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert); + void HandleResult(int error, + const std::string& server_identifier, + const std::string& private_key, + const std::string& cert); + + // Searches for an in-flight request for the same domain. If found, + // attaches to the request and returns true. Returns false if no in-flight + // request is found. + bool JoinToInFlightRequest(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); + + // Looks for the domain bound cert for |domain| in this service's store. + // Returns OK if it can be found synchronously, ERR_IO_PENDING if the + // result cannot be obtained synchronously, or a network error code on + // failure (including failure to find a domain-bound cert of |domain|). + int LookupDomainBoundCert(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); + + scoped_ptr<ServerBoundCertStore> server_bound_cert_store_; + scoped_refptr<base::TaskRunner> task_runner_; + + // inflight_ maps from a server to an active generation which is taking + // place. + std::map<std::string, ServerBoundCertServiceJob*> inflight_; + base::WeakPtrFactory<ServerBoundCertService> weak_ptr_factory_; + + uint64 requests_; + uint64 cert_store_hits_; + uint64 inflight_joins_; + uint64 workers_created_; + + bool is_system_time_valid_; + + DISALLOW_COPY_AND_ASSIGN(ServerBoundCertService); +}; + +} // namespace net + +#endif // NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ |