From 9cc31b6f56d7b34ff14e0fb6cff8aa25eddec231 Mon Sep 17 00:00:00 2001 From: d0k3 Date: Wed, 8 May 2019 00:18:34 +0200 Subject: [PATCH] Fix several alignment assumptions --- arm9/source/crypto/aes.c | 24 ++++++++++++++++++------ arm9/source/crypto/keydb.h | 2 +- arm9/source/filesys/sddata.c | 4 ++-- arm9/source/game/boss.c | 2 +- arm9/source/game/cia.h | 2 +- arm9/source/game/exefs.h | 2 +- arm9/source/game/gba.c | 2 +- arm9/source/game/gba.h | 2 +- arm9/source/game/ncch.c | 4 ++-- arm9/source/game/ncch.h | 2 +- arm9/source/game/ticket.h | 2 +- arm9/source/game/ticketdb.c | 2 +- arm9/source/game/tmd.h | 6 +++--- arm9/source/nand/essentials.h | 8 ++++---- arm9/source/nand/nand.c | 6 +++--- arm9/source/utils/gameutil.c | 2 +- arm9/source/utils/nandcmac.c | 4 ++-- arm9/source/utils/nandutil.c | 4 ++-- arm9/source/utils/scripting.c | 2 +- arm9/source/virtual/vnand.c | 2 +- 20 files changed, 48 insertions(+), 36 deletions(-) diff --git a/arm9/source/crypto/aes.c b/arm9/source/crypto/aes.c index 355ae66..af0c6ab 100644 --- a/arm9/source/crypto/aes.c +++ b/arm9/source/crypto/aes.c @@ -1,11 +1,14 @@ /* original version by megazig */ #include "aes.h" -//FIXME some things make assumptions about alignemnts! - +// FIXME some things make assumptions about alignemnts! +// setup_aeskey? and set_ctr do not anymore (c) d0k3 void setup_aeskeyX(uint8_t keyslot, const void* keyx) { - const uint32_t * _keyx = (const uint32_t*)keyx; + uint32_t _keyx[4] __attribute__((aligned(32))); + for (uint32_t i = 0; i < 16u; i++) + ((uint8_t*)_keyx)[i] = ((uint8_t*)keyx)[i]; + *REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER; *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80; if (keyslot > 3) { @@ -25,7 +28,10 @@ void setup_aeskeyX(uint8_t keyslot, const void* keyx) void setup_aeskeyY(uint8_t keyslot, const void* keyy) { - const uint32_t * _keyy = (const uint32_t*)keyy; + uint32_t _keyy[4] __attribute__((aligned(32))); + for (uint32_t i = 0; i < 16u; i++) + ((uint8_t*)_keyy)[i] = ((uint8_t*)keyy)[i]; + *REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER; *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80; if (keyslot > 3) { @@ -45,7 +51,10 @@ void setup_aeskeyY(uint8_t keyslot, const void* keyy) void setup_aeskey(uint8_t keyslot, const void* key) { - const uint32_t * _key = (const uint32_t*)key; + uint32_t _key[4] __attribute__((aligned(32))); + for (uint32_t i = 0; i < 16u; i++) + ((uint8_t*)_key)[i] = ((uint8_t*)key)[i]; + *REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER; *REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80; if (keyslot > 3) { @@ -73,7 +82,10 @@ void use_aeskey(uint32_t keyno) void set_ctr(void* iv) { - uint32_t * _iv = (uint32_t*)iv; + uint32_t _iv[4] __attribute__((aligned(32))); + for (uint32_t i = 0; i < 16u; i++) + ((uint8_t*)_iv)[i] = ((uint8_t*)iv)[i]; + *REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER; *(REG_AESCTR + 0) = _iv[3]; *(REG_AESCTR + 1) = _iv[2]; diff --git a/arm9/source/crypto/keydb.h b/arm9/source/crypto/keydb.h index d142835..2cbd0a1 100644 --- a/arm9/source/crypto/keydb.h +++ b/arm9/source/crypto/keydb.h @@ -24,7 +24,7 @@ typedef struct { u8 keyUnitType; // 0 for ALL units / 1 for devkit exclusive / 2 for retail exclusive u8 isEncrypted; // 0 if not / anything else if it is u8 key[16]; -} __attribute__((packed)) AesKeyInfo; +} __attribute__((packed)) __attribute__((aligned(16))) AesKeyInfo; u32 GetUnitKeysType(void); void CryptAesKeyInfo(AesKeyInfo* info); diff --git a/arm9/source/filesys/sddata.c b/arm9/source/filesys/sddata.c index 8d59a37..ddf49d6 100644 --- a/arm9/source/filesys/sddata.c +++ b/arm9/source/filesys/sddata.c @@ -18,7 +18,7 @@ static FilCryptInfo filcrypt[NUM_FILCRYPTINFO] = { 0 }; char alias_drv[NUM_ALIAS_DRV]; // 1 char ASCII drive number of the alias drive / 0x00 if unused char alias_path[NUM_ALIAS_DRV][128]; // full path to resolve the alias into -u8 sd_keyy[NUM_ALIAS_DRV][16]; // key Y belonging to alias drive +u8 sd_keyy[NUM_ALIAS_DRV][16] __attribute__((aligned(4))); // key Y belonging to alias drive int alias_num (const TCHAR* path) { int num = -1; @@ -152,7 +152,7 @@ FRESULT fx_open (FIL* fp, const TCHAR* path, BYTE mode) { } else { // get AES counter, see: http://www.3dbrew.org/wiki/Extdata#Encryption // path is the part of the full path after //Nintendo 3DS// - u8 hashstr[256]; + u8 hashstr[256] __attribute__((aligned(4))); u8 sha256sum[32]; u32 plen = 0; // poor man's ASCII -> UTF-16 / uppercase -> lowercase diff --git a/arm9/source/game/boss.c b/arm9/source/game/boss.c index 3e530b5..e10396e 100644 --- a/arm9/source/game/boss.c +++ b/arm9/source/game/boss.c @@ -4,7 +4,7 @@ // http://3dbrew.org/wiki/SpotPass#Content_Header u32 CheckBossHash(BossHeader* boss, bool encrypted) { - u8 hash_area[0x14] = { 0 }; + u8 hash_area[0x14] __attribute__((aligned(4))) = { 0 }; u8 boss_sha256[0x20]; u8 l_sha256[0x20]; diff --git a/arm9/source/game/cia.h b/arm9/source/game/cia.h index 129be4a..f4a20f7 100644 --- a/arm9/source/game/cia.h +++ b/arm9/source/game/cia.h @@ -38,7 +38,7 @@ typedef struct { u8 ticket_padding[0x40 - (TICKET_SIZE % 0x40)]; TitleMetaData tmd; TmdContentChunk content_list[TMD_MAX_CONTENTS]; -} __attribute__((packed)) CiaStub; +} __attribute__((packed, aligned(16))) CiaStub; typedef struct { // first 0x20 bytes are identical with CIA header u32 size_header; diff --git a/arm9/source/game/exefs.h b/arm9/source/game/exefs.h index c86b4dd..07337c8 100644 --- a/arm9/source/game/exefs.h +++ b/arm9/source/game/exefs.h @@ -13,6 +13,6 @@ typedef struct { ExeFsFileHeader files[10]; u8 reserved[0x20]; u8 hashes[10][0x20]; -} __attribute__((packed)) ExeFsHeader; +} __attribute__((packed, aligned(16))) ExeFsHeader; u32 ValidateExeFsHeader(ExeFsHeader* exefs, u32 size); diff --git a/arm9/source/game/gba.c b/arm9/source/game/gba.c index 371760f..5a86969 100644 --- a/arm9/source/game/gba.c +++ b/arm9/source/game/gba.c @@ -29,7 +29,7 @@ u32 ValidateAgbSaveHeader(AgbSaveHeader* header) { // http://problemkaputt.de/gbatek.htm#gbacartridgeheader u32 ValidateAgbHeader(AgbHeader* agb) { const u8 logo_sha[0x20] = { AGBLOGO_SHA256 }; - u8 logo[0x9C]; + u8 logo[0x9C] __attribute__((aligned(4))); // check fixed value if (agb->fixed != 0x96) return 1; diff --git a/arm9/source/game/gba.h b/arm9/source/game/gba.h index 31d0b5c..f33d022 100644 --- a/arm9/source/game/gba.h +++ b/arm9/source/game/gba.h @@ -86,7 +86,7 @@ typedef struct { u8 checksum; // header checksum, required u8 reserved[2]; // always 0x00 // stuff for multiboot not included -} __attribute__((packed)) AgbHeader; +} __attribute__((packed, aligned(16))) AgbHeader; u32 ValidateAgbSaveHeader(AgbSaveHeader* header); diff --git a/arm9/source/game/ncch.c b/arm9/source/game/ncch.c index 2ed9c4f..703c37f 100644 --- a/arm9/source/game/ncch.c +++ b/arm9/source/game/ncch.c @@ -52,7 +52,7 @@ u32 GetNcchCtr(u8* ctr, NcchHeader* ncch, u8 section) { } u32 GetNcchSeed(u8* seed, NcchHeader* ncch) { - static u8 lseed[16+8] = { 0 }; // seed plus title ID for easy validation + static u8 lseed[16+8] __attribute__((aligned(4))) = { 0 }; // seed plus title ID for easy validation u64 titleId = ncch->programId; u32 hash_seed = ncch->hash_seed; u32 sha256sum[8]; @@ -175,7 +175,7 @@ u32 SetNcchKey(NcchHeader* ncch, u16 crypto, u32 keyid) { static u8 lsignature[16] = { 0 }; static u64 ltitleId = 0; if ((memcmp(lsignature, ncch->signature, 16) != 0) || (ltitleId != ncch->programId)) { - u8 keydata[16+16]; + u8 keydata[16+16] __attribute__((aligned(4))); memcpy(keydata, ncch->signature, 16); if (GetNcchSeed(keydata + 16, ncch) != 0) return 1; diff --git a/arm9/source/game/ncch.h b/arm9/source/game/ncch.h index 323d33b..15c4eed 100644 --- a/arm9/source/game/ncch.h +++ b/arm9/source/game/ncch.h @@ -54,7 +54,7 @@ typedef struct { u64 aci_limit_title_id; u32 aci_limit_core_version; u8 aci_limit_data[0x200 - 0xC]; -} __attribute__((packed)) NcchExtHeader; +} __attribute__((packed, aligned(16))) NcchExtHeader; // see: https://www.3dbrew.org/wiki/NCCH#NCCH_Header typedef struct { diff --git a/arm9/source/game/ticket.h b/arm9/source/game/ticket.h index ae6fcec..3c0a5bc 100644 --- a/arm9/source/game/ticket.h +++ b/arm9/source/game/ticket.h @@ -41,7 +41,7 @@ typedef struct { u8 reserved3[2]; u8 timelimits[0x40]; u8 content_index[0xAC]; -} __attribute__((packed)) Ticket; +} __attribute__((packed, aligned(4))) Ticket; u32 ValidateTicket(Ticket* ticket); u32 ValidateTicketSignature(Ticket* ticket); diff --git a/arm9/source/game/ticketdb.c b/arm9/source/game/ticketdb.c index e8cb897..a99cfd0 100644 --- a/arm9/source/game/ticketdb.c +++ b/arm9/source/game/ticketdb.c @@ -54,7 +54,7 @@ u32 GetTitleKey(u8* titlekey, Ticket* ticket) { Ticket* TicketFromTickDbChunk(u8* chunk, u8* title_id, bool legit_pls) { // chunk must be aligned to 0x200 byte in file and at least 0x400 byte big - Ticket* tick = (Ticket*) (chunk + 0x18); + Ticket* tick = (Ticket*) (void*) (chunk + 0x18); if ((getle32(chunk + 0x10) == 0) || (getle32(chunk + 0x14) != sizeof(Ticket))) return NULL; if (ValidateTicket(tick) != 0) return NULL; // ticket not validated if (title_id && (memcmp(title_id, tick->title_id, 8) != 0)) return NULL; // title id not matching diff --git a/arm9/source/game/tmd.h b/arm9/source/game/tmd.h index 8d1cc0d..9bc6104 100644 --- a/arm9/source/game/tmd.h +++ b/arm9/source/game/tmd.h @@ -22,13 +22,13 @@ typedef struct { u8 type[2]; u8 size[8]; u8 hash[0x20]; -} __attribute__((packed)) TmdContentChunk; +} __attribute__((packed, aligned(4))) TmdContentChunk; typedef struct { u8 index[2]; u8 cmd_count[2]; u8 hash[0x20]; -} __attribute__((packed)) TmdContentInfo; +} __attribute__((packed, aligned(4))) TmdContentInfo; typedef struct { u8 sig_type[4]; @@ -55,7 +55,7 @@ typedef struct { u8 reserved3[2]; u8 contentinfo_hash[0x20]; TmdContentInfo contentinfo[64]; -} __attribute__((packed)) TitleMetaData; +} __attribute__((packed, aligned(4))) TitleMetaData; u32 ValidateTmd(TitleMetaData* tmd); u32 ValidateTmdSignature(TitleMetaData* tmd); diff --git a/arm9/source/nand/essentials.h b/arm9/source/nand/essentials.h index 63d1299..40634fd 100644 --- a/arm9/source/nand/essentials.h +++ b/arm9/source/nand/essentials.h @@ -17,7 +17,7 @@ typedef struct { u8 signature[0x100]; u8 unknown[0x8]; // normally zero u8 codeseed[0x8]; // the actual data -} __attribute__((packed)) LocalFriendCodeSeed; +} __attribute__((packed, aligned(4))) LocalFriendCodeSeed; // /private/movable.sed file // see: http://3dbrew.org/wiki/Nand/private/movable.sed @@ -28,7 +28,7 @@ typedef struct { u8 keyy_high[8]; u8 unknown[0x10]; u8 cmac[0x10]; -} __attribute__((packed)) MovableSed; +} __attribute__((packed, aligned(4))) MovableSed; // /rw/sys/SecureInfo_A (/_B) file // see: http://3dbrew.org/wiki/Nandrw/sys/SecureInfo_A @@ -37,7 +37,7 @@ typedef struct { u8 region; u8 unknown; char serial[0xF]; -} __attribute__((packed)) SecureInfo; +} __attribute__((packed, aligned(4))) SecureInfo; // includes all essential system files // (this is of our own making) @@ -58,4 +58,4 @@ typedef struct { u8 padding_hwcal0[0x200 - (SIZE_HWCAL%0x200)]; u8 hwcal1[SIZE_HWCAL]; u8 padding_hwcal1[0x200 - (SIZE_HWCAL%0x200)]; -} __attribute__((packed)) EssentialBackup; +} __attribute__((packed, aligned(16))) EssentialBackup; diff --git a/arm9/source/nand/nand.c b/arm9/source/nand/nand.c index e91aaea..8c06dad 100644 --- a/arm9/source/nand/nand.c +++ b/arm9/source/nand/nand.c @@ -26,7 +26,7 @@ static const u32 np_keyslots[10][4] = { // [NP_TYPE][NP_SUBTYPE] { 0xFF, 0xFF, 0xFF, 0xFF } // BONUS (custom) }; -static u8 slot0x05KeyY[0x10] = { 0x00 }; // need to load this from FIRM0 / external file +static u8 slot0x05KeyY[0x10] __attribute__((aligned(4))) = { 0x00 }; // need to load this from FIRM0 / external file static const u8 slot0x05KeyY_sha256[0x20] = { // hash for slot0x05KeyY (16 byte) 0x98, 0x24, 0x27, 0x14, 0x22, 0xB0, 0x6B, 0xF2, 0x10, 0x96, 0x9C, 0x36, 0x42, 0x53, 0x7C, 0x86, 0x62, 0x22, 0x5C, 0xFD, 0x6F, 0xAE, 0x9B, 0x0A, 0x85, 0xA5, 0xCE, 0x21, 0xAA, 0xB6, 0xC8, 0x4D @@ -195,7 +195,7 @@ bool CheckSlot0x05Crypto(void) bool CheckSector0x96Crypto(void) { if (!Crypto0x96) { - u8 buffer[0x200]; + u8 buffer[0x200] __attribute__((aligned(4))); ReadNandSectors(buffer, SECTOR_SECRET, 1, 0x11, NAND_SYSNAND); Crypto0x96 = (sha_cmp(KEY95_SHA256, buffer, 16, SHA256_MODE) == 0); } @@ -213,7 +213,7 @@ bool CheckGenuineNandNcsd(void) 0xA4, 0xBD, 0x25, 0x03, 0x06, 0x03, 0x47, 0x0B, 0x24, 0x5A, 0x86, 0x6A, 0x43, 0x60, 0xBC, 0x84, }; - u8 gen_hdr[0x100]; + u8 gen_hdr[0x100] __attribute__((aligned(4))); if ((ReadNandBytes(gen_hdr, 0x100, 0x100, 0xFF, NAND_SYSNAND) != 0) || (ReadNandBytes(gen_hdr + 0xBE, 0x1BE, 0x42, 0x03, NAND_SYSNAND) != 0)) return false; diff --git a/arm9/source/utils/gameutil.c b/arm9/source/utils/gameutil.c index 0294cda..8aff4ec 100644 --- a/arm9/source/utils/gameutil.c +++ b/arm9/source/utils/gameutil.c @@ -2403,7 +2403,7 @@ u32 BuildSeedInfo(const char* path, bool dump) { char path_str[128]; if (path_in && (strnlen(path_in, 16) == 2)) { // when only a drive is given... // grab the key Y from movable.sed - u8 movable_keyy[16]; + u8 movable_keyy[16] __attribute__((aligned(4))); snprintf(path_str, 128, "%s/private/movable.sed", path_in); if (fvx_qread(path_str, movable_keyy, 0x110, 0x10, NULL) != FR_OK) return 1; diff --git a/arm9/source/utils/nandcmac.c b/arm9/source/utils/nandcmac.c index 5b4c80d..edc31c1 100644 --- a/arm9/source/utils/nandcmac.c +++ b/arm9/source/utils/nandcmac.c @@ -160,7 +160,7 @@ u32 CalculateFileCmac(const char* path, u8* cmac) { else if (!cmac_type) return 1; const u32 cmac_keyslot[] = { CMAC_KEYSLOT }; - u8 hashdata[0x200]; + u8 hashdata[0x200] __attribute__((aligned(4))); u32 keyslot = cmac_keyslot[cmac_type]; u32 hashsize = 0; @@ -247,7 +247,7 @@ u32 FixFileCmac(const char* path) { u32 FixAgbSaveCmac(void* data, u8* cmac, const char* sddrv) { AgbSaveHeader* agbsave = (AgbSaveHeader*) (void*) data; - u8 temp[0x30]; // final hash @temp+0x00 + u8 temp[0x30] __attribute__((aligned(4))); // final hash @temp+0x00 // safety check if (ValidateAgbSaveHeader(agbsave) != 0) diff --git a/arm9/source/utils/nandutil.c b/arm9/source/utils/nandutil.c index 700ae30..f5ea875 100644 --- a/arm9/source/utils/nandutil.c +++ b/arm9/source/utils/nandutil.c @@ -527,7 +527,7 @@ u32 SafeInstallFirmBuffered(const char* path, u32 slots, u8* buffer, u32 bufsiz) } // check sector 0x96 on N3DS, offer fix if required - u8 sector0x96[0x200]; + u8 sector0x96[0x200] __attribute__((aligned(4))); bool fix_sector0x96 = false; ReadNandSectors(sector0x96, 0x96, 1, 0x11, NAND_SYSNAND); if (!IS_O3DS && !CheckSector0x96Crypto()) { @@ -605,7 +605,7 @@ u32 SafeInstallFirm(const char* path, u32 slots) { u32 SafeInstallKeyDb(const char* path) { const u8 perfect_sha[] = { KEYDB_PERFECT_HASH }; - u8 keydb[KEYDB_PERFECT_SIZE]; + u8 keydb[KEYDB_PERFECT_SIZE] __attribute__((aligned(4))); char pathstr[32 + 1]; // truncated path string TruncateString(pathstr, path, 32, 8); diff --git a/arm9/source/utils/scripting.c b/arm9/source/utils/scripting.c index f8f0b9e..c1cbae0 100644 --- a/arm9/source/utils/scripting.c +++ b/arm9/source/utils/scripting.c @@ -402,7 +402,7 @@ void upd_var(const char* name) { if (!name || (strncmp(name, env_id0_name, _VAR_NAME_LEN) == 0)) { const char* path = emu ? "4:/private/movable.sed" : "1:/private/movable.sed"; char env_id0[32+1]; - u8 sd_keyy[0x10]; + u8 sd_keyy[0x10] __attribute__((aligned(4))); if (FileGetData(path, sd_keyy, 0x10, 0x110) == 0x10) { u32 sha256sum[8]; sha_quick(sha256sum, sd_keyy, 0x10, SHA256_MODE); diff --git a/arm9/source/virtual/vnand.c b/arm9/source/virtual/vnand.c index afd60da..96a2480 100644 --- a/arm9/source/virtual/vnand.c +++ b/arm9/source/virtual/vnand.c @@ -93,7 +93,7 @@ bool ReadVNandDir(VirtualFile* vfile, VirtualDir* vdir) { // uses a generic vdir } if (vfile->flags & VFLAG_KEYDB) { const u8 perfect_sha[] = { KEYDB_PERFECT_HASH }; - u8 keydb[KEYDB_PERFECT_SIZE]; + u8 keydb[KEYDB_PERFECT_SIZE] __attribute__((aligned(4))); ReadNandBytes(keydb, vfile->offset, KEYDB_PERFECT_SIZE, vfile->keyslot, nand_src); if (sha_cmp(perfect_sha, keydb, KEYDB_PERFECT_SIZE, SHA256_MODE) != 0) continue; vfile->size = KEYDB_PERFECT_SIZE;