Update broken references to image assets
[chromium-blink-merge.git] / chrome / browser / chromeos / attestation / platform_verification_flow.h
blob8b8b0b105311e11bdf21af3c7292e83f17f26eee
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.
5 #ifndef CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
6 #define CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_
8 #include <set>
9 #include <string>
11 #include "base/basictypes.h"
12 #include "base/callback.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/time/time.h"
16 #include "base/timer/timer.h"
17 #include "url/gurl.h"
19 namespace content {
20 class WebContents;
23 namespace cryptohome {
24 class AsyncMethodCaller;
27 namespace user_manager {
28 class User;
31 namespace chromeos {
33 class CryptohomeClient;
35 namespace attestation {
37 class AttestationFlow;
38 class PlatformVerificationFlowTest;
40 // This class allows platform verification for the content protection use case.
41 // All methods must only be called on the UI thread. Example:
42 // scoped_refptr<PlatformVerificationFlow> verifier =
43 // new PlatformVerificationFlow();
44 // PlatformVerificationFlow::Callback callback = base::Bind(&MyCallback);
45 // verifier->ChallengePlatformKey(my_web_contents, "my_id", "some_challenge",
46 // callback);
48 // This class is RefCountedThreadSafe because it may need to outlive its caller.
49 // The attestation flow that needs to happen to establish a certified platform
50 // key may take minutes on some hardware. This class will timeout after a much
51 // shorter time so the caller can proceed without platform verification but it
52 // is important that the pending operation be allowed to finish. If the
53 // attestation flow is aborted at any stage, it will need to start over. If we
54 // use weak pointers, the attestation flow will stop when the next callback is
55 // run. So we need the instance to stay alive until the platform key is fully
56 // certified so the next time ChallegePlatformKey() is invoked it will be quick.
57 class PlatformVerificationFlow
58 : public base::RefCountedThreadSafe<PlatformVerificationFlow> {
59 public:
60 // These values are reported to UMA. DO NOT CHANGE THE EXISTING VALUES!
61 enum Result {
62 SUCCESS, // The operation succeeded.
63 INTERNAL_ERROR, // The operation failed unexpectedly.
64 PLATFORM_NOT_VERIFIED, // The platform cannot be verified. For example:
65 // - It is not a Chrome device.
66 // - It is not running a verified OS image.
67 USER_REJECTED, // The user explicitly rejected the operation.
68 POLICY_REJECTED, // The operation is not allowed by policy/settings.
69 TIMEOUT, // The operation timed out.
70 RESULT_MAX
73 // These values are reported to UMA. DO NOT CHANGE THE EXISTING VALUES!
74 enum ExpiryStatus {
75 EXPIRY_STATUS_OK,
76 EXPIRY_STATUS_EXPIRING_SOON,
77 EXPIRY_STATUS_EXPIRED,
78 EXPIRY_STATUS_INVALID_PEM_CHAIN,
79 EXPIRY_STATUS_INVALID_X509,
80 EXPIRY_STATUS_MAX
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() {}
89 // Gets the URL associated with the given |web_contents|.
90 virtual const GURL& GetURL(content::WebContents* web_contents) = 0;
92 // Gets the user associated with the given |web_contents|. NULL may be
93 // returned.
94 virtual const user_manager::User* GetUser(
95 content::WebContents* web_contents) = 0;
97 // Checks whether attestation is permitted by user.
98 virtual bool IsPermittedByUser(content::WebContents* web_contents) = 0;
100 // Returns true iff the device is in a mode that supports platform
101 // verification. For example, platform verification is not supported in
102 // guest or incognito mode. It is also not supported in dev mode unless
103 // overridden by a flag.
104 virtual bool IsInSupportedMode(content::WebContents* web_contents) = 0;
107 // This callback will be called when a challenge operation completes. If
108 // |result| is SUCCESS then |signed_data| holds the data which was signed
109 // by the platform key (this is the original challenge appended with a random
110 // nonce) and |signature| holds the RSA-PKCS1-v1.5 signature. The
111 // |platform_key_certificate| certifies the key used to generate the
112 // signature. This key may be generated on demand and is not guaranteed to
113 // persist across multiple calls to this method. The browser does not check
114 // the validity of |signature| or |platform_key_certificate|.
115 typedef base::Callback<void(Result result,
116 const std::string& signed_data,
117 const std::string& signature,
118 const std::string& platform_key_certificate)>
119 ChallengeCallback;
121 // A constructor that uses the default implementation of all dependencies
122 // including Delegate.
123 PlatformVerificationFlow();
125 // An alternate constructor which specifies dependent objects explicitly.
126 // This is useful in testing. The caller retains ownership of all pointers.
127 PlatformVerificationFlow(AttestationFlow* attestation_flow,
128 cryptohome::AsyncMethodCaller* async_caller,
129 CryptohomeClient* cryptohome_client,
130 Delegate* delegate);
132 // Invokes an asynchronous operation to challenge a platform key. Any user
133 // interaction will be associated with |web_contents|. The |service_id| is an
134 // arbitrary value but it should uniquely identify the origin of the request
135 // and should not be determined by that origin; its purpose is to prevent
136 // collusion between multiple services. The |challenge| is also an arbitrary
137 // value but it should be time sensitive or associated to some kind of session
138 // because its purpose is to prevent certificate replay. The |callback| will
139 // be called when the operation completes. The duration of the operation can
140 // vary depending on system state, hardware capabilities, and interaction with
141 // the user.
142 void ChallengePlatformKey(content::WebContents* web_contents,
143 const std::string& service_id,
144 const std::string& challenge,
145 const ChallengeCallback& callback);
147 void set_timeout_delay(const base::TimeDelta& timeout_delay) {
148 timeout_delay_ = timeout_delay;
151 private:
152 friend class base::RefCountedThreadSafe<PlatformVerificationFlow>;
153 friend class PlatformVerificationFlowTest;
155 // Holds the arguments of a ChallengePlatformKey call. This is convenient for
156 // use with base::Bind so we don't get too many arguments.
157 struct ChallengeContext {
158 ChallengeContext(content::WebContents* web_contents,
159 const std::string& service_id,
160 const std::string& challenge,
161 const ChallengeCallback& callback);
162 ~ChallengeContext();
164 content::WebContents* web_contents;
165 std::string service_id;
166 std::string challenge;
167 ChallengeCallback callback;
170 ~PlatformVerificationFlow();
172 // Callback for attestation preparation. The arguments to ChallengePlatformKey
173 // are in |context|, and |attestation_prepared| specifies whether attestation
174 // has been prepared on this device.
175 void OnAttestationPrepared(const ChallengeContext& context,
176 bool attestation_prepared);
178 // Initiates the flow to get a platform key certificate. The arguments to
179 // ChallengePlatformKey are in |context|. |user_id| identifies the user for
180 // which to get a certificate. If |force_new_key| is true then any existing
181 // key for the same user and service will be ignored and a new key will be
182 // generated and certified.
183 void GetCertificate(const ChallengeContext& context,
184 const std::string& user_id,
185 bool force_new_key);
187 // A callback called when an attestation certificate request operation
188 // completes. The arguments to ChallengePlatformKey are in |context|.
189 // |user_id| identifies the user for which the certificate was requested.
190 // |operation_success| is true iff the certificate request operation
191 // succeeded. |certificate_chain| holds the certificate for the platform key
192 // on success. If the certificate request was successful, this method invokes
193 // a request to sign the challenge. If the operation timed out prior to this
194 // method being called, this method does nothing - notably, the callback is
195 // not invoked.
196 void OnCertificateReady(const ChallengeContext& context,
197 const std::string& user_id,
198 scoped_ptr<base::Timer> timer,
199 bool operation_success,
200 const std::string& certificate_chain);
202 // A callback run after a constant delay to handle timeouts for lengthy
203 // certificate requests. |context.callback| will be invoked with a TIMEOUT
204 // result.
205 void OnCertificateTimeout(const ChallengeContext& context);
207 // A callback called when a challenge signing request has completed. The
208 // |certificate_chain| is the platform certificate chain for the key which
209 // signed the |challenge|. The arguments to ChallengePlatformKey are in
210 // |context|. |user_id| identifies the user for which the certificate was
211 // requested. |is_expiring_soon| will be set iff a certificate in the
212 // |certificate_chain| is expiring soon. |operation_success| is true iff the
213 // challenge signing operation was successful. If it was successful,
214 // |response_data| holds the challenge response and the method will invoke
215 // |context.callback|.
216 void OnChallengeReady(const ChallengeContext& context,
217 const std::string& user_id,
218 const std::string& certificate_chain,
219 bool is_expiring_soon,
220 bool operation_success,
221 const std::string& response_data);
223 // Checks whether attestation for content protection is allowed by policy.
224 bool IsAttestationAllowedByPolicy();
226 // Checks if |certificate_chain| is a PEM certificate chain that contains a
227 // certificate this is expired or expiring soon. Returns the expiry status.
228 ExpiryStatus CheckExpiry(const std::string& certificate_chain);
230 // An AttestationFlow::CertificateCallback that handles renewal completion.
231 // |old_certificate_chain| contains the chain that has been replaced.
232 void RenewCertificateCallback(const std::string& old_certificate_chain,
233 bool operation_success,
234 const std::string& certificate_chain);
236 AttestationFlow* attestation_flow_;
237 scoped_ptr<AttestationFlow> default_attestation_flow_;
238 cryptohome::AsyncMethodCaller* async_caller_;
239 CryptohomeClient* cryptohome_client_;
240 Delegate* delegate_;
241 scoped_ptr<Delegate> default_delegate_;
242 base::TimeDelta timeout_delay_;
243 std::set<std::string> renewals_in_progress_;
245 DISALLOW_COPY_AND_ASSIGN(PlatformVerificationFlow);
248 } // namespace attestation
249 } // namespace chromeos
251 #endif // CHROME_BROWSER_CHROMEOS_ATTESTATION_PLATFORM_VERIFICATION_FLOW_H_