Commit 109cfa7b authored by Leo Lai's avatar Leo Lai Committed by Commit Bot

use AttestationClient to create certificate request.

We are deprecating attestation methods by CryptohomeClient.

This is the minimum change for chromium-side attestation flow to support
ECC key type.

As for implementation details, it is chosen to let the AttestationFlow
object to hold a constant key type instead of being flexible when
calling GetCertificate. The reasons are 1., we don't have the needs to
specify key type with a single attestation flow instance, and it
requires the key type passing through almost the entire attestation
flow. It implied more code change, but also implies impact to
readability because we already use "key type" terminology to refers to
the type of EMK/EUK in this class; more presence of overloaded "key
type" is not easy for readers.

BUG=b:158955123
TEST=unit_tests.

Change-Id: Iab3cdd0b943219765ec7b99626cba53c382ce6d4
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2474933
Commit-Queue: Leo Lai <cylai@google.com>
Reviewed-by: default avatarMaksim Ivanov <emaxx@chromium.org>
Cr-Commit-Position: refs/heads/master@{#820615}
parent f7d23aba
...@@ -26,6 +26,22 @@ namespace attestation { ...@@ -26,6 +26,22 @@ namespace attestation {
namespace { namespace {
base::Optional<::attestation::CertificateProfile> ProfileToAttestationProtoEnum(
AttestationCertificateProfile p) {
switch (p) {
case PROFILE_ENTERPRISE_MACHINE_CERTIFICATE:
return ::attestation::CertificateProfile::ENTERPRISE_MACHINE_CERTIFICATE;
case PROFILE_ENTERPRISE_USER_CERTIFICATE:
return ::attestation::CertificateProfile::ENTERPRISE_USER_CERTIFICATE;
case PROFILE_CONTENT_PROTECTION_CERTIFICATE:
return ::attestation::CertificateProfile::CONTENT_PROTECTION_CERTIFICATE;
case PROFILE_ENTERPRISE_ENROLLMENT_CERTIFICATE:
return ::attestation::CertificateProfile::
ENTERPRISE_ENROLLMENT_CERTIFICATE;
}
return {};
}
// A reasonable timeout that gives enough time for attestation to be ready, // A reasonable timeout that gives enough time for attestation to be ready,
// yet does not make the caller wait too long. // yet does not make the caller wait too long.
constexpr uint16_t kReadyTimeoutInSeconds = 60; constexpr uint16_t kReadyTimeoutInSeconds = 60;
...@@ -67,15 +83,25 @@ AttestationKeyType AttestationFlow::GetKeyTypeForProfile( ...@@ -67,15 +83,25 @@ AttestationKeyType AttestationFlow::GetKeyTypeForProfile(
AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client, CryptohomeClient* cryptohome_client,
std::unique_ptr<ServerProxy> server_proxy) std::unique_ptr<ServerProxy> server_proxy,
::attestation::KeyType crypto_key_type)
: async_caller_(async_caller), : async_caller_(async_caller),
cryptohome_client_(cryptohome_client), cryptohome_client_(cryptohome_client),
attestation_client_(AttestationClient::Get()), attestation_client_(AttestationClient::Get()),
server_proxy_(std::move(server_proxy)), server_proxy_(std::move(server_proxy)),
crypto_key_type_(crypto_key_type),
ready_timeout_(base::TimeDelta::FromSeconds(kReadyTimeoutInSeconds)), ready_timeout_(base::TimeDelta::FromSeconds(kReadyTimeoutInSeconds)),
retry_delay_( retry_delay_(
base::TimeDelta::FromMilliseconds(kRetryDelayInMilliseconds)) {} base::TimeDelta::FromMilliseconds(kRetryDelayInMilliseconds)) {}
AttestationFlow::AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client,
std::unique_ptr<ServerProxy> server_proxy)
: AttestationFlow(async_caller,
cryptohome_client,
std::move(server_proxy),
::attestation::KEY_TYPE_RSA) {}
AttestationFlow::~AttestationFlow() = default; AttestationFlow::~AttestationFlow() = default;
void AttestationFlow::GetCertificate( void AttestationFlow::GetCertificate(
...@@ -220,12 +246,25 @@ void AttestationFlow::StartCertificateRequest( ...@@ -220,12 +246,25 @@ void AttestationFlow::StartCertificateRequest(
AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile); AttestationKeyType key_type = GetKeyTypeForProfile(certificate_profile);
if (generate_new_key) { if (generate_new_key) {
// Get the attestation service to create a Privacy CA certificate request. // Get the attestation service to create a Privacy CA certificate request.
async_caller_->AsyncTpmAttestationCreateCertRequest( const base::Optional<::attestation::CertificateProfile>
server_proxy_->GetType(), certificate_profile, attestation_profile =
cryptohome::Identification(account_id), request_origin, ProfileToAttestationProtoEnum(certificate_profile);
base::BindOnce(&AttestationFlow::SendCertificateRequestToPCA, if (!attestation_profile) {
weak_factory_.GetWeakPtr(), key_type, account_id, LOG(DFATAL) << "Attestation: Unrecognized profile type: "
key_name, std::move(callback))); << certificate_profile;
return;
}
::attestation::CreateCertificateRequestRequest request;
request.set_username(cryptohome::Identification(account_id).id());
request.set_certificate_profile(*attestation_profile);
request.set_request_origin(request_origin);
request.set_key_type(crypto_key_type_);
attestation_client_->CreateCertificateRequest(
request, base::BindOnce(&AttestationFlow::SendCertificateRequestToPCA,
weak_factory_.GetWeakPtr(), key_type,
account_id, key_name, std::move(callback)));
return; return;
} }
...@@ -264,23 +303,25 @@ void AttestationFlow::OnKeyExistCheckComplete( ...@@ -264,23 +303,25 @@ void AttestationFlow::OnKeyExistCheckComplete(
key_name, std::move(callback), true); key_name, std::move(callback), true);
} }
void AttestationFlow::SendCertificateRequestToPCA(AttestationKeyType key_type, void AttestationFlow::SendCertificateRequestToPCA(
AttestationKeyType key_type,
const AccountId& account_id, const AccountId& account_id,
const std::string& key_name, const std::string& key_name,
CertificateCallback callback, CertificateCallback callback,
bool success, const ::attestation::CreateCertificateRequestReply& reply) {
const std::string& data) { if (reply.status() != ::attestation::STATUS_SUCCESS) {
if (!success) { LOG(ERROR) << "Attestation: Failed to create certificate request. Status: "
LOG(ERROR) << "Attestation: Failed to create certificate request."; << reply.status();
std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, ""); std::move(callback).Run(ATTESTATION_UNSPECIFIED_FAILURE, "");
return; return;
} }
// Send the request to the Privacy CA. // Send the request to the Privacy CA.
server_proxy_->SendCertificateRequest( server_proxy_->SendCertificateRequest(
data, base::BindOnce(&AttestationFlow::SendCertificateResponseToDaemon, reply.pca_request(),
weak_factory_.GetWeakPtr(), key_type, account_id, base::BindOnce(&AttestationFlow::SendCertificateResponseToDaemon,
key_name, std::move(callback))); weak_factory_.GetWeakPtr(), key_type, account_id, key_name,
std::move(callback)));
} }
void AttestationFlow::SendCertificateResponseToDaemon( void AttestationFlow::SendCertificateResponseToDaemon(
......
...@@ -74,6 +74,11 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow { ...@@ -74,6 +74,11 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow {
AttestationFlow(cryptohome::AsyncMethodCaller* async_caller, AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client, CryptohomeClient* cryptohome_client,
std::unique_ptr<ServerProxy> server_proxy); std::unique_ptr<ServerProxy> server_proxy);
AttestationFlow(cryptohome::AsyncMethodCaller* async_caller,
CryptohomeClient* cryptohome_client,
std::unique_ptr<ServerProxy> server_proxy,
::attestation::KeyType crypto_key_type);
virtual ~AttestationFlow(); virtual ~AttestationFlow();
// Sets the timeout for attestation to be ready. // Sets the timeout for attestation to be ready.
...@@ -241,14 +246,13 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow { ...@@ -241,14 +246,13 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow {
// account_id - Identifies the active user. // account_id - Identifies the active user.
// key_name - The name of the key for which a certificate is requested. // key_name - The name of the key for which a certificate is requested.
// callback - Called when the operation completes. // callback - Called when the operation completes.
// success - The status of request creation. // reply - the result returned by |AttestationClient|.
// data - The request data for the Privacy CA. void SendCertificateRequestToPCA(
void SendCertificateRequestToPCA(AttestationKeyType key_type, AttestationKeyType key_type,
const AccountId& account_id, const AccountId& account_id,
const std::string& key_name, const std::string& key_name,
CertificateCallback callback, CertificateCallback callback,
bool success, const ::attestation::CreateCertificateRequestReply& reply);
const std::string& data);
// Called when the Privacy CA responds to a certificate request. The response // Called when the Privacy CA responds to a certificate request. The response
// is asynchronously forwarded as-is to the attestation daemon in order to // is asynchronously forwarded as-is to the attestation daemon in order to
...@@ -295,6 +299,9 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow { ...@@ -295,6 +299,9 @@ class COMPONENT_EXPORT(CHROMEOS_ATTESTATION) AttestationFlow {
AttestationClient* attestation_client_; AttestationClient* attestation_client_;
std::unique_ptr<ServerProxy> server_proxy_; std::unique_ptr<ServerProxy> server_proxy_;
// The key type that asks attestation service to create with.
const ::attestation::KeyType crypto_key_type_;
base::TimeDelta ready_timeout_; base::TimeDelta ready_timeout_;
base::TimeDelta retry_delay_; base::TimeDelta retry_delay_;
......
...@@ -92,10 +92,24 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) AttestationClient { ...@@ -92,10 +92,24 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) AttestationClient {
::attestation::AttestationStatus status) = 0; ::attestation::AttestationStatus status) = 0;
// Allowlists |request| so the certificate requests that comes in afterwards // Allowlists |request| so the certificate requests that comes in afterwards
// will get a fake certificate. if any alias of |request| has been // will get a fake certificate. If any alias of |request| has been
// allowlisted this functions performs no-ops. // allowlisted this functions performs no-ops.
virtual void AllowlistCertificateRequest( virtual void AllowlistCertificateRequest(
const ::attestation::GetCertificateRequest& request) = 0; const ::attestation::GetCertificateRequest& request) = 0;
// Allowlists the request that has |username|, |request_origin|, |profile|,
// and |key_type|, so the certificate requests that comes in afterwards will
// be successfully created.
virtual void AllowlistLegacyCreateCertificateRequest(
const std::string& username,
const std::string& request_origin,
::attestation::CertificateProfile profile,
::attestation::KeyType key_type) = 0;
// Gets the mutable |CreateCertificateRequestReply| that is returned when
// queried.
virtual ::attestation::CreateCertificateRequestReply*
mutable_certificate_request_reply() = 0;
}; };
// Not copyable or movable. // Not copyable or movable.
......
...@@ -49,6 +49,11 @@ FakeAttestationClient::FakeAttestationClient() = default; ...@@ -49,6 +49,11 @@ FakeAttestationClient::FakeAttestationClient() = default;
FakeAttestationClient::~FakeAttestationClient() = default; FakeAttestationClient::~FakeAttestationClient() = default;
::attestation::CreateCertificateRequestReply*
FakeAttestationClient::mutable_certificate_request_reply() {
return &certificate_request_reply_;
}
void FakeAttestationClient::GetKeyInfo( void FakeAttestationClient::GetKeyInfo(
const ::attestation::GetKeyInfoRequest& request, const ::attestation::GetKeyInfoRequest& request,
GetKeyInfoCallback callback) { GetKeyInfoCallback callback) {
...@@ -153,7 +158,18 @@ void FakeAttestationClient::FinishEnroll( ...@@ -153,7 +158,18 @@ void FakeAttestationClient::FinishEnroll(
void FakeAttestationClient::CreateCertificateRequest( void FakeAttestationClient::CreateCertificateRequest(
const ::attestation::CreateCertificateRequestRequest& request, const ::attestation::CreateCertificateRequestRequest& request,
CreateCertificateRequestCallback callback) { CreateCertificateRequestCallback callback) {
NOTIMPLEMENTED(); for (const auto& req : allowlisted_create_requests_) {
if (req.username() == request.username() &&
req.request_origin() == request.request_origin() &&
req.certificate_profile() == request.certificate_profile() &&
req.key_type() == request.key_type()) {
PostProtoResponse(std::move(callback), certificate_request_reply_);
return;
}
}
::attestation::CreateCertificateRequestReply failed_reply;
failed_reply.set_status(::attestation::STATUS_UNEXPECTED_DEVICE_ERROR);
PostProtoResponse(std::move(callback), failed_reply);
} }
void FakeAttestationClient::FinishCertificateRequest( void FakeAttestationClient::FinishCertificateRequest(
...@@ -267,6 +283,19 @@ void FakeAttestationClient::AllowlistCertificateRequest( ...@@ -267,6 +283,19 @@ void FakeAttestationClient::AllowlistCertificateRequest(
certificate_indices_.push_back(kCertificateNotAssigned); certificate_indices_.push_back(kCertificateNotAssigned);
} }
void FakeAttestationClient::AllowlistLegacyCreateCertificateRequest(
const std::string& username,
const std::string& request_origin,
::attestation::CertificateProfile profile,
::attestation::KeyType key_type) {
::attestation::CreateCertificateRequestRequest request;
request.set_username(username);
request.set_request_origin(request_origin);
request.set_certificate_profile(profile);
request.set_key_type(key_type);
allowlisted_create_requests_.push_back(request);
}
AttestationClient::TestInterface* FakeAttestationClient::GetTestInterface() { AttestationClient::TestInterface* FakeAttestationClient::GetTestInterface() {
return this; return this;
} }
......
...@@ -99,6 +99,13 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient ...@@ -99,6 +99,13 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient
::attestation::AttestationStatus status) override; ::attestation::AttestationStatus status) override;
void AllowlistCertificateRequest( void AllowlistCertificateRequest(
const ::attestation::GetCertificateRequest& request) override; const ::attestation::GetCertificateRequest& request) override;
void AllowlistLegacyCreateCertificateRequest(
const std::string& username,
const std::string& request_origin,
::attestation::CertificateProfile profile,
::attestation::KeyType key_type) override;
::attestation::CreateCertificateRequestReply*
mutable_certificate_request_reply() override;
AttestationClient::TestInterface* GetTestInterface() override; AttestationClient::TestInterface* GetTestInterface() override;
...@@ -110,8 +117,15 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient ...@@ -110,8 +117,15 @@ class COMPONENT_EXPORT(CHROMEOS_DBUS_ATTESTATION) FakeAttestationClient
bool is_enrolled_ = false; bool is_enrolled_ = false;
::attestation::CreateCertificateRequestReply certificate_request_reply_;
// Maintains the allowlisted certificate requests. // Maintains the allowlisted certificate requests.
std::vector<::attestation::GetCertificateRequest> allowlisted_requests_; std::vector<::attestation::GetCertificateRequest> allowlisted_requests_;
// Maintains the allowlisted legacy create-certificate requests.
std::vector<::attestation::CreateCertificateRequestRequest>
allowlisted_create_requests_;
// Maintains the numbers assigned to the allowlisted requests. // Maintains the numbers assigned to the allowlisted requests.
std::vector<int> certificate_indices_; std::vector<int> certificate_indices_;
// The count of certificates that has been issued. // The count of certificates that has been issued.
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment