mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2025-01-03 11:11:14 +00:00
updater: don't overwrite custom-public-key BCTs
This commit is contained in:
parent
b8c3128d16
commit
29facf6141
3 changed files with 111 additions and 13 deletions
|
@ -158,9 +158,16 @@ namespace ams::updater {
|
|||
R_TRY(boot0_accessor.Initialize());
|
||||
ON_SCOPE_EXIT { boot0_accessor.Finalize(); };
|
||||
|
||||
/* Detect the use of custom public key. */
|
||||
/* If custom public key is present, we want to validate BCT Sub but not Main */
|
||||
bool custom_public_key = false;
|
||||
R_TRY(boot0_accessor.DetectCustomPublicKey(std::addressof(custom_public_key), work_buffer, boot_image_update_type));
|
||||
|
||||
/* Compare BCT hashes. */
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctNormalMain));
|
||||
R_TRY(ValidateBctFileHash(boot0_accessor, Boot0Partition::BctNormalMain, nand_hash, work_buffer, work_buffer_size, boot_image_update_type));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctNormalMain));
|
||||
R_TRY(ValidateBctFileHash(boot0_accessor, Boot0Partition::BctNormalMain, nand_hash, work_buffer, work_buffer_size, boot_image_update_type));
|
||||
}
|
||||
|
||||
/* Compare BCT Sub hashes. */
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctNormalSub));
|
||||
|
@ -213,10 +220,16 @@ namespace ams::updater {
|
|||
R_TRY(boot1_accessor.Initialize());
|
||||
ON_SCOPE_EXIT { boot1_accessor.Finalize(); };
|
||||
|
||||
/* Detect the use of custom public key. */
|
||||
/* If custom public key is present, we want to validate BCT Sub but not Main */
|
||||
bool custom_public_key = false;
|
||||
R_TRY(boot0_accessor.DetectCustomPublicKey(std::addressof(custom_public_key), work_buffer, boot_image_update_type));
|
||||
|
||||
/* Compare BCT hashes. */
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctSafeMain));
|
||||
R_TRY(ValidateBctFileHash(boot0_accessor, Boot0Partition::BctSafeMain, nand_hash, work_buffer, work_buffer_size, boot_image_update_type));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctSafeMain));
|
||||
R_TRY(ValidateBctFileHash(boot0_accessor, Boot0Partition::BctSafeMain, nand_hash, work_buffer, work_buffer_size, boot_image_update_type));
|
||||
}
|
||||
|
||||
/* Compare BCT Sub hashes. */
|
||||
R_TRY(boot0_accessor.GetHash(nand_hash, BctSize, work_buffer, work_buffer_size, Boot0Partition::BctSafeSub));
|
||||
|
@ -260,6 +273,11 @@ namespace ams::updater {
|
|||
R_TRY(boot0_accessor.Initialize());
|
||||
ON_SCOPE_EXIT { boot0_accessor.Finalize(); };
|
||||
|
||||
/* Detect the use of custom public key. */
|
||||
/* If custom public key is present, we want to update BCT Sub but not Main */
|
||||
bool custom_public_key = false;
|
||||
R_TRY(boot0_accessor.DetectCustomPublicKey(std::addressof(custom_public_key), work_buffer, boot_image_update_type));
|
||||
|
||||
/* Write Package1 sub. */
|
||||
R_TRY(boot0_accessor.Clear(work_buffer, work_buffer_size, Boot0Partition::Package1NormalSub));
|
||||
R_TRY(boot0_accessor.Write(GetPackage1Path(boot_image_update_type), work_buffer, work_buffer_size, Boot0Partition::Package1NormalSub));
|
||||
|
@ -282,11 +300,15 @@ namespace ams::updater {
|
|||
if (HasAutoRcmPreserve(boot_image_update_type) && !exosphere::IsRcmBugPatched()) {
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctNormalSub));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalSub));
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctNormalMain));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalMain));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctNormalMain));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalMain));
|
||||
}
|
||||
} else {
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalSub));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalMain));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctNormalMain));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,6 +343,10 @@ namespace ams::updater {
|
|||
R_TRY(boot1_accessor.Initialize());
|
||||
ON_SCOPE_EXIT { boot1_accessor.Finalize(); };
|
||||
|
||||
/* Detect the use of custom public key. */
|
||||
/* If custom public key is present, we want to update BCT Sub but not Main */
|
||||
bool custom_public_key = false;
|
||||
R_TRY(boot0_accessor.DetectCustomPublicKey(std::addressof(custom_public_key), work_buffer, boot_image_update_type));
|
||||
|
||||
/* Write Package1 sub. */
|
||||
R_TRY(boot1_accessor.Clear(work_buffer, work_buffer_size, Boot1Partition::Package1SafeSub));
|
||||
|
@ -343,11 +369,15 @@ namespace ams::updater {
|
|||
if (HasAutoRcmPreserve(boot_image_update_type) && !exosphere::IsRcmBugPatched()) {
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctSafeSub));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeSub));
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctSafeMain));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeMain));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.PreserveAutoRcm(bct, work, Boot0Partition::BctSafeMain));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeMain));
|
||||
}
|
||||
} else {
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeSub));
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeMain));
|
||||
if (!custom_public_key) {
|
||||
R_TRY(boot0_accessor.Write(bct, BctSize, Boot0Partition::BctSafeMain));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,6 +18,36 @@
|
|||
|
||||
namespace ams::updater {
|
||||
|
||||
namespace {
|
||||
|
||||
/* Recognize special public key (https://gist.github.com/SciresM/16b63ac1d80494522bdba2c57995257c). */
|
||||
/* P = 19 */
|
||||
/* Q = 1696986749729493925354392349339746171297507422986462747526968361144447230710192316397327889522451749459854070558277878297255552508603806832852079596337539247651161831569525505882103311631577368514276343192042634740927726070847704397913856975832811679847928433261678072951551065705680482548543833651752439700272736498378724153330763357721354498194000536297732323628263256733931353143625854828275237159155585342783077681713929284136658773985266864804093157854331138230313706015557050002740810464618031715670281442110238274404626065924786185264268216336867948322976979393032640085259926883014490947373494538254895109731 */
|
||||
/* N = 0xFF696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696969696959 */
|
||||
/* E = 0x10001 */
|
||||
/* D = 6512128715229088976470211610075969347035078304643231077895577077900787352712063823560162578441773733649014439616165727455431015055675770987914713980812453585413988983206576233689754710500864883529402371292948326392791238474661859182717295176679567362482790015587820446999760239570255254879359445627372805817473978644067558931078225451477635089763009580492462097185005355990612929951162366081631888011031830742459571000203341001926135389508196521518687349554188686396554248868403128728646457247197407637887195043486221295751496667162366700477934591694110831002874992896076061627516220934290742867397720103040314639313 */
|
||||
|
||||
constexpr const u8 CustomPublicKey[0x100] = {
|
||||
0x59, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69,
|
||||
0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0x69, 0xFF,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
Result BisAccessor::Initialize() {
|
||||
return fs::OpenBisPartition(std::addressof(this->storage), this->partition_id);
|
||||
}
|
||||
|
@ -133,11 +163,36 @@ namespace ams::updater {
|
|||
size_t read_size;
|
||||
R_TRY(this->Read(&read_size, work_buffer, BctSize, which));
|
||||
|
||||
void *dst_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(dst_bct) + BctPubkOffset);
|
||||
void *src_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + BctPubkOffset);
|
||||
/* NOTE: AutoRcm is only viable on Erista, so hardcode erista offsets. */
|
||||
void *dst_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(dst_bct) + BctPubkOffsetErista);
|
||||
void *src_pubk = reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + BctPubkOffsetErista);
|
||||
std::memcpy(dst_pubk, src_pubk, BctPubkSize);
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result Boot0Accessor::DetectCustomPublicKey(bool *out, void *work_buffer, BootImageUpdateType boot_image_update_type) {
|
||||
std::memset(work_buffer, 0, BctSize);
|
||||
|
||||
const size_t pubk_offset = GetBctPubkOffset(boot_image_update_type);
|
||||
|
||||
size_t read_size;
|
||||
R_TRY(this->Read(&read_size, work_buffer, BctSize, Boot0Partition::BctNormalMain));
|
||||
|
||||
if (std::memcmp(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + pubk_offset), CustomPublicKey, sizeof(CustomPublicKey)) != 0) {
|
||||
*out = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
R_TRY(this->Read(&read_size, work_buffer, BctSize, Boot0Partition::BctSafeMain));
|
||||
|
||||
if (std::memcmp(reinterpret_cast<void *>(reinterpret_cast<uintptr_t>(work_buffer) + pubk_offset), CustomPublicKey, sizeof(CustomPublicKey)) != 0) {
|
||||
*out = false;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
*out = true;
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -199,7 +199,8 @@ namespace ams::updater {
|
|||
class Boot0Accessor : public PartitionAccessor<Boot0Meta> {
|
||||
public:
|
||||
static constexpr fs::BisPartitionId PartitionId = fs::BisPartitionId::BootPartition1Root;
|
||||
static constexpr size_t BctPubkOffset = 0x210;
|
||||
static constexpr size_t BctPubkOffsetErista = 0x210;
|
||||
static constexpr size_t BctPubkOffsetMariko = 0x10;
|
||||
static constexpr size_t BctPubkSize = 0x100;
|
||||
static constexpr size_t BctEksOffset = 0x450;
|
||||
static constexpr size_t BctVersionOffset = 0x2330;
|
||||
|
@ -210,10 +211,22 @@ namespace ams::updater {
|
|||
static size_t GetBootloaderVersion(void *bct);
|
||||
static size_t GetEksIndex(size_t bootloader_version);
|
||||
static void CopyEks(void *dst_bct, const void *src_eks, size_t eks_index);
|
||||
|
||||
static size_t GetBctPubkOffset(BootImageUpdateType boot_image_update_type) {
|
||||
switch (boot_image_update_type) {
|
||||
case BootImageUpdateType::Erista:
|
||||
return BctPubkOffsetErista;
|
||||
case BootImageUpdateType::Mariko:
|
||||
return BctPubkOffsetMariko;
|
||||
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||
}
|
||||
}
|
||||
public:
|
||||
Result UpdateEks(void *dst_bct, void *eks_work_buffer);
|
||||
Result UpdateEksManually(void *dst_bct, const void *src_eks);
|
||||
Result PreserveAutoRcm(void *dst_bct, void *work_buffer, Boot0Partition which);
|
||||
|
||||
Result DetectCustomPublicKey(bool *out, void *work_buffer, BootImageUpdateType boot_image_update_type);
|
||||
};
|
||||
|
||||
class Boot1Accessor : public PartitionAccessor<Boot1Meta> {
|
||||
|
|
Loading…
Reference in a new issue