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)); }
void ctr_crypt_counter_block( ctr_crypto_context* ctx, unsigned char input[16], unsigned char output[16] ) { int i; unsigned char stream[16]; aes_crypt_ecb(&ctx->aes, AES_ENCRYPT, ctx->ctr, stream); if (input) { for(i=0; i<16; i++) { output[i] = stream[i] ^ input[i]; } } else { for(i=0; i<16; i++) output[i] = stream[i]; } ctr_add_counter(ctx, 1); }
int exefs_verify(exefs_context* ctx, u32 index, u32 flags) { exefs_sectionheader* section = (exefs_sectionheader*)(ctx->header.section + index); u32 offset; u32 size; u8 buffer[16 * 1024]; u8 hash[0x20]; offset = getle32(section->offset) + sizeof(exefs_header); size = getle32(section->size); if (size == 0) return 0; fseek(ctx->file, ctx->offset + offset, SEEK_SET); ctr_init_counter(&ctx->aes, ctx->key, ctx->counter); ctr_add_counter(&ctx->aes, offset / 0x10); ctr_sha_256_init(&ctx->sha); while(size) { u32 max = sizeof(buffer); if (max > size) max = size; if (max != fread(buffer, 1, max, ctx->file)) { fprintf(stdout, "Error reading input file\n"); goto clean; } if (ctx->encrypted) ctr_crypt_counter(&ctx->aes, buffer, buffer, max); ctr_sha_256_update(&ctx->sha, buffer, max); size -= max; } ctr_sha_256_finish(&ctx->sha, hash); if (memcmp(hash, ctx->header.hashes[7-index], 0x20) == 0) return 1; clean: return 0; }
static u32 rawromfs_Read(file_type* self, u32 ptr, u32 sz, u64 off, u32* read_out) { *read_out = 0; if((off >> 32) || (off >= romfs_sz) || ((off+sz) >= romfs_sz)) { ERROR("Invalid read params.\n"); return -1; } if(fseek64(in_fd, romfs_off + off, SEEK_SET) == -1) { ERROR("fseek failed.\n"); return -1; } u8* b = malloc(sz); if(b == NULL) { ERROR("Not enough mem.\n"); return -1; } u32 read = fread(b, 1, sz, in_fd); ctr_aes_context ctx; if (loader_encrypted) { u8* temp = calloc(sz + (off & 0xF) + (sz & 0xF), sizeof(u8)); memcpy(temp + (off & 0xF), b, sz); ncch_extract_prepare(&ctx, &loader_h, NCCHTYPE_ROMFS, loader_key); ctr_add_counter(&ctx, (u32)((0x1000 + off) / 0x10)); //this is from loader ctr_crypt_counter(&ctx, temp, temp, sz + (off & 0xF)); memcpy(b, temp + (off & 0xF), sz); free(temp); } if(mem_Write(b, ptr, read) != 0) { ERROR("mem_Write failed.\n"); free(b); return -1; } *read_out = read; free(b); return 0; // Result }
void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, ncch_info *ctx, u8 key[16], u8 type) { if(type < 1 || type > 3) return; u8 counter[0x10]; ctr_aes_context aes_ctx; memset(&aes_ctx,0x0,sizeof(ctr_aes_context)); GetNcchAesCounter(ctx,counter,type); ctr_init_counter(&aes_ctx, key, counter); if(src_pos > 0){ u32 carry = 0; carry = align(src_pos,0x10); carry /= 0x10; ctr_add_counter(&aes_ctx,carry); } ctr_crypt_counter(&aes_ctx, buffer, buffer, size); return; }
void exefs_save(exefs_context* ctx, u32 index, u32 flags) { exefs_sectionheader* section = (exefs_sectionheader*)(ctx->header.section + index); char outfname[MAX_PATH]; char name[64]; u32 offset; u32 size; FILE* fout; u32 compressedsize = 0; u32 decompressedsize = 0; u8* compressedbuffer = 0; u8* decompressedbuffer = 0; filepath* dirpath = 0; offset = getle32(section->offset) + sizeof(exefs_header); size = getle32(section->size); dirpath = settings_get_exefs_dir_path(ctx->usersettings); if (size == 0 || dirpath == 0 || dirpath->valid == 0) return; if (size >= ctx->size) { fprintf(stderr, "Error, ExeFS section %d size invalid\n", index); return; } memset(name, 0, sizeof(name)); memcpy(name, section->name, 8); memcpy(outfname, dirpath->pathname, MAX_PATH); strcat(outfname, "/"); if (name[0] == '.') strcat(outfname, name+1); else strcat(outfname, name); strcat(outfname, ".bin"); fout = fopen(outfname, "wb"); if (fout == 0) { fprintf(stderr, "Error, failed to create file %s\n", outfname); goto clean; } fseek(ctx->file, ctx->offset + offset, SEEK_SET); ctr_init_counter(&ctx->aes, ctx->key, ctx->counter); ctr_add_counter(&ctx->aes, offset / 0x10); if (index == 0 && (ctx->compressedflag || (flags & CompressCodeFlag)) && ((flags & RawFlag) == 0)) { fprintf(stdout, "Decompressing section %s to %s...\n", name, outfname); compressedsize = size; compressedbuffer = malloc(compressedsize); if (compressedbuffer == 0) { fprintf(stdout, "Error allocating memory\n"); goto clean; } if (compressedsize != fread(compressedbuffer, 1, compressedsize, ctx->file)) { fprintf(stdout, "Error reading input file\n"); goto clean; } if (ctx->encrypted) ctr_crypt_counter(&ctx->aes, compressedbuffer, compressedbuffer, compressedsize); decompressedsize = lzss_get_decompressed_size(compressedbuffer, compressedsize); decompressedbuffer = malloc(decompressedsize); if (decompressedbuffer == 0) { fprintf(stdout, "Error allocating memory\n"); goto clean; } if (0 == lzss_decompress(compressedbuffer, compressedsize, decompressedbuffer, decompressedsize)) goto clean; if (decompressedsize != fwrite(decompressedbuffer, 1, decompressedsize, fout)) { fprintf(stdout, "Error writing output file\n"); goto clean; } } else { u8 buffer[16 * 1024]; fprintf(stdout, "Saving section %s to %s...\n", name, outfname); while(size) { u32 max = sizeof(buffer); if (max > size) max = size; if (max != fread(buffer, 1, max, ctx->file)) { fprintf(stdout, "Error reading input file\n"); goto clean; } if (ctx->encrypted) ctr_crypt_counter(&ctx->aes, buffer, buffer, max); if (max != fwrite(buffer, 1, max, fout)) { fprintf(stdout, "Error writing output file\n"); goto clean; } size -= max; } } clean: free(compressedbuffer); free(decompressedbuffer); return; }