diff --git a/source/common/common.h b/source/common/common.h index 77d18aa..05b21cb 100644 --- a/source/common/common.h +++ b/source/common/common.h @@ -50,7 +50,7 @@ // GodMode9 version -#define VERSION "1.1.0" +#define VERSION "1.1.1" // Maximum payload size (arbitrary value!) #define SELF_MAX_SIZE (320 * 1024) // 320kB diff --git a/source/fs/filetype.h b/source/fs/filetype.h index cac5c2c..ae08999 100644 --- a/source/fs/filetype.h +++ b/source/fs/filetype.h @@ -30,7 +30,7 @@ #define FLAG_NUSCDN (1UL<<30) #define FLAG_CXI (1UL<<31) -#define FTYPE_MOUNTABLE(tp) (tp&(IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|SYS_FIRM|SYS_TICKDB)) +#define FTYPE_MOUNTABLE(tp) (tp&(IMG_FAT|IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_EXEFS|GAME_ROMFS|SYS_FIRM|SYS_TICKDB|BIN_KEYDB)) #define FYTPE_VERIFICABLE(tp) (tp&(IMG_NAND|GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_TMD|GAME_BOSS|SYS_FIRM)) #define FYTPE_DECRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|GAME_NUSCDN|SYS_FIRM|BIN_KEYDB)) #define FYTPE_ENCRYPTABLE(tp) (tp&(GAME_CIA|GAME_NCSD|GAME_NCCH|GAME_BOSS|BIN_KEYDB)) diff --git a/source/fs/fsdrive.c b/source/fs/fsdrive.c index 3ed6fe7..decaa59 100644 --- a/source/fs/fsdrive.c +++ b/source/fs/fsdrive.c @@ -49,9 +49,7 @@ int DriveType(const char* path) { type = DRV_VIRTUAL | DRV_XORPAD; } else if (vsrc == VRT_MEMORY) { type = DRV_VIRTUAL | DRV_MEMORY; - } else if (vsrc == VRT_GAME) { - type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE; - } else if (vsrc == VRT_TICKDB) { // GAME (???) + } else if ((vsrc == VRT_GAME) || (vsrc == VRT_KEYDB) || (vsrc == VRT_TICKDB)) { type = DRV_VIRTUAL | DRV_GAME | DRV_IMAGE; } else if (vsrc == VRT_CART) { type = DRV_VIRTUAL | DRV_CART; diff --git a/source/fs/fsdrive.h b/source/fs/fsdrive.h index 8cfc19a..ea1fedc 100644 --- a/source/fs/fsdrive.h +++ b/source/fs/fsdrive.h @@ -5,7 +5,7 @@ #define NORM_FS 10 #define IMGN_FS 3 // image normal filesystems -#define VIRT_FS 11 +#define VIRT_FS 12 // primary drive types #define DRV_UNKNOWN (0<<0) @@ -34,13 +34,13 @@ "EMUNAND CTRNAND", "EMUNAND TWLN", "EMUNAND TWLP", "EMUNAND SD", "EMUNAND VIRTUAL", \ "IMGNAND CTRNAND", "IMGNAND TWLN", "IMGNAND TWLP", "IMGNAND VIRTUAL", \ "GAMECART", \ - "GAME IMAGE", "TICKET.DB IMAGE", \ + "GAME IMAGE", "AESKEYDB IMAGE", "TICKET.DB IMAGE", \ "MEMORY VIRTUAL", \ "NAND XORPADS", \ "LAST SEARCH" \ #define FS_DRVNUM \ - "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "T:", "M:", "X:", "Z:" + "0:", "1:", "2:", "3:", "A:", "S:", "4:", "5:", "6:", "B:", "E:", "7:", "8:", "9:", "I:", "C:", "G:", "K:", "T:", "M:", "X:", "Z:" /** Function to identify the type of a drive **/ int DriveType(const char* path); diff --git a/source/godmode.c b/source/godmode.c index 5aeb3f2..a6f1548 100644 --- a/source/godmode.c +++ b/source/godmode.c @@ -839,7 +839,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur if (clipboard->n_entries && (DriveType(clipboard->entry[0].path) & DRV_IMAGE)) clipboard->n_entries = 0; // remove last mounted image clipboard entries InitImgFS(curr_entry->path); - if (!(DriveType("7:")||DriveType("G:")||DriveType("T:"))) { + if (!(DriveType("7:")||DriveType("G:")||DriveType("K:")||DriveType("T:"))) { ShowPrompt(false, "Mounting image: failed"); InitImgFS(NULL); } else { @@ -847,7 +847,7 @@ u32 FileHandlerMenu(char* current_path, u32* cursor, u32* scroll, DirStruct* cur *current_path = '\0'; GetDirContents(current_dir, current_path); for (u32 i = 0; i < current_dir->n_entries; i++) { - if (strspn(current_dir->entry[i].path, "7GTI") == 0) + if (strspn(current_dir->entry[i].path, "7GKTI") == 0) continue; strncpy(current_path, current_dir->entry[i].path, 256); GetDirContents(current_dir, current_path); diff --git a/source/virtual/virtual.c b/source/virtual/virtual.c index ac01734..578b78c 100644 --- a/source/virtual/virtual.c +++ b/source/virtual/virtual.c @@ -3,6 +3,7 @@ #include "vmem.h" #include "vgame.h" #include "vtickdb.h" +#include "vkeydb.h" #include "vcart.h" typedef struct { @@ -23,7 +24,7 @@ u32 GetVirtualSource(const char* path) { } bool InitVirtualImageDrive(void) { - return InitVGameDrive() || InitVTickDbDrive(); + return InitVGameDrive() || InitVTickDbDrive() || InitVKeyDbDrive(); } bool CheckVirtualDrive(const char* path) { @@ -34,6 +35,8 @@ bool CheckVirtualDrive(const char* path) { return CheckVGameDrive(); else if (virtual_src & VRT_TICKDB) return CheckVTickDbDrive(); + else if (virtual_src & VRT_KEYDB) + return CheckVKeyDbDrive(); return virtual_src; // this is safe for SysNAND & memory } @@ -48,6 +51,8 @@ bool ReadVirtualDir(VirtualFile* vfile, VirtualDir* vdir) { ret = ReadVGameDir(vfile, vdir); } else if (virtual_src & VRT_TICKDB) { ret = ReadVTickDbDir(vfile, vdir); + } else if (virtual_src & VRT_KEYDB) { + ret = ReadVKeyDbDir(vfile, vdir); } else if (virtual_src & VRT_CART) { ret = ReadVCartDir(vfile, vdir); } @@ -180,6 +185,8 @@ int ReadVirtualFile(const VirtualFile* vfile, u8* buffer, u64 offset, u64 count, return ReadVGameFile(vfile, buffer, offset, count); } else if (vfile->flags & VRT_TICKDB) { return ReadVTickDbFile(vfile, buffer, offset, count); + } else if (vfile->flags & VRT_KEYDB) { + return ReadVKeyDbFile(vfile, buffer, offset, count); } else if (vfile->flags & VRT_CART) { return ReadVCartFile(vfile, buffer, offset, count); } @@ -199,7 +206,7 @@ int WriteVirtualFile(const VirtualFile* vfile, const u8* buffer, u64 offset, u64 return WriteVNandFile(vfile, buffer, offset, count); } else if (vfile->flags & VRT_MEMORY) { return WriteVMemFile(vfile, buffer, offset, count); - } // no write support for virtual game / tickdb / cart files + } // no write support for virtual game / tickdb / keydb / cart files return -1; } @@ -212,6 +219,8 @@ u64 GetVirtualDriveSize(const char* path) { return GetVGameDriveSize(); else if (virtual_src & VRT_TICKDB) return GetVTickDbDriveSize(); + else if (virtual_src & VRT_KEYDB) + return GetVKeyDbDriveSize(); else if (virtual_src & VRT_CART) return GetVCartDriveSize(); return 0; diff --git a/source/virtual/virtual.h b/source/virtual/virtual.h index 31cb7d3..e8ef5a8 100644 --- a/source/virtual/virtual.h +++ b/source/virtual/virtual.h @@ -11,16 +11,17 @@ #define VRT_MEMORY (1UL<<10) #define VRT_GAME (1UL<<11) #define VRT_TICKDB (1UL<<12) -#define VRT_CART (1UL<<13) +#define VRT_KEYDB (1UL<<13) +#define VRT_CART (1UL<<14) -#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_CART) +#define VRT_SOURCE (VRT_SYSNAND|VRT_EMUNAND|VRT_IMGNAND|VRT_XORPAD|VRT_MEMORY|VRT_GAME|VRT_TICKDB|VRT_KEYDB|VRT_CART) #define VFLAG_DIR (1UL<<16) #define VFLAG_ROOT (1UL<<17) #define VFLAG_LV3 (1UL<<18) #define VRT_DRIVES {'S', VRT_SYSNAND}, {'E', VRT_EMUNAND}, {'I', VRT_IMGNAND}, {'X', VRT_XORPAD }, \ - {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'T', VRT_TICKDB}, {'C', VRT_CART} + {'M', VRT_MEMORY}, {'G', VRT_GAME}, {'K', VRT_KEYDB}, {'T', VRT_TICKDB}, {'C', VRT_CART} // virtual file flag (subject to change): // bits 0...9 : reserved for NAND virtual sources and info diff --git a/source/virtual/vkeydb.c b/source/virtual/vkeydb.c new file mode 100644 index 0000000..6823008 --- /dev/null +++ b/source/virtual/vkeydb.c @@ -0,0 +1,65 @@ +#include "vtickdb.h" +#include "image.h" +#include "keydb.h" + +#define NAME_LEGKEY "slot0x%02lXKey%.10s.bin" // keyslot / type string + +static AesKeyInfo* key_info = (AesKeyInfo*) VGAME_BUFFER; // full 1MB reserved (enough for 32768 entries) +static u32 n_keys = 0; + +u32 InitVKeyDbDrive(void) { // prerequisite: aeskeydb.bin mounted as image + if (!(GetMountState() & BIN_KEYDB)) return 0; + + // sanity check + u64 fsize = GetMountSize(); + if (!fsize || (fsize % sizeof(AesKeyInfo)) || (fsize > VGAME_BUFFER_SIZE)) { + n_keys = 0; + return 0; + } else n_keys = fsize / sizeof(AesKeyInfo); + + // load the full database into memory + if (ReadImageBytes((u8*) key_info, 0, fsize) != 0) n_keys = 0; + + // decrypt keys if required + for (u32 i = 0; i < n_keys; i++) { + if (key_info[i].isEncrypted) CryptAesKeyInfo(&(key_info[i])); + } + + return (n_keys) ? BIN_KEYDB : 0; +} + +u32 CheckVKeyDbDrive(void) { + if ((GetMountState() & BIN_KEYDB) && n_keys) // very basic sanity check + return BIN_KEYDB; + return 0; +} + +bool ReadVKeyDbDir(VirtualFile* vfile, VirtualDir* vdir) { + if (++vdir->index < (int) n_keys) { + AesKeyInfo* key_entry = key_info + vdir->index; + u32 keyslot = key_entry->slot; + char typestr[16] = { 0 }; + if (*(key_entry->id)) snprintf(typestr, 10, key_entry->id); + else if (key_entry->type != 'N') *typestr = key_entry->type; + + memset(vfile, 0, sizeof(VirtualFile)); + snprintf(vfile->name, 32, NAME_LEGKEY, keyslot, typestr); + vfile->offset = vdir->index * sizeof(AesKeyInfo); + vfile->size = 16; // standard size of a key + vfile->keyslot = 0xFF; + + return true; // found + } + + return false; +} + +int ReadVKeyDbFile(const VirtualFile* vfile, u8* buffer, u64 offset, u64 count) { + AesKeyInfo* key_entry = key_info + (vfile->offset / sizeof(AesKeyInfo)); + memcpy(buffer, key_entry->key + offset, count); + return 0; +} + +u64 GetVKeyDbDriveSize(void) { + return (n_keys) ? GetMountSize() : 0; +} diff --git a/source/virtual/vkeydb.h b/source/virtual/vkeydb.h new file mode 100644 index 0000000..2b8943f --- /dev/null +++ b/source/virtual/vkeydb.h @@ -0,0 +1,12 @@ +#pragma once + +#include "common.h" +#include "virtual.h" + +u32 InitVKeyDbDrive(void); +u32 CheckVKeyDbDrive(void); + +bool ReadVKeyDbDir(VirtualFile* vfile, VirtualDir* vdir); +int ReadVKeyDbFile(const VirtualFile* vfile, u8* buffer, u64 offset, u64 count); +// int WriteVKeyDbFile(const VirtualFile* vfile, const u8* buffer, u64 offset, u64 count); // no writing +u64 GetVKeyDbDriveSize(void); diff --git a/source/virtual/vtickdb.c b/source/virtual/vtickdb.c index 292b65c..1b88fa0 100644 --- a/source/virtual/vtickdb.c +++ b/source/virtual/vtickdb.c @@ -64,7 +64,7 @@ u32 AddTickDbInfo(TickDbInfo* info, Ticket* ticket, u32 offset) { u32 InitVTickDbDrive(void) { // prerequisite: ticket.db mounted as image const u32 area_offsets[] = { TICKDB_AREA_OFFSETS }; - if (!(GetMountState() & SYS_TICKDB)) return 1; + if (!(GetMountState() & SYS_TICKDB)) return 0; // reset internal db memset(tick_info, 0, 16);