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

@ -20,6 +20,7 @@ namespace ams::secmon::boot {
void MakePageTable();
void UnmapPhysicalIdentityMapping();
void UnmapDram();
void InitializeColdBoot();
@ -29,7 +30,13 @@ namespace ams::secmon::boot {
bool VerifyBootConfigSignature(pkg1::BootConfig &bc, const void *mod, size_t mod_size);
bool VerifyBootConfigEcid(const pkg1::BootConfig &bc);
void CalculatePackage2Hash(se::Sha256Hash *dst, const pkg2::Package2Meta &meta, uintptr_t package2_start);
bool VerifyPackage2Signature(pkg2::Package2Header &header, const void *mod, size_t mod_size);
void DecryptPackage2(void *dst, size_t dst_size, const void *src, size_t src_size, const void *key, size_t key_size, const void *iv, size_t iv_size, u8 key_generation);
bool VerifyPackage2Meta(const pkg2::Package2Meta &meta);
bool VerifyPackage2Version(const pkg2::Package2Meta &meta);
bool VerifyPackage2Payloads(const pkg2::Package2Meta &meta, uintptr_t payload_address);
}

View file

@ -18,6 +18,7 @@
#include "secmon_boot.hpp"
#include "secmon_boot_cache.hpp"
#include "secmon_boot_functions.hpp"
#include "secmon_boot_key_data.hpp"
namespace ams::secmon::boot {
@ -25,66 +26,9 @@ namespace ams::secmon::boot {
constexpr inline uintptr_t SYSCTR0 = MemoryRegionVirtualDeviceSysCtr0.GetAddress();
constinit const u8 BootConfigRsaPublicModulus[se::RsaSize] = {
0xB5, 0x96, 0x87, 0x31, 0x39, 0xAA, 0xBB, 0x3C, 0x28, 0xF3, 0xF0, 0x65, 0xF1, 0x50, 0x70, 0x64,
0xE6, 0x6C, 0x97, 0x50, 0xCD, 0xA6, 0xEE, 0xEA, 0xC3, 0x8F, 0xE6, 0xB5, 0x81, 0x54, 0x65, 0x33,
0x1B, 0x88, 0x4B, 0xCE, 0x9F, 0x53, 0xDF, 0xE4, 0xF6, 0xAD, 0xC3, 0x78, 0xD7, 0x3C, 0xD1, 0xDB,
0x27, 0x21, 0xA0, 0x24, 0x30, 0x2D, 0x98, 0x41, 0xA8, 0xDF, 0x50, 0x7D, 0xAB, 0xCE, 0x00, 0xD9,
0xCB, 0xAC, 0x8F, 0x37, 0xF5, 0x53, 0xE4, 0x97, 0x1F, 0x13, 0x3C, 0x19, 0xFF, 0x05, 0xA7, 0x3B,
0xF6, 0xF4, 0x01, 0xDE, 0xF0, 0xC3, 0x77, 0x7B, 0x83, 0xBA, 0xAF, 0x99, 0x30, 0x94, 0x87, 0x25,
0x4E, 0x54, 0x42, 0x3F, 0xAC, 0x27, 0xF9, 0xCC, 0x87, 0xDD, 0xAE, 0xF2, 0x54, 0xF3, 0x97, 0x49,
0xF4, 0xB0, 0xF8, 0x6D, 0xDA, 0x60, 0xE0, 0xFD, 0x57, 0xAE, 0x55, 0xA9, 0x76, 0xEA, 0x80, 0x24,
0xA0, 0x04, 0x7D, 0xBE, 0xD1, 0x81, 0xD3, 0x0C, 0x95, 0xCF, 0xB7, 0xE0, 0x2D, 0x21, 0x21, 0xFF,
0x97, 0x1E, 0xB3, 0xD7, 0x9F, 0xBB, 0x33, 0x0C, 0x23, 0xC5, 0x88, 0x4A, 0x33, 0xB9, 0xC9, 0x4E,
0x1E, 0x65, 0x51, 0x45, 0xDE, 0xF9, 0x64, 0x7C, 0xF0, 0xBF, 0x11, 0xB4, 0x93, 0x8D, 0x5D, 0xC6,
0xAB, 0x37, 0x9E, 0xE9, 0x39, 0xC1, 0xC8, 0xDB, 0xB9, 0xFE, 0x45, 0xCE, 0x7B, 0xDD, 0x72, 0xD9,
0x6F, 0x68, 0x13, 0xC0, 0x4B, 0xBA, 0x00, 0xF4, 0x1E, 0x89, 0x71, 0x91, 0x26, 0xA6, 0x46, 0x12,
0xDF, 0x29, 0x6B, 0xC2, 0x5A, 0x53, 0xAF, 0xB9, 0x5B, 0xFD, 0x13, 0x9F, 0xD1, 0x8A, 0x7C, 0xB5,
0x04, 0xFD, 0x69, 0xEA, 0x23, 0xB4, 0x6D, 0x16, 0x21, 0x98, 0x54, 0xB4, 0xDF, 0xE6, 0xAB, 0x93,
0x36, 0xB6, 0xD2, 0x43, 0xCF, 0x2B, 0x98, 0x1D, 0x45, 0xC9, 0xBB, 0x20, 0x42, 0xB1, 0x9D, 0x1D
};
constinit const u8 Package2RsaPublicModulusProduction[se::RsaSize] = {
0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59,
0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE,
0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5,
0x6C, 0x39, 0x7F, 0x41, 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74,
0x8B, 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, 0xD3, 0x48,
0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, 0xBD, 0xC3, 0x29, 0x90, 0xBE,
0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32,
0x9A, 0x42, 0x9D, 0x09, 0x8B, 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A,
0xD7, 0xE1, 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, 0x0B,
0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, 0x9E, 0xF4, 0x46, 0xA3,
0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9,
0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47,
0xFD, 0xFA, 0x4C, 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D,
0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, 0x9A, 0x3F, 0xF2,
0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF,
0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F
};
constinit const u8 Package2RsaPublicModulusDevelopment[se::RsaSize] = {
0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99,
0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7,
0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6,
0xF3, 0xBB, 0x77, 0x87, 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38,
0x06, 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, 0x51, 0x83,
0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, 0x1E, 0x68, 0x11, 0x50, 0xA0,
0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6,
0xC8, 0x26, 0xE9, 0xFE, 0x06, 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50,
0x1A, 0xA4, 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, 0xB7,
0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, 0x69, 0x79, 0x31, 0x42,
0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E,
0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8,
0x6B, 0xAE, 0xC7, 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7,
0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, 0x90, 0x0C, 0xB4,
0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46,
0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B
};
constinit const u8 Package2AesKey[] {
0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7
};
NOINLINE void DecryptPayload(uintptr_t dst, uintptr_t src, size_t size, const void *iv, size_t iv_size, u8 key_generation) {
secmon::boot::DecryptPackage2(reinterpret_cast<void *>(dst), size, reinterpret_cast<void *>(src), size, Package2AesKey, util::size(Package2AesKey), iv, iv_size, key_generation);
}
}
@ -215,4 +159,27 @@ namespace ams::secmon::boot {
}
}
void VerifyPackage2Header(const pkg2::Package2Meta &meta) {
/* Validate the metadata. */
CheckVerifyResult(VerifyPackage2Meta(meta), pkg1::ErrorInfo_InvalidPackage2Meta, "package2 meta verification failed");
/* Validate the version. */
CheckVerifyResult(VerifyPackage2Version(meta), pkg1::ErrorInfo_InvalidPackage2Version, "package2 version verification failed");
}
void DecryptAndLoadPackage2Payloads(uintptr_t dst, const pkg2::Package2Meta &meta, uintptr_t src, bool encrypted) {
/* Get the key generation for crypto. */
const u8 key_generation = meta.GetKeyGeneration();
/* Decrypt or load each payload in order. */
for (int i = 0; i < pkg2::PayloadCount; ++i) {
if (encrypted) {
DecryptPayload(dst + meta.payload_offsets[i], src, meta.payload_sizes[i], meta.payload_ivs[i], sizeof(meta.payload_ivs[i]), key_generation);
} else {
std::memcpy(reinterpret_cast<void *>(dst + meta.payload_offsets[i]), reinterpret_cast<void *>(src), meta.payload_sizes[i]);
}
src += meta.payload_sizes[i];
}
}
}

