mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
Merge pull request #532 from wheremyfoodat/crypto
Fix AES-CTR decryption for non-NCCHKey0 games
This commit is contained in:
commit
83dabc2737
2 changed files with 18 additions and 6 deletions
|
@ -60,6 +60,8 @@ struct NCCH {
|
||||||
CodeSetInfo text, data, rodata;
|
CodeSetInfo text, data, rodata;
|
||||||
FSInfo partitionInfo;
|
FSInfo partitionInfo;
|
||||||
|
|
||||||
|
std::optional<Crypto::AESKey> primaryKey, secondaryKey;
|
||||||
|
|
||||||
// Contents of the .code file in the ExeFS
|
// Contents of the .code file in the ExeFS
|
||||||
std::vector<u8> codeFile;
|
std::vector<u8> codeFile;
|
||||||
// Contains of the cart's save data
|
// Contains of the cart's save data
|
||||||
|
|
|
@ -29,6 +29,9 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
smdh.clear();
|
smdh.clear();
|
||||||
partitionInfo = info;
|
partitionInfo = info;
|
||||||
|
|
||||||
|
primaryKey = {};
|
||||||
|
secondaryKey = {};
|
||||||
|
|
||||||
size = u64(*(u32*)&header[0x104]) * mediaUnit; // TODO: Maybe don't type pun because big endian will break
|
size = u64(*(u32*)&header[0x104]) * mediaUnit; // TODO: Maybe don't type pun because big endian will break
|
||||||
exheaderSize = *(u32*)&header[0x180];
|
exheaderSize = *(u32*)&header[0x180];
|
||||||
|
|
||||||
|
@ -78,11 +81,11 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
if (!primaryResult.first || !secondaryResult.first) {
|
if (!primaryResult.first || !secondaryResult.first) {
|
||||||
gotCryptoKeys = false;
|
gotCryptoKeys = false;
|
||||||
} else {
|
} else {
|
||||||
Crypto::AESKey primaryKey = primaryResult.second;
|
primaryKey = primaryResult.second;
|
||||||
Crypto::AESKey secondaryKey = secondaryResult.second;
|
secondaryKey = secondaryResult.second;
|
||||||
|
|
||||||
EncryptionInfo encryptionInfoTmp;
|
EncryptionInfo encryptionInfoTmp;
|
||||||
encryptionInfoTmp.normalKey = primaryKey;
|
encryptionInfoTmp.normalKey = *primaryKey;
|
||||||
encryptionInfoTmp.initialCounter.fill(0);
|
encryptionInfoTmp.initialCounter.fill(0);
|
||||||
|
|
||||||
for (std::size_t i = 1; i <= sizeof(std::uint64_t) - 1; i++) {
|
for (std::size_t i = 1; i <= sizeof(std::uint64_t) - 1; i++) {
|
||||||
|
@ -94,7 +97,7 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
encryptionInfoTmp.initialCounter[8] = 2;
|
encryptionInfoTmp.initialCounter[8] = 2;
|
||||||
exeFS.encryptionInfo = encryptionInfoTmp;
|
exeFS.encryptionInfo = encryptionInfoTmp;
|
||||||
|
|
||||||
encryptionInfoTmp.normalKey = secondaryKey;
|
encryptionInfoTmp.normalKey = *secondaryKey;
|
||||||
encryptionInfoTmp.initialCounter[8] = 3;
|
encryptionInfoTmp.initialCounter[8] = 3;
|
||||||
romFS.encryptionInfo = encryptionInfoTmp;
|
romFS.encryptionInfo = encryptionInfoTmp;
|
||||||
}
|
}
|
||||||
|
@ -201,13 +204,20 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
Helpers::panic("Second code file in a single NCCH partition. What should this do?\n");
|
Helpers::panic("Second code file in a single NCCH partition. What should this do?\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// All files in ExeFS use the same IV, though .code uses the secondary key for decryption
|
||||||
|
// whereas .icon/.banner use the primary key.
|
||||||
|
FSInfo info = exeFS;
|
||||||
|
if (encrypted && secondaryKey.has_value() && info.encryptionInfo.has_value()) {
|
||||||
|
info.encryptionInfo->normalKey = *secondaryKey;
|
||||||
|
}
|
||||||
|
|
||||||
if (compressCode) {
|
if (compressCode) {
|
||||||
std::vector<u8> tmp;
|
std::vector<u8> tmp;
|
||||||
tmp.resize(fileSize);
|
tmp.resize(fileSize);
|
||||||
|
|
||||||
// A file offset of 0 means our file is located right after the ExeFS header
|
// A file offset of 0 means our file is located right after the ExeFS header
|
||||||
// So in the ROM, files are located at (file offset + exeFS offset + exeFS header size)
|
// So in the ROM, files are located at (file offset + exeFS offset + exeFS header size)
|
||||||
readFromFile(file, exeFS, tmp.data(), fileOffset + exeFSHeaderSize, fileSize);
|
readFromFile(file, info, tmp.data(), fileOffset + exeFSHeaderSize, fileSize);
|
||||||
|
|
||||||
// Decompress .code file from the tmp vector to the "code" vector
|
// Decompress .code file from the tmp vector to the "code" vector
|
||||||
if (!CartLZ77::decompress(codeFile, tmp)) {
|
if (!CartLZ77::decompress(codeFile, tmp)) {
|
||||||
|
@ -216,7 +226,7 @@ bool NCCH::loadFromHeader(Crypto::AESEngine &aesEngine, IOFile& file, const FSIn
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
codeFile.resize(fileSize);
|
codeFile.resize(fileSize);
|
||||||
readFromFile(file, exeFS, codeFile.data(), fileOffset + exeFSHeaderSize, fileSize);
|
readFromFile(file, info, codeFile.data(), fileOffset + exeFSHeaderSize, fileSize);
|
||||||
}
|
}
|
||||||
} else if (std::strcmp(name, "icon") == 0) {
|
} else if (std::strcmp(name, "icon") == 0) {
|
||||||
// Parse icon file to extract region info and more in the future (logo, etc)
|
// Parse icon file to extract region info and more in the future (logo, etc)
|
||||||
|
|
Loading…
Add table
Reference in a new issue