Separate Simple Backend creation from initialization.
[chromium-blink-merge.git] / chromeos / attestation / attestation_flow.cc
blob1f0db4101d67efdc181bf280f6aa43c77ac2c98d
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"
7 #include "base/bind.h"
8 #include "chromeos/cryptohome/async_method_caller.h"
9 #include "chromeos/dbus/cryptohome_client.h"
11 namespace chromeos {
12 namespace attestation {
14 namespace {
16 // Redirects to one of three callbacks based on a boolean value and dbus call
17 // status.
19 // Parameters
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,
29 bool value) {
30 if (status != DBUS_METHOD_CALL_SUCCESS) {
31 LOG(ERROR) << "Attestation: Failed to query enrollment state.";
32 if (!on_fail.is_null())
33 on_fail.Run();
34 return;
36 const base::Closure& task = value ? on_true : on_false;
37 if (!task.is_null())
38 task.Run();
41 } // namespace
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(),
64 name,
65 callback);
66 base::Closure on_enroll_failure = base::Bind(callback, false, "");
67 base::Closure do_enroll = base::Bind(&AttestationFlow::StartEnroll,
68 weak_factory_.GetWeakPtr(),
69 on_enroll_failure,
70 do_cert_request);
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.
75 on_enroll_failure));
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(),
84 on_failure,
85 next_task));
88 void AttestationFlow::SendEnrollRequestToPCA(const base::Closure& on_failure,
89 const base::Closure& next_task,
90 bool success,
91 const std::string& data) {
92 if (!success) {
93 LOG(ERROR) << "Attestation: Failed to create enroll request.";
94 if (!on_failure.is_null())
95 on_failure.Run();
96 return;
99 // Send the request to the Privacy CA.
100 server_proxy_->SendEnrollRequest(
101 data,
102 base::Bind(&AttestationFlow::SendEnrollResponseToDaemon,
103 weak_factory_.GetWeakPtr(),
104 on_failure,
105 next_task));
108 void AttestationFlow::SendEnrollResponseToDaemon(
109 const base::Closure& on_failure,
110 const base::Closure& next_task,
111 bool success,
112 const std::string& data) {
113 if (!success) {
114 LOG(ERROR) << "Attestation: Enroll request failed.";
115 if (!on_failure.is_null())
116 on_failure.Run();
117 return;
120 // Forward the response to the attestation service to complete enrollment.
121 async_caller_->AsyncTpmAttestationEnroll(
122 data,
123 base::Bind(&AttestationFlow::OnEnrollComplete,
124 weak_factory_.GetWeakPtr(),
125 on_failure,
126 next_task));
129 void AttestationFlow::OnEnrollComplete(const base::Closure& on_failure,
130 const base::Closure& next_task,
131 bool success,
132 cryptohome::MountError /*not_used*/) {
133 if (!success) {
134 LOG(ERROR) << "Attestation: Failed to complete enrollment.";
135 if (!on_failure.is_null())
136 on_failure.Run();
137 return;
140 // Enrollment has successfully completed, we can move on to whatever is next.
141 if (!next_task.is_null())
142 next_task.Run();
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(
153 options,
154 base::Bind(&AttestationFlow::SendCertificateRequestToPCA,
155 weak_factory_.GetWeakPtr(),
156 name,
157 callback));
160 void AttestationFlow::SendCertificateRequestToPCA(
161 const std::string& name,
162 const CertificateCallback& callback,
163 bool success,
164 const std::string& data) {
165 if (!success) {
166 LOG(ERROR) << "Attestation: Failed to create certificate request.";
167 if (!callback.is_null())
168 callback.Run(false, "");
169 return;
172 // Send the request to the Privacy CA.
173 server_proxy_->SendCertificateRequest(
174 data,
175 base::Bind(&AttestationFlow::SendCertificateResponseToDaemon,
176 weak_factory_.GetWeakPtr(),
177 name,
178 callback));
181 void AttestationFlow::SendCertificateResponseToDaemon(
182 const std::string& name,
183 const CertificateCallback& callback,
184 bool success,
185 const std::string& data) {
186 if (!success) {
187 LOG(ERROR) << "Attestation: Certificate request failed.";
188 if (!callback.is_null())
189 callback.Run(false, "");
190 return;
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,
198 key_type,
199 name,
200 base::Bind(callback));
203 } // namespace attestation
204 } // namespace chromeos