mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-03 00:39:14 +00:00
[ctrtool] Improved efficiency of aes-ctr operations.
This commit is contained in:
+29
-17
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -45,7 +45,6 @@ typedef struct
|
||||
u64 size;
|
||||
settings* usersettings;
|
||||
u8 counter[16];
|
||||
u8 key[16];
|
||||
ctr_aes_context aes;
|
||||
int encrypted;
|
||||
|
||||
|
||||
+2
-1
@@ -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
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user