View file

@ -33,6 +33,10 @@ namespace ams::secmon::boot {
void VerifyPackage2HeaderSignature(pkg2::Package2Header &header, bool verify);
void DecryptPackage2Header(pkg2::Package2Meta *dst, const pkg2::Package2Meta &src, bool encrypted);
void VerifyPackage2Header(const pkg2::Package2Meta &meta);
void DecryptAndLoadPackage2Payloads(uintptr_t dst, const pkg2::Package2Meta &meta, uintptr_t src, bool encrypted);
void CheckVerifyResult(bool verify_result, pkg1::ErrorInfo error_info, const char *message);
}

View file

@ -0,0 +1,82 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "secmon_boot_key_data.hpp"
namespace ams::secmon::boot {
constinit const u8 BootConfigRsaPublicModulus[se::RsaSize] = {
0xB5, 0x96, 0x87, 0x31, 0x39, 0xAA, 0xBB, 0x3C, 0x28, 0xF3, 0xF0, 0x65, 0xF1, 0x50, 0x70, 0x64,
0xE6, 0x6C, 0x97, 0x50, 0xCD, 0xA6, 0xEE, 0xEA, 0xC3, 0x8F, 0xE6, 0xB5, 0x81, 0x54, 0x65, 0x33,
0x1B, 0x88, 0x4B, 0xCE, 0x9F, 0x53, 0xDF, 0xE4, 0xF6, 0xAD, 0xC3, 0x78, 0xD7, 0x3C, 0xD1, 0xDB,
0x27, 0x21, 0xA0, 0x24, 0x30, 0x2D, 0x98, 0x41, 0xA8, 0xDF, 0x50, 0x7D, 0xAB, 0xCE, 0x00, 0xD9,
0xCB, 0xAC, 0x8F, 0x37, 0xF5, 0x53, 0xE4, 0x97, 0x1F, 0x13, 0x3C, 0x19, 0xFF, 0x05, 0xA7, 0x3B,
0xF6, 0xF4, 0x01, 0xDE, 0xF0, 0xC3, 0x77, 0x7B, 0x83, 0xBA, 0xAF, 0x99, 0x30, 0x94, 0x87, 0x25,
0x4E, 0x54, 0x42, 0x3F, 0xAC, 0x27, 0xF9, 0xCC, 0x87, 0xDD, 0xAE, 0xF2, 0x54, 0xF3, 0x97, 0x49,
0xF4, 0xB0, 0xF8, 0x6D, 0xDA, 0x60, 0xE0, 0xFD, 0x57, 0xAE, 0x55, 0xA9, 0x76, 0xEA, 0x80, 0x24,
0xA0, 0x04, 0x7D, 0xBE, 0xD1, 0x81, 0xD3, 0x0C, 0x95, 0xCF, 0xB7, 0xE0, 0x2D, 0x21, 0x21, 0xFF,
0x97, 0x1E, 0xB3, 0xD7, 0x9F, 0xBB, 0x33, 0x0C, 0x23, 0xC5, 0x88, 0x4A, 0x33, 0xB9, 0xC9, 0x4E,
0x1E, 0x65, 0x51, 0x45, 0xDE, 0xF9, 0x64, 0x7C, 0xF0, 0xBF, 0x11, 0xB4, 0x93, 0x8D, 0x5D, 0xC6,
0xAB, 0x37, 0x9E, 0xE9, 0x39, 0xC1, 0xC8, 0xDB, 0xB9, 0xFE, 0x45, 0xCE, 0x7B, 0xDD, 0x72, 0xD9,
0x6F, 0x68, 0x13, 0xC0, 0x4B, 0xBA, 0x00, 0xF4, 0x1E, 0x89, 0x71, 0x91, 0x26, 0xA6, 0x46, 0x12,
0xDF, 0x29, 0x6B, 0xC2, 0x5A, 0x53, 0xAF, 0xB9, 0x5B, 0xFD, 0x13, 0x9F, 0xD1, 0x8A, 0x7C, 0xB5,
0x04, 0xFD, 0x69, 0xEA, 0x23, 0xB4, 0x6D, 0x16, 0x21, 0x98, 0x54, 0xB4, 0xDF, 0xE6, 0xAB, 0x93,
0x36, 0xB6, 0xD2, 0x43, 0xCF, 0x2B, 0x98, 0x1D, 0x45, 0xC9, 0xBB, 0x20, 0x42, 0xB1, 0x9D, 0x1D
};
constinit const u8 Package2RsaPublicModulusProduction[se::RsaSize] = {
0x8D, 0x13, 0xA7, 0x77, 0x6A, 0xE5, 0xDC, 0xC0, 0x3B, 0x25, 0xD0, 0x58, 0xE4, 0x20, 0x69, 0x59,
0x55, 0x4B, 0xAB, 0x70, 0x40, 0x08, 0x28, 0x07, 0xA8, 0xA7, 0xFD, 0x0F, 0x31, 0x2E, 0x11, 0xFE,
0x47, 0xA0, 0xF9, 0x9D, 0xDF, 0x80, 0xDB, 0x86, 0x5A, 0x27, 0x89, 0xCD, 0x97, 0x6C, 0x85, 0xC5,
0x6C, 0x39, 0x7F, 0x41, 0xF2, 0xFF, 0x24, 0x20, 0xC3, 0x95, 0xA6, 0xF7, 0x9D, 0x4A, 0x45, 0x74,
0x8B, 0x5D, 0x28, 0x8A, 0xC6, 0x99, 0x35, 0x68, 0x85, 0xA5, 0x64, 0x32, 0x80, 0x9F, 0xD3, 0x48,
0x39, 0xA2, 0x1D, 0x24, 0x67, 0x69, 0xDF, 0x75, 0xAC, 0x12, 0xB5, 0xBD, 0xC3, 0x29, 0x90, 0xBE,
0x37, 0xE4, 0xA0, 0x80, 0x9A, 0xBE, 0x36, 0xBF, 0x1F, 0x2C, 0xAB, 0x2B, 0xAD, 0xF5, 0x97, 0x32,
0x9A, 0x42, 0x9D, 0x09, 0x8B, 0x08, 0xF0, 0x63, 0x47, 0xA3, 0xE9, 0x1B, 0x36, 0xD8, 0x2D, 0x8A,
0xD7, 0xE1, 0x54, 0x11, 0x95, 0xE4, 0x45, 0x88, 0x69, 0x8A, 0x2B, 0x35, 0xCE, 0xD0, 0xA5, 0x0B,
0xD5, 0x5D, 0xAC, 0xDB, 0xAF, 0x11, 0x4D, 0xCA, 0xB8, 0x1E, 0xE7, 0x01, 0x9E, 0xF4, 0x46, 0xA3,
0x8A, 0x94, 0x6D, 0x76, 0xBD, 0x8A, 0xC8, 0x3B, 0xD2, 0x31, 0x58, 0x0C, 0x79, 0xA8, 0x26, 0xE9,
0xD1, 0x79, 0x9C, 0xCB, 0xD4, 0x2B, 0x6A, 0x4F, 0xC6, 0xCC, 0xCF, 0x90, 0xA7, 0xB9, 0x98, 0x47,
0xFD, 0xFA, 0x4C, 0x6C, 0x6F, 0x81, 0x87, 0x3B, 0xCA, 0xB8, 0x50, 0xF6, 0x3E, 0x39, 0x5D, 0x4D,
0x97, 0x3F, 0x0F, 0x35, 0x39, 0x53, 0xFB, 0xFA, 0xCD, 0xAB, 0xA8, 0x7A, 0x62, 0x9A, 0x3F, 0xF2,
0x09, 0x27, 0x96, 0x3F, 0x07, 0x9A, 0x91, 0xF7, 0x16, 0xBF, 0xC6, 0x3A, 0x82, 0x5A, 0x4B, 0xCF,
0x49, 0x50, 0x95, 0x8C, 0x55, 0x80, 0x7E, 0x39, 0xB1, 0x48, 0x05, 0x1E, 0x21, 0xC7, 0x24, 0x4F
};
constinit const u8 Package2RsaPublicModulusDevelopment[se::RsaSize] = {
0xB3, 0x65, 0x54, 0xFB, 0x0A, 0xB0, 0x1E, 0x85, 0xA7, 0xF6, 0xCF, 0x91, 0x8E, 0xBA, 0x96, 0x99,
0x0D, 0x8B, 0x91, 0x69, 0x2A, 0xEE, 0x01, 0x20, 0x4F, 0x34, 0x5C, 0x2C, 0x4F, 0x4E, 0x37, 0xC7,
0xF1, 0x0B, 0xD4, 0xCD, 0xA1, 0x7F, 0x93, 0xF1, 0x33, 0x59, 0xCE, 0xB1, 0xE9, 0xDD, 0x26, 0xE6,
0xF3, 0xBB, 0x77, 0x87, 0x46, 0x7A, 0xD6, 0x4E, 0x47, 0x4A, 0xD1, 0x41, 0xB7, 0x79, 0x4A, 0x38,
0x06, 0x6E, 0xCF, 0x61, 0x8F, 0xCD, 0xC1, 0x40, 0x0B, 0xFA, 0x26, 0xDC, 0xC0, 0x34, 0x51, 0x83,
0xD9, 0x3B, 0x11, 0x54, 0x3B, 0x96, 0x27, 0x32, 0x9A, 0x95, 0xBE, 0x1E, 0x68, 0x11, 0x50, 0xA0,
0x6B, 0x10, 0xA8, 0x83, 0x8B, 0xF5, 0xFC, 0xBC, 0x90, 0x84, 0x7A, 0x5A, 0x5C, 0x43, 0x52, 0xE6,
0xC8, 0x26, 0xE9, 0xFE, 0x06, 0xA0, 0x8B, 0x53, 0x0F, 0xAF, 0x1E, 0xC4, 0x1C, 0x0B, 0xCF, 0x50,
0x1A, 0xA4, 0xF3, 0x5C, 0xFB, 0xF0, 0x97, 0xE4, 0xDE, 0x32, 0x0A, 0x9F, 0xE3, 0x5A, 0xAA, 0xB7,
0x44, 0x7F, 0x5C, 0x33, 0x60, 0xB9, 0x0F, 0x22, 0x2D, 0x33, 0x2A, 0xE9, 0x69, 0x79, 0x31, 0x42,
0x8F, 0xE4, 0x3A, 0x13, 0x8B, 0xE7, 0x26, 0xBD, 0x08, 0x87, 0x6C, 0xA6, 0xF2, 0x73, 0xF6, 0x8E,
0xA7, 0xF2, 0xFE, 0xFB, 0x6C, 0x28, 0x66, 0x0D, 0xBD, 0xD7, 0xEB, 0x42, 0xA8, 0x78, 0xE6, 0xB8,
0x6B, 0xAE, 0xC7, 0xA9, 0xE2, 0x40, 0x6E, 0x89, 0x20, 0x82, 0x25, 0x8E, 0x3C, 0x6A, 0x60, 0xD7,
0xF3, 0x56, 0x8E, 0xEC, 0x8D, 0x51, 0x8A, 0x63, 0x3C, 0x04, 0x78, 0x23, 0x0E, 0x90, 0x0C, 0xB4,
0xE7, 0x86, 0x3B, 0x4F, 0x8E, 0x13, 0x09, 0x47, 0x32, 0x0E, 0x04, 0xB8, 0x4D, 0x5B, 0xB0, 0x46,
0x71, 0xB0, 0x5C, 0xF4, 0xAD, 0x63, 0x4F, 0xC5, 0xE2, 0xAC, 0x1E, 0xC4, 0x33, 0x96, 0x09, 0x7B
};
constinit const u8 Package2AesKey[] {
0xFB, 0x8B, 0x6A, 0x9C, 0x79, 0x00, 0xC8, 0x49, 0xEF, 0xD2, 0x4D, 0x85, 0x4D, 0x30, 0xA0, 0xC7
};
}

