From c7c2c3f73e62dfb0430d12480a4e59134da36caf Mon Sep 17 00:00:00 2001 From: applestash Date: Tue, 16 Sep 2014 19:15:55 +1000 Subject: [PATCH] makerom: fixes Moved away from ctrtool's polarssl api completely. Brought certs.c/h inline with code style, fixed bugs relating to tmd savedata field generation and not recording savedata size from rsf (ncsd.c) --- makerom/certs.c | 142 ++++++++++--------------- makerom/certs.h | 29 +++--- makerom/cia.c | 26 ++--- makerom/crypto.c | 248 ++++++++++++++++++++------------------------ makerom/crypto.h | 57 ++++------ makerom/exefs.c | 2 +- makerom/exheader.c | 12 +-- makerom/ncch.c | 18 ++-- makerom/ncsd.c | 11 +- makerom/romfs_gen.c | 2 +- makerom/tik.c | 12 +-- makerom/tmd.c | 7 +- 12 files changed, 243 insertions(+), 323 deletions(-) diff --git a/makerom/certs.c b/makerom/certs.c index f02b3b5..199461b 100644 --- a/makerom/certs.c +++ b/makerom/certs.c @@ -2,57 +2,64 @@ #include "certs.h" // Cert Sizes - -u32 GetCertSize(u8 *cert) +void GetCertSigSectionSizes(u32 *sign_size, u32 *sign_padlen, u8 *cert) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; - - Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding); - - u32 PubKSectionSize = GetCertPubkSectionSize((pubk_types)u8_to_u32(certcore->KeyType,BE)); - - return (4+SigSize+SigPadding+sizeof(Cert_Struct)+PubKSectionSize); -} - -void GetCertSigSectionSizes(u32 *SigSize, u32 *SigPadding, u8 *cert) -{ - sig_types sig = (sig_types)u8_to_u32(cert,BE); + u32 sig = u8_to_u32(cert,BE); switch(sig){ case RSA_4096_SHA1 : - *SigSize = 0x200; - *SigPadding = 0x3C; + *sign_size = 0x200; + *sign_padlen = 0x3C; break; case RSA_2048_SHA1 : - *SigSize = 0x100; - *SigPadding = 0x3C; + *sign_size = 0x100; + *sign_padlen = 0x3C; break; case ECC_SHA1 : - *SigSize = 0x3C; - *SigPadding = 0x40; + *sign_size = 0x3C; + *sign_padlen = 0x40; break; case RSA_4096_SHA256 : - *SigSize = 0x200; - *SigPadding = 0x3C; + *sign_size = 0x200; + *sign_padlen = 0x3C; break; case RSA_2048_SHA256 : - *SigSize = 0x100; - *SigPadding = 0x3C; + *sign_size = 0x100; + *sign_padlen = 0x3C; break; case ECC_SHA256 : - *SigSize = 0x3C; - *SigPadding = 0x40; + *sign_size = 0x3C; + *sign_padlen = 0x40; break; default : - *SigSize = 0; - *SigPadding = 0; + *sign_size = 0; + *sign_padlen = 0; break; } return; } +u32 GetCertSize(u8 *cert) +{ + u32 sign_size = 0; + u32 sign_padlen = 0; + GetCertSigSectionSizes(&sign_size,&sign_padlen,cert); + if(!sign_size || !sign_padlen) + return 0; + + return sizeof(u32) + sign_size + sign_padlen + sizeof(cert_hdr) + GetCertPubkSectionSize(GetCertPubkType(cert)); +} + + +cert_hdr* GetCertHdr(u8 *cert) +{ + u32 sign_size = 0; + u32 sign_padlen = 0; + GetCertSigSectionSizes(&sign_size,&sign_padlen,cert); + if(!sign_size || !sign_padlen) return NULL; + + return (cert_hdr*)(cert+4+sign_size+sign_padlen); +} + u32 GetCertPubkSectionSize(pubk_types type) { switch(type){ @@ -66,80 +73,41 @@ u32 GetCertPubkSectionSize(pubk_types type) // Issuer/Name Functions u8 *GetCertIssuer(u8 *cert) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; - - Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding); - return certcore->Issuer; + cert_hdr *hdr = GetCertHdr(cert); + return hdr->issuer; } u8 *GetCertName(u8 *cert) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; - - Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding); - return certcore->Name; + cert_hdr *hdr = GetCertHdr(cert); + return hdr->name; } -int GenCertChildIssuer(u8 *dest, u8 *cert) +void GenCertChildIssuer(u8 *dest, u8 *cert) { - u8 *issuer = GetCertIssuer(cert); - u8 *name = GetCertName(cert); - - /* - u32 out_size = strlen((char*)issuer) + strlen((char*)name) + 1; - if(out_size > 0x40) return MEM_ERROR; - */ - - snprintf((char*)dest,0x40,"%s-%s",issuer,name); - - /* - strcat((char*)dest,(char*)issuer); - strcat((char*)dest,"-"); - strcat((char*)dest,(char*)name); - */ - return 0; + snprintf((char*)dest,0x40,"%s-%s",GetCertIssuer(cert),GetCertName(cert)); } // Pubk pubk_types GetCertPubkType(u8 *cert) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; + cert_hdr *hdr = GetCertHdr(cert); - Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding); - - return (pubk_types)u8_to_u32(certcore->KeyType,BE); + return (pubk_types)u8_to_u32(hdr->keyType,BE); } u8 *GetCertPubk(u8 *cert) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; - return (cert+4+SigSize+SigPadding+sizeof(Cert_Struct)); + if(!GetCertHdr(cert)) + return NULL; + return ((u8*)GetCertHdr(cert)) + sizeof(cert_hdr); } bool VerifyCert(u8 *cert, u8 *pubk) { - u32 SigSize = 0; - u32 SigPadding = 0; - GetCertSigSectionSizes(&SigSize,&SigPadding,cert); - if(!SigSize || !SigPadding) return 0; + if(!GetCertHdr(cert)) + return false; + u8 *signature = (cert+sizeof(u32)); + u8 *data = (u8*)GetCertHdr(cert); + u32 datasize = sizeof(cert_hdr) + GetCertPubkSectionSize(GetCertPubkType(cert)); - - u8 *signature = (cert+4); - u8 *data = (cert+4+SigSize+SigPadding); - u32 datasize = sizeof(Cert_Struct) + GetCertPubkSectionSize(GetCertPubkType(cert)); - - int result = ctr_sig(data,datasize,signature,pubk,NULL,u8_to_u32(cert,BE),CTR_RSA_VERIFY); - - if(result == 0) return true; - else return false; + return RsaSignVerify(data,datasize,signature,pubk,NULL,u8_to_u32(cert,BE),CTR_RSA_VERIFY); } \ No newline at end of file diff --git a/makerom/certs.h b/makerom/certs.h index 0ab05d1..b88b332 100644 --- a/makerom/certs.h +++ b/makerom/certs.h @@ -2,41 +2,40 @@ typedef struct { - u8 Issuer[0x40]; - u8 KeyType[4]; - u8 Name[0x40]; - u8 Unknown[4]; -} Cert_Struct; + u8 issuer[0x40]; + u8 keyType[4]; + u8 name[0x40]; + u8 id[4]; +} cert_hdr; typedef struct { - u8 Modulus[0x200]; - u8 PubExponent[4]; - u8 Padding[0x34]; + u8 modulus[0x200]; + u8 pubExponent[4]; + u8 padding[0x34]; } rsa_4096_pubk_struct; typedef struct { - u8 Modulus[0x100]; - u8 PubExponent[4]; - u8 Padding[0x34]; + u8 modulus[0x100]; + u8 pubExponent[4]; + u8 padding[0x34]; } rsa_2048_pubk_struct; typedef struct { - u8 PubK[0x3C]; - u8 Padding[0x3C]; + u8 pubK[0x3C]; + u8 padding[0x3C]; } ecc_pubk_struct; // Cert Sizes u32 GetCertSize(u8 *cert); -void GetCertSigSectionSizes(u32 *SigSize, u32 *SigPadding, u8 *cert); u32 GetCertPubkSectionSize(pubk_types type); // Issuer/Name Functions u8 *GetCertIssuer(u8 *cert); u8 *GetCertName(u8 *cert); -int GenCertChildIssuer(u8 *dest, u8 *cert); +void GenCertChildIssuer(u8 *dest, u8 *cert); // Pubk pubk_types GetCertPubkType(u8 *cert); diff --git a/makerom/cia.c b/makerom/cia.c index a1d182a..64925c1 100644 --- a/makerom/cia.c +++ b/makerom/cia.c @@ -17,7 +17,6 @@ const int CIA_ALIGN_SIZE = 0x40; const int CIA_CONTENT_ALIGN = 0x10; // Private Prototypes -void InitCiaSettings(cia_settings *set); void FreeCiaSettings(cia_settings *set); int GetCiaSettings(cia_settings *ciaset, user_settings *usrset); @@ -53,7 +52,6 @@ int build_CIA(user_settings *usrset) } // Get Settings - InitCiaSettings(ciaset); result = GetCiaSettings(ciaset,usrset); if(result) goto finish; @@ -96,11 +94,6 @@ finish: return result; } -void InitCiaSettings(cia_settings *set) -{ - memset(set,0,sizeof(cia_settings)); -} - void FreeCiaSettings(cia_settings *set) { if(set->content.filePtrs){ @@ -198,8 +191,7 @@ int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset) ciaset->tik.formatVersion = 1; - int result = GenCertChildIssuer(ciaset->tik.issuer,ciaset->keys->certs.xsCert); - if(result) return result; + GenCertChildIssuer(ciaset->tik.issuer,ciaset->keys->certs.xsCert); // Tmd Stuff if(usrset->cia.contentId[0] > MAX_U32) @@ -209,7 +201,7 @@ int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset) ciaset->tmd.formatVersion = 1; ciaset->tmd.accessRights = 0; - result = GenCertChildIssuer(ciaset->tmd.issuer,ciaset->keys->certs.cpCert); + GenCertChildIssuer(ciaset->tmd.issuer,ciaset->keys->certs.cpCert); return 0; } @@ -293,14 +285,16 @@ int GetTmdDataFromNcch(cia_settings *ciaset, u8 *ncch, ncch_info *ncch_ctx, u8 * if(IsPatch(GetTidCategory(ciaset->common.titleId))||ciaset->content.IsCfa) ciaset->tmd.savedataSize = 0; - else if(ciaset->content.keyNotFound && ciaset->rsf->SystemControlInfo.SaveDataSize){ // if it's a title which can have save data, but save data size could not be read from exhdr + else if(!ciaset->content.keyNotFound) + ciaset->tmd.savedataSize = (u32)(GetSaveDataSize_frm_exhdr(exhdr) & MAX_U32); + else if(ciaset->rsf->SystemControlInfo.SaveDataSize){ // if it's a title which can have save data, but save data size could not be read from exhdr u64 size = 0; GetSaveDataSizeFromString(&size,ciaset->rsf->SystemControlInfo.SaveDataSize,"CIA"); ciaset->tmd.savedataSize = (u32)(size & MAX_U32); } - else - ciaset->tmd.savedataSize = (u32)(GetSaveDataSize_frm_exhdr(exhdr) & MAX_U32); - + else + ciaset->tmd.savedataSize = 0; + if(ciaset->content.IsCfa||ciaset->content.keyNotFound){ if(ciaset->common.titleVersion[VER_MAJOR] == MAX_U16){ // '-major' wasn't set if(ciaset->content.IsCfa){ // Is a CFA and can be decrypted @@ -569,7 +563,7 @@ u16 SetupVersion(u16 major, u16 minor, u16 micro) void GetContentHashes(cia_settings *ciaset) { for(int i = 0; i < ciaset->content.count; i++) - ctr_sha(ciaset->ciaSections.content.buffer+ciaset->content.offset[i],ciaset->content.size[i],ciaset->content.hash[i],CTR_SHA_256); + ShaCalc(ciaset->ciaSections.content.buffer+ciaset->content.offset[i],ciaset->content.size[i],ciaset->content.hash[i],CTR_SHA_256); } void EncryptContent(cia_settings *ciaset) @@ -653,7 +647,7 @@ int CryptContent(u8 *input, u8 *output, u64 size, u8 *title_key, u16 index, u8 m iv[0] = (index >> 8) & 0xff; iv[1] = index & 0xff; //Crypting content - AesCbc(title_key,iv,input,output,size,mode); + AesCbcCrypt(title_key,iv,input,output,size,mode); return 0; } diff --git a/makerom/crypto.c b/makerom/crypto.c index 71dbdd3..9fd99ee 100644 --- a/makerom/crypto.c +++ b/makerom/crypto.c @@ -1,14 +1,24 @@ #include "lib.h" #include "crypto.h" +const u8 RSA_PUB_EXP[0x3] = {0x01,0x00,0x01}; +const int HASH_MAX_LEN = 0x20; + +int ctr_rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, + int mode, + int hash_id, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + bool VerifySha256(void *data, u64 size, u8 hash[32]) { u8 calchash[32]; - ctr_sha(data, size, calchash, CTR_SHA_256); + ShaCalc(data, size, calchash, CTR_SHA_256); return memcmp(hash,calchash,32) == 0; } -void ctr_sha(void *data, u64 size, u8 *hash, int mode) +void ShaCalc(void *data, u64 size, u8 *hash, int mode) { switch(mode){ case(CTR_SHA_1): sha1((u8*)data, size, hash); break; @@ -21,7 +31,7 @@ void SetAesCtrOffset(u8 *ctr, u64 offset) u64_to_u8(ctr+8,u8_to_u64(ctr+8,BE)|align(offset,16)/16,BE); } -void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset) +void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset) { u8 stream[16]; aes_context aes; @@ -37,7 +47,7 @@ void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset) return; } -void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode) +void AesCbcCrypt(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode) { aes_context aes; clrmem(&aes,sizeof(aes_context)); @@ -56,168 +66,138 @@ void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode) } } -void ctr_rsa_free(ctr_rsa_context* ctx) -{ - rsa_free(&ctx->rsa); -} - -int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode) +bool RsaKeyInit(rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type) { // Sanity Check - if(ctx == NULL || modulus == NULL ||(private_exp == NULL && mode == RSAKEY_PRIV) || (exponent == NULL && mode == RSAKEY_PUB)) - return Fail; - rsa_init(&ctx->rsa, RSA_PKCS_V15, 0); + if(!ctx) + return false; + + rsa_init(ctx, RSA_PKCS_V15, 0); + u16 n_size = 0; u16 d_size = 0; u16 e_size = 0; + switch(rsa_type){ case RSA_2048: - ctx->rsa.len = 0x100; + ctx->len = 0x100; n_size = 0x100; d_size = 0x100; e_size = 3; break; case RSA_4096: - ctx->rsa.len = 0x200; + ctx->len = 0x200; n_size = 0x200; d_size = 0x200; e_size = 3; break; - default: return Fail; - } - - switch(mode){ - case(RSAKEY_PUB): - if (mpi_read_binary(&ctx->rsa.N, modulus, n_size)) - goto clean; - if (mpi_read_binary(&ctx->rsa.E, exponent, e_size)) - goto clean; - break; - case(RSAKEY_PRIV): - if (mpi_read_binary(&ctx->rsa.N, modulus, n_size)) - goto clean; - if (mpi_read_binary(&ctx->rsa.D, private_exp, d_size)) - goto clean; - break; - default: return Fail; + default: return false; } + + if (modulus && mpi_read_binary(&ctx->N, modulus, n_size)) + goto clean; + if (exponent && mpi_read_binary(&ctx->E, exponent, e_size)) + goto clean; + if (private_exp && mpi_read_binary(&ctx->D, private_exp, d_size)) + goto clean; + - return Good; + return true; clean: - ctr_rsa_free(ctx); - return Fail; + rsa_free(ctx); + return false; } -int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode) +u8 GetRsaType(u32 sig_type) { - int result = 0; - int hashtype, hashlen, sigtype; - if(data == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN)) - return Fail; - - switch(type){ + switch(sig_type){ case RSA_4096_SHA1: - hashtype = CTR_SHA_1; - hashlen = 0x14; - sigtype = RSA_4096; case RSA_4096_SHA256: - hashtype = CTR_SHA_256; - hashlen = 0x20; - sigtype = RSA_4096; - break; + return RSA_4096; case RSA_2048_SHA1: - hashtype = CTR_SHA_1; - hashlen = 0x14; - sigtype = RSA_2048; case RSA_2048_SHA256: - hashtype = CTR_SHA_256; - hashlen = 0x20; - sigtype = RSA_2048; - break; - case ECC_SHA1: - hashtype = CTR_SHA_1; - hashlen = 0x14; - sigtype = ECC; - case ECC_SHA256: - hashtype = CTR_SHA_256; - hashlen = 0x20; - sigtype = ECC; - break; - default: return Fail; + return RSA_2048; } - - u8 hash[hashlen]; - memset(hash,0,hashlen); - ctr_sha(data,size,hash,hashtype); - //memdump(stdout,"Data: ",data,size); - //memdump(stdout,"HashFor Sig: ",hash,hashlen); - - if(sigtype == RSA_2048 || sigtype == RSA_4096) - result = ctr_rsa(hash,signature,modulus,private_exp,type,mode); - else if(sigtype == ECC){ - printf("[!] ECC is not yet implemented\n"); - result = Fail; - } - return result; + return INVALID_SIG_TYPE; } -int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode) +u32 GetSigHashType(u32 sig_type) { - int result = 0; - // Sanity Check - if(hash == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN)) - return Fail; - - // Getting details from sig type - int hashtype; - int hashlen; - int sigtype; - switch(type){ - case RSA_4096_SHA1: - hashtype = SIG_RSA_SHA1; - hashlen = 0x14; - sigtype = RSA_4096; - break; - case RSA_4096_SHA256: - hashtype = SIG_RSA_SHA256; - hashlen = 0x14; - sigtype = RSA_4096; - break; - case RSA_2048_SHA1: - hashtype = SIG_RSA_SHA1; - hashlen = 0x20; - sigtype = RSA_2048; - break; - case RSA_2048_SHA256: - hashtype = SIG_RSA_SHA256; - hashlen = 0x20; - sigtype = RSA_2048; - break; - default: return Fail; + switch(sig_type){ + case RSA_4096_SHA1: + case RSA_2048_SHA1: + case ECC_SHA1: + return CTR_SHA_1; + case RSA_4096_SHA256: + case RSA_2048_SHA256: + case ECC_SHA256: + return CTR_SHA_256; } - - // Setting up - ctr_rsa_context ctx; - u8 exponent[3] = {0x01,0x00,0x01}; - switch(mode){ - case CTR_RSA_VERIFY: - result = ctr_rsa_init(&ctx,modulus,NULL,(u8*)exponent,sigtype,RSAKEY_PUB); - break; - case CTR_RSA_SIGN: - result = ctr_rsa_init(&ctx,modulus,private_exp,NULL,sigtype,RSAKEY_PRIV); - break; - } - if(result)return result; - - switch(mode){ - case CTR_RSA_VERIFY: - return rsa_pkcs1_verify(&ctx.rsa,RSA_PUBLIC,hashtype,hashlen,hash,signature); - case CTR_RSA_SIGN: - return ctr_rsa_rsassa_pkcs1_v15_sign(&ctx.rsa,RSA_PRIVATE,hashtype,hashlen,hash,signature); - } - return Fail; -} + return 0; +} +int GetRsaHashType(u32 sig_type) +{ + switch(sig_type){ + case RSA_4096_SHA1: + case RSA_2048_SHA1: + return SIG_RSA_SHA1; + case RSA_4096_SHA256: + case RSA_2048_SHA256: + return SIG_RSA_SHA256; + } + return 0; +} + +u32 GetSigHashLen(u32 sig_type) +{ + switch(sig_type){ + case RSA_4096_SHA1: + return 0x14; + case RSA_4096_SHA256: + return 0x20; + case RSA_2048_SHA1: + return 0x14; + case RSA_2048_SHA256: + return 0x20; + case ECC_SHA1: + return 0x14; + case ECC_SHA256: + return 0x20; + } + return 0; +} + +bool CalcHashForSign(void *data, u64 len, u8 *hash, u32 sig_type) +{ + if(GetSigHashType(sig_type) == 0) + return false; + + ShaCalc(data, len, hash, GetSigHashType(sig_type)); + + return true; +} + +int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode) +{ + int rsa_result = 0; + rsa_context ctx; + u8 hash[HASH_MAX_LEN]; + + if(!RsaKeyInit(&ctx, mod, priv_exp, (u8*)RSA_PUB_EXP, GetRsaType(sig_type))) + return -1; + + if(!CalcHashForSign(data, len, hash, sig_type)) + return -1; + + if(rsa_mode == CTR_RSA_VERIFY) + rsa_result = rsa_pkcs1_verify(&ctx, RSA_PUBLIC, GetRsaHashType(sig_type), 0, hash, sign); + else // CTR_RSA_SIGN + rsa_result = ctr_rsa_rsassa_pkcs1_v15_sign(&ctx, RSA_PRIVATE, GetRsaHashType(sig_type), 0, hash, sign); + + rsa_free(&ctx); + return rsa_result; +} /** * Hacked from rsa.c, polarssl doesn't like generating signatures when only D and N are present diff --git a/makerom/crypto.h b/makerom/crypto.h index 9a29a10..617fdc8 100644 --- a/makerom/crypto.h +++ b/makerom/crypto.h @@ -14,25 +14,26 @@ typedef enum RSA_4096_SHA256 = 0x00010003, RSA_2048_SHA256 = 0x00010004, ECC_SHA256 = 0x00010005 -} sig_types; - -typedef enum -{ - RSA_2048 = 0, - RSA_4096 = 1, - ECC = 2, } ctr_sig_types; typedef enum { - CTR_RSA_VERIFY = 0, - CTR_RSA_SIGN = 1, -} ctr_rsa_functions; + CTR_RSA_VERIFY, + CTR_RSA_SIGN, +} ctr_rsa_mode; typedef enum { - CTR_SHA_1 = 1, - CTR_SHA_256 = 256, + RSA_4096, + RSA_2048, + ECC, + INVALID_SIG_TYPE, +} sig_types; + +typedef enum +{ + CTR_SHA_1, + CTR_SHA_256, } ctr_sha_modes; typedef enum @@ -46,42 +47,22 @@ typedef enum { ENC, DEC -} aescbcmode; +} aes_mode; -typedef enum -{ - RSAKEY_INVALID, - RSAKEY_PRIV, - RSAKEY_PUB -} rsakeytype; - -typedef struct -{ - rsa_context rsa; -} ctr_rsa_context; #ifdef __cplusplus extern "C" { #endif // SHA bool VerifySha256(void *data, u64 size, u8 hash[32]); -void ctr_sha(void *data, u64 size, u8 *hash, int mode); +void ShaCalc(void *data, u64 size, u8 *hash, int mode); // AES -void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset); -void AesCbc(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode); +void AesCtrCrypt(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset); +void AesCbcCrypt(u8 *key, u8 *iv, u8 *input, u8 *output, u64 length, u8 mode); // RSA -void ctr_rsa_free(ctr_rsa_context* ctx); -int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode); -int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode); -int ctr_rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); +int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode); + -// Signature Functions -int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode); #ifdef __cplusplus } diff --git a/makerom/exefs.c b/makerom/exefs.c index 591d3f5..e11f568 100644 --- a/makerom/exefs.c +++ b/makerom/exefs.c @@ -75,7 +75,7 @@ int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff) memcpy(exefs->fileHdr[i].name,ctx->fileName[i],8); u32_to_u8(exefs->fileHdr[i].offset,ctx->fileOffset[i],LE); u32_to_u8(exefs->fileHdr[i].size,ctx->fileSize[i],LE); - ctr_sha(ctx->file[i],ctx->fileSize[i],exefs->fileHashes[MAX_EXEFS_SECTIONS-1-i],CTR_SHA_256); + ShaCalc(ctx->file[i],ctx->fileSize[i],exefs->fileHashes[MAX_EXEFS_SECTIONS-1-i],CTR_SHA_256); } return 0; } diff --git a/makerom/exheader.c b/makerom/exheader.c index d7dba89..730a03a 100644 --- a/makerom/exheader.c +++ b/makerom/exheader.c @@ -53,16 +53,16 @@ int get_ExHeaderARM9AccessControlInfo(exhdr_ARM9AccessControlInfo *arm9, rsf_set /* ExHeader Signature Functions */ int SignAccessDesc(access_descriptor *acexDesc, keys_struct *keys) { - u8 *AccessDesc = (u8*) &acexDesc->ncchRsaPubKey; - u8 *Signature = (u8*) &acexDesc->signature; - return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.acexPub,keys->rsa.acexPvt,RSA_2048_SHA256,CTR_RSA_SIGN); + u8 *data = (u8*) &acexDesc->ncchRsaPubKey; + u8 *sign = (u8*) &acexDesc->signature; + return RsaSignVerify(data,0x300,sign,keys->rsa.acexPub,keys->rsa.acexPvt,RSA_2048_SHA256,CTR_RSA_SIGN); } int CheckAccessDescSignature(access_descriptor *acexDesc, keys_struct *keys) { - u8 *AccessDesc = (u8*) &acexDesc->ncchRsaPubKey; - u8 *Signature = (u8*) &acexDesc->signature; - return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.acexPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); + u8 *data = (u8*) &acexDesc->ncchRsaPubKey; + u8 *sign = (u8*) &acexDesc->signature; + return RsaSignVerify(data,0x300,sign,keys->rsa.acexPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); } /* ExHeader Build Functions */ diff --git a/makerom/ncch.c b/makerom/ncch.c index 5688842..e79e041 100644 --- a/makerom/ncch.c +++ b/makerom/ncch.c @@ -34,22 +34,22 @@ bool IsValidProductCode(char *ProductCode, bool FreeProductCode); // Code int SignCFA(ncch_hdr *hdr, keys_struct *keys) { - return ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,keys->rsa.cciCfaPvt,RSA_2048_SHA256,CTR_RSA_SIGN); + return RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,keys->rsa.cciCfaPvt,RSA_2048_SHA256,CTR_RSA_SIGN); } int CheckCFASignature(ncch_hdr *hdr, keys_struct *keys) { - return ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); + return RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cciCfaPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); } int SignCXI(ncch_hdr *hdr, keys_struct *keys) { - return ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cxiHdrPub,keys->rsa.cxiHdrPvt,RSA_2048_SHA256,CTR_RSA_SIGN); + return RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),keys->rsa.cxiHdrPub,keys->rsa.cxiHdrPvt,RSA_2048_SHA256,CTR_RSA_SIGN); } int CheckCXISignature(ncch_hdr *hdr, u8 *pubk) { - int result = ctr_sig(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),pubk,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); + int result = RsaSignVerify(GetNcchHdrData(hdr),GetNcchHdrDataLen(hdr),GetNcchHdrSig(hdr),pubk,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY); return result; } @@ -500,13 +500,13 @@ int FinaliseNcch(ncch_settings *set) // Taking Hashes if(set->cryptoDetails.exhdrSize) - ctr_sha(exhdr,set->cryptoDetails.exhdrSize,hdr->exhdrHash,CTR_SHA_256); + ShaCalc(exhdr,set->cryptoDetails.exhdrSize,hdr->exhdrHash,CTR_SHA_256); if(set->cryptoDetails.logoSize) - ctr_sha(logo,set->cryptoDetails.logoSize,hdr->logoHash,CTR_SHA_256); + ShaCalc(logo,set->cryptoDetails.logoSize,hdr->logoHash,CTR_SHA_256); if(set->cryptoDetails.exefsHashDataSize) - ctr_sha(exefs,set->cryptoDetails.exefsHashDataSize,hdr->exefsHash,CTR_SHA_256); + ShaCalc(exefs,set->cryptoDetails.exefsHashDataSize,hdr->exefsHash,CTR_SHA_256); if(set->cryptoDetails.romfsHashDataSize) - ctr_sha(romfs,set->cryptoDetails.romfsHashDataSize,hdr->romfsHash,CTR_SHA_256); + ShaCalc(romfs,set->cryptoDetails.romfsHashDataSize,hdr->romfsHash,CTR_SHA_256); // Signing NCCH int sig_result = Good; @@ -1048,6 +1048,6 @@ void CryptNcchRegion(u8 *buffer, u64 size, u64 src_pos, u64 titleId, u8 key[16], { u8 ctr[0x10]; GetNcchAesCounter(ctr,titleId,type); - AesCtr(key,ctr,buffer,buffer,size,src_pos); + AesCtrCrypt(key,ctr,buffer,buffer,size,src_pos); return; } \ No newline at end of file diff --git a/makerom/ncsd.c b/makerom/ncsd.c index cc8cfaf..39d7036 100644 --- a/makerom/ncsd.c +++ b/makerom/ncsd.c @@ -10,7 +10,6 @@ #include "cardinfo.h" #include "titleid.h" - const int NCCH0_OFFSET = 0x4000; const int CCI_BLOCK_SIZE = 0x200; @@ -288,15 +287,15 @@ int ProcessCiaForCci(cci_settings *set) int ImportCciNcch(cci_settings *set) { + if(set->rsf->SystemControlInfo.SaveDataSize) + GetSaveDataSizeFromString(&set->romInfo.saveSize,set->rsf->SystemControlInfo.SaveDataSize,"CCI"); + if(set->content.dataType == infile_ncch) return ImportNcchForCci(set); else if(set->content.dataType == infile_cia) return ProcessCiaForCci(set); else - fprintf(stderr,"[CCI ERROR] Unrecognised input data type\n"); - - if(set->rsf->SystemControlInfo.SaveDataSize) - GetSaveDataSizeFromString(&set->romInfo.saveSize,set->rsf->SystemControlInfo.SaveDataSize,"CCI"); + fprintf(stderr,"[CCI ERROR] Unrecognised input data type\n"); return FAILED_TO_IMPORT_FILE; } @@ -594,7 +593,7 @@ int GenCciHdr(cci_settings *set) SetCciNcchInfo(hdr,set); // Sign Header - ctr_sig(&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); + 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; } diff --git a/makerom/romfs_gen.c b/makerom/romfs_gen.c index 4971895..6a9498f 100644 --- a/makerom/romfs_gen.c +++ b/makerom/romfs_gen.c @@ -467,7 +467,7 @@ void GenIvfcHashTree(romfs_buildctx *ctx) for(u32 j = 0; j < numHashes; j++){ u8 *datapos = (u8*)(ctx->level[i+1].pos + ROMFS_BLOCK_SIZE * j); u8 *hashpos = (u8*)(ctx->level[i].pos + 0x20 * j); - ctr_sha(datapos, ROMFS_BLOCK_SIZE, hashpos, CTR_SHA_256); + ShaCalc(datapos, ROMFS_BLOCK_SIZE, hashpos, CTR_SHA_256); } } diff --git a/makerom/tik.c b/makerom/tik.c index 16cb963..9267baa 100644 --- a/makerom/tik.c +++ b/makerom/tik.c @@ -15,9 +15,8 @@ int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode int BuildTicket(cia_settings *set) { - int result = 0; - result = SetupTicketBuffer(set); - if(result) return result; + if(SetupTicketBuffer(set)) + return MEM_ERROR; // Setting Ticket Struct Ptrs buffer_struct *tik = &set->ciaSections.tik; @@ -31,8 +30,7 @@ int BuildTicket(cia_settings *set) SetContentIndexHeader(idxHdr,set); SetContentIndexData(idxData,set); - result = SignTicketHeader(tik,set->keys); - return 0; + return SignTicketHeader(tik,set->keys); } int SetupTicketBuffer(cia_settings *set) @@ -83,7 +81,7 @@ int SignTicketHeader(buffer_struct *tik, keys_struct *keys) clrmem(sig,sizeof(tik_signature)); u32_to_u8(sig->sigType,RSA_2048_SHA256,BE); - return ctr_sig(data,len,sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN); + return RsaSignVerify(data,len,sig->data,keys->rsa.xsPub,keys->rsa.xsPvt,RSA_2048_SHA256,CTR_RSA_SIGN); } int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode) @@ -94,7 +92,7 @@ int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode memcpy(iv,titleId,0x8); //Crypting TitleKey - AesCbc(keys->aes.commonKey[keys->aes.currentCommonKey],iv,input,output,0x10,mode); + AesCbcCrypt(keys->aes.commonKey[keys->aes.currentCommonKey],iv,input,output,0x10,mode); // Return return 0; diff --git a/makerom/tmd.c b/makerom/tmd.c index f3b7f11..9407ef6 100644 --- a/makerom/tmd.c +++ b/makerom/tmd.c @@ -62,7 +62,7 @@ int SetupTMDHeader(tmd_hdr *hdr, tmd_content_info_record *info_record, cia_setti u32_to_u8(hdr->accessRights,ciaset->tmd.accessRights,BE); u16_to_u8(hdr->titleVersion,ciaset->tmd.version,BE); u16_to_u8(hdr->contentCount,ciaset->content.count,BE); - ctr_sha(info_record,sizeof(tmd_content_info_record)*64,hdr->infoRecordHash,CTR_SHA_256); + ShaCalc(info_record,sizeof(tmd_content_info_record)*64,hdr->infoRecordHash,CTR_SHA_256); return 0; } @@ -70,7 +70,8 @@ int SignTMDHeader(tmd_hdr *hdr, tmd_signature *sig, keys_struct *keys) { clrmem(sig,sizeof(tmd_signature)); u32_to_u8(sig->sigType,RSA_2048_SHA256,BE); - return ctr_sig((u8*)hdr,sizeof(tmd_hdr),sig->data,keys->rsa.cpPub,keys->rsa.cpPvt,RSA_2048_SHA256,CTR_RSA_SIGN); + + return RsaSignVerify((u8*)hdr,sizeof(tmd_hdr),sig->data,keys->rsa.cpPub,keys->rsa.cpPvt,RSA_2048_SHA256,CTR_RSA_SIGN); } int SetupTMDInfoRecord(tmd_content_info_record *info_record, u8 *content_record, u16 ContentCount) @@ -78,7 +79,7 @@ int SetupTMDInfoRecord(tmd_content_info_record *info_record, u8 *content_record, clrmem(info_record,sizeof(tmd_content_info_record)*0x40); u16_to_u8(info_record->contentIndexOffset,0x0,BE); u16_to_u8(info_record->contentCommandCount,ContentCount,BE); - ctr_sha(content_record,sizeof(tmd_content_chunk)*ContentCount,info_record->contentChunkHash,CTR_SHA_256); + ShaCalc(content_record,sizeof(tmd_content_chunk)*ContentCount,info_record->contentChunkHash,CTR_SHA_256); return 0; }