1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
|
// Copyright 2013 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 CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
#define CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
#include <string>
#include "base/basictypes.h"
#include "base/callback.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "url/gurl.h"
class PrefService;
namespace content {
class WebContents;
}
namespace cryptohome {
class AsyncMethodCaller;
}
namespace user_prefs {
class PrefRegistrySyncable;
}
namespace chromeos {
class CryptohomeClient;
class UserManager;
namespace system {
class StatisticsProvider;
}
namespace attestation {
class AttestationFlow;
// This class allows platform verification for the content protection use case.
// All methods must only be called on the UI thread. Example:
// PlatformVerificationFlow verifier;
// PlatformVerificationFlow::Callback callback = base::Bind(&MyCallback);
// verifier.ChallengePlatformKey(my_web_contents, "my_id", "some_challenge",
// callback);
class PlatformVerificationFlow {
public:
enum Result {
SUCCESS, // The operation succeeded.
INTERNAL_ERROR, // The operation failed unexpectedly.
PLATFORM_NOT_VERIFIED, // The platform cannot be verified. For example:
// - It is not a Chrome device.
// - It is not running a verified OS image.
USER_REJECTED, // The user explicitly rejected the operation.
POLICY_REJECTED, // The operation is not allowed by policy/settings.
};
enum ConsentType {
CONSENT_TYPE_NONE, // No consent necessary.
CONSENT_TYPE_ATTESTATION, // Consent to use attestation.
CONSENT_TYPE_ALWAYS, // Consent because 'Always Ask' was requested.
};
enum ConsentResponse {
CONSENT_RESPONSE_NONE,
CONSENT_RESPONSE_ALLOW,
CONSENT_RESPONSE_DENY,
CONSENT_RESPONSE_ALWAYS_ASK,
};
// An interface which allows settings and UI to be abstracted for testing
// purposes. For normal operation the default implementation should be used.
class Delegate {
public:
virtual ~Delegate() {}
// This callback will be called when a user has given a |response| to a
// consent request of the specified |type|.
typedef base::Callback<void(ConsentResponse response)> ConsentCallback;
// Invokes consent UI of the given |type| within the context of
// |web_contents| and calls |callback| when the user responds.
virtual void ShowConsentPrompt(ConsentType type,
content::WebContents* web_contents,
const ConsentCallback& callback) = 0;
};
// This callback will be called when a challenge operation completes. If
// |result| is SUCCESS then |challenge_response| holds the challenge response
// as specified by the protocol. The |platform_key_certificate| is for the
// key which was used to create the challenge response. This key may be
// generated on demand and is not guaranteed to persist across multiple calls
// to this method. Both the response and the certificate are opaque to
// the browser; they are intended for validation by an external application or
// service.
typedef base::Callback<void(Result result,
const std::string& challenge_response,
const std::string& platform_key_certificate)>
ChallengeCallback;
// A constructor that uses the default implementation of all dependencies
// including Delegate.
// TODO(dkrahn): Enable this when the default delegate has been implemented.
// PlatformVerificationFlow();
// An alternate constructor which specifies dependent objects explicitly.
// This is useful in testing. The caller retains ownership of all pointers.
PlatformVerificationFlow(AttestationFlow* attestation_flow,
cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client,
UserManager* user_manager,
system::StatisticsProvider* statistics_provider,
Delegate* delegate);
virtual ~PlatformVerificationFlow();
// Invokes an asynchronous operation to challenge a platform key. Any user
// interaction will be associated with |web_contents|. The |service_id| is an
// arbitrary value but it should uniquely identify the origin of the request
// and should not be determined by that origin; its purpose is to prevent
// collusion between multiple services. The |challenge| is also an arbitrary
// value but it should be time sensitive or associated to some kind of session
// because its purpose is to prevent certificate replay. The |callback| will
// be called when the operation completes. The duration of the operation can
// vary depending on system state, hardware capabilities, and interaction with
// the user.
void ChallengePlatformKey(content::WebContents* web_contents,
const std::string& service_id,
const std::string& challenge,
const ChallengeCallback& callback);
// Performs a quick check to see if platform verification is reasonably
// expected to succeed. The result of the check will be sent to the given
// |callback|. If the |result| is true, then platform verification is
// expected to succeed. However, this result is not authoritative either true
// or false. If an error occurs, |result| will be false.
void CheckPlatformState(const base::Callback<void(bool result)>& callback);
static void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* prefs);
void set_testing_prefs(PrefService* testing_prefs) {
testing_prefs_ = testing_prefs;
}
void set_testing_url(const GURL& testing_url) {
testing_url_ = testing_url;
}
private:
// Checks whether we need to prompt the user for consent before proceeding and
// invokes the consent UI if so. All parameters are the same as in
// ChallengePlatformKey except for the additional |attestation_enrolled| which
// specifies whether attestation has been enrolled for this device.
void CheckConsent(content::WebContents* web_contents,
const std::string& service_id,
const std::string& challenge,
const ChallengeCallback& callback,
bool attestation_enrolled);
// A callback called when the user has given their consent response. All
// parameters are the same as in ChallengePlatformKey except for the
// additional |consent_type| and |consent_response| which indicate the consent
// type and user response, respectively. If the response indicates that the
// operation should proceed, this method invokes a certificate request.
void OnConsentResponse(content::WebContents* web_contents,
const std::string& service_id,
const std::string& challenge,
const ChallengeCallback& callback,
ConsentType consent_type,
ConsentResponse consent_response);
// A callback called when an attestation certificate request operation
// completes. |service_id|, |challenge|, and |callback| are the same as in
// ChallengePlatformKey. |operation_success| is true iff the certificate
// request operation succeeded. |certificate| holds the certificate for the
// platform key on success. If the certificate request was successful, this
// method invokes a request to sign the challenge.
void OnCertificateReady(const std::string& service_id,
const std::string& challenge,
const ChallengeCallback& callback,
bool operation_success,
const std::string& certificate);
// A callback called when a challenge signing request has completed. The
// |certificate| is the platform certificate for the key which signed the
// challenge. |callback| is the same as in ChallengePlatformKey.
// |operation_success| is true iff the challenge signing operation was
// successful. If it was successful, |response_data| holds the challenge
// response and the method will invoke |callback|.
void OnChallengeReady(const std::string& certificate,
const ChallengeCallback& callback,
bool operation_success,
const std::string& response_data);
// Gets prefs associated with the given |web_contents|. If prefs have been
// set explicitly using set_testing_prefs(), then these are always returned.
// If no prefs are associated with |web_contents| then NULL is returned.
PrefService* GetPrefs(content::WebContents* web_contents);
// Gets the URL associated with the given |web_contents|. If a URL as been
// set explicitly using set_testing_url(), then this value is always returned.
const GURL& GetURL(content::WebContents* web_contents);
// Checks whether policy or profile settings associated with |web_contents|
// have attestation for content protection explicitly disabled.
bool IsAttestationEnabled(content::WebContents* web_contents);
// Checks whether this is the first use on this device for the user associated
// with |web_contents|.
bool IsFirstUse(content::WebContents* web_contents);
// Checks if settings indicate that consent is required for the web origin
// represented by |web_contents| because the user requested to be prompted.
bool IsAlwaysAskRequired(content::WebContents* web_contents);
// Updates user settings for the profile associated with |web_contents| based
// on the |consent_response| to the request of type |consent_type|.
bool UpdateSettings(content::WebContents* web_contents,
ConsentType consent_type,
ConsentResponse consent_response);
// Finds the domain-specific consent pref for the domain associated with
// |web_contents|. If a pref exists for the domain, returns true and sets
// |pref_value| if it is not NULL.
//
// Precondition: A valid PrefService must be available via GetPrefs().
bool GetDomainPref(content::WebContents* web_contents, bool* pref_value);
// Records the domain-specific consent pref for the domain associated with
// |web_contents|. The pref will be set to |allow_domain|.
//
// Precondition: A valid PrefService must be available via GetPrefs().
void RecordDomainConsent(content::WebContents* web_contents,
bool allow_domain);
AttestationFlow* attestation_flow_;
scoped_ptr<AttestationFlow> default_attestation_flow_;
cryptohome::AsyncMethodCaller* async_caller_;
CryptohomeClient* cryptohome_client_;
UserManager* user_manager_;
system::StatisticsProvider* statistics_provider_;
Delegate* delegate_;
scoped_ptr<Delegate> default_delegate_;
PrefService* testing_prefs_;
GURL testing_url_;
// Note: This should remain the last member so it'll be destroyed and
// invalidate the weak pointers before any other members are destroyed.
base::WeakPtrFactory<PlatformVerificationFlow> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(PlatformVerificationFlow);
};
} // namespace attestation
} // namespace chromeos
#endif // CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
|