View file

@ -0,0 +1,26 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <exosphere.hpp>
namespace ams::secmon::boot {
extern const u8 BootConfigRsaPublicModulus[se::RsaSize];
extern const u8 Package2RsaPublicModulusDevelopment[se::RsaSize];
extern const u8 Package2RsaPublicModulusProduction[se::RsaSize];
extern const u8 Package2AesKey[se::AesBlockSize];
}

View file

@ -326,6 +326,11 @@ namespace ams::secmon::boot {
InvalidateL1Entries(l1, MemoryRegionPhysical.GetAddress(), MemoryRegionPhysical.GetSize());
}
constexpr void UnmapDramImpl(u64 *l1, u64 *l2, u64 *l3) {
/* Unmap the L1 entry corresponding to to the Dram entries. */
InvalidateL1Entries(l1, MemoryRegionDram.GetAddress(), MemoryRegionDram.GetSize());
}
}
void InitializeColdBoot() {
@ -366,4 +371,16 @@ namespace ams::secmon::boot {
secmon::boot::EnsureMappingConsistency();
}
void UnmapDram() {
/* Get the tables. */
u64 * const l1 = MemoryRegionPhysicalTzramL1PageTable.GetPointer<u64>();
u64 * const l2_l3 = MemoryRegionPhysicalTzramL2L3PageTable.GetPointer<u64>();
/* Unmap. */
UnmapDramImpl(l1, l2_l3, l2_l3);
/* Ensure the mappings are consistent. */
secmon::boot::EnsureMappingConsistency();
}
}

