ro: save 0x25000 while maintaining security improvements

This commit is contained in:
Michael Scire 2020-02-24 18:17:33 -08:00
parent ba8c77fec6
commit ad1158b30a
4 changed files with 27 additions and 16 deletions

View file

@ -119,14 +119,14 @@ namespace ams::ro {
} }
size_t GetSignedAreaSize() const { size_t GetSignedAreaSize() const {
return this->size - this->GetSignedAreaOffset(); return this->size - GetSignedAreaOffset();
} }
size_t GetSignedAreaOffset() const; static constexpr size_t GetSignedAreaOffset();
}; };
static_assert(sizeof(NrrHeader) == 0x350, "NrrHeader definition!"); static_assert(sizeof(NrrHeader) == 0x350, "NrrHeader definition!");
inline size_t NrrHeader::GetSignedAreaOffset() const { constexpr size_t NrrHeader::GetSignedAreaOffset() {
return OFFSETOF(NrrHeader, program_id); return OFFSETOF(NrrHeader, program_id);
} }

View file

@ -228,19 +228,17 @@ namespace ams::ro::impl {
return ResultSuccess(); return ResultSuccess();
} }
bool ValidateNrrHashTableEntry(const void *nrr_hash, const NrrHeader *header, const u8 *hash_table, const void *desired_hash) { bool ValidateNrrHashTableEntry(const void *signed_area, size_t signed_area_size, size_t hashes_offset, size_t num_hashes, const void *nrr_hash, const u8 *hash_table, const void *desired_hash) {
crypto::Sha256Generator sha256; crypto::Sha256Generator sha256;
sha256.Initialize(); sha256.Initialize();
const size_t size = header->GetSignedAreaSize();
const size_t pre_hash_table_size = header->GetHashesOffset() - header->GetSignedAreaOffset();
const size_t num_hashes = header->GetNumHashes();
/* Hash data before the hash table. */ /* Hash data before the hash table. */
sha256.Update(header->GetSignedArea(), pre_hash_table_size); const size_t pre_hash_table_size = hashes_offset - NrrHeader::GetSignedAreaOffset();
sha256.Update(signed_area, pre_hash_table_size);
/* Hash the hash table, checking if the desired hash exists inside it. */ /* Hash the hash table, checking if the desired hash exists inside it. */
size_t remaining_size = size - pre_hash_table_size; size_t remaining_size = signed_area_size - pre_hash_table_size;
bool found_hash = false; bool found_hash = false;
for (size_t i = 0; i < num_hashes; i++) { for (size_t i = 0; i < num_hashes; i++) {
/* Get the current hash. */ /* Get the current hash. */

View file

@ -23,6 +23,6 @@ namespace ams::ro::impl {
Result MapAndValidateNrr(NrrHeader **out_header, u64 *out_mapped_code_address, void *out_hash, size_t out_hash_size, Handle process_handle, ncm::ProgramId program_id, u64 nrr_heap_address, u64 nrr_heap_size, ModuleType expected_type, bool enforce_type); Result MapAndValidateNrr(NrrHeader **out_header, u64 *out_mapped_code_address, void *out_hash, size_t out_hash_size, Handle process_handle, ncm::ProgramId program_id, u64 nrr_heap_address, u64 nrr_heap_size, ModuleType expected_type, bool enforce_type);
Result UnmapNrr(Handle process_handle, const NrrHeader *header, u64 nrr_heap_address, u64 nrr_heap_size, u64 mapped_code_address); Result UnmapNrr(Handle process_handle, const NrrHeader *header, u64 nrr_heap_address, u64 nrr_heap_size, u64 mapped_code_address);
bool ValidateNrrHashTableEntry(const void *nrr_hash, const NrrHeader *header, const u8 *hash_table, const void *desired_hash); bool ValidateNrrHashTableEntry(const void *signed_area, size_t signed_area_size, size_t hashes_offset, size_t num_hashes, const void *nrr_hash, const u8 *hash_table, const void *desired_hash);
} }

View file

@ -62,7 +62,12 @@ namespace ams::ro::impl {
u64 nrr_heap_address; u64 nrr_heap_address;
u64 nrr_heap_size; u64 nrr_heap_size;
u64 mapped_code_address; u64 mapped_code_address;
NrrHeader cached_header;
/* Verification. */
u32 cached_signed_area_size;
u32 cached_hashes_offset;
u32 cached_num_hashes;
u8 cached_signed_area[sizeof(NrrHeader) - NrrHeader::GetSignedAreaOffset()];
Sha256Hash signed_area_hash; Sha256Hash signed_area_hash;
}; };
@ -165,7 +170,6 @@ namespace ams::ro::impl {
} }
/* Get the mapped header, ensure that it has hashes. */ /* Get the mapped header, ensure that it has hashes. */
const NrrHeader *cached_nrr_header = std::addressof(this->nrr_infos[i].cached_header);
const NrrHeader *mapped_nrr_header = this->nrr_infos[i].mapped_header; const NrrHeader *mapped_nrr_header = this->nrr_infos[i].mapped_header;
const size_t mapped_num_hashes = mapped_nrr_header->GetNumHashes(); const size_t mapped_num_hashes = mapped_nrr_header->GetNumHashes();
if (mapped_num_hashes == 0) { if (mapped_num_hashes == 0) {
@ -183,8 +187,12 @@ namespace ams::ro::impl {
/* Check that the hash entry is valid, since our heuristic passed. */ /* Check that the hash entry is valid, since our heuristic passed. */
const void *nrr_hash = std::addressof(this->nrr_infos[i].signed_area_hash); const void *nrr_hash = std::addressof(this->nrr_infos[i].signed_area_hash);
const void *signed_area = this->nrr_infos[i].cached_signed_area;
const size_t signed_area_size = this->nrr_infos[i].cached_signed_area_size;
const size_t hashes_offset = this->nrr_infos[i].cached_hashes_offset;
const size_t num_hashes = this->nrr_infos[i].cached_num_hashes;
const u8 *hash_table = reinterpret_cast<const u8 *>(mapped_nro_hashes_start); const u8 *hash_table = reinterpret_cast<const u8 *>(mapped_nro_hashes_start);
if (!ValidateNrrHashTableEntry(nrr_hash, cached_nrr_header, hash_table, std::addressof(hash))) { if (!ValidateNrrHashTableEntry(signed_area, signed_area_size, hashes_offset, num_hashes, nrr_hash, hash_table, std::addressof(hash))) {
continue; continue;
} }
@ -434,7 +442,12 @@ namespace ams::ro::impl {
nrr_info->nrr_heap_address = nrr_address; nrr_info->nrr_heap_address = nrr_address;
nrr_info->nrr_heap_size = nrr_size; nrr_info->nrr_heap_size = nrr_size;
nrr_info->mapped_code_address = mapped_code_address; nrr_info->mapped_code_address = mapped_code_address;
nrr_info->cached_header = *header;
nrr_info->cached_signed_area_size = header->GetSignedAreaSize();
nrr_info->cached_hashes_offset = header->GetHashesOffset();
nrr_info->cached_num_hashes = header->GetNumHashes();
std::memcpy(nrr_info->cached_signed_area, header->GetSignedArea(), std::min(sizeof(nrr_info->cached_signed_area), header->GetHashesOffset() - header->GetSignedAreaOffset()));
std::memcpy(std::addressof(nrr_info->signed_area_hash), std::addressof(signed_area_hash), sizeof(signed_area_hash)); std::memcpy(std::addressof(nrr_info->signed_area_hash), std::addressof(signed_area_hash), sizeof(signed_area_hash));
return ResultSuccess(); return ResultSuccess();