[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 <time.h>
#include "ctr.h" #include "ctr.h"
#include "utils.h"
void ctr_set_iv( ctr_aes_context* ctx, 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, void ctr_add_counter( ctr_aes_context* ctx,
u32 block_num ) u32 block_num )
{ {
u32 i, j; u32 ctr[4];
for (i = 0; i < block_num; i++) { ctr[3] = getbe32(&ctx->ctr[0]);
for (j = 0x10; j > 0; j--) { ctr[2] = getbe32(&ctx->ctr[4]);
// increment u8 by 1 ctr[1] = getbe32(&ctx->ctr[8]);
ctx->ctr[j - 1]++; ctr[0] = getbe32(&ctx->ctr[12]);
// if it didn't overflow to 0, then we can exit now for (u32 i = 0; i < 4; i++) {
if (ctx->ctr[j - 1]) u64 total = ctr[i] + block_num;
break; // if there wasn't a wrap around, add the two together and exit
if (total <= 0xffffffff) {
// if we reach here, the next u8 needs to be incremented ctr[i] += block_num;
break;
// Loop to beginning back if needed
if (j == 1)
j = 0x10;
} }
// 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, 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, void ctr_init_key(ctr_aes_context* ctx,
u8 key[16], u8 key[16])
u8 ctr[16] )
{ {
aes_setkey_enc(&ctx->aes, key, 128); aes_setkey_enc(&ctx->aes, key, 128);
}
void ctr_init_counter( ctr_aes_context* ctx,
u8 ctr[16] )
{
ctr_set_counter(ctx, ctr); 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, void ctr_set_counter( ctr_aes_context* ctx,
u8 ctr[16] ); u8 ctr[16] );
void ctr_init_key(ctr_aes_context* ctx,
u8 key[16]);
void ctr_init_counter( ctr_aes_context* ctx, 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, 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); 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_add_counter(&ctx->aes, offset / 0x10);
if (index == 0 && (ctx->compressedflag || (flags & DecompressCodeFlag)) && ((flags & RawFlag) == 0)) 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); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exefs_header), ctx->file); fread(&ctx->header, 1, sizeof(exefs_header), ctx->file);
ctr_init_counter(&ctx->aes, ctx->key, ctx->counter); if (ctx->encrypted) {
ctr_init_key(&ctx->aes, ctx->key);
if (ctx->encrypted) ctr_init_counter(&ctx->aes, ctx->counter);
ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exefs_header)); ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exefs_header));
}
} }
void exefs_calculate_hash(exefs_context* ctx, u8 hash[32]) 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; return 0;
fseeko64(ctx->file, ctx->offset + offset, SEEK_SET); 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_add_counter(&ctx->aes, offset / 0x10);
ctr_sha_256_init(&ctx->sha); 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); fseeko64(ctx->file, ctx->offset, SEEK_SET);
fread(&ctx->header, 1, sizeof(exheader_header), ctx->file); 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) if (ctx->encrypted)
ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exheader_header)); 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]) 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]) 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; u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET); 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) 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; level->hashcheck = Fail;
} }
for(i=0; i<ctx->levelcount; i++) // Import IVFC level hashes
{ uint8_t *levelhash[IVFC_MAX_LEVEL] = { NULL };
ivfc_level* level = ctx->level + i;
blockcount = (u32) (level->datasize / level->hashblocksize); for (i=0; i<ctx->levelcount; i++)
if (level->datasize % level->hashblocksize != 0) {
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"); fprintf(stderr, "Error, IVFC block size mismatch\n");
return; 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 calchash[32];
u8 testhash[32];
ivfc_hash(ctx, level->dataoffset + level->hashblocksize * j, level->hashblocksize, calchash); // a hash level
ivfc_read(ctx, level->hashoffset + 0x20 * j, 0x20, testhash); 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) if (memcmp(calchash, levelhash[i] + 0x20 * j, 0x20) != 0) {
level->hashcheck = Fail; 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) void ivfc_read(ivfc_context* ctx, u64 offset, u64 size, u8* buffer)
-1
View File
@@ -45,7 +45,6 @@ typedef struct
u64 size; u64 size;
settings* usersettings; settings* usersettings;
u8 counter[16]; u8 counter[16];
u8 key[16];
ctr_aes_context aes; ctr_aes_context aes;
int encrypted; int encrypted;
+2 -1
View File
@@ -135,7 +135,8 @@ int ncch_extract_prepare(ncch_context* ctx, u32 type, u32 flags)
ctx->extractflags = flags; ctx->extractflags = flags;
fseeko64(ctx->file, offset, SEEK_SET); fseeko64(ctx->file, offset, SEEK_SET);
ncch_get_counter(ctx, counter, type); 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; 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]) void romfs_set_key(romfs_context* ctx, u8 key[16])
{ {
memcpy(ctx->key, key, 16); memcpy(ctx->key, key, 16);
ctr_init_key(&ctx->aes, key);
} }
void romfs_set_counter(romfs_context* ctx, u8 counter[16]) 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; u64 data_pos = offset - ctx->offset;
fseeko64(ctx->file, offset, SEEK_SET); 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) size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count)