1 // Copyright (c) 2012 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 #include "chromeos/attestation/attestation_flow.h"
8 #include "chromeos/cryptohome/async_method_caller.h"
9 #include "chromeos/dbus/cryptohome_client.h"
12 namespace attestation
{
16 // Redirects to one of three callbacks based on a boolean value and dbus call
20 // on_true - Called when status=succes and value=true.
21 // on_false - Called when status=success and value=false.
22 // on_fail - Called when status=failure.
23 // status - The D-Bus operation status.
24 // value - The value returned by the D-Bus operation.
25 void DBusBoolRedirectCallback(const base::Closure
& on_true
,
26 const base::Closure
& on_false
,
27 const base::Closure
& on_fail
,
28 DBusMethodCallStatus status
,
30 if (status
!= DBUS_METHOD_CALL_SUCCESS
) {
31 LOG(ERROR
) << "Attestation: Failed to query enrollment state.";
32 if (!on_fail
.is_null())
36 const base::Closure
& task
= value
? on_true
: on_false
;
41 void DBusDataMethodCallback(
42 const AttestationFlow::CertificateCallback
& callback
,
43 DBusMethodCallStatus status
,
45 const std::string
& data
) {
46 if (status
!= DBUS_METHOD_CALL_SUCCESS
) {
47 LOG(ERROR
) << "Attestation: DBus data operation failed.";
48 if (!callback
.is_null())
49 callback
.Run(false, "");
52 if (!callback
.is_null())
53 callback
.Run(result
, data
);
56 AttestationKeyType
GetKeyTypeForProfile(
57 AttestationCertificateProfile profile
) {
59 case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE
:
61 case PROFILE_ENTERPRISE_USER_CERTIFICATE
:
62 case PROFILE_CONTENT_PROTECTION_CERTIFICATE
:
69 std::string
GetKeyNameForProfile(AttestationCertificateProfile profile
,
70 const std::string
& origin
) {
72 case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE
:
73 return kEnterpriseMachineKey
;
74 case PROFILE_ENTERPRISE_USER_CERTIFICATE
:
75 return kEnterpriseUserKey
;
76 case PROFILE_CONTENT_PROTECTION_CERTIFICATE
:
77 return std::string(kContentProtectionKeyPrefix
) + origin
;
85 AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller
* async_caller
,
86 CryptohomeClient
* cryptohome_client
,
87 scoped_ptr
<ServerProxy
> server_proxy
)
88 : async_caller_(async_caller
),
89 cryptohome_client_(cryptohome_client
),
90 server_proxy_(server_proxy
.Pass()),
94 AttestationFlow::~AttestationFlow() {
97 void AttestationFlow::GetCertificate(
98 AttestationCertificateProfile certificate_profile
,
99 const std::string
& user_id
,
100 const std::string
& request_origin
,
102 const CertificateCallback
& callback
) {
103 // If this device has not enrolled with the Privacy CA, we need to do that
104 // first. Once enrolled we can proceed with the certificate request.
105 base::Closure do_cert_request
= base::Bind(
106 &AttestationFlow::StartCertificateRequest
,
107 weak_factory_
.GetWeakPtr(),
113 base::Closure on_enroll_failure
= base::Bind(callback
, false, "");
114 base::Closure do_enroll
= base::Bind(&AttestationFlow::StartEnroll
,
115 weak_factory_
.GetWeakPtr(),
118 cryptohome_client_
->TpmAttestationIsEnrolled(base::Bind(
119 &DBusBoolRedirectCallback
,
120 do_cert_request
, // If enrolled, proceed with cert request.
121 do_enroll
, // If not enrolled, initiate enrollment.
125 void AttestationFlow::StartEnroll(const base::Closure
& on_failure
,
126 const base::Closure
& next_task
) {
127 // Get the attestation service to create a Privacy CA enrollment request.
128 async_caller_
->AsyncTpmAttestationCreateEnrollRequest(
129 server_proxy_
->GetType(),
130 base::Bind(&AttestationFlow::SendEnrollRequestToPCA
,
131 weak_factory_
.GetWeakPtr(),
136 void AttestationFlow::SendEnrollRequestToPCA(const base::Closure
& on_failure
,
137 const base::Closure
& next_task
,
139 const std::string
& data
) {
141 LOG(ERROR
) << "Attestation: Failed to create enroll request.";
142 if (!on_failure
.is_null())
147 // Send the request to the Privacy CA.
148 server_proxy_
->SendEnrollRequest(
150 base::Bind(&AttestationFlow::SendEnrollResponseToDaemon
,
151 weak_factory_
.GetWeakPtr(),
156 void AttestationFlow::SendEnrollResponseToDaemon(
157 const base::Closure
& on_failure
,
158 const base::Closure
& next_task
,
160 const std::string
& data
) {
162 LOG(ERROR
) << "Attestation: Enroll request failed.";
163 if (!on_failure
.is_null())
168 // Forward the response to the attestation service to complete enrollment.
169 async_caller_
->AsyncTpmAttestationEnroll(
170 server_proxy_
->GetType(),
172 base::Bind(&AttestationFlow::OnEnrollComplete
,
173 weak_factory_
.GetWeakPtr(),
178 void AttestationFlow::OnEnrollComplete(const base::Closure
& on_failure
,
179 const base::Closure
& next_task
,
181 cryptohome::MountError
/*not_used*/) {
183 LOG(ERROR
) << "Attestation: Failed to complete enrollment.";
184 if (!on_failure
.is_null())
189 // Enrollment has successfully completed, we can move on to whatever is next.
190 if (!next_task
.is_null())
194 void AttestationFlow::StartCertificateRequest(
195 AttestationCertificateProfile certificate_profile
,
196 const std::string
& user_id
,
197 const std::string
& request_origin
,
198 bool generate_new_key
,
199 const CertificateCallback
& callback
) {
200 AttestationKeyType key_type
= GetKeyTypeForProfile(certificate_profile
);
201 std::string key_name
= GetKeyNameForProfile(certificate_profile
,
203 if (generate_new_key
) {
204 // Get the attestation service to create a Privacy CA certificate request.
205 async_caller_
->AsyncTpmAttestationCreateCertRequest(
206 server_proxy_
->GetType(),
210 base::Bind(&AttestationFlow::SendCertificateRequestToPCA
,
211 weak_factory_
.GetWeakPtr(),
217 // If the key already exists, query the existing certificate.
218 base::Closure on_key_exists
= base::Bind(
219 &AttestationFlow::GetExistingCertificate
,
220 weak_factory_
.GetWeakPtr(),
225 // If the key does not exist, call this method back with |generate_new_key|
227 base::Closure on_key_not_exists
= base::Bind(
228 &AttestationFlow::StartCertificateRequest
,
229 weak_factory_
.GetWeakPtr(),
235 cryptohome_client_
->TpmAttestationDoesKeyExist(
239 base::Bind(&DBusBoolRedirectCallback
,
242 base::Bind(callback
, false, "")));
246 void AttestationFlow::SendCertificateRequestToPCA(
247 AttestationKeyType key_type
,
248 const std::string
& user_id
,
249 const std::string
& key_name
,
250 const CertificateCallback
& callback
,
252 const std::string
& data
) {
254 LOG(ERROR
) << "Attestation: Failed to create certificate request.";
255 if (!callback
.is_null())
256 callback
.Run(false, "");
260 // Send the request to the Privacy CA.
261 server_proxy_
->SendCertificateRequest(
263 base::Bind(&AttestationFlow::SendCertificateResponseToDaemon
,
264 weak_factory_
.GetWeakPtr(),
271 void AttestationFlow::SendCertificateResponseToDaemon(
272 AttestationKeyType key_type
,
273 const std::string
& user_id
,
274 const std::string
& key_name
,
275 const CertificateCallback
& callback
,
277 const std::string
& data
) {
279 LOG(ERROR
) << "Attestation: Certificate request failed.";
280 if (!callback
.is_null())
281 callback
.Run(false, "");
285 // Forward the response to the attestation service to complete the operation.
286 async_caller_
->AsyncTpmAttestationFinishCertRequest(data
,
290 base::Bind(callback
));
293 void AttestationFlow::GetExistingCertificate(
294 AttestationKeyType key_type
,
295 const std::string
& user_id
,
296 const std::string
& key_name
,
297 const CertificateCallback
& callback
) {
298 cryptohome_client_
->TpmAttestationGetCertificate(
302 base::Bind(&DBusDataMethodCallback
, callback
));
305 ServerProxy::~ServerProxy() {}
307 PrivacyCAType
ServerProxy::GetType() {
311 } // namespace attestation
312 } // namespace chromeos