mirror of
https://github.com/rvtr/SafeNANDManager.git
synced 2026-01-26 13:43:04 -05:00
Files upload
This commit is contained in:
parent
94de24724d
commit
5871c63a7d
55
Makefile
Normal file
55
Makefile
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
export TARGET := $(shell basename $(CURDIR))
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
# specify a directory which contains the nitro filesystem
|
||||||
|
# this is relative to the Makefile
|
||||||
|
NITRO_FILES :=
|
||||||
|
|
||||||
|
# These set the information text in the nds file
|
||||||
|
GAME_TITLE := dumpTool
|
||||||
|
GAME_SUBTITLE1 := zoogie
|
||||||
|
GAME_SUBTITLE2 := Dump DSi NAND w/ nocash footer
|
||||||
|
|
||||||
|
include $(DEVKITARM)/ds_rules
|
||||||
|
|
||||||
|
.PHONY: checkarm7 checkarm9 clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: checkarm7 checkarm9 $(TARGET).nds
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
checkarm7:
|
||||||
|
$(MAKE) -C arm7
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
checkarm9:
|
||||||
|
$(MAKE) -C arm9
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(TARGET).nds : $(NITRO_FILES) arm7/$(TARGET).elf arm9/$(TARGET).elf
|
||||||
|
ndstool -c $(TARGET).nds -7 arm7/$(TARGET).elf -9 arm9/$(TARGET).elf \
|
||||||
|
-b $(GAME_ICON) "$(GAME_TITLE);$(GAME_SUBTITLE1);$(GAME_SUBTITLE2)" \
|
||||||
|
$(_ADDFILES)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
arm7/$(TARGET).elf:
|
||||||
|
$(MAKE) -C arm7
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
arm9/$(TARGET).elf:
|
||||||
|
$(MAKE) -C arm9
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
$(MAKE) -C arm9 clean
|
||||||
|
$(MAKE) -C arm7 clean
|
||||||
|
rm -f $(TARGET).nds $(TARGET).arm7 $(TARGET).arm9
|
||||||
27
README.txt
Normal file
27
README.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
Directions:
|
||||||
|
Just boot the dumpTool.nds app and press A.
|
||||||
|
It will dump a nand.bin with nocash footer to your dsi at
|
||||||
|
DT010203040A0B0C0D/nand.bin
|
||||||
|
The folder will be next to wherever you put dumpTool.nds. And obviously, your foldername will have different characters. It's console-unique.
|
||||||
|
|
||||||
|
General Info:
|
||||||
|
This tool should create a nand.bin identical to fwTool.nds 2.0. The same holds true for its nand.bin.sha1 file as well.
|
||||||
|
If this isn't the case in your neck of the woods, please make an issue :)
|
||||||
|
(note that identical nands can only occur if both app's output are compared in the same hbmenu session; booting to dsi home menu in between will undoubtably change NAND contents)
|
||||||
|
|
||||||
|
Features:
|
||||||
|
- Completely open source.
|
||||||
|
- Lots of checks, including verifying the nocash footer will decrypt the outputed NAND. Low battery and insufficient SD space are also checked.
|
||||||
|
- Project has a permissive license, and more importantly, its dev is permissive. I don't care what's done with this post-release as long as credit is given.
|
||||||
|
- Simple operation. Just press A and watch it go.
|
||||||
|
- You can cancel the dump in progress. The incomplete nand will be cleaned up.
|
||||||
|
- A little bit faster than fwTool. Should complete in about 7 minutes.
|
||||||
|
|
||||||
|
Thanks:
|
||||||
|
Martin Korth (nocash) - Documenting the consoleID dumping method on GBAtek.
|
||||||
|
Tinivi - Borrowed his 3ds mode (arm9) aes function from https://github.com/TiniVi/AHPCFW/
|
||||||
|
WulfyStylez - Loosely followed his method for nocash footer verification in twlTool:
|
||||||
|
https://gbatemp.net/threads/release-twltool-dsi-downgrading-save-injection-etc-multitool.393488/ (attachment has source code)
|
||||||
|
neimod - Taddy dsi aes functions (dsi.c/h) https://github.com/neimod/dsi/tree/master/taddy (this inlcludes some polarssl files (aes.c/h) and that is GPL v2, info in aes.h)
|
||||||
|
|
||||||
|
|
||||||
126
arm7/Makefile
Normal file
126
arm7/Makefile
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITARM)/ds_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
# DATA is a list of directories containing binary files
|
||||||
|
# all directories are relative to this makefile
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source
|
||||||
|
INCLUDES := include build
|
||||||
|
DATA :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -mthumb-interwork
|
||||||
|
|
||||||
|
CFLAGS := -g -Wall -O0\
|
||||||
|
-mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\
|
||||||
|
-ffast-math \
|
||||||
|
$(ARCH)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -DARM7
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -fno-rtti
|
||||||
|
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,-Map,$(notdir $*).map
|
||||||
|
|
||||||
|
LIBS := -ldswifi7 -lmm7 -lnds7
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(LIBNDS)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export ARM7ELF := $(CURDIR)/$(TARGET).elf
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) *.elf
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(ARM7ELF) : $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
157
arm7/source/arm7.c
Normal file
157
arm7/source/arm7.c
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/*---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
derived from the default ARM7 core
|
||||||
|
|
||||||
|
Copyright (C) 2005 - 2010
|
||||||
|
Michael Noland (joat)
|
||||||
|
Jason Rogers (dovoto)
|
||||||
|
Dave Murphy (WinterMute)
|
||||||
|
|
||||||
|
This software is provided 'as-is', without any express or implied
|
||||||
|
warranty. In no event will the authors be held liable for any
|
||||||
|
damages arising from the use of this software.
|
||||||
|
|
||||||
|
Permission is granted to anyone to use this software for any
|
||||||
|
purpose, including commercial applications, and to alter it and
|
||||||
|
redistribute it freely, subject to the following restrictions:
|
||||||
|
|
||||||
|
1. The origin of this software must not be misrepresented; you
|
||||||
|
must not claim that you wrote the original software. If you use
|
||||||
|
this software in a product, an acknowledgment in the product
|
||||||
|
documentation would be appreciated but is not required.
|
||||||
|
|
||||||
|
2. Altered source versions must be plainly marked as such, and
|
||||||
|
must not be misrepresented as being the original software.
|
||||||
|
|
||||||
|
3. This notice may not be removed or altered from any source
|
||||||
|
distribution.
|
||||||
|
|
||||||
|
---------------------------------------------------------------------------------*/
|
||||||
|
#include <nds.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <dswifi7.h>
|
||||||
|
#include <maxmod7.h>
|
||||||
|
#include <nds/bios.h>
|
||||||
|
#include <nds/arm7/aes.h>
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
void VblankHandler(void) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
Wifi_Update();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
void VcountHandler() {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
inputGetAndSend();
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile bool exitflag = false;
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
void powerButtonCB() {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
exitflag = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
REG_AESCNT 0x04004400 4
|
||||||
|
REG_AESBLKCNT 0x04004404 4
|
||||||
|
REG_AESWRFIFO 0x04004408 4
|
||||||
|
REG_AESRDFIFO 0x0400440C 4
|
||||||
|
REG_AESCTR 0x04004420 16
|
||||||
|
REG_AESMAC 0x04004430 16
|
||||||
|
REG_AESKEY0 0x04004440 48
|
||||||
|
REG_AESKEY1 0x04004470 48
|
||||||
|
REG_AESKEY2 0x040044A0 48
|
||||||
|
REG_AESKEY3 0x040044D0 48
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define AES_CTR_DECRYPT (2 << 27)
|
||||||
|
|
||||||
|
void set_ctr(u32* ctr){
|
||||||
|
for (int i = 0; i < 4; i++) REG_AES_IV[i] = ctr[3-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void wait(int ticks){
|
||||||
|
|
||||||
|
while(ticks--)swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 10 11 22 23 24 25
|
||||||
|
void aes(void* in, void* out, void* iv, u32 method){ //this is sort of a bodged together dsi aes function adapted from this 3ds function
|
||||||
|
REG_AES_CNT = ( AES_CNT_MODE(method) | //https://github.com/TiniVi/AHPCFW/blob/master/source/aes.c#L42
|
||||||
|
AES_WRFIFO_FLUSH | //as long as the output changes when keyslot values change, it's good enough.
|
||||||
|
AES_RDFIFO_FLUSH |
|
||||||
|
AES_CNT_KEY_APPLY |
|
||||||
|
AES_CNT_KEYSLOT(3) |
|
||||||
|
AES_CNT_DMA_WRITE_SIZE(2) |
|
||||||
|
AES_CNT_DMA_READ_SIZE(1)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (iv != NULL) set_ctr((u32*)iv);
|
||||||
|
REG_AES_BLKCNT = (1 << 16);
|
||||||
|
REG_AES_CNT |= 0x80000000;
|
||||||
|
|
||||||
|
for (int j = 0; j < 0x10; j+=4) REG_AES_WRFIFO = *((u32*)(in+j));
|
||||||
|
while(((REG_AES_CNT >> 0x5) & 0x1F) < 0x4); //wait for every word to get processed
|
||||||
|
for (int j = 0; j < 0x10; j+=4) *((u32*)(out+j)) = REG_AES_RDFIFO;
|
||||||
|
//REG_AES_CNT &= ~0x80000000;
|
||||||
|
//if (method & (AES_CTR_DECRYPT | AES_CTR_ENCRYPT)) add_ctr((u8*)iv);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
int main() {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
//readUserSettings();
|
||||||
|
irqInit();
|
||||||
|
fifoInit();
|
||||||
|
//mmInstall(FIFO_MAXMOD);
|
||||||
|
//initClockIRQ(); // Start the RTC tracking IRQ
|
||||||
|
//SetYtrigger(80);
|
||||||
|
//installWifiFIFO();
|
||||||
|
//installSoundFIFO();
|
||||||
|
installSystemFIFO();
|
||||||
|
irqSet(IRQ_VCOUNT, VcountHandler);
|
||||||
|
irqSet(IRQ_VBLANK, VblankHandler);
|
||||||
|
irqEnable( IRQ_VBLANK | IRQ_VCOUNT | IRQ_NETWORK);
|
||||||
|
//setPowerButtonCB(powerButtonCB);
|
||||||
|
|
||||||
|
u8 base[16]={0};
|
||||||
|
u8 in[16]={0};
|
||||||
|
u8 iv[16]={0};
|
||||||
|
u8 *scratch=(u8*)0x02300200;
|
||||||
|
u8 *out=(u8*)0x02300000;
|
||||||
|
u8 *key3=(u8*)0x40044D0;
|
||||||
|
|
||||||
|
aes(in, base, iv, 2);
|
||||||
|
|
||||||
|
//write consecutive 0-255 values to any byte in key3 until we get the same aes output as "base" above - this reveals the hidden byte. this way we can uncover all 16 bytes of the key3 normalkey pretty easily.
|
||||||
|
//greets to Martin Korth for this trick https://problemkaputt.de/gbatek.htm#dsiaesioports (Reading Write-Only Values)
|
||||||
|
for(int i=0;i<16;i++){
|
||||||
|
for(int j=0;j<256;j++){
|
||||||
|
*(key3+i)=j & 0xFF;
|
||||||
|
aes(in, scratch, iv, 2);
|
||||||
|
if(!memcmp(scratch, base, 16)){
|
||||||
|
out[i]=j;
|
||||||
|
//hit++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fifoSendValue32(FIFO_USER_01, 42);//just signal to the arm9 that everything's ready. the value doesn't matter
|
||||||
|
|
||||||
|
// Keep the ARM7 mostly eric idle
|
||||||
|
while (!exitflag) {
|
||||||
|
if ( 0 == (REG_KEYINPUT & (KEY_SELECT | KEY_START | KEY_X | KEY_Y))) {
|
||||||
|
exitflag = true;
|
||||||
|
}
|
||||||
|
swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
127
arm9/Makefile
Normal file
127
arm9/Makefile
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITARM)/ds_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# INCLUDES is a list of directories containing extra header files
|
||||||
|
# DATA is a list of directories containing binary files
|
||||||
|
# all directories are relative to this makefile
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source
|
||||||
|
INCLUDES := include
|
||||||
|
DATA :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -mthumb -mthumb-interwork
|
||||||
|
|
||||||
|
CFLAGS := -g -Wall -O0\
|
||||||
|
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||||
|
-ffast-math \
|
||||||
|
$(ARCH)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -DARM9
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH) -march=armv5te -mtune=arm946e-s
|
||||||
|
|
||||||
|
LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# any extra libraries we wish to link with the project
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBS := -lfat -lnds9
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS := $(LIBNDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export ARM9ELF := $(CURDIR)/$(TARGET).elf
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) *.elf *.nds* *.bin
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(ARM9ELF) : $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPSDIR)/*.d
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
1144
arm9/source/aes.c
Normal file
1144
arm9/source/aes.c
Normal file
File diff suppressed because it is too large
Load Diff
130
arm9/source/aes.h
Normal file
130
arm9/source/aes.h
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
/**
|
||||||
|
* \file aes.h
|
||||||
|
*
|
||||||
|
* Copyright (C) 2006-2009, Paul Bakker <polarssl_maintainer at polarssl.org>
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* Joined copyright on original XySSL code with: Christophe Devine
|
||||||
|
*
|
||||||
|
* 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 2 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, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
#ifndef POLARSSL_AES_H
|
||||||
|
#define POLARSSL_AES_H
|
||||||
|
|
||||||
|
#define AES_ENCRYPT 1
|
||||||
|
#define AES_DECRYPT 0
|
||||||
|
|
||||||
|
#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0800
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES context structure
|
||||||
|
*/
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
int nr; /*!< number of rounds */
|
||||||
|
unsigned long *rk; /*!< AES round keys */
|
||||||
|
unsigned long buf[68]; /*!< unaligned data */
|
||||||
|
}
|
||||||
|
aes_context;
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES key schedule (encryption)
|
||||||
|
*
|
||||||
|
* \param ctx AES context to be initialized
|
||||||
|
* \param key encryption key
|
||||||
|
* \param keysize must be 128, 192 or 256
|
||||||
|
*
|
||||||
|
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||||
|
*/
|
||||||
|
int aes_setkey_enc( aes_context *ctx, unsigned char *key, int keysize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES key schedule (decryption)
|
||||||
|
*
|
||||||
|
* \param ctx AES context to be initialized
|
||||||
|
* \param key decryption key
|
||||||
|
* \param keysize must be 128, 192 or 256
|
||||||
|
*
|
||||||
|
* \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH
|
||||||
|
*/
|
||||||
|
int aes_setkey_dec( aes_context *ctx, unsigned char *key, int keysize );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES-ECB block encryption/decryption
|
||||||
|
*
|
||||||
|
* \param ctx AES context
|
||||||
|
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||||
|
* \param input 16-byte input block
|
||||||
|
* \param output 16-byte output block
|
||||||
|
*/
|
||||||
|
void aes_crypt_ecb( aes_context *ctx,
|
||||||
|
int mode,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16] );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES-CBC buffer encryption/decryption
|
||||||
|
* Length should be a multiple of the block
|
||||||
|
* size (16 bytes)
|
||||||
|
*
|
||||||
|
* \param ctx AES context
|
||||||
|
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||||
|
* \param length length of the input data
|
||||||
|
* \param iv initialization vector (updated after use)
|
||||||
|
* \param input buffer holding the input data
|
||||||
|
* \param output buffer holding the output data
|
||||||
|
*/
|
||||||
|
void aes_crypt_cbc( aes_context *ctx,
|
||||||
|
int mode,
|
||||||
|
int length,
|
||||||
|
unsigned char iv[16],
|
||||||
|
unsigned char *input,
|
||||||
|
unsigned char *output );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief AES-CFB128 buffer encryption/decryption.
|
||||||
|
*
|
||||||
|
* \param ctx AES context
|
||||||
|
* \param mode AES_ENCRYPT or AES_DECRYPT
|
||||||
|
* \param length length of the input data
|
||||||
|
* \param iv_off offset in IV (updated after use)
|
||||||
|
* \param iv initialization vector (updated after use)
|
||||||
|
* \param input buffer holding the input data
|
||||||
|
* \param output buffer holding the output data
|
||||||
|
*/
|
||||||
|
void aes_crypt_cfb128( aes_context *ctx,
|
||||||
|
int mode,
|
||||||
|
int length,
|
||||||
|
int *iv_off,
|
||||||
|
unsigned char iv[16],
|
||||||
|
unsigned char *input,
|
||||||
|
unsigned char *output );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Checkup routine
|
||||||
|
*
|
||||||
|
* \return 0 if successful, or 1 if the test failed
|
||||||
|
*/
|
||||||
|
int aes_self_test( int verbose );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* aes.h */
|
||||||
220
arm9/source/arm9.c
Normal file
220
arm9/source/arm9.c
Normal file
@ -0,0 +1,220 @@
|
|||||||
|
#include <nds.h>
|
||||||
|
#include <fat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/statvfs.h>
|
||||||
|
#include <nds/arm9/nand.h>
|
||||||
|
#include "f_xy.h"
|
||||||
|
#include "dsi.h"
|
||||||
|
|
||||||
|
#define CHUNKSIZE 0x80000
|
||||||
|
u8 *workbuffer;
|
||||||
|
u32 done=0;
|
||||||
|
|
||||||
|
typedef struct nocash_footer {
|
||||||
|
char footerID[16];
|
||||||
|
u8 nand_cid[16];
|
||||||
|
u8 consoleid[8];
|
||||||
|
u8 pad[0x18];
|
||||||
|
} nocash_footer_t;
|
||||||
|
|
||||||
|
void wait(int ticks){
|
||||||
|
while(ticks--)swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 getMBremaining(){
|
||||||
|
struct statvfs stats;
|
||||||
|
statvfs("/", &stats);
|
||||||
|
u64 total_remaining = ((u64)stats.f_bsize * (u64)stats.f_bavail) / (u64)0x100000;
|
||||||
|
return (u32)total_remaining;
|
||||||
|
}
|
||||||
|
|
||||||
|
void death(char *message){
|
||||||
|
iprintf("%s\n", message);
|
||||||
|
iprintf("Hold Power to exit\n");
|
||||||
|
free(workbuffer);
|
||||||
|
while(1)swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
void getCID(u8 *CID){
|
||||||
|
memcpy(CID,(u8*)0x02FFD7BC,16); //arm9 location
|
||||||
|
}
|
||||||
|
|
||||||
|
void getConsoleID(u8 *consoleID){
|
||||||
|
u8 *fifo=(u8*)0x02300000; //shared mem address that has our computed key3 stuff
|
||||||
|
u8 key[16]; //key3 normalkey - keyslot 3 is used for DSi/twln NAND crypto
|
||||||
|
u8 key_xy[16]; //key3_y ^ key3_x
|
||||||
|
u8 key_x[16];////key3_x - contains a DSi console id (which just happens to be the LFCS on 3ds)
|
||||||
|
u8 key_y[16] = {0x76, 0xDC, 0xB9, 0x0A, 0xD3, 0xC4, 0x4D, 0xBD, 0x1D, 0xDD, 0x2D, 0x20, 0x05, 0x00, 0xA0, 0xE1}; //key3_y NAND constant
|
||||||
|
|
||||||
|
while(1){
|
||||||
|
if(fifoCheckValue32(FIFO_USER_01)){ //checking to see when that plucky little arm7 has finished its consoleID magic
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
swiWaitForVBlank();
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(key, fifo, 16); //receive the goods from arm7
|
||||||
|
|
||||||
|
F_XY_reverse((uint32_t*)key, (uint32_t*)key_xy); //work backwards from the normalkey to get key_x that has the consoleID
|
||||||
|
|
||||||
|
for(int i=0;i<16;i++){
|
||||||
|
key_x[i] = key_xy[i] ^ key_y[i]; //''
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(&consoleID[0], &key_x[0], 4);
|
||||||
|
memcpy(&consoleID[4], &key_x[0xC], 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
int dumpNAND(nocash_footer_t *footer){
|
||||||
|
|
||||||
|
u32 rwTotal=nand_GetSize()*0x200; //240MB or 245.5MB
|
||||||
|
printf("NAND size: %.2fMB\n", (float)rwTotal/(float)0x100000);
|
||||||
|
|
||||||
|
if(rwTotal != 0xF000000 && rwTotal != 0xF580000) death("Unknown NAND size. Please\ncontact zoogie at:\nhttps://github.com/zoogie/dumpTool/issues"); //there's no documented nand chip with sizes different from these two.
|
||||||
|
|
||||||
|
while(getBatteryLevel() < 0x4){
|
||||||
|
iprintf("Battery low: plug in to proceed\r"); //user can charge to 2 bars or more OR just plug in the charger. charging state adds +0x80 to battery level. low 4 bits are the battery charge level.
|
||||||
|
wait(60); //don't spam getbatterylevel too much
|
||||||
|
}
|
||||||
|
|
||||||
|
char *filename="nand.bin";
|
||||||
|
int fail=0;
|
||||||
|
swiSHA1context_t ctx;
|
||||||
|
ctx.sha_block=0; //this is weird but it has to be done
|
||||||
|
u8 sha1[20]={0};
|
||||||
|
char sha1file[0x33]={0};
|
||||||
|
|
||||||
|
FILE *f = fopen("nand.bin", "wb");
|
||||||
|
if(!f) death("Could not open nand file");
|
||||||
|
|
||||||
|
iprintf("Dumping... \n");
|
||||||
|
iprintf("Hold A & B to cancel\n");
|
||||||
|
iprintf("Progress: 0%% \r");
|
||||||
|
swiSHA1Init(&ctx);
|
||||||
|
|
||||||
|
for(int i=0;i<rwTotal;i+=CHUNKSIZE){ //read from nand, dump to sd
|
||||||
|
if(nand_ReadSectors(i / 0x200, CHUNKSIZE / 0x200, workbuffer) == false){
|
||||||
|
iprintf("Nand read error\nOffset: %08X\nAborting...", (int)i);
|
||||||
|
fclose(f);
|
||||||
|
unlink(filename);
|
||||||
|
fail=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
swiSHA1Update(&ctx, workbuffer, CHUNKSIZE);
|
||||||
|
if(fwrite(workbuffer, 1, CHUNKSIZE, f) < CHUNKSIZE){
|
||||||
|
iprintf("Sdmc write error\nOffset: %08X\nAborting...", (int)i);
|
||||||
|
fclose(f);
|
||||||
|
unlink(filename);
|
||||||
|
fail=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
iprintf("Progress: %lu%% \r", (i+CHUNKSIZE)/(rwTotal/100));
|
||||||
|
scanKeys();
|
||||||
|
int keys = keysHeld();
|
||||||
|
if(keys & KEY_A && keys & KEY_B){
|
||||||
|
iprintf("\nCanceling...");
|
||||||
|
fclose(f);
|
||||||
|
unlink(filename);
|
||||||
|
fail=1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!fail)
|
||||||
|
{
|
||||||
|
fwrite(footer, 1, sizeof(nocash_footer_t), f);
|
||||||
|
fclose(f);
|
||||||
|
swiSHA1Final(sha1, &ctx);
|
||||||
|
char temp[3];
|
||||||
|
for(int i=0;i<20;i++){
|
||||||
|
snprintf(temp, 3, "%02X", sha1[i]);
|
||||||
|
memcpy(&sha1file[i*2], temp, 2);
|
||||||
|
}
|
||||||
|
memcpy(&sha1file[20*2], " *nand.bin\n", 11);
|
||||||
|
FILE *g=fopen("nand.bin.sha1","wb");
|
||||||
|
fwrite(sha1file, 1, 0x33, g);
|
||||||
|
fclose(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
iprintf("\nDone.\nPress START to exit");
|
||||||
|
done=1;
|
||||||
|
|
||||||
|
return fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
int verifyNocashFooter(nocash_footer_t *footer){
|
||||||
|
u8 out[0x200]={0};
|
||||||
|
u8 sha1[20]={0};
|
||||||
|
u32 key_x[4]={0};
|
||||||
|
u32 key_y[4] = {0x0AB9DC76,0xBD4DC4D3,0x202DDD1D,0xE1A00005}; //key3_y NAND constant
|
||||||
|
u8 key[16]={0};
|
||||||
|
u8 iv[16]={0};
|
||||||
|
u32 cpuid[2]={0};
|
||||||
|
|
||||||
|
nand_ReadSectors(0, 1, workbuffer);
|
||||||
|
dsi_context ctx;
|
||||||
|
|
||||||
|
swiSHA1Calc(sha1, &footer->nand_cid, 16);
|
||||||
|
memcpy(iv, sha1, 16);
|
||||||
|
memcpy(cpuid, &footer->consoleid[0], 8);
|
||||||
|
|
||||||
|
key_x[0]=cpuid[0];
|
||||||
|
key_x[1]=cpuid[0] ^ 0x24EE6906;
|
||||||
|
key_x[2]=cpuid[1] ^ 0xE65B601D;
|
||||||
|
key_x[3]=cpuid[1];
|
||||||
|
|
||||||
|
F_XY((u32*)key, (u32*)key_x, (u32*)key_y);
|
||||||
|
|
||||||
|
dsi_init_ctr(&ctx, key, (u8*)iv);
|
||||||
|
dsi_crypt_ctr(&ctx, workbuffer, out, 0x200);
|
||||||
|
|
||||||
|
if(out[510]==0x55 && out[511]==0xAA) return 1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void) {
|
||||||
|
consoleDemoInit();
|
||||||
|
iprintf("dumpTool v1.0 - zoogie\n");
|
||||||
|
|
||||||
|
workbuffer=(u8*)malloc(CHUNKSIZE);
|
||||||
|
if(!workbuffer) death("Could not allocate workbuffer");
|
||||||
|
nocash_footer_t nocash_footer;
|
||||||
|
u8 CID[16];
|
||||||
|
u8 consoleID[8];
|
||||||
|
getCID(CID);
|
||||||
|
getConsoleID(consoleID); //request bruteforce with write only arm7 aes registers to get consoleID. not as easy as CID!
|
||||||
|
char dirname[128]={0};
|
||||||
|
|
||||||
|
memset(nocash_footer.footerID, 0, sizeof(nocash_footer_t));
|
||||||
|
memcpy(nocash_footer.footerID, "DSi eMMC CID/CPU", 16);
|
||||||
|
memcpy(nocash_footer.nand_cid, CID, 16);
|
||||||
|
memcpy(nocash_footer.consoleid, consoleID, 8);
|
||||||
|
|
||||||
|
if(!fatInitDefault() || !nand_Startup()) death("MMC init problem - dying...");
|
||||||
|
wait(1); //was having a race condition issue with nand_startup and nand_readsectors, so this might help
|
||||||
|
|
||||||
|
if(getMBremaining() < 250) death("SD space remaining < 250MBs");
|
||||||
|
if(nand_GetSize()*0x200 > 600*0x100000) death("This isn't a DSi!"); //I'll give you a kidney if there's unmodified DSi out there with a 600MB NAND.
|
||||||
|
|
||||||
|
snprintf(dirname, 32, "DT%016llX", *(u64*)CID); //that 'certain other tool' uses MAC for console-unique ID, while this one uses part of the nand CID. either is fine but I don't want to overwrite the other app's dump.
|
||||||
|
mkdir(dirname, 0777);
|
||||||
|
chdir(dirname);
|
||||||
|
|
||||||
|
iprintf("Verifying nocash_footer: ");
|
||||||
|
iprintf("%s\n", verifyNocashFooter(&nocash_footer) ? "GOOD":"BAD\nThis dump can't be decrypted\nwith this footer!");
|
||||||
|
iprintf("\n");
|
||||||
|
iprintf("Press A to begin NAND dump\nPress START to exit\n\n");
|
||||||
|
|
||||||
|
while(1) {
|
||||||
|
|
||||||
|
swiWaitForVBlank();
|
||||||
|
scanKeys();
|
||||||
|
if (keysDown() & KEY_A && !done) dumpNAND(&nocash_footer);
|
||||||
|
else if (keysDown() & KEY_START) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
free(workbuffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
356
arm9/source/dsi.c
Normal file
356
arm9/source/dsi.c
Normal file
@ -0,0 +1,356 @@
|
|||||||
|
#include "dsi.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
void dsi_set_key( dsi_context* ctx,
|
||||||
|
unsigned char key[16] )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char keyswap[16];
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
keyswap[i] = key[15-i];
|
||||||
|
|
||||||
|
aes_setkey_enc(&ctx->aes, keyswap, 128);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_add_ctr( dsi_context* ctx,
|
||||||
|
unsigned char carry )
|
||||||
|
{
|
||||||
|
unsigned char sum;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=15; i>=0; i--)
|
||||||
|
{
|
||||||
|
sum = ctx->ctr[i] + carry;
|
||||||
|
|
||||||
|
if (sum < ctx->ctr[i])
|
||||||
|
carry = 1;
|
||||||
|
else
|
||||||
|
carry = 0;
|
||||||
|
|
||||||
|
ctx->ctr[i] = sum;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_set_ctr( dsi_context* ctx,
|
||||||
|
unsigned char ctr[16] )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
ctx->ctr[i] = ctr[15-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_init_ctr( dsi_context* ctx,
|
||||||
|
unsigned char key[16],
|
||||||
|
unsigned char ctr[12] )
|
||||||
|
{
|
||||||
|
dsi_set_key(ctx, key);
|
||||||
|
dsi_set_ctr(ctx, ctr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_crypt_ctr( dsi_context* ctx,
|
||||||
|
void* in,
|
||||||
|
void* out,
|
||||||
|
unsigned int len)
|
||||||
|
{
|
||||||
|
unsigned int i;
|
||||||
|
for(i = 0; i < len; i += 0x10)
|
||||||
|
dsi_crypt_ctr_block(ctx, in+i, out+i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_crypt_ctr_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16] )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char stream[16];
|
||||||
|
|
||||||
|
|
||||||
|
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream);
|
||||||
|
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
{
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
{
|
||||||
|
output[i] = stream[15-i] ^ input[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
output[i] = stream[15-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi_add_ctr(ctx, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_init_ccm( dsi_context* ctx,
|
||||||
|
unsigned char key[16],
|
||||||
|
unsigned int maclength,
|
||||||
|
unsigned int payloadlength,
|
||||||
|
unsigned int assoclength,
|
||||||
|
unsigned char nonce[12] )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
dsi_set_key(ctx, key);
|
||||||
|
|
||||||
|
ctx->maclen = maclength;
|
||||||
|
|
||||||
|
maclength = (maclength-2)/2;
|
||||||
|
|
||||||
|
payloadlength = (payloadlength+15) & ~15;
|
||||||
|
|
||||||
|
// CCM B0 block:
|
||||||
|
// [1-byte flags] [12-byte nonce] [3-byte size]
|
||||||
|
ctx->mac[0] = (maclength<<3) | 2;
|
||||||
|
if (assoclength)
|
||||||
|
ctx->mac[0] |= (1<<6);
|
||||||
|
for(i=0; i<12; i++)
|
||||||
|
ctx->mac[1+i] = nonce[11-i];
|
||||||
|
ctx->mac[13] = payloadlength>>16;
|
||||||
|
ctx->mac[14] = payloadlength>>8;
|
||||||
|
ctx->mac[15] = payloadlength>>0;
|
||||||
|
|
||||||
|
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||||
|
|
||||||
|
// CCM CTR:
|
||||||
|
// [1-byte flags] [12-byte nonce] [3-byte ctr]
|
||||||
|
ctx->ctr[0] = 2;
|
||||||
|
for(i=0; i<12; i++)
|
||||||
|
ctx->ctr[1+i] = nonce[11-i];
|
||||||
|
ctx->ctr[13] = 0;
|
||||||
|
ctx->ctr[14] = 0;
|
||||||
|
ctx->ctr[15] = 0;
|
||||||
|
|
||||||
|
dsi_crypt_ctr_block(ctx, 0, ctx->S0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_encrypt_ccm_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16],
|
||||||
|
unsigned char* mac )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
ctx->mac[i] ^= input[15-i];
|
||||||
|
|
||||||
|
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||||
|
|
||||||
|
if (mac)
|
||||||
|
{
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
dsi_crypt_ctr_block(ctx, input, output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_decrypt_ccm_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16],
|
||||||
|
unsigned char* mac )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
|
||||||
|
if (output)
|
||||||
|
{
|
||||||
|
dsi_crypt_ctr_block(ctx, input, output);
|
||||||
|
|
||||||
|
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
ctx->mac[i] ^= output[15-i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
ctx->mac[i] ^= input[15-i];
|
||||||
|
}
|
||||||
|
|
||||||
|
aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->mac, ctx->mac);
|
||||||
|
|
||||||
|
|
||||||
|
if (mac)
|
||||||
|
{
|
||||||
|
for(i=0; i<16; i++)
|
||||||
|
mac[i] = ctx->mac[15-i] ^ ctx->S0[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_decrypt_ccm( dsi_context* ctx,
|
||||||
|
unsigned char* input,
|
||||||
|
unsigned char* output,
|
||||||
|
unsigned int size,
|
||||||
|
unsigned char* mac )
|
||||||
|
{
|
||||||
|
unsigned char block[16];
|
||||||
|
unsigned char ctr[16];
|
||||||
|
|
||||||
|
while(size > 16)
|
||||||
|
{
|
||||||
|
dsi_decrypt_ccm_block(ctx, input, output, mac);
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
input += 16;
|
||||||
|
if (output)
|
||||||
|
output += 16;
|
||||||
|
|
||||||
|
size -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(ctr, ctx->ctr, 16);
|
||||||
|
memset(block, 0, 16);
|
||||||
|
dsi_crypt_ctr_block(ctx, block, block);
|
||||||
|
memcpy(ctx->ctr, ctr, 16);
|
||||||
|
memcpy(block, input, size);
|
||||||
|
|
||||||
|
|
||||||
|
dsi_decrypt_ccm_block(ctx, block, block, mac);
|
||||||
|
memcpy(output, block, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_encrypt_ccm( dsi_context* ctx,
|
||||||
|
unsigned char* input,
|
||||||
|
unsigned char* output,
|
||||||
|
unsigned int size,
|
||||||
|
unsigned char* mac )
|
||||||
|
{
|
||||||
|
unsigned char block[16];
|
||||||
|
|
||||||
|
while(size > 16)
|
||||||
|
{
|
||||||
|
dsi_encrypt_ccm_block(ctx, input, output, mac);
|
||||||
|
|
||||||
|
if (input)
|
||||||
|
input += 16;
|
||||||
|
if (output)
|
||||||
|
output += 16;
|
||||||
|
|
||||||
|
size -= 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(block, 0, 16);
|
||||||
|
memcpy(block, input, size);
|
||||||
|
dsi_encrypt_ccm_block(ctx, block, block, mac);
|
||||||
|
memcpy(output, block, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_es_init( dsi_es_context* ctx,
|
||||||
|
unsigned char key[16] )
|
||||||
|
{
|
||||||
|
memcpy(ctx->key, key, 16);
|
||||||
|
ctx->randomnonce = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_es_set_nonce( dsi_es_context* ctx,
|
||||||
|
unsigned char nonce[12] )
|
||||||
|
{
|
||||||
|
memcpy(ctx->nonce, nonce, 12);
|
||||||
|
ctx->randomnonce = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dsi_es_set_random_nonce( dsi_es_context* ctx )
|
||||||
|
{
|
||||||
|
ctx->randomnonce = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int dsi_es_decrypt( dsi_es_context* ctx,
|
||||||
|
unsigned char* buffer,
|
||||||
|
unsigned char metablock[32],
|
||||||
|
unsigned int size )
|
||||||
|
{
|
||||||
|
unsigned char ctr[16];
|
||||||
|
unsigned char nonce[12];
|
||||||
|
unsigned char scratchpad[16];
|
||||||
|
unsigned char chkmac[16];
|
||||||
|
unsigned char genmac[16];
|
||||||
|
dsi_context cryptoctx;
|
||||||
|
unsigned int chksize;
|
||||||
|
|
||||||
|
|
||||||
|
memcpy(chkmac, metablock, 16);
|
||||||
|
|
||||||
|
memcpy(ctr, metablock + 16, 16);
|
||||||
|
ctr[0] = 0;
|
||||||
|
ctr[13] = 0;
|
||||||
|
ctr[14] = 0;
|
||||||
|
ctr[15] = 0;
|
||||||
|
|
||||||
|
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
|
||||||
|
dsi_crypt_ctr_block(&cryptoctx, metablock+16, scratchpad);
|
||||||
|
|
||||||
|
chksize = (scratchpad[13]<<16) | (scratchpad[14]<<8) | (scratchpad[15]<<0);
|
||||||
|
|
||||||
|
if (scratchpad[0] != 0x3A || chksize != size)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
memcpy(nonce, metablock + 17, 12);
|
||||||
|
|
||||||
|
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
|
||||||
|
dsi_decrypt_ccm(&cryptoctx, buffer, buffer, size, genmac);
|
||||||
|
|
||||||
|
if (memcmp(genmac, chkmac, 16) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_es_encrypt( dsi_es_context* ctx,
|
||||||
|
unsigned char* buffer,
|
||||||
|
unsigned char metablock[32],
|
||||||
|
unsigned int size )
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char nonce[12];
|
||||||
|
unsigned char mac[16];
|
||||||
|
unsigned char ctr[16];
|
||||||
|
unsigned char scratchpad[16];
|
||||||
|
dsi_context cryptoctx;
|
||||||
|
|
||||||
|
if (ctx->randomnonce)
|
||||||
|
{
|
||||||
|
srand( time(0) );
|
||||||
|
|
||||||
|
for(i=0; i<12; i++)
|
||||||
|
nonce[i] = rand();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
memcpy(nonce, ctx->nonce, 12);
|
||||||
|
}
|
||||||
|
|
||||||
|
dsi_init_ccm(&cryptoctx, ctx->key, 16, size, 0, nonce);
|
||||||
|
dsi_encrypt_ccm(&cryptoctx, buffer, buffer, size, mac);
|
||||||
|
|
||||||
|
memset(scratchpad, 0, 16);
|
||||||
|
scratchpad[0] = 0x3A;
|
||||||
|
scratchpad[13] = size >> 16;
|
||||||
|
scratchpad[14] = size >> 8;
|
||||||
|
scratchpad[15] = size >> 0;
|
||||||
|
|
||||||
|
memset(ctr, 0, 16);
|
||||||
|
memcpy(ctr+1, nonce, 12);
|
||||||
|
|
||||||
|
dsi_init_ctr(&cryptoctx, ctx->key, ctr);
|
||||||
|
dsi_crypt_ctr_block(&cryptoctx, scratchpad, metablock+16);
|
||||||
|
memcpy(metablock+17, nonce, 12);
|
||||||
|
|
||||||
|
memcpy(metablock, mac, 16);
|
||||||
|
|
||||||
|
}
|
||||||
104
arm9/source/dsi.h
Normal file
104
arm9/source/dsi.h
Normal file
@ -0,0 +1,104 @@
|
|||||||
|
#ifndef _DSI_H_
|
||||||
|
#define _DSI_H_
|
||||||
|
|
||||||
|
#include "aes.h"
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char ctr[16];
|
||||||
|
unsigned char mac[16];
|
||||||
|
unsigned char S0[16];
|
||||||
|
unsigned int maclen;
|
||||||
|
|
||||||
|
aes_context aes;
|
||||||
|
}
|
||||||
|
dsi_context;
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
unsigned char key[16];
|
||||||
|
unsigned char nonce[12];
|
||||||
|
int randomnonce;
|
||||||
|
} dsi_es_context;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void dsi_set_key( dsi_context* ctx,
|
||||||
|
unsigned char key[16] );
|
||||||
|
|
||||||
|
void dsi_add_ctr( dsi_context* ctx,
|
||||||
|
unsigned char carry );
|
||||||
|
|
||||||
|
void dsi_set_ctr( dsi_context* ctx,
|
||||||
|
unsigned char ctr[16] );
|
||||||
|
|
||||||
|
void dsi_init_ctr( dsi_context* ctx,
|
||||||
|
unsigned char key[16],
|
||||||
|
unsigned char ctr[12] );
|
||||||
|
|
||||||
|
void dsi_crypt_ctr( dsi_context* ctx,
|
||||||
|
void* in,
|
||||||
|
void* out,
|
||||||
|
unsigned int len);
|
||||||
|
|
||||||
|
void dsi_crypt_ctr_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16] );
|
||||||
|
|
||||||
|
void dsi_init_ccm( dsi_context* ctx,
|
||||||
|
unsigned char key[16],
|
||||||
|
unsigned int maclength,
|
||||||
|
unsigned int payloadlength,
|
||||||
|
unsigned int assoclength,
|
||||||
|
unsigned char nonce[12] );
|
||||||
|
|
||||||
|
void dsi_encrypt_ccm_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16],
|
||||||
|
unsigned char* mac );
|
||||||
|
|
||||||
|
void dsi_decrypt_ccm_block( dsi_context* ctx,
|
||||||
|
unsigned char input[16],
|
||||||
|
unsigned char output[16],
|
||||||
|
unsigned char* mac );
|
||||||
|
|
||||||
|
|
||||||
|
void dsi_decrypt_ccm( dsi_context* ctx,
|
||||||
|
unsigned char* input,
|
||||||
|
unsigned char* output,
|
||||||
|
unsigned int size,
|
||||||
|
unsigned char* mac );
|
||||||
|
|
||||||
|
void dsi_encrypt_ccm( dsi_context* ctx,
|
||||||
|
unsigned char* input,
|
||||||
|
unsigned char* output,
|
||||||
|
unsigned int size,
|
||||||
|
unsigned char* mac );
|
||||||
|
|
||||||
|
void dsi_es_init( dsi_es_context* ctx,
|
||||||
|
unsigned char key[16] );
|
||||||
|
|
||||||
|
void dsi_es_set_nonce( dsi_es_context* ctx,
|
||||||
|
unsigned char nonce[12] );
|
||||||
|
|
||||||
|
void dsi_es_set_random_nonce( dsi_es_context* ctx );
|
||||||
|
|
||||||
|
int dsi_es_decrypt( dsi_es_context* ctx,
|
||||||
|
unsigned char* buffer,
|
||||||
|
unsigned char metablock[32],
|
||||||
|
unsigned int size );
|
||||||
|
|
||||||
|
void dsi_es_encrypt( dsi_es_context* ctx,
|
||||||
|
unsigned char* buffer,
|
||||||
|
unsigned char metablock[32],
|
||||||
|
unsigned int size );
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // _DSI_H_
|
||||||
91
arm9/source/f_xy.c
Normal file
91
arm9/source/f_xy.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
//#define DEBUG
|
||||||
|
|
||||||
|
|
||||||
|
void n128_lrot(uint64_t *num, uint32_t shift)
|
||||||
|
{
|
||||||
|
uint64_t tmp[2];
|
||||||
|
|
||||||
|
tmp[0] = num[0]<<shift;
|
||||||
|
tmp[1] = num[1]<<shift;
|
||||||
|
tmp[0] |= (num[1]>>(64-shift));
|
||||||
|
tmp[1] |= (num[0]>>(64-shift));
|
||||||
|
|
||||||
|
num[0] = tmp[0];
|
||||||
|
num[1] = tmp[1];
|
||||||
|
}
|
||||||
|
void n128_rrot(uint64_t *num, uint32_t shift)
|
||||||
|
{
|
||||||
|
uint64_t tmp[2];
|
||||||
|
|
||||||
|
tmp[0] = num[0]>>shift;
|
||||||
|
tmp[1] = num[1]>>shift;
|
||||||
|
tmp[0] |= (num[1]<<(64-shift));
|
||||||
|
tmp[1] |= (num[0]<<(64-shift));
|
||||||
|
|
||||||
|
num[0] = tmp[0];
|
||||||
|
num[1] = tmp[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
void n128_add(uint64_t *a, uint64_t *b)
|
||||||
|
{
|
||||||
|
uint64_t *a64 = a;
|
||||||
|
uint64_t *b64 = b;
|
||||||
|
uint64_t tmp = (a64[0]>>1)+(b64[0]>>1) + (a64[0] & b64[0] & 1);
|
||||||
|
|
||||||
|
tmp = tmp >> 63;
|
||||||
|
a64[0] = a64[0] + b64[0];
|
||||||
|
a64[1] = a64[1] + b64[1] + tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void n128_sub(uint64_t *a, uint64_t *b)
|
||||||
|
{
|
||||||
|
uint64_t *a64 = a;
|
||||||
|
uint64_t *b64 = b;
|
||||||
|
uint64_t tmp = (a64[0]>>1)-(b64[0]>>1) - ((a64[0]>>63) & (b64[0]>>63) & 1);
|
||||||
|
|
||||||
|
tmp = tmp >> 63;
|
||||||
|
a64[0] = a64[0] - b64[0];
|
||||||
|
a64[1] = a64[1] - b64[1] - tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned char key_xy[16];
|
||||||
|
|
||||||
|
memset(key_xy, 0, 16);
|
||||||
|
memset(key, 0, 16);
|
||||||
|
for(i=0; i<16; i++)key_xy[i] = ((unsigned char*)key_x)[i] ^ ((unsigned char*)key_y)[i];
|
||||||
|
|
||||||
|
key[0] = 0x1a4f3e79;
|
||||||
|
key[1] = 0x2a680f5f;
|
||||||
|
key[2] = 0x29590258;
|
||||||
|
key[3] = 0xfffefb4e;
|
||||||
|
|
||||||
|
n128_add((uint64_t*)key, (uint64_t*)key_xy);
|
||||||
|
n128_lrot((uint64_t*)key, 42);
|
||||||
|
}
|
||||||
|
|
||||||
|
//F_XY_reverse does the reverse of F(X^Y): takes (normal)key, and does F in reverse to generate the original X^Y key_xy.
|
||||||
|
void F_XY_reverse(uint32_t *key, uint32_t *key_xy)
|
||||||
|
{
|
||||||
|
uint32_t tmpkey[4];
|
||||||
|
memset(key_xy, 0, 16);
|
||||||
|
memset(tmpkey, 0, 16);
|
||||||
|
memcpy(tmpkey, key, 16);
|
||||||
|
|
||||||
|
key_xy[0] = 0x1a4f3e79;
|
||||||
|
key_xy[1] = 0x2a680f5f;
|
||||||
|
key_xy[2] = 0x29590258;
|
||||||
|
key_xy[3] = 0xfffefb4e;
|
||||||
|
|
||||||
|
n128_rrot((uint64_t*)tmpkey, 42);
|
||||||
|
n128_sub((uint64_t*)tmpkey, (uint64_t*)key_xy);
|
||||||
|
memcpy(key_xy, tmpkey, 16);
|
||||||
|
}
|
||||||
|
|
||||||
16
arm9/source/f_xy.h
Normal file
16
arm9/source/f_xy.h
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#ifndef _H_F_XY
|
||||||
|
#define _H_F_XY
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void F_XY(uint32_t *key, uint32_t *key_x, uint32_t *key_y);
|
||||||
|
void F_XY_reverse(uint32_t *key, uint32_t *key_xy);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
Loading…
Reference in New Issue
Block a user