exo2: implement rest of main other than SetupSocProtections

This commit is contained in:
Michael Scire
2020-05-12 13:27:53 -07:00
committed by SciresM
parent f391354415
commit 87bdc46beb
18 changed files with 408 additions and 78 deletions

View File

@@ -17,9 +17,23 @@
#include "../secmon_error.hpp"
#include "../secmon_key_storage.hpp"
#include "secmon_boot.hpp"
#include "secmon_boot_key_data.hpp"
namespace ams::secmon::boot {
void CalculatePackage2Hash(se::Sha256Hash *dst, const pkg2::Package2Meta &meta, uintptr_t package2_start) {
/* Determine the region to hash. */
const void *data = reinterpret_cast<const void *>(package2_start);
const size_t size = meta.GetSize();
/* Flush to ensure the SE sees the correct data. */
hw::FlushDataCache(data, size);
hw::DataSynchronizationBarrierInnerShareable();
/* Calculate the hash. */
se::CalculateSha256(dst, data, size);
}
bool VerifyPackage2Signature(pkg2::Package2Header &header, const void *mod, size_t mod_size) {
return VerifySignature(header.signature, sizeof(header.signature), mod, mod_size, std::addressof(header.meta), sizeof(header.meta));
}
@@ -49,4 +63,90 @@ namespace ams::secmon::boot {
hw::DataSynchronizationBarrierInnerShareable();
}
bool VerifyPackage2Meta(const pkg2::Package2Meta &meta) {
/* Get the obfuscated metadata. */
const size_t size = meta.GetSize();
const u8 key_generation = meta.GetKeyGeneration();
/* Check that size is big enough for the header. */
if (size <= sizeof(pkg2::Package2Header)) {
return false;
}
/* Check that the size isn't larger than what we allow. */
if (size > pkg2::Package2SizeMax) {
return false;
}
/* Check that the key generation is one that we can use. */
static_assert(pkg1::KeyGeneration_Count == 11);
if (key_generation >= pkg1::KeyGeneration_Count) {
return false;
}
/* Check the magic number. */
if (!crypto::IsSameBytes(meta.magic, pkg2::Package2Meta::Magic::String, sizeof(meta.magic))) {
return false;
}
/* Check the payload alignments. */
if ((meta.entrypoint % pkg2::PayloadAlignment) != 0) {
return false;
}
for (int i = 0; i < pkg2::PayloadCount; ++i) {
if ((meta.payload_sizes[i] % pkg2::PayloadAlignment) != 0) {
return false;
}
}
/* Check that the sizes sum to the total. */
if (size != sizeof(pkg2::Package2Header) + meta.payload_sizes[0] + meta.payload_sizes[1] + meta.payload_sizes[2]) {
return false;
}
/* Check that the payloads do not overflow. */
for (int i = 0; i < pkg2::PayloadCount; ++i) {
if (meta.payload_offsets[i] > meta.payload_offsets[i] + meta.payload_sizes[i]) {
return false;
}
}
/* Verify that no payloads overlap. */
for (int i = 0; i < pkg2::PayloadCount - 1; ++i) {
for (int j = i + 1; j < pkg2::PayloadCount; ++j) {
if (util::HasOverlap(meta.payload_offsets[i], meta.payload_sizes[i], meta.payload_offsets[j], meta.payload_sizes[j])) {
return false;
}
}
}
/* Check whether any payload contains the entrypoint. */
for (int i = 0; i < pkg2::PayloadCount; ++i) {
if (util::Contains(meta.payload_offsets[i], meta.payload_sizes[i], meta.entrypoint)) {
return true;
}
}
/* No payload contains the entrypoint, so we're not valid. */
return false;
}
bool VerifyPackage2Version(const pkg2::Package2Meta &meta) {
return meta.bootloader_version <= pkg2::CurrentBootloaderVersion && meta.package2_version >= pkg2::MinimumValidDataVersion;
}
bool VerifyPackage2Payloads(const pkg2::Package2Meta &meta, uintptr_t payload_address) {
/* Verify hashes match for all payloads. */
for (int i = 0; i < pkg2::PayloadCount; ++i) {
if (!VerifyHash(meta.payload_hashes[i], payload_address, meta.payload_sizes[i])) {
return false;
}
payload_address += meta.payload_sizes[i];
}
return true;
}
}