forked from Mirror/GodMode9
165 lines
3.6 KiB
C
165 lines
3.6 KiB
C
|
/* original version by megazig */
|
||
|
#include "aes.h"
|
||
|
|
||
|
void setup_aeskeyX(u8 keyslot, void* keyx)
|
||
|
{
|
||
|
u32 * _keyx = (u32*)keyx;
|
||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||
|
*REG_AESKEYXFIFO = _keyx[0];
|
||
|
*REG_AESKEYXFIFO = _keyx[1];
|
||
|
*REG_AESKEYXFIFO = _keyx[2];
|
||
|
*REG_AESKEYXFIFO = _keyx[3];
|
||
|
}
|
||
|
|
||
|
void setup_aeskeyY(u8 keyslot, void* keyy)
|
||
|
{
|
||
|
u32 * _keyy = (u32*)keyy;
|
||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||
|
*REG_AESKEYYFIFO = _keyy[0];
|
||
|
*REG_AESKEYYFIFO = _keyy[1];
|
||
|
*REG_AESKEYYFIFO = _keyy[2];
|
||
|
*REG_AESKEYYFIFO = _keyy[3];
|
||
|
}
|
||
|
|
||
|
void setup_aeskey(u8 keyslot, void* key)
|
||
|
{
|
||
|
u32 * _key = (u32*)key;
|
||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||
|
*REG_AESKEYFIFO = _key[0];
|
||
|
*REG_AESKEYFIFO = _key[1];
|
||
|
*REG_AESKEYFIFO = _key[2];
|
||
|
*REG_AESKEYFIFO = _key[3];
|
||
|
}
|
||
|
|
||
|
void use_aeskey(u32 keyno)
|
||
|
{
|
||
|
if (keyno > 0x3F)
|
||
|
return;
|
||
|
*REG_AESKEYSEL = keyno;
|
||
|
*REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */
|
||
|
}
|
||
|
|
||
|
void set_ctr(void* iv)
|
||
|
{
|
||
|
u32 * _iv = (u32*)iv;
|
||
|
*REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER;
|
||
|
*(REG_AESCTR + 0) = _iv[3];
|
||
|
*(REG_AESCTR + 1) = _iv[2];
|
||
|
*(REG_AESCTR + 2) = _iv[1];
|
||
|
*(REG_AESCTR + 3) = _iv[0];
|
||
|
}
|
||
|
|
||
|
void add_ctr(void* ctr, u32 carry)
|
||
|
{
|
||
|
u32 counter[4];
|
||
|
u8 *outctr = (u8 *) ctr;
|
||
|
u32 sum;
|
||
|
int32_t 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;
|
||
|
if (sum < counter[i]) {
|
||
|
carry = 1;
|
||
|
}
|
||
|
else {
|
||
|
carry = 0;
|
||
|
}
|
||
|
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 aes_decrypt(void* inbuf, void* outbuf, size_t size, u32 mode)
|
||
|
{
|
||
|
u32 in = (u32)inbuf;
|
||
|
u32 out = (u32)outbuf;
|
||
|
size_t block_count = size;
|
||
|
size_t blocks;
|
||
|
while (block_count != 0)
|
||
|
{
|
||
|
blocks = (block_count >= 0xFFFF) ? 0xFFFF : block_count;
|
||
|
*REG_AESCNT = 0;
|
||
|
*REG_AESBLKCNT = blocks << 16;
|
||
|
*REG_AESCNT = mode |
|
||
|
AES_CNT_START |
|
||
|
AES_CNT_FLUSH_READ |
|
||
|
AES_CNT_FLUSH_WRITE;
|
||
|
aes_fifos((void*)in, (void*)out, blocks);
|
||
|
in += blocks * AES_BLOCK_SIZE;
|
||
|
out += blocks * AES_BLOCK_SIZE;
|
||
|
block_count -= blocks;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void aes_fifos(void* inbuf, void* outbuf, size_t blocks)
|
||
|
{
|
||
|
u32 in = (u32)inbuf;
|
||
|
if (!in) return;
|
||
|
|
||
|
u32 out = (u32)outbuf;
|
||
|
size_t curblock = 0;
|
||
|
while (curblock != blocks)
|
||
|
{
|
||
|
while (aescnt_checkwrite());
|
||
|
|
||
|
int ii = 0;
|
||
|
for (ii = in; ii != in + AES_BLOCK_SIZE; ii += 4)
|
||
|
{
|
||
|
set_aeswrfifo( *(u32*)(ii) );
|
||
|
}
|
||
|
if (out)
|
||
|
{
|
||
|
while (aescnt_checkread()) ;
|
||
|
for (ii = out; ii != out + AES_BLOCK_SIZE; ii += 4)
|
||
|
{
|
||
|
*(u32*)ii = read_aesrdfifo();
|
||
|
}
|
||
|
}
|
||
|
curblock++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void set_aeswrfifo(u32 value)
|
||
|
{
|
||
|
*REG_AESWRFIFO = value;
|
||
|
}
|
||
|
|
||
|
u32 read_aesrdfifo(void)
|
||
|
{
|
||
|
return *REG_AESRDFIFO;
|
||
|
}
|
||
|
|
||
|
u32 aes_getwritecount()
|
||
|
{
|
||
|
return *REG_AESCNT & 0x1F;
|
||
|
}
|
||
|
|
||
|
u32 aes_getreadcount()
|
||
|
{
|
||
|
return (*REG_AESCNT >> 5) & 0x1F;
|
||
|
}
|
||
|
|
||
|
u32 aescnt_checkwrite()
|
||
|
{
|
||
|
size_t ret = aes_getwritecount();
|
||
|
return (ret > 0xF);
|
||
|
}
|
||
|
|
||
|
u32 aescnt_checkread()
|
||
|
{
|
||
|
size_t ret = aes_getreadcount();
|
||
|
return (ret <= 3);
|
||
|
}
|