- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / chromeos / attestation / platform_verification_flow.h
1 // Copyright 2013 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 CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
6 #define CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
7
8 #include <string>
9
10 #include "base/basictypes.h"
11 #include "base/callback.h"
12 #include "base/memory/ref_counted.h"
13 #include "base/memory/scoped_ptr.h"
14 #include "base/time/time.h"
15 #include "base/timer/timer.h"
16 #include "url/gurl.h"
17
18 class HostContentSettingsMap;
19 class PrefService;
20
21 namespace content {
22 class WebContents;
23 }
24
25 namespace cryptohome {
26 class AsyncMethodCaller;
27 }
28
29 namespace user_prefs {
30 class PrefRegistrySyncable;
31 }
32
33 namespace chromeos {
34
35 class CryptohomeClient;
36 class UserManager;
37 class User;
38
39 namespace attestation {
40
41 class AttestationFlow;
42 class PlatformVerificationFlowTest;
43
44 // This class allows platform verification for the content protection use case.
45 // All methods must only be called on the UI thread.  Example:
46 //   scoped_refptr<PlatformVerificationFlow> verifier =
47 //       new PlatformVerificationFlow();
48 //   PlatformVerificationFlow::Callback callback = base::Bind(&MyCallback);
49 //   verifier->ChallengePlatformKey(my_web_contents, "my_id", "some_challenge",
50 //                                  callback);
51 //
52 // This class is RefCountedThreadSafe because it may need to outlive its caller.
53 // The attestation flow that needs to happen to establish a certified platform
54 // key may take minutes on some hardware.  This class will timeout after a much
55 // shorter time so the caller can proceed without platform verification but it
56 // is important that the pending operation be allowed to finish.  If the
57 // attestation flow is aborted at any stage, it will need to start over.  If we
58 // use weak pointers, the attestation flow will stop when the next callback is
59 // run.  So we need the instance to stay alive until the platform key is fully
60 // certified so the next time ChallegePlatformKey() is invoked it will be quick.
61 class PlatformVerificationFlow
62     : public base::RefCountedThreadSafe<PlatformVerificationFlow> {
63  public:
64   enum Result {
65     SUCCESS,                // The operation succeeded.
66     INTERNAL_ERROR,         // The operation failed unexpectedly.
67     PLATFORM_NOT_VERIFIED,  // The platform cannot be verified.  For example:
68                             // - It is not a Chrome device.
69                             // - It is not running a verified OS image.
70     USER_REJECTED,          // The user explicitly rejected the operation.
71     POLICY_REJECTED,        // The operation is not allowed by policy/settings.
72     TIMEOUT,                // The operation timed out.
73   };
74
75   enum ConsentResponse {
76     CONSENT_RESPONSE_NONE,
77     CONSENT_RESPONSE_ALLOW,
78     CONSENT_RESPONSE_DENY,
79   };
80
81   // An interface which allows settings and UI to be abstracted for testing
82   // purposes.  For normal operation the default implementation should be used.
83   class Delegate {
84    public:
85     virtual ~Delegate() {}
86
87     // This callback will be called when a user has given a |response| to a
88     // consent request of the specified |type|.
89     typedef base::Callback<void(ConsentResponse response)> ConsentCallback;
90
91     // Invokes consent UI within the context of |web_contents| and calls
92     // |callback| when the user responds.
93     // Precondition: The last committed URL for |web_contents| has a valid
94     //               origin.
95     virtual void ShowConsentPrompt(content::WebContents* web_contents,
96                                    const ConsentCallback& callback) = 0;
97   };
98
99   // This callback will be called when a challenge operation completes.  If
100   // |result| is SUCCESS then |signed_data| holds the data which was signed
101   // by the platform key (this is the original challenge appended with a random
102   // nonce) and |signature| holds the RSA-PKCS1-v1.5 signature.  The
103   // |platform_key_certificate| certifies the key used to generate the
104   // signature.  This key may be generated on demand and is not guaranteed to
105   // persist across multiple calls to this method.  The browser does not check
106   // the validity of |signature| or |platform_key_certificate|.
107   typedef base::Callback<void(Result result,
108                               const std::string& signed_data,
109                               const std::string& signature,
110                               const std::string& platform_key_certificate)>
111       ChallengeCallback;
112
113   // A constructor that uses the default implementation of all dependencies
114   // including Delegate.
115   PlatformVerificationFlow();
116
117   // An alternate constructor which specifies dependent objects explicitly.
118   // This is useful in testing.  The caller retains ownership of all pointers.
119   PlatformVerificationFlow(AttestationFlow* attestation_flow,
120                            cryptohome::AsyncMethodCaller* async_caller,
121                            CryptohomeClient* cryptohome_client,
122                            UserManager* user_manager,
123                            Delegate* delegate);
124
125   // Invokes an asynchronous operation to challenge a platform key.  Any user
126   // interaction will be associated with |web_contents|.  The |service_id| is an
127   // arbitrary value but it should uniquely identify the origin of the request
128   // and should not be determined by that origin; its purpose is to prevent
129   // collusion between multiple services.  The |challenge| is also an arbitrary
130   // value but it should be time sensitive or associated to some kind of session
131   // because its purpose is to prevent certificate replay.  The |callback| will
132   // be called when the operation completes.  The duration of the operation can
133   // vary depending on system state, hardware capabilities, and interaction with
134   // the user.
135   void ChallengePlatformKey(content::WebContents* web_contents,
136                             const std::string& service_id,
137                             const std::string& challenge,
138                             const ChallengeCallback& callback);
139
140   static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs);
141
142   void set_timeout_delay(const base::TimeDelta& timeout_delay) {
143     timeout_delay_ = timeout_delay;
144   }
145
146  private:
147   friend class base::RefCountedThreadSafe<PlatformVerificationFlow>;
148   friend class PlatformVerificationFlowTest;
149
150   // Holds the arguments of a ChallengePlatformKey call.  This is convenient for
151   // use with base::Bind so we don't get too many arguments.
152   struct ChallengeContext {
153     ChallengeContext(content::WebContents* web_contents,
154                      const std::string& service_id,
155                      const std::string& challenge,
156                      const ChallengeCallback& callback);
157     ~ChallengeContext();
158
159     content::WebContents* web_contents;
160     std::string service_id;
161     std::string challenge;
162     ChallengeCallback callback;
163   };
164
165   ~PlatformVerificationFlow();
166
167   // Checks whether we need to prompt the user for consent before proceeding and
168   // invokes the consent UI if so.  The arguments to ChallengePlatformKey are
169   // in |context| and |attestation_enrolled| specifies whether attestation has
170   // been enrolled for this device.
171   void CheckConsent(const ChallengeContext& context,
172                     bool attestation_enrolled);
173
174   // A callback called when the user has given their consent response.  The
175   // arguments to ChallengePlatformKey are in |context|.  |consent_required| and
176   // |consent_response| indicate whether consent was required and user response,
177   // respectively.  If the response indicates that the operation should proceed,
178   // this method invokes a certificate request.
179   void OnConsentResponse(const ChallengeContext& context,
180                          bool consent_required,
181                          ConsentResponse consent_response);
182
183   // A callback called when an attestation certificate request operation
184   // completes.  The arguments to ChallengePlatformKey are in |context|.
185   // |user_id| identifies the user for which the certificate was requested.
186   // |operation_success| is true iff the certificate request operation
187   // succeeded.  |certificate| holds the certificate for the platform key on
188   // success.  If the certificate request was successful, this method invokes a
189   // request to sign the challenge.  If the operation timed out prior to this
190   // method being called, this method does nothing - notably, the callback is
191   // not invoked.
192   void OnCertificateReady(const ChallengeContext& context,
193                           const std::string& user_id,
194                           scoped_ptr<base::Timer> timer,
195                           bool operation_success,
196                           const std::string& certificate);
197
198   // A callback run after a constant delay to handle timeouts for lengthy
199   // certificate requests.  |context.callback| will be invoked with a TIMEOUT
200   // result.
201   void OnCertificateTimeout(const ChallengeContext& context);
202
203   // A callback called when a challenge signing request has completed.  The
204   // |certificate| is the platform certificate for the key which signed the
205   // |challenge|.  The arguments to ChallengePlatformKey are in |context|.
206   // |operation_success| is true iff the challenge signing operation was
207   // successful.  If it was successful, |response_data| holds the challenge
208   // response and the method will invoke |context.callback|.
209   void OnChallengeReady(const ChallengeContext& context,
210                         const std::string& certificate,
211                         bool operation_success,
212                         const std::string& response_data);
213
214   // Gets prefs associated with the given |web_contents|.  If prefs have been
215   // set explicitly using set_testing_prefs(), then these are always returned.
216   // If no prefs are associated with |web_contents| then NULL is returned.
217   PrefService* GetPrefs(content::WebContents* web_contents);
218
219   // Gets the URL associated with the given |web_contents|.  If a URL as been
220   // set explicitly using set_testing_url(), then this value is always returned.
221   const GURL& GetURL(content::WebContents* web_contents);
222
223   // Gets the user associated with the given |web_contents|.  NULL may be
224   // returned.  If |web_contents| is NULL (e.g. during testing), then the
225   // current active user will be returned.
226   User* GetUser(content::WebContents* web_contents);
227
228   // Gets the content settings map associated with the given |web_contents|.  If
229   // |testing_content_settings_| is set, then this is always returned.
230   HostContentSettingsMap* GetContentSettings(
231       content::WebContents* web_contents);
232
233   // Checks whether policy or profile settings associated with |web_contents|
234   // have attestation for content protection explicitly disabled.
235   bool IsAttestationEnabled(content::WebContents* web_contents);
236
237   // Updates user settings for the profile associated with |web_contents| based
238   // on the |consent_response| to the request of type |consent_type|.
239   bool UpdateSettings(content::WebContents* web_contents,
240                       ConsentResponse consent_response);
241
242   // Finds the domain-specific consent pref in |content_settings| for |url|.  If
243   // a pref exists for the domain, returns true and sets |pref_value| if it is
244   // not NULL.
245   bool GetDomainPref(HostContentSettingsMap* content_settings,
246                      const GURL& url,
247                      bool* pref_value);
248
249   // Records the domain-specific consent pref in |content_settings| for |url|.
250   // The pref will be set to |allow_domain|.
251   void RecordDomainConsent(HostContentSettingsMap* content_settings,
252                            const GURL& url,
253                            bool allow_domain);
254
255   void set_testing_prefs(PrefService* testing_prefs) {
256     testing_prefs_ = testing_prefs;
257   }
258
259   void set_testing_url(const GURL& testing_url) {
260     testing_url_ = testing_url;
261   }
262
263   void set_testing_content_settings(HostContentSettingsMap* settings) {
264     testing_content_settings_ = settings;
265   }
266
267   AttestationFlow* attestation_flow_;
268   scoped_ptr<AttestationFlow> default_attestation_flow_;
269   cryptohome::AsyncMethodCaller* async_caller_;
270   CryptohomeClient* cryptohome_client_;
271   UserManager* user_manager_;
272   Delegate* delegate_;
273   scoped_ptr<Delegate> default_delegate_;
274   PrefService* testing_prefs_;
275   GURL testing_url_;
276   HostContentSettingsMap* testing_content_settings_;
277   base::TimeDelta timeout_delay_;
278
279   DISALLOW_COPY_AND_ASSIGN(PlatformVerificationFlow);
280 };
281
282 }  // namespace attestation
283 }  // namespace chromeos
284
285 #endif  // CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_