Improved and extended aes.c / aes.h

Thanks @Gemarcano
This commit is contained in:
d0k3 2016-12-07 00:00:05 +01:00
parent ae9a8aaf75
commit c2a4d5c0d1
4 changed files with 82 additions and 23 deletions

View File

@ -3,9 +3,9 @@
//FIXME some things make assumptions about alignemnts!
void setup_aeskeyX(uint8_t keyslot, void* keyx)
void setup_aeskeyX(uint8_t keyslot, const void* keyx)
{
uint32_t * _keyx = (uint32_t*)keyx;
const uint32_t * _keyx = (const uint32_t*)keyx;
*REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
if (keyslot > 3) {
@ -23,9 +23,9 @@ void setup_aeskeyX(uint8_t keyslot, void* keyx)
}
}
void setup_aeskeyY(uint8_t keyslot, void* keyy)
void setup_aeskeyY(uint8_t keyslot, const void* keyy)
{
uint32_t * _keyy = (uint32_t*)keyy;
const uint32_t * _keyy = (const uint32_t*)keyy;
*REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
if (keyslot > 3) {
@ -43,9 +43,9 @@ void setup_aeskeyY(uint8_t keyslot, void* keyy)
}
}
void setup_aeskey(uint8_t keyslot, void* key)
void setup_aeskey(uint8_t keyslot, const void* key)
{
uint32_t * _key = (uint32_t*)key;
const uint32_t * _key = (const uint32_t*)key;
*REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER;
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
if (keyslot > 3) {
@ -88,7 +88,8 @@ void add_ctr(void* ctr, uint32_t carry)
uint32_t sum;
int32_t i;
for(i=0; i < 4; i++) {
for(i = 0; i < 4; i++) {
//FIXME this assumes alignment...
counter[i] = ((uint32_t)outctr[i*4+0]<<24) | ((uint32_t)outctr[i*4+1]<<16) | ((uint32_t)outctr[i*4+2]<<8) | ((uint32_t)outctr[i*4+3]<<0);
}
@ -113,23 +114,80 @@ void add_ctr(void* ctr, uint32_t carry)
}
}
void ctr_decrypt_boffset(void *inbuf, void *outbuf, size_t size, size_t off, uint32_t mode, uint8_t *ctr)
void subtract_ctr(void* ctr, uint32_t carry)
{
//ctr is in big endian format, 16 bytes
uint32_t counter[4];
uint8_t *outctr = (uint8_t *) ctr;
//Convert each 4 byte part of ctr to uint32_t equivalents
for(size_t i = 0; i < 4; i++) {
//FIXME this assumes alignment...
counter[i] = ((uint32_t)outctr[i*4+0]<<24) | ((uint32_t)outctr[i*4+1]<<16) | ((uint32_t)outctr[i*4+2]<<8) | ((uint32_t)outctr[i*4+3]<<0);
}
for(size_t i = 0; i < 4; ++i)
{
uint32_t sub;
//using modular arithmetic to handle carry
sub = counter[3-i] - carry;
carry = counter[3-i] < carry;
counter[3-i] = sub;
}
for(size_t 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 ecb_decrypt(void *inbuf, void *outbuf, size_t size, uint32_t mode)
{
aes_decrypt(inbuf, outbuf, size, mode);
}
void cbc_decrypt(void *inbuf, void *outbuf, size_t size, uint32_t mode, uint8_t *ctr)
{
size_t blocks_left = size;
size_t blocks;
uint8_t *in = inbuf;
uint8_t *out = outbuf;
uint32_t i;
while (blocks_left)
{
set_ctr(ctr);
blocks = (blocks_left >= 0xFFFF) ? 0xFFFF : blocks_left;
for (i=0; i<AES_BLOCK_SIZE; i++)
ctr[i] = in[(blocks - 1) * AES_BLOCK_SIZE] + i;
aes_decrypt(in, out, blocks, mode);
in += blocks * AES_BLOCK_SIZE;
out += blocks * AES_BLOCK_SIZE;
blocks_left -= blocks;
}
}
void ctr_decrypt_byte(void *inbuf, void *outbuf, size_t size, size_t off, uint32_t mode, uint8_t *ctr)
{
size_t bytes_left = size;
size_t off_fix = off % AES_BLOCK_SIZE;
uint8_t temp[AES_BLOCK_SIZE];
uint8_t ctr_local[16];
uint8_t __attribute__((aligned(32))) temp[AES_BLOCK_SIZE];
uint8_t __attribute__((aligned(32))) ctr_local[AES_BLOCK_SIZE];
uint8_t *in = inbuf;
uint8_t *out = outbuf;
uint32_t i;
for (i=0; i<16; i++) // setup local ctr
for (i=0; i<AES_BLOCK_SIZE; i++) // setup local ctr
ctr_local[i] = ctr[i];
add_ctr(ctr_local, off / AES_BLOCK_SIZE);
if (off_fix) // handle misaligned offset (at beginning)
{
uint32_t last_byte = ((off_fix + bytes_left) >= AES_BLOCK_SIZE) ?
size_t last_byte = ((off_fix + bytes_left) >= AES_BLOCK_SIZE) ?
AES_BLOCK_SIZE : off_fix + bytes_left;
for (i=off_fix; i<last_byte; i++)
temp[i] = *(in++);
@ -141,10 +199,11 @@ void ctr_decrypt_boffset(void *inbuf, void *outbuf, size_t size, size_t off, uin
if (bytes_left >= AES_BLOCK_SIZE)
{
ctr_decrypt(in, out, bytes_left / AES_BLOCK_SIZE, mode, ctr_local);
in += AES_BLOCK_SIZE * (uint32_t) (bytes_left / AES_BLOCK_SIZE);
out += AES_BLOCK_SIZE * (uint32_t) (bytes_left / AES_BLOCK_SIZE);
bytes_left -= AES_BLOCK_SIZE * (uint32_t) (bytes_left / AES_BLOCK_SIZE);
size_t blocks = bytes_left / AES_BLOCK_SIZE;
ctr_decrypt(in, out, blocks, mode, ctr_local);
in += AES_BLOCK_SIZE * blocks;
out += AES_BLOCK_SIZE * blocks;
bytes_left -= AES_BLOCK_SIZE * blocks;
}
if (bytes_left) // handle misaligned offset (at end)

View File

@ -46,15 +46,15 @@ extern "C" {
#define AES_CNT_ECB_DECRYPT_MODE (AES_ECB_DECRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
#define AES_CNT_ECB_ENCRYPT_MODE (AES_ECB_ENCRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
void setup_aeskeyX(uint8_t keyslot, void* keyx);
void setup_aeskeyY(uint8_t keyslot, void* keyy);
void setup_aeskey(uint8_t keyslot, void* keyy);
void setup_aeskeyX(uint8_t keyslot, const void* keyx);
void setup_aeskeyY(uint8_t keyslot, const void* keyy);
void setup_aeskey(uint8_t keyslot, const void* keyy);
void use_aeskey(uint32_t keyno);
void set_ctr(void* iv);
void add_ctr(void* ctr, uint32_t carry);
void aes_decrypt(void* inbuf, void* outbuf, size_t size, uint32_t mode);
void ctr_decrypt(void* inbuf, void* outbuf, size_t size, uint32_t mode, uint8_t *ctr);
void ctr_decrypt_boffset(void *inbuf, void *outbuf, size_t size, size_t off, uint32_t mode, uint8_t *ctr);
void ctr_decrypt_byte(void *inbuf, void *outbuf, size_t size, size_t off, uint32_t mode, uint8_t *ctr);
void aes_cmac(void* inbuf, void* outbuf, size_t size);
void aes_fifos(void* inbuf, void* outbuf, size_t blocks);
void set_aeswrfifo(uint32_t value);

View File

@ -217,7 +217,7 @@ u32 DecryptNcchSection(u8* data, u32 offset_data, u32 size_data,
u8 ctr[16];
GetNcchCtr(ctr, ncch, snum);
if (SetNcchKey(ncch, keyid) != 0) return 1;
ctr_decrypt_boffset(data_i, data_i, size_i, offset_i + offset_ctr, mode, ctr);
ctr_decrypt_byte(data_i, data_i, size_i, offset_i + offset_ctr, mode, ctr);
return 0;
}

View File

@ -87,7 +87,7 @@ FRESULT fx_read (FIL* fp, void* buff, UINT btr, UINT* br) {
if (info && info->fptr) {
setup_aeskeyY(0x34, info->keyy);
use_aeskey(0x34);
ctr_decrypt_boffset(buff, buff, btr, off, AES_CNT_CTRNAND_MODE, info->ctr);
ctr_decrypt_byte(buff, buff, btr, off, AES_CNT_CTRNAND_MODE, info->ctr);
}
return res;
}
@ -104,7 +104,7 @@ FRESULT fx_write (FIL* fp, const void* buff, UINT btw, UINT* bw) {
UINT pcount = min(SDCRYPT_BUFFER_SIZE, (btw - p));
UINT bwl = 0;
memcpy(SDCRYPT_BUFFER, (u8*) buff + p, pcount);
ctr_decrypt_boffset(SDCRYPT_BUFFER, SDCRYPT_BUFFER, pcount, off + p, AES_CNT_CTRNAND_MODE, info->ctr);
ctr_decrypt_byte(SDCRYPT_BUFFER, SDCRYPT_BUFFER, pcount, off + p, AES_CNT_CTRNAND_MODE, info->ctr);
res = f_write(fp, (const void*) SDCRYPT_BUFFER, pcount, &bwl);
*bw += bwl;
}