2017-05-31 16:16:31 +02:00

74 lines
2.5 KiB
C

#include "ncsd.h"
#include "ncch.h"
u32 ValidateNcsdHeader(NcsdHeader* header) {
u8 zeroes[16] = { 0 };
if ((memcmp(header->magic, "NCSD", 4) != 0) || // check magic number
(memcmp(header->partitions_fs_type, zeroes, 8) != 0) || !header->mediaId) // prevent detection of NAND images
return 1;
u32 data_units = 0;
for (u32 i = 0; i < 8; i++) {
NcchPartition* partition = header->partitions + i;
if ((i == 0) && !partition->size) return 1; // first content must be there
else if (!partition->size) continue;
if (partition->offset < data_units)
return 1; // overlapping partitions, failed
data_units = partition->offset + partition->size;
}
if (data_units > header->size)
return 1;
return 0;
}
u64 GetNcsdTrimmedSize(NcsdHeader* header) {
u32 data_units = 0;
for (u32 i = 0; i < 8; i++) {
NcchPartition* partition = header->partitions + i;
u32 partition_end = partition->offset + partition->size;
if (!partition->size) continue;
data_units = (partition_end > data_units) ? partition_end : data_units;
}
return data_units * NCSD_MEDIA_UNIT;
}
// on the fly decryptor for NCSD
u32 CryptNcsdSequential(u8* data, u32 offset_data, u32 size_data, u16 crypto) {
// warning: this will only work for sequential processing
static NcsdHeader ncsd;
// fetch ncsd header from data
if ((offset_data == 0) && (size_data >= sizeof(NcsdHeader)))
memcpy(&ncsd, data, sizeof(NcsdHeader));
for (u32 i = 0; i < 8; i++) {
NcchPartition* partition = ncsd.partitions + i;
u32 offset_p = partition->offset * NCSD_MEDIA_UNIT;
u32 size_p = partition->size * NCSD_MEDIA_UNIT;
// check if partition in data
if ((offset_p >= offset_data + size_data) ||
(offset_data >= offset_p + size_p) ||
!size_p) {
continue; // section not in data
}
// determine data / offset / size
u8* data_i = data;
u32 offset_i = 0;
u32 size_i = size_p;
if (offset_p < offset_data)
offset_i = offset_data - offset_p;
else data_i = data + (offset_p - offset_data);
size_i = size_p - offset_i;
if (size_i > size_data - (data_i - data))
size_i = size_data - (data_i - data);
// decrypt ncch segment
if (CryptNcchSequential(data_i, offset_i, size_i, crypto) != 0)
return 1;
}
return 0;
}