blob: d133e12db1901cb33a1fe78d2deb052c0127b38e [file] [log] [blame]
// Copyright 2019 The Chromium OS 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 "arc/keymaster/keymaster_server.h"
#include <utility>
#include <base/bind.h>
#include <base/threading/platform_thread.h>
#include <base/threading/thread_task_runner_handle.h>
#include <keymaster/android_keymaster_messages.h>
#include "arc/keymaster/conversion.h"
// The implementations of |arc::mojom::KeymasterServer| methods below have the
// following overall pattern:
//
// * Generate an std::unique_ptr to a Keymaster request data structure from the
// arguments received from Mojo, usually through the helpers in conversion.h.
//
// * Execute the operation in |backend->keymaster()|, posting this task to a
// background thread. This produces a Keymaster response data structure.
//
// * Post the response to a callback that runs on the original thread (in this
// case, the Mojo thread where the request started).
//
// * Convert the Keymaster response to the Mojo return values, and run the
// result callback.
//
namespace arc {
namespace keymaster {
namespace {
constexpr size_t kOperationTableSize = 16;
} // namespace
KeymasterServer::Backend::Backend()
: context_(new context::ArcKeymasterContext()),
keymaster_(context_, kOperationTableSize) {}
KeymasterServer::Backend::~Backend() = default;
KeymasterServer::KeymasterServer() : backend_thread_("BackendKeymasterThread") {
CHECK(backend_thread_.Start()) << "Failed to start keymaster thread";
}
KeymasterServer::~KeymasterServer() = default;
void KeymasterServer::SetSystemVersion(uint32_t os_version,
uint32_t os_patchlevel) {
backend_thread_.task_runner()->PostTask(
FROM_HERE, base::BindOnce(
[](context::ArcKeymasterContext* context,
uint32_t os_version, uint32_t os_patchlevel) {
// |context| is guaranteed valid here because it's owned
// by |backend_|, which outlives the |backend_thread_|
// this runs on.
context->SetSystemVersion(os_version, os_patchlevel);
},
backend_.context(), os_version, os_patchlevel));
}
template <typename KmMember, typename KmRequest, typename KmResponse>
void KeymasterServer::RunKeymasterRequest(
const base::Location& location,
KmMember member,
std::unique_ptr<KmRequest> request,
base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) {
// Post the Keymaster operation to a background thread while capturing the
// current task runner.
backend_thread_.task_runner()->PostTask(
location,
base::BindOnce(
[](const base::Location& location,
scoped_refptr<base::TaskRunner> original_task_runner,
::keymaster::AndroidKeymaster* keymaster, KmMember member,
std::unique_ptr<KmRequest> request,
base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) {
// Prepare a Keymaster response data structure.
auto response = std::make_unique<KmResponse>();
// Execute the operation.
(*keymaster.*member)(*request, response.get());
// Post |callback| to the |original_task_runner| given |response|.
original_task_runner->PostTask(
location,
base::BindOnce(std::move(callback), std::move(response)));
},
location, base::ThreadTaskRunnerHandle::Get(), backend_.keymaster(),
member, std::move(request), std::move(callback)));
}
void KeymasterServer::AddRngEntropy(const std::vector<uint8_t>& data,
AddRngEntropyCallback callback) {
// Convert input |data| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = std::make_unique<::keymaster::AddEntropyRequest>();
ConvertToMessage(data, &km_request->random_data);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::AddRngEntropy,
std::move(km_request),
base::BindOnce(
[](AddRngEntropyCallback callback,
std::unique_ptr<::keymaster::AddEntropyResponse> km_response) {
// Run callback.
std::move(callback).Run(km_response->error);
},
std::move(callback)));
}
void KeymasterServer::GetKeyCharacteristics(
::arc::mojom::GetKeyCharacteristicsRequestPtr request,
GetKeyCharacteristicsCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeGetKeyCharacteristicsRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::GetKeyCharacteristics,
std::move(km_request),
base::BindOnce(
[](GetKeyCharacteristicsCallback callback,
std::unique_ptr<::keymaster::GetKeyCharacteristicsResponse>
km_response) {
// Prepare mojo response.
auto response = MakeGetKeyCharacteristicsResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::GenerateKey(
std::vector<mojom::KeyParameterPtr> key_params,
GenerateKeyCallback callback) {
// Convert input |key_params| into |km_request|. All data is deep copied to
// avoid use-after-free.
auto km_request = MakeGenerateKeyRequest(key_params);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::GenerateKey,
std::move(km_request),
base::BindOnce(
[](GenerateKeyCallback callback,
std::unique_ptr<::keymaster::GenerateKeyResponse> km_response) {
// Prepare mojo response.
auto response = MakeGenerateKeyResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::ImportKey(arc::mojom::ImportKeyRequestPtr request,
ImportKeyCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeImportKeyRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::ImportKey,
std::move(km_request),
base::BindOnce(
[](ImportKeyCallback callback,
std::unique_ptr<::keymaster::ImportKeyResponse> km_response) {
// Prepare mojo response.
auto response = MakeImportKeyResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::ExportKey(arc::mojom::ExportKeyRequestPtr request,
ExportKeyCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeExportKeyRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::ExportKey,
std::move(km_request),
base::BindOnce(
[](ExportKeyCallback callback,
std::unique_ptr<::keymaster::ExportKeyResponse> km_response) {
// Prepare mojo response.
auto response = MakeExportKeyResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::AttestKey(arc::mojom::AttestKeyRequestPtr request,
AttestKeyCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeAttestKeyRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::AttestKey,
std::move(km_request),
base::BindOnce(
[](AttestKeyCallback callback,
std::unique_ptr<::keymaster::AttestKeyResponse> km_response) {
// Prepare mojo response.
auto response = MakeAttestKeyResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::UpgradeKey(arc::mojom::UpgradeKeyRequestPtr request,
UpgradeKeyCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeUpgradeKeyRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::UpgradeKey,
std::move(km_request),
base::BindOnce(
[](UpgradeKeyCallback callback,
std::unique_ptr<::keymaster::UpgradeKeyResponse> km_response) {
// Prepare mojo response.
auto response = MakeUpgradeKeyResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::DeleteKey(const std::vector<uint8_t>& key_blob,
DeleteKeyCallback callback) {
// Convert input |key_blob| into |km_request|. All data is deep copied to
// avoid use-after-free.
auto km_request = std::make_unique<::keymaster::DeleteKeyRequest>();
km_request->SetKeyMaterial(key_blob.data(), key_blob.size());
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::DeleteKey,
std::move(km_request),
base::BindOnce(
[](DeleteKeyCallback callback,
std::unique_ptr<::keymaster::DeleteKeyResponse> km_response) {
// Run callback.
std::move(callback).Run(km_response->error);
},
std::move(callback)));
}
void KeymasterServer::DeleteAllKeys(DeleteAllKeysCallback callback) {
// Prepare keymaster request.
auto km_request = std::make_unique<::keymaster::DeleteAllKeysRequest>();
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::DeleteAllKeys,
std::move(km_request),
base::BindOnce(
[](DeleteAllKeysCallback callback,
std::unique_ptr<::keymaster::DeleteAllKeysResponse> km_response) {
// Run callback.
std::move(callback).Run(km_response->error);
},
std::move(callback)));
}
void KeymasterServer::Begin(arc::mojom::BeginRequestPtr request,
BeginCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeBeginOperationRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::BeginOperation,
std::move(km_request),
base::BindOnce(
[](BeginCallback callback,
std::unique_ptr<::keymaster::BeginOperationResponse> km_response) {
// Prepare mojo response.
auto response = MakeBeginResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::Update(arc::mojom::UpdateRequestPtr request,
UpdateCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeUpdateOperationRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::UpdateOperation,
std::move(km_request),
base::BindOnce(
[](UpdateCallback callback,
std::unique_ptr<::keymaster::UpdateOperationResponse>
km_response) {
// Prepare mojo response.
auto response = MakeUpdateResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::Finish(arc::mojom::FinishRequestPtr request,
FinishCallback callback) {
// Convert input |request| into |km_request|. All data is deep copied to avoid
// use-after-free.
auto km_request = MakeFinishOperationRequest(request);
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::FinishOperation,
std::move(km_request),
base::BindOnce(
[](FinishCallback callback,
std::unique_ptr<::keymaster::FinishOperationResponse>
km_response) {
// Prepare mojo response.
auto response = MakeFinishResult(*km_response);
// Run callback.
std::move(callback).Run(std::move(response));
},
std::move(callback)));
}
void KeymasterServer::Abort(uint64_t op_handle, AbortCallback callback) {
// Prepare keymaster request.
auto km_request = std::make_unique<::keymaster::AbortOperationRequest>();
km_request->op_handle = op_handle;
// Call keymaster.
RunKeymasterRequest(
FROM_HERE, &::keymaster::AndroidKeymaster::AbortOperation,
std::move(km_request),
base::BindOnce(
[](AbortCallback callback,
std::unique_ptr<::keymaster::AbortOperationResponse> km_response) {
// Run callback.
std::move(callback).Run(km_response->error);
},
std::move(callback)));
}
} // namespace keymaster
} // namespace arc