diff options
Diffstat (limited to 'chromeos/attestation/attestation_flow.cc')
-rw-r--r-- | chromeos/attestation/attestation_flow.cc | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/chromeos/attestation/attestation_flow.cc b/chromeos/attestation/attestation_flow.cc new file mode 100644 index 0000000..b60e194 --- /dev/null +++ b/chromeos/attestation/attestation_flow.cc @@ -0,0 +1,192 @@ +// 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."; + if (!on_fail.is_null()) + on_fail.Run(); + return; + } + const base::Closure& task = value ? on_true : on_false; + if (!task.is_null()) + 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."; + if (!on_failure.is_null()) + on_failure.Run(); + return; + } + + // Send the request to the Privacy CA. + server_proxy_->SendEnrollRequest( + data, + base::Bind(&AttestationFlow::SendEnrollResponseToDaemon, + weak_factory_.GetWeakPtr(), + on_failure, + next_task)); +} + +void AttestationFlow::SendEnrollResponseToDaemon( + const base::Closure& on_failure, + const base::Closure& next_task, + bool success, + const std::string& data) { + if (!success) { + LOG(ERROR) << "Attestation: Enroll request failed."; + if (!on_failure.is_null()) + 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."; + if (!on_failure.is_null()) + on_failure.Run(); + return; + } + + // Enrollment has successfully completed, we can move on to whatever is next. + if (!next_task.is_null()) + 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."; + if (!callback.is_null()) + callback.Run(false, ""); + return; + } + + // Send the request to the Privacy CA. + server_proxy_->SendCertificateRequest( + data, + base::Bind(&AttestationFlow::SendCertificateResponseToDaemon, + weak_factory_.GetWeakPtr(), + callback)); +} + +void AttestationFlow::SendCertificateResponseToDaemon( + const CertificateCallback& callback, + bool success, + const std::string& data) { + if (!success) { + LOG(ERROR) << "Attestation: Certificate request failed."; + if (!callback.is_null()) + 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 |