Skip to content

Commit

Permalink
2.1
Browse files Browse the repository at this point in the history
Remove mbedtls
Fix decryption error bug
Check for correct movable.sed at boot
Faster signing
Load srl + ctcert from sdmc
Verify ppm file is written at boot
Other minor things
  • Loading branch information
zoogie authored and zoogie committed Dec 8, 2018
1 parent ccfc9ec commit 5cc06bf
Show file tree
Hide file tree
Showing 9 changed files with 223 additions and 141 deletions.
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ TOPDIR ?= $(CURDIR)
include $(DEVKITARM)/3ds_rules

APP_TITLE = Frogtool
APP_DESCRIPTION = v2.0 - Frogminer title manager
APP_DESCRIPTION = v2.1 - Frogminer title manager
APP_AUTHOR = zoogie & jason0597

#---------------------------------------------------------------------------------
Expand Down Expand Up @@ -59,13 +59,13 @@ CXXFLAGS := $(CFLAGS) -fno-rtti -std=c++17
ASFLAGS := -g $(ARCH)
LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)

LIBS := -lctru -lm -lmbedcrypto
LIBS := -lctru

#---------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level containing
# include and lib
#---------------------------------------------------------------------------------
LIBDIRS := $(CTRULIB) $(PORTLIBS)
LIBDIRS := $(CTRULIB)

#---------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
Expand Down
1 change: 0 additions & 1 deletion romfs/ctcert.bin_goes_here.txt

This file was deleted.

1 change: 0 additions & 1 deletion romfs/srl.nds_goes_here.txt

This file was deleted.

19 changes: 4 additions & 15 deletions source/crypto.cpp
Original file line number Diff line number Diff line change
@@ -1,32 +1,21 @@
#include <mbedtls/aes.h>
#include <mbedtls/sha256.h>
#include <3ds.h>
#include "aes-cbc-cmac.h"
#include "crypto.h"

void encryptAES(u8 *plaintext, u32 size, u8 *key, u8 *iv, u8 *output) {
mbedtls_aes_context curctx;
mbedtls_aes_init(&curctx);
mbedtls_aes_setkey_enc(&curctx, key, 128);
mbedtls_aes_crypt_cbc(&curctx, MBEDTLS_AES_ENCRYPT, size, iv, plaintext, output);
AES_CBC_ENC(iv, key, plaintext, size, output, size);
}

void decryptAES(u8 *ciphertext, u32 size, u8 *key, u8 *iv, u8 *output) {
mbedtls_aes_context curctx;
mbedtls_aes_init(&curctx);
mbedtls_aes_setkey_dec(&curctx, key, 128);
mbedtls_aes_crypt_cbc(&curctx, MBEDTLS_AES_DECRYPT, size, iv, ciphertext, output);
AES_CBC_DEC(iv, key, ciphertext, size, output, size);
}

void calculateCMAC(u8 *input, u32 size, u8 *key, u8 *output) {
AES_CMAC(key, input, size, output);
}

void calculateSha256(u8 *input, u32 size, u8 *output) {
mbedtls_sha256_context curctx;
mbedtls_sha256_init(&curctx);
mbedtls_sha256_starts(&curctx, 0);
mbedtls_sha256_update(&curctx, input, size);
mbedtls_sha256_finish(&curctx, output);
FSUSER_UpdateSha256Context(input, size, output);
}

// Full credit goes to https://github.com/luigoalma/3ds_keyscrambler/blob/master/src/UnScrambler.c#L50
Expand Down
55 changes: 19 additions & 36 deletions source/ec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,17 +32,14 @@ static u8 ec_G[61] =
"\x8a\x0b\xef\xf8\x67\xa7\xca\x36\x71\x6f\x7e\x01\xf8\x10\x52";

#if 0
static void elt_print(const char *name1, const char *name2, u8 *a, u8 *b)
static void elt_print(char *name, u8 *a)
{
u32 i;

printf(" %s:", name1);
for (i = 0; i < 4; i++)
printf("%s = ", name);

for (i = 0; i < 30; i++)
printf("%02x", a[i]);

printf(" %s:", name2);
for (i = 0; i < 4; i++)
printf("%02x", b[i]);

printf("\n");
}
Expand Down Expand Up @@ -331,56 +328,42 @@ void point_mul(u8 *d, u8 *a, u8 *b) // a is bignum
}


