void exefs_read_header(exefs_context* ctx, u32 flags) { fseek(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) ctr_crypt_counter(&ctx->aes, (u8*)&ctx->header, (u8*)&ctx->header, sizeof(exefs_header)); }
size_t romfs_fread(romfs_context* ctx, void* buffer, size_t size, size_t count) { size_t read; if ((read = fread(buffer, size, count, ctx->file)) != count) { //printf("romfs_fread() fail\n"); return read; } if (ctx->encrypted) { ctr_crypt_counter(&ctx->aes, buffer, buffer, size*read); } return read; }
int VerifyNCCHSection(USER_CONTEXT *ctx, u8 cxi_key[0x10], u32 offset, FILE *ncch) { NCCH_STRUCT *cxi_ctx = malloc(sizeof(NCCH_STRUCT)); if(cxi_ctx == NULL){ printf("[!] Memory Allocation Failure\n"); return Fail; } memset(cxi_ctx,0x0,sizeof(NCCH_STRUCT)); GetCXIStruct(cxi_ctx,offset,ncch); u8 HeaderSignature[0x100]; u8 Header[0x100]; u8 HeaderSHAHash[0x20]; u8 ExHeader[0x800]; memset(&HeaderSignature,0x0,0x100); memset(&Header,0x0,0x100); memset(&HeaderSHAHash,0x0,0x20); fseek(ncch,offset+0x0,SEEK_SET); fread(HeaderSignature,0x100,1,ncch); fread(Header,0x100,1,ncch); ctr_sha(&Header,0x100,HeaderSHAHash,CTR_SHA_256); RSA_2048_KEY HeaderRSA; memset(&HeaderRSA,0x0,sizeof(RSA_2048_KEY)); u8 Exponent[0x3] = {0x01,0x00,0x01}; memcpy(HeaderRSA.e,Exponent,0x3); if(cxi_ctx->is_cfa == True) memcpy(HeaderRSA.n,ctx->keys.NcsdCfa.n,0x100); else{ memset(&ExHeader,0x0,0x800); fseek(ncch,offset+cxi_ctx->exheader_offset,SEEK_SET); fread(&ExHeader,0x800,1,ncch); if(cxi_ctx->encrypted == True){ u8 counter[0x10]; ncch_get_counter(cxi_ctx,counter,NCCHTYPE_EXHEADER); ctr_aes_context aes_ctx; memset(&aes_ctx,0x0,sizeof(ctr_aes_context)); ctr_init_counter(&aes_ctx, cxi_key, counter); ctr_crypt_counter(&aes_ctx, ExHeader, ExHeader, 0x800); if(memcmp((ExHeader+0x200),cxi_ctx->programID,8) != 0){ printf("[!] CXI decryption failed\n"); return Fail; } } memcpy(HeaderRSA.n,ExHeader+0x500,0x100); } return ctr_rsa(HeaderSHAHash,HeaderSignature,HeaderRSA.n,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); }
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; }