blob: 39a19967432b4af671db88d6aef20d2d081ce8ae [file] [log] [blame]
// 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