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