static inline size_t lz4hc_commonlength(const u8 *p1, const u8 *p2, const u8 *const matchlimit) { const u8 *p1t = p1; while (p1t < matchlimit - (STEPSIZE - 1)) { #if LZ4_ARCH64 u64 diff = A64(p2) ^ A64(p1t); #else u32 diff = A32(p2) ^ A32(p1t); #endif if (!diff) { p1t += STEPSIZE; p2 += STEPSIZE; continue; } p1t += LZ4_NBCOMMONBYTES(diff); return p1t - p1; } #if LZ4_ARCH64 if ((p1t < (matchlimit-3)) && (A32(p2) == A32(p1t))) { p1t += 4; p2 += 4; } #endif if ((p1t < (matchlimit - 1)) && (A16(p2) == A16(p1t))) { p1t += 2; p2 += 2; } if ((p1t < matchlimit) && (*p2 == *p1t)) p1t++; return p1t - p1; }
static inline U64 XXH_readLE64_align(const U64* ptr, XXH_endianess endian, XXH_alignment align) { if (align==XXH_unaligned) return endian==XXH_littleEndian ? A64(ptr) : XXH_swap64(A64(ptr)); else return endian==XXH_littleEndian ? *ptr : XXH_swap64(*ptr); }
static inline int lz4hc_insertandgetwidermatch(struct lz4hc_data *hc4, const u8 *ip, const u8 *startlimit, const u8 *matchlimit, int longest, const u8 **matchpos, const u8 **startpos) { u16 *const chaintable = hc4->chaintable; HTYPE *const hashtable = hc4->hashtable; #if LZ4_ARCH64 const BYTE * const base = hc4->base; #else const int base = 0; #endif const u8 *ref; int nbattempts = MAX_NB_ATTEMPTS; int delta = (int)(ip - startlimit); /* First Match */ lz4hc_insert(hc4, ip); ref = hashtable[HASH_VALUE(ip)] + base; while ((ref >= ip - MAX_DISTANCE) && (ref >= hc4->base) && (nbattempts)) { nbattempts--; if (*(startlimit + longest) == *(ref - delta + longest)) { if (A32(ref) == A32(ip)) { const u8 *reft = ref + MINMATCH; const u8 *ipt = ip + MINMATCH; const u8 *startt = ip; while (ipt < matchlimit-(STEPSIZE - 1)) { #if LZ4_ARCH64 u64 diff = A64(reft) ^ A64(ipt); #else u32 diff = A32(reft) ^ A32(ipt); #endif if (!diff) { ipt += STEPSIZE; reft += STEPSIZE; continue; } ipt += LZ4_NBCOMMONBYTES(diff); goto _endcount; } #if LZ4_ARCH64 if ((ipt < (matchlimit - 3)) && (A32(reft) == A32(ipt))) { ipt += 4; reft += 4; } ipt += 2; #endif if ((ipt < (matchlimit - 1)) && (A16(reft) == A16(ipt))) { reft += 2; } if ((ipt < matchlimit) && (*reft == *ipt)) ipt++; _endcount: reft = ref; while ((startt > startlimit) && (reft > hc4->base) && (startt[-1] == reft[-1])) { startt--; reft--; } if ((ipt - startt) > longest) { longest = (int)(ipt - startt); *matchpos = reft; *startpos = startt; } } } ref -= (size_t)chaintable[(size_t)(ref) & MAXD_MASK]; } return longest; }
int main() { u8 *buf = NULL, *newContentBuf = NULL; FILE *f = fopen("title.cia","rb"); if(!f) { puts("Unable to open title.cia!"); goto end; } fseek(f,0,SEEK_END); size_t fsize = ftell(f); fseek(f,0,SEEK_SET); buf = malloc(fsize); if(!buf) { printf("Unable to allocate %i bytes!\n",fsize); goto end; } fread(buf,1,fsize,f); fclose(f); f = NULL; u32 certsize = A64(*(u32*)(buf+0x8)), tiksize=A64(*(u32*)(buf+0xC)), tmdsize=A64(*(u32*)(buf+0x10)), metasize=A64(*(u32*)(buf+0x14)), contentsize=A64(*(u32*)(buf+0x18)); printf("Cert Size:%x, Tik Size: %x, TMD Size: %x\nMeta Size: %x, Total Content Size:%x\n", certsize,tiksize,tmdsize,metasize,contentsize); u32 tmdstart = 0x2040+certsize+tiksize; printf("TMD Start: %x\n",tmdstart); u32 sigtype = S32(*(u32*)(buf+tmdstart)); u32 tmdsigsize = 0x100; if(sigtype != RSA_2048_SHA256) { printf("Signature Type not supported:0x%08x\n",sigtype); goto end; } u32 tmdhdr = A64(tmdstart+4+tmdsigsize); u32 tmdverpos = tmdhdr+0x40; int tmdver = *(buf+tmdverpos); if(tmdver != 1) { printf("Unknown tmd ver:%i\n",tmdver); goto end; } printf("Title ID: %016I64x\n",S64(*(u64*)(buf+tmdhdr+0x4C))); u32 numcontentpos = tmdhdr+0x9E; u16 numcontents = S16(*(u16*)(buf+numcontentpos)); printf("Num Contents: %i\n",numcontents); u32 infoshapos = numcontentpos+6; //has sha1 of 0x900 inforecords u32 inforecords = infoshapos+0x20; //has sha1 of each chunkrecord f = fopen("content.bin","rb"); fseek(f,0,SEEK_END); size_t newContentSize = ftell(f); fseek(f,0,SEEK_SET); newContentBuf = malloc(newContentSize); fread(newContentBuf,newContentSize,1,f); fclose(f); memcpy(buf+0x18,&newContentSize,4); printf("New Content Size: %x\n",A64(*(u32*)(buf+0x18))); u32 chunkrecords = inforecords+(0x40*0x24); //has sha1 of each content u32 chunkrecordsSize = chunkrecords+(numcontents*0x30); u32 content = A64(chunkrecordsSize); printf("Content starts at 0x%x\n",content); int i; for(i = 0; i < numcontents; i++) { *(u64*)(buf+(chunkrecords+(i*0x30))+0x8) = S64(newContentSize); u64 thisContentSize = S64(*(u64*)(buf+(chunkrecords+(i*0x30))+0x8)); printf("Content %i Size: %I64x\n", S16(*(u16*)(buf+(chunkrecords+(i*0x30))+0x4)), thisContentSize); sha2(newContentBuf,(u32)thisContentSize,buf+(chunkrecords+(i*0x30))+0x10,0); } sha2(buf+chunkrecords,0x30,buf+inforecords+4,0); sha2(buf+inforecords,(0x40*0x24),buf+infoshapos,0); printf("Signing TMD, RsaSignVerify=%i\n", RsaSignVerify(buf+tmdstart+0x140,0xC4,buf+tmdstart+4,mod,priv_exp,RSA_2048_SHA256,CTR_RSA_SIGN)); f = fopen("titleNew.cia","wb"); fwrite(buf,content,1,f); fwrite(newContentBuf,newContentSize,1,f); if(metasize > 0) { u32 metastart = 0x2040+certsize+tiksize+tmdsize+contentsize; fwrite(buf+metastart,metasize,1,f); } fclose(f); puts("Wrote titleNew.cia"); end: if(buf) free(buf); if(f) fclose(f); return 0; }