mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-11-24 18:44:55 +00:00
Enable optional signature verification for NCCH & NCSD
This commit is contained in:
parent
748c46ed5a
commit
ceabad8b3f
@ -2,6 +2,8 @@
|
|||||||
#include "keydb.h"
|
#include "keydb.h"
|
||||||
#include "aes.h"
|
#include "aes.h"
|
||||||
#include "sha.h"
|
#include "sha.h"
|
||||||
|
#include "rsa.h"
|
||||||
|
#include "itcm.h"
|
||||||
|
|
||||||
#define EXEFS_KEYID(name) (((strncmp(name, "banner", 8) == 0) || (strncmp(name, "icon", 8) == 0)) ? 0 : 1)
|
#define EXEFS_KEYID(name) (((strncmp(name, "banner", 8) == 0) || (strncmp(name, "icon", 8) == 0)) ? 0 : 1)
|
||||||
|
|
||||||
@ -28,6 +30,26 @@ u32 ValidateNcchHeader(NcchHeader* header) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ValidateNcchSignature(NcchHeader* header, NcchExtHeader* exthdr)
|
||||||
|
{
|
||||||
|
u8 exp[4] = { 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
u8* pubkey = ARM9_ITCM->rsaModulusCartNCSD;
|
||||||
|
|
||||||
|
if (exthdr) {
|
||||||
|
// check extheader signature
|
||||||
|
if (!RSA_setKey2048(3, (const u32*)(const void*)ARM9_ITCM->rsaModulusAccessDesc, getle32(exp)) ||
|
||||||
|
!RSA_verify2048((const u32*)(const void*)&exthdr->signature[0], (const u32*)(const void*)&exthdr->public_key[0], 0x300))
|
||||||
|
return 1;
|
||||||
|
pubkey = exthdr->public_key;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check NCCH header signature
|
||||||
|
if (!RSA_setKey2048(3, (const u32*)(const void*)&pubkey[0], getle32(exp)) ||
|
||||||
|
!RSA_verify2048((const u32*)(const void*)&header->signature[0], (const u32*)(const void*)&((u8*)header)[0x100], 0x100))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u32 GetNcchCtr(u8* ctr, NcchHeader* ncch, u8 section) {
|
u32 GetNcchCtr(u8* ctr, NcchHeader* ncch, u8 section) {
|
||||||
memset(ctr, 0x00, 16);
|
memset(ctr, 0x00, 16);
|
||||||
if (ncch->version == 1) {
|
if (ncch->version == 1) {
|
||||||
|
|||||||
@ -84,6 +84,7 @@ typedef struct {
|
|||||||
} __attribute__((packed, aligned(16))) NcchHeader;
|
} __attribute__((packed, aligned(16))) NcchHeader;
|
||||||
|
|
||||||
u32 ValidateNcchHeader(NcchHeader* header);
|
u32 ValidateNcchHeader(NcchHeader* header);
|
||||||
|
u32 ValidateNcchSignature(NcchHeader* header, NcchExtHeader* exthdr);
|
||||||
u32 SetNcchKey(NcchHeader* ncch, u16 crypto, u32 keyid);
|
u32 SetNcchKey(NcchHeader* ncch, u16 crypto, u32 keyid);
|
||||||
u32 SetupNcchCrypto(NcchHeader* ncch, u16 crypt_to);
|
u32 SetupNcchCrypto(NcchHeader* ncch, u16 crypt_to);
|
||||||
u32 CryptNcch(void* data, u32 offset, u32 size, NcchHeader* ncch, ExeFsHeader* exefs, u16 crypto);
|
u32 CryptNcch(void* data, u32 offset, u32 size, NcchHeader* ncch, ExeFsHeader* exefs, u16 crypto);
|
||||||
|
|||||||
@ -1,5 +1,7 @@
|
|||||||
#include "ncsd.h"
|
#include "ncsd.h"
|
||||||
#include "ncch.h"
|
#include "ncch.h"
|
||||||
|
#include "rsa.h"
|
||||||
|
#include "itcm.h"
|
||||||
|
|
||||||
u32 ValidateNcsdHeader(NcsdHeader* header) {
|
u32 ValidateNcsdHeader(NcsdHeader* header) {
|
||||||
static const u8 zeroes[16] = { 0 };
|
static const u8 zeroes[16] = { 0 };
|
||||||
@ -22,6 +24,15 @@ u32 ValidateNcsdHeader(NcsdHeader* header) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 ValidateNcsdSignature(NcsdHeader* header) {
|
||||||
|
u8 exp[4] = { 0x00, 0x01, 0x00, 0x01 };
|
||||||
|
// this will fail for non-cart NCSDs anyways, so we don't need to check
|
||||||
|
if (!RSA_setKey2048(3, (const u32*)(const void*)&ARM9_ITCM->rsaModulusCartNCSD[0], getle32(exp)) ||
|
||||||
|
!RSA_verify2048((const u32*)(const void*)&header->signature[0], (const u32*)(const void*)&((u8*)header)[0x100], 0x100))
|
||||||
|
return 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u64 GetNcsdTrimmedSize(NcsdHeader* header) {
|
u64 GetNcsdTrimmedSize(NcsdHeader* header) {
|
||||||
u32 data_units = 0;
|
u32 data_units = 0;
|
||||||
for (u32 i = 0; i < 8; i++) {
|
for (u32 i = 0; i < 8; i++) {
|
||||||
|
|||||||
@ -37,5 +37,6 @@ typedef struct {
|
|||||||
} PACKED_STRUCT NcsdHeader;
|
} PACKED_STRUCT NcsdHeader;
|
||||||
|
|
||||||
u32 ValidateNcsdHeader(NcsdHeader* header);
|
u32 ValidateNcsdHeader(NcsdHeader* header);
|
||||||
|
u32 ValidateNcsdSignature(NcsdHeader* header);
|
||||||
u64 GetNcsdTrimmedSize(NcsdHeader* header);
|
u64 GetNcsdTrimmedSize(NcsdHeader* header);
|
||||||
u32 CryptNcsdSequential(void* data, u32 offset_data, u32 size_data, u16 crypto);
|
u32 CryptNcsdSequential(void* data, u32 offset_data, u32 size_data, u16 crypto);
|
||||||
|
|||||||
@ -1744,7 +1744,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
|||||||
ShowPrompt(false, STR_PATH_TYPE_BUILD_FAILED, pathstr, type);
|
ShowPrompt(false, STR_PATH_TYPE_BUILD_FAILED, pathstr, type);
|
||||||
if ((filetype & (GAME_NCCH|GAME_NCSD)) &&
|
if ((filetype & (GAME_NCCH|GAME_NCSD)) &&
|
||||||
ShowPrompt(true, "%s\n%s", pathstr, STR_FILE_FAILED_CONVERSION_VERIFY_NOW)) {
|
ShowPrompt(true, "%s\n%s", pathstr, STR_FILE_FAILED_CONVERSION_VERIFY_NOW)) {
|
||||||
ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path, false) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1797,7 +1797,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
|||||||
ShowPrompt(false, "%s\n%s", pathstr, (ret == 0) ? STR_INSTALL_SUCCESS : STR_INSTALL_FAILED);
|
ShowPrompt(false, "%s\n%s", pathstr, (ret == 0) ? STR_INSTALL_SUCCESS : STR_INSTALL_FAILED);
|
||||||
if ((ret != 0) && (filetype & (GAME_NCCH|GAME_NCSD)) &&
|
if ((ret != 0) && (filetype & (GAME_NCCH|GAME_NCSD)) &&
|
||||||
ShowPrompt(true, "%s\n%s", pathstr, STR_FILE_FAILED_INSTALL_VERIFY_NOW)) {
|
ShowPrompt(true, "%s\n%s", pathstr, STR_FILE_FAILED_INSTALL_VERIFY_NOW)) {
|
||||||
ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path, false) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
@ -1841,10 +1841,24 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (user_select == verify) { // -> verify game / nand file
|
else if (user_select == verify) { // -> verify game / nand file
|
||||||
if ((n_marked > 1) && ShowPrompt(true, STR_TRY_TO_VERIFY_N_SELECTED_FILES, n_marked)) {
|
bool sig_check = false;
|
||||||
|
|
||||||
|
// check signatures?
|
||||||
|
if (filetype & (GAME_NCSD|GAME_NCCH)) {
|
||||||
|
optionstr[0] = STR_IGNORE_SIGNATURES;
|
||||||
|
optionstr[1] = STR_VERIFY_SIGNATURES;
|
||||||
|
user_select = ShowSelectPrompt(2, optionstr, "%s", STR_USE_SIGNATURE_VERIFICATION);
|
||||||
|
if (!user_select) return 1;
|
||||||
|
sig_check = (user_select == 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// file verification
|
||||||
|
if (n_marked > 1) {
|
||||||
u32 n_success = 0;
|
u32 n_success = 0;
|
||||||
u32 n_other = 0;
|
u32 n_other = 0;
|
||||||
u32 n_processed = 0;
|
u32 n_processed = 0;
|
||||||
|
if (!ShowPrompt(true, STR_TRY_TO_VERIFY_N_SELECTED_FILES, n_marked)) // confirmation
|
||||||
|
return 1;
|
||||||
for (u32 i = 0; i < current_dir->n_entries; i++) {
|
for (u32 i = 0; i < current_dir->n_entries; i++) {
|
||||||
const char* path = current_dir->entry[i].path;
|
const char* path = current_dir->entry[i].path;
|
||||||
if (!current_dir->entry[i].marked)
|
if (!current_dir->entry[i].marked)
|
||||||
@ -1857,7 +1871,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
|||||||
}
|
}
|
||||||
DrawDirContents(current_dir, (*cursor = i), scroll);
|
DrawDirContents(current_dir, (*cursor = i), scroll);
|
||||||
if ((filetype & IMG_NAND) && (ValidateNandDump(path) == 0)) n_success++;
|
if ((filetype & IMG_NAND) && (ValidateNandDump(path) == 0)) n_success++;
|
||||||
else if (VerifyGameFile(path) == 0) n_success++;
|
else if (VerifyGameFile(path, sig_check) == 0) n_success++;
|
||||||
else { // on failure: show error, continue
|
else { // on failure: show error, continue
|
||||||
char lpathstr[UTF_BUFFER_BYTESIZE(32)];
|
char lpathstr[UTF_BUFFER_BYTESIZE(32)];
|
||||||
TruncateString(lpathstr, path, 32, 8);
|
TruncateString(lpathstr, path, 32, 8);
|
||||||
@ -1876,7 +1890,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, PaneData** pan
|
|||||||
ShowString("%s\n%s", pathstr, STR_VERIFYING_FILE_PLEASE_WAIT);
|
ShowString("%s\n%s", pathstr, STR_VERIFYING_FILE_PLEASE_WAIT);
|
||||||
if (filetype & IMG_NAND) {
|
if (filetype & IMG_NAND) {
|
||||||
ShowPrompt(false, "%s\n%s", pathstr, (ValidateNandDump(file_path) == 0) ? STR_NAND_VALIDATION_SUCCESS : STR_NAND_VALIDATION_FAILED);
|
ShowPrompt(false, "%s\n%s", pathstr, (ValidateNandDump(file_path) == 0) ? STR_NAND_VALIDATION_SUCCESS : STR_NAND_VALIDATION_FAILED);
|
||||||
} else ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
} else ShowPrompt(false, "%s\n%s", pathstr, (VerifyGameFile(file_path, sig_check) == 0) ? STR_VERIFICATION_SUCCESS : STR_VERIFICATION_FAILED);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -624,7 +624,7 @@ static int internalfs_verify(lua_State* L) {
|
|||||||
|
|
||||||
u64 filetype = IdentifyFileType(path);
|
u64 filetype = IdentifyFileType(path);
|
||||||
if (filetype & IMG_NAND) res = (ValidateNandDump(path) == 0);
|
if (filetype & IMG_NAND) res = (ValidateNandDump(path) == 0);
|
||||||
else res = (VerifyGameFile(path) == 0);
|
else res = (VerifyGameFile(path, false) == 0);
|
||||||
|
|
||||||
lua_pushboolean(L, res);
|
lua_pushboolean(L, res);
|
||||||
return 1;
|
return 1;
|
||||||
|
|||||||
@ -162,6 +162,8 @@ typedef struct _Arm9Itcm {
|
|||||||
|
|
||||||
// Sanity checking.
|
// Sanity checking.
|
||||||
STATIC_ASSERT(offsetof(Arm9Itcm, otp) == 0x3800);
|
STATIC_ASSERT(offsetof(Arm9Itcm, otp) == 0x3800);
|
||||||
|
STATIC_ASSERT(offsetof(Arm9Itcm, rsaModulusCartNCSD) == 0x4900);
|
||||||
|
STATIC_ASSERT(offsetof(Arm9Itcm, rsaModulusAccessDesc) == 0x4A00);
|
||||||
STATIC_ASSERT(offsetof(Arm9Itcm, twlNANDKeyY) == 0x53C8);
|
STATIC_ASSERT(offsetof(Arm9Itcm, twlNANDKeyY) == 0x53C8);
|
||||||
STATIC_ASSERT(offsetof(Arm9Itcm, twlBlowfishCartKey) == 0x53E0);
|
STATIC_ASSERT(offsetof(Arm9Itcm, twlBlowfishCartKey) == 0x53E0);
|
||||||
STATIC_ASSERT(offsetof(Arm9Itcm, ntrBlowfishCartKey) == 0x6428);
|
STATIC_ASSERT(offsetof(Arm9Itcm, ntrBlowfishCartKey) == 0x6428);
|
||||||
|
|||||||
@ -519,7 +519,7 @@ u32 VerifyTmdContent(const char* path, u64 offset, TmdContentChunk* chunk, const
|
|||||||
return memcmp(hash, expected, 32);
|
return memcmp(hash, expected, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VerifyNcchFile(const char* path, u32 offset, u32 size) {
|
u32 VerifyNcchFile(const char* path, u32 offset, u32 size, bool sig_check) {
|
||||||
static bool cryptofix_always = false;
|
static bool cryptofix_always = false;
|
||||||
bool cryptofix = false;
|
bool cryptofix = false;
|
||||||
NcchHeader ncch;
|
NcchHeader ncch;
|
||||||
@ -583,6 +583,13 @@ u32 VerifyNcchFile(const char* path, u32 offset, u32 size) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// signature verification
|
||||||
|
if (sig_check && ValidateNcchSignature(&ncch, ncch.size_exthdr ? &exthdr : NULL) != 0) {
|
||||||
|
if (!offset) ShowPrompt(false, "%s\n%s", pathstr, STR_ERROR_SIGNATURE_CHECK_FAILED);
|
||||||
|
fvx_close(&file);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// check / setup crypto
|
// check / setup crypto
|
||||||
if (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0) {
|
if (SetupNcchCrypto(&ncch, NCCH_NOCRYPTO) != 0) {
|
||||||
if (!offset) ShowPrompt(false, "%s\n%s", pathstr, STR_ERROR_CRYPTO_NOT_SET_UP);
|
if (!offset) ShowPrompt(false, "%s\n%s", pathstr, STR_ERROR_CRYPTO_NOT_SET_UP);
|
||||||
@ -723,7 +730,7 @@ u32 VerifyNcchFile(const char* path, u32 offset, u32 size) {
|
|||||||
return ver_exthdr|ver_exefs|ver_romfs;
|
return ver_exthdr|ver_exefs|ver_romfs;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VerifyNcsdFile(const char* path) {
|
u32 VerifyNcsdFile(const char* path, bool sig_check) {
|
||||||
NcsdHeader ncsd;
|
NcsdHeader ncsd;
|
||||||
|
|
||||||
// path string
|
// path string
|
||||||
@ -736,13 +743,19 @@ u32 VerifyNcsdFile(const char* path) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// signature verification
|
||||||
|
if (sig_check && ValidateNcsdSignature(&ncsd) != 0) {
|
||||||
|
ShowPrompt(false, "%s\n%s", pathstr, STR_ERROR_SIGNATURE_CHECK_FAILED);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// validate NCSD contents
|
// validate NCSD contents
|
||||||
for (u32 i = 0; i < 8; i++) {
|
for (u32 i = 0; i < 8; i++) {
|
||||||
NcchPartition* partition = ncsd.partitions + i;
|
NcchPartition* partition = ncsd.partitions + i;
|
||||||
u32 offset = partition->offset * NCSD_MEDIA_UNIT;
|
u32 offset = partition->offset * NCSD_MEDIA_UNIT;
|
||||||
u32 size = partition->size * NCSD_MEDIA_UNIT;
|
u32 size = partition->size * NCSD_MEDIA_UNIT;
|
||||||
if (!size) continue;
|
if (!size) continue;
|
||||||
if (VerifyNcchFile(path, offset, size) != 0) {
|
if (VerifyNcchFile(path, offset, size, sig_check) != 0) {
|
||||||
ShowPrompt(false, STR_PATH_CONTENT_N_SIZE_AT_OFFSET_VERIFICATION_FAILED,
|
ShowPrompt(false, STR_PATH_CONTENT_N_SIZE_AT_OFFSET_VERIFICATION_FAILED,
|
||||||
pathstr, i, size, offset);
|
pathstr, i, size, offset);
|
||||||
return 1;
|
return 1;
|
||||||
@ -1032,14 +1045,14 @@ u32 VerifyTicketFile(const char* path) {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 VerifyGameFile(const char* path) {
|
u32 VerifyGameFile(const char* path, bool sig_check) {
|
||||||
u64 filetype = IdentifyFileType(path);
|
u64 filetype = IdentifyFileType(path);
|
||||||
if (filetype & GAME_CIA)
|
if (filetype & GAME_CIA)
|
||||||
return VerifyCiaFile(path);
|
return VerifyCiaFile(path);
|
||||||
else if (filetype & GAME_NCSD)
|
else if (filetype & GAME_NCSD)
|
||||||
return VerifyNcsdFile(path);
|
return VerifyNcsdFile(path, sig_check);
|
||||||
else if (filetype & GAME_NCCH)
|
else if (filetype & GAME_NCCH)
|
||||||
return VerifyNcchFile(path, 0, 0);
|
return VerifyNcchFile(path, 0, 0, sig_check);
|
||||||
else if (filetype & (GAME_TMD|GAME_CDNTMD|GAME_TWLTMD))
|
else if (filetype & (GAME_TMD|GAME_CDNTMD|GAME_TWLTMD))
|
||||||
return VerifyTmdFile(path, filetype & (GAME_CDNTMD|GAME_TWLTMD));
|
return VerifyTmdFile(path, filetype & (GAME_CDNTMD|GAME_TWLTMD));
|
||||||
else if (filetype & GAME_TIE)
|
else if (filetype & GAME_TIE)
|
||||||
@ -3617,7 +3630,7 @@ u32 ShowGameCheckerInfo(const char* path) {
|
|||||||
(state_tmd == 0) ? STR_STATE_INVALID : (state_tmd == 2) ? STR_STATE_LEGIT : STR_STATE_ILLEGIT,
|
(state_tmd == 0) ? STR_STATE_INVALID : (state_tmd == 2) ? STR_STATE_LEGIT : STR_STATE_ILLEGIT,
|
||||||
(state_verify < 0) ? STR_STATE_PENDING_PROCEED_WITH_VERIFICATION : (state_verify == 0) ? STR_STATE_PASSED : STR_STATE_FAILED) ||
|
(state_verify < 0) ? STR_STATE_PENDING_PROCEED_WITH_VERIFICATION : (state_verify == 0) ? STR_STATE_PASSED : STR_STATE_FAILED) ||
|
||||||
(state_verify >= 0)) break;
|
(state_verify >= 0)) break;
|
||||||
state_verify = VerifyGameFile(path);
|
state_verify = VerifyGameFile(path, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tmd) free(tmd);
|
if (tmd) free(tmd);
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
u32 VerifyGameFile(const char* path);
|
u32 VerifyGameFile(const char* path, bool sig_check);
|
||||||
u32 CheckEncryptedGameFile(const char* path);
|
u32 CheckEncryptedGameFile(const char* path);
|
||||||
u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
|
u32 CryptGameFile(const char* path, bool inplace, bool encrypt);
|
||||||
u32 BuildCiaFromGameFile(const char* path, bool force_legit);
|
u32 BuildCiaFromGameFile(const char* path, bool force_legit);
|
||||||
|
|||||||
@ -1346,7 +1346,7 @@ bool run_cmd(cmd_id id, u32 flags, char** argv, char* err_str) {
|
|||||||
else if (id == CMD_ID_VERIFY) {
|
else if (id == CMD_ID_VERIFY) {
|
||||||
u64 filetype = IdentifyFileType(argv[0]);
|
u64 filetype = IdentifyFileType(argv[0]);
|
||||||
if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0);
|
if (filetype & IMG_NAND) ret = (ValidateNandDump(argv[0]) == 0);
|
||||||
else ret = (VerifyGameFile(argv[0]) == 0);
|
else ret = (VerifyGameFile(argv[0], false) == 0);
|
||||||
if (err_str) snprintf(err_str, _ERR_STR_LEN, "%s", STR_VERIFICATION_FAILED);
|
if (err_str) snprintf(err_str, _ERR_STR_LEN, "%s", STR_VERIFICATION_FAILED);
|
||||||
}
|
}
|
||||||
else if (id == CMD_ID_DECRYPT) {
|
else if (id == CMD_ID_DECRYPT) {
|
||||||
|
|||||||
@ -812,5 +812,9 @@
|
|||||||
"SYSINFO_SYSTEM_ID0": "System ID0: %s\r\n",
|
"SYSINFO_SYSTEM_ID0": "System ID0: %s\r\n",
|
||||||
"SYSINFO_SYSTEM_ID1": "System ID1: %s\r\n",
|
"SYSINFO_SYSTEM_ID1": "System ID1: %s\r\n",
|
||||||
"SORTING_TICKETS_PLEASE_WAIT": "Sorting tickets, please wait ...",
|
"SORTING_TICKETS_PLEASE_WAIT": "Sorting tickets, please wait ...",
|
||||||
"LUA_NOT_INCLUDED": "This build of GodMode9 was\ncompiled without Lua support."
|
"LUA_NOT_INCLUDED": "This build of GodMode9 was\ncompiled without Lua support.",
|
||||||
|
"ERROR_SIGNATURE_CHECK_FAILED": "Error: Signature check failed",
|
||||||
|
"USE_SIGNATURE_VERIFICATION": "Use signature verification?",
|
||||||
|
"IGNORE_SIGNATURES": "Ignore signatures",
|
||||||
|
"VERIFY_SIGNATURES": "Verify signatures"
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user