diff --git a/Makefile b/Makefile index c8f6d19fa..7244d463f 100644 --- a/Makefile +++ b/Makefile @@ -6,7 +6,7 @@ endif include $(DEVKITARM)/base_tools -name := Luma3DS +name := Luma3DS-Kecleon revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/i') commit := $(shell git rev-parse --short=8 HEAD) @@ -96,7 +96,7 @@ $(dir_build)/%.bin: $(dir_patches)/%.s $(dir_build) @armips $< $(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3 -$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\"" +$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision)\"" $(dir_build)/patches.o: CFLAGS += -DREVISION=\"$(revision)\" -DCOMMIT_HASH="0x$(commit)" $(dir_build)/%.o: $(dir_source)/%.c $(bundled) diff --git a/README.md b/README.md index 92460ad7c..0ce2a1209 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# Luma3DS - Kecleon + +Please read the [gbatemp thread](https://gbatemp.net/threads/release-kecleon-patch-for-luma3ds.455090/). + +Original Readme: + # Luma3DS *Noob-proof (N)3DS "Custom Firmware"* diff --git a/injector/source/patcher.c b/injector/source/patcher.c index 7e7e6ae82..579a3cb6b 100644 --- a/injector/source/patcher.c +++ b/injector/source/patcher.c @@ -499,14 +499,15 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size) { loadCFWInfo(); - if(((progId == 0x0004003000008F02LL || //USA Home Menu - progId == 0x0004003000008202LL || //JPN Home Menu - progId == 0x0004003000009802LL) //EUR Home Menu - && progVer > 4) || - (progId == 0x000400300000A902LL //KOR Home Menu - && progVer > 0) || - progId == 0x000400300000A102LL || //CHN Home Menu - progId == 0x000400300000B102LL) //TWN Home Menu + if((((progId == 0x0004003000008F02LL || //USA Home Menu + progId == 0x0004003000008202LL || //JPN Home Menu + progId == 0x0004003000009802LL) //EUR Home Menu + && progVer > 4) || + (progId == 0x000400300000A902LL //KOR Home Menu + && progVer > 0) || + progId == 0x000400300000A102LL || //CHN Home Menu + progId == 0x000400300000B102LL) //TWN Home Menu + && !CONFIG(KECPATCH)) { static const u8 pattern[] = { 0x0A, 0x0C, 0x00, 0x10 @@ -591,7 +592,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size) )) goto error; } - else if(progId == 0x0004013000008002LL) //NS + else if(progId == 0x0004013000008002LL && !CONFIG(KECPATCH)) //NS { if(progVer > 4) { @@ -731,7 +732,7 @@ void patchCode(u64 progId, u16 progVer, u8 *code, u32 size) ) != 3) goto error; } - else if(progId == 0x0004013000002802LL && progVer > 0) //DLP + else if(progId == 0x0004013000002802LL && progVer > 0 && !CONFIG(KECPATCH)) //DLP { static const u8 pattern[] = { 0x0C, 0xAC, 0xC0, 0xD8 diff --git a/injector/source/patcher.h b/injector/source/patcher.h index 236a1b0a4..bc76b68b0 100644 --- a/injector/source/patcher.h +++ b/injector/source/patcher.h @@ -20,7 +20,6 @@ enum multiOptions DEFAULTEMU = 0, BRIGHTNESS, SPLASH, - PIN, NEWCPU, DEVOPTIONS }; @@ -34,7 +33,11 @@ enum singleOptions PATCHGAMES, PATCHVERSTRING, SHOWGBABOOT, - PATCHACCESS + PATCHACCESS, + KECNAND, + KECPATCH, + KECMENU, + KECCOMBO }; enum flags @@ -43,4 +46,4 @@ enum flags ISSAFEMODE }; -void patchCode(u64 progId, u16 progVer, u8 *code, u32 size); \ No newline at end of file +void patchCode(u64 progId, u16 progVer, u8 *code, u32 size); diff --git a/source/config.c b/source/config.c index 5a69722d4..b9013394e 100644 --- a/source/config.c +++ b/source/config.c @@ -27,7 +27,6 @@ #include "screen.h" #include "draw.h" #include "buttons.h" -#include "pin.h" CfgData configData; @@ -50,7 +49,7 @@ void writeConfig(ConfigurationStatus needConfig, u32 configTemp) { /* If the configuration is different from previously, overwrite it. Just the no-forcing flag being set is not enough */ - if(needConfig != CREATE_CONFIGURATION && (configTemp & 0xFFFFFF7F) == configData.config) return; + if(needConfig != CREATE_CONFIGURATION && (configTemp & 0xFFFFFFFFFFFFFF7F) == configData.config) return; if(needConfig == CREATE_CONFIGURATION) { @@ -60,18 +59,35 @@ void writeConfig(ConfigurationStatus needConfig, u32 configTemp) } //Merge the new options and new boot configuration - configData.config = (configData.config & 0xFFFFFF00) | (configTemp & 0xFF); + configData.config = (configData.config & 0xFFFFFFFFFFFFFF00) | (configTemp & 0xFF); if(!fileWrite(&configData, CONFIG_FILE, sizeof(CfgData))) error("Error writing the configuration file"); } -void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) +u32 getPAD() +{ + initScreens(); + + drawString("Set key combo with ABXY, START, SELECT & D-Pad.\n" + "Press R while holding down combo to finish.\n" + "This may take a few seconds.", + true, 10, 10, COLOR_WHITE); + + u32 pressed; + do { + pressed = waitInput(true); + } + while(!(pressed & BUTTON_R1)); + + return pressed & PIN_BUTTONS; +} + +void configMenu(bool isSdMode) { const char *multiOptionsText[] = { "Default EmuNAND: 1( ) 2( ) 3( ) 4( )", "Screen brightness: 4( ) 3( ) 2( ) 1( )", "Splash: Off( ) Before( ) After( ) payloads", - "PIN lock: Off( ) 4( ) 6( ) 8( ) digits", "New 3DS CPU: Off( ) Clock( ) L2( ) Clock+L2( )", "Dev. features: Off( ) ErrDisp( ) UNITINFO( )" }; @@ -84,7 +100,10 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) "( ) Show NAND or user string in System Settings", "( ) Show GBA boot screen in patched AGB_FIRM", "( ) Patch SVC/service/archive/ARM9 access", - "( ) Hide Pin when entering" + "( ) Kecleon: Save config.bin in CTRNAND.", + "( ) Kecleon: Disable Region-Free/Flashcart\n patches", + "( ) Kecleon: Ignore all Button Presses on boot", + "( ) Kecleon: Set key-combo to remove above lock" }; const char *optionsDescription[] = { "Select the default EmuNAND.\n\n" @@ -101,15 +120,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) "\t* 'After payloads' displays it\n" "afterwards.", - "Activate a PIN lock.\n\n" - "The PIN will be asked each time\n" - "Luma3DS boots.\n\n" - "4, 6 or 8 digits can be selected.\n\n" - "The ABXY buttons and the directional\n" - "pad buttons can be used as keys.\n\n" - "A message can also be displayed\n" - "(refer to the wiki for instructions).", - "Select the New 3DS CPU mode.\n\n" "This won't apply to\n" "New 3DS exclusive/enhanced games.\n\n" @@ -191,9 +201,28 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) "9.3 and 10.4.\n\n" "Only change this if you know what you\n" "are doing!", - - "Hides the input when entering pin\n" - "to unlock the 3DS" + + "Save configuration file in CTRNAND\n" + "at '/rw/luma/config.bin'.", + + "This disables patches that can give\n" + "away this 3DS is running CFW,\n" + "such as out-of-region cartridges,\n" + "out-of-region download play,\n" + "or banned flashcarts.", + + "This makes Luma3DS ignore all Button\n" + "Presses on boot, hiding chainloading\n" + "and boot menus that give away this\n" + "3DS is running CFW.\n\n" + "Warning: config.bin must be deleted\n" + "to re-enable configuration menus\n" + "if Key Combo is not set.\n", + + "Set a Key Combo to make this\n" + "configuration menu appear on\n" + "startup, when the above option is\n" + "set." }; struct multiOption { @@ -205,7 +234,6 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) { .posXs = {19, 24, 29, 34}, .visible = isSdMode }, { .posXs = {21, 26, 31, 36}, .visible = true }, { .posXs = {12, 22, 31, 0}, .visible = true }, - { .posXs = {14, 19, 24, 29}, .visible = true }, { .posXs = {17, 26, 32, 44}, .visible = ISN3DS }, { .posXs = {19, 30, 42, 0}, .visible = true } }; @@ -223,6 +251,9 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) { .visible = true }, { .visible = true }, { .visible = true }, + { .visible = true }, + { .visible = true }, + { .visible = true }, { .visible = true } }; @@ -392,11 +423,7 @@ void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode) for(u32 i = 0; i < singleOptionsAmount; i++) configData.config |= (singleOptions[i].enabled ? 1 : 0) << (i + 20); - u32 newPinMode = MULTICONFIG(PIN); - - if(newPinMode != 0) newPin(oldPinStatus && newPinMode == oldPinMode, newPinMode); - else if(oldPinStatus) fileDelete(PIN_FILE); + if (CONFIG(KECCOMBO)) configData.combo = getPAD(); - while(HID_PAD & PIN_BUTTONS); wait(2000ULL); } diff --git a/source/config.h b/source/config.h index f86f571c4..6c8f4d1b6 100644 --- a/source/config.h +++ b/source/config.h @@ -29,7 +29,8 @@ #define BOOTCONFIG(a, b) ((configData.config >> a) & b) #define CONFIG_FILE "config.bin" -#define CONFIG_VERSIONMAJOR 1 +/* Corresponds to downstream 1.8 */ +#define CONFIG_VERSIONMAJOR 24801 #define CONFIG_VERSIONMINOR 8 #define BOOTCFG_NAND BOOTCONFIG(0, 7) @@ -42,7 +43,6 @@ enum multiOptions DEFAULTEMU = 0, BRIGHTNESS, SPLASH, - PIN, NEWCPU, DEVOPTIONS }; @@ -57,7 +57,10 @@ enum singleOptions PATCHVERSTRING, SHOWGBABOOT, PATCHACCESS, - HIDEPIN + KECNAND, + KECPATCH, + KECMENU, + KECCOMBO }; typedef enum ConfigurationStatus @@ -69,4 +72,4 @@ typedef enum ConfigurationStatus bool readConfig(void); void writeConfig(ConfigurationStatus needConfig, u32 configTemp); -void configMenu(bool isSdMode, bool oldPinStatus, u32 oldPinMode); +void configMenu(bool isSdMode); diff --git a/source/fs.c b/source/fs.c index 831c0309c..f9ff70f65 100644 --- a/source/fs.c +++ b/source/fs.c @@ -35,6 +35,26 @@ static FATFS sdFs, nandFs; +void rmEmptyDir() +{ + DIR dir; + FILINFO fno; + + if (f_chdir("/") != FR_OK) error("Filesystem Error!"); + if (f_opendir(&dir, "luma") != FR_OK) + error("Directory /luma does not exist"); + f_readdir(&dir, &fno); + f_closedir(&dir); + + if (fno.fname[0] == 0) { + f_unlink("luma"); + } else { + if (f_opendir(&dir, "luma") != FR_OK) + error("Directory /luma does not exist"); + } + +} + static bool switchToMainDir(bool isSd) { const char *mainDir = isSd ? "/luma" : "/rw/luma"; @@ -51,12 +71,18 @@ static bool switchToMainDir(bool isSd) } } -bool mountFs(bool isSd, bool switchToCtrNand) +bool mountFs(bool isSdMode, bool switchToCtrNand) { - return isSd ? f_mount(&sdFs, "0:", 1) == FR_OK && switchToMainDir(true) : + return isSdMode ? f_mount(&sdFs, "0:", 1) == FR_OK && switchToMainDir(true) : f_mount(&nandFs, "1:", 1) == FR_OK && (!switchToCtrNand || (f_chdrive("1:") == FR_OK && switchToMainDir(false))); } +bool changeDrive(bool switchToSd) +{ + return switchToSd ? f_chdrive("0:") == FR_OK && switchToMainDir(true) : + f_chdrive("1:") == FR_OK && switchToMainDir(false); +} + u32 fileRead(void *dest, const char *path, u32 maxSize) { FIL file; @@ -114,8 +140,22 @@ void fileDelete(const char *path) f_unlink(path); } -void loadPayload(u32 pressed, const char *payloadPath) +void loadPayload(u32 pressed, const char *payloadPath, bool isSdMode) { + DIR dir; + FILINFO info; + char path[22] = "payloads"; + FRESULT result; + + /* Test SD for payloads. On fail, use NAND. */ + if (isSdMode) { + changeDrive(true); + result = f_findfirst(&dir, &info, path, "*.bin"); + if (result != FR_OK) { + changeDrive(false); + } + } + u32 *loaderAddress = (u32 *)0x24FFFE00; u8 *payloadAddress = (u8 *)0x24F00000; u32 payloadSize = 0, @@ -137,11 +177,6 @@ void loadPayload(u32 pressed, const char *payloadPath) else if(pressed & BUTTON_A) pattern = PATTERN("a"); else pattern = PATTERN("select"); - DIR dir; - FILINFO info; - FRESULT result; - char path[22] = "payloads"; - result = f_findfirst(&dir, &info, path, pattern); if(result != FR_OK) return; @@ -170,14 +205,25 @@ void loadPayload(u32 pressed, const char *payloadPath) ((void (*)())loaderAddress)(); } -void payloadMenu(void) +void payloadMenu(bool isSdMode) { DIR dir; + FILINFO info; char path[62] = "payloads"; + FRESULT result; + + /* Test SD for payloads. On fail, use NAND. */ + if (isSdMode) { + changeDrive(true); + result = f_findfirst(&dir, &info, path, "*.bin"); + if (result != FR_OK) { + changeDrive(false); + } + } + if(f_opendir(&dir, path) != FR_OK) return; - FILINFO info; u32 payloadNum = 0; char payloadList[20][49]; @@ -255,7 +301,7 @@ void payloadMenu(void) concatenateStrings(path, "/"); concatenateStrings(path, payloadList[selectedPayload]); concatenateStrings(path, ".bin"); - loadPayload(0, path); + loadPayload(0, path, isSdMode); error("The payload is too large or corrupted."); } @@ -328,4 +374,4 @@ void findDumpFile(const char *path, char *fileName) } if(result == FR_OK) f_closedir(&dir); -} \ No newline at end of file +} diff --git a/source/fs.h b/source/fs.h index 14f26c0c4..c0cfacd3f 100644 --- a/source/fs.h +++ b/source/fs.h @@ -26,12 +26,14 @@ #define PATTERN(a) a "_*.bin" -bool mountFs(bool isSd, bool switchToCtrNand); +void rmEmptyDir(); +bool mountFs(bool isSdMode, bool switchToCtrNand); +bool changeDrive(bool switchToSd); u32 fileRead(void *dest, const char *path, u32 maxSize); u32 getFileSize(const char *path); bool fileWrite(const void *buffer, const char *path, u32 size); void fileDelete(const char *path); -void loadPayload(u32 pressed, const char *payloadPath); -void payloadMenu(void); +void loadPayload(u32 pressed, const char *payloadPath, bool isSdMode); +void payloadMenu(bool isSdMode); u32 firmRead(void *dest, u32 firmType); -void findDumpFile(const char *path, char *fileName); \ No newline at end of file +void findDumpFile(const char *path, char *fileName); diff --git a/source/main.c b/source/main.c index 17b6d3cf9..de61b8d9b 100644 --- a/source/main.c +++ b/source/main.c @@ -29,7 +29,6 @@ #include "draw.h" #include "strings.h" #include "buttons.h" -#include "pin.h" #include "crypto.h" extern CfgData configData; @@ -45,19 +44,25 @@ void main(void) FirmwareSource nandType; ConfigurationStatus needConfig; - //Mount SD or CTRNAND - bool isSdMode; - if(mountFs(true, false)) isSdMode = true; - else - { + // Attempt to mount SD card. + bool isSdMode = mountFs(true, false); + if (isSdMode) { + // Attempt to load configuration. + if (readConfig()) { + needConfig = MODIFY_CONFIGURATION; + } else { + needConfig = CREATE_CONFIGURATION; + rmEmptyDir(); + } + } + // If either of those fail, attempt to mount CTRNAND. + if (!isSdMode || needConfig == CREATE_CONFIGURATION) { firmSource = FIRMWARE_SYSNAND; if(!mountFs(false, true)) error("Failed to mount SD and CTRNAND."); - isSdMode = false; + // Attempt to load configuration file. + needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; } - //Attempt to read the configuration file - needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION; - //Determine if this is a firmlaunch boot if(ISFIRMLAUNCH) { @@ -92,8 +97,11 @@ void main(void) firmType = NATIVE_FIRM; isA9lhInstalled = ISA9LH; - //Get pressed buttons - u32 pressed = HID_PAD; + //Get pressed buttons only if chainloading/boot menus aren't disabled + u32 pressed = CONFIG(KECMENU) ? 0 : HID_PAD; + + //Should load menu via key combo + bool keyComboPressed = CONFIG(KECCOMBO) && configData.combo == HID_PAD; //Save old options and begin saving the new boot configuration configTemp = (configData.config & 0xFFFFFF00) | ((u32)ISA9LH << 6); @@ -127,16 +135,15 @@ void main(void) } } - u32 pinMode = MULTICONFIG(PIN); - bool hidePin = CONFIG(HIDEPIN); - bool pinExists = pinMode != 0 && verifyPin(pinMode, hidePin); - //If no configuration file exists or SELECT is held, load configuration menu - bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT); + bool shouldLoadConfigMenu = + needConfig == CREATE_CONFIGURATION || + ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT) || + keyComboPressed; if(shouldLoadConfigMenu) { - configMenu(isSdMode, pinExists, pinMode); + configMenu(isSdMode); //Update pressed buttons pressed = HID_PAD; @@ -149,13 +156,6 @@ void main(void) isSafeMode = true; - //If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo - if(pinExists && !shouldLoadConfigMenu) - { - while(HID_PAD & PIN_BUTTONS); - wait(2000ULL); - } - goto boot; } @@ -165,11 +165,11 @@ void main(void) if((pressed & (BUTTON_START | BUTTON_L1)) == BUTTON_START) { - payloadMenu(); + payloadMenu(isSdMode); pressed = HID_PAD; } else if(((pressed & SINGLE_PAYLOAD_BUTTONS) && !(pressed & (BUTTON_L1 | BUTTON_R1 | BUTTON_A))) || - ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL); + ((pressed & L_PAYLOAD_BUTTONS) && (pressed & BUTTON_L1))) loadPayload(pressed, NULL, isSdMode); if(splashMode == 2) loadSplash(); @@ -238,6 +238,12 @@ void main(void) if(!ISFIRMLAUNCH) { configTemp |= (u32)nandType | ((u32)firmSource << 3); + + /* Change to SD card if writing config to SD card. */ + if (isSdMode && !CONFIG(KECNAND)) { + if (!changeDrive(true)) error("SD card unavailible."); + } + writeConfig(needConfig, configTemp); } diff --git a/source/patches.c b/source/patches.c index def865d23..3a92498f2 100644 --- a/source/patches.c +++ b/source/patches.c @@ -511,6 +511,8 @@ u32 patchUnitInfoValueSet(u8 *pos, u32 size) u32 patchLgySignatureChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x47, 0xC1, 0x17, 0x49}; u8 *temp = memsearch(pos, pattern, size, sizeof(pattern)); @@ -527,6 +529,8 @@ u32 patchLgySignatureChecks(u8 *pos, u32 size) u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x20, 0xF6, 0xE7, 0x7F}; u8 *temp = memsearch(pos, pattern, size, sizeof(pattern)); @@ -541,6 +545,8 @@ u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size) u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0xC0, 0x30, 0x06, 0xF0}; u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern)); @@ -555,6 +561,8 @@ u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size) u32 patchTwlWhitelistChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x22, 0x00, 0x20, 0x30}; u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern)); @@ -569,6 +577,8 @@ u32 patchTwlWhitelistChecks(u8 *pos, u32 size) u32 patchTwlFlashcartChecks(u8 *pos, u32 size, u32 firmVersion) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x25, 0x20, 0x00, 0x0E}; u8 *temp = memsearch(pos, pattern, size, sizeof(pattern)); @@ -589,6 +599,8 @@ u32 patchTwlFlashcartChecks(u8 *pos, u32 size, u32 firmVersion) u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x06, 0xF0, 0xA0, 0xFD}; u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern)); @@ -603,6 +615,8 @@ u32 patchOldTwlFlashcartChecks(u8 *pos, u32 size) u32 patchTwlShaHashChecks(u8 *pos, u32 size) { + if (CONFIG(KECPATCH)) return 0; + const u8 pattern[] = {0x10, 0xB5, 0x14, 0x22}; u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern)); diff --git a/source/pin.c b/source/pin.c deleted file mode 100644 index 935343cf4..000000000 --- a/source/pin.c +++ /dev/null @@ -1,220 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified -* reasonable legal notices or author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -*/ - -/* -* Code originally by reworks -*/ - -#include "draw.h" -#include "config.h" -#include "screen.h" -#include "utils.h" -#include "memory.h" -#include "buttons.h" -#include "fs.h" -#include "pin.h" -#include "crypto.h" - -static char pinKeyToLetter(u32 pressed) -{ - const char keys[] = "AB--RLUD--XY"; - - u32 i; - for(i = 31; pressed > 1; i--) pressed /= 2; - - return keys[31 - i]; -} - -void newPin(bool allowSkipping, u32 pinMode) -{ - clearScreens(false); - - u8 length = 4 + 2 * (pinMode - 1); - - drawString("Enter a new PIN using ABXY and the DPad", true, 10, 10, COLOR_TITLE); - drawString(allowSkipping ? "Press START to skip, SELECT to reset" : "Press SELECT to reset", true, 10, 10 + SPACING_Y, COLOR_TITLE); - - drawString("PIN ( digits): ", true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE); - drawCharacter('0' + length, true, 10 + 5 * SPACING_X, 10 + 3 * SPACING_Y, COLOR_WHITE); - - //Pad to AES block length with zeroes - __attribute__((aligned(4))) u8 enteredPassword[AES_BLOCK_SIZE] = {0}; - - bool reset = false; - u8 cnt = 0; - - while(cnt < length) - { - if(reset) - { - for(u32 i = 0; i < cnt; i++) - drawCharacter((char)enteredPassword[i], true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK); - - cnt = 0; - reset = false; - } - - u32 pressed; - do - { - pressed = waitInput(false); - } - while(!(pressed & PIN_BUTTONS)); - - pressed &= PIN_BUTTONS; - if(!allowSkipping) pressed &= ~BUTTON_START; - - if(pressed & BUTTON_START) return; - - if(pressed & BUTTON_SELECT) - { - reset = true; - continue; - } - - if(!pressed) continue; - - //Add character to password - enteredPassword[cnt] = (u8)pinKeyToLetter(pressed); - - //Visualize character on screen - drawCharacter(enteredPassword[cnt], true, 10 + (16 + 2 * cnt) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_WHITE); - - cnt++; - } - - PinData pin; - - memcpy(pin.magic, "PINF", 4); - pin.formatVersionMajor = PIN_VERSIONMAJOR; - pin.formatVersionMinor = PIN_VERSIONMINOR; - - __attribute__((aligned(4))) u8 tmp[SHA_256_HASH_SIZE], - lengthBlock[AES_BLOCK_SIZE] = {0}; - lengthBlock[0] = length; - - computePinHash(tmp, lengthBlock); - memcpy(pin.lengthHash, tmp, sizeof(tmp)); - - computePinHash(tmp, enteredPassword); - memcpy(pin.hash, tmp, sizeof(tmp)); - - if(!fileWrite(&pin, PIN_FILE, sizeof(PinData))) - error("Error writing the PIN file"); -} - -bool verifyPin(u32 pinMode, bool hidePin) -{ - PinData pin; - - if(fileRead(&pin, PIN_FILE, sizeof(PinData)) != sizeof(PinData) || - memcmp(pin.magic, "PINF", 4) != 0 || - pin.formatVersionMajor != PIN_VERSIONMAJOR || - pin.formatVersionMinor != PIN_VERSIONMINOR) - return false; - - __attribute__((aligned(4))) u8 tmp[SHA_256_HASH_SIZE], - lengthBlock[AES_BLOCK_SIZE] = {0}; - lengthBlock[0] = 4 + 2 * (pinMode - 1); - - computePinHash(tmp, lengthBlock); - - //Test vector verification (check if SD card has been used on another console or PIN length changed) - if(memcmp(pin.lengthHash, tmp, sizeof(tmp)) != 0) return false; - - initScreens(); - - drawString("Enter the PIN using ABXY and the DPad to proceed", true, 10, 10, COLOR_TITLE); - drawString("Press START to shutdown, SELECT to clear", true, 10, 10 + SPACING_Y, COLOR_TITLE); - - drawString("PIN ( digits): ", true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE); - drawCharacter('0' + lengthBlock[0], true, 10 + 5 * SPACING_X, 10 + 3 * SPACING_Y, COLOR_WHITE); - - const char *messageFile = "pinmessage.txt"; - char message[801]; - - u32 messageSize = fileRead(message, messageFile, sizeof(message) - 1); - - if(messageSize != 0) - { - message[messageSize] = 0; - drawString(message, false, 10, 10, COLOR_WHITE); - } - - //Pad to AES block length with zeroes - __attribute__((aligned(4))) u8 enteredPassword[AES_BLOCK_SIZE] = {0}; - - bool unlock = false, - reset = false; - u8 cnt = 0; - - while(!unlock) - { - if(reset) - { - for(u32 i = 0; i < cnt; i++) - drawCharacter((char)enteredPassword[i], true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK); - - cnt = 0; - reset = false; - } - - u32 pressed; - do - { - pressed = waitInput(false); - } - while(!(pressed & PIN_BUTTONS)); - - if(pressed & BUTTON_START) mcuPowerOff(); - - pressed &= PIN_BUTTONS; - - if(pressed & BUTTON_SELECT) - { - reset = true; - continue; - } - - if(!pressed) continue; - - //Add character to password - enteredPassword[cnt] = (u8)pinKeyToLetter(pressed); - //Visualize character on screen - char display = hidePin ? '*' : (char)enteredPassword[cnt]; - drawCharacter(display, true, 10 + (16 + 2 * cnt) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_WHITE); - - if(++cnt < lengthBlock[0]) continue; - - computePinHash(tmp, enteredPassword); - unlock = memcmp(pin.hash, tmp, sizeof(tmp)) == 0; - - if(!unlock) - { - reset = true; - - drawString("Wrong PIN, try again", true, 10, 10 + 5 * SPACING_Y, COLOR_RED); - } - } - - return true; -} \ No newline at end of file diff --git a/source/pin.h b/source/pin.h deleted file mode 100644 index a6c18fcaf..000000000 --- a/source/pin.h +++ /dev/null @@ -1,36 +0,0 @@ -/* -* This file is part of Luma3DS -* Copyright (C) 2016 Aurora Wright, TuxSH -* -* This program is free software: you can redistribute it and/or modify -* it under the terms of the GNU General Public License as published by -* the Free Software Foundation, either version 3 of the License, or -* (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program. If not, see . -* -* Additional Terms 7.b of GPLv3 applies to this file: Requiring preservation of specified -* reasonable legal notices or author attributions in that material or in the Appropriate Legal -* Notices displayed by works containing it. -*/ - -/* -* Code originally by reworks -*/ - -#pragma once - -#include "types.h" - -#define PIN_FILE "pin.bin" -#define PIN_VERSIONMAJOR 1 -#define PIN_VERSIONMINOR 3 - -void newPin(bool allowSkipping, u32 pinMode); -bool verifyPin(u32 pinMode, bool hidePin); \ No newline at end of file diff --git a/source/types.h b/source/types.h index 8b624d44a..7967b381f 100644 --- a/source/types.h +++ b/source/types.h @@ -59,7 +59,8 @@ typedef struct __attribute__((packed)) char magic[4]; u16 formatVersionMajor, formatVersionMinor; - u32 config; + u64 config; + u32 combo; } CfgData; typedef struct __attribute__((packed))