diff --git a/.gitignore b/.gitignore index c6e1d50..8605dcd 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,8 @@ *.app *.exe *.cia +*.rar +*.zip /*.nds *.app *.tmd diff --git a/BootLoader/Makefile b/BootLoader/Makefile index f8f4061..e55d40a 100755 --- a/BootLoader/Makefile +++ b/BootLoader/Makefile @@ -14,8 +14,8 @@ endif #--------------------------------------------------------------------------------- TARGET := load BUILD := build -SOURCES := source source/patches -INCLUDES := build ../include +SOURCES := source source/patches source/modcrypt +INCLUDES := build ../include source/modcrypt DATA := ../data SPECS := specs @@ -24,10 +24,9 @@ SPECS := specs #--------------------------------------------------------------------------------- ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi -CFLAGS := -g -Wall -O2 \ +CFLAGS := -g -Wall -Wextra -Werror -O2 \ -fomit-frame-pointer \ -ffast-math \ - -Wall -Wextra -Werror \ $(ARCH) CFLAGS += $(INCLUDE) -DARM7 diff --git a/BootLoader/load.ld b/BootLoader/load.ld index 1c8efa1..07333db 100755 --- a/BootLoader/load.ld +++ b/BootLoader/load.ld @@ -3,10 +3,8 @@ OUTPUT_ARCH(arm) ENTRY(_start) MEMORY { - vram : ORIGIN = 0x06020000, LENGTH = 128K - /* arm9ram : ORIGIN = 0x026FD800, LENGTH = 4K Used for the ARM9's functions */ - arm9ram : ORIGIN = 0x027FC800, LENGTH = 4K /* Used for the ARM9's functions */ + arm9ram : ORIGIN = 0x02FFD000, LENGTH = 4K /* Used for the ARM9's functions */ } __vram_start = ORIGIN(vram); diff --git a/BootLoader/source/clear_cache.arm9.s b/BootLoader/source/clear_cache.arm9.s index 9d37fe9..49ec8bb 100644 --- a/BootLoader/source/clear_cache.arm9.s +++ b/BootLoader/source/clear_cache.arm9.s @@ -41,5 +41,28 @@ BEGIN_ASM_FUNC arm9_clearCache mcr p15, 0, r3, c7, c6, 0 @ Flush DCache mcr p15, 0, r3, c7, c10, 4 @ empty write buffer + mcr p15, 0, r3, c3, c0, 0 @ disable write buffer (def = 0) + + mcr p15, 0, r3, c2, c0, 0 @ disable DTCM and protection unit + + mcr p15, 0, r3, c6, c0, 0 @ disable protection unit 0 (def = 0) + mcr p15, 0, r3, c6, c1, 0 @ disable protection unit 1 (def = 0) + mcr p15, 0, r3, c6, c2, 0 @ disable protection unit 2 (def = 0) + mcr p15, 0, r3, c6, c3, 0 @ disable protection unit 3 (def = 0) + mcr p15, 0, r3, c6, c4, 0 @ disable protection unit 4 (def = ?) + mcr p15, 0, r3, c6, c5, 0 @ disable protection unit 5 (def = ?) + mcr p15, 0, r3, c6, c6, 0 @ disable protection unit 6 (def = ?) + mcr p15, 0, r3, c6, c7, 0 @ disable protection unit 7 (def = ?) + + mcr p15, 0, r3, c5, c0, 3 @ IAccess + mcr p15, 0, r3, c5, c0, 2 @ DAccess + + mov r3, #0x00800000 + add r3, r3, #0x00A + mcr p15, 0, r3, c9, c1, 0 @ DTCM base (def = 0x0080000A) ??? + + mov r3, #0x0000000C + mcr p15, 0, r3, c9, c1, 1 @ ITCM base (def = 0x0000000C) ??? + bx lr diff --git a/BootLoader/source/common.h b/BootLoader/source/common.h index 7de1577..a678eed 100755 --- a/BootLoader/source/common.h +++ b/BootLoader/source/common.h @@ -25,46 +25,38 @@ #define resetCpu() \ __asm volatile("swi 0x000000") - -typedef struct sLauncherSettings { - u8 language; - u8 scfgUnlock; - u8 twlMode; - u8 twlCLK; - u8 twlVRAM; - u8 debugMode; - u8 fastBoot; - u8 unused2; -} tLauncherSettings; -extern volatile tLauncherSettings* launchData; -extern volatile int language; -extern volatile bool scfgUnlock; -extern volatile bool twlMode; -extern volatile bool twlCLK; -extern volatile bool debugMode; +#include "../../arm9/common/launcherData.h" -#define CartHeaderCopy 0x02000000 -#define CartChipIDCopy 0x02000180 +ALIGN(4) extern volatile u16 arm9_errorCode; +ALIGN(4) extern volatile tLauncherSettings* launchData; +ALIGN(4) extern volatile u16 language; +ALIGN(4) extern volatile u16 scfgUnlock; +ALIGN(4) extern volatile u16 twlMode; +// ALIGN(4) extern volatile u16 twlVRAM; +ALIGN(4) extern volatile u16 twlRAM; +ALIGN(4) extern volatile u16 twlCLK; +ALIGN(4) extern volatile u16 isTWLSRL; +ALIGN(4) extern volatile u16 debugMode; -enum ERROR_CODES { - ERR_NONE = 0x00, - ERR_STS_CLR_MEM = 0x01, - ERR_STS_LOAD_BIN = 0x02, - ERR_STS_HOOK_BIN = 0x03, - ERR_STS_START = 0x04, +ALIGN(4) enum ERROR_CODES { + ERR_NONE = (u16)0x00, + ERR_STS_STARTBIN = (u16)0x01, + ERR_STS_CLR_MEM = (u16)0x02, + ERR_STS_LOAD_BIN = (u16)0x03, + ERR_STS_START = (u16)0x04, // initCard error codes: - ERR_LOAD_NORM = 0x11, - ERR_LOAD_OTHR = 0x12, - ERR_SEC_NORM = 0x13, - ERR_SEC_OTHR = 0x14, - ERR_LOGO_CRC = 0x15, - ERR_HEAD_CRC = 0x16, - ERR_STS_STARTBIN = 0x21, + ERR_LOAD_NORM = (u16)0x05, + ERR_LOAD_OTHR = (u16)0x06, + ERR_SEC_NORM = (u16)0x07, + ERR_SEC_OTHR = (u16)0x08, + ERR_HEAD_CRC = (u16)0x09, + ERR_UNKNOWN = (u16)0x10, + ERR_UNKNOWN2 = (u16)0x11 }; // Values fixed so they can be shared with ASM code -enum ARM9_STATE { +ALIGN(4) enum ARM9_STATE { ARM9_BOOT = 0, ARM9_START = 1, ARM9_RESET = 2, @@ -72,7 +64,7 @@ enum ARM9_STATE { ARM9_MEMCLR = 4 }; -enum ARM7_STATE { +ALIGN(4) enum ARM7_STATE { ARM7_BOOT = 0, ARM7_START = 1, ARM7_RESET = 2, @@ -84,27 +76,152 @@ enum ARM7_STATE { ARM7_ERR = 8 }; -extern volatile u32 arm9_errorCode; - -static inline void dmaFill(const void* src, void* dest, uint32 size) { +ALIGN(4) static inline void dmaFill(const void* src, void* dest, uint32 size) { DMA_SRC(3) = (uint32)src; DMA_DEST(3) = (uint32)dest; DMA_CR(3) = DMA_COPY_WORDS | DMA_SRC_FIX | (size>>2); while(DMA_CR(3) & DMA_BUSY); } -static inline void copyLoop (u32* dest, const u32* src, size_t size) { +ALIGN(4) static inline void copyLoop (u32* dest, const u32* src, size_t size) { do { *dest++ = *src++; } while (size -= 4); } -static inline void ipcSendState(uint8_t state) { +ALIGN(4) static inline void ipcSendState(uint8_t state) { REG_IPC_SYNC = (state & 0x0f) << 8; } -static inline uint8_t ipcRecvState(void) { +ALIGN(4) static inline uint8_t ipcRecvState(void) { return (uint8_t)(REG_IPC_SYNC & 0x0f); } +typedef struct sTWLHeader { + char gameTitle[12]; //!< 12 characters for the game title. + char gameCode[4]; //!< 4 characters for the game code. + char makercode[2]; //!< identifies the (commercial) developer. + u8 unitCode; //!< identifies the required hardware. + u8 deviceType; //!< type of device in the game card + u8 deviceSize; //!< capacity of the device (1 << n Mbit) + u8 reserved1[7]; + u8 twlHeaderSettings; + u8 jumpSettings; + u8 romversion; //!< version of the ROM. + u8 flags; //!< bit 2: auto-boot flag. + + u32 arm9romOffset; //!< offset of the arm9 binary in the nds file. + void *arm9executeAddress; //!< adress that should be executed after the binary has been copied. + void *arm9destination; //!< destination address to where the arm9 binary should be copied. + u32 arm9binarySize; //!< size of the arm9 binary. + + u32 arm7romOffset; //!< offset of the arm7 binary in the nds file. + void *arm7executeAddress; //!< adress that should be executed after the binary has been copied. + void *arm7destination; //!< destination address to where the arm7 binary should be copied. + u32 arm7binarySize; //!< size of the arm7 binary. + + u32 filenameOffset; //!< File Name Table (FNT) offset. + u32 filenameSize; //!< File Name Table (FNT) size. + u32 fatOffset; //!< File Allocation Table (FAT) offset. + u32 fatSize; //!< File Allocation Table (FAT) size. + + u32 arm9overlaySource; //!< File arm9 overlay offset. + u32 arm9overlaySize; //!< File arm9 overlay size. + u32 arm7overlaySource; //!< File arm7 overlay offset. + u32 arm7overlaySize; //!< File arm7 overlay size. + + u32 cardControl13; //!< Port 40001A4h setting for normal commands (used in modes 1 and 3) + u32 cardControlBF; //!< Port 40001A4h setting for KEY1 commands (used in mode 2) + u32 bannerOffset; //!< offset to the banner with icon and titles etc. + + u16 secureCRC16; //!< Secure Area Checksum, CRC-16. + + u16 readTimeout; //!< Secure Area Loading Timeout. + + u32 unknownRAM1; //!< ARM9 Auto Load List RAM Address (?) + u32 unknownRAM2; //!< ARM7 Auto Load List RAM Address (?) + + u32 bfPrime1; //!< Secure Area Disable part 1. + u32 bfPrime2; //!< Secure Area Disable part 2. + u32 romSize; //!< total size of the ROM. + + u32 headerSize; //!< ROM header size. + u32 zeros88[14]; + u8 gbaLogo[156]; //!< Nintendo logo needed for booting the game. + u16 logoCRC16; //!< Nintendo Logo Checksum, CRC-16. + u16 headerCRC16; //!< header checksum, CRC-16. + + u32 debugRomSource; //!< debug ROM offset. + u32 debugRomSize; //!< debug size. + u32 debugRomDestination; //!< debug RAM destination. + u32 offset_0x16C; //reserved? + + u8 zero[0x10]; + + u32 arm9MBK1; + u32 arm9MBK2; + u32 arm9MBK3; + u32 arm9MBK4; + u32 arm9MBK5; + u32 arm9MBK6; + u32 arm9MBK7; + u32 arm9MBK8; + u32 arm7MBK6; + u32 arm7MBK7; + u32 arm7MBK8; + u32 arm9MBKMaster; + + u32 region; + u32 accessControl; + u32 arm7SCFGSettings; + u16 dsi_unk1; + u8 dsi_unk2; + u8 dsi_flags; + + u32 arm9iromOffset; //!< offset of the arm9 binary in the nds file. + u32 arm9iexecuteAddress; + u32 arm9idestination; //!< destination address to where the arm9 binary should be copied. + u32 arm9ibinarySize; //!< size of the arm9 binary. + + u32 arm7iromOffset; //!< offset of the arm7 binary in the nds file. + u32 deviceListDestination; + u32 arm7idestination; //!< destination address to where the arm7 binary should be copied. + u32 arm7ibinarySize; //!< size of the arm7 binary. + + u8 zero2[0x20]; + + // 0x200 + // TODO: More DSi-specific fields. + u32 dsi1[0x10/4]; + u32 twlRomSize; + u32 dsi_unk3; + u32 dsi_unk4; + u32 dsi_unk5; + + u32 modCrypt1Offset; + u32 modcrypt1Size; + u32 modcrypt2Offset; + u32 modcrypt2Size; + + u32 dsi_tid; + u32 dsi_tid2; + u32 pubSavSize; + u32 prvSavSize; + + u8 reserved3[176]; + u8 age_ratings[0x10]; + + unsigned char hmac_arm9[16]; + unsigned char hmac_arm7[16]; + u8 hmac_digest_master[0x14]; + u8 hmac_icon_title[0x14]; + u8 hmac_arm9i[0x14]; + u8 hmac_arm7i[0x14]; + u8 reserved4[0x28]; + u8 hmac_arm9_no_secure[0x14]; + u8 reserved5[0xA4C]; + u8 debug_args[0x180]; + u8 rsa_signature[0x80]; +} tTWLHeader; + #endif // _COMMON_H diff --git a/BootLoader/source/encryption.c b/BootLoader/source/encryption.c index 37523ac..0634891 100755 --- a/BootLoader/source/encryption.c +++ b/BootLoader/source/encryption.c @@ -18,7 +18,9 @@ #include #include "encryption.h" -#include "read_bios.h" +#include "key1.h" +#include "key2.h" +#include "tonccpy.h" #define KEYSIZE 0x1048 @@ -84,7 +86,7 @@ void apply_keycode (u32 modulo) { crypt_64bit_up (&keycode[1]); crypt_64bit_up (&keycode[0]); - memset (scratch, 0, 8); + toncset (scratch, 0, 8); for (i = 0; i < 0x12; i+=1) { keybuf[i] = keybuf[i] ^ bswap_32bit (keycode[i % modulo]); @@ -96,8 +98,8 @@ void apply_keycode (u32 modulo) { } } -void init_keycode (u32 idcode, u32 level, u32 modulo) { - readBios ((u8*)keybuf, 0x30, KEYSIZE); +void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice) { + tonccpy ((u8*)keybuf, (iCardDevice ? gEncrDataTwl : gEncrData), KEYSIZE); keycode[0] = idcode; keycode[1] = idcode/2; keycode[2] = idcode*2; diff --git a/BootLoader/source/encryption.h b/BootLoader/source/encryption.h index 6eb27b4..0b947b3 100755 --- a/BootLoader/source/encryption.h +++ b/BootLoader/source/encryption.h @@ -20,7 +20,7 @@ #define ENCRYPTION_H #include -void init_keycode (u32 idcode, u32 level, u32 modulo); +void init_keycode (u32 idcode, u32 level, u32 modulo, int iCardDevice); void crypt_64bit_down (u32* ptr); void crypt_64bit_up (u32* ptr); diff --git a/BootLoader/source/key1.h b/BootLoader/source/key1.h new file mode 100644 index 0000000..5980e77 --- /dev/null +++ b/BootLoader/source/key1.h @@ -0,0 +1,264 @@ +const unsigned char gEncrData[] = +{ + 0x99,0xD5,0x20,0x5F,0x57,0x44,0xF5,0xB9,0x6E,0x19,0xA4,0xD9,0x9E,0x6A,0x5A,0x94, + 0xD8,0xAE,0xF1,0xEB,0x41,0x75,0xE2,0x3A,0x93,0x82,0xD0,0x32,0x33,0xEE,0x31,0xD5, + 0xCC,0x57,0x61,0x9A,0x37,0x06,0xA2,0x1B,0x79,0x39,0x72,0xF5,0x55,0xAE,0xF6,0xBE, + 0x5F,0x1B,0x69,0xFB,0xE5,0x9D,0xF1,0xE9,0xCE,0x2C,0xD9,0xA1,0x5E,0x32,0x05,0xE6, + 0xFE,0xD3,0xFE,0xCF,0xD4,0x62,0x04,0x0D,0x8B,0xF5,0xEC,0xB7,0x2B,0x60,0x79,0xBB, + 0x12,0x95,0x31,0x0D,0x6E,0x3F,0xDA,0x2B,0x88,0x84,0xF0,0xF1,0x3D,0x12,0x7E,0x25, + 0x45,0x22,0xF1,0xBB,0x24,0x06,0x1A,0x06,0x11,0xAD,0xDF,0x28,0x8B,0x64,0x81,0x34, + 0x2B,0xEB,0x33,0x29,0x99,0xAA,0xF2,0xBD,0x9C,0x14,0x95,0x9D,0x9F,0xF7,0xF5,0x8C, + 0x72,0x97,0xA1,0x29,0x9D,0xD1,0x5F,0xCF,0x66,0x4D,0x07,0x1A,0xDE,0xD3,0x4A,0x4B, + 0x85,0xC9,0xA7,0xA3,0x17,0x95,0x05,0x3A,0x3D,0x49,0x0A,0xBF,0x0A,0x89,0x8B,0xA2, + 0x4A,0x82,0x49,0xDD,0x27,0x90,0xF1,0x0B,0xE9,0xEB,0x1C,0x6A,0x83,0x76,0x45,0x05, + 0xBA,0x81,0x70,0x61,0x17,0x3F,0x4B,0xDE,0xAE,0xCF,0xAB,0x39,0x57,0xF2,0x3A,0x56, + 0x48,0x11,0xAD,0x8A,0x40,0xE1,0x45,0x3F,0xFA,0x9B,0x02,0x54,0xCA,0xA6,0x93,0xFB, + 0xEF,0x4D,0xFE,0x6F,0xA3,0xD8,0x87,0x9C,0x08,0xBA,0xD5,0x48,0x6A,0x8D,0x2D,0xFD, + 0x6E,0x15,0xF8,0x74,0xBD,0xBE,0x52,0x8B,0x18,0x22,0x8A,0x9E,0xFB,0x74,0x37,0x07, + 0x1B,0x36,0x6C,0x4A,0x19,0xBA,0x42,0x62,0xB9,0x79,0x91,0x10,0x7B,0x67,0x65,0x96, + 0xFE,0x02,0x23,0xE8,0xEE,0x99,0x8C,0x77,0x3E,0x5C,0x86,0x64,0x4D,0x6D,0x78,0x86, + 0xA5,0x4F,0x65,0xE2,0x1E,0xB2,0xDF,0x5A,0x0A,0xD0,0x7E,0x08,0x14,0xB0,0x71,0xAC, + 0xBD,0xDB,0x83,0x1C,0xB9,0xD7,0xA1,0x62,0xCD,0xC6,0x63,0x7C,0x52,0x69,0xC3,0xE6, + 0xBF,0x75,0xCE,0x12,0x44,0x5D,0x21,0x04,0xFA,0xFB,0xD3,0x3C,0x38,0x11,0x63,0xD4, + 0x95,0x85,0x41,0x49,0x46,0x09,0xF2,0x08,0x43,0x11,0xDC,0x1F,0x76,0xC0,0x15,0x6D, + 0x1F,0x3C,0x63,0x70,0xEA,0x87,0x80,0x6C,0xC3,0xBD,0x63,0x8B,0xC2,0x37,0x21,0x37, + 0xDC,0xEE,0x09,0x23,0x2E,0x37,0x6A,0x4D,0x73,0x90,0xF7,0x50,0x30,0xAC,0x1C,0x92, + 0x04,0x10,0x23,0x91,0x4F,0xD2,0x07,0xAA,0x68,0x3E,0x4F,0x9A,0xC9,0x64,0x60,0x6A, + 0xC8,0x14,0x21,0xF3,0xD6,0x22,0x41,0x12,0x44,0x24,0xCF,0xE6,0x8A,0x56,0xDD,0x0D, + 0x53,0x4D,0xE1,0x85,0x1E,0x8C,0x52,0x5A,0x9C,0x19,0x84,0xC2,0x03,0x57,0xF1,0x6F, + 0xE3,0x00,0xBE,0x58,0xF6,0x4C,0xED,0xD5,0x21,0x64,0x9C,0x1F,0xBE,0x55,0x03,0x3C, + 0x4A,0xDC,0xFF,0xAA,0xC9,0xDA,0xE0,0x5D,0x5E,0xBF,0xE6,0xDE,0xF5,0xD8,0xB1,0xF8, + 0xFF,0x36,0xB3,0xB9,0x62,0x67,0x95,0xDB,0x31,0x5F,0x37,0xED,0x4C,0x70,0x67,0x99, + 0x90,0xB5,0x18,0x31,0x6C,0x3D,0x99,0x99,0xE4,0x42,0xDA,0xD3,0x25,0x42,0x13,0xA0, + 0xAE,0xD7,0x70,0x6C,0xB1,0x55,0xCF,0xC7,0xD7,0x46,0xD5,0x43,0x61,0x17,0x3D,0x44, + 0x28,0xE9,0x33,0x85,0xD5,0xD0,0xA2,0x93,0xAA,0x25,0x12,0x1F,0xFB,0xC5,0x0B,0x46, + 0xF5,0x97,0x76,0x56,0x45,0xA6,0xBE,0x87,0xB1,0x94,0x6B,0xE8,0xB1,0xFE,0x33,0x99, + 0xAE,0x1F,0x3E,0x6C,0x39,0x71,0x1D,0x09,0x00,0x90,0x37,0xE4,0x10,0x3E,0x75,0x74, + 0xFF,0x8C,0x83,0x3B,0xB0,0xF1,0xB0,0xF9,0x01,0x05,0x47,0x42,0x95,0xF1,0xD6,0xAC, + 0x7E,0x38,0xE6,0x9E,0x95,0x74,0x26,0x3F,0xB4,0x68,0x50,0x18,0xD0,0x43,0x30,0xB4, + 0x4C,0x4B,0xE3,0x68,0xBF,0xE5,0x4D,0xB6,0x95,0x8B,0x0A,0xA0,0x74,0x25,0x32,0x77, + 0xCF,0xA1,0xF7,0x2C,0xD8,0x71,0x13,0x5A,0xAB,0xEA,0xC9,0x51,0xE8,0x0D,0xEE,0xEF, + 0xE9,0x93,0x7E,0x19,0xA7,0x1E,0x43,0x38,0x81,0x16,0x2C,0xA1,0x48,0xE3,0x73,0xCC, + 0x29,0x21,0x6C,0xD3,0x5D,0xCE,0xA0,0xD9,0x61,0x71,0x43,0xA0,0x15,0x13,0xB5,0x64, + 0x92,0xCF,0x2A,0x19,0xDC,0xAD,0xB7,0xA5,0x9F,0x86,0x65,0xF8,0x1A,0x9F,0xE7,0xFB, + 0xF7,0xFD,0xB8,0x13,0x6C,0x27,0xDB,0x6F,0xDF,0x35,0x1C,0xF7,0x8D,0x2C,0x5B,0x9B, + 0x12,0xAB,0x38,0x64,0x06,0xCC,0xDE,0x31,0xE8,0x4E,0x75,0x11,0x64,0xE3,0xFA,0xEA, + 0xEB,0x34,0x54,0xC2,0xAD,0x3F,0x34,0xEB,0x93,0x2C,0x7D,0x26,0x36,0x9D,0x56,0xF3, + 0x5A,0xE1,0xF6,0xB3,0x98,0x63,0x4A,0x9E,0x32,0x83,0xE4,0x9A,0x84,0x60,0x7D,0x90, + 0x2E,0x13,0x0E,0xEE,0x93,0x4B,0x36,0xA2,0x85,0xEC,0x16,0x38,0xE8,0x88,0x06,0x02, + 0xBF,0xF0,0xA0,0x3A,0xED,0xD7,0x6A,0x9A,0x73,0xE1,0x57,0xCF,0xF8,0x44,0xB8,0xDC, + 0x2E,0x23,0x59,0xD1,0xDF,0x95,0x52,0x71,0x99,0x61,0xA0,0x4B,0xD5,0x7F,0x6E,0x78, + 0xBA,0xA9,0xC5,0x30,0xD3,0x40,0x86,0x32,0x9D,0x32,0x0C,0x9C,0x37,0xB7,0x02,0x2F, + 0xBA,0x54,0x98,0xA9,0xC4,0x13,0x04,0xC9,0x8D,0xBE,0xC8,0xE7,0x5D,0x97,0x50,0x2E, + 0x93,0xD6,0x22,0x59,0x0C,0x27,0xBC,0x22,0x92,0xE0,0xA7,0x20,0x0F,0x93,0x6F,0x7F, + 0x4C,0x9F,0xD3,0xB5,0xA6,0x2A,0x0B,0x74,0x67,0x49,0x7D,0x10,0x26,0xCB,0xD1,0xC5, + 0x86,0x71,0xE7,0x8C,0xA0,0x9C,0xE9,0x5B,0xB2,0x1A,0xF6,0x01,0xEE,0x8C,0x9E,0x5E, + 0x83,0xF2,0x1A,0xDB,0xE6,0xE5,0xEA,0x84,0x59,0x76,0xD2,0x7C,0xF6,0x8D,0xA5,0x49, + 0x36,0x48,0xC2,0x16,0x52,0xBB,0x83,0xA3,0x74,0xB9,0x07,0x0C,0x3B,0xFF,0x61,0x28, + 0xE1,0x61,0xE9,0xE4,0xEF,0x6E,0x15,0xAA,0x4E,0xBA,0xE8,0x5D,0x05,0x96,0xBB,0x32, + 0x56,0xB0,0xFB,0x72,0x52,0x0F,0x0E,0xC8,0x42,0x25,0x65,0x76,0x89,0xAF,0xF2,0xDE, + 0x10,0x27,0xF0,0x01,0x4B,0x74,0xA7,0x97,0x07,0xD5,0x26,0x54,0x54,0x09,0x1F,0x82, + 0x0A,0x86,0x7D,0x30,0x39,0x0E,0xB3,0x26,0x9B,0x0B,0x57,0xBB,0x36,0x06,0x31,0xAF, + 0xFD,0x79,0xFC,0xD9,0x30,0x10,0x2B,0x0C,0xB3,0xE1,0x9B,0xD7,0x7B,0xDC,0x5F,0xEF, + 0xD2,0xF8,0x13,0x45,0x4D,0x47,0x75,0xBD,0x46,0x96,0x3C,0x7E,0x75,0xF3,0x3E,0xB5, + 0x67,0xC5,0x9A,0x3B,0xB0,0x5B,0x29,0x6B,0xDE,0x80,0x5B,0xC8,0x15,0x05,0xB1,0x31, + 0xB6,0xCE,0x49,0xDD,0xAD,0x84,0xB5,0xAE,0x60,0xDC,0x67,0x31,0x34,0x30,0xFE,0x4E, + 0xBD,0x80,0x2F,0xA6,0xBF,0x63,0x39,0x21,0x86,0xD9,0x35,0x7F,0x16,0x68,0x22,0x05, + 0x54,0xE9,0x90,0x26,0x8C,0x07,0x6C,0x51,0xA4,0x31,0x55,0xD7,0x09,0x07,0xA8,0x3E, + 0x2E,0x53,0x66,0xC1,0xF8,0xF2,0x7B,0xC4,0xF2,0x58,0xCF,0xF1,0x87,0xC5,0xA2,0xE7, + 0x27,0x8F,0x30,0x87,0x58,0xA0,0x64,0x62,0x23,0x18,0xB9,0x88,0x7C,0xFA,0xCE,0xC4, + 0x98,0xAE,0xAD,0x17,0xCC,0x4A,0x5B,0xF3,0xE9,0x48,0xD5,0x56,0xD3,0x0D,0xF2,0xC8, + 0x92,0x73,0x8C,0xDB,0xD7,0x2F,0x56,0xAC,0x81,0xF9,0x92,0x69,0x4D,0xC6,0x32,0xF6, + 0xE6,0xC0,0x8D,0x21,0xE2,0x76,0x80,0x61,0x11,0xBC,0xDC,0x6C,0x93,0xAF,0x19,0x69, + 0x9B,0xD0,0xBF,0xB9,0x31,0x9F,0x02,0x67,0xA3,0x51,0xEE,0x83,0x06,0x22,0x7B,0x0C, + 0xAB,0x49,0x42,0x40,0xB8,0xD5,0x01,0x7D,0xCE,0x5E,0xF7,0x55,0x53,0x39,0xC5,0x99, + 0x46,0xD8,0x87,0x9F,0xBA,0xF7,0x64,0xB4,0xE3,0x9A,0xFA,0xA1,0x6D,0x90,0x68,0x10, + 0x30,0xCA,0x8A,0x54,0xA7,0x9F,0x60,0xC3,0x19,0xF5,0x6B,0x0D,0x7A,0x51,0x98,0xE6, + 0x98,0x43,0x51,0xB4,0xD6,0x35,0xE9,0x4F,0xC3,0xDF,0x0F,0x7B,0xD6,0x2F,0x5C,0xBD, + 0x3A,0x15,0x61,0x19,0xF1,0x4B,0xCB,0xAA,0xDC,0x6D,0x64,0xC9,0xD3,0xC6,0x1E,0x56, + 0xEF,0x38,0x4C,0x50,0x71,0x86,0x75,0xCC,0x0D,0x0D,0x4E,0xE9,0x28,0xF6,0x06,0x5D, + 0x70,0x1B,0xAA,0xD3,0x45,0xCF,0xA8,0x39,0xAC,0x95,0xA6,0x2E,0xB4,0xE4,0x22,0xD4, + 0x74,0xA8,0x37,0x5F,0x48,0x7A,0x04,0xCC,0xA5,0x4C,0x40,0xD8,0x28,0xB4,0x28,0x08, + 0x0D,0x1C,0x72,0x52,0x41,0xF0,0x7D,0x47,0x19,0x3A,0x53,0x4E,0x58,0x84,0x62,0x6B, + 0x93,0xB5,0x8A,0x81,0x21,0x4E,0x0D,0xDC,0xB4,0x3F,0xA2,0xC6,0xFC,0xC9,0x2B,0x40, + 0xDA,0x38,0x04,0xE9,0x5E,0x5A,0x86,0x6B,0x0C,0x22,0x25,0x85,0x68,0x11,0x8D,0x7C, + 0x92,0x1D,0x95,0x55,0x4D,0xAB,0x8E,0xBB,0xDA,0xA6,0xE6,0xB7,0x51,0xB6,0x32,0x5A, + 0x05,0x41,0xDD,0x05,0x2A,0x0A,0x56,0x50,0x91,0x17,0x47,0xCC,0xC9,0xE6,0x7E,0xB5, + 0x61,0x4A,0xDB,0x73,0x67,0x51,0xC8,0x33,0xF5,0xDA,0x6E,0x74,0x2E,0x54,0xC3,0x37, + 0x0D,0x6D,0xAF,0x08,0xE8,0x15,0x8A,0x5F,0xE2,0x59,0x21,0xCD,0xA8,0xDE,0x0C,0x06, + 0x5A,0x77,0x6B,0x5F,0xDB,0x18,0x65,0x3E,0xC8,0x50,0xDE,0x78,0xE0,0xB8,0x82,0xB3, + 0x5D,0x4E,0x72,0x32,0x07,0x4F,0xC1,0x34,0x23,0xBA,0x96,0xB7,0x67,0x4E,0xA4,0x28, + 0x1E,0x34,0x62,0xEB,0x2D,0x6A,0x70,0xE9,0x2F,0x42,0xC4,0x70,0x4E,0x5A,0x31,0x9C, + 0xF9,0x5B,0x47,0x28,0xAA,0xDA,0x71,0x6F,0x38,0x1F,0xB3,0x78,0xC4,0x92,0x6B,0x1C, + 0x9E,0xF6,0x35,0x9A,0xB7,0x4D,0x0E,0xBF,0xCC,0x18,0x29,0x41,0x03,0x48,0x35,0x5D, + 0x55,0xD0,0x2B,0xC6,0x29,0xAF,0x5C,0x60,0x74,0x69,0x8E,0x5E,0x9B,0x7C,0xD4,0xBD, + 0x7B,0x44,0x64,0x7D,0x3F,0x92,0x5D,0x69,0xB6,0x1F,0x00,0x4B,0xD4,0x83,0x35,0xCF, + 0x7E,0x64,0x4E,0x17,0xAE,0x8D,0xD5,0x2E,0x9A,0x28,0x12,0x4E,0x2E,0x2B,0x49,0x08, + 0x5C,0xAE,0xC6,0x46,0x85,0xAE,0x41,0x61,0x1E,0x6F,0x82,0xD2,0x51,0x37,0x16,0x1F, + 0x0B,0xF6,0x59,0xA4,0x9A,0xCA,0x5A,0xAF,0x0D,0xD4,0x33,0x8B,0x20,0x63,0xF1,0x84, + 0x80,0x5C,0xCB,0xCF,0x08,0xB4,0xB9,0xD3,0x16,0x05,0xBD,0x62,0x83,0x31,0x9B,0x56, + 0x51,0x98,0x9F,0xBA,0xB2,0x5B,0xAA,0xB2,0x22,0x6B,0x2C,0xB5,0xD4,0x48,0xFA,0x63, + 0x2B,0x5F,0x58,0xFA,0x61,0xFA,0x64,0x09,0xBB,0x38,0xE0,0xB8,0x9D,0x92,0x60,0xA8, + 0x0D,0x67,0x6F,0x0E,0x37,0xF5,0x0D,0x01,0x9F,0xC2,0x77,0xD4,0xFE,0xEC,0xF1,0x73, + 0x30,0x39,0xE0,0x7D,0xF5,0x61,0x98,0xE4,0x2C,0x28,0x55,0x04,0x56,0x55,0xDB,0x2F, + 0x6B,0xEC,0xE5,0x58,0x06,0xB6,0x64,0x80,0x6A,0x2A,0x1A,0x4E,0x5B,0x0F,0xD8,0xC4, + 0x0A,0x2E,0x52,0x19,0xD9,0x62,0xF5,0x30,0x48,0xBE,0x8C,0x7B,0x4F,0x38,0x9B,0xA2, + 0xC3,0xAF,0xC9,0xD3,0xC7,0xC1,0x62,0x41,0x86,0xB9,0x61,0x21,0x57,0x6F,0x99,0x4F, + 0xC1,0xBA,0xCE,0x7B,0xB5,0x3B,0x4D,0x5E,0x8A,0x8B,0x44,0x57,0x5F,0x13,0x5F,0x70, + 0x6D,0x5B,0x29,0x47,0xDC,0x38,0xE2,0xEC,0x04,0x55,0x65,0x12,0x2A,0xE8,0x17,0x43, + 0xE1,0x8E,0xDD,0x2A,0xB3,0xE2,0x94,0xF7,0x09,0x6E,0x5C,0xE6,0xEB,0x8A,0xF8,0x6D, + 0x89,0x49,0x54,0x48,0xF5,0x2F,0xAD,0xBF,0xEA,0x94,0x4B,0xCA,0xFC,0x39,0x87,0x82, + 0x5F,0x8A,0x01,0xF2,0x75,0xF2,0xE6,0x71,0xD6,0xD8,0x42,0xDE,0xF1,0x2D,0x1D,0x28, + 0xA6,0x88,0x7E,0xA3,0xA0,0x47,0x1D,0x30,0xD9,0xA3,0x71,0xDF,0x49,0x1C,0xCB,0x01, + 0xF8,0x36,0xB1,0xF2,0xF0,0x22,0x58,0x5D,0x45,0x6B,0xBD,0xA0,0xBB,0xB2,0x88,0x42, + 0xC7,0x8C,0x28,0xCE,0x93,0xE8,0x90,0x63,0x08,0x90,0x7C,0x89,0x3C,0xF5,0x7D,0xB7, + 0x04,0x2D,0x4F,0x55,0x51,0x16,0xFD,0x7E,0x79,0xE8,0xBE,0xC1,0xF2,0x12,0xD4,0xF8, + 0xB4,0x84,0x05,0x23,0xA0,0xCC,0xD2,0x2B,0xFD,0xE1,0xAB,0xAD,0x0D,0xD1,0x55,0x6C, + 0x23,0x41,0x94,0x4D,0x77,0x37,0x4F,0x05,0x28,0x0C,0xBF,0x17,0xB3,0x12,0x67,0x6C, + 0x8C,0xC3,0x5A,0xF7,0x41,0x84,0x2A,0x6D,0xD0,0x94,0x12,0x27,0x2C,0xB4,0xED,0x9C, + 0x4D,0xEC,0x47,0x82,0x97,0xD5,0x67,0xB9,0x1B,0x9D,0xC0,0x55,0x07,0x7E,0xE5,0x8E, + 0xE2,0xA8,0xE7,0x3E,0x12,0xE4,0x0E,0x3A,0x2A,0x45,0x55,0x34,0xA2,0xF9,0x2D,0x5A, + 0x1B,0xAB,0x52,0x7C,0x83,0x10,0x5F,0x55,0xD2,0xF1,0x5A,0x43,0x2B,0xC6,0xA7,0xA4, + 0x89,0x15,0x95,0xE8,0xB4,0x4B,0x9D,0xF8,0x75,0xE3,0x9F,0x60,0x78,0x5B,0xD6,0xE6, + 0x0D,0x44,0xE6,0x21,0x06,0xBD,0x47,0x22,0x53,0xA4,0x00,0xAD,0x8D,0x43,0x13,0x85, + 0x39,0xF7,0xAA,0xFC,0x38,0xAF,0x7B,0xED,0xFC,0xE4,0x2B,0x54,0x50,0x98,0x4C,0xFC, + 0x85,0x80,0xF7,0xDF,0x3C,0x80,0x22,0xE1,0x94,0xDA,0xDE,0x24,0xC6,0xB0,0x7A,0x39, + 0x38,0xDC,0x0F,0xA1,0xA7,0xF4,0xF9,0x6F,0x63,0x18,0x57,0x8B,0x84,0x41,0x2A,0x2E, + 0xD4,0x53,0xF2,0xD9,0x00,0x0F,0xD0,0xDD,0x99,0x6E,0x19,0xA6,0x0A,0xD0,0xEC,0x5B, + 0x58,0x24,0xAB,0xC0,0xCB,0x06,0x65,0xEC,0x1A,0x13,0x38,0x94,0x0A,0x67,0x03,0x2F, + 0x3F,0xF7,0xE3,0x77,0x44,0x77,0x33,0xC6,0x14,0x39,0xD0,0xE3,0xC0,0xA2,0x08,0x79, + 0xBB,0x40,0x99,0x57,0x41,0x0B,0x01,0x90,0xCD,0xE1,0xCC,0x48,0x67,0xDB,0xB3,0xAF, + 0x88,0x74,0xF3,0x4C,0x82,0x8F,0x72,0xB1,0xB5,0x23,0x29,0xC4,0x12,0x6C,0x19,0xFC, + 0x8E,0x46,0xA4,0x9C,0xC4,0x25,0x65,0x87,0xD3,0x6D,0xBE,0x8A,0x93,0x11,0x03,0x38, + 0xED,0x83,0x2B,0xF3,0x46,0xA4,0x93,0xEA,0x3B,0x53,0x85,0x1D,0xCE,0xD4,0xF1,0x08, + 0x83,0x27,0xED,0xFC,0x9B,0x1A,0x18,0xBC,0xF9,0x8B,0xAE,0xDC,0x24,0xAB,0x50,0x38, + 0xE9,0x72,0x4B,0x10,0x22,0x17,0x7B,0x46,0x5D,0xAB,0x59,0x64,0xF3,0x40,0xAE,0xF8, + 0xBB,0xE5,0xC8,0xF9,0x26,0x03,0x4E,0x55,0x7D,0xEB,0xEB,0xFE,0xF7,0x39,0xE6,0xE0, + 0x0A,0x11,0xBE,0x2E,0x28,0xFF,0x98,0xED,0xC0,0xC9,0x42,0x56,0x42,0xC3,0xFD,0x00, + 0xF6,0xAF,0x87,0xA2,0x5B,0x01,0x3F,0x32,0x92,0x47,0x95,0x9A,0x72,0xA5,0x32,0x3D, + 0xAE,0x6B,0xD0,0x9B,0x07,0xD2,0x49,0x92,0xE3,0x78,0x4A,0xFA,0xA1,0x06,0x7D,0xF2, + 0x41,0xCF,0x77,0x74,0x04,0x14,0xB2,0x0C,0x86,0x84,0x64,0x16,0xD5,0xBB,0x51,0xA1, + 0xE5,0x6F,0xF1,0xD1,0xF2,0xE2,0xF7,0x5F,0x58,0x20,0x4D,0xB8,0x57,0xC7,0xCF,0xDD, + 0xC5,0xD8,0xBE,0x76,0x3D,0xF6,0x5F,0x7E,0xE7,0x2A,0x8B,0x88,0x24,0x1B,0x38,0x3F, + 0x0E,0x41,0x23,0x77,0xF5,0xF0,0x4B,0xD4,0x0C,0x1F,0xFA,0xA4,0x0B,0x80,0x5F,0xCF, + 0x45,0xF6,0xE0,0xDA,0x2F,0x34,0x59,0x53,0xFB,0x20,0x3C,0x52,0x62,0x5E,0x35,0xB5, + 0x62,0xFE,0x8B,0x60,0x63,0xE3,0x86,0x5A,0x15,0x1A,0x6E,0xD1,0x47,0x45,0xBC,0x32, + 0xB4,0xEB,0x67,0x38,0xAB,0xE4,0x6E,0x33,0x3A,0xB5,0xED,0xA3,0xAD,0x67,0xE0,0x4E, + 0x41,0x95,0xEE,0x62,0x62,0x71,0x26,0x1D,0x31,0xEF,0x62,0x30,0xAF,0xD7,0x82,0xAC, + 0xC2,0xDC,0x05,0x04,0xF5,0x97,0x07,0xBF,0x11,0x59,0x23,0x07,0xC0,0x64,0x02,0xE8, + 0x97,0xE5,0x3E,0xAF,0x18,0xAC,0x59,0xA6,0x8B,0x4A,0x33,0x90,0x1C,0x6E,0x7C,0x9C, + 0x20,0x7E,0x4C,0x3C,0x3E,0x61,0x64,0xBB,0xC5,0x6B,0x7C,0x7E,0x3E,0x9F,0xC5,0x4C, + 0x9F,0xEA,0x73,0xF5,0xD7,0x89,0xC0,0x4C,0xF4,0xFB,0xF4,0x2D,0xEC,0x14,0x1B,0x51, + 0xD5,0xC1,0x12,0xC8,0x10,0xDF,0x0B,0x4A,0x8B,0x9C,0xBC,0x93,0x45,0x6A,0x3E,0x3E, + 0x7D,0xC1,0xA9,0xBA,0xCD,0xC1,0xB4,0x07,0xE4,0xE1,0x68,0x86,0x43,0xB2,0x6D,0x38, + 0xF3,0xFB,0x0C,0x5C,0x66,0x37,0x71,0xDE,0x56,0xEF,0x6E,0xA0,0x10,0x40,0x65,0xA7, + 0x98,0xF7,0xD0,0xBE,0x0E,0xC8,0x37,0x36,0xEC,0x10,0xCA,0x7C,0x9C,0xAB,0x84,0x1E, + 0x05,0x17,0x76,0x02,0x1C,0x4F,0x52,0xAA,0x5F,0xC1,0xC6,0xA0,0x56,0xB9,0xD8,0x04, + 0x84,0x44,0x4D,0xA7,0x59,0xD8,0xDE,0x60,0xE6,0x38,0x0E,0x05,0x8F,0x03,0xE1,0x3B, + 0x6D,0x81,0x04,0x33,0x6F,0x30,0x0B,0xCE,0x69,0x05,0x21,0x33,0xFB,0x26,0xBB,0x89, + 0x7D,0xB6,0xAE,0x87,0x7E,0x51,0x07,0xE0,0xAC,0xF7,0x96,0x0A,0x6B,0xF9,0xC4,0x5C, + 0x1D,0xE4,0x44,0x47,0xB8,0x5E,0xFA,0xE3,0x78,0x84,0x55,0x42,0x4B,0x48,0x5E,0xF7, + 0x7D,0x47,0x35,0x86,0x1D,0x2B,0x43,0x05,0x03,0xEC,0x8A,0xB8,0x1E,0x06,0x3C,0x76, + 0x0C,0x48,0x1A,0x43,0xA7,0xB7,0x8A,0xED,0x1E,0x13,0xC6,0x43,0xEE,0x10,0xEF,0xDB, + 0xEC,0xFB,0x3C,0x83,0xB2,0x95,0x44,0xEF,0xD8,0x54,0x51,0x4E,0x2D,0x11,0x44,0x1D, + 0xFB,0x36,0x59,0x1E,0x7A,0x34,0xC1,0xC3,0xCA,0x57,0x00,0x61,0xEA,0x67,0xA5,0x16, + 0x9B,0x55,0xD0,0x55,0xE1,0x7F,0xD9,0x36,0xD2,0x40,0x76,0xAE,0xDC,0x01,0xCE,0xB0, + 0x7A,0x83,0xD5,0xCB,0x20,0x98,0xEC,0x6B,0xC1,0x72,0x92,0x34,0xF3,0x82,0x57,0x37, + 0x62,0x8A,0x32,0x36,0x0C,0x90,0x43,0xAE,0xAE,0x5C,0x9B,0x78,0x8E,0x13,0x65,0x02, + 0xFD,0x68,0x71,0xC1,0xFE,0xB0,0x31,0xA0,0x24,0x82,0xB0,0xC3,0xB1,0x79,0x69,0xA7, + 0xF5,0xD2,0xEB,0xD0,0x82,0xC0,0x32,0xDC,0x9E,0xC7,0x26,0x3C,0x6D,0x8D,0x98,0xC1, + 0xBB,0x22,0xD4,0xD0,0x0F,0x33,0xEC,0x3E,0xB9,0xCC,0xE1,0xDC,0x6A,0x4C,0x77,0x36, + 0x14,0x1C,0xF9,0xBF,0x81,0x9F,0x28,0x5F,0x71,0x85,0x32,0x29,0x90,0x75,0x48,0xC4, + 0xB3,0x4A,0xCE,0xD8,0x44,0x8F,0x14,0x2F,0xFD,0x40,0x57,0xEF,0xAA,0x08,0x75,0xD9, + 0x46,0xD1,0xD6,0x6E,0x32,0x55,0x1F,0xC3,0x18,0xFE,0x84,0x1F,0xFC,0x84,0xD5,0xFF, + 0x71,0x5E,0x1B,0x48,0xC3,0x86,0x95,0x0E,0x28,0x08,0x27,0xD3,0x38,0x83,0x71,0x7B, + 0x4C,0x80,0x63,0x54,0x9A,0x56,0xB0,0xAC,0xCF,0x80,0xCA,0x31,0x09,0xEF,0xFE,0xF3, + 0xBE,0xAF,0x24,0x7E,0xA6,0xFE,0x53,0x3F,0xC2,0x8D,0x4A,0x33,0x68,0xD1,0x22,0xA6, + 0x66,0xAD,0x7B,0xEA,0xDE,0xB6,0x43,0xB0,0xA1,0x25,0x95,0x00,0xA3,0x3F,0x75,0x46, + 0x14,0x11,0x44,0xEC,0xD7,0x95,0xBC,0x92,0xF0,0x4F,0xA9,0x16,0x53,0x62,0x97,0x60, + 0x2A,0x0F,0x41,0xF1,0x71,0x24,0xBE,0xEE,0x94,0x7F,0x08,0xCD,0x60,0x93,0xB3,0x85, + 0x5B,0x07,0x00,0x3F,0xD8,0x0F,0x28,0x83,0x9A,0xD1,0x69,0x9F,0xD1,0xDA,0x2E,0xC3, + 0x90,0x01,0xA2,0xB9,0x6B,0x4E,0x2A,0x66,0x9D,0xDA,0xAE,0xA6,0xEA,0x2A,0xD3,0x68, + 0x2F,0x0C,0x0C,0x9C,0xD2,0x8C,0x4A,0xED,0xE2,0x9E,0x57,0x65,0x9D,0x09,0x87,0xA3, + 0xB4,0xC4,0x32,0x5D,0xC9,0xD4,0x32,0x2B,0xB1,0xE0,0x71,0x1E,0x64,0x4D,0xE6,0x90, + 0x71,0xE3,0x1E,0x40,0xED,0x7D,0xF3,0x84,0x0E,0xED,0xC8,0x78,0x76,0xAE,0xC0,0x71, + 0x27,0x72,0xBB,0x05,0xEA,0x02,0x64,0xFB,0xF3,0x48,0x6B,0xB5,0x42,0x93,0x3F,0xED, + 0x9F,0x13,0x53,0xD2,0xF7,0xFE,0x2A,0xEC,0x1D,0x47,0x25,0xDB,0x3C,0x91,0x86,0xC6, + 0x8E,0xF0,0x11,0xFD,0x23,0x74,0x36,0xF7,0xA4,0xF5,0x9E,0x7A,0x7E,0x53,0x50,0x44, + 0xD4,0x47,0xCA,0xD3,0xEB,0x38,0x6D,0xE6,0xD9,0x71,0x94,0x7F,0x4A,0xC6,0x69,0x4B, + 0x11,0xF4,0x52,0xEA,0x22,0xFE,0x8A,0xB0,0x36,0x67,0x8B,0x59,0xE8,0xE6,0x80,0x2A, + 0xEB,0x65,0x04,0x13,0xEE,0xEC,0xDC,0x9E,0x5F,0xB1,0xEC,0x05,0x6A,0x59,0xE6,0x9F, + 0x5E,0x59,0x6B,0x89,0xBF,0xF7,0x1A,0xCA,0x44,0xF9,0x5B,0x6A,0x71,0x85,0x03,0xE4, + 0x29,0x62,0xE0,0x70,0x6F,0x41,0xC4,0xCF,0xB2,0xB1,0xCC,0xE3,0x7E,0xA6,0x07,0xA8, + 0x87,0xE7,0x7F,0x84,0x93,0xDB,0x52,0x4B,0x6C,0xEC,0x7E,0xDD,0xD4,0x24,0x48,0x10, + 0x69,0x9F,0x04,0x60,0x74,0xE6,0x48,0x18,0xF3,0xE4,0x2C,0xB9,0x4F,0x2E,0x50,0x7A, + 0xDF,0xD4,0x54,0x69,0x2B,0x8B,0xA7,0xF3,0xCE,0xFF,0x1F,0xF3,0x3E,0x26,0x01,0x39, + 0x17,0x95,0x84,0x89,0xB0,0xF0,0x4C,0x4B,0x82,0x91,0x9F,0xC4,0x4B,0xAC,0x9D,0xA5, + 0x74,0xAF,0x17,0x25,0xC9,0xCA,0x32,0xD3,0xBC,0x89,0x8A,0x84,0x89,0xCC,0x0D,0xAE, + 0x7C,0xA2,0xDB,0x9C,0x6A,0x78,0x91,0xEE,0xEA,0x76,0x5D,0x4E,0x87,0x60,0xF5,0x69, + 0x15,0x67,0xD4,0x02,0xCF,0xAF,0x48,0x36,0x07,0xEA,0xBF,0x6F,0x66,0x2D,0x06,0x8F, + 0xC4,0x9A,0xFE,0xF9,0xF6,0x90,0x87,0x75,0xB8,0xF7,0xAD,0x0F,0x76,0x10,0x5A,0x3D, + 0x59,0xB0,0x2E,0xB3,0xC7,0x35,0x2C,0xCC,0x70,0x56,0x2B,0xCB,0xE3,0x37,0x96,0xC5, + 0x2F,0x46,0x1B,0x8A,0x22,0x46,0xC7,0x88,0xA7,0x26,0x32,0x98,0x61,0xDF,0x86,0x22, + 0x8A,0xF4,0x1C,0x2F,0x87,0xA1,0x09,0xAA,0xCC,0xA9,0xAE,0xD3,0xBD,0x00,0x45,0x1C, + 0x9A,0x54,0x87,0x86,0x52,0x87,0xEF,0xFF,0x1E,0x8F,0xA1,0x8F,0xC1,0x89,0x5C,0x35, + 0x1B,0xDA,0x2D,0x3A,0x2C,0x16,0xB2,0xC2,0xF1,0x56,0xE2,0x78,0xC1,0x6B,0x63,0x97, + 0xC5,0x56,0x8F,0xC9,0x32,0x7F,0x2C,0xAA,0xAF,0xA6,0xA8,0xAC,0x20,0x91,0x22,0x88, + 0xDE,0xE4,0x60,0x8B,0xF9,0x4B,0x42,0x25,0x1A,0xE3,0x7F,0x9C,0x2C,0x19,0x89,0x3A, + 0x7E,0x05,0xD4,0x36,0xCC,0x69,0x58,0xC2,0xC1,0x32,0x8B,0x2F,0x90,0x85,0xEB,0x7A, + 0x39,0x50,0xA5,0xA1,0x27,0x92,0xC5,0x66,0xB0,0x20,0x4F,0x58,0x7E,0x55,0x83,0x43, + 0x2B,0x45,0xE2,0x9C,0xE4,0xD8,0x12,0x90,0x2C,0x16,0x83,0x56,0x16,0x79,0x03,0xB3, + 0xAD,0x2D,0x61,0x18,0x1A,0x13,0x1F,0x37,0xE2,0xE1,0x9C,0x73,0x7B,0x80,0xD5,0xFD, + 0x2D,0x51,0x87,0xFC,0x7B,0xAA,0xD7,0x1F,0x2C,0x7A,0x8E,0xAF,0xF4,0x8D,0xBB,0xCD, + 0x95,0x11,0x7C,0x72,0x0B,0xEE,0x6F,0xE2,0xB9,0xAF,0xDE,0x37,0x83,0xDE,0x8C,0x8D, + 0x62,0x05,0x67,0xB7,0x96,0xC6,0x8D,0x56,0xB6,0x0D,0xD7,0x62,0xBA,0xD6,0x46,0x36, + 0xBD,0x8E,0xC8,0xE6,0xEA,0x2A,0x6C,0x10,0x14,0xFF,0x6B,0x5B,0xFA,0x82,0x3C,0x46, + 0xB1,0x30,0x43,0x46,0x51,0x8A,0x7D,0x9B,0x92,0x3E,0x83,0x79,0x5B,0x55,0x5D,0xB2, + 0x6C,0x5E,0xCE,0x90,0x62,0x8E,0x53,0x98,0xC9,0x0D,0x6D,0xE5,0x2D,0x57,0xCD,0xC5, + 0x81,0x57,0xBA,0xE1,0xE8,0xB8,0x8F,0x72,0xE5,0x4F,0x13,0xDC,0xEA,0x9D,0x71,0x15, + 0x10,0xB2,0x11,0x88,0xD5,0x09,0xD4,0x7F,0x5B,0x65,0x7F,0x2C,0x3B,0x38,0x4C,0x11, + 0x68,0x50,0x8D,0xFB,0x9E,0xB0,0x59,0xBF,0x94,0x80,0x89,0x4A,0xC5,0x1A,0x18,0x12, + 0x89,0x53,0xD1,0x4A,0x10,0x29,0xE8,0x8C,0x1C,0xEC,0xB6,0xEA,0x46,0xC7,0x17,0x8B, + 0x25,0x15,0x31,0xA8,0xA2,0x6B,0x43,0xB1,0x9D,0xE2,0xDB,0x0B,0x87,0x9B,0xB0,0x11, + 0x04,0x0E,0x71,0xD2,0x29,0x77,0x89,0x82,0x0A,0x66,0x41,0x7F,0x1D,0x0B,0x48,0xFF, + 0x72,0xBB,0x24,0xFD,0xC2,0x48,0xA1,0x9B,0xFE,0x7B,0x7F,0xCE,0x88,0xDB,0x86,0xD9, + 0x85,0x3B,0x1C,0xB0,0xDC,0xA8,0x33,0x07,0xBF,0x51,0x2E,0xE3,0x0E,0x9A,0x00,0x97, + 0x1E,0x06,0xC0,0x97,0x43,0x9D,0xD8,0xB6,0x45,0xC4,0x86,0x67,0x5F,0x00,0xF8,0x88, + 0x9A,0xA4,0x52,0x9E,0xC7,0xAA,0x8A,0x83,0x75,0xEC,0xC5,0x18,0xAE,0xCE,0xC3,0x2F, + 0x1A,0x2B,0xF9,0x18,0xFF,0xAE,0x1A,0xF5,0x53,0x0B,0xB5,0x33,0x51,0xA7,0xFD,0xE8, + 0xA8,0xE1,0xA2,0x64,0xB6,0x22,0x17,0x43,0x80,0xCC,0x0A,0xD8,0xAE,0x3B,0xBA,0x40, + 0xD7,0xD9,0x92,0x4A,0x89,0xDF,0x04,0x10,0xEE,0x9B,0x18,0x2B,0x6A,0x77,0x69,0x8A, + 0x68,0xF4,0xF9,0xB9,0xA2,0x21,0x15,0x6E,0xE6,0x1E,0x3B,0x03,0x62,0x30,0x9B,0x60, + 0x41,0x7E,0x25,0x9B,0x9E,0x8F,0xC5,0x52,0x10,0x08,0xF8,0xC2,0x69,0xA1,0x21,0x11, + 0x88,0x37,0x5E,0x79,0x35,0x66,0xFF,0x10,0x42,0x18,0x6E,0xED,0x97,0xB6,0x6B,0x1C, + 0x4E,0x36,0xE5,0x6D,0x7D,0xB4,0xE4,0xBF,0x20,0xB9,0xE0,0x05,0x3A,0x69,0xD5,0xB8, + 0xE3,0xD5,0xDC,0xE0,0xB9,0xAC,0x53,0x3E,0x07,0xA4,0x57,0xAD,0x77,0xFF,0x48,0x18, + 0x76,0x2A,0xAC,0x49,0x2A,0x8E,0x47,0x75,0x6D,0x9F,0x67,0x63,0x30,0x35,0x8C,0x39, + 0x05,0x39,0xD5,0x6F,0x64,0x3A,0x5B,0xAD,0xCA,0x0B,0xBB,0x82,0x52,0x99,0x45,0xB1, + 0x93,0x36,0x36,0x99,0xAF,0x13,0x20,0x44,0x36,0xD8,0x02,0x44,0x09,0x39,0x92,0x85, + 0xFF,0x4A,0x4A,0x97,0x87,0xA6,0x63,0xD7,0xC7,0xB5,0xB5,0x24,0xED,0x0F,0xB4,0x6F, + 0x0C,0x58,0x52,0x14,0xD9,0xA6,0x7B,0xD3,0x79,0xBC,0x38,0x58,0xA1,0xBD,0x3B,0x84, + 0x06,0xD8,0x1A,0x06,0xFD,0x6B,0xA8,0xEA,0x4B,0x69,0x28,0x04,0x37,0xAD,0x82,0x99, + 0xFB,0x0E,0x1B,0x85,0xBD,0xA8,0x5D,0x73,0xCD,0xDC,0x58,0x75,0x0A,0xBE,0x63,0x6C, + 0x48,0xE7,0x4C,0xE4,0x30,0x2B,0x04,0x60,0xB9,0x15,0xD8,0xDA,0x86,0x81,0x75,0x8F, + 0x96,0xD4,0x8D,0x1C,0x5D,0x70,0x85,0x7C,0x1C,0x67,0x7B,0xD5,0x08,0x67,0xA6,0xCE, + 0x4B,0x0A,0x66,0x70,0xB7,0xE5,0x63,0xD4,0x5B,0x8A,0x82,0xEA,0x10,0x67,0xCA,0xE2, + 0xF4,0xEF,0x17,0x85,0x2F,0x2A,0x5F,0x8A,0x97,0x82,0xF8,0x6A,0xD6,0x34,0x10,0xEA, + 0xEB,0xC9,0x5C,0x3C,0xE1,0x49,0xF8,0x46,0xEB,0xDE,0xBD,0xF6,0xA9,0x92,0xF1,0xAA, + 0xA6,0xA0,0x18,0xB0,0x3A,0xD3,0x0F,0x1F,0xF3,0x6F,0xFF,0x31,0x45,0x43,0x44,0xD3, + 0x50,0x9A,0xF7,0x88,0x09,0x96,0xC1,0xCE,0x76,0xCC,0xF2,0x2C,0x2C,0xBA,0xAD,0x82, + 0x77,0x8F,0x18,0x84,0xC0,0xD2,0x07,0x9C,0x36,0x90,0x83,0x4E,0x0B,0xA5,0x4F,0x43, + 0x3E,0x04,0xAB,0x78,0x4F,0xD6,0xFB,0x09,0x01,0x24,0x90,0xDA,0x6F,0x3C,0x3A,0x61, + 0x0D,0x7F,0x69,0x4A,0xEB,0x2B,0x30,0x02,0xB4,0xDB,0xE0,0x84,0xA9,0xEC,0xD7,0x35, + 0xBF,0x37,0x7D,0x85,0x58,0xCE,0xA9,0x4E,0xE4,0x80,0xC7,0xA8,0xD3,0x30,0x67,0x48, + 0xEB,0x29,0xAF,0x2F,0x74,0x6A,0xB4,0xA7,0x3F,0x0F,0x3F,0x92,0xAF,0xF3,0xCA,0xAC, + 0xAF,0x4B,0xD9,0x94,0xC0,0x43,0xCA,0x81,0x0D,0x2F,0x48,0xA1,0xB0,0x27,0xD5,0xD2, + 0xEF,0x4B,0x05,0x85,0xA3,0xDE,0x4D,0x93,0x30,0x3C,0xF0,0xBB,0x4A,0x8F,0x30,0x27, + 0x4C,0xEB,0xE3,0x3E,0x64,0xED,0x9A,0x2F,0x3B,0xF1,0x82,0xF0,0xBA,0xF4,0xCF,0x7F, + 0x40,0xCB,0xB0,0xE1,0x7F,0xBC,0xAA,0x57,0xD3,0xC9,0x74,0xF2,0xFA,0x43,0x0D,0x22, + 0xD0,0xF4,0x77,0x4E,0x93,0xD7,0x85,0x70,0x1F,0x99,0xBF,0xB6,0xDE,0x35,0xF1,0x30, + 0xA7,0x5E,0x71,0xF0,0x6B,0x01,0x2D,0x7B,0x64,0xF0,0x33,0x53,0x0A,0x39,0x88,0xF3, + 0x6B,0x3A,0xA6,0x6B,0x35,0xD2,0x2F,0x43,0xCD,0x02,0xFD,0xB5,0xE9,0xBC,0x5B,0xAA, + 0xD8,0xA4,0x19,0x7E,0x0E,0x5D,0x94,0x81,0x9E,0x6F,0x77,0xAD,0xD6,0x0E,0x74,0x93, + 0x96,0xE7,0xC4,0x18,0x5F,0xAD,0xF5,0x19 +}; diff --git a/BootLoader/source/key2.h b/BootLoader/source/key2.h new file mode 100644 index 0000000..72b8ef2 --- /dev/null +++ b/BootLoader/source/key2.h @@ -0,0 +1,350 @@ +const unsigned char gEncrDataTwl[] = { + 0x59, 0xaa, 0x56, 0x8e, 0x90, 0xd7, 0x11, 0x55, 0x4d, 0xea, 0xbf, 0xfe, + 0xbd, 0x0d, 0x75, 0x91, 0xf7, 0x85, 0x39, 0x98, 0xd0, 0x9c, 0xc3, 0x58, + 0xc4, 0x15, 0x6f, 0xf1, 0x90, 0xf9, 0xe4, 0xc3, 0x8e, 0xc0, 0x9b, 0x0e, + 0x5d, 0xe1, 0x87, 0x94, 0xb9, 0x07, 0x2c, 0xba, 0xa6, 0x4f, 0x75, 0x74, + 0xc1, 0xe3, 0x1c, 0x86, 0xe6, 0xed, 0xf8, 0x09, 0x3b, 0xbb, 0x37, 0x7a, + 0x4e, 0xf0, 0xf0, 0x92, 0xf6, 0x55, 0xfa, 0x47, 0xfb, 0x1b, 0xc5, 0x16, + 0x06, 0x74, 0x4e, 0x56, 0x20, 0xdd, 0xb6, 0xd1, 0x42, 0xcf, 0xcf, 0xf1, + 0x55, 0x7e, 0x17, 0x18, 0xa1, 0x93, 0xff, 0x09, 0xda, 0x36, 0xa6, 0x9a, + 0x43, 0x3d, 0xf4, 0x65, 0xed, 0x40, 0x97, 0x6c, 0xd5, 0xa6, 0xdd, 0x6d, + 0x6c, 0x23, 0xbf, 0x94, 0xe7, 0x51, 0xa6, 0x68, 0x3c, 0xe8, 0xe6, 0x65, + 0xd6, 0xbc, 0x9e, 0x92, 0x78, 0x26, 0x46, 0xa1, 0x73, 0xdc, 0xe5, 0x36, + 0x8e, 0xcd, 0xec, 0xa1, 0xf1, 0xee, 0x8b, 0x68, 0xf4, 0xac, 0xc1, 0xdc, + 0xc8, 0x84, 0x95, 0x31, 0xe8, 0xed, 0xc7, 0x5e, 0xe4, 0x5a, 0x37, 0xca, + 0xec, 0x55, 0xbe, 0x2a, 0xfc, 0xf6, 0x45, 0x67, 0xa9, 0xb4, 0x7d, 0x7d, + 0x9b, 0x6e, 0xe9, 0x2c, 0xff, 0x3f, 0xeb, 0x69, 0xb7, 0x2e, 0x68, 0xa8, + 0x94, 0xef, 0x7b, 0xbd, 0x88, 0x93, 0x15, 0x66, 0x3a, 0xb7, 0x7f, 0xfe, + 0x1d, 0xc3, 0x89, 0x08, 0xd7, 0x74, 0x59, 0xfa, 0xaf, 0x91, 0x41, 0x9e, + 0x57, 0xd5, 0x67, 0x84, 0xba, 0x00, 0xe9, 0x63, 0x58, 0x07, 0x4d, 0xec, + 0xdf, 0xc6, 0xda, 0x1e, 0x62, 0x52, 0xd9, 0x14, 0xbc, 0x03, 0xc3, 0xb0, + 0xa5, 0xfd, 0xb7, 0x27, 0xde, 0xb1, 0x6f, 0x1b, 0x7c, 0x72, 0x4a, 0xcd, + 0x09, 0xe5, 0x82, 0x70, 0xd3, 0x9f, 0xb6, 0xd6, 0xa4, 0x6a, 0x2f, 0xc2, + 0x32, 0xbd, 0xb5, 0x39, 0xe4, 0xea, 0xb9, 0x71, 0x1c, 0x70, 0x67, 0x21, + 0x92, 0x21, 0xac, 0xf4, 0x9e, 0x63, 0xe8, 0x5e, 0x83, 0x02, 0xcc, 0x0c, + 0xf8, 0xf8, 0x9e, 0x87, 0x89, 0xfc, 0x03, 0x85, 0xfa, 0xcc, 0x77, 0x07, + 0x44, 0x5f, 0x4d, 0xe5, 0x19, 0xd3, 0x12, 0xee, 0xca, 0xe1, 0xe0, 0xbf, + 0x1e, 0xbe, 0xe7, 0x12, 0x1f, 0x6a, 0x93, 0x1e, 0x38, 0x4b, 0xa7, 0x9f, + 0x81, 0xa9, 0x77, 0x85, 0x0c, 0xc6, 0x39, 0x02, 0x55, 0xd2, 0x62, 0x56, + 0x19, 0x85, 0xa6, 0x38, 0x85, 0xe1, 0x2d, 0x3c, 0x38, 0x3b, 0x5b, 0xa0, + 0x24, 0x18, 0xe9, 0x29, 0x6c, 0x9f, 0xe4, 0x4d, 0x4e, 0x23, 0x5f, 0xb1, + 0xe2, 0xa0, 0x6f, 0x97, 0xb2, 0x41, 0xd1, 0xea, 0xdb, 0xa7, 0x37, 0x81, + 0xeb, 0x06, 0x8d, 0x77, 0xc2, 0x68, 0xfc, 0x5a, 0x65, 0x97, 0x33, 0x58, + 0xa1, 0xb8, 0x35, 0x0f, 0xf4, 0x25, 0xbc, 0x3b, 0x4f, 0x18, 0x0f, 0x0e, + 0x60, 0x25, 0x3d, 0xd8, 0x77, 0x1a, 0xd0, 0x8a, 0xb0, 0x61, 0x57, 0x16, + 0x0b, 0x55, 0xf2, 0x58, 0xb9, 0x91, 0x52, 0x30, 0x33, 0xab, 0x29, 0x9b, + 0x03, 0x62, 0xe5, 0xcc, 0xdf, 0x6e, 0x62, 0x86, 0x9d, 0x76, 0xe5, 0xdd, + 0x6f, 0xca, 0x3e, 0x75, 0xd8, 0x88, 0x58, 0x06, 0x8d, 0xa4, 0x58, 0xf5, + 0xaa, 0x7c, 0xce, 0x17, 0xdd, 0xde, 0xca, 0x0a, 0x72, 0x87, 0x6f, 0x29, + 0x6c, 0x0c, 0xe9, 0xc0, 0x3d, 0x32, 0x2e, 0x55, 0xf3, 0xa7, 0x27, 0xda, + 0xfc, 0x86, 0x0c, 0x9e, 0x33, 0x83, 0xb5, 0x47, 0xeb, 0xe8, 0xf6, 0xc9, + 0xf4, 0x24, 0x72, 0xee, 0xaf, 0xf8, 0xb5, 0x59, 0x70, 0x06, 0x85, 0x71, + 0xbb, 0x3c, 0xbe, 0xbb, 0x2c, 0x24, 0xad, 0x67, 0xba, 0x42, 0xb9, 0xee, + 0x68, 0xec, 0x0b, 0xe6, 0x5b, 0x26, 0x0f, 0x2b, 0xb6, 0x3a, 0x93, 0x4f, + 0x9f, 0xe6, 0x9f, 0xb9, 0x1a, 0xa0, 0xb9, 0x51, 0x1c, 0x8d, 0x66, 0x37, + 0xd2, 0x50, 0xcc, 0xae, 0x10, 0x30, 0x16, 0x60, 0x56, 0x3b, 0x99, 0x0e, + 0x90, 0x7b, 0x28, 0xde, 0x93, 0xf4, 0x16, 0x87, 0x1f, 0xd0, 0x9b, 0xc2, + 0x33, 0x42, 0x2c, 0x2c, 0xf1, 0x36, 0xc3, 0x39, 0xf8, 0x4f, 0xa4, 0x1e, + 0x00, 0x43, 0xb1, 0xac, 0xdf, 0x08, 0xbb, 0xfe, 0x5e, 0x2a, 0xdc, 0x2a, + 0x10, 0xf3, 0x7b, 0xc5, 0x2f, 0x96, 0xc9, 0x1d, 0x51, 0x4f, 0xc0, 0xde, + 0x6e, 0x93, 0x9a, 0x35, 0x19, 0xb8, 0x58, 0xb5, 0x19, 0xba, 0xaf, 0x2a, + 0xb1, 0xb5, 0xb2, 0xff, 0xc1, 0x89, 0xbc, 0x3f, 0xd8, 0x8f, 0x34, 0x07, + 0x63, 0x60, 0xa5, 0xed, 0xdb, 0xff, 0x9e, 0xf5, 0x5b, 0x23, 0xc0, 0x1b, + 0x13, 0x96, 0xd4, 0x2f, 0x07, 0x51, 0x1b, 0xac, 0x90, 0x72, 0x71, 0x28, + 0x65, 0x98, 0xe1, 0xff, 0x6a, 0x9d, 0xe7, 0x30, 0x6d, 0xb1, 0x2c, 0x21, + 0xfa, 0xcb, 0xbc, 0x6a, 0x3c, 0x25, 0xe8, 0x50, 0x5c, 0x53, 0xd8, 0xd5, + 0xcb, 0xa2, 0x53, 0x53, 0xa5, 0x64, 0x3f, 0x78, 0x61, 0x77, 0x1d, 0x8d, + 0x16, 0xe4, 0xe4, 0xa1, 0x32, 0x9c, 0x00, 0x52, 0x5f, 0x2a, 0xd7, 0xf5, + 0x3c, 0xfd, 0x09, 0xd7, 0x1b, 0x3b, 0x99, 0x01, 0x4d, 0xdc, 0x91, 0xe4, + 0x6d, 0xe8, 0x9e, 0xa3, 0x18, 0xad, 0x43, 0x27, 0xba, 0xc1, 0x5f, 0x37, + 0xa6, 0x12, 0x61, 0xf5, 0x1c, 0x63, 0x0c, 0x25, 0x2d, 0x90, 0xf8, 0x52, + 0xcb, 0x2c, 0x37, 0x4b, 0xde, 0x1e, 0x6c, 0x36, 0x1d, 0x47, 0xf5, 0xdf, + 0x87, 0xca, 0x79, 0x98, 0x80, 0x09, 0x59, 0xd7, 0x14, 0xfd, 0xf7, 0xf9, + 0xf4, 0xce, 0x69, 0x23, 0xd2, 0xf8, 0xc4, 0xee, 0xa0, 0x7e, 0xf8, 0x36, + 0x8e, 0x35, 0x93, 0x45, 0x82, 0xae, 0x0d, 0xfc, 0x65, 0xbc, 0xaa, 0xf5, + 0x58, 0xa9, 0x65, 0xba, 0xc6, 0x08, 0x4b, 0x63, 0xc3, 0x3f, 0xa6, 0x8a, + 0xf4, 0xc1, 0x9b, 0x8f, 0x02, 0x45, 0x1b, 0x13, 0x78, 0x28, 0x9f, 0xd6, + 0x53, 0xb1, 0xc2, 0x7e, 0x4e, 0x71, 0x17, 0xe7, 0x55, 0x09, 0x62, 0xc7, + 0xad, 0xd5, 0x91, 0x1a, 0xc0, 0xfa, 0x49, 0x4a, 0xef, 0x00, 0xd6, 0xf6, + 0xf1, 0xd0, 0xc9, 0x40, 0x1b, 0xb1, 0xfd, 0x0e, 0xd3, 0x95, 0xf1, 0xcd, + 0x95, 0x60, 0x08, 0x73, 0xd2, 0xe0, 0x56, 0xfa, 0xd0, 0x65, 0x51, 0xfd, + 0xc4, 0x48, 0xd1, 0xaa, 0x5a, 0xba, 0xcb, 0x8f, 0x76, 0x22, 0xe3, 0x60, + 0x6f, 0x4a, 0x3c, 0x86, 0x35, 0xee, 0xe9, 0x88, 0x9a, 0x4a, 0x36, 0x34, + 0x74, 0xe3, 0x6d, 0x3f, 0xe4, 0x2a, 0x93, 0x0b, 0xe2, 0xc6, 0x47, 0x4d, + 0xf2, 0xb6, 0x8e, 0x78, 0x14, 0x91, 0x61, 0xcf, 0xfa, 0xb6, 0x1b, 0x39, + 0xca, 0x88, 0x0c, 0x04, 0x65, 0xd3, 0x3b, 0xd1, 0xc6, 0xda, 0xe5, 0xf4, + 0xe9, 0x1a, 0x38, 0x0f, 0xa5, 0xca, 0x32, 0x29, 0x78, 0x6c, 0x91, 0x9d, + 0xd8, 0xc1, 0x8c, 0x3d, 0x6e, 0x82, 0x49, 0x10, 0x38, 0x4c, 0x95, 0xe3, + 0xf1, 0x69, 0x30, 0x2e, 0x3e, 0xbf, 0xaf, 0x7d, 0x5e, 0x51, 0x3c, 0x6a, + 0x15, 0x04, 0xbd, 0x8f, 0xcf, 0xeb, 0x3f, 0xe0, 0xe0, 0xa7, 0xb3, 0x3e, + 0xf3, 0xf7, 0xd8, 0x1d, 0x15, 0x74, 0xef, 0x4e, 0x5b, 0xa0, 0x1e, 0x3a, + 0x45, 0xec, 0x98, 0x8b, 0xe4, 0x0c, 0xfb, 0x77, 0xfd, 0xcf, 0xde, 0x88, + 0x4d, 0x42, 0x18, 0x81, 0x14, 0x0d, 0xe2, 0x20, 0x4e, 0xcf, 0x0d, 0x3b, + 0xc8, 0x41, 0x36, 0x9d, 0x99, 0xab, 0x47, 0xcb, 0x55, 0xf0, 0x79, 0x77, + 0x32, 0x85, 0xa4, 0xe4, 0x11, 0x14, 0x42, 0x8d, 0x03, 0x8c, 0x76, 0xba, + 0x05, 0xcf, 0xe8, 0x40, 0x47, 0xcf, 0xbd, 0xe7, 0x22, 0xe6, 0x72, 0xce, + 0xa0, 0x13, 0xe4, 0x59, 0x5e, 0x68, 0xc2, 0x53, 0x7a, 0x4d, 0x4b, 0x4c, + 0xcd, 0xbf, 0xe2, 0xb0, 0xa3, 0x63, 0x77, 0xf2, 0x1e, 0xc3, 0x21, 0xca, + 0xd2, 0xb6, 0x7b, 0x01, 0x79, 0x02, 0x43, 0xec, 0x6d, 0x98, 0x97, 0x86, + 0x27, 0x41, 0x67, 0xe7, 0x04, 0xcf, 0x71, 0x0e, 0xfc, 0xc8, 0x3d, 0x32, + 0x99, 0x35, 0x4d, 0x2c, 0x94, 0xd7, 0x82, 0xb5, 0x2e, 0x20, 0x73, 0xd8, + 0xa4, 0xf9, 0xae, 0x6c, 0xd6, 0x12, 0x57, 0xe9, 0x44, 0x86, 0x6a, 0x9e, + 0xe0, 0x72, 0x84, 0x97, 0xb3, 0x8d, 0x56, 0x28, 0x66, 0xdb, 0xec, 0x25, + 0xbf, 0x01, 0x11, 0x76, 0x9b, 0xe1, 0x43, 0x8d, 0x6d, 0x0b, 0xfa, 0x3d, + 0x45, 0x15, 0x4a, 0xb4, 0xac, 0x76, 0x2a, 0x4a, 0xfb, 0x8d, 0xa5, 0x03, + 0xe4, 0x36, 0xe6, 0xd9, 0xfd, 0xc1, 0x20, 0x63, 0xe3, 0x5c, 0x9a, 0x0e, + 0x0f, 0x99, 0x49, 0xc6, 0x10, 0x9a, 0x08, 0x47, 0xff, 0x3d, 0xaa, 0x0c, + 0x9f, 0x46, 0x57, 0x5a, 0xe5, 0xc5, 0x24, 0xc5, 0xf1, 0xca, 0x1a, 0xa2, + 0xb0, 0x29, 0x78, 0xdd, 0x7a, 0x72, 0x49, 0x54, 0xac, 0xc4, 0x22, 0x04, + 0x97, 0xa2, 0xa1, 0x1a, 0x2f, 0x57, 0xfd, 0x9b, 0xaf, 0xc9, 0x30, 0x10, + 0x4a, 0xf4, 0x5e, 0x52, 0xf8, 0x25, 0x32, 0x48, 0xcb, 0x02, 0x6c, 0x3b, + 0xa7, 0xe3, 0xbd, 0xe9, 0x54, 0xd5, 0xbe, 0x46, 0x6b, 0xea, 0x0b, 0x43, + 0x13, 0x1d, 0x6f, 0x9c, 0xf5, 0xeb, 0x0e, 0xba, 0x28, 0x4f, 0x98, 0x84, + 0xb2, 0x19, 0x9c, 0xfe, 0xa0, 0x4a, 0xf6, 0x07, 0xcc, 0x0c, 0x8f, 0x75, + 0x6a, 0x16, 0xa1, 0x1c, 0x4e, 0x42, 0x51, 0xdc, 0x17, 0xb0, 0xa4, 0x2c, + 0x86, 0x87, 0x55, 0xf5, 0x7a, 0x5a, 0xd0, 0x0d, 0x4b, 0x9f, 0xb9, 0xcb, + 0xf3, 0x23, 0x5b, 0xaa, 0x81, 0x0e, 0x74, 0x56, 0x96, 0xbb, 0x65, 0x14, + 0x3e, 0xb2, 0x17, 0x53, 0x7e, 0x71, 0xf1, 0x9b, 0xfd, 0x1c, 0x5c, 0xfe, + 0xee, 0x6b, 0x58, 0xc7, 0xb5, 0x82, 0xed, 0x14, 0x47, 0xb0, 0x62, 0xe8, + 0xad, 0x34, 0x9c, 0xe6, 0x12, 0x29, 0x3b, 0x91, 0x2b, 0x83, 0xe6, 0x5c, + 0xd4, 0xf1, 0x5b, 0x7f, 0xe0, 0x58, 0xc8, 0x29, 0xa4, 0x17, 0x76, 0xa0, + 0x95, 0x9d, 0xb1, 0xad, 0xa1, 0x01, 0xa2, 0xce, 0xd0, 0xa3, 0x14, 0x1e, + 0xb7, 0x22, 0x98, 0x9d, 0xcd, 0x7f, 0x8c, 0xb8, 0x0f, 0x5b, 0x5b, 0x36, + 0x3f, 0xce, 0xca, 0xce, 0x5b, 0x54, 0x8b, 0xbd, 0xde, 0x82, 0x7e, 0xf1, + 0xf9, 0xa0, 0x30, 0xfe, 0xbd, 0xe7, 0x35, 0x84, 0x29, 0x1e, 0x41, 0x8e, + 0x55, 0x3f, 0xf7, 0x40, 0x23, 0xaa, 0x2d, 0x5a, 0xe5, 0xc4, 0x32, 0x9e, + 0xbf, 0x22, 0xb0, 0xc1, 0xe7, 0x8c, 0x7d, 0x5d, 0x0b, 0x28, 0xb4, 0x57, + 0x8e, 0xe7, 0x56, 0x3d, 0x1f, 0x35, 0x1e, 0x98, 0xa9, 0x0d, 0xd7, 0xb7, + 0x20, 0xe2, 0x89, 0x90, 0x04, 0xa7, 0x56, 0xea, 0x84, 0x16, 0x6f, 0xff, + 0xa9, 0x38, 0x5e, 0xa0, 0xaf, 0x2d, 0xc1, 0xb6, 0xc1, 0x77, 0x72, 0xe1, + 0x21, 0xc7, 0x2f, 0x3f, 0x85, 0x51, 0x4b, 0x83, 0xca, 0x33, 0x50, 0xb1, + 0x4c, 0x58, 0x0c, 0x54, 0x7c, 0x70, 0xfe, 0x23, 0xef, 0xc7, 0xc7, 0xaf, + 0xaf, 0xbf, 0xe5, 0x7b, 0x05, 0x90, 0x6c, 0x7a, 0x9f, 0x66, 0xb9, 0xc6, + 0x44, 0xd5, 0x99, 0x6c, 0xd5, 0xac, 0x74, 0xce, 0x00, 0x49, 0x4b, 0xcf, + 0x51, 0x01, 0xda, 0x24, 0xc5, 0x42, 0xba, 0x6f, 0x8a, 0x73, 0x20, 0x11, + 0xbc, 0x4a, 0x4f, 0xdb, 0xa6, 0x40, 0x27, 0xbc, 0x93, 0xa3, 0x30, 0xb2, + 0xcc, 0x6e, 0x78, 0xa0, 0x28, 0x7d, 0xe7, 0x34, 0x11, 0x4c, 0x00, 0x8b, + 0x04, 0x3d, 0x93, 0x7f, 0x2a, 0x3c, 0x67, 0x56, 0xad, 0xc5, 0xdd, 0x2a, + 0x75, 0xe1, 0x96, 0x02, 0x8d, 0x66, 0x0e, 0xd8, 0xc1, 0x83, 0xdf, 0x27, + 0x42, 0xc4, 0x47, 0x18, 0x24, 0xac, 0x99, 0x8b, 0x22, 0x28, 0x68, 0x74, + 0xb2, 0x7e, 0x58, 0x19, 0x19, 0xda, 0xd4, 0x96, 0x36, 0x26, 0xc7, 0x53, + 0x37, 0xdb, 0x53, 0xa5, 0xd3, 0x98, 0xb4, 0x65, 0x80, 0xde, 0x73, 0xcb, + 0x97, 0x7e, 0x59, 0x80, 0xf6, 0x25, 0x60, 0x6f, 0x77, 0x20, 0x4c, 0xc7, + 0x35, 0xc6, 0x80, 0xe3, 0x56, 0x2c, 0xba, 0x62, 0xf7, 0x56, 0xf9, 0x63, + 0x3e, 0xf9, 0x91, 0x7b, 0x9c, 0x35, 0x02, 0x04, 0xd8, 0x3d, 0x35, 0xfd, + 0xb7, 0x85, 0xba, 0x04, 0x19, 0x7f, 0xb9, 0xe6, 0x6a, 0x65, 0x51, 0x9e, + 0xde, 0x21, 0xec, 0xf0, 0x6b, 0xfd, 0x41, 0x90, 0xdc, 0x32, 0x08, 0x4d, + 0x9b, 0x43, 0x2a, 0x61, 0x5b, 0x35, 0x61, 0xc1, 0xfd, 0xa2, 0xde, 0x30, + 0xd3, 0x93, 0xc6, 0x0d, 0xad, 0x76, 0xac, 0xfb, 0xb0, 0xee, 0x85, 0x5f, + 0xde, 0x4e, 0x2b, 0xe8, 0x8f, 0x67, 0xa0, 0x12, 0x00, 0x3f, 0xcf, 0x04, + 0xe4, 0xb1, 0x2b, 0xa0, 0xda, 0xbb, 0x33, 0x5a, 0x58, 0x9b, 0x7c, 0x05, + 0xea, 0x2b, 0x7b, 0x40, 0x9c, 0xc3, 0xe0, 0x99, 0x9e, 0xe0, 0x91, 0x67, + 0xa5, 0x63, 0x6b, 0x9f, 0x15, 0xb6, 0x3c, 0xda, 0x17, 0x90, 0x8f, 0x05, + 0x7e, 0x61, 0x7c, 0xc7, 0x25, 0xdf, 0xbb, 0xd6, 0x96, 0xba, 0x45, 0xa8, + 0x84, 0xa0, 0x7d, 0x0f, 0x41, 0xdd, 0xba, 0xe5, 0x5a, 0x09, 0x3d, 0xe7, + 0x20, 0x22, 0xc6, 0x8e, 0x0d, 0xd5, 0xc5, 0x75, 0x38, 0x8c, 0x6e, 0x4f, + 0xa0, 0x42, 0xf7, 0x5e, 0xb1, 0x35, 0xe5, 0xfc, 0x93, 0x13, 0x58, 0x2b, + 0xa7, 0xe0, 0xfe, 0xff, 0x1a, 0xdd, 0x30, 0x27, 0x9e, 0x69, 0xdd, 0x05, + 0x18, 0xf7, 0x23, 0x5d, 0x9c, 0x64, 0xbe, 0x47, 0xf0, 0xa8, 0xe1, 0xf5, + 0xde, 0x67, 0x8a, 0xcc, 0x18, 0xed, 0x4a, 0x76, 0xa0, 0x23, 0x96, 0x55, + 0xd0, 0x84, 0x22, 0xce, 0xe1, 0xe2, 0x11, 0x80, 0x95, 0x61, 0x0d, 0x75, + 0x12, 0x86, 0xb9, 0x3c, 0x10, 0x9d, 0x4d, 0x39, 0x93, 0x42, 0x7d, 0x83, + 0xa5, 0xf4, 0xe4, 0xaa, 0x9b, 0x59, 0x22, 0x5e, 0xd3, 0xfd, 0xad, 0xf9, + 0xa0, 0xf2, 0xb2, 0x70, 0x86, 0x29, 0xcd, 0x71, 0x61, 0x98, 0xb8, 0x21, + 0x15, 0x5d, 0xf5, 0xde, 0x4d, 0x65, 0x27, 0x09, 0x8c, 0xed, 0xd0, 0xc8, + 0xe7, 0xed, 0x0b, 0x0c, 0x13, 0x9e, 0x78, 0xea, 0xf8, 0x3c, 0x10, 0xda, + 0xcd, 0xfc, 0xaf, 0x33, 0x96, 0x62, 0x31, 0x9c, 0xb6, 0x9d, 0xc8, 0x7a, + 0x35, 0xe6, 0xff, 0x75, 0xa8, 0x30, 0x98, 0xd4, 0xaa, 0xcf, 0x9c, 0xef, + 0xda, 0xb9, 0x64, 0xe8, 0x3b, 0xa6, 0x2f, 0xc1, 0xbd, 0x7e, 0x6b, 0xfc, + 0x1a, 0xef, 0x62, 0xad, 0x90, 0x5e, 0x7d, 0x29, 0x12, 0x4d, 0x76, 0x86, + 0x5c, 0x29, 0x7c, 0x61, 0x1d, 0x1e, 0x63, 0x97, 0x21, 0xcd, 0x77, 0xbd, + 0xc2, 0x32, 0x45, 0xca, 0x7a, 0xdc, 0x0b, 0x16, 0xa4, 0x10, 0xac, 0x37, + 0xba, 0xf5, 0xf6, 0xbc, 0x26, 0x66, 0x67, 0x2b, 0xb8, 0x2e, 0x22, 0xc0, + 0xea, 0x90, 0x78, 0xf0, 0x0d, 0x0f, 0x80, 0x69, 0x60, 0xd2, 0x89, 0xa5, + 0x1a, 0xb0, 0xcf, 0x5e, 0x57, 0x6f, 0x79, 0xdc, 0xd8, 0x2c, 0x51, 0x92, + 0xd6, 0x62, 0x41, 0xf9, 0xf7, 0x26, 0xf0, 0x59, 0x93, 0xe2, 0x76, 0x82, + 0x21, 0xf6, 0xab, 0x7a, 0xd2, 0x7b, 0x81, 0xcb, 0x8c, 0xe8, 0x87, 0x77, + 0x76, 0xce, 0xf2, 0xaa, 0x00, 0xdc, 0xec, 0xd1, 0xc1, 0x8d, 0xf8, 0x42, + 0x41, 0x8c, 0x35, 0xd1, 0x70, 0x97, 0xf4, 0x82, 0x2f, 0x3a, 0x2f, 0x4a, + 0x18, 0x8f, 0xac, 0x41, 0xfa, 0x29, 0xc2, 0x9d, 0x0a, 0xfa, 0x0c, 0x44, + 0xdd, 0xea, 0xc6, 0x2b, 0xd3, 0x2e, 0x28, 0xee, 0xca, 0x6e, 0x84, 0x90, + 0xec, 0xaf, 0xf4, 0x8f, 0xbd, 0xc7, 0xd1, 0x2d, 0xf6, 0x9a, 0xd2, 0x00, + 0xaa, 0x5c, 0x38, 0xc5, 0x11, 0x43, 0x7c, 0xf4, 0x0d, 0xbd, 0x57, 0x6d, + 0x42, 0x62, 0xa5, 0xd8, 0x05, 0xa7, 0xe9, 0x30, 0xc0, 0x81, 0x9b, 0xfc, + 0x30, 0xda, 0x16, 0x2f, 0x54, 0x61, 0x08, 0xaa, 0xf7, 0xc0, 0x1e, 0x4d, + 0xf2, 0xd4, 0xed, 0x5c, 0x96, 0x30, 0xad, 0x9f, 0xc5, 0xe3, 0xf0, 0x91, + 0xff, 0xf0, 0xb1, 0xe4, 0x93, 0x7b, 0x67, 0x11, 0xba, 0xef, 0xb7, 0xf4, + 0x29, 0x93, 0x6d, 0x32, 0x1f, 0x88, 0xd1, 0x6c, 0x7c, 0x5a, 0x7e, 0x0a, + 0xef, 0x6a, 0xe9, 0x23, 0x2c, 0xde, 0x4c, 0x68, 0x36, 0xcb, 0xaa, 0x1f, + 0xd3, 0x71, 0xce, 0x31, 0x8b, 0x2b, 0x51, 0x16, 0xe6, 0x65, 0xd1, 0x30, + 0xaf, 0xb8, 0xbe, 0x02, 0x21, 0x61, 0x36, 0xbc, 0x19, 0x7c, 0x0e, 0x9d, + 0x9c, 0xd6, 0xa9, 0xc7, 0x5c, 0x2f, 0xb6, 0x23, 0x4b, 0x64, 0x3b, 0x99, + 0x74, 0x83, 0x51, 0xda, 0x3e, 0xf8, 0xcf, 0x0f, 0xa3, 0x7a, 0xfb, 0xaa, + 0xd1, 0xe2, 0x09, 0x05, 0x3a, 0xf5, 0xa8, 0x61, 0x51, 0x59, 0xf6, 0xb3, + 0x3d, 0xe9, 0xa3, 0xc7, 0x3a, 0xe6, 0xff, 0x2d, 0x96, 0xaf, 0xe4, 0x41, + 0xb8, 0x7d, 0xca, 0xdf, 0x42, 0x16, 0x5c, 0xee, 0xd0, 0x9d, 0xa3, 0x74, + 0xa9, 0xae, 0xfd, 0x6d, 0x3b, 0x15, 0xb9, 0x89, 0x19, 0xa8, 0xf8, 0x48, + 0xfe, 0x3a, 0xf6, 0xd7, 0x44, 0x4b, 0x96, 0x07, 0x37, 0x4b, 0xf9, 0x33, + 0x62, 0x4f, 0x08, 0x38, 0xfc, 0x02, 0xfc, 0x8d, 0x3d, 0x65, 0x83, 0x02, + 0xed, 0xd7, 0x48, 0x40, 0x51, 0x99, 0x0a, 0x20, 0xb2, 0xda, 0x9d, 0xca, + 0xbf, 0xb7, 0xcf, 0xa8, 0x32, 0x67, 0x2f, 0x31, 0xa3, 0x00, 0xe3, 0xcb, + 0x09, 0x7e, 0x0a, 0xb0, 0x7a, 0x34, 0x7b, 0xfc, 0x1d, 0x97, 0x8c, 0xa6, + 0x17, 0xcb, 0x62, 0xc7, 0x28, 0xf4, 0xb8, 0x21, 0xdb, 0x51, 0xc9, 0xef, + 0x69, 0xb6, 0xac, 0x36, 0x90, 0x74, 0x90, 0xb7, 0xdb, 0xcb, 0xfd, 0xdb, + 0x17, 0x81, 0xed, 0x94, 0x4d, 0xe5, 0x4e, 0xe5, 0xf6, 0x01, 0x4a, 0x99, + 0x9f, 0x5e, 0xe0, 0x45, 0x70, 0x41, 0x45, 0xa2, 0x2b, 0x4e, 0xd6, 0xab, + 0xdc, 0x06, 0x15, 0x2d, 0x48, 0x88, 0x17, 0x43, 0x39, 0x94, 0xb4, 0x3a, + 0x23, 0xce, 0xbb, 0xda, 0x0e, 0xb0, 0x5c, 0x1e, 0x0d, 0x0b, 0x31, 0x8e, + 0x9b, 0x04, 0x80, 0x78, 0x75, 0x1c, 0x9b, 0x97, 0xac, 0xc7, 0xad, 0xde, + 0x2b, 0x7f, 0x48, 0xb2, 0x29, 0xae, 0x76, 0x59, 0x27, 0xee, 0x79, 0xb8, + 0x8e, 0x30, 0xe7, 0xf2, 0x84, 0x44, 0x40, 0x79, 0x25, 0xce, 0x13, 0x87, + 0x8e, 0xfa, 0x08, 0x18, 0x8d, 0x71, 0xac, 0xeb, 0xf2, 0x7c, 0xa6, 0x69, + 0x29, 0x1b, 0xd8, 0x02, 0xea, 0x64, 0x40, 0x7d, 0xa1, 0xb2, 0x05, 0xd3, + 0x2b, 0x9d, 0x98, 0xa4, 0x2c, 0xee, 0xc9, 0x2c, 0x52, 0x5a, 0xd9, 0x3e, + 0xd4, 0xcc, 0x6b, 0xf5, 0x11, 0x4a, 0x0a, 0x84, 0x4b, 0x6e, 0xa4, 0xab, + 0x16, 0x46, 0x31, 0xb2, 0x84, 0x32, 0x43, 0x43, 0xe3, 0x21, 0x09, 0x33, + 0x53, 0x9d, 0x93, 0x60, 0xd4, 0x18, 0xef, 0x71, 0xc8, 0xd1, 0x97, 0x2b, + 0x2d, 0xa0, 0xe3, 0xc3, 0xb7, 0x54, 0x5b, 0xa2, 0xbf, 0x92, 0xa0, 0x48, + 0x15, 0xef, 0x8e, 0x25, 0x02, 0x49, 0x35, 0x20, 0x9e, 0x1b, 0x52, 0xfa, + 0xf9, 0x33, 0x99, 0x31, 0x2c, 0x1b, 0x04, 0x92, 0x8d, 0x19, 0xdb, 0x7d, + 0xad, 0x61, 0x29, 0xe3, 0x5c, 0xb7, 0x94, 0xa6, 0x8b, 0x2e, 0xc5, 0x2e, + 0xbd, 0xe0, 0x60, 0xae, 0xea, 0x93, 0x08, 0x64, 0x98, 0x9e, 0x8e, 0xa1, + 0x2e, 0xf1, 0xe0, 0x31, 0x57, 0x87, 0xd4, 0x77, 0x81, 0x6d, 0xf5, 0xa6, + 0x4c, 0x9b, 0x89, 0x8d, 0x08, 0x96, 0xc5, 0x96, 0xbe, 0x59, 0xcc, 0xbd, + 0x58, 0x7b, 0x21, 0x08, 0x19, 0xc0, 0x55, 0x33, 0x80, 0x44, 0x0d, 0x8e, + 0x59, 0xf9, 0xe8, 0x00, 0x50, 0x98, 0xa2, 0x30, 0xa6, 0xfd, 0xa8, 0x46, + 0xc5, 0x05, 0x65, 0x59, 0xe7, 0x25, 0x1a, 0x17, 0x32, 0x8a, 0xc0, 0x2a, + 0x15, 0x7e, 0x69, 0x11, 0xe9, 0x6d, 0xff, 0x96, 0x52, 0x98, 0xa3, 0xfa, + 0x43, 0x7b, 0x33, 0x79, 0x56, 0xc4, 0xe3, 0x27, 0x40, 0xd6, 0x33, 0xea, + 0xac, 0x87, 0x4e, 0x74, 0xbb, 0xe0, 0x52, 0xab, 0x56, 0x8a, 0xed, 0x3e, + 0xd2, 0x25, 0xb2, 0xbe, 0x58, 0x4c, 0xdf, 0x0e, 0x8f, 0xca, 0x57, 0xdc, + 0x00, 0xfa, 0xb0, 0xc0, 0xf3, 0x7b, 0x6e, 0x41, 0x17, 0x07, 0xcb, 0x08, + 0xe3, 0xd8, 0xa5, 0x04, 0xdb, 0x42, 0x99, 0x67, 0x73, 0xd5, 0xd7, 0x1f, + 0x22, 0x9e, 0xea, 0x66, 0x5f, 0x44, 0x7d, 0xf4, 0xbf, 0x50, 0xb2, 0x3e, + 0x2f, 0x9f, 0x7a, 0xca, 0x80, 0x95, 0x59, 0x83, 0x69, 0x05, 0xec, 0x70, + 0x71, 0x12, 0x97, 0xaf, 0xdb, 0xfd, 0xe8, 0x11, 0x44, 0x8a, 0x6e, 0x09, + 0x90, 0xd5, 0x59, 0x8c, 0x6a, 0x65, 0xf9, 0xa9, 0x3d, 0x3c, 0x0c, 0xf3, + 0x2f, 0xa0, 0xb1, 0x8e, 0xf0, 0x3f, 0x16, 0x63, 0xf6, 0xe8, 0x80, 0x27, + 0x64, 0x56, 0x99, 0x94, 0x93, 0xc8, 0x36, 0x00, 0x21, 0xeb, 0x7c, 0x41, + 0x86, 0xae, 0xb2, 0x4b, 0x7d, 0xac, 0xac, 0x90, 0x8b, 0x99, 0x18, 0x25, + 0xa4, 0x0d, 0x9c, 0x96, 0x53, 0x0c, 0xfa, 0x7e, 0x61, 0xba, 0x7f, 0xca, + 0x61, 0x7b, 0xba, 0x2f, 0x96, 0x2f, 0x75, 0x29, 0x84, 0xb7, 0x32, 0xca, + 0x3b, 0x1f, 0xe6, 0x57, 0x34, 0xf3, 0xf1, 0x58, 0x61, 0xc9, 0x04, 0xa2, + 0x20, 0xea, 0x77, 0xa7, 0x83, 0xed, 0x3e, 0x14, 0x87, 0x8f, 0x82, 0x86, + 0x88, 0xc3, 0xf9, 0x10, 0x7e, 0x03, 0xa4, 0x33, 0xe0, 0x4e, 0x97, 0xef, + 0x66, 0x91, 0x9f, 0xce, 0x85, 0xc8, 0xca, 0x04, 0x3a, 0x8b, 0xf6, 0xc7, + 0xdf, 0xeb, 0x75, 0x31, 0xf4, 0x1a, 0x9a, 0x67, 0xc7, 0xb1, 0xd0, 0x33, + 0x97, 0xea, 0xd2, 0x52, 0xc3, 0x81, 0xdb, 0x63, 0x64, 0x31, 0x0f, 0x9e, + 0x75, 0x5f, 0xde, 0xe7, 0x46, 0x01, 0x19, 0x03, 0xe5, 0x0b, 0xf8, 0x9f, + 0xab, 0x4f, 0x1a, 0x1f, 0xe0, 0xb0, 0x75, 0x96, 0xf2, 0x15, 0x49, 0x63, + 0xa7, 0xae, 0x26, 0xe5, 0x41, 0x82, 0x1b, 0x1e, 0xd0, 0x8b, 0x2e, 0xcc, + 0xf7, 0x30, 0xb3, 0xb5, 0x1b, 0xd9, 0xe7, 0x65, 0x1e, 0x60, 0x3b, 0x74, + 0xfa, 0x52, 0x03, 0xe9, 0x0f, 0x45, 0x87, 0x8c, 0x1a, 0x4d, 0x0d, 0xb9, + 0x90, 0xec, 0xa3, 0x59, 0xad, 0xa2, 0x33, 0xfb, 0xd3, 0xac, 0xf0, 0x58, + 0x0c, 0x6f, 0x27, 0xa9, 0x1b, 0x18, 0xcb, 0x5d, 0x70, 0xcd, 0x14, 0xd9, + 0xe3, 0x9f, 0x42, 0xf7, 0x82, 0x3e, 0x47, 0x39, 0xe4, 0xa2, 0x9e, 0x03, + 0x7c, 0x2f, 0x5d, 0x18, 0x55, 0x20, 0x63, 0x68, 0x38, 0xc8, 0x0b, 0x3d, + 0xf3, 0xc7, 0x91, 0x72, 0x70, 0x4c, 0x8a, 0x0d, 0xc0, 0x80, 0x7d, 0xde, + 0xa3, 0x7f, 0x0a, 0x54, 0xb5, 0xd0, 0x49, 0x42, 0xc3, 0x27, 0x69, 0x19, + 0x1c, 0xbc, 0xf9, 0x5e, 0x16, 0x19, 0xab, 0xdb, 0x99, 0x1e, 0x90, 0x8c, + 0x6e, 0xb9, 0x17, 0x95, 0xad, 0xde, 0x70, 0x93, 0x7f, 0x5f, 0x26, 0xb0, + 0x9f, 0x86, 0xb3, 0x82, 0x9d, 0x30, 0x24, 0x19, 0x83, 0x7d, 0x20, 0x70, + 0x29, 0xe1, 0xb3, 0x22, 0x99, 0xb5, 0xef, 0x8f, 0x7a, 0x66, 0xbc, 0x86, + 0x18, 0x85, 0x39, 0x56, 0x9b, 0x5f, 0xf6, 0x63, 0xc8, 0x24, 0xbc, 0x54, + 0xc3, 0xc3, 0xa3, 0x27, 0xad, 0x80, 0xa9, 0x8f, 0x3b, 0x4b, 0xa0, 0x08, + 0xcc, 0xf9, 0xde, 0x0b, 0x92, 0xa3, 0x26, 0x79, 0x42, 0xa2, 0xd0, 0x7c, + 0xd4, 0x2e, 0x8f, 0x63, 0x4b, 0xaf, 0x6b, 0x7a, 0x58, 0x99, 0xb2, 0xb4, + 0x01, 0x55, 0x75, 0x4a, 0xca, 0x9d, 0xd7, 0x85, 0xa8, 0x28, 0x97, 0x3d, + 0xa6, 0x3c, 0xd1, 0xf6, 0x97, 0xd4, 0x15, 0x45, 0xc4, 0x25, 0x48, 0xd5, + 0xa6, 0x10, 0x00, 0xa4, 0x3e, 0xc4, 0xb4, 0x1d, 0x08, 0xf0, 0xf7, 0x6d, + 0x91, 0xc9, 0xc4, 0x4e, 0xb5, 0xd5, 0x45, 0x07, 0x3e, 0x05, 0x34, 0x44, + 0x14, 0xe1, 0x11, 0x1e, 0xa2, 0xba, 0x37, 0x18, 0xea, 0x16, 0x78, 0x58, + 0x83, 0xfd, 0x98, 0x42, 0xd3, 0x83, 0xac, 0x77, 0x65, 0xc9, 0x5b, 0x36, + 0x8b, 0x9d, 0x76, 0x25, 0x5d, 0xfc, 0x80, 0x21, 0x0e, 0xd8, 0xcb, 0xc4, + 0xcc, 0x59, 0x4e, 0x85, 0x51, 0x3b, 0xc0, 0xa8, 0x0b, 0x5d, 0x60, 0xa2, + 0xc3, 0x2f, 0x2e, 0x8a, 0x18, 0x3c, 0x9d, 0x18, 0x0d, 0xd5, 0xa7, 0x32, + 0x72, 0xf0, 0xef, 0xdf, 0xa4, 0x35, 0x09, 0x75, 0x2f, 0xb0, 0xe0, 0xec, + 0xb2, 0x2d, 0x54, 0xeb, 0x22, 0x01, 0x67, 0x73, 0x61, 0x2d, 0x00, 0x8e, + 0x2a, 0x59, 0xc5, 0xa0, 0xf1, 0xb4, 0x20, 0x15, 0xeb, 0xe5, 0x0b, 0x7d, + 0x6b, 0x70, 0x45, 0x64, 0x3a, 0xc6, 0xbf, 0x34, 0x6a, 0x33, 0x35, 0xf2, + 0x88, 0x47, 0x4d, 0x95, 0x3d, 0x76, 0x7c, 0x56, 0x7a, 0x6a, 0x72, 0x48, + 0xa9, 0x28, 0x32, 0xf6, 0x25, 0xf5, 0x2a, 0x52, 0x40, 0x70, 0x46, 0x93, + 0x4e, 0x86, 0x58, 0xde, 0x11, 0x66, 0x2f, 0xa6, 0x75, 0xbd, 0x24, 0x05, + 0x3c, 0x5e, 0xf4, 0xbc, 0x88, 0xda, 0x69, 0xd0, 0x9d, 0x7f, 0xfa, 0x6b, + 0xf4, 0x50, 0x51, 0x03, 0x26, 0xf6, 0xaa, 0x11, 0xa6, 0x3d, 0x2a, 0xa3, + 0x18, 0x0e, 0xb1, 0x0b, 0x8c, 0x5a, 0x3a, 0xc4, 0x14, 0xd3, 0x9b, 0xea, + 0x2f, 0xf9, 0x5f, 0xbc, 0x9a, 0x94, 0x92, 0x2b, 0xaa, 0xf7, 0x62, 0x0c, + 0xf0, 0xf9, 0xcc, 0x20, 0x1b, 0x5b, 0x56, 0xed, 0xe4, 0x5f, 0xef, 0xa0, + 0x5d, 0xe2, 0xe7, 0x50, 0x0d, 0x13, 0x92, 0x7f, 0x70, 0x68, 0x81, 0x3c, + 0x5d, 0x71, 0x12, 0x14, 0xba, 0xe9, 0xf1, 0x24, 0x70, 0xc3, 0xea, 0x3a, + 0x8e, 0x19, 0xab, 0x4f, 0x5f, 0x20, 0x38, 0xcb, 0xd8, 0x91, 0x3d, 0x47, + 0x8a, 0xb8, 0xe0, 0x81, 0x73, 0x57, 0x19, 0xc4, 0xb6, 0xd7, 0x6e, 0x01, + 0xad, 0xb7, 0x80, 0xb2, 0x44, 0xe7, 0x77, 0x3a, 0x55, 0x9f, 0x36, 0x77, + 0x4c, 0x88, 0x69, 0x6b, 0xc6, 0x67, 0x2f, 0xbd, 0x37, 0x0c, 0xf2, 0x9f, + 0x88, 0x6e, 0xa6, 0xa0, 0xd7, 0x5a, 0x53, 0xf3, 0xc0, 0xaa, 0x7b, 0xca, + 0xc3, 0x07, 0xf4, 0x08, 0xc9, 0x84, 0x0c, 0x36, 0x49, 0x15, 0x71, 0x8c, + 0x60, 0x6f, 0xd5, 0x91, 0xc5, 0x3a, 0x33, 0x3b, 0xde, 0x8c, 0xe0, 0xf4, + 0x08, 0x42, 0x6d, 0xf7, 0x3b, 0xae, 0xd0, 0x06, 0xe5, 0x1b, 0x60, 0x24, + 0xc4, 0xaa, 0xcf, 0x54, 0x0e, 0x78, 0xa6, 0xf9, 0x40, 0x3b, 0xca, 0xed, + 0x5f, 0xa4, 0xd3, 0x13, 0x6e, 0x0a, 0x59, 0x3c, 0xda, 0xdb, 0xc6, 0x6f, + 0x8f, 0x89, 0x31, 0x8c, 0x87, 0x1e, 0xfe, 0x01, 0x16, 0x5b, 0xac, 0x1a, + 0x62, 0x85, 0x39, 0x61, 0xe1, 0x4c, 0xae, 0xae, 0x85, 0xd9, 0x5d, 0x9c, + 0x2a, 0x6e, 0x6b, 0xec, 0xef, 0x2b, 0xc6, 0x32, 0xd6, 0x62, 0x7e, 0x46, + 0x67, 0xe8, 0x6f, 0x4a, 0x50, 0x05, 0x75, 0xda, 0xe0, 0x6b, 0x47, 0xb6, + 0x2a, 0x48, 0x56, 0x3e, 0x22, 0x18, 0xfb, 0xf5, 0x66, 0xf1, 0x42, 0xd6, + 0xf3, 0x3d, 0x26, 0xc8, 0x44, 0xea, 0xa7, 0x9f, 0x90, 0xd8, 0x8f, 0xeb, + 0x45, 0x50, 0x99, 0xf8, 0x86, 0x5f, 0x70, 0x03, 0x89, 0x06, 0x08, 0x92, + 0x02, 0x6a, 0x93, 0x90, 0xce, 0xf2, 0xb5, 0x06, 0x78, 0x1e, 0x96, 0x1d, + 0xa2, 0x20, 0x27, 0x90, 0xfc, 0x07, 0x50, 0x84, 0xf8, 0x19, 0xd0, 0xb1, + 0x0c, 0x75, 0xb6, 0x3b, 0xb2, 0xaa, 0x73, 0x34, 0x49, 0xc9, 0xb2, 0xc2, + 0x58, 0x7e, 0x40, 0x19, 0xa6, 0x08, 0x6b, 0x9e, 0x87, 0xce, 0x7a, 0x27, + 0x3d, 0x7e, 0xe3, 0xe4, 0x12, 0x7c, 0x39, 0x24, 0x16, 0x80, 0x97, 0xbb, + 0x94, 0x9e, 0xa6, 0x0f, 0x5f, 0x42, 0xa1, 0xca, 0x37, 0xa0, 0xbe, 0x1c, + 0x4f, 0x62, 0x68, 0x6a, 0x50, 0x1e, 0x77, 0xe2, 0xb6, 0xdf, 0xa8, 0x89, + 0xdf, 0x98, 0x9b, 0x80, 0xc2, 0x00, 0x21, 0x6a, 0xf6, 0x82, 0xb3, 0x5f, + 0x8b, 0x98, 0x68, 0xe1, 0x76, 0xef, 0x06, 0x8c, 0x24, 0x07, 0xd2, 0xe5, + 0x86, 0xc1, 0xc0, 0x26, 0x94, 0x2d, 0x96, 0xb1, 0xa4, 0x77, 0x11, 0xcb, + 0xa9, 0xf9, 0x46, 0xe8, 0xfd, 0x91, 0x61, 0x9d, 0xce, 0xd1, 0x24, 0x27, + 0xbb, 0xae, 0x68, 0x04, 0x44, 0xc9, 0x44, 0x69, 0x52, 0x05, 0x10, 0x4d, + 0x96, 0x56, 0x98, 0x69, 0x46, 0x49, 0xc2, 0x75, 0xb9, 0xd8, 0x1c, 0x46, + 0xdc, 0x71, 0x86, 0x71, 0x07, 0xea, 0x18, 0x5d, 0x7c, 0x3f, 0x81, 0x97, + 0xfc, 0xc8, 0x88, 0xe4, 0xe7, 0x5e, 0xb2, 0xf8, 0x04, 0x17, 0x14, 0xcf, + 0x24, 0x4c, 0x35, 0x1e, 0x0d, 0xba, 0xf6, 0x0d, 0x29, 0x1c, 0x3c, 0x5a, + 0x0f, 0xd0, 0xf8, 0xf8, 0xdb, 0xa6, 0xa5, 0xf2, 0x83, 0x3d, 0xa0, 0x16, + 0x5d, 0xf4, 0xb7, 0xc0, 0xc5, 0xf1, 0x0f, 0x09, 0x7d, 0x6a, 0x24, 0xf0, + 0x94, 0x03, 0x7d, 0xc0, 0x96, 0x61, 0xa7, 0x44, 0xe2, 0xa3, 0x40, 0xa5, + 0x00, 0x06, 0x13, 0x45, 0xba, 0x60, 0xc3, 0x15, 0x75, 0x6a, 0xe6, 0xd9, + 0x21, 0x37, 0x15, 0x80, 0xfd, 0x68, 0xdf, 0xab, 0x9f, 0xde, 0xcf, 0x4a, + 0x98, 0xf8, 0xa9, 0x27, 0xd3, 0x2d, 0x3d, 0x5c, 0xdc, 0xff, 0x8c, 0x61, + 0x4d, 0x25, 0xc8, 0xdf, 0x66, 0xf6, 0xde, 0xf0, 0x21, 0x5a, 0x27, 0x36, + 0x38, 0x1f, 0xfe, 0x89, 0x33, 0x52, 0x4e, 0x99, 0x55, 0x9b, 0xd0, 0x4f, + 0x15, 0xba, 0x91, 0xdd, 0x95, 0xeb, 0x57, 0x18, 0xc4, 0x21, 0x86, 0x24, + 0x67, 0x38, 0xf0, 0x2f, 0xd2, 0x66, 0x0b, 0x92, 0xb9, 0xc3, 0xcb, 0x8e, + 0x7f, 0x6c, 0x44, 0xbc, 0xcb, 0x45, 0x71, 0x51, 0x61, 0x35, 0xf2, 0x9f, + 0xbf, 0xf2, 0x8f, 0x5a, 0xdb, 0xaa, 0x54, 0x20, 0x1d, 0x52, 0xce, 0x89, + 0xd4, 0xe7, 0x79, 0x75, 0xa7, 0xff, 0x1f, 0x6a, 0xfd, 0xb9, 0x56, 0xee, + 0xca, 0x2c, 0x9f, 0xf3, 0x6d, 0xdf, 0xce, 0x96, 0x0c, 0xaf, 0x2c, 0x2c, + 0x7d, 0x35, 0x79, 0x5d, 0x43, 0xbb, 0x27, 0xaf, 0x07, 0x17, 0x9a, 0x67, + 0xde, 0x3b, 0x35, 0xf1, 0xd9, 0x98, 0x92, 0xf8, 0x3d, 0x35, 0xf1, 0x25, + 0xf8, 0x15, 0xcc, 0x6f, 0x49, 0x9e, 0xba, 0x52, 0xd8, 0x76, 0x71, 0x8d, + 0x90, 0x2c, 0x73, 0x3f, 0xef, 0xa2, 0xef, 0x43, 0x19, 0x2d, 0x83, 0xb9, + 0xde, 0xc6, 0x33, 0x00, 0xd9, 0x9d, 0x50, 0x58, 0xa7, 0xaa, 0x07, 0xa6, + 0x81, 0x8c, 0x1b, 0xe7, 0x9a, 0x3f, 0x11, 0x4c, 0xef, 0x96, 0x07, 0xb3, + 0x48, 0x3e, 0x95, 0x2e, 0xb1, 0x27, 0x2d, 0xf9, 0x50, 0x49, 0x91, 0x7e, + 0x91, 0xd2, 0xcc, 0xf0, 0x36, 0xe8, 0xcd, 0x69, 0x05, 0x68, 0x50, 0xe6, + 0x4d, 0xbe, 0xd7, 0x55, 0xd5, 0xd2, 0xe4, 0x96, 0xd0, 0xa8, 0x1b, 0x4b, + 0x28, 0x54, 0xcb, 0x95, 0x4c, 0xb5, 0xe7, 0x1c, 0x95, 0x2e, 0x11, 0xda, + 0x30, 0x0e, 0x87, 0xfe, 0x5e, 0x34, 0x80, 0x59, 0x9d, 0x70, 0x09, 0x48, + 0x9e, 0xe8, 0x31, 0x12, 0x3f, 0xe2, 0x07, 0x35, 0x74, 0x79, 0x43, 0x68, + 0x42, 0x85, 0x09, 0x85, 0x42, 0x99, 0x5a, 0x92, 0x8c, 0xe9, 0x14, 0x6c, + 0xf3, 0x06, 0x50, 0x2a, 0x6d, 0xd8, 0xd5, 0x06, 0xdc, 0x8c, 0x4d, 0x60, + 0x84, 0x98, 0x6a, 0xf6, 0x30, 0xb9, 0x06, 0xe3, 0xcd, 0x75, 0xd7, 0xaa, + 0xbc, 0x56, 0x8d, 0x2f, 0x6b, 0x0d, 0x2e, 0x26, 0x40, 0x86, 0x08, 0xf5, + 0xc6, 0xee, 0x12, 0xd6, 0x06, 0x59, 0x7f, 0xa6, 0xac, 0x3f, 0xef, 0x15, + 0xd6, 0x20, 0x55, 0x21, 0xa9, 0x29, 0xdb, 0xf4, 0x1f, 0xa6, 0x79, 0x3c, + 0x13, 0xf0, 0x32, 0x7f, 0x25, 0x27, 0x7a, 0x64, 0xe1, 0x64, 0x3b, 0x86, + 0x14, 0x4e, 0xfd, 0x29, 0xbc, 0x6e, 0x9f, 0x1b, 0xaa, 0xdf, 0xe3, 0x77, + 0xd7, 0xb8, 0x7f, 0x61, 0x2f, 0xbc, 0xea, 0xfe, 0x18, 0xc6, 0x54, 0x91, + 0x85, 0xaa, 0x55, 0xa7, 0xca, 0x00, 0x8f, 0x56, 0xaf, 0xa8, 0x49, 0x02, + 0xcb, 0xbe, 0x20, 0x5a +}; diff --git a/BootLoader/source/launch_ds_crt0.s b/BootLoader/source/launch_ds_crt0.s index 51e7896..d8923a4 100755 --- a/BootLoader/source/launch_ds_crt0.s +++ b/BootLoader/source/launch_ds_crt0.s @@ -36,7 +36,7 @@ _start: bl CopyMem @ Start ARM9 binary - ldr r0, =0x027FFE24 + ldr r0, =0x02FFFE24 ldr r1, =_arm9_start str r1, [r0] diff --git a/BootLoader/source/main.arm7.c b/BootLoader/source/main.arm7.c index 5af0327..3de179c 100755 --- a/BootLoader/source/main.arm7.c +++ b/BootLoader/source/main.arm7.c @@ -25,7 +25,6 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ - #ifndef ARM7 # define ARM7 #endif @@ -44,31 +43,44 @@ #define NULL 0 #endif + #include "common.h" +#include "../../arm9/common/launcherData.h" + #include "read_card.h" #include "tonccpy.h" + +#include "crypto.h" +#include "f_xy.h" +#include "dsi.h" +#include "u128_math.h" + /*------------------------------------------------------------------------- External functions --------------------------------------------------------------------------*/ extern void arm7_clearmem (void* loc, size_t len); extern void arm7_reset (void); -static bool useTwlCfg = false; -static int twlCfgLang = 0; -// static bool useShortInit = false; +volatile u16 useTwlCfg = 0; +volatile int twlCfgLang = 0; +// volatile bool useShortInit = false; + +// ALIGN(4) char modcrypt_shared_key[8] = "Nintendo"; //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Important things -#define NDS_HEADER 0x027FFE00 -#define NDS_HEADER_POKEMON 0x027FF000 -#define TWL_HEADER 0x027FE000 -#define TMP_HEADER 0x027FC000 +#define NDS_HEADER 0x02FFFE00 +#define NDS_HEADER_POKEMON 0x02FFF000 +#define TWL_HEADER 0x02FFE000 +#define TMP_HEADER 0x02FFC000 tNDSHeader* ndsHeader; -tNDSHeader* tmpHeader; +tTWLHeader* twlHeader; #define REG_GPIO_WIFI *(vu16*)0x4004C04 -static u32 chipID; +// ALIGN(4) u32 chipID = 0; + +// static void memset_addrs_arm7(u32 start, u32 end) { toncset((u32*)start, 0, ((int)end - (int)start)); } static tNDSHeader* loadHeader(tDSiHeader* twlHeaderTemp) { tNDSHeader* ntrHeader = (tNDSHeader*)NDS_HEADER; @@ -80,9 +92,22 @@ static tNDSHeader* loadHeader(tDSiHeader* twlHeaderTemp) { return ntrHeader; } +static void decrypt_modcrypt_area(dsi_context* ctx, u8 *buffer, unsigned int size) { + uint32_t len = size / 0x10; + u8 block[0x10]; + + while (len>0) { + toncset(block, 0, 0x10); + dsi_crypt_ctr_block(ctx, buffer, block); + tonccpy(buffer, block, 0x10); + buffer+=0x10; + len--; + } +} + static void NDSTouchscreenMode(void) { - bool specialSetting = false; + u16 specialSetting = 0; u8 volLevel; static const char list[][4] = { @@ -146,12 +171,12 @@ static void NDSTouchscreenMode(void) { for (unsigned int i = 0; i < sizeof(list) / sizeof(list[0]); i++) { if (memcmp(ndsHeader->gameCode, list[i], 3) == 0) { // Found a match. - specialSetting = true; // Special setting (when found special gamecode) + specialSetting = 0xFFFF; // Special setting (when found special gamecode) break; } } - if (specialSetting) { + if (specialSetting > 0) { // special setting (when found special gamecode) volLevel = 0xAC; } else { @@ -318,9 +343,9 @@ const char* getRomTid(const tNDSHeader* ndsHeader) { return romTid; } -static void errorOutput (u32 code, bool isError) { +ALIGN(4) static void errorOutput (u16 code, u16 isError) { arm9_errorCode = code; - if (isError) { + if (isError > 0) { ipcSendState(ARM7_ERR); while(1); // Stop } @@ -369,16 +394,16 @@ static void arm7_readFirmware(tNDSHeader* ndsHeader) { tonccpy(PersonalData, currentSettings, sizeof(PERSONAL_DATA)); - if (useTwlCfg && (language == 0xFF)) { language = twlCfgLang; } + if ((useTwlCfg > 0) && (language == 0xFF)) { language = twlCfgLang; } - if (language >= 0 && language <= 7) { + if ((language != 0) && (language <= 7)) { // Change language - personalData->language = language; //*(u8*)((u32)ndsHeader - 0x11C) = language; + personalData->language = (unsigned int)language; //*(u8*)((u32)ndsHeader - 0x11C) = language; } - if (personalData->language != 6 && ndsHeader->reserved1[8] == 0x80) { + if ((unsigned int)personalData->language != 6 && ndsHeader->reserved1[8] == 0x80) { ndsHeader->reserved1[8] = 0; // Patch iQue game to be region-free - ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x15E); // Fix CRC + ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x015E); // Fix CRC } } @@ -393,6 +418,7 @@ static void arm7_resetMemory (void) { SCHANNEL_SOURCE(i) = 0; SCHANNEL_LENGTH(i) = 0; } + REG_SOUNDCNT = 0; // Clear out ARM7 DMA channels and timers @@ -411,7 +437,7 @@ static void arm7_resetMemory (void) { REG_IPC_FIFO_CR = 0; // clear IWRAM - 037F:8000 to 0380:FFFF, total 96KiB - arm7_clearmem ((void*)0x037F8000, 96*1024); + // arm7_clearmem ((void*)0x037F8000, 96*1024); // clear most of EXRAM - except after 0x022FD800, which has the ARM9 code // Skip 0x0200000 region if fastBoot enabled. (cart header copy stored here) @@ -420,24 +446,100 @@ static void arm7_resetMemory (void) { } else { arm7_clearmem ((void*)0x02000000, 0x002FD800); }*/ - arm7_clearmem ((void*)0x02000000, 0x002FD800); + + // arm7_clearmem ((void*)0x02000000, 0x002FD000); + // clear last part of EXRAM, skipping the ARM9's section - arm7_clearmem ((void*)0x023FE000, 0x2000); + // arm7_clearmem ((void*)0x023FF800, 0x800); // Clear tmp header region previously used by custom struct - arm7_clearmem ((void*)TMP_HEADER, 0x160); + // arm7_clearmem ((void*)TMP_HEADER, 0x160); + + /*if ((REG_SNDEXTCNT != 0) && (REG_SCFG_EXT & BIT(31)) && (REG_SCFG_ROM != 0x703)) { + memset_addrs_arm7(0x03000000, 0x0380FFC0); + memset_addrs_arm7(0x0380FFD0, 0x03800000 + 0x10000); + } else { + memset_addrs_arm7(0x03800000 - 0x8000, 0x03800000 + 0x10000); + }*/ + // memset_addrs_arm7(0x03000000, 0x0380FFC0); + // memset_addrs_arm7(0x0380FFD0, 0x03800000 + 0x10000); + arm7_clearmem((void*)0x03000000, 0x80FFC0); + arm7_clearmem((void*)0x0380FFD0, 0x30); + + // clear most of EXRAM + arm7_clearmem((void*)0x02000000, 0x3FD000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader + // memset_addrs_arm7(0x02000000, 0x023FD000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader + // memset_addrs_arm7(0x023FD000, 0x023FD7BC); // Leave eMMC CID Mirror intact + // memset_addrs_arm7(0x023FD7CC, 0x02400000); + + arm7_clearmem((void*)0x023FE000, 0x2000); + + if (twlRAM > 0) { + arm7_clearmem((void*)0x02FFE000, 0x2000); + // memset_addrs_arm7(0x02400000, 0x02800000); // Clear the rest of EXRAM + // clear last part of EXRAM + // memset_addrs_arm7(0x02800000, 0x02FFD000); // Leave arm9 temp area intact (used by bootloader) + // memset_addrs_arm7(0x02FFD000, 0x02FFD7BC); // Leave eMMC CID intact + // memset_addrs_arm7(0x02FFD7CC, 0x03000000); + // memset_addrs_arm7(0x02FFE000, 0x03000000); + } REG_IE = 0; REG_IF = ~0; REG_AUXIE = 0; REG_AUXIF = ~0; + REG_POWERCNT = 1; //turn off power to stuffs (*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version (*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version } -static void setMemoryAddress(const tNDSHeader* ndsHeader) { - if (ndsHeader->unitCode > 0) { +static void setMemoryAddress(const tNDSHeader* ndsHeader, u32 ChipID) { + if (ndsHeader->unitCode & BIT(1)) { + copyLoop((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header + + *(u32*)(0x02FFA680) = 0x02FD4D80; + *(u32*)(0x02FFA684) = 0x00000000; + *(u32*)(0x02FFA688) = 0x00001980; + + *(u32*)(0x02FFF00C) = 0x0000007F; + *(u32*)(0x02FFF010) = 0x550E25B8; + *(u32*)(0x02FFF014) = 0x02FF4000; + + // Set region flag + if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) { + *(u8*)(0x02FFFD70) = 0; + } else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) { + *(u8*)(0x02FFFD70) = 1; + } else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) { + *(u8*)(0x02FFFD70) = 2; + } else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) { + *(u8*)(0x02FFFD70) = 3; + } else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) { + *(u8*)(0x02FFFD70) = 4; + } else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) { + *(u8*)(0x02FFFD70) = 5; + } + } + + // Set memory values expected by loaded NDS + // from NitroHax, thanks to Chism + *((u32*)0x02FFF800) = ChipID; // CurrentCardID + // *((u32*)0x02FFF804) = ChipID; // Command10CardID // This does not result in correct v + *((u16*)0x02FFF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x02FFF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x02FFF850) = 0x5835; + // Copies of above + *((u32*)0x02FFFC00) = ChipID; // CurrentCardID + // *((u32*)0x02FFFC04) = ChipID; // Command10CardID + *((u16*)0x02FFFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x02FFFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x02FFFC10) = 0x5835; + *((u16*)0x02FFFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr +} + +static void setMemoryAddressTWL(const tNDSHeader* ndsHeader, u32 ChipID) { + if (ndsHeader->unitCode & BIT(1)) { copyLoop((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header *(u32*)(0x027FA680) = 0x02FD4D80; @@ -466,23 +568,90 @@ static void setMemoryAddress(const tNDSHeader* ndsHeader) { // Set memory values expected by loaded NDS // from NitroHax, thanks to Chism - *((u32*)0x027FF800) = chipID; // CurrentCardID - *((u32*)0x027FF804) = chipID; // Command10CardID + *((u32*)0x027FF800) = ChipID; // CurrentCardID + // *((u32*)0x027FF804) = ChipID; // Command10CardID *((u16*)0x027FF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] *((u16*)0x027FF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] *((u16*)0x027FF850) = 0x5835; // Copies of above - *((u32*)0x027FFC00) = chipID; // CurrentCardID - *((u32*)0x027FFC04) = chipID; // Command10CardID + *((u32*)0x027FFC00) = ChipID; // CurrentCardID + // *((u32*)0x027FFC04) = ChipID; // Command10CardID *((u16*)0x027FFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] *((u16*)0x027FFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] *((u16*)0x027FFC10) = 0x5835; *((u16*)0x027FFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr + + tonccpy((u32*)0x027FC000, (u32*)TMP_HEADER, 0x1000); + tonccpy((u32*)0x027FF000, (u32*)NDS_HEADER_POKEMON, 0x170); + tonccpy((u32*)0x027FFE00, (u32*)NDS_HEADER, 0x160); + tonccpy((u32*)0x027FE000, (u32*)TWL_HEADER, 0x1000); + + tonccpy((u32*)0x027FF830, (u32*)0x02FFF830, 0x20); + tonccpy((u32*)0x027FFC80, (u32*)0x02FFFC80, 0x70); + tonccpy((u32*)0x027FFD80, (u32*)0x02FFFD80, 0x70); } -static u32 arm7_loadBinary (void) { - u32 errorCode; +static void arm7_loadExtendedBinary(sNDSHeaderExt* ndsHeader) { + twlHeader = (tTWLHeader*)TWL_HEADER; + + *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; + *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; + *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; + *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; + *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; + REG_MBK6 = *(u32*)0x02FFE1A0; + REG_MBK7 = *(u32*)0x02FFE1A4; + REG_MBK8 = *(u32*)0x02FFE1A8; + REG_MBK9 = *(u32*)0x02FFE1AC; + /*REG_MBK9 = twlHeader->arm9MBKMaster; + REG_MBK6 = twlHeader->arm7MBK6; + REG_MBK7 = twlHeader->arm7MBK7; + REG_MBK8 = twlHeader->arm7MBK8;*/ + + cardRead(ndsHeader, twlHeader->arm9iromOffset, (u32*)twlHeader->arm9idestination, twlHeader->arm9ibinarySize); + cardRead(ndsHeader, twlHeader->arm7iromOffset, (u32*)twlHeader->arm7idestination, twlHeader->arm7ibinarySize); + + if (twlHeader->twlHeaderSettings & BIT(1)) { + char modcrypt_shared_key[9] = { 'N', 'i', 'n', 't', 'e', 'n', 'd', 'o', '\0' }; + int i; + u8 key[16]; + u8 keyp[16]; + for (i = 0; i < 16; i++) { + key[i] = 0; + keyp[i] = 0; + } + + if (twlHeader->twlHeaderSettings & BIT(3)) { + // Debug Key + tonccpy(key, (u8*)twlHeader, 16); + } else { + u8 *target = (u8*)twlHeader; + tonccpy(keyp, modcrypt_shared_key, 8); + for (int i=0;i<4;i++) { keyp[8+i] = target[0x0c+i]; keyp[15-i] = target[0x0c+i]; } + tonccpy(key, target+0x350, 16); + u128_xor(key, keyp); + u128_add(key, DSi_KEY_MAGIC); + u128_lrot(key, 42); + } + + u32 rk[4]; + tonccpy(rk, key, 16); + + dsi_context ctx; + dsi_set_key(&ctx, key); + dsi_set_ctr(&ctx, twlHeader->hmac_arm9); + if (twlHeader->modcrypt1Size != 0) { decrypt_modcrypt_area(&ctx, (u8*)twlHeader->arm9idestination, twlHeader->modcrypt1Size); } + + dsi_set_key(&ctx, key); + dsi_set_ctr(&ctx, twlHeader->hmac_arm7); + if (twlHeader->modcrypt2Size != 0) { decrypt_modcrypt_area(&ctx, (u8*)twlHeader->arm7idestination, twlHeader->modcrypt2Size); } + } +} + +static u16 arm7_loadBinary (void) { + u16 errorCode; + tDSiHeader* twlHeaderTemp = (tDSiHeader*)TMP_HEADER; // Use same region cheat engine goes. Cheat engine will replace this later when it's not needed. // Init card @@ -493,14 +662,16 @@ static u32 arm7_loadBinary (void) { errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID); }*/ - errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, &chipID); + errorCode = cardInit((sNDSHeaderExt*)twlHeaderTemp, (u32*)InitialCartChipID); if (errorCode)return errorCode; ndsHeader = loadHeader(twlHeaderTemp); // copy twlHeaderTemp to ndsHeader location - cardRead(ndsHeader->arm9romOffset, (u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize); - cardRead(ndsHeader->arm7romOffset, (u32*)ndsHeader->arm7destination, ndsHeader->arm7binarySize); + cardRead((sNDSHeaderExt*)twlHeaderTemp, ndsHeader->arm9romOffset, (u32*)ndsHeader->arm9destination, ndsHeader->arm9binarySize); + cardRead((sNDSHeaderExt*)twlHeaderTemp, ndsHeader->arm7romOffset, (u32*)ndsHeader->arm7destination, ndsHeader->arm7binarySize); + + if ((ndsHeader->unitCode & BIT(1)) && (twlMode > 0) && (twlRAM > 0))arm7_loadExtendedBinary((sNDSHeaderExt*)twlHeaderTemp); // Fix Pokemon games needing header data. copyLoop((u32*)NDS_HEADER_POKEMON, (u32*)NDS_HEADER, 0x170); @@ -524,7 +695,7 @@ static u32 arm7_loadBinary (void) { // Main function void arm7_main (void) { - u32 errorCode; + u16 errorCode; // Synchronise start while (ipcRecvState() != ARM9_START); @@ -533,54 +704,44 @@ void arm7_main (void) { // Wait until ARM9 is ready while (ipcRecvState() != ARM9_READY); - if (language != 0xFF)language = (int)launchData->language; - if (launchData->scfgUnlock > 0x00)scfgUnlock = true; - if (launchData->twlMode > 0x00)twlMode = true; - if (launchData->twlCLK > 0x00)twlCLK = true; - if (launchData->debugMode > 0x00)debugMode = true; - // if (launchData->fastBoot > 0x00)useShortInit = true; - - - if (twlMode) { - REG_MBK9=0x0300000F; - REG_MBK6=0x080037C0; - REG_MBK7=0x07C03740; - REG_MBK8=0x07403700; - } else { + if ((twlMode == 0) || (twlRAM == 0) || (isTWLSRL == 0)) { REG_MBK9=0xFCFFFF0F; REG_MBK6=0x09403900; REG_MBK7=0x09803940; REG_MBK8=0x09C03980; } - errorOutput(ERR_STS_CLR_MEM, false); + errorOutput(ERR_STS_CLR_MEM, 0); ipcSendState(ARM7_MEMCLR); // Get ARM7 to clear RAM arm7_resetMemory(); - tmpHeader = (tNDSHeader*)TMP_HEADER; - - if (!twlMode)REG_SCFG_ROM = 0x703; + if (twlMode == 0)REG_SCFG_ROM = 0x703; - errorOutput(ERR_STS_LOAD_BIN, false); + errorOutput(ERR_STS_LOAD_BIN, 0); ipcSendState(ARM7_LOADBIN); // Load the NDS file errorCode = arm7_loadBinary(); - if (errorCode)errorOutput(errorCode, true); + if (errorCode)errorOutput(errorCode, 0xFFFF); - errorOutput(ERR_STS_STARTBIN, false); + errorOutput(ERR_STS_STARTBIN, 0); - tonccpy((u32*)0x023FF000, (u32*)0x027FF000, 0x1000); + if (twlRAM == 0)tonccpy((u32*)0x023FF000, (u32*)0x02FFF000, 0x1000); arm7_readFirmware(ndsHeader); // Header has to be loaded first - if (twlMode) { - REG_SCFG_EXT = 0x92FBFB06; + if (twlMode > 0) { + REG_SCFG_CLK = 0x187; + // REG_SCFG_ROM = 0x501; + // REG_SCFG_EXT = 0x92FBFB06; + // REG_SCFG_EXT = 0x9307F100; + REG_SCFG_EXT = 0x93FFFB06; } else { + REG_SCFG_CLK = 0x107; if (cdcReadReg(CDC_SOUND, 0x22) == 0xF0) { // Switch touch mode to NTR *(u16*)0x4004700 = 0x800F; @@ -588,19 +749,18 @@ void arm7_main (void) { *(u16*)0x4000500 = 0x807F; } REG_GPIO_WIFI |= BIT(8); // Old NDS-Wifi mode - REG_SCFG_EXT = 0x92A00000; + REG_SCFG_EXT = 0x92A40000; } - if (twlCLK) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; } - if (scfgUnlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); } + // if (twlCLK > 0) { REG_SCFG_CLK = 0x187; } else { REG_SCFG_CLK = 0x107; } + if (scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31); /// REG_SCFG_EXT |= BIT(18); - setMemoryAddress(ndsHeader); + setMemoryAddress(ndsHeader, *(u32*)InitialCartChipID); + + if ((twlRAM > 0) && ((twlMode == 0) || (isTWLSRL == 0)))setMemoryAddressTWL(ndsHeader, *(u32*)InitialCartChipID); ipcSendState(ARM7_BOOTBIN); - - // Moved here to prevent interfering with arm9main's new console - REG_POWERCNT = 1; //turn off power to stuffs - + arm7_reset(); } diff --git a/BootLoader/source/main.arm9.c b/BootLoader/source/main.arm9.c index ca1efce..34687ea 100755 --- a/BootLoader/source/main.arm9.c +++ b/BootLoader/source/main.arm9.c @@ -40,39 +40,41 @@ #include "common.h" #include "miniconsole.h" -#define LAUNCH_DATA 0x020007F0 - -volatile int arm9_stateFlag = ARM9_BOOT; -volatile u32 arm9_errorCode = 0xFFFFFFFF; -volatile bool arm9_errorClearBG = false; -volatile bool consoleDebugMode = false; -volatile u32 arm9_BLANK_RAM = 0; -volatile u32 defaultFontPalSlot = 0; +#include "../../arm9/common/launcherData.h" volatile tLauncherSettings* launchData = (tLauncherSettings*)LAUNCH_DATA; -volatile int language = -1; -volatile bool scfgUnlock = false; -volatile bool twlMode = false; -volatile bool twlCLK = false; -volatile bool TWLVRAM = false; -volatile bool debugMode = false; -volatile bool consoleInit = false; +ALIGN(4) volatile int arm9_stateFlag = ARM9_BOOT; +ALIGN(4) volatile u16 arm9_errorCode = 0xFFFF; +ALIGN(4) volatile u16 consoleDebugMode = 0; +ALIGN(4) volatile u32 arm9_BLANK_RAM = 0; +ALIGN(4) volatile u32 defaultFontPalSlot = 0; +ALIGN(4) volatile u32 arm9_cachedChipID = 0xFFFFFFFF; -static char TXT_STATUS[] = "STATUS: "; -static char TXT_ERROR[] = "ERROR: "; -static char ERRTXT_NONE[] = "NONE"; -static char ERRTXT_STS_CLRMEM[] = "CLEAR MEMORY"; -static char ERRTXT_STS_LOAD_BIN[] = "LOAD CART"; -static char ERRTXT_STS_STARTBIN[] = "START BINARY"; -static char ERRTXT_STS_START[] = "BOOTLOADER STARTUP"; -static char ERRTXT_LOAD_NORM[] = "LOAD NORMAL"; -static char ERRTXT_LOAD_OTHR[] = "LOAD OTHER"; -static char ERRTXT_SEC_NORM[] = "SECURE NORMAL"; -static char ERRTXT_SEC_OTHR[] = "SECURE OTHER"; -static char ERRTXT_LOGO_CRC[] = "LOGO CRC"; -static char ERRTXT_HEAD_CRC[] = "HEADER CRC"; -static char NEW_LINE[] = "\n"; +ALIGN(4) volatile u16 language = 0xFFFF; +ALIGN(4) volatile u16 scfgUnlock = 0; +ALIGN(4) volatile u16 twlMode = 0; +ALIGN(4) volatile u16 twlCLK = 0; +ALIGN(4) volatile u16 isTWLSRL = 0; +// ALIGN(4) volatile u16 twlVRAM = 0; +ALIGN(4) volatile u16 twlRAM = 0; +ALIGN(4) volatile u16 debugMode = 0; +ALIGN(4) volatile u16 consoleInit = 0; + + +ALIGN(4) const u16 redFont = 0x801B; +ALIGN(4) const u16 greenFont = 0x8360; + +ALIGN(4) char ERRTXT_NONE[14] = "\nSTATUS: NONE"; +ALIGN(4) char ERRTXT_STS_START[22] = "\nSTATUS: LOADER START"; +ALIGN(4) char ERRTXT_STS_CLRMEM[22] = "\nSTATUS: CLEAR MEMORY"; +ALIGN(4) char ERRTXT_STS_LOAD_BIN[19] = "\nSTATUS: LOAD CART"; +ALIGN(4) char ERRTXT_STS_STARTBIN[21] = "\nSTATUS: START BINARY"; +ALIGN(4) char ERRTXT_LOAD_NORM[20] = "\nERROR: LOAD NORMAL"; +ALIGN(4) char ERRTXT_LOAD_OTHR[19] = "\nERROR: LOAD OTHER"; +ALIGN(4) char ERRTXT_SEC_NORM[22] = "\nERROR: SECURE NORMAL"; +ALIGN(4) char ERRTXT_SEC_OTHR[21] = "\nERROR: SECURE OTHER"; +ALIGN(4) char ERRTXT_HEAD_CRC[19] = "\nERROR: HEADER CRC"; /*------------------------------------------------------------------------- External functions @@ -81,72 +83,58 @@ extern void arm9_clearCache (void); extern void arm9_reset (void); extern void Print(char *str); +static void waitForVBlank() { while (REG_VCOUNT!=191); while (REG_VCOUNT==191); } + /*------------------------------------------------------------------------- arm9_errorOutput -Displays an error code on screen. - -Each box is 2 bits, and left-to-right is most-significant bits to least. -Red = 00, Yellow = 01, Green = 10, Blue = 11 - -Written by Chishm +Displays an error text on screen. +Rewritten by Apache Thunder. --------------------------------------------------------------------------*/ -static void arm9_errorOutput (u32 code) { - Print(NEW_LINE); +static void arm9_errorOutput (u16 code) { switch (code) { - case (ERR_NONE) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360; - Print(TXT_STATUS); - Print(ERRTXT_NONE); + case ERR_NONE: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERRTXT_NONE); } break; - case (ERR_STS_CLR_MEM) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360; - Print(TXT_STATUS); - Print(ERRTXT_STS_CLRMEM); + case ERR_STS_START: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERRTXT_STS_START); } break; - case (ERR_STS_LOAD_BIN) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360; - Print(TXT_STATUS); - Print(ERRTXT_STS_LOAD_BIN); + case ERR_STS_CLR_MEM: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERRTXT_STS_CLRMEM); } break; - case (ERR_STS_STARTBIN) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360; - Print(TXT_STATUS); - Print(ERRTXT_STS_STARTBIN); + case ERR_STS_LOAD_BIN: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERRTXT_STS_LOAD_BIN); } break; - case (ERR_STS_START) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x8360; - Print(TXT_STATUS); - Print(ERRTXT_STS_START); + case ERR_STS_STARTBIN: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERRTXT_STS_STARTBIN); } break; - case (ERR_LOAD_NORM) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_LOAD_NORM); + case ERR_LOAD_NORM: { + BG_PALETTE_SUB[defaultFontPalSlot] = redFont; + Print((char*)ERRTXT_LOAD_NORM); } break; - case (ERR_LOAD_OTHR) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_LOAD_OTHR); + case ERR_LOAD_OTHR: { + BG_PALETTE_SUB[defaultFontPalSlot] = redFont; + Print((char*)ERRTXT_LOAD_OTHR); } break; - case (ERR_SEC_NORM) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_SEC_NORM); + case ERR_SEC_NORM: { + BG_PALETTE_SUB[defaultFontPalSlot] = redFont; + Print((char*)ERRTXT_SEC_NORM); } break; - case (ERR_SEC_OTHR) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_SEC_OTHR); + case ERR_SEC_OTHR: { + BG_PALETTE_SUB[defaultFontPalSlot] = redFont; + Print((char*)ERRTXT_SEC_OTHR); } break; - case (ERR_LOGO_CRC) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_LOGO_CRC); + case ERR_HEAD_CRC: { + BG_PALETTE_SUB[defaultFontPalSlot] = redFont; + Print((char*)ERRTXT_HEAD_CRC); } break; - case (ERR_HEAD_CRC) : { - BG_PALETTE_SUB[defaultFontPalSlot] = 0x801B; - Print(TXT_ERROR); - Print(ERRTXT_HEAD_CRC); + default: { + BG_PALETTE_SUB[defaultFontPalSlot] = greenFont; + Print((char*)ERR_NONE); } break; } } @@ -159,26 +147,40 @@ Jumps to the ARM9 NDS binary in sync with the ARM7 Written by Darkain, modified by Chishm --------------------------------------------------------------------------*/ void arm9_main (void) { - register int i; + language = 0xFFFF; + scfgUnlock = 0; + twlMode = 0; + twlCLK = 0; + // twlVRAM = 0; + twlRAM = 0; + isTWLSRL = 0; + debugMode = 0; + consoleInit = 0; + + if (launchData->language != 0xFF)language = (u16)launchData->language; + if (launchData->scfgUnlock > 0)scfgUnlock = 0xFFFF; + if (launchData->twlMode > 0)twlMode = 0xFFFF; + // if (launchData->twlVRAM > 0)twlVRAM = 0xFFFF; + if (launchData->twlRAM > 0)twlRAM = 0xFFFF; + if (launchData->twlCLK > 0)twlCLK = 0xFFFF; + if (launchData->isTWLSRL > 0)isTWLSRL = 0xFFFF; + if (launchData->debugMode > 0)debugMode = 0xFFFF; + arm9_cachedChipID = launchData->cachedChipID; - if (launchData->language != 0xFF)language = (u8)launchData->language; - if (launchData->scfgUnlock == 0x01)scfgUnlock = true; - if (launchData->twlMode == 0x01)twlMode = true; - if (launchData->twlVRAM == 0x01)TWLVRAM = true; - if (launchData->twlCLK == 0x01)twlCLK = true; - if (launchData->debugMode == 0x01)debugMode = true; - - if (twlMode) { - *((vu32*)REG_MBK1)=0x8D898581; - *((vu32*)REG_MBK2)=0x8C888480; - *((vu32*)REG_MBK3)=0x9C989490; - *((vu32*)REG_MBK4)=0x8C888480; - *((vu32*)REG_MBK5)=0x9C989490; - REG_MBK6=0x00000000; - REG_MBK7=0x07C03740; - REG_MBK8=0x07403700; + if ((isTWLSRL > 0) && (twlMode > 0) && (twlRAM > 0)) { + *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; + *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; + *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; + *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; + *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; + REG_MBK6 = *(u32*)0x02FFE194; + REG_MBK7 = *(u32*)0x02FFE198; + REG_MBK8 = *(u32*)0x02FFE19C; + REG_MBK9 = *(u32*)0x02FFE1AC; + WRAM_CR = *(u8*)0x02FFE1AF; + scfgUnlock = 0x01; } else { // MBK settings for NTR mode games *((vu32*)REG_MBK1)=0x8D898581; @@ -200,7 +202,7 @@ void arm9_main (void) { REG_IE = 0; REG_IF = ~0; - if (debugMode)arm9_errorCode = ERR_STS_START; + if (debugMode > 0)arm9_errorCode = ERR_STS_START; // Synchronise start ipcSendState(ARM9_START); @@ -276,8 +278,8 @@ void arm9_main (void) { } arm9_errorOutput (arm9_errorCode); // Halt after displaying error code - while(1); - } else if ((arm9_errorCode != ERR_NONE) && debugMode) { + while(1)waitForVBlank(); + } else if ((arm9_errorCode != ERR_NONE) && debugMode > 0) { if (!consoleInit) { BG_PALETTE_SUB[0] = RGB15(31,31,31); BG_PALETTE_SUB[255] = RGB15(0,0,0); @@ -285,13 +287,12 @@ void arm9_main (void) { miniconsoleSetWindow(5, 11, 24, 1); // Set console position for debug text if/when needed. consoleInit = true; } - while(REG_VCOUNT!=191); // Add vblank delay. Arm7 can somtimes go through the status codes pretty quick. - while(REG_VCOUNT==191); + waitForVBlank(); arm9_errorOutput (arm9_errorCode); arm9_errorCode = ERR_NONE; } } - + VRAM_C_CR = 0x80; // BG_PALETTE_SUB[0] = 0xFFFF; dmaFill((void*)&arm9_BLANK_RAM, BG_PALETTE+1, (2*1024)-2); @@ -306,14 +307,16 @@ void arm9_main (void) { videoSetModeSub(0); REG_POWERCNT = 0x820F; - if (!twlCLK)REG_SCFG_CLK = 0x80; - if (twlMode) { - REG_SCFG_EXT = 0x82073100; - REG_SCFG_RST = 1; + /*if ((twlRAM > 0) && ((twlMode == 0) || (isTWLSRL == 0))) { + *((u32*)0x027FF800) = arm9_cachedChipID; + *((u32*)0x027FFC00) = arm9_cachedChipID; } - if (!TWLVRAM)REG_SCFG_EXT &= ~(1UL << 13); - if (!scfgUnlock)REG_SCFG_EXT &= ~(1UL << 31); + *((u32*)0x02FFF800) = arm9_cachedChipID; + *((u32*)0x02FFFC00) = arm9_cachedChipID;*/ + if (twlCLK == 0) { REG_SCFG_CLK = 0x80; } else { REG_SCFG_CLK = 0x87; }; + if (scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31); + arm9_reset(); } diff --git a/BootLoader/source/miniConsole.h b/BootLoader/source/miniConsole.h index 505bf29..a836c9b 100644 --- a/BootLoader/source/miniConsole.h +++ b/BootLoader/source/miniConsole.h @@ -7,27 +7,18 @@ #include #include -static int windowX = 0; -static int windowY = 0; -static int windowWidth = 32; -static int windowHeight = 24; -static int consoleWidth = 32; -static int tabSize = 3; -static int cursorX = 0; -static int cursorY = 0; -static u16 fontCurPal = 1; -static u16* fontBgMap = BG_MAP_RAM_SUB(4); +int windowX = 0; +int windowY = 0; +int windowWidth = 32; +int windowHeight = 24; +int consoleWidth = 32; +int tabSize = 3; +int cursorX = 0; +int cursorY = 0; +u16 fontCurPal = 1; +u16* fontBgMap = BG_MAP_RAM_SUB(4); -static void miniconsoleSetWindow(int x, int y, int width, int height) { - windowX = x; - windowY = y; - windowWidth = width; - windowHeight = height; - cursorX = 0; - cursorY = 0; -} - -void miniNewRow() { +static void miniNewRow() { cursorY ++; if(cursorY >= windowHeight) { int rowCount; @@ -44,7 +35,7 @@ void miniNewRow() { } } -void miniconsolePrintChar(char c) { +static void miniconsolePrintChar(char c) { if (c==0) return; if(fontBgMap == 0) return; if(cursorX >= windowWidth) { cursorX = 0; miniNewRow(); } @@ -76,7 +67,7 @@ void miniconsolePrintChar(char c) { } } -void miniconsoleCls(char mode) { +/*static void miniconsoleCls(char mode) { int i = 0; int colTemp,rowTemp; @@ -122,13 +113,22 @@ void miniconsoleCls(char mode) { break; } } +}*/ + + +void miniconsoleSetWindow(int x, int y, int width, int height) { + windowX = x; + windowY = y; + windowWidth = width; + windowHeight = height; + cursorX = 0; + cursorY = 0; } -static void Print(char *str) { +void Print(char *str) { if (str == 0)return; while(*str)miniconsolePrintChar(*(str++)); } - #endif // MINICONSOLE_ARM9_H diff --git a/BootLoader/source/modcrypt/aes.c b/BootLoader/source/modcrypt/aes.c new file mode 100644 index 0000000..6966e93 --- /dev/null +++ b/BootLoader/source/modcrypt/aes.c @@ -0,0 +1,1165 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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. + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#include "config.h" + +#if defined(POLARSSL_AES_C) + +#include "aes.h" +#include "padlock.h" + +#include + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_ULONG_LE +#define GET_ULONG_LE(n,b,i) \ +{ \ + (n) = ( (unsigned long) (b)[(i) ] ) \ + | ( (unsigned long) (b)[(i) + 1] << 8 ) \ + | ( (unsigned long) (b)[(i) + 2] << 16 ) \ + | ( (unsigned long) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_ULONG_LE +#define PUT_ULONG_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ +} +#endif + +#if defined(POLARSSL_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned long FT0[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned long FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned long FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned long FT3[256] = { FT }; +#undef V + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const unsigned long RT0[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##b##c##d##a +static const unsigned long RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const unsigned long RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const unsigned long RT3[256] = { RT }; +#undef V + +#undef RT + +/* + * Round constants + */ +static const unsigned long RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static unsigned long FT0[256]; +static unsigned long FT1[256]; +static unsigned long FT2[256]; +static unsigned long FT3[256]; + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static unsigned long RT0[256]; +static unsigned long RT1[256]; +static unsigned long RT2[256]; +static unsigned long RT3[256]; + +/* + * Round constants + */ +static unsigned long RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for ( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for ( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (unsigned long) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for ( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y; y = ( (y << 1) | (y >> 7) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for ( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (unsigned long) y ) ^ + ( (unsigned long) x << 8 ) ^ + ( (unsigned long) x << 16 ) ^ + ( (unsigned long) z << 24 ); + + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); + + x = RSb[i]; + + RT0[i] = ( (unsigned long) MUL( 0x0E, x ) ) ^ + ( (unsigned long) MUL( 0x09, x ) << 8 ) ^ + ( (unsigned long) MUL( 0x0D, x ) << 16 ) ^ + ( (unsigned long) MUL( 0x0B, x ) << 24 ); + + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); + } +} + +#endif + +/* + * AES key schedule (encryption) + */ +int aes_setkey_enc( aes_context *ctx, const unsigned char *key, int keysize ) +{ + int i; + unsigned long *RK; + +#if !defined(POLARSSL_AES_ROM_TABLES) + if ( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + } +#endif + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(PADLOCK_ALIGN16) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); +#else + ctx->rk = RK = ctx->buf; +#endif + + for ( i = 0; i < (keysize >> 5); i++ ) + { + GET_ULONG_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for ( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for ( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for ( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (unsigned long) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (unsigned long) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + + default: + + break; + } + + return( 0 ); +} + +/* + * AES key schedule (decryption) + */ +int aes_setkey_dec( aes_context *ctx, const unsigned char *key, int keysize ) +{ + int i, j; + aes_context cty; + unsigned long *RK; + unsigned long *SK; + int ret; + + switch( keysize ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(PADLOCK_ALIGN16) + ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); +#else + ctx->rk = RK = ctx->buf; +#endif + + ret = aes_setkey_enc( &cty, key, keysize ); + if ( ret != 0 ) + return( ret ); + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for ( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for ( j = 0; j < 4; j++, SK++ ) + { + *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ + RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ + RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ + RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + memset( &cty, 0, sizeof( aes_context ) ); + + return( 0 ); +} + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ + FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ + FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y0 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ + FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ + FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + FT3[ ( Y2 >> 24 ) & 0xFF ]; \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ + RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y1 >> 24 ) & 0xFF ]; \ + \ + X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ + RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y2 >> 24 ) & 0xFF ]; \ + \ + X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ + RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y3 >> 24 ) & 0xFF ]; \ + \ + X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ + RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ + RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ + RT3[ ( Y0 >> 24 ) & 0xFF ]; \ +} + +/* + * AES-ECB block encryption/decryption + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + unsigned long *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if ( padlock_supports( PADLOCK_ACE ) ) + { + if ( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + RK = ctx->rk; + + GET_ULONG_LE( X0, input, 0 ); X0 ^= *RK++; + GET_ULONG_LE( X1, input, 4 ); X1 ^= *RK++; + GET_ULONG_LE( X2, input, 8 ); X2 ^= *RK++; + GET_ULONG_LE( X3, input, 12 ); X3 ^= *RK++; + + if ( mode == AES_DECRYPT ) + { + for ( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (unsigned long) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (unsigned long) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + } + else /* AES_ENCRYPT */ + { + for ( i = (ctx->nr >> 1) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (unsigned long) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (unsigned long) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (unsigned long) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (unsigned long) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + } + + PUT_ULONG_LE( X0, output, 0 ); + PUT_ULONG_LE( X1, output, 4 ); + PUT_ULONG_LE( X2, output, 8 ); + PUT_ULONG_LE( X3, output, 12 ); + + return( 0 ); +} + +/* + * AES-CBC buffer encryption/decryption + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + int length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if ( length % 16 ) + return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) + if ( padlock_supports( PADLOCK_ACE ) ) + { + if ( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if ( mode == AES_DECRYPT ) + { + while ( length > 0 ) + { + memcpy( temp, input, 16 ); + aes_crypt_ecb( ctx, mode, input, output ); + + for ( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while ( length > 0 ) + { + for ( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} + +/* + * AES-CFB128 buffer encryption/decryption + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + int length, + int *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, n = *iv_off; + + if ( mode == AES_DECRYPT ) + { + while ( length-- ) + { + if ( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = (n + 1) & 0x0F; + } + } + else + { + while ( length-- ) + { + if ( n == 0 ) + aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = (n + 1) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +#if defined(POLARSSL_SELF_TEST) + +#include + +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; + +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; + +/* + * Checkup routine + */ +int aes_self_test( int verbose ) +{ + int i, j, u, v, offset; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char prv[16]; + unsigned char iv[16]; + aes_context ctx; + + memset( key, 0, 32 ); + + /* + * ECB mode + */ + for ( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if ( verbose != 0 ) + printf( " AES-ECB-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if ( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for ( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if ( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for ( j = 0; j < 10000; j++ ) + aes_crypt_ecb( &ctx, v, buf, buf ); + + if ( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if ( verbose != 0 ) + printf( "passed\n" ); + } + + if ( verbose != 0 ) + printf( "\n" ); + + /* + * CBC mode + */ + for ( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if ( verbose != 0 ) + printf( " AES-CBC-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if ( v == AES_DECRYPT ) + { + aes_setkey_dec( &ctx, key, 128 + u * 64 ); + + for ( j = 0; j < 10000; j++ ) + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + if ( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + for ( j = 0; j < 10000; j++ ) + { + unsigned char tmp[16]; + + aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + if ( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if ( verbose != 0 ) + printf( "passed\n" ); + } + + if ( verbose != 0 ) + printf( "\n" ); + + /* + * CFB128 mode + */ + for ( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if ( verbose != 0 ) + printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, + ( v == AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); + + offset = 0; + aes_setkey_enc( &ctx, key, 128 + u * 64 ); + + if ( v == AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if ( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); + + if ( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) + { + if ( verbose != 0 ) + printf( "failed\n" ); + + return( 1 ); + } + } + + if ( verbose != 0 ) + printf( "passed\n" ); + } + + + if ( verbose != 0 ) + printf( "\n" ); + + return( 0 ); +} + +#endif + +#endif + diff --git a/BootLoader/source/modcrypt/aes.h b/BootLoader/source/modcrypt/aes.h new file mode 100644 index 0000000..5576680 --- /dev/null +++ b/BootLoader/source/modcrypt/aes.h @@ -0,0 +1,139 @@ +/** + * \file aes.h + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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 +#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0810 + +/** + * \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, const 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, const 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 + * + * \return 0 if successful + */ +int aes_crypt_ecb( aes_context *ctx, + int mode, + const 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 + * + * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH + */ +int aes_crypt_cbc( aes_context *ctx, + int mode, + int length, + unsigned char iv[16], + const 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 + * + * \return 0 if successful + */ +int aes_crypt_cfb128( aes_context *ctx, + int mode, + int length, + int *iv_off, + unsigned char iv[16], + const 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 */ diff --git a/BootLoader/source/modcrypt/bignum.c b/BootLoader/source/modcrypt/bignum.c new file mode 100644 index 0000000..b6ce9ee --- /dev/null +++ b/BootLoader/source/modcrypt/bignum.c @@ -0,0 +1,2452 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "bignum.h" +#include "bn_mul.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +// #include +#include +// #define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) { + volatile mbedtls_mpi_uint *p = v; while ( n-- ) *p++ = 0; +} + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if ( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if ( X == NULL ) + return; + + if ( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if ( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if ( X->n < nblimbs ) + { + if ( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if ( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if ( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for ( i = X->n - 1; i > 0; i-- ) + if ( X->p[i] != 0 ) + break; + i++; + + if ( i < nblimbs ) + i = nblimbs; + + if ( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if ( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret; + size_t i; + + if ( X == Y ) + return( 0 ); + + if ( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for ( i = Y->n - 1; i > 0; i-- ) + if ( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + + memset( X->p, 0, X->n * ciL ); + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for ( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for ( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if ( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for ( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if ( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if ( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if ( X->n * biL <= pos ) + { + if ( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for ( i = 0; i < X->n; i++ ) + for ( j = 0; j < biL; j++, count++ ) + if ( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for ( j = 0; j < biL; j++ ) + { + if ( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if ( X->n == 0 ) + return( 0 ); + + for ( i = X->n - 1; i > 0; i-- ) + if ( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +#if 0 // not used +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if ( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if ( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if ( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if ( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if ( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if ( radix == 16 ) + { + if ( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for ( i = slen, j = 0; i > 0; i--, j++ ) + { + if ( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for ( i = 0; i < slen; i++ ) + { + if ( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if ( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if ( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if ( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if ( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if ( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if ( radix >= 4 ) n >>= 1; + if ( radix >= 16 ) n >>= 1; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); + + if ( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if ( X->s == -1 ) + *p++ = '-'; + + if ( radix == 16 ) + { + int c; + size_t i, j, k; + + for ( i = X->n, k = 0; i > 0; i-- ) + { + for ( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if ( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if ( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} +#endif // not used + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if ( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if ( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if ( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if ( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while ( p-- > s ) + if ( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if ( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if ( fout != NULL ) + { + if ( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j, n; + + for ( n = 0; n < buflen; n++ ) + if ( buf[n] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for ( i = buflen, j = 0; i > n; i--, j++ ) + X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mbedtls_mpi_size( X ); + + if ( buflen < n ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for ( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if ( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if ( v0 > 0 ) + { + for ( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for ( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if ( t1 > 0 ) + { + for ( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if ( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if ( v0 > 0 ) + { + for ( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for ( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if ( v1 > 0 ) + { + for ( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for ( i = X->n; i > 0; i-- ) + if ( X->p[i - 1] != 0 ) + break; + + for ( j = Y->n; j > 0; j-- ) + if ( Y->p[j - 1] != 0 ) + break; + + if ( i == 0 && j == 0 ) + return( 0 ); + + if ( i > j ) return( 1 ); + if ( j > i ) return( -1 ); + + for ( ; i > 0; i-- ) + { + if ( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if ( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for ( i = X->n; i > 0; i-- ) + if ( X->p[i - 1] != 0 ) + break; + + for ( j = Y->n; j > 0; j-- ) + if ( Y->p[j - 1] != 0 ) + break; + + if ( i == 0 && j == 0 ) + return( 0 ); + + if ( i > j ) return( X->s ); + if ( j > i ) return( -Y->s ); + + if ( X->s > 0 && Y->s < 0 ) return( 1 ); + if ( Y->s > 0 && X->s < 0 ) return( -1 ); + + for ( ; i > 0; i-- ) + { + if ( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if ( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + + if ( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if ( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for ( j = B->n; j > 0; j-- ) + if ( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for ( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while ( c != 0 ) + { + if ( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mbedtls_mpi subtraction + */ +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for ( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while ( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; i++; d++; + } +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + + if ( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + mbedtls_mpi_init( &TB ); + + if ( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if ( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for ( n = B->n; n > 0; n-- ) + if ( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if ( A->s * B->s < 0 ) + { + if ( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if ( A->s * B->s > 0 ) + { + if ( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for ( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for ( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for ( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for ( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for ( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while ( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi TA, TB; + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if ( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if ( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for ( i = A->n; i > 0; i-- ) + if ( A->p[i - 1] != 0 ) + break; + + for ( j = B->n; j > 0; j-- ) + if ( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for ( i++; j > 0; j-- ) + mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if ( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if ( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if ( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while ( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while ( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + + if ( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + + if ( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if ( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if ( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if ( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while ( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for ( i = n; i > t ; i-- ) + { + if ( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while ( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if ( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if ( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if ( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if ( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + + if ( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while ( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while ( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + + if ( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if ( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if ( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if ( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for ( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if ( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for ( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if ( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for ( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if ( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + if ( mbedtls_mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if ( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if ( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if ( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if ( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if ( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if ( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if ( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for ( i = 0; i < wsize - 1; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for ( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while ( 1 ) + { + if ( bufsize == 0 ) + { + if ( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if ( ei == 0 && state == 0 ) + continue; + + if ( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if ( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for ( i = 0; i < wsize; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for ( i = 0; i < nbits; i++ ) + { + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + wbits <<= 1; + + if ( ( wbits & ( one << wsize ) ) != 0 ) + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if ( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for ( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if ( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +#if 0 // not used +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t lz, lzt; + mbedtls_mpi TG, TA, TB; + + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if ( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while ( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if ( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if ( size > MBEDTLS_MPI_MAX_SIZE ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); + +cleanup: + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if ( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if ( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while ( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if ( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while ( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if ( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if ( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while ( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while ( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while ( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if ( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for ( i = 0; small_prime[i] > 0; i++ ) + { + if ( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if ( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mbedtls_mpi W, R, T, A, RR; + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + i = mbedtls_mpi_bitlen( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for ( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if ( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while ( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if ( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if ( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if ( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if ( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if ( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if ( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t k, n; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + if ( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + + k = mbedtls_mpi_bitlen( X ); + if ( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits + 1 ) ); + + mbedtls_mpi_set_bit( X, nbits-1, 1 ); + + X->p[0] |= 1; + + if ( dh_flag == 0 ) + { + while ( ( ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) + { + if ( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 2 ) ); + } + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if ( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if ( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while ( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if ( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + { + break; + } + + if ( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if ( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if ( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if ( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if ( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if ( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if ( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if ( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if ( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if ( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if ( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if ( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if ( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if ( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if ( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if ( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if ( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if ( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for ( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if ( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if ( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if ( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if ( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if ( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif // not used + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/BootLoader/source/modcrypt/bignum.h b/BootLoader/source/modcrypt/bignum.h new file mode 100644 index 0000000..7bf9a73 --- /dev/null +++ b/BootLoader/source/modcrypt/bignum.h @@ -0,0 +1,761 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if ( ( ret = f ) != 0 ) goto cleanup; } while ( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can results temporarily in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI + * \param Y Source MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if ( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if ( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with buflen = 0 to obtain the + * minimum required buffer size in *olen. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read MPI from a line in an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * MBEDTLS_ERR_MPI_XXX error code + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix 16. + * + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/BootLoader/source/modcrypt/bn_mul.h b/BootLoader/source/modcrypt/bn_mul.h new file mode 100644 index 0000000..9210dd1 --- /dev/null +++ b/BootLoader/source/modcrypt/bn_mul.h @@ -0,0 +1,887 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may + * not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#include "bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) +#if defined(__i386__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4" "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#pragma message "using ARM THUMB MULADDC" + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/BootLoader/source/modcrypt/config.h b/BootLoader/source/modcrypt/config.h new file mode 100644 index 0000000..fb70eb2 --- /dev/null +++ b/BootLoader/source/modcrypt/config.h @@ -0,0 +1,5 @@ + +#define MBEDTLS_BIGNUM_C +#define POLARSSL_AES_C + +#define MBEDTLS_HAVE_ASM diff --git a/BootLoader/source/modcrypt/crypto.c b/BootLoader/source/modcrypt/crypto.c new file mode 100644 index 0000000..db69c75 --- /dev/null +++ b/BootLoader/source/modcrypt/crypto.c @@ -0,0 +1,125 @@ +#include +#include +#include "crypto.h" +#include "u128_math.h" +#include "f_xy.h" +#include "dsi.h" + +// more info: +// https://github.com/Jimmy-Z/TWLbf/blob/master/dsi.c +// https://github.com/Jimmy-Z/bfCL/blob/master/dsi.h +// ported back to 32 bit for ARM9 + +static dsi_context nand_ctx ; +static dsi_context boot2_ctx ; +static dsi_context es_ctx ; + +static uint8_t nand_ctr_iv[16]; +static uint8_t boot2_ctr[16]; + +static void generate_key(uint8_t *generated_key, const uint32_t *console_id, const key_mode_t mode) +{ + uint32_t key[4]; + switch (mode) + { + case NAND: + key[0] = console_id[0]; + key[1] = console_id[0] ^ KEYSEED_DSI_NAND_0; + key[2] = console_id[1] ^ KEYSEED_DSI_NAND_1; + key[3] = console_id[1]; + break; + case NAND_3DS: + key[0] = (console_id[0] ^ KEYSEED_3DS_NAND_0) | 0x80000000; + key[1] = KEYSEED_3DS_NAND_1; + key[2] = KEYSEED_3DS_NAND_2; + key[3] = console_id[1] ^ KEYSEED_3DS_NAND_3; + break; + case ES: + key[0] = KEYSEED_ES_0; + key[1] = KEYSEED_ES_1; + key[2] = console_id[1] ^ KEYSEED_ES_2; + key[3] = console_id[0]; + break; + default: + break; + } + u128_xor((uint8_t *)key, mode == ES ? DSi_ES_KEY_Y : DSi_NAND_KEY_Y); + u128_add((uint8_t *)key, DSi_KEY_MAGIC); + u128_lrot((uint8_t *)key, 42) ; + memcpy(generated_key, key, 16) ; +} + +int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len) +{ + uint8_t digest[SHA1_LEN]; + swiSHA1Calc(digest, data, len); + return memcmp(digest, digest_verify, SHA1_LEN); +} + +void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS) +{ + uint32_t console_id[2]; + GET_UINT32_BE(console_id[0], console_id_be, 4); + GET_UINT32_BE(console_id[1], console_id_be, 0); + + uint8_t key[16]; + generate_key(key, console_id, is3DS ? NAND_3DS : NAND); + dsi_set_key(&nand_ctx, key) ; + + generate_key(key, console_id, ES); + dsi_set_key(&es_ctx, key) ; + + dsi_set_key(&boot2_ctx, DSi_BOOT2_KEY) ; + + swiSHA1Calc(nand_ctr_iv, emmc_cid, 16); + +} + +// crypt one block, in/out must be aligned to 32 bit(restriction induced by xor_128) +// offset as block offset, block as AES block +void dsi_nand_crypt_1(uint8_t* out, const uint8_t* in, uint32_t offset) +{ + uint8_t ctr[16] ; + memcpy(ctr, nand_ctr_iv, sizeof(nand_ctr_iv)) ; + u128_add32(ctr, offset); + dsi_set_ctr(&nand_ctx, ctr) ; + dsi_crypt_ctr(&nand_ctx, in, out, 16) ; +} + +void dsi_nand_crypt(uint8_t* out, const uint8_t* in, uint32_t offset, unsigned count) +{ + uint8_t ctr[16] ; + memcpy(ctr, nand_ctr_iv, sizeof(nand_ctr_iv)) ; + u128_add32(ctr, offset); + for (unsigned i = 0; i < count; ++i) + { + dsi_set_ctr(&nand_ctx, ctr) ; + dsi_crypt_ctr(&nand_ctx, in, out, 16) ; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + u128_add32(ctr, 1); + } +} + +void dsi_boot2_crypt_set_ctr(uint32_t size_r) +{ + for (int i=0;i<4;i++) + { + boot2_ctr[i] = (size_r) >> (8*i) ; + boot2_ctr[i+4] = (-size_r) >> (8*i) ; + boot2_ctr[i+8] = (~size_r) >> (8*i) ; + boot2_ctr[i+12] = 0 ; + } +} + +void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count) +{ + for (unsigned i = 0; i < count; ++i) + { + dsi_set_ctr(&boot2_ctx, boot2_ctr) ; + dsi_crypt_ctr(&boot2_ctx, in, out, 16) ; + out += AES_BLOCK_SIZE; + in += AES_BLOCK_SIZE; + u128_add32(boot2_ctr, 1); + } +} diff --git a/BootLoader/source/modcrypt/crypto.h b/BootLoader/source/modcrypt/crypto.h new file mode 100644 index 0000000..aafd9e2 --- /dev/null +++ b/BootLoader/source/modcrypt/crypto.h @@ -0,0 +1,70 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/************************ Constants / Defines *********************************/ + +#define AES_BLOCK_SIZE 16 +#define SHA1_LEN 20 + +#define KEYSEED_DSI_NAND_0 0x24ee6906 +#define KEYSEED_DSI_NAND_1 0xe65b601d + +#define KEYSEED_3DS_NAND_0 0xb358a6af +#define KEYSEED_3DS_NAND_1 0x544e494e +#define KEYSEED_3DS_NAND_2 0x4f444e45 +#define KEYSEED_3DS_NAND_3 0x08c267b7 + +#define KEYSEED_ES_0 0x4e00004a +#define KEYSEED_ES_1 0x4a00004e +#define KEYSEED_ES_2 0xc80c4b72 + +#define GET_UINT32_BE(n, b, i) \ + ((uint8_t*)&(n))[0] = (b)[i + 3]; \ + ((uint8_t*)&(n))[1] = (b)[i + 2]; \ + ((uint8_t*)&(n))[2] = (b)[i + 1]; \ + ((uint8_t*)&(n))[3] = (b)[i + 0] + +#define PUT_UINT32_BE(n, b, i) \ + (b)[i + 0] = ((uint8_t*)&(n))[3]; \ + (b)[i + 1] = ((uint8_t*)&(n))[2]; \ + (b)[i + 2] = ((uint8_t*)&(n))[1]; \ + (b)[i + 3] = ((uint8_t*)&(n))[0] + + +typedef enum { + ENCRYPT, + DECRYPT +} crypt_mode_t; + +typedef enum { + NAND, + NAND_3DS, + ES +} key_mode_t; + + +// don't want to include nds.h just for this +void swiSHA1Calc(void *digest, const void *buf, size_t len); + +int dsi_sha1_verify(const void *digest_verify, const void *data, unsigned len); + +void dsi_crypt_init(const uint8_t *console_id_be, const uint8_t *emmc_cid, int is3DS); + +void dsi_nand_crypt_1(uint8_t *out, const uint8_t* in, u32 offset); + +void dsi_nand_crypt(uint8_t *out, const uint8_t* in, u32 offset, unsigned count); + +int dsi_es_block_crypt(uint8_t *buf, unsigned buf_len, crypt_mode_t mode); + +void dsi_boot2_crypt_set_ctr(uint32_t size_r); + +void dsi_boot2_crypt(uint8_t* out, const uint8_t* in, unsigned count); + +#ifdef __cplusplus +} +#endif diff --git a/BootLoader/source/modcrypt/dsi.c b/BootLoader/source/modcrypt/dsi.c new file mode 100644 index 0000000..cca4b48 --- /dev/null +++ b/BootLoader/source/modcrypt/dsi.c @@ -0,0 +1,346 @@ +#include "dsi.h" +#include +#include +#include +#include +#include "u128_math.h" + +void dsi_set_key( dsi_context* ctx, + const unsigned char key[16] ) +{ + unsigned char keyswap[16]; + u128_swap(keyswap, key) ; + + aes_setkey_enc(&ctx->aes, keyswap, 128); +} + +void dsi_add_ctr( dsi_context* ctx, + unsigned int carry) +{ + unsigned int counter[4]; + unsigned char *outctr = (unsigned char*)ctx->ctr; + unsigned int sum; + signed int i; + + for (i = 0; i < 4; i++) + counter[i] = (outctr[i * 4 + 0] << 24) | (outctr[i * 4 + 1] << 16) | + (outctr[i * 4 + 2] << 8) | (outctr[i * 4 + 3] << 0); + + for (i = 3; i >= 0; i--) { + sum = counter[i] + carry; + carry = (uint)(sum < counter[i]); + + counter[i] = sum; + } + + for (i = 0; i < 4; i++) { + outctr[i * 4 + 0] = counter[i] >> 24; + outctr[i * 4 + 1] = counter[i] >> 16; + outctr[i * 4 + 2] = counter[i] >> 8; + outctr[i * 4 + 3] = counter[i] >> 0; + } +} + +void dsi_set_ctr( dsi_context* ctx, const unsigned char ctr[16] ) { + for (int i = 0; i < 16; i++)ctx->ctr[i] = ctr[15-i]; +} + +void dsi_init_ctr( dsi_context* ctx, const unsigned char key[16], const unsigned char ctr[16]) { +// void dsi_init_ctr( dsi_context* ctx, const unsigned char key[16], const unsigned char ctr[12]) { + dsi_set_key(ctx, key); + dsi_set_ctr(ctx, ctr); +} + +void dsi_crypt_ctr( dsi_context* ctx, + const 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, + const 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) { + return -1; + } + + if (chksize != size) { + return -2; + } + + 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 -3; + } + + 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( (unsigned int)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); + +} + diff --git a/BootLoader/source/modcrypt/dsi.h b/BootLoader/source/modcrypt/dsi.h new file mode 100644 index 0000000..d7acfc0 --- /dev/null +++ b/BootLoader/source/modcrypt/dsi.h @@ -0,0 +1,105 @@ +#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, + const unsigned char key[16] ); + +void dsi_add_ctr( dsi_context* ctx, + unsigned int carry ); + +void dsi_set_ctr( dsi_context* ctx, + const unsigned char ctr[16] ); + +void dsi_init_ctr( dsi_context* ctx, + const unsigned char key[16], + const unsigned char ctr[16]); + +void dsi_crypt_ctr( dsi_context* ctx, + const void* in, + void* out, + unsigned int len); + +void dsi_crypt_ctr_block( dsi_context* ctx, + const 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_ + diff --git a/BootLoader/source/modcrypt/f_xy.c b/BootLoader/source/modcrypt/f_xy.c new file mode 100644 index 0000000..374924c --- /dev/null +++ b/BootLoader/source/modcrypt/f_xy.c @@ -0,0 +1,50 @@ +/* f_xy.c + * + * This file was imported from godmode9i, but it is liely not the + * original source. twltool uses the same file. + * + * If you happen to know whom to credit I'd love to add the name + * + * Refactored to reduce the pointer casts and remove the dependency + * from tonccpy. + */ + +#include +#include +#include "u128_math.h" + + +/************************ Constants / Defines *********************************/ + +const uint8_t DSi_KEY_MAGIC[16] = { 0x79, 0x3e, 0x4f, 0x1a, 0x5f, 0x0f, 0x68, 0x2a, + 0x58, 0x02, 0x59, 0x29, 0x4e, 0xfb, 0xfe, 0xff }; +const uint8_t DSi_NAND_KEY_Y[16] = { 0x76, 0xdc, 0xb9, 0x0a, 0xd3, 0xc4, 0x4d, 0xbd, + 0x1d, 0xdd, 0x2d, 0x20, 0x05, 0x00, 0xa0, 0xe1 }; +const uint8_t DSi_ES_KEY_Y[16] = { 0xe5, 0xcc, 0x5a, 0x8b, 0x56, 0xd0, 0xc9,0x72, + 0x9c, 0x17, 0xe8, 0xdc, 0x39, 0x12, 0x36, 0xa9 }; +const uint8_t DSi_BOOT2_KEY[16] = { 0x98, 0xee, 0x80, 0x80, 0x00, 0x6c, 0xb4, 0xf6, + 0x3a, 0xc2, 0x6e, 0x62, 0xf9, 0xec, 0x34, 0xad }; + +/************************ Functions *******************************************/ + +void F_XY(uint8_t *key, const uint8_t *key_x, const uint8_t *key_y) +{ + uint8_t key_xy[16]; + + for (int i=0; i<16; i++) + key_xy[i] = key_x[i] ^ key_y[i]; + + memcpy(key, DSi_KEY_MAGIC, sizeof(DSi_KEY_MAGIC)); + + u128_add(key, key_xy); + u128_lrot(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(const uint8_t *key, uint8_t *key_xy) +{ + memcpy(key_xy, key, 16); + u128_rrot(key_xy, 42); + u128_sub(key_xy, DSi_KEY_MAGIC); +} + diff --git a/BootLoader/source/modcrypt/f_xy.h b/BootLoader/source/modcrypt/f_xy.h new file mode 100644 index 0000000..383868e --- /dev/null +++ b/BootLoader/source/modcrypt/f_xy.h @@ -0,0 +1,36 @@ +/* f_xy.h + * + * This file was imported from godmode9i, but it is liely not the + * original source. twltool uses the same file. + * + * If you happen to know whom to credit I'd love to add the name + * + * Refactored to reduce the pointer casts and remove the dependency + * from tonccpy. + */ + +#ifndef _H_F_XY +#define _H_F_XY + +#ifdef __cplusplus +extern "C" { +#endif + +/************************ Constants / Defines *********************************/ + +extern const uint8_t DSi_KEY_MAGIC[16] ; +extern const uint8_t DSi_NAND_KEY_Y[16] ; +extern const uint8_t DSi_ES_KEY_Y[16] ; +extern const uint8_t DSi_BOOT2_KEY[16] ; + +/************************ Function Protoypes **********************************/ + +void F_XY(uint8_t *key, const uint8_t *key_x, const uint8_t *key_y); +void F_XY_reverse(const uint8_t *key, uint8_t *key_xy); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/BootLoader/source/modcrypt/padlock.h b/BootLoader/source/modcrypt/padlock.h new file mode 100644 index 0000000..86f019e --- /dev/null +++ b/BootLoader/source/modcrypt/padlock.h @@ -0,0 +1,98 @@ +/** + * \file padlock.h + * + * Copyright (C) 2006-2010, Brainspark B.V. + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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_PADLOCK_H +#define POLARSSL_PADLOCK_H + +#include "aes.h" + +#if defined(POLARSSL_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) + +#ifndef POLARSSL_HAVE_X86 +#define POLARSSL_HAVE_X86 +#endif + +#define PADLOCK_RNG 0x000C +#define PADLOCK_ACE 0x00C0 +#define PADLOCK_PHE 0x0C00 +#define PADLOCK_PMM 0x3000 + +#define PADLOCK_ALIGN16(x) (unsigned long *) (16 + ((long) x & ~15)) + +#define POLARSSL_ERR_PADLOCK_DATA_MISALIGNED -0x08E0 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PadLock detection routine + * + * \param The feature to detect + * + * \return 1 if CPU has support for the feature, 0 otherwise + */ +int padlock_supports( int feature ); + +/** + * \brief PadLock AES-ECB block en(de)cryption + * + * \param ctx AES context + * \param mode AES_ENCRYPT or AES_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptecb( aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief PadLock AES-CBC buffer en(de)cryption + * + * \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 + * + * \return 0 if success, 1 if operation failed + */ +int padlock_xcryptcbc( aes_context *ctx, + int mode, + int length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#ifdef __cplusplus +} +#endif + +#endif /* HAVE_X86 */ + +#endif /* padlock.h */ diff --git a/BootLoader/source/modcrypt/u128_math.c b/BootLoader/source/modcrypt/u128_math.c new file mode 100644 index 0000000..e6b2abe --- /dev/null +++ b/BootLoader/source/modcrypt/u128_math.c @@ -0,0 +1,106 @@ +// u128_math + +#include "u128_math.h" +#include + +// rotate a 128bit, little endian by shift bits in direction of increasing significance. +void u128_lrot(uint8_t *num, uint32_t shift) +{ + uint8_t tmp[16]; + for (int i=0;i<16;i++) + { + // rot: rotate to more significant. + // LSB is tmp[0], MSB is tmp[15] + const uint32_t byteshift = shift / 8 ; + const uint32_t bitshift = shift % 8; + tmp[(i+byteshift) % 16] = (num[i] << bitshift) + | ((num[(i+16-1) % 16] >> (8-bitshift)) & 0xff); + } + memcpy(num, tmp, 16) ; +} + +// rotate a 128bit, little endian by shift bits in direction of decreasing significance. +void u128_rrot(uint8_t *num, uint32_t shift) +{ + uint8_t tmp[16]; + for (int i=0;i<16;i++) + { + // rot: rotate to less significant. + // LSB is tmp[0], MSB is tmp[15] + const uint32_t byteshift = shift / 8 ; + const uint32_t bitshift = shift % 8; + tmp[i] = (num[(i+byteshift) % 16] >> bitshift) + | ((num[(i+byteshift+1) % 16] << (8-bitshift)) & 0xff); + } + memcpy(num, tmp, 16) ; +} + +// xor two 128bit, little endian values and store the result into the first +void u128_xor(uint8_t *a, const uint8_t *b) +{ + for (int i=0;i<16;i++) + { + a[i] = a[i] ^ b[i] ; + } +} + +// or two 128bit, little endian values and store the result into the first +void u128_or(uint8_t *a, const uint8_t *b) +{ + for (int i=0;i<16;i++) + { + a[i] = a[i] | b[i] ; + } +} + +// and two 128bit, little endian values and store the result into the first +void u128_and(uint8_t *a, const uint8_t *b) +{ + for (int i=0;i<16;i++) + { + a[i] = a[i] & b[i] ; + } +} + + +// add two 128bit, little endian values and store the result into the first +void u128_add(uint8_t *a, const uint8_t *b) +{ + uint8_t carry = 0 ; + for (int i=0;i<16;i++) + { + uint16_t sum = a[i] + b[i] + carry ; + a[i] = sum & 0xff ; + carry = sum >> 8 ; + } +} + +// add two 128bit, little endian values and store the result into the first +void u128_add32(uint8_t *a, const uint32_t b) +{ + uint8_t _b[16]; + memset(_b, 0, sizeof(_b)) ; + for (int i=0;i<4;i++) + _b[i] = b >> (i*8) ; + u128_add(a, _b); +} + +// sub two 128bit, little endian values and store the result into the first +void u128_sub(uint8_t *a, const uint8_t *b) +{ + uint8_t carry = 0 ; + for (int i=0;i<16;i++) + { + uint16_t sub = a[i] - b[i] - (carry & 1); + a[i] = sub & 0xff ; + carry = sub >> 8 ; + } +} + +void u128_swap(uint8_t *out, const uint8_t *in) +{ + for (int i=0;i<16;i++) + { + out[15-i] = in[i]; + } +} \ No newline at end of file diff --git a/BootLoader/source/modcrypt/u128_math.h b/BootLoader/source/modcrypt/u128_math.h new file mode 100644 index 0000000..114b500 --- /dev/null +++ b/BootLoader/source/modcrypt/u128_math.h @@ -0,0 +1,38 @@ +// u128_math + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +// left rotate by (shift % 128) bits +void u128_lrot(uint8_t *num, uint32_t shift) ; + +// right rotate by (shift % 128) bits +void u128_rrot(uint8_t *num, uint32_t shift) ; + +// bitwise xor strored to a +void u128_xor(uint8_t *a, const uint8_t *b) ; + +// bitwise or strored to a +void u128_or(uint8_t *a, const uint8_t *b) ; + +// bitwise and strored to a +void u128_and(uint8_t *a, const uint8_t *b) ; + +// add b to a and store in a +void u128_add(uint8_t *a, const uint8_t *b) ; + +// add 32 bit value b to a and store in a +void u128_add32(uint8_t *a, const uint32_t b) ; + +// substract b from a and store in a +void u128_sub(uint8_t *a, const uint8_t *b) ; + +// swap byte order +void u128_swap(uint8_t *out, const uint8_t *in) ; + +#ifdef __cplusplus +} +#endif \ No newline at end of file diff --git a/BootLoader/source/read_bios.h b/BootLoader/source/read_bios.h deleted file mode 100755 index 4efa97f..0000000 --- a/BootLoader/source/read_bios.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - NitroHax -- Cheat tool for the Nintendo DS - Copyright (C) 2008 Michael "Chishm" Chisholm - - 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 . -*/ - #include - -void readBios (u8* dest, u32 src, u32 size); - diff --git a/BootLoader/source/read_bios.s b/BootLoader/source/read_bios.s deleted file mode 100755 index 57474ef..0000000 --- a/BootLoader/source/read_bios.s +++ /dev/null @@ -1,54 +0,0 @@ -#include - -@This code comes from a post by CaitSith2 at gbadev.org - THANKS!! -@ -@Code to dump the complete Nintendo DS ARM7 bios, including the -@first 0x1204 bytes residing in the secure area. -@ -@The ARM7 bios has read protection where 0x(Word)[FFFF(Half word)[FF(Byte)[FF]]] -@is returned, if any reads are attempted while PC is outside the arm7 bios range. -@ -@Additionally, if the PC is outside the 0x0000 - 0x1204 range, that range of the bios -@is completely locked out from reading. - - -@ void readBios (u8* dest, u32 src, u32 size) - - .arm - -BEGIN_ASM_FUNC readBios - adr r3,bios_dump+1 - bx r3 - .thumb - -bios_dump: - push {r4-r7,lr} @Even though we don't use R7, the code we are jumping to is going - @trash R7, therefore, we must save it. - mov r5, r1 @ src - sub r1, r2, #1 @ size - mov r2, r0 @ dest - ldr r0,=0x5ED @The code that will be made to read the full bios resides here. - -loop: - mov r6,#0x12 @We Subtract 12 from the location we wish to read - sub r3,r1,r6 @because the code at 0x5EC is LDRB R3, [R3,#0x12] - add r3, r3, r5 - adr r6,ret - push {r2-r6} @The line of code at 0x5EE is POP {R2,R4,R6,R7,PC} - bx r0 - .align - -ret: - strb r3,[r2,r1] @Store the read byte contained in r3, to SRAM. - sub r1,#1 @Subtract 1 - bpl loop @And branch as long as R1 doesn't roll into -1 (0xFFFFFFFF). - - pop {r4-r7} @Restore the saved registers - pop {r3} @and return. - bx r3 - - .END - -@The exact code that resides at 0x5EC (secure area range) of the arm7 bios. -@ROM:000005EC 9B 7C LDRB R3, [R3,#0x12] -@ROM:000005EE D4 BD POP {R2,R4,R6,R7,PC} diff --git a/BootLoader/source/read_card.c b/BootLoader/source/read_card.c index fef797c..66cd640 100755 --- a/BootLoader/source/read_card.c +++ b/BootLoader/source/read_card.c @@ -20,9 +20,6 @@ #include #include -#include -#include -#include #include #include @@ -30,25 +27,72 @@ #include "common.h" #include "tonccpy.h" +#define BASE_DELAY (100) + +/*#define ARM7OWNSCARD BIT(11) +#define ARM7OWNSROM BIT(7)*/ + typedef union { char title[4]; u32 key; } GameCode; +/*void SetCardOwner(bool arm9) { + REG_EXMEMSTAT = (REG_EXMEMSTAT & ~ARM7OWNSCARD) | (arm9 ? 0 : ARM7OWNSCARD); +}*/ + +static u32 twlBlowfish = 0; +static u32 normalChip = 0; static u32 portFlags = 0; static u32 secureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)]; +static ALIGN(4) u32 twlSecureAreaData[CARD_SECURE_AREA_SIZE/sizeof(u32)]; // static bool shortInit = false; +// static u32 iCardId; + +// u32 cardGetId() { return iCardId; } + +static const u8 cardSeedBytes[] = { 0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5 }; + +void EnableSlot1() { + int oldIME = enterCriticalSection(); + + while((REG_SCFG_MC & 0x0c) == 0x0c) swiDelay(1 * BASE_DELAY); + + if(!(REG_SCFG_MC & 0x0c)) { + REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 4; + swiDelay(20 * BASE_DELAY); + REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 8; + swiDelay(20 * BASE_DELAY); + } + + /*REG_ROMCTRL = 0x20000000; // wait 27ms, then set ROMCTRL=20000000h + while((REG_ROMCTRL & 0x8000000))swiDelay(1 * BASE_DELAY);*/ + + leaveCriticalSection(oldIME); +} + +void DisableSlot1() { + int oldIME = enterCriticalSection(); + + while((REG_SCFG_MC & 0x0c) == 0x0c) swiDelay(1 * BASE_DELAY); + + if((REG_SCFG_MC & 0x0c) == 8) { + REG_SCFG_MC = (REG_SCFG_MC & ~0x0c) | 0x0c; + while((REG_SCFG_MC & 0x0c) != 0) swiDelay(1 * BASE_DELAY); + } + + leaveCriticalSection(oldIME); +} -static const u8 cardSeedBytes[] = {0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5}; // chosen by fair dice roll. // guaranteed to be random. // static u32 getRandomNumber(void) { return 4; } -static u32 getRandomNumber(void) { return rand(); } // make this actually random lol. :P +// static u32 getRandomNumber(void) { return rand(); } // make this actually random lol. :P +static u32 getRandomNumber(void) { return 0xDDAC86F5; } -static void decryptSecureArea (u32 gameCode, u32* secureArea) { - int i; - init_keycode (gameCode, 2, 8); +static void decryptSecureArea (u32 gameCode, u32* secureArea, int iCardDevice) { + init_keycode (gameCode, 2, 8, iCardDevice); crypt_64bit_down (secureArea); - init_keycode (gameCode, 3, 8); - for (i = 0; i < 0x200; i+= 2) { crypt_64bit_down (secureArea + i); } + init_keycode (gameCode, 3, 8, iCardDevice); + for (int i = 0; i < 0x200; i+= 2)crypt_64bit_down (secureArea + i); } static struct { @@ -61,7 +105,7 @@ static struct { } key1data; -static void initKey1Encryption (u8* cmdData) { +static void initKey1Encryption (u8* cmdData, int iCardDevice) { key1data.iii = getRandomNumber() & 0x00000fff; key1data.jjj = getRandomNumber() & 0x00000fff; key1data.kkkkk = getRandomNumber() & 0x000fffff; @@ -69,7 +113,11 @@ static void initKey1Encryption (u8* cmdData) { key1data.mmm = getRandomNumber() & 0x00000fff; key1data.nnn = getRandomNumber() & 0x00000fff; - cmdData[7] = CARD_CMD_ACTIVATE_BF; + if (iCardDevice) //DSi + cmdData[7]=0x3D; // CARD_CMD_ACTIVATE_BF2 + else + cmdData[7]=CARD_CMD_ACTIVATE_BF; + cmdData[6] = (u8) (key1data.iii >> 4); cmdData[5] = (u8) ((key1data.iii << 4) | (key1data.jjj >> 8)); cmdData[4] = (u8) key1data.jjj; @@ -122,10 +170,118 @@ static void cardDelay (u16 readTimeout) { TIMER_DATA(0) = 0; } +static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) { + if ((twlBlowfish == 0) || ndsHeader->unitCode == 0) return; + + // Used for dumping the DSi arm9i/7i binaries -u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { u32 portFlagsKey1, portFlagsSecRead; - bool normalChip; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000 + int secureBlockNumber; + int i; + u8 cmdData[8] __attribute__ ((aligned)); + GameCode* gameCode; + + if (REG_SCFG_EXT & BIT(31)) { + // int oldIME = 0; + // Reset card slot + DisableSlot1(); + // oldIME = enterCriticalSection(); + swiDelay(40 * BASE_DELAY); + // leaveCriticalSection(oldIME); + EnableSlot1(); + // oldIME = enterCriticalSection(); + swiDelay(30 * BASE_DELAY); + // leaveCriticalSection(oldIME); + } + + // Dummy command sent after card reset + cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0); + + //int iCardDevice = 1; + + // Initialise blowfish encryption for KEY1 commands and decrypting the secure area + gameCode = (GameCode*)ndsHeader->gameCode; + init_keycode (gameCode->key, 1, 8, 1); + + // Port 40001A4h setting for normal reads (command B7) + portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); + // Port 40001A4h setting for KEY1 commands (usually 001808F8h) + portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | + ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)); + + // Adjust card transfer method depending on the most significant bit of the chip ID + if (normalChip == 0)portFlagsKey1 |= CARD_SEC_LARGE; + + // 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode + initKey1Encryption(cmdData, 1); + cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData); + + // 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode + createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0); + + if (normalChip > 0) { + cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); + cardDelay(ndsHeader->readTimeout); + } + cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); + + // Set the KEY2 encryption registers + REG_ROMCTRL = 0; + REG_CARD_1B0 = cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000; + REG_CARD_1B4 = 0x879b9b05; + REG_CARD_1B8 = key1data.mmm >> 5; + REG_CARD_1BA = 0x5c; + REG_ROMCTRL = CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT; + + // Update the DS card flags to suit KEY2 encryption + portFlagsKey1 |= CARD_SEC_EN | CARD_SEC_DAT; + + // 1lllliii jjjkkkkk - 2nd Get ROM Chip ID / Get KEY2 Stream + createEncryptedCommand (CARD_CMD_SECURE_CHIPID, cmdData, 0); + + if (normalChip > 0) { + cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); + cardDelay(ndsHeader->readTimeout); + } + cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData); + + // 2bbbbiii jjjkkkkk - Get Secure Area Block + portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) + | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT; + + int secureAreaOffset = 0; + for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) { + createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber); + + if (normalChip > 0) { + cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData); + cardDelay(ndsHeader->readTimeout); + for (i = 8; i > 0; i--) { + cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(1), twlSecureAreaData + secureAreaOffset, 0x200, cmdData); + secureAreaOffset += 0x200/sizeof(u32); + } + } else { + cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE, twlSecureAreaData + secureAreaOffset, 0x1000, cmdData); + secureAreaOffset += 0x1000/sizeof(u32); + } + } + + // Alllliii jjjkkkkk - Enter Main Data Mode + createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0); + + if (normalChip > 0) { + cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); + cardDelay(ndsHeader->readTimeout); + } + cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); + + twlBlowfish = 0x01; +} + + +u16 cardInit (sNDSHeaderExt* ndsHeader, u32 *chipID) { + u32 portFlagsKey1, portFlagsSecRead; + normalChip = 0; // As defined by GBAtek, normal chip secure area is accessed in blocks of 0x200, other chip in blocks of 0x1000 u32* secureArea; int secureBlockNumber; int i; @@ -133,6 +289,8 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { GameCode* gameCode; // shortInit = false; + // SetCardOwner(false); + // Dummy command sent after card reset cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0); @@ -140,36 +298,43 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { static_assert(sizeof(tNDSHeader) == 0x160, "tNDSHeader not packed properly"); // Read the header - cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (u32*)ndsHeader, sizeof(tNDSHeader)); - + cardReadHeader((u8*)ndsHeader); + // cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (u32*)ndsHeader, sizeof(tNDSHeader)); + // while (REG_ROMCTRL & CARD_BUSY); + // Check header CRC if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC; - + + // 1st Get ROM Chip ID + cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), chipID, sizeof(u32)); + // iCardId = cardReadID((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7)); + // iCardId = cardReadID(CARD_CLK_SLOW); + // chipID = cardReadID(CARD_CLK_SLOW); + while (REG_ROMCTRL & CARD_BUSY); + + // *chipID = iCardId; + // Initialise blowfish encryption for KEY1 commands and decrypting the secure area gameCode = (GameCode*)ndsHeader->gameCode; - init_keycode (gameCode->key, 2, 8); + init_keycode (gameCode->key, 2, 8, 0); // Port 40001A4h setting for normal reads (command B7) portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); // Port 40001A4h setting for KEY1 commands (usually 001808F8h) portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)); - - // 1st Get ROM Chip ID - cardParamCommand (CARD_CMD_HEADER_CHIPID, 0, (ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE | CARD_BLK_SIZE(7), chipID, sizeof(u32)); - while (REG_ROMCTRL & CARD_BUSY); // Adjust card transfer method depending on the most significant bit of the chip ID - normalChip = ((*chipID) & 0x80000000) != 0; // ROM chip ID MSB - if (!normalChip)portFlagsKey1 |= CARD_SEC_LARGE; + if(((*chipID) & 0x80000000) != 0)normalChip = 0xFFFF; // ROM chip ID MSB + if (normalChip == 0)portFlagsKey1 |= CARD_SEC_LARGE; // 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode - initKey1Encryption (cmdData); + initKey1Encryption (cmdData, 0); cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData); // 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0); - if (normalChip) { + if (normalChip > 0) { cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); @@ -191,7 +356,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { // 1lllliii jjjkkkkk - 2nd Get ROM Chip ID / Get KEY2 Stream createEncryptedCommand (CARD_CMD_SECURE_CHIPID, cmdData, 0); - if (normalChip) { + if (normalChip > 0) { cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData); @@ -205,7 +370,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) { createEncryptedCommand (CARD_CMD_SECURE_READ, cmdData, secureBlockNumber); - if (normalChip) { + if (normalChip > 0) { cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); for (i = 8; i > 0; i--) { @@ -221,7 +386,7 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { // Alllliii jjjkkkkk - Enter Main Data Mode createEncryptedCommand (CARD_CMD_DATA_MODE, cmdData, 0); - if (normalChip) { + if (normalChip > 0) { cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); @@ -230,47 +395,52 @@ u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID) { } // Now deal with secure area decryption and verification - decryptSecureArea (gameCode->key, secureAreaData); + decryptSecureArea (gameCode->key, secureAreaData, 0); secureArea = secureAreaData; if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) { // Secure area exists, so just clear the tag secureArea[0] = 0xe7ffdeff; secureArea[1] = 0xe7ffdeff; - }/* else { - // Secure area tag is not there, so destroy the entire secure area - for (i = 0; i < 0x200; i ++) { - *secureArea++ = 0xe7ffdeff; - } - return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR; - }*/ + } return ERR_NONE; } -void cardRead (u32 src, u32* dest, size_t size) { +void cardRead(sNDSHeaderExt* ndsHeader, u32 src, u32* dest, size_t size) { size_t readSize; - if ((src < CARD_SECURE_AREA_OFFSET) /*&& !shortInit*/) { + if ((twlBlowfish == 0) && (ndsHeader->unitCode & BIT(1)) && (src > ndsHeader->romSize))switchToTwlBlowfish(ndsHeader); + + if (src < CARD_SECURE_AREA_OFFSET) { return; } else if (src < CARD_DATA_OFFSET) { // Read data from secure area readSize = src + size < CARD_DATA_OFFSET ? size : CARD_DATA_OFFSET - src; - memcpy (dest, (u8*)secureAreaData + src - CARD_SECURE_AREA_OFFSET, readSize); + tonccpy (dest, (u8*)secureAreaData + src - CARD_SECURE_AREA_OFFSET, readSize); src += readSize; dest += readSize/sizeof(*dest); size -= readSize; + } else if ((ndsHeader->unitCode & BIT(1)) && (twlBlowfish > 0) && (src >= ndsHeader->arm9iromOffset) && (src < ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE)) { + // Read data from secure area + readSize = src + size < (ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE) ? size : (ndsHeader->arm9iromOffset+CARD_SECURE_AREA_SIZE) - src; + tonccpy (dest, (u8*)twlSecureAreaData + src - ndsHeader->arm9iromOffset, readSize); + src += readSize; + dest += readSize/sizeof(*dest); + size -= readSize; + if (size <= 0)return; } - + while (size > 0) { readSize = size < CARD_DATA_BLOCK_SIZE ? size : CARD_DATA_BLOCK_SIZE; - cardParamCommand (CARD_CMD_DATA_READ, src, (portFlags &~CARD_BLK_SIZE(7)) | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize); + cardParamCommand (CARD_CMD_DATA_READ, src, portFlags | CARD_ACTIVATE | CARD_nRESET | CARD_BLK_SIZE(1), dest, readSize); src += readSize; dest += readSize/sizeof(*dest); size -= readSize; } } + // If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done. // System Menu is nice enough to do this for you. :P // (also is the case for booting from DS Download Play. ;) ) @@ -291,7 +461,7 @@ void cardRead (u32 src, u32* dest, size_t size) { // Initialise blowfish encryption for KEY1 commands and decrypting the secure area gameCode = (GameCode*)ndsHeader->gameCode; - init_keycode (gameCode->key, 2, 8); + init_keycode (gameCode->key, 2, 8, 0); // Port 40001A4h setting for normal reads (command B7) portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); @@ -314,7 +484,7 @@ void cardRead (u32 src, u32* dest, size_t size) { cardRead (ndsHeader->arm9romOffset, secureArea, secureBlockSize); // Now deal with secure area decryption and verification - decryptSecureArea (gameCode->key, secureAreaData); + decryptSecureArea (gameCode->key, secureAreaData, 0); secureArea = secureAreaData; if (secureArea[0] == 0x72636e65 && secureArea[1] == 0x6a624f79) { diff --git a/BootLoader/source/read_card.h b/BootLoader/source/read_card.h index 2750fe1..3c668f0 100755 --- a/BootLoader/source/read_card.h +++ b/BootLoader/source/read_card.h @@ -20,7 +20,6 @@ #define READ_CARD_H #include -#include #include #define CARD_NDS_HEADER_SIZE (0x200) @@ -121,8 +120,9 @@ typedef struct { u8 dsi3[0x174]; } sNDSHeaderExt; -u32 cardInit (sNDSHeaderExt* ndsHeader, u32* chipID); -void cardRead (u32 src, u32* dest, size_t size); +// u32 cardGetId(); +u16 cardInit (sNDSHeaderExt* ndsHeader, u32 *chipID); +void cardRead (sNDSHeaderExt* ndsHeader, u32 src, u32* dest, size_t size); // u32 cardInitShort (sNDSHeaderExt* ndsHeader, u32* chipID); #endif // READ_CARD_H diff --git a/BootLoader/source/reset.arm7.s b/BootLoader/source/reset.arm7.s index 34f3ac3..344ee8a 100644 --- a/BootLoader/source/reset.arm7.s +++ b/BootLoader/source/reset.arm7.s @@ -64,7 +64,7 @@ arm7_reset: @ ipcSendState(ARM7_BOOT) strh r0, [r12] - ldr r0,=0x27FFE34 + ldr r0,=0x2FFFE34 ldr r0,[r0] bx r0 diff --git a/BootLoader/source/reset.arm9.s b/BootLoader/source/reset.arm9.s index d36d8a1..5d2a256 100644 --- a/BootLoader/source/reset.arm9.s +++ b/BootLoader/source/reset.arm9.s @@ -100,7 +100,7 @@ arm9_reset: @ while (ipcRecvState() != ARM7_BOOT); bl waitsync - ldr r10, =0x27FFE24 + ldr r10, =0x2FFFE24 ldr r2, [r10] @ Switch MPU to startup default @@ -130,6 +130,6 @@ mpu_initial_data: .word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3 .word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4 .word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6 - .word 0x027ff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB + .word 0x02fff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB .word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size itcm_reset_code_end: \ No newline at end of file diff --git a/CartFiles/NTR_Launcher/CycloDS.nds b/CartFiles/NTR_Launcher/CycloDS.nds new file mode 100644 index 0000000..149fb3c Binary files /dev/null and b/CartFiles/NTR_Launcher/CycloDS.nds differ diff --git a/CartFiles/NTR_Launcher/DSONEi.nds b/CartFiles/NTR_Launcher/DSONEi.nds new file mode 100644 index 0000000..772bba2 Binary files /dev/null and b/CartFiles/NTR_Launcher/DSONEi.nds differ diff --git a/CartFiles/NTR_Launcher/DSTwo.nds b/CartFiles/NTR_Launcher/DSTwo.nds index 847de31..4e79567 100644 Binary files a/CartFiles/NTR_Launcher/DSTwo.nds and b/CartFiles/NTR_Launcher/DSTwo.nds differ diff --git a/CartFiles/NTR_Launcher/NCARD.nds b/CartFiles/NTR_Launcher/NCARD.nds new file mode 100644 index 0000000..c404045 Binary files /dev/null and b/CartFiles/NTR_Launcher/NCARD.nds differ diff --git a/CartFiles/NTR_Launcher/NTR_Launcher.ini b/CartFiles/NTR_Launcher/NTR_Launcher.ini index 453fc2c..af17373 100644 --- a/CartFiles/NTR_Launcher/NTR_Launcher.ini +++ b/CartFiles/NTR_Launcher/NTR_Launcher.ini @@ -1,7 +1,8 @@ [NTRLAUNCHER] -TWLCLOCK = 0 -TWLVRAM = 0 TWLMODE = 0 +TWLRAM = 0 +TWLVRAM = 0 +TWLCLOCK = 0 SCFGUNLOCK = 0 ANIMATEDSPLASH = 0 NTRSPLASH = 0 diff --git a/CartFiles/NTR_Launcher/R4iGold_Launcher.nds b/CartFiles/NTR_Launcher/R4iGold_Launcher.nds index aecc3f6..688bef1 100644 Binary files a/CartFiles/NTR_Launcher/R4iGold_Launcher.nds and b/CartFiles/NTR_Launcher/R4iGold_Launcher.nds differ diff --git a/CartFiles/NTR_Launcher/R4i_SDHC_AVRJ.nds b/CartFiles/NTR_Launcher/R4i_SDHC_AVRJ.nds index c30e768..3660b51 100644 Binary files a/CartFiles/NTR_Launcher/R4i_SDHC_AVRJ.nds and b/CartFiles/NTR_Launcher/R4i_SDHC_AVRJ.nds differ diff --git a/Makefile b/Makefile index 29948de..9519810 100755 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ export TARGET := NTR_Launcher export TOPDIR := $(CURDIR) export VERSION_MAJOR := 3 -export VERSION_MINOR := 1 +export VERSION_MINOR := 2 export VERSTRING := $(VERSION_MAJOR).$(VERSION_MINOR) # specify a directory which contains the nitro filesystem @@ -24,6 +24,7 @@ NITRO_FILES := CartFiles #--------------------------------------------------------------------------------- # main targets +# -g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 \ #--------------------------------------------------------------------------------- all: bootloader ndsbootloader $(TARGET).nds @@ -34,8 +35,8 @@ dist: all $(TARGET).nds: $(TARGET).arm7 $(TARGET).arm9 ndstool -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf \ - -b $(CURDIR)/icon.bmp "NTR Launcher;Slot-1 Launcher;Apache Thunder & RocketRobz" \ - -g KKGP 01 "NTR Launcher" -z 80040000 -u 00030004 -a 00000138 -p 0001 \ + -b $(CURDIR)/icon.bmp "NTR Launcher v$(VERSTRING);Slot-1 Launcher;Apache Thunder & RocketRobz" \ + -g KKGP 01 "NTR Launcher" -z 80040407 -u 00030004 -a 00000138 -p 0001 \ -d $(NITRO_FILES) @cp $(TARGET).nds 00000000.app diff --git a/arm7/Makefile b/arm7/Makefile index 8871d23..c842a15 100755 --- a/arm7/Makefile +++ b/arm7/Makefile @@ -24,8 +24,8 @@ DATA := #--------------------------------------------------------------------------------- ARCH := -mthumb-interwork -march=armv4t -mtune=arm7tdmi -CFLAGS := -g -Wall -O2\ - -fomit-frame-pointer\ +CFLAGS := -g -Wall -O2 \ + -fomit-frame-pointer \ -ffast-math \ $(ARCH) diff --git a/arm7/source/main.c b/arm7/source/main.c index 906f756..a8e51c7 100755 --- a/arm7/source/main.c +++ b/arm7/source/main.c @@ -218,7 +218,7 @@ int main(void) { irqSet(IRQ_VCOUNT, VcountHandler); irqSet(IRQ_VBLANK, VblankHandler); - irqEnable( IRQ_VBLANK | IRQ_VCOUNT); + irqEnable(IRQ_VBLANK | IRQ_VCOUNT); i2cWriteRegister(0x4A, 0x12, 0x00); // Press power-button for auto-reset i2cWriteRegister(0x4A, 0x70, 0x01); // Bootflag = Warmboot/SkipHealthSafety diff --git a/arm9/Makefile b/arm9/Makefile index 174a96d..bdca3fb 100755 --- a/arm9/Makefile +++ b/arm9/Makefile @@ -27,7 +27,7 @@ MUSIC := audio ARCH := -march=armv5te -mtune=arm946e-s -mthumb -mthumb-interwork CFLAGS := -g -Wall -O2 \ - -fomit-frame-pointer\ + -fomit-frame-pointer \ -ffast-math \ $(ARCH) diff --git a/arm9/common/audio.cpp b/arm9/common/audio.twl.cpp similarity index 100% rename from arm9/common/audio.cpp rename to arm9/common/audio.twl.cpp diff --git a/arm9/common/crc.c b/arm9/common/crc.twl.c similarity index 100% rename from arm9/common/crc.c rename to arm9/common/crc.twl.c diff --git a/arm9/common/defaultBanners.s b/arm9/common/defaultBanners.s index a413bdb..96d66c1 100644 --- a/arm9/common/defaultBanners.s +++ b/arm9/common/defaultBanners.s @@ -1,6 +1,7 @@ .arm - .global dsCardDefault_bin, hbNoIcon_bin + .global dsCardDefault_bin, dsCardInvalid_bin, hbNoIcon_bin dsCardDefault_bin: .incbin "../include/dsCardDefault.bin" +dsCardInvalid_bin: .incbin "../include/dsCardInvalid.bin" hbNoIcon_bin: .incbin "../include/hbNoIcon.bin" diff --git a/arm9/common/encryption.c b/arm9/common/encryption.twl.c similarity index 100% rename from arm9/common/encryption.c rename to arm9/common/encryption.twl.c diff --git a/arm9/common/inifile.cpp b/arm9/common/inifile.twl.cpp similarity index 100% rename from arm9/common/inifile.cpp rename to arm9/common/inifile.twl.cpp diff --git a/arm9/common/launcherData.h b/arm9/common/launcherData.h index da1c8b4..e4d9d6b 100644 --- a/arm9/common/launcherData.h +++ b/arm9/common/launcherData.h @@ -1,21 +1,3 @@ -/* - NitroHax -- Cheat tool for the Nintendo DS - Copyright (C) 2008 Michael "Chishm" Chisholm - - 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 . -*/ - #ifndef LAUNCHERDATA_H #define LAUNCHERDATA_H @@ -23,13 +5,12 @@ extern "C" { #endif -#define LAUNCH_DATA 0x020007F0 #define CartHeaderCopy 0x02000000 #define CartChipIDCopy 0x02000180 -#define CartBannerBuffer 0x02500000 -// #define InitialCartBannerOffset 0x02FFC068 +#define LAUNCH_DATA 0x020007F0 +// #define InitialCartBannerOffset 0x02FFC068 #define InitialCartHeaderTWL 0x02FFC000 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare! #define InitialCartHeader 0x02FFFA80 // System Menu keeps cart's header here (if cart is present) on initial boot of any DSiWare! #define InitialCartChipID 0x02FFFC00 // System Menu keeps cart's chip id here (if cart is present) on initial boot of any DSiWare! @@ -40,10 +21,11 @@ typedef struct sLauncherSettings { u8 scfgUnlock; u8 twlMode; u8 twlCLK; + u8 twlRAM; u8 twlVRAM; u8 debugMode; - u8 fastBoot; - u8 unused2; + u8 isTWLSRL; + u32 cachedChipID; } tLauncherSettings; diff --git a/arm9/common/nds_card.c b/arm9/common/nds_card.twl.c similarity index 87% rename from arm9/common/nds_card.c rename to arm9/common/nds_card.twl.c index 7e9f46d..bd0c3e3 100644 --- a/arm9/common/nds_card.c +++ b/arm9/common/nds_card.twl.c @@ -19,16 +19,18 @@ #include #include #include "nds_card.h" +#include "read_card.h" void CardReset(bool properReset) { int i; sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart if (isDSiMode()) { // Reset card slot - disableSlot1(); + /*disableSlot1(); for (i = 0; i < 25; i++) { swiWaitForVBlank(); } enableSlot1(); - for (i = 0; i < 15; i++) { swiWaitForVBlank(); } + for (i = 0; i < 15; i++) { swiWaitForVBlank(); }*/ + ResetSlot(); if (!properReset) { // Dummy command sent after card reset @@ -43,9 +45,9 @@ void CardReset(bool properReset) { for (i = 0; i < 10; i++) { swiWaitForVBlank(); } REG_AUXSPICNT=CARD_CR1_ENABLE|CARD_CR1_IRQ; REG_ROMCTRL=CARD_nRESET|CARD_SEC_SEED; - while (REG_ROMCTRL&CARD_BUSY); + while (REG_ROMCTRL&CARD_BUSY)swiWaitForVBlank(); cardReset(); - while (REG_ROMCTRL&CARD_BUSY); + while (REG_ROMCTRL&CARD_BUSY)swiWaitForVBlank(); } } diff --git a/arm9/common/ndsheaderbanner.h b/arm9/common/ndsheaderbanner.h index 133b2e3..68d9e34 100644 --- a/arm9/common/ndsheaderbanner.h +++ b/arm9/common/ndsheaderbanner.h @@ -139,3 +139,4 @@ typedef struct { //static_assert(sizeof(sNDSHeaderExt) == 0x3B4, "sizeof(sNDSHeaderExt) is not 0x3B4 bytes"); #endif // NDS_HEADER2 + diff --git a/arm9/common/nitrofs.c b/arm9/common/nitrofs.twl.c similarity index 100% rename from arm9/common/nitrofs.c rename to arm9/common/nitrofs.twl.c diff --git a/arm9/common/read_card.h b/arm9/common/read_card.h index f8821bc..20b6c91 100644 --- a/arm9/common/read_card.h +++ b/arm9/common/read_card.h @@ -39,8 +39,10 @@ extern "C" { extern u32 cardNandRomEnd; extern u32 cardNandRwStart; -int cardInit (sNDSHeaderExt* ndsHeader); -int cardInitShort(sNDSHeaderExt* ndsHeader); +void ResetSlot(); + +u32 cardInit (sNDSHeaderExt* ndsHeader); +u32 cardInitShort(sNDSHeaderExt* ndsHeader); void cardRead (u32 src, void* dest, bool nandSave); void cardReadAlt (u32 src, void* dest, size_t size); diff --git a/arm9/common/read_card.c b/arm9/common/read_card.twl.c similarity index 87% rename from arm9/common/read_card.c rename to arm9/common/read_card.twl.c index bbb00eb..03516ad 100644 --- a/arm9/common/read_card.c +++ b/arm9/common/read_card.twl.c @@ -72,7 +72,18 @@ u32 cardNandRwStart = 0; static const u8 cardSeedBytes[] = { 0xE8, 0x4D, 0x5A, 0xB1, 0x17, 0x8F, 0x99, 0xD5 }; -static u32 getRandomNumber(void) { return rand(); } +static u32 getRandomNumber() { return 0xDDAC86F5; } + +void ResetSlot() { + // Reset card slot + if((REG_SCFG_MC != 0x11) && (REG_SCFG_MC != 0x10)) { + disableSlot1(); + for(int i = 0; i < 15; i++)swiWaitForVBlank(); + } + enableSlot1(); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); + for(int i = 0; i < 15; i++)swiWaitForVBlank(); +} //--------------------------------------------------------------------------------- // https://github.com/devkitPro/libnds/blob/105d4943dbac8f2bd99a47b22cd3ed48f96af083/source/common/card.c#L47-L62 @@ -302,8 +313,7 @@ static void switchToTwlBlowfish(sNDSHeaderExt* ndsHeader) { twlBlowfish = true; } - -int cardInit (sNDSHeaderExt* ndsHeader) { +u32 cardInit (sNDSHeaderExt* ndsHeader) { u32 portFlagsKey1, portFlagsSecRead; normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000 nandChip = false; @@ -316,41 +326,37 @@ int cardInit (sNDSHeaderExt* ndsHeader) { twlBlowfish = false; sysSetCardOwner (BUS_OWNER_ARM9); // Allow arm9 to access NDS cart + if (isDSiMode()) { - // Reset card slot - if(REG_SCFG_MC != 0x11){ - disableSlot1(); - for(i = 0; i < 15; i++)swiWaitForVBlank(); - } - enableSlot1(); - for(i = 0; i < 10; i++)swiWaitForVBlank(); + ResetSlot(); // Dummy command sent after card reset cardParamCommand (CARD_CMD_DUMMY, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), NULL, 0); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); } - REG_ROMCTRL=0; - REG_AUXSPICNT=0; + /*REG_ROMCTRL = 0; + REG_AUXSPICNT = 0; //ioDelay2(167550); for(i = 0; i < 25; i++) { swiWaitForVBlank(); } - REG_AUXSPICNT=CARD_CR1_ENABLE|CARD_CR1_IRQ; - REG_ROMCTRL=CARD_nRESET|CARD_SEC_SEED; - while(REG_ROMCTRL&CARD_BUSY) ; + REG_AUXSPICNT = (CARD_CR1_ENABLE | CARD_CR1_IRQ); + REG_ROMCTRL = (CARD_nRESET | CARD_SEC_SEED); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); cardReset(); - while(REG_ROMCTRL&CARD_BUSY) ; + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank();*/ toncset(headerData, 0, 0x1000); // Read the header - cardParamCommand (CARD_CMD_HEADER_READ, 0, - CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), - (void*)headerData, 0x200/sizeof(u32)); - while(REG_ROMCTRL&CARD_BUSY); + cardReadHeader((u8*)headerData); + /*cardParamCommand (CARD_CMD_HEADER_READ, 0, CARD_ACTIVATE | CARD_nRESET | CARD_CLK_SLOW | CARD_BLK_SIZE(1) | CARD_DELAY1(0x1FFF) | CARD_DELAY2(0x3F), (void*)headerData, 0x200/sizeof(u32)); + while(REG_ROMCTRL & CARD_BUSY);*/ tonccpy(ndsHeader, headerData, 0x200); - iCardId=cardReadID(CARD_CLK_SLOW); - while(REG_ROMCTRL & CARD_BUSY); - + iCardId = cardReadID(CARD_CLK_SLOW); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); + *(u32*)InitialCartChipID = iCardId; + normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip @@ -377,35 +383,23 @@ int cardInit (sNDSHeaderExt* ndsHeader) { } // Check header CRC - if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E)) { - return ERR_HEAD_CRC; - } - - /* - // Check logo CRC - if (ndsHeader->logoCRC16 != 0xCF56) { - return ERR_LOGO_CRC; - } - */ + if (ndsHeader->headerCRC16 != swiCRC16(0xFFFF, (void*)ndsHeader, 0x15E))return ERR_HEAD_CRC; // Initialise blowfish encryption for KEY1 commands and decrypting the secure area gameCode = (GameCode*)ndsHeader->gameCode; init_keycode (gameCode->key, 2, 8, 0); // Port 40001A4h setting for normal reads (command B7) - portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); + portFlags = (ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7)); // Port 40001A4h setting for KEY1 commands (usually 001808F8h) - portFlagsKey1 = CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | - ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16)); + portFlagsKey1 = (CARD_ACTIVATE | CARD_nRESET | (ndsHeader->cardControl13 & (CARD_WR|CARD_CLK_SLOW)) | ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF))) + ((ndsHeader->cardControlBF & CARD_DELAY2(0x3F)) >> 16))); // Adjust card transfer method depending on the most significant bit of the chip ID - if (!normalChip) { - portFlagsKey1 |= CARD_SEC_LARGE; - } + if (!normalChip)portFlagsKey1 |= CARD_SEC_LARGE; // 3Ciiijjj xkkkkkxx - Activate KEY1 Encryption Mode initKey1Encryption (cmdData, 0); - cardPolledTransfer((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE, NULL, 0, cmdData); + cardPolledTransfer (((ndsHeader->cardControl13 & (CARD_WR|CARD_nRESET|CARD_CLK_SLOW)) | CARD_ACTIVATE), NULL, 0, cmdData); // 4llllmmm nnnkkkkk - Activate KEY2 Encryption Mode createEncryptedCommand (CARD_CMD_ACTIVATE_SEC, cmdData, 0); @@ -418,11 +412,11 @@ int cardInit (sNDSHeaderExt* ndsHeader) { // Set the KEY2 encryption registers REG_ROMCTRL = 0; - REG_CARD_1B0 = cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000; - REG_CARD_1B4 = 0x879b9b05; - REG_CARD_1B8 = key1data.mmm >> 5; + REG_CARD_1B0 = (cardSeedBytes[ndsHeader->deviceType & 0x07] | (key1data.nnn << 15) | (key1data.mmm << 27) | 0x6000); + REG_CARD_1B4 = 0x879B9B05; + REG_CARD_1B8 = (key1data.mmm >> 5); REG_CARD_1BA = 0x5c; - REG_ROMCTRL = CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT; + REG_ROMCTRL = (CARD_nRESET | CARD_SEC_SEED | CARD_SEC_EN | CARD_SEC_DAT); // Update the DS card flags to suit KEY2 encryption portFlagsKey1 |= CARD_SEC_EN | CARD_SEC_DAT; @@ -434,11 +428,10 @@ int cardInit (sNDSHeaderExt* ndsHeader) { cardPolledTransfer(portFlagsKey1, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); } - cardPolledTransfer(portFlagsKey1 | CARD_BLK_SIZE(7), NULL, 0, cmdData); + cardPolledTransfer((portFlagsKey1 | CARD_BLK_SIZE(7)), NULL, 0, cmdData); // 2bbbbiii jjjkkkkk - Get Secure Area Block - portFlagsSecRead = (ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) - | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT; + portFlagsSecRead = ((ndsHeader->cardControlBF & (CARD_CLK_SLOW|CARD_DELAY1(0x1FFF)|CARD_DELAY2(0x3F))) | CARD_ACTIVATE | CARD_nRESET | CARD_SEC_EN | CARD_SEC_DAT); int secureAreaOffset = 0; for (secureBlockNumber = 4; secureBlockNumber < 8; secureBlockNumber++) { @@ -448,11 +441,11 @@ int cardInit (sNDSHeaderExt* ndsHeader) { cardPolledTransfer(portFlagsSecRead, NULL, 0, cmdData); cardDelay(ndsHeader->readTimeout); for (i = 8; i > 0; i--) { - cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(1), secureArea + secureAreaOffset, 0x200, cmdData); + cardPolledTransfer((portFlagsSecRead | CARD_BLK_SIZE(1)), (secureArea + secureAreaOffset), 0x200, cmdData); secureAreaOffset += 0x200/sizeof(u32); } } else { - cardPolledTransfer(portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE, secureArea + secureAreaOffset, 0x1000, cmdData); + cardPolledTransfer((portFlagsSecRead | CARD_BLK_SIZE(4) | CARD_SEC_LARGE), (secureArea + secureAreaOffset), 0x1000, cmdData); secureAreaOffset += 0x1000/sizeof(u32); } } @@ -469,12 +462,10 @@ int cardInit (sNDSHeaderExt* ndsHeader) { //CycloDS doesn't like the dsi secure area being decrypted if((ndsHeader->arm9romOffset != 0x4000) || secureArea[0] || secureArea[1])decryptSecureArea (gameCode->key, secureArea, 0); - if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) { + if (secureArea[0] == 0x72636E65 /*'encr'*/ && secureArea[1] == 0x6A624F79 /*'yObj'*/) { // Secure area exists, so just clear the tag - secureArea[0] = 0xe7ffdeff; - secureArea[1] = 0xe7ffdeff; - } else { - //return normalChip ? ERR_SEC_NORM : ERR_SEC_OTHR; + secureArea[0] = 0xE7FFDEFF; + secureArea[1] = 0xE7FFDEFF; } // Set NAND card section location variables @@ -496,7 +487,7 @@ int cardInit (sNDSHeaderExt* ndsHeader) { // If booted from DSi System Menu short cart init with no card reads or pokes to rom ctrl registers can be done. // System Menu is nice enough to do this for you. :P // (also is the case for booting from DS Download Play. ;) ) -int cardInitShort(sNDSHeaderExt* ndsHeader) { +u32 cardInitShort(sNDSHeaderExt* ndsHeader) { normalChip = false; // As defined by GBAtek, normal chip secure area and header are accessed in blocks of 0x200, other chip in blocks of 0x1000 nandChip = false; nandSection = -1; @@ -515,8 +506,8 @@ int cardInitShort(sNDSHeaderExt* ndsHeader) { iCardId = *(u32*)CartChipIDCopy; // This location contains cart's chipID when booting DSiWare that has Slot-1 access. // iCardId = *(u32*)0x027FF800; // This location contains cart's chipID for DS Download Play users - normalChip = (iCardId & BIT(31)) != 0; // ROM chip ID MSB - nandChip = (iCardId & BIT(27)) != 0; // Card has a NAND chip + normalChip = ((iCardId & BIT(31)) != 0); // ROM chip ID MSB + nandChip = ((iCardId & BIT(27)) != 0); // Card has a NAND chip tonccpy(ndsHeader, headerData, 0x200); @@ -528,20 +519,20 @@ int cardInitShort(sNDSHeaderExt* ndsHeader) { init_keycode (gameCode->key, 2, 8, 0); // Port 40001A4h setting for normal reads (command B7) - portFlags = ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7); + portFlags = (ndsHeader->cardControl13 & ~CARD_BLK_SIZE(7)); - if (secureArea[0] == 0x72636e65 /*'encr'*/ && secureArea[1] == 0x6a624f79 /*'yObj'*/) { + if (secureArea[0] == 0x72636E65 /*'encr'*/ && secureArea[1] == 0x6A624F79 /*'yObj'*/) { // Secure area exists, so just clear the tag - secureArea[0] = 0xe7ffdeff; - secureArea[1] = 0xe7ffdeff; + secureArea[0] = 0xE7FFDEFF; + secureArea[1] = 0xE7FFDEFF; } // Set NAND card section location variables if (nandChip) { if(ndsHeader->nandRomEnd != 0) { // TWL cards (Face Training) multiply by 0x80000 instead of 0x20000 - cardNandRomEnd = ndsHeader->nandRomEnd * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000); - cardNandRwStart = ndsHeader->nandRwStart * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000); + cardNandRomEnd = (ndsHeader->nandRomEnd * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000)); + cardNandRwStart = (ndsHeader->nandRwStart * (ndsHeader->unitCode == 0 ? 0x20000 : 0x80000)); } else { // Jam with the Band (J) (大合奏!バンドブラザーズ) doesn't have the RW section in the header cardNandRomEnd = 0x7200000; diff --git a/arm9/common/tonccpy.itcm.c b/arm9/common/tonccpy.itcm.c new file mode 100644 index 0000000..09f80ec --- /dev/null +++ b/arm9/common/tonccpy.itcm.c @@ -0,0 +1,126 @@ +#include +#include "tonccpy.h" +//# tonccpy.c + +//! VRAM-safe cpy. +/*! This version mimics memcpy in functionality, with + the benefit of working for VRAM as well. It is also + slightly faster than the original memcpy, but faster + implementations can be made. + \param dst Destination pointer. + \param src Source pointer. + \param size Fill-length in bytes. + \note The pointers and size need not be word-aligned. +*/ +void tonccpy(void *dst, const void *src, uint size) { + + if(size==0 || dst==NULL || src==NULL) { return; } + + uint count; + u16 *dst16; // hword destination + u8 *src8; // byte source + + // Ideal case: copy by 4x words. Leaves tail for later. + if( ((u32)src|(u32)dst)%4==0 && size>=4) { + u32 *src32= (u32*)src, *dst32= (u32*)dst; + + count= size/4; + uint tmp= count&3; + count /= 4; + + // Duff's Device, good friend! + // Added fall through attribute to silance the compiler about this. ;) + switch(tmp) { + do { *dst32++ = *src32++; // fallthrough + case 3: *dst32++ = *src32++; // fallthrough + case 2: *dst32++ = *src32++; // fallthrough + case 1: *dst32++ = *src32++; // fallthrough + case 0: ;} while(count--); // fallthrough + } + + // Check for tail + size &= 3; + if(size == 0) { return; } + src8= (u8*)src32; + dst16= (u16*)dst32; + } else { + // Unaligned. + uint dstOfs= (u32)dst&1; + src8= (u8*)src; + dst16= (u16*)(dst-dstOfs); + + // Head: 1 byte. + if(dstOfs != 0) { + *dst16= (*dst16 & 0xFF) | *src8++<<8; + dst16++; + if(--size==0) { return; } + } + } + + // Unaligned main: copy by 2x byte. + count= size/2; + while(count--) { + *dst16++ = src8[0] | src8[1]<<8; + src8 += 2; + } + + // Tail: 1 byte. + if(size&1) { *dst16= (*dst16 &~ 0xFF) | *src8; } +} +//# toncset.c + +//! VRAM-safe memset, internal routine. +/*! This version mimics memset in functionality, with + the benefit of working for VRAM as well. It is also + slightly faster than the original memset. + \param dst Destination pointer. + \param fill Word to fill with. + \param size Fill-length in bytes. + \note The \a dst pointer and \a size need not be + word-aligned. In the case of unaligned fills, \a fill + will be masked off to match the situation. +*/ +void __toncset(void *dst, u32 fill, uint size) { + if(size==0 || dst==NULL) { return; } + + uint left= (u32)dst&3; + u32 *dst32= (u32*)(dst-left); + u32 count, mask; + + // Unaligned head. + if(left != 0) { + // Adjust for very small stint. + if(left+size<4) { + mask= BIT_MASK(size*8)<<(left*8); + *dst32= (*dst32 &~ mask) | (fill & mask); + return; + } + + mask= BIT_MASK(left*8); + *dst32= (*dst32 & mask) | (fill&~mask); + dst32++; + size -= 4-left; + } + + // Main stint. + count= size/4; + uint tmp= count&3; + count /= 4; + + // Added fall through attribute to silance the compiler about this. ;) + switch(tmp) { + do { *dst32++ = fill; // fallthrough + case 3: *dst32++ = fill; // fallthrough + case 2: *dst32++ = fill; // fallthrough + case 1: *dst32++ = fill; // fallthrough + case 0: ;} while(count--); // fallthrough + } + + // Tail + size &= 3; + if(size) { + mask= BIT_MASK(size*8); + *dst32= (*dst32 &~ mask) | (fill & mask); + } +} + diff --git a/arm9/hbmenu/args.cpp b/arm9/hbmenu/args.twl.cpp similarity index 100% rename from arm9/hbmenu/args.cpp rename to arm9/hbmenu/args.twl.cpp diff --git a/arm9/hbmenu/file_browse.h b/arm9/hbmenu/file_browse.h index f091667..0533f02 100644 --- a/arm9/hbmenu/file_browse.h +++ b/arm9/hbmenu/file_browse.h @@ -25,12 +25,13 @@ #include #include #include "read_card.h" +#include "launcherData.h" extern bool cartInsertedOnBoot; extern sNDSHeaderExt ntrHeader; -std::string browseForFile (const std::vector& extensionList); +std::string browseForFile (const std::vector& extensionList, tLauncherSettings launchdata); #endif //FILE_BROWSE_H diff --git a/arm9/hbmenu/file_browse.cpp b/arm9/hbmenu/file_browse.twl.cpp similarity index 92% rename from arm9/hbmenu/file_browse.cpp rename to arm9/hbmenu/file_browse.twl.cpp index 59b5347..5197b63 100644 --- a/arm9/hbmenu/file_browse.cpp +++ b/arm9/hbmenu/file_browse.twl.cpp @@ -35,6 +35,8 @@ #include "iconTitle.h" #include "read_card.h" #include "audio.h" +#include "tonccpy.h" +#include "launcherData.h" #define SCREEN_COLS 30 #define ENTRIES_PER_SCREEN 20 @@ -60,18 +62,24 @@ extern bool cartSelected; bool cartInsertedOnBoot = false; -static void cartCheck() { +static void cartCheck(tLauncherSettings launchdata) { switch (REG_SCFG_MC) { case 0x10: { if (!cardInserted)cardInserted = true; initialLoad = false; - if (cartInsertedOnBoot)cartInsertedOnBoot = false; + if (cartInsertedOnBoot) { + cartInsertedOnBoot = false; + launchdata.cachedChipID = 0x00000000; + } }break; case 0x11: { cardInserted = false; initialLoad = false; if (cartSelected)cartSelected = false; - if (cartInsertedOnBoot)cartInsertedOnBoot = false; + if (cartInsertedOnBoot) { + cartInsertedOnBoot = false; + launchdata.cachedChipID = 0x00000000; + } }break; case 0x18: { cardInserted = true; @@ -85,10 +93,12 @@ static void cartCheck() { } if (cartInsertedOnBoot)cartInsertedOnBoot = false; if (cartSelected)cartSelected = false; + launchdata.cachedChipID = 0x00000000; ToggleBackground(true); return; } if (cardInserted && initialLoad) { + launchdata.cachedChipID = *(u32*)0x02FFFC00; cardInitShort(&ntrHeader); cartIconUpdate(0, initialLoad); initialLoad = false; @@ -97,7 +107,9 @@ static void cartCheck() { ToggleBackground(false); } else if (cardInserted && !cardLoaded){ cardInit(&ntrHeader); - for (int i = 0; i < 25; i++)swiWaitForVBlank(); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); + launchdata.cachedChipID = cardGetId(); + for (int i = 0; i < 30; i++)swiWaitForVBlank(); cartIconUpdate(ntrHeader.bannerOffset, false); ToggleBackground(false); cardLoaded = true; @@ -202,7 +214,7 @@ void showDirectoryContents (const vector& dirContents, int startRow) { } } -string browseForFile (const vector& extensionList) { +string browseForFile (const vector& extensionList, tLauncherSettings launchdata) { int pressed = 0; int screenOffset = 0; int fileOffset = 0; @@ -223,7 +235,7 @@ string browseForFile (const vector& extensionList) { // Power saving loop. Only poll the keys once per frame and sleep the CPU if there is nothing else to do do { - cartCheck(); + cartCheck(launchdata); scanKeys(); pressed = keysDownRepeat(); swiWaitForVBlank(); diff --git a/arm9/hbmenu/hbmenu.cpp b/arm9/hbmenu/hbmenu.twl.cpp similarity index 64% rename from arm9/hbmenu/hbmenu.cpp rename to arm9/hbmenu/hbmenu.twl.cpp index bf67e6a..f4e2bd4 100644 --- a/arm9/hbmenu/hbmenu.cpp +++ b/arm9/hbmenu/hbmenu.twl.cpp @@ -42,53 +42,61 @@ using namespace std; -// ALIGN(4) sNDSHeaderExt NTRHeader; - static char gameTitle[13] = {0}; -// static char gameCode[5] = {0}; -static u8* fileBuffer; +static ALIGN(4) u8* fileBuffer; +static const int FileListSize = 13; +static const u32 FileMaxSize = 0x500000; -static const char* NitroSourceFileList[9] = { - "nitro:/NTR_Launcher/Acekard2i.nds", - "nitro:/NTR_Launcher/ActionReplayDS.nds", - "nitro:/NTR_Launcher/DSTwo.nds", - "nitro:/NTR_Launcher/EZFlashV.nds", - "nitro:/NTR_Launcher/R4DS_Ultra.nds", - "nitro:/NTR_Launcher/R4i_SDHC_AVRJ.nds", - "nitro:/NTR_Launcher/R4iGold_Launcher.nds", - "nitro:/NTR_Launcher/R4iSDHC_Demon.nds", - "nitro:/NTR_Launcher/TTDS.nds" +static const char* NitroSourceFileList[FileListSize] = { + "nitro:/NTR_Launcher/Acekard2i.nds", // 0 + "nitro:/NTR_Launcher/ActionReplayDS.nds", // 1 + "nitro:/NTR_Launcher/CycloDS.nds", // 2 + "nitro:/NTR_Launcher/DSONEi.nds", // 3 + "nitro:/NTR_Launcher/DSTwo.nds", // 4 + "nitro:/NTR_Launcher/EZFlashV.nds", // 5 + "nitro:/NTR_Launcher/NCARD.nds", // 6 + "nitro:/NTR_Launcher/R4DS.nds", // 7 + "nitro:/NTR_Launcher/R4DS_Ultra.nds", // 8 + "nitro:/NTR_Launcher/R4i_SDHC_AVRJ.nds", // 9 + "nitro:/NTR_Launcher/R4iGold_Launcher.nds", // 10 + "nitro:/NTR_Launcher/R4iSDHC_Demon.nds", // 11 + "nitro:/NTR_Launcher/TTDS.nds" // 12 }; -static const char* NitroDestFileList[9] = { - "sd:/NTR_Launcher/Acekard2i.nds", - "sd:/NTR_Launcher/ActionReplayDS.nds", - "sd:/NTR_Launcher/DSTwo.nds", - "sd:/NTR_Launcher/EZFlashV.nds", - "sd:/NTR_Launcher/R4DS_Ultra.nds", - "sd:/NTR_Launcher/R4i_SDHC_AVRJ.nds", - "sd:/NTR_Launcher/R4iGold_Launcher.nds", - "sd:/NTR_Launcher/R4iSDHC_Demon.nds", - "sd:/NTR_Launcher/TTDS.nds" +static const char* NitroDestFileList[FileListSize] = { + "sd:/NTR_Launcher/Acekard2i.nds", // 0 + "sd:/NTR_Launcher/ActionReplayDS.nds", // 1 + "sd:/NTR_Launcher/CycloDS.nds", // 2 + "sd:/NTR_Launcher/DSONEi.nds", // 3 + "sd:/NTR_Launcher/DSTwo.nds", // 4 + "sd:/NTR_Launcher/EZFlashV.nds", // 5 + "sd:/NTR_Launcher/NCARD.nds", // 6 + "sd:/NTR_Launcher/R4DS.nds", // 7 + "sd:/NTR_Launcher/R4DS_Ultra.nds", // 8 + "sd:/NTR_Launcher/R4i_SDHC_AVRJ.nds", // 9 + "sd:/NTR_Launcher/R4iGold_Launcher.nds", // 10 + "sd:/NTR_Launcher/R4iSDHC_Demon.nds", // 11 + "sd:/NTR_Launcher/TTDS.nds" // 12 }; static void DoWait(int waitTime = 30) { for (int i = 0; i < waitTime; i++)swiWaitForVBlank(); }; static void DoCardInit() { + sysSetCardOwner(BUS_OWNER_ARM9); switch (REG_SCFG_MC) { case 0x10: { enableSlot1(); DoWait(15); }break; case 0x11: { enableSlot1(); DoWait(15); }break; } // Do cart init stuff to wake cart up. DLDI init may fail otherwise! - CardReset(true); - cardReadHeader((u8*)&ntrHeader); + cardInit(&ntrHeader); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); + // CardReset(true); + // cardReadHeader((u8*)&ntrHeader); CardReset(false); - // cardInit(&ntrHeader); tonccpy(gameTitle, ntrHeader.gameTitle, 12); - // tonccpy(gameCode, ntrHeader.gameCode, 4); - // DoWait(25); + while(REG_ROMCTRL & CARD_BUSY)swiWaitForVBlank(); } @@ -121,30 +129,28 @@ static int stop(void) { } static void CheckFolder() { - // if (sizeof(NitroSourceFileList) != sizeof(NitroDestFileList))return; bool copyNeeded = false; - int listSize = 8; - for (int i = 0; i < listSize; i++) { + int i = 0; + for (i = 0; i < FileListSize; i++) { if (access(NitroDestFileList[i], F_OK) != 0) { copyNeeded = true; break; } } if (!copyNeeded)return; + printf("\n\n\n\n\n\n\n\n\n Setting up Stage2 folder"); printf("\n\n Please Wait...\n"); - u32 BufferSize = 0x40000; - fileBuffer = (u8*)malloc(BufferSize); - for (int i = 0; i < listSize; i++) { + fileBuffer = (u8*)malloc(FileMaxSize); + for (i = 0; i < FileListSize; i++) { if (access(NitroDestFileList[i], F_OK) != 0) { FILE *src = fopen(NitroSourceFileList[i], "rb"); if (src) { fseek(src, 0, SEEK_END); u32 fSize = ftell(src); - // toncset((u8*)fileBuffer, 0xFF, fSize); fseek(src, 0, SEEK_SET); - if (fSize <= BufferSize) { + if (fSize <= FileMaxSize) { FILE *dest = fopen(NitroDestFileList[i], "wb"); if (dest) { fread((u8*)fileBuffer, 1, fSize, src); @@ -164,7 +170,7 @@ static int BrowserUI(tLauncherSettings launchdata) { vector extensionList = argsGetExtensionList(); chdir("sd:/NTR_Launcher"); while(1) { - string filename = browseForFile(extensionList); + string filename = browseForFile(extensionList, launchdata); if (cartSelected)break; // Construct a command line vector argarray; @@ -176,6 +182,16 @@ static int BrowserUI(tLauncherSettings launchdata) { vector c_args; for (const auto& arg: argarray) { c_args.push_back(arg.c_str()); } // Try to run the NDS file with the given arguments + if (access(c_args[0], F_OK) == 0) { + FILE *src = fopen(c_args[0], "rb"); + if (src) { + fread((u8*)0x02FFE000, 1, 0x200, src); + if (((tNDSHeader*)0x02FFE000)->unitCode & BIT(1))launchdata.isTWLSRL = 0xFF; + fclose(src); + } + } + // tonccpy((void*)0x02FFDFF0, (void*)LAUNCH_DATA, 0x10); + launchdata.cachedChipID = *(u32*)InitialCartChipID; int err = runNdsFile(c_args[0], c_args.size(), &c_args[0], launchdata); iprintf("Start failed. Error %i\n", err); break; @@ -185,17 +201,22 @@ static int BrowserUI(tLauncherSettings launchdata) { if (cartSelected) { // DS-Xtreme does not like running in TWL clock speeds. // (write function likely goes too fast and semi-bricks hidden sector region randomly when using official launcher) - if (!memcmp(gameTitle, "D!S!XTREME", 9)) { + if (!memcmp(gameTitle, "D!S!XTREME", 10)) { launchdata.scfgUnlock = 0x00; launchdata.twlMode = 0x00; launchdata.twlCLK = 0x00; launchdata.twlVRAM = 0x00; - cardInit(&ntrHeader); - } else { - if (cartInsertedOnBoot)DoCardInit(); // Currently required for bootlaoder to succeed with card init. - // Give launch soundfx time to finish if card Init already occured. - if (!cartInsertedOnBoot)DoWait(29); + launchdata.twlRAM = 0x00; + launchdata.isTWLSRL = 0x00; + // cardInit(&ntrHeader); } + if (cartInsertedOnBoot) { + DoCardInit(); // Currently required for bootlaoder to succeed with card init. + } else { + DoWait(29); // Give launch soundfx time to finish if card Init already occured. + } + if (ntrHeader.unitCode & BIT(1))launchdata.isTWLSRL = 0x01; + launchdata.cachedChipID = *(u32*)InitialCartChipID; runLaunchEngine(launchdata); } return stop(); diff --git a/arm9/hbmenu/iconTitle.cpp b/arm9/hbmenu/iconTitle.twl.cpp similarity index 86% rename from arm9/hbmenu/iconTitle.cpp rename to arm9/hbmenu/iconTitle.twl.cpp index b24c11c..4420d87 100644 --- a/arm9/hbmenu/iconTitle.cpp +++ b/arm9/hbmenu/iconTitle.twl.cpp @@ -31,6 +31,7 @@ #include "hbmenu_banner_cartSelected.h" #include "hbmenu_banner_noCart.h" #include "font6x8.h" +#include "tonccpy.h" #include "read_card.h" #include "launcherData.h" @@ -45,19 +46,29 @@ #define ICON2_POS_X 26 #define ICON2_POS_Y 132 - #define TEXT_WIDTH ((22-4)*8/6) +typedef struct sNDSBannerTest { + u16 version; //!< version of the banner. + u16 crc; //!< 16 bit crc/checksum of the banner. + u8 reserved[28]; + u8 iconData[2080]; +} tNDSBannerTest; + + static int bg2, bg3; static u16 *sprite; static u16 *sprite2; extern tNDSBanner dsCardDefault_bin; +extern tNDSBanner dsCardInvalid_bin; extern tNDSBanner hbNoIcon_bin; static tNDSBanner banner; static tNDSBanner* cartBanner; +static u32 CartBannerBuffer[2304]; + bool cartSelected = false; static inline void writecharRS (int row, int col, u16 car) { @@ -115,6 +126,10 @@ void clearCartIcon(bool clearBannerText) { dmaFillHalfWords(0, sprite2, sizeof(banner.icon)); } +static bool checkBannerCRC(u8* banner) { + return (((tNDSBannerTest*)banner)->crc == swiCRC16(0xFFFF, ((tNDSBannerTest*)banner)->iconData, 0x820)); +} + void iconTitleInit (void) { // initialize video mode @@ -162,6 +177,8 @@ void iconTitleInit (void) { // oam can only be updated during vblank swiWaitForVBlank(); oamUpdate(&oamMain); + + toncset32(CartBannerBuffer, 0, 0x900); cartBanner = (tNDSBanner*)CartBannerBuffer; @@ -253,6 +270,18 @@ void iconTitleUpdate (int isdir, const std::string& name) { return; } + if (!checkBannerCRC((u8*)&banner)) { + // text + writeRow (2,"(invalid icon/title!)", false); + // icon + clearIcon(); + DC_FlushAll(); + dmaCopy(hbNoIcon_bin.icon, sprite, sizeof(hbNoIcon_bin.icon)); + dmaCopy(hbNoIcon_bin.palette, SPRITE_PALETTE, sizeof(hbNoIcon_bin.palette)); + fclose (fp); + return; + } + // close file! fclose (fp); @@ -287,28 +316,37 @@ void iconTitleUpdate (int isdir, const std::string& name) { void cartIconUpdate (u32 BannerOffset, bool readExistingBanner) { + toncset32(CartBannerBuffer, 0, 0x900); if(readExistingBanner) { - cardReadAlt(*(u32*)InitialCartBannerOffset, (u32*)CartBannerBuffer, 0x1000); + cardReadAlt(*(u32*)InitialCartBannerOffset, (u32*)CartBannerBuffer, 0x2400); } else { - cardReadAlt(BannerOffset, (u32*)CartBannerBuffer, 0x1000); + cardReadAlt(BannerOffset, (u32*)CartBannerBuffer, 0x2400); } switch (cartBanner->crc) { case 0x0000: { clearCartIcon(false); writeRow (1,"(invalid icon/title!)", true); DC_FlushAll(); - dmaCopy(dsCardDefault_bin.icon, sprite2, 512); - dmaCopy(dsCardDefault_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); + dmaCopy(dsCardInvalid_bin.icon, sprite2, 512); + dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); return; - }break; + } break; case 0xFFFF: { clearCartIcon(false); - dmaCopy(dsCardDefault_bin.icon, sprite2, 512); - dmaCopy(dsCardDefault_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); + dmaCopy(dsCardInvalid_bin.icon, sprite2, 512); + dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); writeRow (1,"(invalid icon/title!)", true); return; }break; default: { + if (!checkBannerCRC((u8*)cartBanner)) { + clearCartIcon(false); + dmaCopy(dsCardInvalid_bin.icon, sprite2, 512); + dmaCopy(dsCardInvalid_bin.palette, (u16*)((u32)SPRITE_PALETTE + 0x20), 0x20); + writeRow (1,"(invalid icon/title!)", true); + return; + } + clearCartIcon(false); // turn unicode into ascii (kind of) // and convert 0x0A into 0x00 @@ -326,11 +364,7 @@ void cartIconUpdate (u32 BannerOffset, bool readExistingBanner) { // Recenter text to center row if less then 2 rows of text. // Default offset 0 instead of 1 since no NDS file name for this to account for. - if (lineReturns < 2 && lineReturns != 1) { - rowOffset = 1; - } else if (lineReturns == 1) { - rowOffset = 0; - } + if (lineReturns < 2 && lineReturns != 1) { rowOffset = 1; } else if (lineReturns == 1) { rowOffset = 0; } // text for (size_t i = 0; i < 3; ++i) { diff --git a/arm9/hbmenu/nds_loader_arm9.c b/arm9/hbmenu/nds_loader_arm9.c index 0fb6b7c..664cab3 100644 --- a/arm9/hbmenu/nds_loader_arm9.c +++ b/arm9/hbmenu/nds_loader_arm9.c @@ -214,9 +214,8 @@ static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) { return true; }*/ -ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM) { - - if (twlMode > 0) { +ITCM_CODE static void SetSCFG(tLauncherSettings launchData) { + /*if (launchData->twlMode > 0) { *((vu32*)REG_MBK1)=0x8D898581; *((vu32*)REG_MBK2)=0x8C888480; *((vu32*)REG_MBK3)=0x9C989490; @@ -225,7 +224,7 @@ ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM) REG_MBK6=0x00000000; REG_MBK7=0x07C03740; REG_MBK8=0x07403700; - } else { + } else if ((launchData->twlMode == 0) && (launchData->twlRAM == 0)) { // MBK settings for NTR mode games *((vu32*)REG_MBK1)=0x8D898581; *((vu32*)REG_MBK2)=0x91898581; @@ -235,18 +234,47 @@ ITCM_CODE static void SetSCFG(u8 scfgUnlock, u8 twlMode, u8 twlCLK, u8 twlVRAM) REG_MBK6 = 0x00003000; REG_MBK7 = 0x00003000; REG_MBK8 = 0x00003000; - } + }*/ + + if (launchData.twlCLK == 0) { REG_SCFG_CLK = 0x80; } else { REG_SCFG_CLK = 0x87; }; - if (twlCLK == 0)REG_SCFG_CLK = 0x80; - if (twlMode > 0) { - REG_SCFG_EXT = 0x82073100; + if (launchData.twlMode > 0) { + REG_SCFG_EXT = 0x8307F100; REG_SCFG_RST = 1; } else { - REG_SCFG_EXT=0x83002000; + REG_SCFG_EXT = 0x8300E000; } - if (twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13); - if (scfgUnlock == 0x00)REG_SCFG_EXT &= ~(1UL << 31); - for (int i = 0; i < 10; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); } + + if (launchData.twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13); + if (launchData.twlRAM == 0) { + REG_SCFG_EXT &= ~(1UL << 14); + REG_SCFG_EXT &= ~(1UL << 15); + } + + if ((launchData.isTWLSRL > 0) && (launchData.twlRAM > 0) && (launchData.twlMode > 0)) { + *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; + *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; + *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; + *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; + *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; + REG_MBK6 = *(u32*)0x02FFE194; + REG_MBK7 = *(u32*)0x02FFE198; + REG_MBK8 = *(u32*)0x02FFE19C; + REG_MBK9 = *(u32*)0x02FFE1AC; + WRAM_CR = *(u8*)0x02FFE1AF; + } else { + *((vu32*)REG_MBK1)=0x8D898581; + *((vu32*)REG_MBK2)=0x91898581; + *((vu32*)REG_MBK3)=0x91999591; + *((vu32*)REG_MBK4)=0x91898581; + *((vu32*)REG_MBK5)=0x91999591; + REG_MBK6 = 0x00003000; + REG_MBK7 = 0x00003000; + REG_MBK8 = 0x00003000; + if (launchData.scfgUnlock == 0)REG_SCFG_EXT &= ~(1UL << 31); + } + + for (int i = 0; i < 10; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); } } @@ -256,28 +284,18 @@ eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool ini u16 argTempVal = 0; int argSize; const char* argChar; - - bool scfgUnlock = false; - bool twlMode = false; - bool twlCLK = false; - bool twlVRAM = false; - if (launchdata.scfgUnlock > 0x00)scfgUnlock = true; - if (launchdata.twlMode > 0x00)twlMode = true; - if (launchdata.twlCLK > 0x00)twlCLK = true; - if (launchdata.twlVRAM > 0x00)twlVRAM = true; - - if (!twlMode) { + if (launchdata.twlMode == 0) { fifoSendValue32(FIFO_USER_01, 1); fifoWaitValue32(FIFO_USER_02); } irqDisable(IRQ_ALL); - SetSCFG(scfgUnlock, twlMode, twlCLK, twlVRAM); + SetSCFG(launchdata); // Direct CPU access to VRAM bank C - VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD; + VRAM_D_CR = (VRAM_ENABLE | VRAM_D_LCD); // Load the loader/patcher into the correct address vramcpy (LCDC_BANK_D, loader, loaderSize); @@ -332,9 +350,9 @@ eRunNdsRetCode runNds (const void* loader, u32 loaderSize, u32 cluster, bool ini *(tLauncherSettings*)LAUNCH_DATA = launchdata; // Give the VRAM to the ARM7 - VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000; + VRAM_D_CR = (VRAM_ENABLE | VRAM_D_ARM7_0x06020000); // Reset into a passme loop - REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; + REG_EXMEMCNT |= (ARM7_OWNS_ROM | ARM7_OWNS_CARD); *((vu32*)0x02FFFFFC) = 0; *((vu32*)0x02FFFE04) = (u32)0xE59FF018; *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; diff --git a/arm9/include/dsCardInvalid.bin b/arm9/include/dsCardInvalid.bin new file mode 100644 index 0000000..db63766 Binary files /dev/null and b/arm9/include/dsCardInvalid.bin differ diff --git a/arm9/source/bootsplash.cpp b/arm9/source/bootsplash.twl.cpp similarity index 100% rename from arm9/source/bootsplash.cpp rename to arm9/source/bootsplash.twl.cpp diff --git a/arm9/source/debugConsole.c b/arm9/source/debugConsole.twl.c similarity index 100% rename from arm9/source/debugConsole.c rename to arm9/source/debugConsole.twl.c diff --git a/arm9/source/launch_engine.c b/arm9/source/launch_engine.c index 39ed94d..33e50ae 100644 --- a/arm9/source/launch_engine.c +++ b/arm9/source/launch_engine.c @@ -39,23 +39,34 @@ extern void InitConsole(); extern bool ConsoleInit; -ITCM_CODE static void SETSCFG() { - REG_SCFG_EXT=0x83002000; +ITCM_CODE static void SETSCFG(u8 twlMode, u8 twlVRAM, u8 twlRAM) { + if (twlMode > 0) { + // if (twlRAM > 0) { REG_SCFG_EXT = 0x82076100; } else { REG_SCFG_EXT = 0x82073100; } + // if (twlRAM > 0) { REG_SCFG_EXT = 0x8207611F; } else { REG_SCFG_EXT = 0x8207311F; } + // if (twlRAM > 0) { REG_SCFG_EXT = 0x8207711F; } else { REG_SCFG_EXT = 0x8207311F; } + // REG_SCFG_EXT = 0x8207711F; + REG_SCFG_EXT = 0x8307F100; + REG_SCFG_RST = 1; + } else { + // if (twlRAM == 0) { REG_SCFG_EXT = 0x83002000; } else { REG_SCFG_EXT = 0x83006000; } + // REG_SCFG_EXT = 0x83006000; + REG_SCFG_EXT = 0x8300E000; + } + if (twlVRAM == 0)REG_SCFG_EXT &= ~(1UL << 13); + if (twlRAM == 0)REG_SCFG_EXT &= ~(1UL << 14); + if (twlRAM == 0)REG_SCFG_EXT &= ~(1UL << 15); for(int i = 0; i < 8; i++) { while(REG_VCOUNT!=191); while(REG_VCOUNT==191); } } void runLaunchEngine (tLauncherSettings launchdata) { // Always init console so bootloader's new console can display error codes if needed. - if (!launchdata.debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); } - + if (!launchdata.debugMode || !ConsoleInit) { InitConsole(); } else { consoleClear(); } + irqDisable(IRQ_ALL); // Direct CPU access to VRAM bank D - VRAM_D_CR = VRAM_ENABLE | VRAM_D_LCD; - - // Clear VRAM - // memset (LCDC_BANK_D, 0x00, 128 * 1024); - + VRAM_D_CR = (VRAM_ENABLE | VRAM_D_LCD); + // Load the loader/patcher into the correct address vramcpy (LCDC_BANK_D, load_bin, load_bin_size); @@ -64,17 +75,17 @@ void runLaunchEngine (tLauncherSettings launchdata) { VRAM_D_CR = VRAM_ENABLE | VRAM_D_ARM7_0x06020000; // Reset into a passme loop - nocashMessage("Reset into a passme loop"); + // nocashMessage("Reset into a passme loop"); REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; *(tLauncherSettings*)LAUNCH_DATA = launchdata; - SETSCFG(); + SETSCFG(launchdata.twlMode, launchdata.twlVRAM, launchdata.twlRAM); // Return to passme loop - *(vu32*)0x027FFFFC = 0; - *(vu32*)0x027FFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 - *(vu32*)0x027FFE24 = (u32)0x02FFFE04; // Set ARM9 Loop address --> resetARM9(0x027FFE04); + *(vu32*)0x02FFFFFC = 0; + *(vu32*)0x02FFFE04 = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 + *(vu32*)0x02FFFE24 = (u32)0x02FFFE04; // Set ARM9 Loop address --> resetARM9(0x02FFFE04); // Reset ARM7 // nocashMessage("resetARM7"); resetARM7(0x06020000); diff --git a/arm9/source/main.cpp b/arm9/source/main.cpp index 6434d8b..d6aef9d 100755 --- a/arm9/source/main.cpp +++ b/arm9/source/main.cpp @@ -49,7 +49,7 @@ static char gameTitle[13] = {0}; // static char gameCode[7] = {0}; static char gameCode[5] = {0}; static bool nitroFSMounted = false; -static ALIGN(4) sNDSHeaderExt ntrHeader; +// static ALIGN(4) sNDSHeaderExt ntrHeader; const char* PROGVERSION = "3.1"; @@ -75,7 +75,7 @@ void DisplayText(const char* text, bool clear = false, bool noText = false){ if (clear)consoleClear(); printf("--------------------------------\n"); printf("----[NTR Launcher Debug Mode]---\n"); - printf("----------[Version: 3.1]--------\n"); + printf("----------[Version: 3.2]--------\n"); printf("--------------------------------\n\n"); if (!noText)printf(text); } @@ -110,8 +110,8 @@ bool DoCardInit(bool DebugMode, bool fastBoot) { DisplayText("Loading Cart details.\nPlease Wait...\n", true); } switch (REG_SCFG_MC) { - case 0x10: { enableSlot1(); DoWait(10); FastBoot = false; }break; - case 0x11: { enableSlot1(); DoWait(10); FastBoot = false; }break; + case 0x10: { enableSlot1(); DoWait(15); FastBoot = false; }break; + case 0x11: { enableSlot1(); DoWait(15); FastBoot = false; }break; } // Do cart init stuff to wake cart up. DLDI init may fail otherwise! /*if (FastBoot) { @@ -121,10 +121,14 @@ bool DoCardInit(bool DebugMode, bool fastBoot) { } else {*/ CardReset(true); cardReadHeader((u8*)&ndsHeader); + while(REG_ROMCTRL & CARD_BUSY); CardReset(false); tonccpy(gameTitle, ndsHeader.header.gameTitle, 12); tonccpy(gameCode, ndsHeader.header.gameCode, 4); - // cardInit(&ntrHeader); + /*cardInit((sNDSHeaderExt*)&ndsHeader.header); + tonccpy(gameTitle, ndsHeader.header.gameTitle, 12); + tonccpy(gameCode, ndsHeader.header.gameCode, 4); + CardReset(false);*/ // } if (DebugMode) { DisplayText("CLR", true, true); @@ -170,8 +174,19 @@ int main() { defaultExceptionHandler(); sysSetCardOwner(BUS_OWNER_ARM9); + + if (!isDSiMode()) { + InitConsole(); + printf("--------------------------------\n"); + printf("----------[NTR Launcher]--------\n"); + printf("----------[Version: 3.2]--------\n"); + printf("--------------------------------\n\n"); + printf("\nError has occured.!\nDSi Mode not detected.\nDS/DS Lite Unsupported!"); + do { swiWaitForVBlank(); scanKeys(); } while (!keysDown()); + return 0; + } - tLauncherSettings LaunchData = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF }; + tLauncherSettings LaunchData = { 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFFFFFFFF }; // Create backup of Cart header (if present) saved by DSi System Menu. // It will not survive memory reallocation after dropping to NTR ram spec during bootloader. @@ -181,6 +196,7 @@ int main() { bool scfgunlock = true; bool twlmode = false; bool twlclk = false; + bool twlram = false; bool twlvram = false; bool debugmode = false; // bool fastBoot = false; @@ -220,6 +236,7 @@ int main() { twlclk = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLCLOCK",0); twlvram = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLVRAM",0); + twlram = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLRAM",0); twlmode = ntrlauncher_config.GetInt("NTRLAUNCHER","TWLMODE",0); scfgunlock = ntrlauncher_config.GetInt("NTRLAUNCHER","SCFGUNLOCK",0); useAnimatedSplash = ntrlauncher_config.GetInt("NTRLAUNCHER","ANIMATEDSPLASH",0); @@ -236,10 +253,19 @@ int main() { scanKeys(); swiWaitForVBlank(); + /*scfgunlock = true; + twlmode = true; + twlclk = true; + twlram = true; + twlvram = true; + debugmode = true;*/ + + if (scfgunlock)LaunchData.scfgUnlock = 0x01; if (twlmode)LaunchData.twlMode = 0x01; if (twlclk)LaunchData.twlCLK = 0x01; if (twlvram)LaunchData.twlVRAM = 0x01; + if (twlram)LaunchData.twlRAM = 0x01; if (!autoBoot)stage2Menu = true; // if (fastBoot)LaunchData.fastBoot = 0x01; @@ -251,6 +277,8 @@ int main() { if ((REG_SCFG_MC == 0x10) && !stage2Menu) { sysSetCardOwner (BUS_OWNER_ARM9); DoCardInit(false, false); } + if (!fatInit)stage2Menu = false; + if (!stage2Menu) { if ((keysHeld() & KEY_L) && (keysHeld() & KEY_R)) { debugmode = true; @@ -261,7 +289,6 @@ int main() { } } - if (!fatInit)stage2Menu = false; ConsoleInit = debugmode; if (stage2Menu) { ConsoleInit = false; debugmode = false; } @@ -307,7 +334,9 @@ int main() { LaunchData.twlVRAM = 0x00; LaunchData.twlMode = 0x00; if (!useAnimatedSplash)SimpleSplashInit(); - cardInit(&ntrHeader); + // cardInit(&ntrHeader); + } else { + if (ndsHeader.header.unitCode & BIT(1))LaunchData.isTWLSRL = 0x01; } while(1) { // If SCFG_MC is returning as zero/null, this means SCFG_EXT registers are locked on arm9 or user attempted to run this while in NTR mode. @@ -320,6 +349,7 @@ int main() { } break; } else { + LaunchData.cachedChipID = *(u32*)InitialCartChipID; runLaunchEngine(LaunchData); break; } diff --git a/ndsbootloader/source/bios.s b/ndsbootloader/source/bios.s deleted file mode 100644 index e98f57c..0000000 --- a/ndsbootloader/source/bios.s +++ /dev/null @@ -1,13 +0,0 @@ - .text - .align 4 - - .thumb - -@--------------------------------------------------------------------------------- - .global swiDelay - .thumb_func -@--------------------------------------------------------------------------------- -swiDelay: -@--------------------------------------------------------------------------------- - swi 0x03 - bx lr diff --git a/ndsbootloader/source/biosCalls.s b/ndsbootloader/source/biosCalls.s new file mode 100644 index 0000000..fb1bc13 --- /dev/null +++ b/ndsbootloader/source/biosCalls.s @@ -0,0 +1,233 @@ +/*--------------------------------------------------------------------------------- + + Copyright (C) 2005 + 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 + + .text + .align 4 + + .thumb + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDelay +@--------------------------------------------------------------------------------- + swi 0x03 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiSleep +@--------------------------------------------------------------------------------- + swi 0x07 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiChangeSoundBias +@--------------------------------------------------------------------------------- + swi 0x08 + bx lr + + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDivide +@--------------------------------------------------------------------------------- + swi 0x09 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiRemainder +@--------------------------------------------------------------------------------- + swi 0x09 + mov r0, r1 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDivMod +@--------------------------------------------------------------------------------- + push {r2, r3} + swi 0x09 + pop {r2, r3} + str r0, [r2] + str r1, [r3] + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiCopy +@--------------------------------------------------------------------------------- + swi 0x0B + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiFastCopy +@--------------------------------------------------------------------------------- + swi 0x0C + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiSqrt +@--------------------------------------------------------------------------------- + swi 0x0D + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiCRC16 +@--------------------------------------------------------------------------------- + swi 0x0E + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiIsDebugger +@--------------------------------------------------------------------------------- + swi 0x0F + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiUnpackBits +@--------------------------------------------------------------------------------- + swi 0x10 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressLZSSWram +@--------------------------------------------------------------------------------- + swi 0x11 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressLZSSVramNTR +@--------------------------------------------------------------------------------- + swi 0x12 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressLZSSVramTWL +@--------------------------------------------------------------------------------- + swi 0x02 + bx lr + + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressHuffman +@--------------------------------------------------------------------------------- + swi 0x13 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressRLEWram +@--------------------------------------------------------------------------------- + swi 0x14 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecompressRLEVram +@--------------------------------------------------------------------------------- + swi 0x15 + bx lr + +@--------------------------------------------------------------------------------- +@ ARM7 only bios calls +@--------------------------------------------------------------------------------- +#ifdef ARM7 + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiHalt +@--------------------------------------------------------------------------------- + swi 0x06 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiGetSineTable +@--------------------------------------------------------------------------------- + swi 0x1A + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiGetPitchTable +@--------------------------------------------------------------------------------- + swi 0x1B + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiGetVolumeTable +@--------------------------------------------------------------------------------- + swi 0x1C + bx lr + + +@ ARM7 function, but no real point in exposing it, at least not +@ without adding a way to get the 3 arguments back into C +@ .global swiGetFptrs +@ .thumb_func +@swiGetFptrs: +@ swi 0x1D +@ bx lr + + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiSwitchToGBAMode +@--------------------------------------------------------------------------------- + mov r0, #0x40 + swi 0x1F +@ does not return, of course + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiSetHaltCR +@--------------------------------------------------------------------------------- + mov r2, r0 + swi 0x1F + bx lr + +#endif // ARM7 + +@--------------------------------------------------------------------------------- +@ ARM9 only bios calls +@--------------------------------------------------------------------------------- +#ifdef ARM9 + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiWaitForIRQ +@--------------------------------------------------------------------------------- + swi 0x06 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecodeDelta8 +@--------------------------------------------------------------------------------- + swi 0x16 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiDecodeDelta16 +@--------------------------------------------------------------------------------- + swi 0x18 + bx lr + +@--------------------------------------------------------------------------------- +BEGIN_ASM_FUNC swiSetHaltCR +@--------------------------------------------------------------------------------- + swi 0x1F + bx lr + +#endif // ARM9 + diff --git a/ndsbootloader/source/boot.c b/ndsbootloader/source/boot.c index 52c4b15..32bcdc1 100644 --- a/ndsbootloader/source/boot.c +++ b/ndsbootloader/source/boot.c @@ -40,19 +40,29 @@ Helpful information: #include #include #include +#include +#include #include "fat.h" #include "card.h" #include "boot.h" #include "sdmmc.h" +#include "tonccpy.h" + +#include "../../arm9/common/launcherData.h" void arm7clearRAM(); //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Important things -#define TEMP_MEM 0x02FFD000 -#define TWL_HEAD 0x02FFE000 -#define NDS_HEAD 0x02FFFE00 +#define TEMP_MEM 0x02FFD000 +#define TEMP_LAUNCHMEM 0x02FFDFF0 +#define TWL_HEAD 0x02FFE000 +#define NDS_HEAD 0x02FFFE00 +#define NDS_HEAD_POKEMON 0x02FFF000 + #define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4) +tTWLHeader* ntrHeader; +tTWLHeader* twlHeader; const char* bootName = "BOOT.NDS"; @@ -65,61 +75,39 @@ extern unsigned long argSize; extern unsigned long dsiSD; extern unsigned long dsiMode; -static bool scfgunlock = false; -static bool twlmode = false; -static bool twlclk = false; -static bool twlvram = false; +volatile u16 scfgunlock = 0; +volatile u16 twlmode = 0; +volatile u16 twlclk = 0; +volatile u16 twlvram = 0; +volatile u16 twlram = 0; +volatile u32 chipID = 0; -#define LAUNCH_DATA 0x020007F0 +static volatile u32 ROM_TID = 0; -typedef struct sLauncherSettings { - u8 language; - u8 scfgUnlock; - u8 twlMode; - u8 twlCLK; - u8 twlVRAM; - u8 debugMode; - u8 fastBoot; - u8 unused2; -} tLauncherSettings; +static void setTWLMBK() { + *(vu32*)REG_MBK1 = *(u32*)0x02FFE180; + *(vu32*)REG_MBK2 = *(u32*)0x02FFE184; + *(vu32*)REG_MBK3 = *(u32*)0x02FFE188; + *(vu32*)REG_MBK4 = *(u32*)0x02FFE18C; + *(vu32*)REG_MBK5 = *(u32*)0x02FFE190; + REG_MBK6 = *(u32*)0x02FFE1A0; + REG_MBK7 = *(u32*)0x02FFE1A4; + REG_MBK8 = *(u32*)0x02FFE1A8; + REG_MBK9 = *(u32*)0x02FFE1AC; +} + + +const char* getRomTid(const tNDSHeader* ndsHeader) { + static char romTid[5]; + strncpy(romTid, ndsHeader->gameCode, 4); + romTid[4] = '\0'; + return romTid; +} //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ // Firmware stuff - #define FW_READ 0x03 -void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) { - uint32 index; - - // Read command - while (REG_SPICNT & SPI_BUSY); - REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM; - REG_SPIDATA = FW_READ; - while (REG_SPICNT & SPI_BUSY); - - // Set the address - REG_SPIDATA = (address>>16) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - REG_SPIDATA = (address>>8) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - REG_SPIDATA = (address) & 0xFF; - while (REG_SPICNT & SPI_BUSY); - - for (index = 0; index < size; index++) { - REG_SPIDATA = 0; - while (REG_SPICNT & SPI_BUSY); - buffer[index] = REG_SPIDATA & 0xFF; - } - REG_SPICNT = 0; -} - -static inline void copyLoop (u32* dest, const u32* src, u32 size) { - size = (size +3) & ~3; - do { *dest++ = *src++; } while (size -= 4); -} - -//#define resetCpu() __asm volatile("\tswi 0x000000\n"); - void mpu_reset(); void mpu_reset_end(); @@ -173,17 +161,17 @@ void passArgs_ARM7 (void) { argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned - /* if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) { + if ((twlmode > 0) && dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) { u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8)); u32 ARM9i_LEN = *((u32*)(TWL_HEAD + 0x1CC)); if (ARM9i_LEN) { u32* argDst2 = (u32*)((ARM9i_DST + ARM9i_LEN + 3) & ~3); // Word aligned - if (argDst2 > argDst) - argDst = argDst2; + if (argDst2 > argDst)argDst = argDst2; } - }*/ + } - copyLoop(argDst, argSrc, argSize); + // copyLoop(argDst, argSrc, argSize); + tonccpy(argDst, argSrc, argSize); __system_argv->argvMagic = ARGV_MAGIC; __system_argv->commandLine = (char*)argDst; @@ -197,10 +185,8 @@ Written by Darkain. Modified by Chishm: * Added STMIA clear mem loop --------------------------------------------------------------------------*/ -void resetMemory_ARM7 (void) { - int i; - u8 settings1, settings2; - u32 settingsOffset = 0; +void resetMemory_ARM7(void) { + int i, reg; REG_IME = 0; @@ -212,82 +198,281 @@ void resetMemory_ARM7 (void) { } REG_SOUNDCNT = 0; + REG_SNDCAP0CNT = 0; + REG_SNDCAP1CNT = 0; - //clear out ARM7 DMA channels and timers + REG_SNDCAP0DAD = 0; + REG_SNDCAP0LEN = 0; + REG_SNDCAP1DAD = 0; + REG_SNDCAP1LEN = 0; + + // Clear out ARM7 DMA channels and timers for (i=0; i<4; i++) { DMA_CR(i) = 0; DMA_SRC(i) = 0; DMA_DEST(i) = 0; TIMER_CR(i) = 0; TIMER_DATA(i) = 0; + if ((twlmode > 0) || dsiMode) { + for (reg=0; reg<0x1c; reg+=4)*((u32*)(0x04004104 + ((i*0x1c)+reg))) = 0; //Reset NDMA. + } } + REG_RCNT = 0; + + // Clear out FIFO + REG_IPC_SYNC = 0; + REG_IPC_FIFO_CR = IPC_FIFO_ENABLE | IPC_FIFO_SEND_CLEAR; + REG_IPC_FIFO_CR = 0; + arm7clearRAM(); + // clear most of EXRAM + toncset((u8*)0x02000000, 0, 0x3FC000); // clear more of EXRAM, skipping the arm9 temp area used by bootloader + REG_IE = 0; REG_IF = ~0; + REG_AUXIE = 0; + REG_AUXIF = ~0; (*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version (*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version - REG_POWERCNT = 1; //turn off power to stuff + REG_POWERCNT = 1; //turn off power to stuffs +} - // Get settings location - boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2); - settingsOffset *= 8; +static void XMenuFix() { + *((vu8*)0x02FFFF70) = 0x91; + if (twlmode > 0)*((vu8*)0x027FFF70) = 0x91; + +} - // Reload DS Firmware settings - boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1); - boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1); +static void setMemoryAddressTWL(const tNDSHeader* ndsHeader) { + if (ndsHeader->unitCode > 0) { + // copyLoop((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header + tonccpy((u32*)0x027FFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header - if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) { - boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70); - } else { - boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70); + *(u32*)(0x027FA680) = 0x02FD4D80; + *(u32*)(0x027FA684) = 0x00000000; + *(u32*)(0x027FA688) = 0x00001980; + + *(u32*)(0x027FF00C) = 0x0000007F; + *(u32*)(0x027FF010) = 0x550E25B8; + *(u32*)(0x027FF014) = 0x02FF4000; + + // Set region flag + if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) { + *(u8*)(0x027FFD70) = 0; + } else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) { + *(u8*)(0x027FFD70) = 1; + } else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) { + *(u8*)(0x027FFD70) = 2; + } else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) { + *(u8*)(0x027FFD70) = 3; + } else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) { + *(u8*)(0x027FFD70) = 4; + } else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) { + *(u8*)(0x027FFD70) = 5; + } + } + + // Set memory values expected by loaded NDS + // from NitroHax, thanks to Chism + *((u32*)0x027FF800) = *(u32*)0x02FFFC00; // CurrentCardID + // *((u32*)0x027FF804) = *(u32*)0x02FFFC00; // Command10CardID + *((u16*)0x027FF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x027FF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x027FF850) = 0x5835; + // Copies of above + *((u32*)0x027FFC00) = *(u32*)0x02FFFC00; // CurrentCardID + // *((u32*)0x027FFC04) = *(u32*)0x02FFFC00; // Command10CardID + *((u16*)0x027FFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x027FFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x027FFC10) = 0x5835; + *((u16*)0x027FFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr + + tonccpy((u32*)0x027FC000, (u32*)0x02FFC000, 0x1000); + tonccpy((u32*)0x027FF000, (u32*)NDS_HEAD_POKEMON, 0x170); + tonccpy((u32*)0x027FFE00, (u32*)NDS_HEAD, 0x160); + tonccpy((u32*)0x027FE000, (u32*)TWL_HEAD, 0x1000); + + tonccpy((u32*)0x027FF830, (u32*)0x02FFF830, 0x20); + tonccpy((u32*)0x027FFC80, (u32*)0x02FFFC80, 0x70); + tonccpy((u32*)0x027FFD80, (u32*)0x02FFFD80, 0x70); +} + +static void setMemoryAddress(const tNDSHeader* ndsHeader) { + if (ndsHeader->unitCode > 0) { + // copyLoop((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header + tonccpy((u32*)0x02FFFA80, (u32*)ndsHeader, 0x160); // Make a duplicate of DS header + + *(u32*)(0x02FFA680) = 0x02FD4D80; + *(u32*)(0x02FFA684) = 0x00000000; + *(u32*)(0x02FFA688) = 0x00001980; + + *(u32*)(0x02FFF00C) = 0x0000007F; + *(u32*)(0x02FFF010) = 0x550E25B8; + *(u32*)(0x02FFF014) = 0x02FF4000; + + // Set region flag + if (strncmp(getRomTid(ndsHeader)+3, "J", 1) == 0) { + *(u8*)(0x02FFFD70) = 0; + } else if (strncmp(getRomTid(ndsHeader)+3, "E", 1) == 0) { + *(u8*)(0x02FFFD70) = 1; + } else if (strncmp(getRomTid(ndsHeader)+3, "P", 1) == 0) { + *(u8*)(0x02FFFD70) = 2; + } else if (strncmp(getRomTid(ndsHeader)+3, "U", 1) == 0) { + *(u8*)(0x02FFFD70) = 3; + } else if (strncmp(getRomTid(ndsHeader)+3, "C", 1) == 0) { + *(u8*)(0x02FFFD70) = 4; + } else if (strncmp(getRomTid(ndsHeader)+3, "K", 1) == 0) { + *(u8*)(0x02FFFD70) = 5; + } + } + + // Fix Pokemon games needing header data. + // copyLoop((u32*)NDS_HEAD_POKEMON, (u32*)NDS_HEAD, 0x170); + tonccpy((u32*)NDS_HEAD_POKEMON, (u32*)NDS_HEAD, 0x170); + + // Set memory values expected by loaded NDS + // from NitroHax, thanks to Chism + *((u32*)0x02FFF800) = chipID; // CurrentCardID + // *((u32*)0x02FFF804) = chipID; // Command10CardID + *((u16*)0x02FFF808) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x02FFF80A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x02FFF850) = 0x5835; + // Copies of above + *((u32*)0x02FFFC00) = chipID; // CurrentCardID + // *((u32*)0x02FFFC04) = chipID; // Command10CardID + *((u16*)0x02FFFC08) = ndsHeader->headerCRC16; // Header Checksum, CRC-16 of [000h-15Dh] + *((u16*)0x02FFFC0A) = ndsHeader->secureCRC16; // Secure Area Checksum, CRC-16 of [ [20h]..7FFFh] + *((u16*)0x02FFFC10) = 0x5835; + *((u16*)0x02FFFC40) = 0x01; // Boot Indicator -- EXTREMELY IMPORTANT!!! Thanks to cReDiAr + + if ((twlram > 0) && (ndsHeader->unitCode == 0))setMemoryAddressTWL(ndsHeader); + + switch (*((vu16*)0x02FFFF5E)) { + case 0xF63D: XMenuFix(); break; + case 0x0695: XMenuFix(); break; + case 0xE4C4: XMenuFix(); break; + case 0x918C: XMenuFix(); break; + } +} + +static u8 readwriteSPI(u8 data) { + REG_SPIDATA = data; + SerialWaitBusy(); + return REG_SPIDATA; +} + +//--------------------------------------------------------------------------------- +void readFirmware(u32 address, void * destination, u32 size) { +//--------------------------------------------------------------------------------- + int oldIME=enterCriticalSection(); + u8 *buffer = destination; + + // Read command + REG_SPICNT = SPI_ENABLE | SPI_BYTE_MODE | SPI_CONTINUOUS | SPI_DEVICE_FIRMWARE; + readwriteSPI(FIRMWARE_READ); + + // Set the address + readwriteSPI((address>>16) & 0xFF); + readwriteSPI((address>> 8) & 0xFF); + readwriteSPI((address) & 0xFF); + + u32 i; + + // Read the data + for(i=0;ilanguage != 6 && ndsHeader->reserved1[8] == 0x80) { + ndsHeader->reserved1[8] = 0; // Patch iQue game to be region-free + ndsHeader->headerCRC16 = swiCRC16(0xFFFF, ndsHeader, 0x15E); // Fix CRC + } } void loadBinary_ARM7 (u32 fileCluster) { - u32 ndsHeader[0x170>>2]; - // read NDS header - fileRead ((char*)ndsHeader, fileCluster, 0, 0x170); - // read ARM9 info from NDS header - u32 ARM9_SRC = ndsHeader[0x020>>2]; - char* ARM9_DST = (char*)ndsHeader[0x028>>2]; - u32 ARM9_LEN = ndsHeader[0x02C>>2]; - // read ARM7 info from NDS header - u32 ARM7_SRC = ndsHeader[0x030>>2]; - char* ARM7_DST = (char*)ndsHeader[0x038>>2]; - u32 ARM7_LEN = ndsHeader[0x03C>>2]; - + fileRead ((char*)NDS_HEAD, fileCluster, 0, 0x170); + // Load binaries into memory - fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN); - fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN); + fileRead((char*)ntrHeader->arm9destination, fileCluster, ntrHeader->arm9romOffset, ntrHeader->arm9binarySize); + fileRead((char*)ntrHeader->arm7destination, fileCluster, ntrHeader->arm7romOffset, ntrHeader->arm7binarySize); // first copy the header to its proper location, excluding // the ARM9 start address, so as not to start it - TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later - ndsHeader[0x024>>2] = 0; - dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170); - - /*if (dsiMode && (ndsHeader[0x10>>2]&BIT(16+1))) { + TEMP_ARM9_START_ADDRESS = ntrHeader->arm9executeAddress; // Store for later + *(u32*)ntrHeader->arm9executeAddress = 0; + dmaCopyWords(3, (void*)ntrHeader, (void*)NDS_HEAD, 0x170); + + ROM_TID = *(u32*)0x02FFFE0C; + + setMemoryAddress((tNDSHeader*)ntrHeader); + + if ((twlram > 0) && (ntrHeader->unitCode & BIT(1))) { // Read full TWL header fileRead((char*)TWL_HEAD, fileCluster, 0, 0x1000); + tonccpy((void*)0x02FFC000, (void*)TWL_HEAD, 0x1000); + + if (twlHeader->arm9ibinarySize > 0)fileRead((char*)twlHeader->arm9idestination, fileCluster, twlHeader->arm9iromOffset, twlHeader->arm9ibinarySize); + if (twlHeader->arm7ibinarySize > 0)fileRead((char*)twlHeader->arm7idestination, fileCluster, twlHeader->arm7iromOffset, twlHeader->arm7ibinarySize); + + if (twlmode > 0) { + setTWLMBK(); + if (twlHeader->unitCode == 0x02)scfgunlock = 0; + } + } - u32 ARM9i_SRC = *(u32*)(TWL_HEAD+0x1C0); - char* ARM9i_DST = (char*)*(u32*)(TWL_HEAD+0x1C8); - u32 ARM9i_LEN = *(u32*)(TWL_HEAD+0x1CC); - u32 ARM7i_SRC = *(u32*)(TWL_HEAD+0x1D0); - char* ARM7i_DST = (char*)*(u32*)(TWL_HEAD+0x1D8); - u32 ARM7i_LEN = *(u32*)(TWL_HEAD+0x1DC); - - if (ARM9i_LEN)fileRead(ARM9i_DST, fileCluster, ARM9i_SRC, ARM9i_LEN); - if (ARM7i_LEN)fileRead(ARM7i_DST, fileCluster, ARM7i_SRC, ARM7i_LEN); - }*/ + my_readUserSettings((tNDSHeader*)ntrHeader); } /*------------------------------------------------------------------------- @@ -310,20 +495,19 @@ void startBinary_ARM7 (void) { } int main (void) { - + ntrHeader = (tTWLHeader*)NDS_HEAD; + twlHeader = (tTWLHeader*)TWL_HEAD; + tLauncherSettings* tmpData = (tLauncherSettings*)LAUNCH_DATA; - if (tmpData->scfgUnlock > 0x00)scfgunlock = true; - if (tmpData->twlMode > 0x00)twlmode = true; - if (tmpData->twlCLK > 0x00)twlclk = true; - if (tmpData->twlVRAM > 0x00)twlvram = true; + if (tmpData->scfgUnlock > 0x00)scfgunlock = 0xFFFF; + if (tmpData->twlMode > 0x00)twlmode = 0xFFFF; + if (tmpData->twlCLK > 0x00)twlclk = 0xFFFF; + if (tmpData->twlRAM > 0x00)twlram = 0xFFFF; + if (tmpData->twlVRAM > 0x00)twlvram = 0xFFFF; + if (tmpData->cachedChipID > 0x00)chipID = tmpData->cachedChipID; - if (twlmode) { - REG_MBK9=0x0300000F; - REG_MBK6=0x080037C0; - REG_MBK7=0x07C03740; - REG_MBK8=0x07403700; - } else { + if ((twlmode == 0) && (twlram == 0)) { REG_MBK9=0xFCFFFF0F; REG_MBK6=0x09403900; REG_MBK7=0x09803940; @@ -350,14 +534,14 @@ int main (void) { // ARM9 clears its memory part 2 // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size); + tonccpy((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size); (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function // Wait until the ARM9 has completed its task while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); // ARM9 sets up mpu // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset); + tonccpy((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset); (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function // Wait until the ARM9 has completed its task @@ -365,15 +549,22 @@ int main (void) { // Get ARM7 to clear RAM resetMemory_ARM7(); - + // ARM9 enters a wait loop // copy ARM9 function to RAM, and make the ARM9 jump to it - copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size); + tonccpy((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size); (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function - + // Load the NDS file loadBinary_ARM7(fileCluster); - + + // Fix for Pictochat and DLP + if (ROM_TID == 0x41444E48 || ROM_TID == 0x41454E48 + || ROM_TID == 0x43444E48 || ROM_TID == 0x43454E48 + || ROM_TID == 0x4B444E48 || ROM_TID == 0x4B454E48) { + (*(vu16*)0x02FFFCFA) = 0x1041; // NoCash: channel ch1+7+13 + } + #ifndef NO_SDMMC if (dsiSD && dsiMode) { sdmmc_controller_init(true); @@ -385,17 +576,18 @@ int main (void) { // Pass command line arguments to loaded program passArgs_ARM7(); - if (twlclk) { REG_SCFG_CLK = 0x0187; } else { REG_SCFG_CLK = 0x0101; } - if (twlmode) { - REG_SCFG_EXT = 0x92FBFB06; + if (twlmode > 0) { + // REG_SCFG_EXT = 0x92FBFB06; + // REG_SCFG_EXT = 0x8307F100; + REG_SCFG_EXT = 0x93FFFB06; } else { - REG_SCFG_EXT = 0x92A00000; + REG_SCFG_EXT = 0x92A40000; // REG_SCFG_EXT |= BIT(18); REG_SCFG_ROM = 0x703; } - if (scfgunlock) { REG_SCFG_EXT |= BIT(18); } else { REG_SCFG_EXT &= ~(1UL << 31); } + if (twlclk > 0) { REG_SCFG_CLK = 0x187; } else { REG_SCFG_CLK = 0x107; } + if (scfgunlock == 0)REG_SCFG_EXT &= ~(1UL << 31); startBinary_ARM7(); - return 0; } diff --git a/ndsbootloader/source/boot.h b/ndsbootloader/source/boot.h index 20c8cc0..1222e52 100644 --- a/ndsbootloader/source/boot.h +++ b/ndsbootloader/source/boot.h @@ -1,11 +1,140 @@ #ifndef _BOOT_H_ #define _BOOT_H_ +typedef struct sTWLHeader { + char gameTitle[12]; //!< 12 characters for the game title. + char gameCode[4]; //!< 4 characters for the game code. + char makercode[2]; //!< identifies the (commercial) developer. + u8 unitCode; //!< identifies the required hardware. + u8 deviceType; //!< type of device in the game card + u8 deviceSize; //!< capacity of the device (1 << n Mbit) + u8 reserved1[9]; + u8 romversion; //!< version of the ROM. + u8 flags; //!< bit 2: auto-boot flag. + + u32 arm9romOffset; //!< offset of the arm9 binary in the nds file. + u32 arm9executeAddress; //!< adress that should be executed after the binary has been copied. + u32 arm9destination; //!< destination address to where the arm9 binary should be copied. + u32 arm9binarySize; //!< size of the arm9 binary. + + u32 arm7romOffset; //!< offset of the arm7 binary in the nds file. + u32 arm7executeAddress; //!< adress that should be executed after the binary has been copied. + u32 arm7destination; //!< destination address to where the arm7 binary should be copied. + u32 arm7binarySize; //!< size of the arm7 binary. + + u32 filenameOffset; //!< File Name Table (FNT) offset. + u32 filenameSize; //!< File Name Table (FNT) size. + u32 fatOffset; //!< File Allocation Table (FAT) offset. + u32 fatSize; //!< File Allocation Table (FAT) size. + + u32 arm9overlaySource; //!< File arm9 overlay offset. + u32 arm9overlaySize; //!< File arm9 overlay size. + u32 arm7overlaySource; //!< File arm7 overlay offset. + u32 arm7overlaySize; //!< File arm7 overlay size. + + u32 cardControl13; //!< Port 40001A4h setting for normal commands (used in modes 1 and 3) + u32 cardControlBF; //!< Port 40001A4h setting for KEY1 commands (used in mode 2) + u32 bannerOffset; //!< offset to the banner with icon and titles etc. + + u16 secureCRC16; //!< Secure Area Checksum, CRC-16. + + u16 readTimeout; //!< Secure Area Loading Timeout. + + u32 unknownRAM1; //!< ARM9 Auto Load List RAM Address (?) + u32 unknownRAM2; //!< ARM7 Auto Load List RAM Address (?) + + u32 bfPrime1; //!< Secure Area Disable part 1. + u32 bfPrime2; //!< Secure Area Disable part 2. + u32 romSize; //!< total size of the ROM. + + u32 headerSize; //!< ROM header size. + u32 zeros88[14]; + u8 gbaLogo[156]; //!< Nintendo logo needed for booting the game. + u16 logoCRC16; //!< Nintendo Logo Checksum, CRC-16. + u16 headerCRC16; //!< header checksum, CRC-16. + + u32 debugRomSource; //!< debug ROM offset. + u32 debugRomSize; //!< debug size. + u32 debugRomDestination; //!< debug RAM destination. + u32 offset_0x16C; //reserved? + + u8 zero[0x10]; + + u32 arm9MBK1; + u32 arm9MBK2; + u32 arm9MBK3; + u32 arm9MBK4; + u32 arm9MBK5; + u32 arm9MBK6; + u32 arm9MBK7; + u32 arm9MBK8; + u32 arm7MBK6; + u32 arm7MBK7; + u32 arm7MBK8; + u32 arm9MBKMaster; + + u32 region; + u32 accessControl; + u32 arm7SCFGSettings; + u16 dsi_unk1; + u8 dsi_unk2; + u8 dsi_flags; + + u32 arm9iromOffset; //!< offset of the arm9 binary in the nds file. + u32 arm9iexecuteAddress; + u32 arm9idestination; //!< destination address to where the arm9 binary should be copied. + u32 arm9ibinarySize; //!< size of the arm9 binary. + + u32 arm7iromOffset; //!< offset of the arm7 binary in the nds file. + u32 deviceListDestination; + u32 arm7idestination; //!< destination address to where the arm7 binary should be copied. + u32 arm7ibinarySize; //!< size of the arm7 binary. + + u8 zero2[0x20]; + + // 0x200 + // TODO: More DSi-specific fields. + u32 dsi1[0x10/4]; + u32 twlRomSize; + u32 dsi_unk3; + u32 dsi_unk4; + u32 dsi_unk5; + + u32 modCrypt1Offset; + u32 modcrypt1Size; + u32 modcrypt2Offset; + u32 modcrypt2Size; + + u32 dsi_tid; + u32 dsi_tid2; + u32 pubSavSize; + u32 prvSavSize; + + u8 reserved3[176]; + u8 age_ratings[0x10]; + + unsigned char hmac_arm9[16]; + unsigned char hmac_arm7[16]; + u8 hmac_digest_master[0x14]; + u8 hmac_icon_title[0x14]; + u8 hmac_arm9i[0x14]; + u8 hmac_arm7i[0x14]; + u8 reserved4[0x28]; + u8 hmac_arm9_no_secure[0x14]; + u8 reserved5[0xA4C]; + u8 debug_args[0x180]; + u8 rsa_signature[0x80]; +} tTWLHeader; + + #define resetMemory2_ARM9_size 0x400 -void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9(); #define startBinary_ARM9_size 0x100 -void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9(); +// #define setSCFG_ARM9_size 0x400 #define ARM9_START_FLAG (*(vu8*)0x02FFFDFB) +void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9(); +// void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) setSCFG_ARM9(); +void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9(); + #endif // _BOOT_H_ diff --git a/arm9/common/tonccpy.c b/ndsbootloader/source/tonccpy.c similarity index 66% rename from arm9/common/tonccpy.c rename to ndsbootloader/source/tonccpy.c index a51437e..09f80ec 100644 --- a/arm9/common/tonccpy.c +++ b/ndsbootloader/source/tonccpy.c @@ -1,3 +1,4 @@ +#include #include "tonccpy.h" //# tonccpy.c @@ -11,18 +12,16 @@ \param size Fill-length in bytes. \note The pointers and size need not be word-aligned. */ -void tonccpy(void *dst, const void *src, uint size) -{ - if(size==0 || dst==0 || src==0) - return; +void tonccpy(void *dst, const void *src, uint size) { + + if(size==0 || dst==NULL || src==NULL) { return; } uint count; u16 *dst16; // hword destination u8 *src8; // byte source // Ideal case: copy by 4x words. Leaves tail for later. - if( ((u32)src|(u32)dst)%4==0 && size>=4) - { + if( ((u32)src|(u32)dst)%4==0 && size>=4) { u32 *src32= (u32*)src, *dst32= (u32*)dst; count= size/4; @@ -30,49 +29,43 @@ void tonccpy(void *dst, const void *src, uint size) count /= 4; // Duff's Device, good friend! + // Added fall through attribute to silance the compiler about this. ;) switch(tmp) { - do { *dst32++ = *src32++; - case 3: *dst32++ = *src32++; - case 2: *dst32++ = *src32++; - case 1: *dst32++ = *src32++; - case 0: ; } while(count--); + do { *dst32++ = *src32++; // fallthrough + case 3: *dst32++ = *src32++; // fallthrough + case 2: *dst32++ = *src32++; // fallthrough + case 1: *dst32++ = *src32++; // fallthrough + case 0: ;} while(count--); // fallthrough } // Check for tail size &= 3; - if(size == 0) - return; - + if(size == 0) { return; } src8= (u8*)src32; dst16= (u16*)dst32; - } - else // Unaligned. - { + } else { + // Unaligned. uint dstOfs= (u32)dst&1; src8= (u8*)src; dst16= (u16*)(dst-dstOfs); // Head: 1 byte. - if(dstOfs != 0) - { + if(dstOfs != 0) { *dst16= (*dst16 & 0xFF) | *src8++<<8; dst16++; - if(--size==0) - return; + if(--size==0) { return; } } } // Unaligned main: copy by 2x byte. count= size/2; - while(count--) - { + while(count--) { *dst16++ = src8[0] | src8[1]<<8; src8 += 2; } // Tail: 1 byte. - if(size&1) - *dst16= (*dst16 &~ 0xFF) | *src8; + if(size&1) { *dst16= (*dst16 &~ 0xFF) | *src8; } } //# toncset.c @@ -87,21 +80,17 @@ void tonccpy(void *dst, const void *src, uint size) word-aligned. In the case of unaligned fills, \a fill will be masked off to match the situation. */ -void __toncset(void *dst, u32 fill, uint size) -{ - if(size==0 || dst==0) - return; +void __toncset(void *dst, u32 fill, uint size) { + if(size==0 || dst==NULL) { return; } uint left= (u32)dst&3; u32 *dst32= (u32*)(dst-left); u32 count, mask; // Unaligned head. - if(left != 0) - { + if(left != 0) { // Adjust for very small stint. - if(left+size<4) - { + if(left+size<4) { mask= BIT_MASK(size*8)<<(left*8); *dst32= (*dst32 &~ mask) | (fill & mask); return; @@ -117,20 +106,21 @@ void __toncset(void *dst, u32 fill, uint size) count= size/4; uint tmp= count&3; count /= 4; - + + // Added fall through attribute to silance the compiler about this. ;) switch(tmp) { - do { *dst32++ = fill; - case 3: *dst32++ = fill; - case 2: *dst32++ = fill; - case 1: *dst32++ = fill; - case 0: ; } while(count--); + do { *dst32++ = fill; // fallthrough + case 3: *dst32++ = fill; // fallthrough + case 2: *dst32++ = fill; // fallthrough + case 1: *dst32++ = fill; // fallthrough + case 0: ;} while(count--); // fallthrough } // Tail size &= 3; - if(size) - { + if(size) { mask= BIT_MASK(size*8); *dst32= (*dst32 &~ mask) | (fill & mask); } } + diff --git a/ndsbootloader/source/tonccpy.h b/ndsbootloader/source/tonccpy.h new file mode 100644 index 0000000..dd4267d --- /dev/null +++ b/ndsbootloader/source/tonccpy.h @@ -0,0 +1,43 @@ +//# Stuff you may not have yet. + +#ifndef TONCCPY_H +#define TONCCPY_H + + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef unsigned int uint; +#define BIT_MASK(len) ( (1<<(len))-1 ) +static inline u32 quad8(u16 x) { x |= x<<8; return x | x<<16; } + + +//# Declarations and inlines. + +void tonccpy(void *dst, const void *src, uint size); + +void __toncset(void *dst, u32 fill, uint size); +static inline void toncset(void *dst, u8 src, uint size); +static inline void toncset16(void *dst, u16 src, uint size); +static inline void toncset32(void *dst, u32 src, uint size); + + +//! VRAM-safe memset, byte version. Size in bytes. +static inline void toncset(void *dst, u8 src, uint size) +{ __toncset(dst, quad8(src), size); } + +//! VRAM-safe memset, halfword version. Size in hwords. +static inline void toncset16(void *dst, u16 src, uint size) +{ __toncset(dst, src|src<<16, size*2); } + +//! VRAM-safe memset, word version. Size in words. +static inline void toncset32(void *dst, u32 src, uint size) +{ __toncset(dst, src, size*4); } + +#ifdef __cplusplus +} +#endif +#endif