[ctrtool] Improved efficiency of aes-ctr operations.

This commit is contained in:
jakcron
2016-06-14 20:35:05 +08:00
parent de5c4e1b2a
commit 01cd4cba7b
8 changed files with 96 additions and 44 deletions
+29 -17
View File
@@ -4,6 +4,7 @@
#include <time.h>
#include "ctr.h"
#include "utils.h"
void ctr_set_iv( ctr_aes_context* ctx,
@@ -15,23 +16,30 @@ void ctr_set_iv( ctr_aes_context* ctx,
void ctr_add_counter( ctr_aes_context* ctx,
u32 block_num )
{
u32 i, j;
for (i = 0; i < block_num; i++) {
for (j = 0x10; j > 0; j--) {
// increment u8 by 1
ctx->ctr[j - 1]++;
u32 ctr[4];
ctr[3] = getbe32(&ctx->ctr[0]);
ctr[2] = getbe32(&ctx->ctr[4]);
ctr[1] = getbe32(&ctx->ctr[8]);
ctr[0] = getbe32(&ctx->ctr[12]);
// if it didn't overflow to 0, then we can exit now
if (ctx->ctr[j - 1])
break;
// if we reach here, the next u8 needs to be incremented
// Loop to beginning back if needed
if (j == 1)
j = 0x10;
for (u32 i = 0; i < 4; i++) {
u64 total = ctr[i] + block_num;
// if there wasn't a wrap around, add the two together and exit
if (total <= 0xffffffff) {
ctr[i] += block_num;
break;
}
// add the difference
ctr[i] = (u32)(total - 0x100000000);
// carry to next word
block_num = (u32)(total >> 32);
}
putbe32(ctx->ctr + 0x00, ctr[3]);
putbe32(ctx->ctr + 0x04, ctr[2]);
putbe32(ctx->ctr + 0x08, ctr[1]);
putbe32(ctx->ctr + 0x0C, ctr[0]);
}
void ctr_set_counter( ctr_aes_context* ctx,
@@ -41,11 +49,15 @@ void ctr_set_counter( ctr_aes_context* ctx,
}
void ctr_init_counter( ctr_aes_context* ctx,
u8 key[16],
u8 ctr[16] )
void ctr_init_key(ctr_aes_context* ctx,
u8 key[16])
{
aes_setkey_enc(&ctx->aes, key, 128);
}
void ctr_init_counter( ctr_aes_context* ctx,
u8 ctr[16] )
{
ctr_set_counter(ctx, ctr);
}
+4 -2
View File
@@ -61,10 +61,12 @@ void ctr_add_counter( ctr_aes_context* ctx,
void ctr_set_counter( ctr_aes_context* ctx,
u8 ctr[16] );
void ctr_init_key(ctr_aes_context* ctx,
u8 key[16]);
void ctr_init_counter( ctr_aes_context* ctx,
u8 key[16],
u8 ctr[16] );
u8 ctr[16] );
void ctr_crypt_counter_block( ctr_aes_context* ctx,
+9 -5
View File
@@ -124,7 +124,8 @@ void exefs_save(exefs_context* ctx, u32 index, u32 flags)
}
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_init_key(&ctx->aes, ctx->key);
ctr_init_counter(&ctx->aes, ctx->counter);
ctr_add_counter(&ctx->aes, offset / 0x10);
if (index == 0 && (ctx->compressedflag || (flags & DecompressCodeFlag)) && ((flags & RawFlag) == 0))
@@ -210,10 +211,12 @@ void exefs_read_header(exefs_context* ctx, u32 flags)
fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exefs_header), ctx->file);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
if (ctx->encrypted)
if (ctx->encrypted) {
ctr_init_key(&ctx->aes, ctx->key);
ctr_init_counter(&ctx->aes, ctx->counter);
ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exefs_header));
}
}
void exefs_calculate_hash(exefs_context* ctx, u8 hash[32])
@@ -269,7 +272,8 @@ int exefs_verify(exefs_context* ctx, u32 index, u32 flags)
return 0;
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_init_key(&ctx->aes, ctx->key);
ctr_init_counter(&ctx->aes, ctx->counter);
ctr_add_counter(&ctx->aes, offset / 0x10);
ctr_sha_256_init(&ctx->sha);
+2 -1
View File
@@ -93,7 +93,8 @@ void exheader_read(exheader_context* ctx, u32 actions)
fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exheader_header), ctx->file);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_init_key(&ctx->aes, ctx->key);
ctr_init_counter(&ctx->aes, ctx->counter);
if (ctx->encrypted)
ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exheader_header));
+44 -15
View File
@@ -38,7 +38,7 @@ void ivfc_set_encrypted(ivfc_context* ctx, u32 encrypted)
void ivfc_set_key(ivfc_context* ctx, u8 key[16])
{
memcpy(ctx->key, key, 16);
ctr_init_key(&ctx->aes, key);
}
void ivfc_set_counter(ivfc_context* ctx, u8 counter[16])
@@ -50,8 +50,14 @@ void ivfc_fseek(ivfc_context* ctx, u64 offset)
{
u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_add_counter(&ctx->aes, (u32) (data_pos / 0x10));
if (ctx->encrypted) {
//printf("start fseek encrypted prep\n");
ctr_init_counter(&ctx->aes, ctx->counter);
//printf("middle fseek encrypted prep\n");
ctr_add_counter(&ctx->aes, (u32)(data_pos / 0x10));
//printf("finish fseek encrypted prep\n");
}
}
size_t ivfc_fread(ivfc_context* ctx, void* buffer, size_t size, size_t count)
@@ -124,31 +130,54 @@ void ivfc_verify(ivfc_context* ctx, u32 flags)
level->hashcheck = Fail;
}
for(i=0; i<ctx->levelcount; i++)
{
ivfc_level* level = ctx->level + i;
// Import IVFC level hashes
uint8_t *levelhash[IVFC_MAX_LEVEL] = { NULL };
blockcount = (u32) (level->datasize / level->hashblocksize);
if (level->datasize % level->hashblocksize != 0)
for (i=0; i<ctx->levelcount; i++)
{
blockcount = (u32)(ctx->level[i].datasize / ctx->level[i].hashblocksize);
u32 read_size = align(blockcount * 0x20, ctx->level[i].hashblocksize);
levelhash[i] = malloc(read_size);
ivfc_read(ctx, ctx->level[i].hashoffset, read_size, levelhash[i]);
}
// Verify blocks
for (i=0; i<ctx->levelcount; i++)
{
blockcount = (u32) (ctx->level[i].datasize / ctx->level[i].hashblocksize);
if (ctx->level[i].datasize % ctx->level[i].hashblocksize != 0)
{
fprintf(stderr, "Error, IVFC block size mismatch\n");
return;
}
level->hashcheck = Good;
ctx->level[i].hashcheck = Good;
for(j=0; j<blockcount; j++)
for (j=0; j<blockcount; j++)
{
u8 calchash[32];
u8 testhash[32];
ivfc_hash(ctx, level->dataoffset + level->hashblocksize * j, level->hashblocksize, calchash);
ivfc_read(ctx, level->hashoffset + 0x20 * j, 0x20, testhash);
// a hash level
if (i < 2) {
ctr_sha_256(levelhash[i+1] + ctx->level[i].hashblocksize * j, ctx->level[i].hashblocksize, calchash);
}
// a data level
else {
ivfc_read(ctx, ctx->level[i].dataoffset + j * ctx->level[i].hashblocksize, ctx->level[i].hashblocksize, ctx->buffer);
ctr_sha_256(ctx->buffer, (u32)ctx->level[i].hashblocksize, calchash);
}
if (memcmp(calchash, testhash, 0x20) != 0)
level->hashcheck = Fail;
if (memcmp(calchash, levelhash[i] + 0x20 * j, 0x20) != 0) {
ctx->level[i].hashcheck = Fail;
}
}
}
// Free level hashes
for (int i = 0; i < 3; i++) {
free(levelhash[i]);
}
}
void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer)
-1
View File
@@ -45,7 +45,6 @@ typedef struct
u64 size;
settings* usersettings;
u8 counter[16];
u8 key[16];
ctr_aes_context aes;
int encrypted;
+2 -1
View File
@@ -135,7 +135,8 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
ctx->extractflags = flags;
fseeko64(ctx->file, offset, SEEK_SET);
ncch_get_counter(ctx, counter, type);
ctr_init_counter(&ctx->aes, ctx->key, counter);
ctr_init_key(&ctx->aes, ctx->key);
ctr_init_counter(&ctx->aes, counter);
return 1;
+6 -2
View File
@@ -38,6 +38,7 @@ void romfs_set_encrypted(romfs_context* ctx, u32 encrypted)
void romfs_set_key(romfs_context* ctx, u8 key[16])
{
memcpy(ctx->key, key, 16);
ctr_init_key(&ctx->aes, key);
}
void romfs_set_counter(romfs_context* ctx, u8 counter[16])
@@ -49,8 +50,11 @@ void romfs_fseek(romfs_context* ctx, u64 offset)
{
u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter);
ctr_add_counter(&ctx->aes, (u32) (data_pos / 0x10));
if (ctx->encrypted) {
ctr_init_counter(&ctx->aes, ctx->counter);
ctr_add_counter(&ctx->aes, (u32)(data_pos / 0x10));
}
}
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count)