Chromium Code Reviews| Index: chromeos/attestation/attestation_flow.cc |
| diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..74ec3f21274e02f165ffa3026f573684e57ece12 |
| --- /dev/null |
| +++ b/chromeos/attestation/attestation_flow.cc |
| @@ -0,0 +1,182 @@ |
| +// Copyright (c) 2012 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. |
| + |
| +#include "chromeos/attestation/attestation_flow.h" |
| + |
| +#include "base/bind.h" |
| +#include "chromeos/cryptohome/async_method_caller.h" |
| +#include "chromeos/dbus/cryptohome_client.h" |
| + |
| +namespace chromeos { |
| +namespace attestation { |
| + |
| +namespace { |
| + |
| +// Redirects to one of three callbacks based on a boolean value and dbus call |
| +// status. |
| +// |
| +// Parameters |
| +// on_true - Called when status=succes and value=true. |
| +// on_false - Called when status=success and value=false. |
| +// on_fail - Called when status=failure. |
| +// status - The D-Bus operation status. |
| +// value - The value returned by the D-Bus operation. |
| +void DBusBoolRedirectCallback(const base::Closure& on_true, |
| + const base::Closure& on_false, |
| + const base::Closure& on_fail, |
| + DBusMethodCallStatus status, |
| + bool value) { |
| + if (status != DBUS_METHOD_CALL_SUCCESS) { |
| + LOG(ERROR) << "Attestation: Failed to query enrollment state."; |
| + on_fail.Run(); |
|
Mattias Nissler (ping if slow)
2013/01/18 13:38:46
IIRC base::Callback implementors generally advise
dkrahn
2013/01/22 22:50:11
Done.
|
| + return; |
| + } |
| + const base::Closure& task = value ? on_true : on_false; |
| + task.Run(); |
| +} |
| + |
| +} // namespace |
| + |
| +const char AttestationFlow::kEnterpriseMachineKey[] = "attest-ent-machine"; |
| + |
| +AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, |
| + CryptohomeClient* cryptohome_client, |
| + ServerProxy* server_proxy) |
| + : ALLOW_THIS_IN_INITIALIZER_LIST(weak_factory_(this)), |
| + async_caller_(async_caller), |
| + cryptohome_client_(cryptohome_client), |
| + server_proxy_(server_proxy) { |
| +} |
| + |
| +AttestationFlow::~AttestationFlow() { |
| +} |
| + |
| +void AttestationFlow::GetCertificate(const std::string& name, |
| + const CertificateCallback& callback) { |
| + // If this device has not enrolled with the Privacy CA, we need to do that |
| + // first. Once enrolled we can proceed with the certificate request. |
| + base::Closure do_cert_request = base::Bind( |
| + &AttestationFlow::StartCertificateRequest, |
| + weak_factory_.GetWeakPtr(), |
| + name, |
| + callback); |
| + base::Closure on_enroll_failure = base::Bind(callback, false, ""); |
| + base::Closure do_enroll = base::Bind(&AttestationFlow::StartEnroll, |
| + weak_factory_.GetWeakPtr(), |
| + on_enroll_failure, |
| + do_cert_request); |
| + cryptohome_client_->TpmAttestationIsEnrolled(base::Bind( |
| + &DBusBoolRedirectCallback, |
| + do_cert_request, // If enrolled, proceed with cert request. |
| + do_enroll, // If not enrolled, initiate enrollment. |
| + on_enroll_failure)); |
| +} |
| + |
| +void AttestationFlow::StartEnroll(const base::Closure& on_failure, |
| + const base::Closure& next_task) { |
| + // Get the attestation service to create a Privacy CA enrollment request. |
| + async_caller_->AsyncTpmAttestationCreateEnrollRequest(base::Bind( |
| + &AttestationFlow::SendEnrollRequestToPCA, |
| + weak_factory_.GetWeakPtr(), |
| + on_failure, |
| + next_task)); |
| +} |
| + |
| +void AttestationFlow::SendEnrollRequestToPCA(const base::Closure& on_failure, |
| + const base::Closure& next_task, |
| + bool success, |
| + const std::string& data) { |
| + if (!success) { |
| + LOG(ERROR) << "Attestation: Failed to create enroll request."; |
| + on_failure.Run(); |
| + return; |
| + } |
| + |
| + // Send the request to the Privacy CA. |
| + server_proxy_->SendEnrollRequest( |
| + data, |
| + base::Bind(&AttestationFlow::OnEnrollResponse, |
| + weak_factory_.GetWeakPtr(), |
| + on_failure, |
| + next_task)); |
| +} |
| + |
| +void AttestationFlow::OnEnrollResponse(const base::Closure& on_failure, |
| + const base::Closure& next_task, |
| + bool success, |
| + const std::string& data) { |
| + if (!success) { |
| + LOG(ERROR) << "Attestation: Enroll request failed."; |
| + on_failure.Run(); |
| + return; |
| + } |
| + |
| + // Forward the response to the attestation service to complete enrollment. |
| + async_caller_->AsyncTpmAttestationEnroll( |
| + data, |
| + base::Bind(&AttestationFlow::OnEnrollComplete, |
| + weak_factory_.GetWeakPtr(), |
| + on_failure, |
| + next_task)); |
| +} |
| + |
| +void AttestationFlow::OnEnrollComplete(const base::Closure& on_failure, |
| + const base::Closure& next_task, |
| + bool success, |
| + cryptohome::MountError /*not_used*/) { |
| + if (!success) { |
| + LOG(ERROR) << "Attestation: Failed to complete enrollment."; |
| + on_failure.Run(); |
| + return; |
| + } |
| + |
| + // Enrollment has successfully completed, we can move on to whatever is next. |
| + next_task.Run(); |
| +} |
| + |
| +void AttestationFlow::StartCertificateRequest( |
| + const std::string& name, |
| + const CertificateCallback& callback) { |
| + // Get the attestation service to create a Privacy CA certificate request. |
| + async_caller_->AsyncTpmAttestationCreateCertRequest( |
| + (name == kEnterpriseMachineKey), |
| + base::Bind(&AttestationFlow::SendCertificateRequestToPCA, |
| + weak_factory_.GetWeakPtr(), |
| + callback)); |
| +} |
| + |
| +void AttestationFlow::SendCertificateRequestToPCA( |
| + const CertificateCallback& callback, |
| + bool success, |
| + const std::string& data) { |
| + if (!success) { |
| + LOG(ERROR) << "Attestation: Failed to create certificate request."; |
| + callback.Run(false, ""); |
| + return; |
| + } |
| + |
| + // Send the request to the Privacy CA. |
| + server_proxy_->SendCertificateRequest( |
| + data, |
| + base::Bind(&AttestationFlow::OnCertificateResponse, |
| + weak_factory_.GetWeakPtr(), |
| + callback)); |
| +} |
| + |
| +void AttestationFlow::OnCertificateResponse(const CertificateCallback& callback, |
| + bool success, |
| + const std::string& data) { |
| + if (!success) { |
| + LOG(ERROR) << "Attestation: Certificate request failed."; |
| + callback.Run(false, ""); |
| + return; |
| + } |
| + |
| + // Forward the response to the attestation service to complete the operation. |
| + async_caller_->AsyncTpmAttestationFinishCertRequest(data, |
| + base::Bind(callback)); |
| +} |
| + |
| +} // namespace attestation |
| +} // namespace chromeos |