int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, u8 *Q)
int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, bool randsig)
{
u8 e[30];
u8 kk[30];
u8 m[30];
u8 minv[30];
u8 mG[60];
u8 temphash[32];
srand(time(0));

elt_zero(e);
//elt_zero(R);
//elt_zero(S);
memcpy(temphash, hash, 32);
bn_shiftr(temphash, 32, 7);
memcpy(e, temphash, 30);

for(int i=0;i<30;i++) m[i] = rand() & 0xFF;
m[0]=0;
bn_shiftr(hash, 32, 7);
memcpy(e, hash, 30);

// R = (mG).x
memset(m, 0, 30);

if(randsig){
for(int i=1;i<30;i++){
m[i]=rand() & 0xFF;
}
}

m[29]=1;

point_mul(mG, m, ec_G);
elt_copy(R, mG);
if (bn_compare(R, ec_N, 30) >= 0)
bn_sub_modulus(R, ec_N, 30);

// S = m**-1*(e + Rk) (mod N)

elt_copy(kk, k);
if (bn_compare(kk, ec_N, 30) >= 0)
bn_sub_modulus(kk, ec_N, 30);
bn_mul(S, R, kk, ec_N, 30);
bn_add(kk, S, e, ec_N, 30);
bn_inv(minv, m, ec_N, 30);
bn_mul(S, minv, kk, ec_N, 30);

if(R[0] & 0xFE || S[0] & 0xFE) {
printf(" bad dice roll, trying again...\n");
return 1;
}

if(check_ecdsa(Q, R, S, temphash) != 1){
printf(" sig verify FAIL, trying again...\n");
return 2;
}
else{
printf(" sig verify PASS!!\n");
}

//elt_print("R", "S", R, S);


return 0;
}
Expand All @@ -396,7 +379,7 @@ int check_ecdsa(u8 *Q, u8 *R, u8 *S, u8 *hash)
bn_inv(Sinv, S, ec_N, 30);

elt_zero(e);
//bn_shiftr(hash, 32, 7); //shift right 7 bits.
bn_shiftr(hash, 32, 7); //shift right 7 bits.
memcpy(e, hash, 30); //then shift 16 more bits right by cutting off the last two bytes of 32 byte sha256.
//this gets our bignum sha256 hash to fit in the 233 bit limit of this ecdsa curve.
bn_mul(w1, e, Sinv, ec_N, 30);
Expand Down
2 changes: 1 addition & 1 deletion source/ec.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@

void ec_priv_to_pub(u8 *k, u8 *Q);
int check_ecdsa(u8 *Q, u8 *R, u8 *S, u8 *hash);
int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, u8 *Q);
int generate_ecdsa(u8 *R, u8 *S, u8 *k, u8 *hash, bool randsig);

#endif
106 changes: 79 additions & 27 deletions source/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
#include "tadpole.h"
#include "superfrog_bin.h"