View file

@ -17,11 +17,19 @@
#include "secmon_boot.hpp"
#include "secmon_boot_functions.hpp"
#include "../smc/secmon_random_cache.hpp"
#include "../secmon_setup.hpp"
#include "../secmon_cache.hpp"
#include "../secmon_cpu_context.hpp"
#include "../secmon_misc.hpp"
#include "../secmon_setup.hpp"
namespace ams::secmon {
namespace {
constexpr inline const uintptr_t Package2LoadAddress = MemoryRegionDramPackage2Payloads.GetAddress();
}
void Main() {
/* Set library register addresses. */
/* actmon::SetRegisterAddress(MemoryRegionVirtualDeviceActivityMonitor.GetAddress()); */
@ -122,7 +130,7 @@ namespace ams::secmon {
/* Parse and decrypt the package2 header. */
pkg2::Package2Meta pkg2_meta;
const uintptr_t pkg2_segments_start = MemoryRegionDramPackage2.GetAddress() + sizeof(pkg2::Package2Header);
const uintptr_t pkg2_payloads_start = MemoryRegionDramPackage2.GetAddress() + sizeof(pkg2::Package2Header);
{
/* Read the encrypred header. */
pkg2::Package2Header encrypted_header;
@ -143,8 +151,38 @@ namespace ams::secmon {
secmon::boot::DecryptPackage2Header(std::addressof(pkg2_meta), encrypted_header.meta, !bc.signed_data.IsPackage2EncryptionDisabled());
}
/* TODO */
AMS_UNUSED(pkg2_segments_start);
/* Verify the package2 header. */
secmon::boot::VerifyPackage2Header(pkg2_meta);
/* Save the package2 hash if in recovery boot. */
if (secmon::IsRecoveryBoot()) {
se::Sha256Hash hash;
secmon::boot::CalculatePackage2Hash(std::addressof(hash), pkg2_meta, MemoryRegionDramPackage2.GetAddress());
secmon::SetPackage2Hash(hash);
}
/* Verify the package2 payloads. */
secmon::boot::CheckVerifyResult(secmon::boot::VerifyPackage2Payloads(pkg2_meta, pkg2_payloads_start), pkg1::ErrorInfo_InvalidPackage2Payload, "package2 payload verification failed");
/* Decrypt/Move the package2 payloads to the right places. */
secmon::boot::DecryptAndLoadPackage2Payloads(Package2LoadAddress, pkg2_meta, pkg2_payloads_start, !bc.signed_data.IsPackage2EncryptionDisabled());
/* Ensure that the CPU sees correct package2 data. */
secmon::FlushEntireDataCache();
secmon::EnsureInstructionConsistency();
/* Set the core's entrypoint and argument. */
secmon::SetEntryContext(0, Package2LoadAddress + pkg2_meta.entrypoint, 0);
/* Unmap DRAM. */
secmon::boot::UnmapDram();
/* Wait for NX bootloader to be done. */
secmon::boot::WaitForNxBootloader(secmon_params, pkg1::BootloaderState_Done);
/* Perform final initialization. */
secmon::SetupSocProtections();
secmon::SetupCpuSErrorDebug();
}
}
}

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;
}
}

