fs.mitm: Protect the CAL0 backup from being read.

This commit is contained in:
Michael Scire
2018-11-15 15:27:01 -08:00
parent e0c7bfc93d
commit cff283f77d
4 changed files with 346 additions and 24 deletions

View File

@@ -23,6 +23,7 @@
#include "debug.hpp"
#include "fsmitm_utils.hpp"
#include "ini.h"
#include "sha256.h"
static FsFileSystem g_sd_filesystem = {0};
static std::vector<u64> g_mitm_flagged_tids;
@@ -37,6 +38,11 @@ static bool g_override_by_default = true;
/* Static buffer for loader.ini contents at runtime. */
static char g_config_ini_data[0x800];
/* Backup file for CAL0 partition. */
static constexpr size_t ProdinfoSize = 0x8000;
static FsFile g_cal0_file;
static u8 g_cal0_backup[ProdinfoSize];
static bool IsHexadecimal(const char *str) {
while (*str) {
if (isxdigit(*str)) {
@@ -69,8 +75,7 @@ void Utils::InitializeSdThreadFunc(void *args) {
fsFsCreateDirectory(&g_sd_filesystem, "/atmosphere/automatic_backups");
{
FsStorage cal0_storage;
FsFile cal0_file;
bool has_auto_backup = false;
char serial_number[0x40] = {0};
if (R_SUCCEEDED(setsysInitialize())) {
@@ -84,32 +89,37 @@ void Utils::InitializeSdThreadFunc(void *args) {
} else {
snprintf(prodinfo_backup_path, sizeof(prodinfo_backup_path) - 1, "/atmosphere/automatic_backups/PRODINFO.bin");
}
constexpr size_t PRODINFO_SIZE = 0x4000;
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ, &cal0_file))) {
char magic[4];
size_t read;
if (R_SUCCEEDED(fsFileRead(&cal0_file, 0, magic, sizeof(magic), &read)) && read == sizeof(magic) && memcmp(magic, "CAL0", sizeof(magic)) == 0) {
has_auto_backup = true;
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &g_cal0_file))) {
bool has_auto_backup = false;
size_t read = 0;
if (R_SUCCEEDED(fsFileRead(&g_cal0_file, 0, g_cal0_backup, sizeof(g_cal0_backup), &read)) && read == sizeof(g_cal0_backup)) {
bool is_cal0_valid = true;
is_cal0_valid &= memcmp(g_cal0_backup, "CAL0", 4) == 0;
is_cal0_valid &= memcmp(g_cal0_backup + 0x250, serial_number, 0x18) == 0;
u32 cal0_size = ((u32 *)g_cal0_backup)[2];
is_cal0_valid &= cal0_size + 0x40 <= ProdinfoSize;
if (is_cal0_valid) {
struct sha256_state sha_ctx;
u8 calc_hash[0x20];
sha256_init(&sha_ctx);
sha256_update(&sha_ctx, g_cal0_backup + 0x40, cal0_size);
sha256_finalize(&sha_ctx);
sha256_finish(&sha_ctx, calc_hash);
is_cal0_valid &= memcmp(calc_hash, g_cal0_backup + 0x20, sizeof(calc_hash)) == 0;
}
has_auto_backup = is_cal0_valid;
}
fsFileClose(&cal0_file);
}
if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) {
u8 *cal0 = new u8[PRODINFO_SIZE];
if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, cal0, PRODINFO_SIZE)) ) {
fsFsCreateFile(&g_sd_filesystem, prodinfo_backup_path, PRODINFO_SIZE, 0);
if (R_SUCCEEDED(fsFsOpenFile(&g_sd_filesystem, prodinfo_backup_path, FS_OPEN_READ | FS_OPEN_WRITE, &cal0_file))) {
fsFileSetSize(&cal0_file, PRODINFO_SIZE);
fsFileWrite(&cal0_file, 0, cal0, PRODINFO_SIZE);
fsFileFlush(&cal0_file);
fsFileClose(&cal0_file);
if (!has_auto_backup && R_SUCCEEDED(fsOpenBisStorage(&cal0_storage, BisStorageId_Prodinfo))) {
if (R_SUCCEEDED(fsStorageRead(&cal0_storage, 0, g_cal0_backup, ProdinfoSize)) ) {
fsFileSetSize(&g_cal0_file, ProdinfoSize);
fsFileWrite(&g_cal0_file, 0, g_cal0_backup, ProdinfoSize);
fsFileFlush(&g_cal0_file);
}
}
delete cal0;
fsStorageClose(&cal0_storage);
/* NOTE: g_cal0_file is intentionally not closed here. This prevents any other process from opening it. */
}
}