#define ROMFS "romfs:" //define as "" to load srl.nds and ctcert.bin from sd instead
#define menu_size 3
#define WAITA() while (1) {gspWaitForVBlank(); hidScanInput(); if (hidKeysDown() & KEY_A) { break; } }
#define FROGHASH "\xb8\x50\x8a\x15\x95\xdb\x0b\xab"
#define WAIT() while (1) {gspWaitForVBlank(); hidScanInput(); if (hidKeysDown() & KEY_START) { break; } }
PrintConsole topScreen, bottomScreen;
AM_TWLPartitionInfo info;
u8 region=42; //42 would be an error for region, which should be <= 6
Expand Down Expand Up @@ -79,7 +79,7 @@ Result export_tad(u64 tid, u8 op, u8 *workbuf, const char *ext){ //export is a

Result menuUpdate(int cursor, int showinfo){
consoleClear();
printf("%sFrogtool v2.0 - zoogie & jason0597%s\n\n", green, white);
printf("%sFrogtool v2.1 - zoogie & jason0597%s\n\n", green, white);
char menu[menu_size][128] = {
"INJECT patched DS Download Play",
"BOOT patched DS Download Play",
Expand Down Expand Up @@ -137,9 +137,14 @@ Result waitKey(){
u8 *readAllBytes(const char *filename, u32 *filelen) {
FILE *fileptr = fopen(filename, "rb");
if (fileptr == NULL) {
printf("!!! Failed to open %s !!!\n", filename);
WAITA();
exit(-1);
printf("ERROR: Failed to open sdmc:%s !!!\n\n", filename);
printf("Press START to exit\n");
WAIT();
nsExit(); //see if we can exit in a civilized manner here
amExit();
romfsExit();
gfxExit();
exit(0);
}
fseek(fileptr, 0, SEEK_END);
*filelen = ftell(fileptr);
Expand All @@ -159,36 +164,52 @@ void writeAllBytes(const char* filename, u8 *filedata, u32 filelen) {
fclose(fileptr);
}

void doStuff() {
u8 *dsiware, *ctcert, *injection, *movable;
Result doStuff() {
Result res=0;
u32 dsiware_size, ctcert_size, movable_size, injection_size;
u8 *dsiware, *ctcert, *injection, *movable;
u8 header_hash[0x20], srl_hash[0x20];

printf("Reading 484E4441.bin\n");
u8 flipnote_size_LE[4] = {0x00, 0x88, 0x21, 0x00}; // the size of flipnote in little endian
footer_t *footer=(footer_t*)malloc(SIZE_FOOTER);
u8 normalKey[0x10], normalKey_CMAC[0x10];
u8 *header = new u8[0xF0];

ctcert_size = 0x19E;
ctcert = (u8*)malloc(ctcert_size);

printf("Reading sdmc:/484E4441.bin\n");
dsiware = readAllBytes("/484E4441.bin", &dsiware_size);
printf("Reading ctcert.bin\n");
ctcert = readAllBytes(ROMFS "/ctcert.bin", &ctcert_size);
printf("Reading flipnote srl.nds\n");
injection = readAllBytes(ROMFS "/srl.nds", &injection_size);
printf("Reading & parsing movable.sed\n");
printf("Reading & parsing sdmc:/movable.sed\n");
movable = readAllBytes("/movable.sed", &movable_size);

printf("Reading sdmc:/frogcert.bin\n");
injection = readAllBytes("/frogcert.bin", &injection_size);
FSUSER_UpdateSha256Context(injection, injection_size, srl_hash);
injection_size -= ctcert_size;
memcpy(ctcert, injection + injection_size, ctcert_size);

printf("Checking frogcert.bin\n");
if(memcmp(srl_hash, FROGHASH, 8)) {
printf("Oh noes, sdmc:/frogcert.bin is corrupted!\n");
res = 4;
goto fail;
}

printf("Scrambling keys\n");
u8 normalKey[0x10], normalKey_CMAC[0x10];
keyScrambler((movable + 0x110), false, normalKey);
keyScrambler((movable + 0x110), true, normalKey_CMAC);

// === HEADER ===
printf("Decrypting header\n");
u8 *header = new u8[0xF0];
getSection((dsiware + 0x4020), 0xF0, normalKey, header);

if (header[0] != 0x33 || header[1] != 0x46 || header[2] != 0x44 || header[3] != 0x54) {
printf("DECRYPTION FAILED!!!\n");
printf("DECRYPTION FAILED!!!\nThis likely means the input movable.sed is wrong\nPress START to continue\n");
WAIT();
res=3;
goto fail;
}

printf("Injecting new srl.nds size\n");
u8 flipnote_size_LE[4] = {0x00, 0x88, 0x21, 0x00}; // the size of flipnote in little endian
memcpy((header + 0x48 + 4), flipnote_size_LE, 4);

printf("Placing back header\n");
Expand Down Expand Up @@ -217,7 +238,6 @@ void doStuff() {

// === FOOTER ===
printf("Decrypting footer\n");
footer_t *footer=(footer_t*)malloc(SIZE_FOOTER);
getSection((dsiware + 0x4130), 0x4E0, normalKey, (u8*)footer);

printf("Fixing hashes\n");
Expand All @@ -226,7 +246,7 @@ void doStuff() {
//calculateSha256((u8*)footer, (13 * 0x20), ((u8*)footer + (13 * 0x20))); //Fix the master hash

printf("Signing footer...\n");
doSigning(ctcert, footer);
if((res = doSigning(ctcert, footer))) goto fail;

printf("Placing back footer\n");
placeSection((dsiware + 0x4130), (u8*)footer, 0x4E0, normalKey, normalKey_CMAC);
Expand All @@ -236,10 +256,12 @@ void doStuff() {
writeAllBytes("/484E4441.bin.patched", dsiware, dsiware_size);
printf("Done!\n\n");

fail:
free(dsiware);
free(ctcert);
free(injection);
free(movable);
return res;
}

Result copyStuff(){
Expand All @@ -248,7 +270,7 @@ Result copyStuff(){
//copyFile("romfs:/boot.firm","/boot.firm");
mkdir("/private/",0777); mkdir("/private/ds/",0777); mkdir("/private/ds/app/",0777); mkdir("/private/ds/app/4B47554A/",0777); mkdir("/private/ds/app/4B47554A/001/",0777); //inelegant but simple
copyFile("romfs:/T00031_1038C2A757B77_000.ppm","/private/ds/app/4B47554A/001/T00031_1038C2A757B77_000.ppm");
printf("Done!\n\n");
printf("Done!\n");
return 0;
}

Expand All @@ -265,6 +287,7 @@ int main(int argc, char* argv[])
u32 SECOND=1000*1000*1000;
int cursor=0;
int showinfo=1;
const char *ppm="/private/ds/app/4B47554A/001/T00031_1038C2A757B77_000.ppm";
Result res;

u32 kver = osGetKernelVersion(); //the current recommended frogminer guide requires firm 11.8 so we will enforce that here. if a surprise firm drops and native firm changes, this will safeguard users immediately
Expand All @@ -291,7 +314,34 @@ int main(int argc, char* argv[])
res = AM_GetTWLPartitionInfo(&info);
printf("twlInfo: %08X\n",(int)res);
res = CFGU_SecureInfoGetRegion(&region);
printf("region: %d\n\n", (int)region);
printf("region: %d\n", (int)region);

if(access(ppm, F_OK ) != -1){
printf("ppm: ready!\n");
}
else{
copyStuff();
if(access(ppm, F_OK ) == -1){
printf("ERROR: Your flipnote .ppm file cannot be written!\n");
printf("Please copy it to sdmc manually!\n");
printf("(sdmc:%s)\n", ppm);
WAIT();
goto fail;
}
}

res = seed_check();
if(res){
if(res==3)printf("ERROR: sdmc:/movable.sed keyy isn't correct!\n");
else printf("ERROR: sdmc:/movable.sed couldn't be read!\nDid you forget it?\n");
WAIT();
goto fail;
}
else{
printf("movable.sed: good!\n");
}

printf("\n");
svcSleepThread(2*SECOND);

tid = 0x00048005484E4441; //dlp
Expand All @@ -310,9 +360,9 @@ int main(int argc, char* argv[])
if(kDown & KEY_A){
switch(cursor){
case 0: if(havecfw) {printf("You already have CFW!\n\n"); break;}
if(wrongfirmware) {printf("You are not on firm 11.8.0-XX!\n\n"); break;}
export_tad(tid, op, buf, ".bin"); doStuff();
import_tad(tid, op, buf, ".bin.patched"); copyStuff(); break;
if(wrongfirmware) {printf("You are not on the correct firmware!\n\n"); break;}
export_tad(tid, op, buf, ".bin"); if(doStuff()) break;
import_tad(tid, op, buf, ".bin.patched"); break;
case 1: //if(havecfw) {printf("You already have CFW!\n\n"); break;}
//if(wrongfirmware) {printf("You are not on firm 11.8.0-XX!\n\n"); break;}
printf("Booting dlp now ...\n");
Expand All @@ -337,6 +387,8 @@ int main(int argc, char* argv[])
}

}

fail:

free(buf);
nsExit();
Expand Down
Loading

0 comments on commit 5cc06bf

Please sign in to comment.