View file

@ -0,0 +1,23 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <exosphere.hpp>
#include "secmon_cache.hpp"
namespace ams::secmon {
#include "secmon_cache_impl.inc"
}

View file

@ -13,10 +13,11 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <exosphere.hpp>
namespace ams::secmon::boot {
namespace ams::secmon {
/* TODO */
#include "secmon_cache.inc"
}

View file

@ -129,4 +129,4 @@ void EnsureInstructionConsistency() {
::ams::hw::DataSynchronizationBarrierInnerShareable();
::ams::hw::InstructionSynchronizationBarrier();
}
}

View file

@ -20,7 +20,8 @@ namespace ams::secmon {
namespace {
pkg1::BctParameters g_bct_params;
constinit pkg1::BctParameters g_bct_params = {};
constinit se::Sha256Hash g_package2_hash = {};
}
@ -43,4 +44,12 @@ namespace ams::secmon {
return dbg_auth.Get<hw::DbgAuthStatusEl1::Nsid>() == 3;
}
}
void GetPackage2Hash(se::Sha256Hash *out) {
*out = g_package2_hash;
}
void SetPackage2Hash(const se::Sha256Hash &hash) {
g_package2_hash = hash;
}
}

View file

@ -26,4 +26,7 @@ namespace ams::secmon {
bool IsJtagEnabled();
void GetPackage2Hash(se::Sha256Hash *out);
void SetPackage2Hash(const se::Sha256Hash &hash);
}

