blob: 4d3abd817d9968bbe53a15a8497800d3b62f4167 [file] [log] [blame]
// Copyright 2025 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT
#include <lib/boot-shim/devicetree.h>
#include <lib/boot-shim/item-base.h>
#include <lib/devicetree/matcher.h>
#include <lib/fit/defer.h>
#include <lib/fit/internal/result.h>
#include <lib/zbi-format/secure-entropy.h>
#include <lib/zbi-format/zbi.h>
#include <lib/zbitl/image.h>
#include <explicit-memory/bytes.h>
namespace boot_shim {
namespace {
constexpr std::string_view kKaslrProperty = "kaslr-seed";
constexpr std::string_view kRngProperty = "rng-seed";
fit::result<ItemBase::DataZbi::Error> MaybeAppendEntropy(std::span<std::byte> random_bytes,
zbi_secure_entropy_t entropy_type,
ItemBase::DataZbi& zbi) {
if (!random_bytes.empty()) {
if (auto res = zbi.Append(
{
.type = ZBI_TYPE_SECURE_ENTROPY,
.length = static_cast<uint32_t>(random_bytes.size_bytes()),
.extra = entropy_type,
},
random_bytes);
res.is_error()) {
return res.take_error();
}
// clear the original source of the bytes, devicetree.
mandatory_memset(random_bytes.data(), DevicetreeSecureEntropyItem::kFillPattern,
random_bytes.size_bytes());
}
return fit::ok();
}
} // namespace
fit::result<ItemBase::DataZbi::Error> DevicetreeSecureEntropyItem::AppendItems(DataZbi& zbi) {
if (auto res = MaybeAppendEntropy(rng_bytes_, ZBI_SECURE_ENTROPY_GENERAL, zbi); res.is_error()) {
return res.take_error();
}
rng_bytes_ = {};
if (auto res = MaybeAppendEntropy(kaslr_bytes_, ZBI_SECURE_ENTROPY_EARLY_BOOT, zbi);
res.is_error()) {
return res.take_error();
}
kaslr_bytes_ = {};
return fit::ok();
}
devicetree::ScanState DevicetreeSecureEntropyItem::OnNode(
const devicetree::NodePath& path, const devicetree::PropertyDecoder& decoder) {
if (path == "/") {
return devicetree::ScanState::kActive;
}
if (path != "/chosen") {
return devicetree::ScanState::kDoneWithSubtree;
}
auto [kaslr_seed_prop, rng_seed_prop] = decoder.FindProperties(kKaslrProperty, kRngProperty);
if (rng_seed_prop) {
auto tmp = rng_seed_prop->AsBytes();
rng_bytes_ = {reinterpret_cast<std::byte*>(const_cast<uint8_t*>(tmp.data())), tmp.size_bytes()};
}
if (kaslr_seed_prop) {
auto tmp = kaslr_seed_prop->AsBytes();
kaslr_bytes_ = {reinterpret_cast<std::byte*>(const_cast<uint8_t*>(tmp.data())),
tmp.size_bytes()};
}
return devicetree::ScanState::kDone;
}
} // namespace boot_shim