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
;
43 const char AttestationFlow::kEnterpriseMachineKey
[] = "attest-ent-machine";
45 AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller
* async_caller
,
46 CryptohomeClient
* cryptohome_client
,
47 ServerProxy
* server_proxy
)
48 : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)),
49 async_caller_(async_caller
),
50 cryptohome_client_(cryptohome_client
),
51 server_proxy_(server_proxy
) {
54 AttestationFlow::~AttestationFlow() {
57 void AttestationFlow::GetCertificate(const std::string
& name
,
58 const CertificateCallback
& callback
) {
59 // If this device has not enrolled with the Privacy CA, we need to do that
60 // first. Once enrolled we can proceed with the certificate request.
61 base::Closure do_cert_request
= base::Bind(
62 &AttestationFlow::StartCertificateRequest
,
63 weak_factory_
.GetWeakPtr(),
66 base::Closure on_enroll_failure
= base::Bind(callback
, false, "");
67 base::Closure do_enroll
= base::Bind(&AttestationFlow::StartEnroll
,
68 weak_factory_
.GetWeakPtr(),
71 cryptohome_client_
->TpmAttestationIsEnrolled(base::Bind(
72 &DBusBoolRedirectCallback
,
73 do_cert_request
, // If enrolled, proceed with cert request.
74 do_enroll
, // If not enrolled, initiate enrollment.
78 void AttestationFlow::StartEnroll(const base::Closure
& on_failure
,
79 const base::Closure
& next_task
) {
80 // Get the attestation service to create a Privacy CA enrollment request.
81 async_caller_
->AsyncTpmAttestationCreateEnrollRequest(base::Bind(
82 &AttestationFlow::SendEnrollRequestToPCA
,
83 weak_factory_
.GetWeakPtr(),
88 void AttestationFlow::SendEnrollRequestToPCA(const base::Closure
& on_failure
,
89 const base::Closure
& next_task
,
91 const std::string
& data
) {
93 LOG(ERROR
) << "Attestation: Failed to create enroll request.";
94 if (!on_failure
.is_null())
99 // Send the request to the Privacy CA.
100 server_proxy_
->SendEnrollRequest(
102 base::Bind(&AttestationFlow::SendEnrollResponseToDaemon
,
103 weak_factory_
.GetWeakPtr(),
108 void AttestationFlow::SendEnrollResponseToDaemon(
109 const base::Closure
& on_failure
,
110 const base::Closure
& next_task
,
112 const std::string
& data
) {
114 LOG(ERROR
) << "Attestation: Enroll request failed.";
115 if (!on_failure
.is_null())
120 // Forward the response to the attestation service to complete enrollment.
121 async_caller_
->AsyncTpmAttestationEnroll(
123 base::Bind(&AttestationFlow::OnEnrollComplete
,
124 weak_factory_
.GetWeakPtr(),
129 void AttestationFlow::OnEnrollComplete(const base::Closure
& on_failure
,
130 const base::Closure
& next_task
,
132 cryptohome::MountError
/*not_used*/) {
134 LOG(ERROR
) << "Attestation: Failed to complete enrollment.";
135 if (!on_failure
.is_null())
140 // Enrollment has successfully completed, we can move on to whatever is next.
141 if (!next_task
.is_null())
145 void AttestationFlow::StartCertificateRequest(
146 const std::string
& name
,
147 const CertificateCallback
& callback
) {
148 // Get the attestation service to create a Privacy CA certificate request.
149 int options
= CryptohomeClient::INCLUDE_DEVICE_STATE
;
150 if (name
== kEnterpriseMachineKey
)
151 options
|= CryptohomeClient::INCLUDE_STABLE_ID
;
152 async_caller_
->AsyncTpmAttestationCreateCertRequest(
154 base::Bind(&AttestationFlow::SendCertificateRequestToPCA
,
155 weak_factory_
.GetWeakPtr(),
160 void AttestationFlow::SendCertificateRequestToPCA(
161 const std::string
& name
,
162 const CertificateCallback
& callback
,
164 const std::string
& data
) {
166 LOG(ERROR
) << "Attestation: Failed to create certificate request.";
167 if (!callback
.is_null())
168 callback
.Run(false, "");
172 // Send the request to the Privacy CA.
173 server_proxy_
->SendCertificateRequest(
175 base::Bind(&AttestationFlow::SendCertificateResponseToDaemon
,
176 weak_factory_
.GetWeakPtr(),
181 void AttestationFlow::SendCertificateResponseToDaemon(
182 const std::string
& name
,
183 const CertificateCallback
& callback
,
185 const std::string
& data
) {
187 LOG(ERROR
) << "Attestation: Certificate request failed.";
188 if (!callback
.is_null())
189 callback
.Run(false, "");
193 // Forward the response to the attestation service to complete the operation.
194 CryptohomeClient::AttestationKeyType key_type
= CryptohomeClient::USER_KEY
;
195 if (name
== kEnterpriseMachineKey
)
196 key_type
= CryptohomeClient::DEVICE_KEY
;
197 async_caller_
->AsyncTpmAttestationFinishCertRequest(data
,
200 base::Bind(callback
));
203 } // namespace attestation
204 } // namespace chromeos