| // Copyright 2023 The ChromiumOS Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| #include "arc/keymint/keymint_server.h" | |
| #include <utility> | |
| #include <base/check.h> | |
| #include <base/functional/bind.h> | |
| #include <base/logging.h> | |
| #include <base/task/single_thread_task_runner.h> | |
| #include <base/threading/platform_thread.h> | |
| #include <keymaster/android_keymaster_messages.h> | |
| #include <libarc-attestation/lib/interface.h> | |
| #include <mojo/keymint.mojom.h> | |
| #include "arc/keymint/conversion.h" | |
| // The implementations of |arc::mojom::KeyMintServer| methods below have the | |
| // following overall pattern: | |
| // | |
| // * Generate an std::unique_ptr to a KeyMint request data structure from the | |
| // arguments received from Mojo, usually through the helpers in conversion.h. | |
| // | |
| // * Execute the operation in |backend->keymint()|, posting this task to a | |
| // background thread. This produces a KeyMint 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 KeyMint response to the Mojo return values, and run the | |
| // result callback. | |
| // | |
| namespace arc::keymint { | |
| namespace { | |
| constexpr size_t kOperationTableSize = 16; | |
| // TODO(b/278968783): Add version negotiation for KeyMint. | |
| // KeyMint Message versions are drawn from Android | |
| // Keymaster Messages. | |
| constexpr int32_t kKeyMintMessageVersion = 4; | |
| constexpr ::keymaster::KmVersion kKeyMintVersion = | |
| ::keymaster::KmVersion::KEYMINT_2; | |
| } // namespace | |
| KeyMintServer::Backend::Backend() | |
| : context_(new context::ArcKeyMintContext(kKeyMintVersion)), | |
| keymint_(context_, kOperationTableSize, kKeyMintMessageVersion) {} | |
| KeyMintServer::Backend::~Backend() = default; | |
| KeyMintServer::KeyMintServer() | |
| : backend_thread_("BackendKeyMintThread"), weak_ptr_factory_(this) { | |
| CHECK(backend_thread_.Start()) << "Failed to start keymint thread"; | |
| } | |
| KeyMintServer::~KeyMintServer() = default; | |
| void KeyMintServer::UpdateContextPlaceholderKeys( | |
| std::vector<mojom::ChromeOsKeyPtr> keys, | |
| base::OnceCallback<void(bool)> callback) { | |
| base::OnceCallback<void(bool)> callback_in_original_runner = base::BindOnce( | |
| [](scoped_refptr<base::TaskRunner> original_task_runner, | |
| base::OnceCallback<void(bool)> callback, bool success) { | |
| original_task_runner->PostTask( | |
| FROM_HERE, base::BindOnce(std::move(callback), success)); | |
| }, | |
| base::SingleThreadTaskRunner::GetCurrentDefault(), std::move(callback)); | |
| backend_thread_.task_runner()->PostTask( | |
| FROM_HERE, base::BindOnce( | |
| [](context::ArcKeyMintContext* context, | |
| std::vector<mojom::ChromeOsKeyPtr> keys, | |
| base::OnceCallback<void(bool)> callback) { | |
| // |context| is guaranteed valid here because it's owned | |
| // by |backend_|, which outlives the |backend_thread_| | |
| // this runs on. | |
| context->set_placeholder_keys(std::move(keys)); | |
| std::move(callback).Run(/*success=*/true); | |
| }, | |
| backend_.context(), std::move(keys), | |
| std::move(callback_in_original_runner))); | |
| } | |
| void KeyMintServer::SetSystemVersion(uint32_t android_version, | |
| uint32_t android_patchlevel) { | |
| auto task_lambda = [](context::ArcKeyMintContext* context, | |
| uint32_t android_version, uint32_t android_patchlevel) { | |
| // |context| is guaranteed valid here because it's owned | |
| // by |backend_|, which outlives the |backend_thread_| | |
| // this runs on. | |
| context->SetSystemVersion(android_version, android_patchlevel); | |
| }; | |
| backend_thread_.task_runner()->PostTask( | |
| FROM_HERE, base::BindOnce(task_lambda, backend_.context(), | |
| android_version, android_patchlevel)); | |
| } | |
| template <typename KmMember, typename KmRequest, typename KmResponse> | |
| void KeyMintServer::RunKeyMintRequest( | |
| const base::Location& location, | |
| KmMember member, | |
| std::unique_ptr<KmRequest> request, | |
| base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) { | |
| auto task_lambda = | |
| [](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 KeyMint response data structure. | |
| auto response = | |
| std::make_unique<KmResponse>(keymaster->message_version()); | |
| // 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))); | |
| }; | |
| // Post the KeyMint operation to a background thread while capturing the | |
| // current task runner. | |
| backend_thread_.task_runner()->PostTask( | |
| location, | |
| base::BindOnce(task_lambda, location, | |
| base::SingleThreadTaskRunner::GetCurrentDefault(), | |
| backend_.keymint(), member, std::move(request), | |
| std::move(callback))); | |
| } | |
| template <typename KmMember, typename KmResponse> | |
| void KeyMintServer::RunKeyMintRequest_EmptyInput( | |
| const base::Location& location, | |
| KmMember member, | |
| base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) { | |
| auto task_lambda = | |
| [](const base::Location& location, | |
| scoped_refptr<base::TaskRunner> original_task_runner, | |
| ::keymaster::AndroidKeymaster* keymaster, KmMember member, | |
| base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) { | |
| // Prepare a KeyMint response data structure. | |
| auto response = | |
| std::make_unique<KmResponse>(keymaster->message_version()); | |
| // Execute the operation. | |
| auto result = (*keymaster.*member)(); | |
| response->error = result.error; | |
| // Post |callback| to the |original_task_runner| given |response|. | |
| original_task_runner->PostTask( | |
| location, base::BindOnce(std::move(callback), std::move(response))); | |
| }; | |
| // Post the KeyMint operation to a background thread while capturing the | |
| // current task runner. | |
| backend_thread_.task_runner()->PostTask( | |
| location, | |
| base::BindOnce(task_lambda, location, | |
| base::SingleThreadTaskRunner::GetCurrentDefault(), | |
| backend_.keymint(), member, std::move(callback))); | |
| } | |
| template <typename KmMember, typename KmRequest, typename KmResponse> | |
| void KeyMintServer::RunKeyMintRequest_SingleInput( | |
| const base::Location& location, | |
| KmMember member, | |
| std::unique_ptr<KmRequest> request, | |
| base::OnceCallback<void(std::unique_ptr<KmResponse>)> callback) { | |
| auto task_lambda = | |
| [](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 KeyMint response data structure. | |
| auto response = | |
| std::make_unique<KmResponse>(keymaster->message_version()); | |
| // Execute the operation. | |
| auto result = (*keymaster.*member)(*request); | |
| // Post |callback| to the |original_task_runner| given |response|. | |
| response->error = result.error; | |
| original_task_runner->PostTask( | |
| location, base::BindOnce(std::move(callback), std::move(response))); | |
| }; | |
| // Post the KeyMint operation to a background thread while capturing the | |
| // current task runner. | |
| backend_thread_.task_runner()->PostTask( | |
| location, | |
| base::BindOnce(task_lambda, location, | |
| base::SingleThreadTaskRunner::GetCurrentDefault(), | |
| backend_.keymint(), member, std::move(request), | |
| std::move(callback))); | |
| } | |
| void KeyMintServer::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>(kKeyMintMessageVersion); | |
| ConvertToKeymasterMessage(data, &km_request->random_data); | |
| auto task_lambda = base::BindOnce( | |
| [](AddRngEntropyCallback callback, | |
| std::unique_ptr<::keymaster::AddEntropyResponse> km_response) { | |
| // Run callback. | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::AddRngEntropy, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::GetKeyCharacteristics( | |
| arc::mojom::keymint::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, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](GetKeyCharacteristicsCallback callback, | |
| std::unique_ptr<::keymaster::GetKeyCharacteristicsResponse> | |
| km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeGetKeyCharacteristicsResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, | |
| &::keymaster::AndroidKeymaster::GetKeyCharacteristics, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::GenerateKey( | |
| arc::mojom::keymint::GenerateKeyRequestPtr request, | |
| GenerateKeyCallback callback) { | |
| auto km_request = | |
| MakeGenerateKeyRequest(request, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](GenerateKeyCallback callback, | |
| std::unique_ptr<::keymaster::GenerateKeyResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeGenerateKeyResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::GenerateKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::ImportKey(arc::mojom::keymint::ImportKeyRequestPtr request, | |
| ImportKeyCallback callback) { | |
| auto km_request = | |
| MakeImportKeyRequest(request, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](ImportKeyCallback callback, | |
| std::unique_ptr<::keymaster::ImportKeyResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeImportKeyResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::ImportKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::ImportWrappedKey( | |
| arc::mojom::keymint::ImportWrappedKeyRequestPtr request, | |
| ImportWrappedKeyCallback callback) { | |
| auto km_request = MakeImportWrappedKeyRequest( | |
| request, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](ImportKeyCallback callback, | |
| std::unique_ptr<::keymaster::ImportWrappedKeyResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeImportWrappedKeyResult(*km_response); | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::ImportWrappedKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::UpgradeKey( | |
| arc::mojom::keymint::UpgradeKeyRequestPtr request, | |
| UpgradeKeyCallback callback) { | |
| auto km_request = | |
| MakeUpgradeKeyRequest(request, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](UpgradeKeyCallback callback, | |
| std::unique_ptr<::keymaster::UpgradeKeyResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeUpgradeKeyResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::UpgradeKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::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>( | |
| backend_.keymint()->message_version()); | |
| km_request->SetKeyMaterial(key_blob.data(), key_blob.size()); | |
| auto task_lambda = base::BindOnce( | |
| [](DeleteKeyCallback callback, | |
| std::unique_ptr<::keymaster::DeleteKeyResponse> km_response) { | |
| // Run callback. | |
| CHECK(km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::DeleteKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::DeleteAllKeys(DeleteAllKeysCallback callback) { | |
| // Prepare keymint request. | |
| auto km_request = std::make_unique<::keymaster::DeleteAllKeysRequest>( | |
| backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](DeleteAllKeysCallback callback, | |
| std::unique_ptr<::keymaster::DeleteAllKeysResponse> km_response) { | |
| // Run callback. | |
| CHECK(km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::DeleteAllKeys, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::DestroyAttestationIds( | |
| DestroyAttestationIdsCallback callback) { | |
| // Implement this when needed. | |
| std::move(callback).Run(KM_ERROR_UNIMPLEMENTED); | |
| } | |
| void KeyMintServer::Begin(arc::mojom::keymint::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, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](BeginCallback callback, | |
| std::unique_ptr<::keymaster::BeginOperationResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeBeginResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::BeginOperation, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::DeviceLocked( | |
| bool password_only, | |
| arc::mojom::keymint::TimeStampTokenPtr timestamp_token, | |
| DeviceLockedCallback callback) { | |
| // Convert input |request| into |km_request|. All data is deep copied to avoid | |
| // use-after-free. | |
| auto km_request = | |
| MakeDeviceLockedRequest(password_only, std::move(timestamp_token), | |
| backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](DeviceLockedCallback callback, | |
| std::unique_ptr<::keymaster::DeviceLockedResponse> km_response) { | |
| // Run callback. | |
| CHECK(km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest_SingleInput(FROM_HERE, | |
| &::keymaster::AndroidKeymaster::DeviceLocked, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::EarlyBootEnded(EarlyBootEndedCallback callback) { | |
| auto task_lambda = base::BindOnce( | |
| [](EarlyBootEndedCallback callback, | |
| std::unique_ptr<::keymaster::EarlyBootEndedResponse> km_response) { | |
| // Run callback. | |
| CHECK(km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest_EmptyInput(FROM_HERE, | |
| &::keymaster::AndroidKeymaster::EarlyBootEnded, | |
| std::move(task_lambda)); | |
| // Signal to libarc-attestation to start provisioning the certificate for | |
| // attestation. | |
| LOG(INFO) << "Provisioning the Lib Arc-Attestation DK Certificate"; | |
| arc_attestation::ProvisionDkCert(false /* blocking */); | |
| } | |
| void KeyMintServer::ConvertStorageKeyToEphemeral( | |
| const std::vector<uint8_t>& storage_key_blob, | |
| ConvertStorageKeyToEphemeralCallback callback) { | |
| // Implement this when needed. | |
| auto error = | |
| arc::mojom::keymint::ByteArrayOrError::NewError(KM_ERROR_UNIMPLEMENTED); | |
| std::move(callback).Run(std::move(error)); | |
| } | |
| void KeyMintServer::GetRootOfTrustChallenge( | |
| GetRootOfTrustChallengeCallback callback) { | |
| // Implement this when needed. | |
| auto error = | |
| arc::mojom::keymint::ByteArrayOrError::NewError(KM_ERROR_UNIMPLEMENTED); | |
| std::move(callback).Run(std::move(error)); | |
| } | |
| void KeyMintServer::GetRootOfTrust(const std::vector<uint8_t>& challenge, | |
| GetRootOfTrustCallback callback) { | |
| // Implement this when needed. | |
| auto error = | |
| arc::mojom::keymint::ByteArrayOrError::NewError(KM_ERROR_UNIMPLEMENTED); | |
| std::move(callback).Run(std::move(error)); | |
| } | |
| void KeyMintServer::SendRootOfTrust(const std::vector<uint8_t>& root_of_trust, | |
| SendRootOfTrustCallback callback) { | |
| // Implement this when needed. | |
| std::move(callback).Run(KM_ERROR_UNIMPLEMENTED); | |
| } | |
| void KeyMintServer::UpdateAad(arc::mojom::keymint::UpdateRequestPtr request, | |
| UpdateAadCallback callback) { | |
| // Convert input |request| into |km_request|. All data is deep copied to avoid | |
| // use-after-free. | |
| auto km_request = MakeUpdateAadOperationRequest( | |
| request, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](UpdateAadCallback callback, | |
| std::unique_ptr<::keymaster::UpdateOperationResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeUpdateResult(*km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::UpdateOperation, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::Update(arc::mojom::keymint::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, backend_.keymint()->message_version()); | |
| auto input_size = km_request->input.buffer_size(); | |
| auto task_lambda = base::BindOnce( | |
| [](UpdateCallback callback, const size_t input_size, | |
| std::unique_ptr<::keymaster::UpdateOperationResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeUpdateResult(*km_response); | |
| // Run callback. | |
| // This logic is derived from AndroidKeyMintOperation.cpp | |
| if (km_response->error == KM_ERROR_OK && | |
| km_response->input_consumed != input_size) { | |
| LOG(ERROR) << "KeyMint Server: Unknown error in Update due to size " | |
| "mismatch."; | |
| std::move(callback).Run( | |
| arc::mojom::keymint::ByteArrayOrError::NewError( | |
| KM_ERROR_UNKNOWN_ERROR)); | |
| } else { | |
| std::move(callback).Run(std::move(response)); | |
| } | |
| }, | |
| std::move(callback), std::move(input_size)); | |
| // Call KeyMint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::UpdateOperation, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::Finish(arc::mojom::keymint::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, backend_.keymint()->message_version()); | |
| auto task_lambda = base::BindOnce( | |
| [](FinishCallback callback, | |
| std::unique_ptr<::keymaster::FinishOperationResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeFinishResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::FinishOperation, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::Abort(uint64_t op_handle, AbortCallback callback) { | |
| // Prepare keymint request. | |
| auto km_request = std::make_unique<::keymaster::AbortOperationRequest>( | |
| backend_.keymint()->message_version()); | |
| km_request->op_handle = op_handle; | |
| auto task_lambda = base::BindOnce( | |
| [](AbortCallback callback, | |
| std::unique_ptr<::keymaster::AbortOperationResponse> km_response) { | |
| // Run callback. | |
| CHECK(km_response); | |
| std::move(callback).Run(km_response->error); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::AbortOperation, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::GetSharedSecretParameters( | |
| GetSharedSecretParametersCallback callback) { | |
| auto task_lambda = base::BindOnce( | |
| [](GetSharedSecretParametersCallback callback, | |
| std::unique_ptr<::keymaster::GetHmacSharingParametersResponse> | |
| km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeGetSharedSecretParametersResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest_EmptyInput( | |
| FROM_HERE, &::keymaster::AndroidKeymaster::GetHmacSharingParameters, | |
| std::move(task_lambda)); | |
| } | |
| void KeyMintServer::ComputeSharedSecret( | |
| const std::vector<arc::mojom::keymint::SharedSecretParametersPtr> request, | |
| ComputeSharedSecretCallback callback) { | |
| // Convert input |request| into |km_request|. All data is deep copied to avoid | |
| // use-after-free. | |
| auto km_request = MakeComputeSharedSecretRequest( | |
| request, backend_.keymint()->message_version()); | |
| // Validate the |km_request| before passing to Reference impl. | |
| if (km_request->params_array.params_array == nullptr) { | |
| auto response = arc::mojom::keymint::ByteArrayOrError::NewError( | |
| KM_ERROR_MEMORY_ALLOCATION_FAILED); | |
| std::move(callback).Run(std::move(response)); | |
| return; | |
| } | |
| // Validate nonce size for each shared secret parameter. | |
| for (size_t i = 0; i < request.size(); i++) { | |
| if (sizeof(km_request->params_array.params_array[i].nonce) != | |
| request[i]->nonce.size()) { | |
| auto response = arc::mojom::keymint::ByteArrayOrError::NewError( | |
| KM_ERROR_INVALID_ARGUMENT); | |
| std::move(callback).Run(std::move(response)); | |
| return; | |
| } | |
| } | |
| auto task_lambda = base::BindOnce( | |
| [](ComputeSharedSecretCallback callback, | |
| std::unique_ptr<::keymaster::ComputeSharedHmacResponse> km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeComputeSharedSecretResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest_SingleInput( | |
| FROM_HERE, &::keymaster::AndroidKeymaster::ComputeSharedHmac, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::GenerateTimeStamp(const uint64 challenge, | |
| GenerateTimeStampCallback callback) { | |
| // Convert input |request| into |km_request|. All data is deep copied to avoid | |
| // use-after-free. | |
| auto km_request = | |
| std::make_unique<::keymaster::GenerateTimestampTokenRequest>( | |
| backend_.keymint()->message_version()); | |
| km_request->challenge = challenge; | |
| auto task_lambda = base::BindOnce( | |
| [](GenerateTimeStampCallback callback, | |
| std::unique_ptr<::keymaster::GenerateTimestampTokenResponse> | |
| km_response) { | |
| // Prepare mojo response. | |
| CHECK(km_response); | |
| auto response = MakeGenerateTimeStampTokenResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call KeyMint. | |
| RunKeyMintRequest(FROM_HERE, | |
| &::keymaster::AndroidKeymaster::GenerateTimestampToken, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| void KeyMintServer::GenerateEcdsaP256KeyPair( | |
| bool test_mode, GenerateEcdsaP256KeyPairCallback callback) { | |
| // Prepare keymint request. | |
| auto km_request = std::make_unique<::keymaster::GenerateRkpKeyRequest>( | |
| backend_.keymint()->message_version()); | |
| km_request->test_mode = test_mode; | |
| auto task_lambda = base::BindOnce( | |
| [](GenerateEcdsaP256KeyPairCallback callback, | |
| std::unique_ptr<::keymaster::GenerateRkpKeyResponse> km_response) { | |
| CHECK(km_response); | |
| arc::mojom::keymint::GenerateEcdsaP256KeyPairResultOrErrorPtr response = | |
| MakeGenerateEcdsaP256KeyPairResult(*km_response); | |
| // Run callback. | |
| std::move(callback).Run(std::move(response)); | |
| }, | |
| std::move(callback)); | |
| // Call keymint. | |
| RunKeyMintRequest(FROM_HERE, &::keymaster::AndroidKeymaster::GenerateRkpKey, | |
| std::move(km_request), std::move(task_lambda)); | |
| } | |
| } // namespace arc::keymint |