1 // Copyright 2014 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.
5 #ifndef NET_SSL_CHANNEL_ID_SERVICE_H_
6 #define NET_SSL_CHANNEL_ID_SERVICE_H_
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/channel_id_store.h"
27 class ChannelIDServiceJob
;
28 class ChannelIDServiceRequest
;
29 class ChannelIDServiceWorker
;
31 // A class for creating and fetching domain bound certs. They 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
39 // Inherits from NonThreadSafe in order to use the function
40 // |CalledOnValidThread|.
41 class NET_EXPORT ChannelIDService
42 : NON_EXPORTED_BASE(public base::NonThreadSafe
) {
44 class NET_EXPORT RequestHandle
{
49 // Cancel the request. Does nothing if the request finished or was already
53 bool is_active() const { return request_
!= NULL
; }
56 friend class ChannelIDService
;
58 void RequestStarted(ChannelIDService
* service
,
59 ChannelIDServiceRequest
* request
,
60 const CompletionCallback
& callback
);
62 void OnRequestComplete(int result
);
64 ChannelIDService
* service_
;
65 ChannelIDServiceRequest
* request_
;
66 CompletionCallback callback_
;
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
[];
74 // This object owns |channel_id_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.
78 ChannelIDStore
* channel_id_store
,
79 const scoped_refptr
<base::TaskRunner
>& task_runner
);
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
);
88 // Tests whether the system time is within the supported range for
89 // certificate generation. This value is cached when ChannelIDService
90 // is created, so if the system time is changed by a huge amount, this may no
92 bool IsSystemTimeValid() const { return is_system_time_valid_
; }
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
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.
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.
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 // ChannelIDService is destroyed.
109 int GetOrCreateChannelID(
110 const std::string
& host
,
111 std::string
* private_key
,
113 const CompletionCallback
& callback
,
114 RequestHandle
* out_req
);
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.
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.
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 // GetChannelID is pending, and a new GetOrCreateDomainBoundCert
128 // request arrives for the same domain, the GetChannelID request will
129 // not complete until a new cert is created.
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 // ChannelIDService is destroyed.
135 const std::string
& host
,
136 std::string
* private_key
,
138 const CompletionCallback
& callback
,
139 RequestHandle
* out_req
);
141 // Returns the backing ChannelIDStore.
142 ChannelIDStore
* GetChannelIDStore();
144 // Public only for unit testing.
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_
; }
152 // Cancels the specified request. |req| is the handle stored by
153 // GetChannelID(). After a request is canceled, its completion
154 // callback will not be called.
155 void CancelRequest(ChannelIDServiceRequest
* req
);
157 void GotChannelID(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 GeneratedChannelID(
163 const std::string
& server_identifier
,
165 scoped_ptr
<ChannelIDStore::ChannelID
> channel_id
);
166 void HandleResult(int error
,
167 const std::string
& server_identifier
,
168 const std::string
& private_key
,
169 const std::string
& cert
);
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
174 bool JoinToInFlightRequest(const base::TimeTicks
& request_start
,
175 const std::string
& domain
,
176 std::string
* private_key
,
178 bool create_if_missing
,
179 const CompletionCallback
& callback
,
180 RequestHandle
* out_req
);
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 LookupChannelID(const base::TimeTicks
& request_start
,
187 const std::string
& domain
,
188 std::string
* private_key
,
190 bool create_if_missing
,
191 const CompletionCallback
& callback
,
192 RequestHandle
* out_req
);
194 scoped_ptr
<ChannelIDStore
> channel_id_store_
;
195 scoped_refptr
<base::TaskRunner
> task_runner_
;
197 // inflight_ maps from a server to an active generation which is taking
199 std::map
<std::string
, ChannelIDServiceJob
*> inflight_
;
202 uint64 cert_store_hits_
;
203 uint64 inflight_joins_
;
204 uint64 workers_created_
;
206 bool is_system_time_valid_
;
208 base::WeakPtrFactory
<ChannelIDService
> weak_ptr_factory_
;
210 DISALLOW_COPY_AND_ASSIGN(ChannelIDService
);
215 #endif // NET_SSL_CHANNEL_ID_SERVICE_H_