View file

@ -837,7 +837,7 @@ namespace ams::secmon {
}
void SetupSocProtections() {
/* TODO */
}
void SetupPmcAndMcSecure() {
@ -877,7 +877,21 @@ namespace ams::secmon {
}
void SetupCpuSErrorDebug() {
/* Get whether we should enable SError debug. */
const auto &bc_data = secmon::GetBootConfig().data;
const bool enabled = bc_data.IsDevelopmentFunctionEnabled() && bc_data.IsSErrorDebugEnabled();
/* Get and set scr_el3. */
{
util::BitPack32 scr;
HW_CPU_GET_SCR_EL3(scr);
scr.Set<hw::ScrEl3::Ea>(enabled ? 0 : 1);
HW_CPU_SET_SCR_EL3(scr);
}
/* Prevent reordering instructions around this call. */
hw::InstructionSynchronizationBarrier();
}
}

View file

@ -19,9 +19,9 @@
namespace ams::pkg2 {
constexpr inline size_t Package2SizeMax = 8_MB - 16_KB;
constexpr inline size_t SegmentAlignment = 4;
constexpr inline size_t PayloadAlignment = 4;
constexpr inline int SegmentCount = 3;
constexpr inline int PayloadCount = 3;
constexpr inline int MinimumValidDataVersion = 0; /* We allow older package2 to load; this value is currently 0x10 in Nintendo's code. */
constexpr inline int CurrentBootloaderVersion = 0xD;
@ -32,7 +32,7 @@ namespace ams::pkg2 {
u32 package2_size;
u8 key_generation;
u8 header_iv_remainder[11];
u8 segment_iv[SegmentCount][0x10];
u8 payload_ivs[PayloadCount][0x10];
u8 padding_40[0x10];
u8 magic[4];
u32 entrypoint;
@ -40,11 +40,11 @@ namespace ams::pkg2 {
u8 package2_version;
u8 bootloader_version;
u8 padding_5E[2];
u32 segment_sizes[SegmentCount];
u32 payload_sizes[PayloadCount];
u8 padding_6C[4];
u32 segment_offsets[SegmentCount];
u32 payload_offsets[PayloadCount];
u8 padding_7C[4];
u8 segment_hashes[SegmentCount][crypto::Sha256Generator::HashSize];
u8 payload_hashes[PayloadCount][crypto::Sha256Generator::HashSize];
u8 padding_E0[0x20];
private:
@ -53,7 +53,7 @@ namespace ams::pkg2 {
}
public:
ALWAYS_INLINE u8 GetKeyGeneration() const {
return std::min<u8>(0, (this->key_generation ^ this->header_iv_remainder[1] ^ this->header_iv_remainder[2]) - 1);
return static_cast<u8>(std::max<s32>(0, static_cast<s32>(this->key_generation ^ this->header_iv_remainder[1] ^ this->header_iv_remainder[2]) - 1));
}
ALWAYS_INLINE u32 GetSize() const {

View file

@ -80,6 +80,9 @@ namespace ams::secmon {
constexpr inline const MemoryRegion MemoryRegionDramDefaultKernelCarveout = MemoryRegion(UINT64_C(0x80060000), UINT64_C(0x1FFE0000));
static_assert(MemoryRegionDram.Contains(MemoryRegionDramDefaultKernelCarveout));
constexpr inline const MemoryRegion MemoryRegionDramPackage2Payloads = MemoryRegion(MemoryRegionDram.GetAddress(), 8_MB);
static_assert(MemoryRegionDram.Contains(MemoryRegionDramPackage2Payloads));
constexpr inline const MemoryRegion MemoryRegionDramPackage2 = MemoryRegion(UINT64_C(0xA9800000), UINT64_C(0x07FC0000));
static_assert(MemoryRegionDram.Contains(MemoryRegionDramPackage2));

View file

@ -36,5 +36,6 @@
#include <vapours/util/util_tinymt.hpp>
#include <vapours/util/util_uuid.hpp>
#include <vapours/util/util_bounded_map.hpp>
#include <vapours/util/util_overlap.hpp>
#include <vapours/util/util_string_util.hpp>
#include <vapours/util/util_variadic.hpp>

View file

@ -0,0 +1,35 @@
/*
* Copyright (c) 2018-2020 Atmosphère-NX
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include <vapours/common.hpp>
#include <vapours/assert.hpp>
namespace ams::util {
constexpr inline bool HasOverlap(uintptr_t addr0, size_t size0, uintptr_t addr1, size_t size1) {
if (addr0 <= addr1) {
return addr1 < addr0 + size0;
} else {
return addr0 < addr1 + size1;
}
}
constexpr inline bool Contains(uintptr_t addr, size_t size, uintptr_t ptr) {
return (addr <= ptr) && (ptr < addr + size);
}
}