1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ 6 #define NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ 7 8 #include <map> 9 #include <string> 10 #include <vector> 11 12 #include "base/basictypes.h" 13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/weak_ptr.h" 15 #include "base/threading/non_thread_safe.h" 16 #include "base/time/time.h" 17 #include "net/base/completion_callback.h" 18 #include "net/base/net_export.h" 19 #include "net/ssl/server_bound_cert_store.h" 20 21 namespace base { 22 class TaskRunner; 23 } 24 25 namespace net { 26 27 class ServerBoundCertServiceJob; 28 class ServerBoundCertServiceRequest; 29 class ServerBoundCertServiceWorker; 30 31 // A class for creating and fetching server bound certs. These certs are used 32 // to identify users' machines; their public keys are used as channel IDs in 33 // http://tools.ietf.org/html/draft-balfanz-tls-channelid-00. 34 // As a result although certs are set to be invalid after one year, we don't 35 // actually expire them. Once generated, certs are valid as long as the users 36 // want. Users can delete existing certs, and new certs will be generated 37 // automatically. 38 39 // Inherits from NonThreadSafe in order to use the function 40 // |CalledOnValidThread|. 41 class NET_EXPORT ServerBoundCertService NON_EXPORTED_BASE(public base::NonThreadSafe)42 : NON_EXPORTED_BASE(public base::NonThreadSafe) { 43 public: 44 class NET_EXPORT RequestHandle { 45 public: 46 RequestHandle(); 47 ~RequestHandle(); 48 49 // Cancel the request. Does nothing if the request finished or was already 50 // cancelled. 51 void Cancel(); 52 53 bool is_active() const { return request_ != NULL; } 54 55 private: 56 friend class ServerBoundCertService; 57 58 void RequestStarted(ServerBoundCertService* service, 59 ServerBoundCertServiceRequest* request, 60 const CompletionCallback& callback); 61 62 void OnRequestComplete(int result); 63 64 ServerBoundCertService* service_; 65 ServerBoundCertServiceRequest* request_; 66 CompletionCallback callback_; 67 }; 68 69 // Password used on EncryptedPrivateKeyInfo data stored in EC private_key 70 // values. (This is not used to provide any security, but to workaround NSS 71 // being unable to import unencrypted PrivateKeyInfo for EC keys.) 72 static const char kEPKIPassword[]; 73 74 // This object owns |server_bound_cert_store|. |task_runner| will 75 // be used to post certificate generation worker tasks. The tasks are 76 // safe for use with WorkerPool and SequencedWorkerPool::CONTINUE_ON_SHUTDOWN. 77 ServerBoundCertService( 78 ServerBoundCertStore* server_bound_cert_store, 79 const scoped_refptr<base::TaskRunner>& task_runner); 80 81 ~ServerBoundCertService(); 82 83 // Returns the domain to be used for |host|. The domain is the 84 // "registry controlled domain", or the "ETLD + 1" where one exists, or 85 // the origin otherwise. 86 static std::string GetDomainForHost(const std::string& host); 87 88 // Tests whether the system time is within the supported range for 89 // certificate generation. This value is cached when ServerBoundCertService 90 // is created, so if the system time is changed by a huge amount, this may no 91 // longer hold. 92 bool IsSystemTimeValid() const { return is_system_time_valid_; } 93 94 // Fetches the domain bound cert for the specified host if one exists and 95 // creates one otherwise. Returns OK if successful or an error code upon 96 // failure. 97 // 98 // On successful completion, |private_key| stores a DER-encoded 99 // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. 100 // The PrivateKeyInfo is always an ECDSA private key. 101 // 102 // |callback| must not be null. ERR_IO_PENDING is returned if the operation 103 // could not be completed immediately, in which case the result code will 104 // be passed to the callback when available. 105 // 106 // |*out_req| will be initialized with a handle to the async request. This 107 // RequestHandle object must be cancelled or destroyed before the 108 // ServerBoundCertService is destroyed. 109 int GetOrCreateDomainBoundCert( 110 const std::string& host, 111 std::string* private_key, 112 std::string* cert, 113 const CompletionCallback& callback, 114 RequestHandle* out_req); 115 116 // Fetches the domain bound cert for the specified host if one exists. 117 // Returns OK if successful, ERR_FILE_NOT_FOUND if none exists, or an error 118 // code upon failure. 119 // 120 // On successful completion, |private_key| stores a DER-encoded 121 // PrivateKeyInfo struct, and |cert| stores a DER-encoded certificate. 122 // The PrivateKeyInfo is always an ECDSA private key. 123 // 124 // |callback| must not be null. ERR_IO_PENDING is returned if the operation 125 // could not be completed immediately, in which case the result code will 126 // be passed to the callback when available. If an in-flight 127 // GetDomainBoundCert is pending, and a new GetOrCreateDomainBoundCert 128 // request arrives for the same domain, the GetDomainBoundCert request will 129 // not complete until a new cert is created. 130 // 131 // |*out_req| will be initialized with a handle to the async request. This 132 // RequestHandle object must be cancelled or destroyed before the 133 // ServerBoundCertService is destroyed. 134 int GetDomainBoundCert( 135 const std::string& host, 136 std::string* private_key, 137 std::string* cert, 138 const CompletionCallback& callback, 139 RequestHandle* out_req); 140 141 // Returns the backing ServerBoundCertStore. 142 ServerBoundCertStore* GetCertStore(); 143 144 // Public only for unit testing. 145 int cert_count(); 146 uint64 requests() const { return requests_; } 147 uint64 cert_store_hits() const { return cert_store_hits_; } 148 uint64 inflight_joins() const { return inflight_joins_; } 149 uint64 workers_created() const { return workers_created_; } 150 151 private: 152 // Cancels the specified request. |req| is the handle stored by 153 // GetDomainBoundCert(). After a request is canceled, its completion 154 // callback will not be called. 155 void CancelRequest(ServerBoundCertServiceRequest* req); 156 157 void GotServerBoundCert(int err, 158 const std::string& server_identifier, 159 base::Time expiration_time, 160 const std::string& key, 161 const std::string& cert); 162 void GeneratedServerBoundCert( 163 const std::string& server_identifier, 164 int error, 165 scoped_ptr<ServerBoundCertStore::ServerBoundCert> cert); 166 void HandleResult(int error, 167 const std::string& server_identifier, 168 const std::string& private_key, 169 const std::string& cert); 170 171 // Searches for an in-flight request for the same domain. If found, 172 // attaches to the request and returns true. Returns false if no in-flight 173 // request is found. 174 bool JoinToInFlightRequest(const base::TimeTicks& request_start, 175 const std::string& domain, 176 std::string* private_key, 177 std::string* cert, 178 bool create_if_missing, 179 const CompletionCallback& callback, 180 RequestHandle* out_req); 181 182 // Looks for the domain bound cert for |domain| in this service's store. 183 // Returns OK if it can be found synchronously, ERR_IO_PENDING if the 184 // result cannot be obtained synchronously, or a network error code on 185 // failure (including failure to find a domain-bound cert of |domain|). 186 int LookupDomainBoundCert(const base::TimeTicks& request_start, 187 const std::string& domain, 188 std::string* private_key, 189 std::string* cert, 190 bool create_if_missing, 191 const CompletionCallback& callback, 192 RequestHandle* out_req); 193 194 scoped_ptr<ServerBoundCertStore> server_bound_cert_store_; 195 scoped_refptr<base::TaskRunner> task_runner_; 196 197 // inflight_ maps from a server to an active generation which is taking 198 // place. 199 std::map<std::string, ServerBoundCertServiceJob*> inflight_; 200 201 uint64 requests_; 202 uint64 cert_store_hits_; 203 uint64 inflight_joins_; 204 uint64 workers_created_; 205 206 bool is_system_time_valid_; 207 208 base::WeakPtrFactory<ServerBoundCertService> weak_ptr_factory_; 209 210 DISALLOW_COPY_AND_ASSIGN(ServerBoundCertService); 211 }; 212 213 } // namespace net 214 215 #endif // NET_SSL_SERVER_BOUND_CERT_SERVICE_H_ 216