| // Copyright 2019 The Fuchsia 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 "src/ledger/bin/encryption/impl/key_service.h" |
| |
| #include <lib/async/cpp/task.h> |
| #include <lib/fit/function.h> |
| |
| #include <string> |
| |
| #include "src/ledger/bin/encryption/primitives/kdf.h" |
| #include "src/ledger/lib/callback/scoped_callback.h" |
| #include "third_party/abseil-cpp/absl/strings/str_cat.h" |
| |
| namespace encryption { |
| |
| namespace { |
| |
| constexpr size_t kMasterKeysCacheSize = 10u; |
| |
| } // namespace |
| |
| KeyService::KeyService(async_dispatcher_t* dispatcher, std::string namespace_id) |
| : dispatcher_(dispatcher), |
| namespace_id_(std::move(namespace_id)), |
| master_keys_(kMasterKeysCacheSize, Status::OK, |
| [this](auto k, auto c) { GenerateMasterKey(std::move(k), std::move(c)); }), |
| weak_factory_(this) {} |
| |
| void KeyService::GetReferenceKey(const std::string& namespace_id, |
| const std::string& reference_key_id, |
| fit::function<void(const std::string&)> callback) { |
| std::string result = |
| HMAC256KDF(absl::StrCat(namespace_id, reference_key_id), kRandomlyGeneratedKeySize); |
| async::PostTask(dispatcher_, ledger::MakeScoped(weak_factory_.GetWeakPtr(), |
| [result = std::move(result), |
| callback = std::move(callback)]() mutable { |
| callback(result); |
| })); |
| } |
| |
| void KeyService::GetWrappingKey(uint32_t key_index, |
| fit::function<void(Status, std::string)> callback) { |
| master_keys_.Get(kDefaultKeyIndex, [this, callback = std::move(callback)]( |
| Status status, const std::string& master_key) { |
| if (status != Status::OK) { |
| callback(status, ""); |
| return; |
| } |
| std::string derived_key = |
| HMAC256KDF(absl::StrCat(master_key, namespace_id_, "wrapping"), kDerivedKeySize); |
| callback(Status::OK, derived_key); |
| }); |
| } |
| |
| void KeyService::GetChunkingKey(fit::function<void(Status, std::string)> callback) { |
| master_keys_.Get(kDefaultKeyIndex, [this, callback = std::move(callback)]( |
| Status status, const std::string& master_key) { |
| if (status != Status::OK) { |
| callback(status, ""); |
| return; |
| } |
| std::string derived_key = |
| HMAC256KDF(absl::StrCat(master_key, namespace_id_, "chunking"), kChunkingKeySize); |
| callback(Status::OK, derived_key); |
| }); |
| } |
| |
| void KeyService::GetPageIdKey(fit::function<void(Status, std::string)> callback) { |
| master_keys_.Get(kDefaultKeyIndex, [this, callback = std::move(callback)]( |
| Status status, const std::string& master_key) { |
| if (status != Status::OK) { |
| callback(status, ""); |
| return; |
| } |
| std::string derived_key = |
| HMAC256KDF(absl::StrCat(master_key, namespace_id_, "page_id"), kDerivedKeySize); |
| callback(Status::OK, derived_key); |
| }); |
| } |
| |
| void KeyService::GetEncryptionKey(uint32_t key_index, |
| fit::function<void(Status, std::string)> callback) { |
| // TODO(12320): Derive this key from master key + shredding keys. |
| master_keys_.Get(key_index, [this, callback = std::move(callback)]( |
| Status status, const std::string& master_key) { |
| if (status != Status::OK) { |
| callback(status, ""); |
| return; |
| } |
| std::string derived_key = |
| HMAC256KDF(absl::StrCat(master_key, namespace_id_, "encryption"), 16u); |
| callback(Status::OK, derived_key); |
| }); |
| } |
| |
| void KeyService::GetRemoteObjectIdKey(uint32_t key_index, |
| fit::function<void(Status, std::string)> callback) { |
| // TODO(12320): Derive this key from master key + shredding keys. |
| master_keys_.Get(key_index, [this, callback = std::move(callback)]( |
| Status status, const std::string& master_key) { |
| if (status != Status::OK) { |
| callback(status, ""); |
| return; |
| } |
| std::string derived_key = |
| HMAC256KDF(absl::StrCat(master_key, namespace_id_, "remote_object_id"), kDerivedKeySize); |
| callback(Status::OK, derived_key); |
| }); |
| } |
| |
| void KeyService::GenerateMasterKey(uint32_t key_index, |
| fit::function<void(Status, std::string)> callback) { |
| async::PostTask( |
| dispatcher_, |
| ledger::MakeScoped(weak_factory_.GetWeakPtr(), [key_index, callback = std::move(callback)]() { |
| std::string master_key(16u, 0); |
| memcpy(&master_key[0], &key_index, sizeof(key_index)); |
| callback(Status::OK, std::move(master_key)); |
| })); |
| } |
| |
| } // namespace encryption |