int GenCciHdr(cci_settings *set) { set->headers.ccihdr.size = sizeof(cci_hdr); set->headers.ccihdr.buffer = calloc(1,set->headers.ccihdr.size); if(!set->headers.ccihdr.buffer){ set->headers.ccihdr.size = 0; fprintf(stderr,"[CCI ERROR] Not enough memory\n"); return MEM_ERROR; } cci_hdr *hdr = (cci_hdr*)set->headers.ccihdr.buffer; // Magic & TitleId memcpy(hdr->magic,"NCSD",4); u64_to_u8(hdr->titleId,set->content.titleId[0],LE); if(SetMediaSize(hdr->mediaSize,set)) return GEN_HDR_FAIL; if(SetCciFlags(hdr->flags,set)) return GEN_HDR_FAIL; SetCciNcchInfo(hdr,set); // Sign Header RsaSignVerify(&hdr->magic,sizeof(cci_hdr)-RSA_2048_KEY_SIZE,hdr->signature,set->keys->rsa.cciCfaPub,set->keys->rsa.cciCfaPvt,RSA_2048_SHA256,CTR_RSA_SIGN); return 0; }
bool VerifyCert(u8 *cert, u8 *pubk) { if(!GetCertHdr(cert)) return false; u8 *signature = (cert+sizeof(u32)); u8 *data = (u8*)GetCertHdr(cert); u32 datasize = sizeof(cert_hdr) + GetCertPubkSectionSize(GetCertPubkType(cert)); return RsaSignVerify(data,datasize,signature,pubk,NULL,u8_to_u32(cert,BE),CTR_RSA_VERIFY); }
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; }
int CheckCXISignature(ncch_hdr *hdr, u8 *pubk) { int result = RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),pubk,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); return result; }
int SignCXI(ncch_hdr *hdr, keys_struct *keys) { return RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cxiHdrPub,keys->rsa.cxiHdrPvt,RSA_2048_SHA256,CTR_RSA_SIGN); }
int CheckCFASignature(ncch_hdr *hdr, keys_struct *keys) { return RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); }