mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Use iomemcpy for registers (thanks @profi200)
This commit is contained in:
parent
afd2c6593c
commit
151e6389ac
32
arm9/source/common/asmfunc.h
Normal file
32
arm9/source/common/asmfunc.h
Normal file
@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2017 derrek, profi200
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#if !__ASSEMBLER__
|
||||
#error Only include this in assembly files!
|
||||
#endif
|
||||
|
||||
|
||||
.macro ASM_FUNC name
|
||||
.section .text.\name, "ax", %progbits
|
||||
.global \name
|
||||
.type \name %function
|
||||
.align 2
|
||||
\name:
|
||||
.endm
|
26
arm9/source/common/mmio.h
Normal file
26
arm9/source/common/mmio.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
// Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
|
||||
void iomemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size);
|
||||
void iomemset(vu32 *ptr, u32 value, u32 size);
|
87
arm9/source/common/mmio.s
Normal file
87
arm9/source/common/mmio.s
Normal file
@ -0,0 +1,87 @@
|
||||
/*
|
||||
* This file is part of fastboot 3DS
|
||||
* Copyright (C) 2019 Aurora Wright, TuxSH, derrek, profi200
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
@ Based on https://github.com/AuroraWright/Luma3DS/blob/master/arm9/source/alignedseqmemcpy.s
|
||||
|
||||
#include "asmfunc.h"
|
||||
|
||||
.arm
|
||||
.cpu arm946e-s
|
||||
.fpu softvfp
|
||||
|
||||
|
||||
|
||||
@ void iomemcpy(vu32 *restrict dst, const vu32 *restrict src, u32 size)
|
||||
ASM_FUNC iomemcpy
|
||||
bics r12, r2, #31
|
||||
beq iomemcpy_test_words
|
||||
stmfd sp!, {r4-r10}
|
||||
iomemcpy_blocks_lp:
|
||||
ldmia r1!, {r3-r10}
|
||||
stmia r0!, {r3-r10}
|
||||
subs r12, #32
|
||||
bne iomemcpy_blocks_lp
|
||||
ldmfd sp!, {r4-r10}
|
||||
iomemcpy_test_words:
|
||||
ands r12, r2, #28
|
||||
beq iomemcpy_halfword_byte
|
||||
iomemcpy_words_lp:
|
||||
ldr r3, [r1], #4
|
||||
str r3, [r0], #4
|
||||
subs r12, #4
|
||||
bne iomemcpy_words_lp
|
||||
iomemcpy_halfword_byte:
|
||||
tst r2, #2
|
||||
ldrneh r3, [r1], #2
|
||||
strneh r3, [r0], #2
|
||||
tst r2, #1
|
||||
ldrneb r3, [r1]
|
||||
strneb r3, [r0]
|
||||
bx lr
|
||||
|
||||
|
||||
@ void iomemset(vu32 *ptr, u32 value, u32 size)
|
||||
ASM_FUNC iomemset
|
||||
bics r12, r2, #31
|
||||
beq iomemset_test_words
|
||||
stmfd sp!, {r4-r9}
|
||||
mov r3, r1
|
||||
mov r4, r1
|
||||
mov r5, r1
|
||||
mov r6, r1
|
||||
mov r7, r1
|
||||
mov r8, r1
|
||||
mov r9, r1
|
||||
iomemset_blocks_lp:
|
||||
stmia r0!, {r1, r3-r9}
|
||||
subs r12, #32
|
||||
bne iomemset_blocks_lp
|
||||
ldmfd sp!, {r4-r9}
|
||||
iomemset_test_words:
|
||||
ands r12, r2, #28
|
||||
beq iomemset_halfword_byte
|
||||
iomemset_words_lp:
|
||||
str r1, [r0], #4
|
||||
subs r12, #4
|
||||
bne iomemset_words_lp
|
||||
iomemset_halfword_byte:
|
||||
tst r2, #2
|
||||
strneh r1, [r0], #2
|
||||
tst r2, #1
|
||||
strneb r1, [r0]
|
||||
bx lr
|
@ -16,15 +16,10 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* To ensure correct functionality, the builtin memcpy should perform a sequential copy.
|
||||
* If not, it should be replaced with a different reimplementation that does for sure act sequential.
|
||||
* Or alternatively, it's own memcpy with it's own name, say perhaps seqmemcpy, and memcpy calls replaced.
|
||||
*/
|
||||
|
||||
#include "common.h"
|
||||
#include "rsa.h"
|
||||
#include "sha.h"
|
||||
#include "mmio.h"
|
||||
|
||||
|
||||
|
||||
@ -40,9 +35,9 @@
|
||||
#define REGs_RSA_SLOT2 ((vu32*)(RSA_REGS_BASE + 0x120))
|
||||
#define REGs_RSA_SLOT3 ((vu32*)(RSA_REGS_BASE + 0x130))
|
||||
#define rsaSlots ((RsaSlot*)(RSA_REGS_BASE + 0x100))
|
||||
#define REG_RSA_EXP ((vu32*)(RSA_REGS_BASE + 0x200))
|
||||
#define REG_RSA_MOD ( (RSA_REGS_BASE + 0x400))
|
||||
#define REG_RSA_TXT ( (RSA_REGS_BASE + 0x800))
|
||||
#define REGs_RSA_EXP ((vu32*)(RSA_REGS_BASE + 0x200))
|
||||
#define REGs_RSA_MOD ((vu32*)(RSA_REGS_BASE + 0x400))
|
||||
#define REGs_RSA_TXT ((vu32*)(RSA_REGS_BASE + 0x800))
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -69,7 +64,7 @@ void RSA_selectKeyslot(u8 keyslot)
|
||||
REG_RSA_CNT = (REG_RSA_CNT & ~RSA_KEYSLOT(0xFu)) | RSA_KEYSLOT(keyslot);
|
||||
}
|
||||
|
||||
bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp)
|
||||
bool RSA_setKey2048(u8 keyslot, const u32 *const mod, u32 exp)
|
||||
{
|
||||
RsaSlot *slot = &rsaSlots[keyslot];
|
||||
rsaWaitBusy();
|
||||
@ -78,35 +73,35 @@ bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp)
|
||||
if(!(slot->REG_RSA_SLOTCNT & RSA_KEY_UNK_BIT31)) slot->REG_RSA_SLOTCNT &= ~RSA_KEY_STAT_SET;
|
||||
|
||||
REG_RSA_CNT = RSA_INPUT_NORMAL | RSA_INPUT_BIG | RSA_KEYSLOT(keyslot);
|
||||
memset((void*)REG_RSA_EXP, 0, 0x100 - 4);
|
||||
REG_RSA_EXP[(0x100>>2) - 1] = exp;
|
||||
iomemset(REGs_RSA_EXP, 0, 0x100 - 4);
|
||||
REGs_RSA_EXP[(0x100>>2) - 1] = exp;
|
||||
|
||||
if(slot->REG_RSA_SLOTSIZE != RSA_SLOTSIZE_2048) return false;
|
||||
memcpy((void*)REG_RSA_MOD, mod, 0x100);
|
||||
iomemcpy(REGs_RSA_MOD, mod, 0x100);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RSA_decrypt2048(void *const decSig, const void *const encSig)
|
||||
bool RSA_decrypt2048(u32 *const decSig, const u32 *const encSig)
|
||||
{
|
||||
const u8 keyslot = RSA_GET_KEYSLOT;
|
||||
rsaWaitBusy();
|
||||
if(!(rsaSlots[keyslot].REG_RSA_SLOTCNT & RSA_KEY_STAT_SET)) return false;
|
||||
|
||||
REG_RSA_CNT |= RSA_INPUT_NORMAL | RSA_INPUT_BIG;
|
||||
memcpy((void*)REG_RSA_TXT, encSig, 0x100);
|
||||
iomemcpy(REGs_RSA_TXT, encSig, 0x100);
|
||||
|
||||
REG_RSA_CNT |= RSA_ENABLE;
|
||||
rsaWaitBusy();
|
||||
memcpy(decSig, (void*)REG_RSA_TXT, 0x100);
|
||||
iomemcpy(decSig, REGs_RSA_TXT, 0x100);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool RSA_verify2048(const u32 *const encSig, const u32 *const data, u32 size)
|
||||
{
|
||||
u8 decSig[0x100];
|
||||
if(!RSA_decrypt2048(decSig, encSig)) return false;
|
||||
alignas(4) u8 decSig[0x100];
|
||||
if(!RSA_decrypt2048((u32*)(void*)decSig, encSig)) return false;
|
||||
|
||||
if(decSig[0] != 0x00 || decSig[1] != 0x01) return false;
|
||||
|
||||
|
@ -66,7 +66,7 @@ void RSA_selectKeyslot(u8 keyslot);
|
||||
*
|
||||
* @return Returns true on success, false otherwise.
|
||||
*/
|
||||
bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp);
|
||||
bool RSA_setKey2048(u8 keyslot, const u32 *const mod, u32 exp);
|
||||
|
||||
/**
|
||||
* @brief Decrypts a RSA 2048 signature.
|
||||
@ -76,7 +76,7 @@ bool RSA_setKey2048(u8 keyslot, const u8 *const mod, u32 exp);
|
||||
*
|
||||
* @return Returns true on success, false otherwise.
|
||||
*/
|
||||
bool RSA_decrypt2048(void *const decSig, const void *const encSig);
|
||||
bool RSA_decrypt2048(u32 *const decSig, const u32 *const encSig);
|
||||
|
||||
/**
|
||||
* @brief Verifies a RSA 2048 SHA 256 signature.
|
||||
|
@ -1,9 +1,5 @@
|
||||
/*
|
||||
* To ensure correct functionality, the builtin memcpy should perform a sequential copy.
|
||||
* If not, it should be replaced with a different reimplementation that does for sure act sequential.
|
||||
* Or alternatively, it's own memcpy with it's own name, say perhaps seqmemcpy, and memcpy calls replaced, as well the line "*((_sha_block*)REG_SHAINFIFO) = *((const _sha_block*)src32);" inside sha_update, to call explicitly seqmemcpy like, "seqmemcpy(REG_SHAINFIFO, src32, 0x40);".
|
||||
*/
|
||||
#include "sha.h"
|
||||
#include "mmio.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -27,7 +23,7 @@ void sha_update(const void* src, u32 size)
|
||||
size -= 0x40;
|
||||
}
|
||||
while(*REG_SHACNT & 1);
|
||||
if(size) memcpy((void*)REG_SHAINFIFO, src32, size);
|
||||
if(size) iomemcpy((void*)REG_SHAINFIFO, src32, size);
|
||||
}
|
||||
|
||||
void sha_get(void* res) {
|
||||
@ -36,7 +32,7 @@ void sha_get(void* res) {
|
||||
*REG_SHACNT = (*REG_SHACNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
|
||||
while(*REG_SHACNT & SHA_FINAL_ROUND);
|
||||
while(*REG_SHACNT & 1);
|
||||
if (hash_size) memcpy(res, (void*)REG_SHAHASH, hash_size);
|
||||
if (hash_size) iomemcpy(res, (void*)REG_SHAHASH, hash_size);
|
||||
}
|
||||
|
||||
void sha_quick(void* res, const void* src, u32 size, u32 mode) {
|
||||
|
@ -1,7 +1,7 @@
|
||||
#include "cert.h"
|
||||
#include "ff.h"
|
||||
|
||||
u32 LoadCertFromCertDb(u64 offset, Certificate* cert, u8* mod, u32* exp) {
|
||||
u32 LoadCertFromCertDb(u64 offset, Certificate* cert, u32* mod, u32* exp) {
|
||||
Certificate cert_local;
|
||||
FIL db;
|
||||
UINT bytes_read;
|
||||
|
@ -19,4 +19,4 @@ typedef struct {
|
||||
u8 padding1[0x34];
|
||||
} __attribute__((packed)) Certificate;
|
||||
|
||||
u32 LoadCertFromCertDb(u64 offset, Certificate* cert, u8* mod, u32* exp);
|
||||
u32 LoadCertFromCertDb(u64 offset, Certificate* cert, u32* mod, u32* exp);
|
||||
|
@ -17,7 +17,7 @@ u32 ValidateTicket(Ticket* ticket) {
|
||||
|
||||
u32 ValidateTicketSignature(Ticket* ticket) {
|
||||
static bool got_modexp = false;
|
||||
static u8 mod[0x100] = { 0 };
|
||||
static u32 mod[0x100 / 0x4] = { 0 };
|
||||
static u32 exp = 0;
|
||||
|
||||
if (!got_modexp) {
|
||||
|
@ -16,7 +16,7 @@ u32 ValidateTmd(TitleMetaData* tmd) {
|
||||
|
||||
u32 ValidateTmdSignature(TitleMetaData* tmd) {
|
||||
static bool got_modexp = false;
|
||||
static u8 mod[0x100] = { 0 };
|
||||
static u32 mod[0x100 / 4] = { 0 };
|
||||
static u32 exp = 0;
|
||||
|
||||
if (!got_modexp) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user