mirror of
https://github.com/DarkStore-3DS/Project_CTR.git
synced 2026-07-04 08:49:03 +00:00
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)
This commit is contained in:
+55
-87
@@ -2,57 +2,64 @@
|
|||||||
#include "certs.h"
|
#include "certs.h"
|
||||||
|
|
||||||
// Cert Sizes
|
// Cert Sizes
|
||||||
|
void GetCertSigSectionSizes(u32 *sign_size, u32 *sign_padlen, u8 *cert)
|
||||||
u32 GetCertSize(u8 *cert)
|
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
u32 sig = u8_to_u32(cert,BE);
|
||||||
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);
|
|
||||||
switch(sig){
|
switch(sig){
|
||||||
case RSA_4096_SHA1 :
|
case RSA_4096_SHA1 :
|
||||||
*SigSize = 0x200;
|
*sign_size = 0x200;
|
||||||
*SigPadding = 0x3C;
|
*sign_padlen = 0x3C;
|
||||||
break;
|
break;
|
||||||
case RSA_2048_SHA1 :
|
case RSA_2048_SHA1 :
|
||||||
*SigSize = 0x100;
|
*sign_size = 0x100;
|
||||||
*SigPadding = 0x3C;
|
*sign_padlen = 0x3C;
|
||||||
break;
|
break;
|
||||||
case ECC_SHA1 :
|
case ECC_SHA1 :
|
||||||
*SigSize = 0x3C;
|
*sign_size = 0x3C;
|
||||||
*SigPadding = 0x40;
|
*sign_padlen = 0x40;
|
||||||
break;
|
break;
|
||||||
case RSA_4096_SHA256 :
|
case RSA_4096_SHA256 :
|
||||||
*SigSize = 0x200;
|
*sign_size = 0x200;
|
||||||
*SigPadding = 0x3C;
|
*sign_padlen = 0x3C;
|
||||||
break;
|
break;
|
||||||
case RSA_2048_SHA256 :
|
case RSA_2048_SHA256 :
|
||||||
*SigSize = 0x100;
|
*sign_size = 0x100;
|
||||||
*SigPadding = 0x3C;
|
*sign_padlen = 0x3C;
|
||||||
break;
|
break;
|
||||||
case ECC_SHA256 :
|
case ECC_SHA256 :
|
||||||
*SigSize = 0x3C;
|
*sign_size = 0x3C;
|
||||||
*SigPadding = 0x40;
|
*sign_padlen = 0x40;
|
||||||
break;
|
break;
|
||||||
default :
|
default :
|
||||||
*SigSize = 0;
|
*sign_size = 0;
|
||||||
*SigPadding = 0;
|
*sign_padlen = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return;
|
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)
|
u32 GetCertPubkSectionSize(pubk_types type)
|
||||||
{
|
{
|
||||||
switch(type){
|
switch(type){
|
||||||
@@ -66,80 +73,41 @@ u32 GetCertPubkSectionSize(pubk_types type)
|
|||||||
// Issuer/Name Functions
|
// Issuer/Name Functions
|
||||||
u8 *GetCertIssuer(u8 *cert)
|
u8 *GetCertIssuer(u8 *cert)
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
cert_hdr *hdr = GetCertHdr(cert);
|
||||||
u32 SigPadding = 0;
|
return hdr->issuer;
|
||||||
GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
|
|
||||||
if(!SigSize || !SigPadding) return 0;
|
|
||||||
|
|
||||||
Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
|
|
||||||
return certcore->Issuer;
|
|
||||||
}
|
}
|
||||||
u8 *GetCertName(u8 *cert)
|
u8 *GetCertName(u8 *cert)
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
cert_hdr *hdr = GetCertHdr(cert);
|
||||||
u32 SigPadding = 0;
|
return hdr->name;
|
||||||
GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
|
|
||||||
if(!SigSize || !SigPadding) return 0;
|
|
||||||
|
|
||||||
Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
|
|
||||||
return certcore->Name;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int GenCertChildIssuer(u8 *dest, u8 *cert)
|
void GenCertChildIssuer(u8 *dest, u8 *cert)
|
||||||
{
|
{
|
||||||
u8 *issuer = GetCertIssuer(cert);
|
snprintf((char*)dest,0x40,"%s-%s",GetCertIssuer(cert),GetCertName(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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pubk
|
// Pubk
|
||||||
pubk_types GetCertPubkType(u8 *cert)
|
pubk_types GetCertPubkType(u8 *cert)
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
cert_hdr *hdr = GetCertHdr(cert);
|
||||||
u32 SigPadding = 0;
|
|
||||||
GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
|
|
||||||
if(!SigSize || !SigPadding) return 0;
|
|
||||||
|
|
||||||
Cert_Struct *certcore = (Cert_Struct*)(cert+4+SigSize+SigPadding);
|
return (pubk_types)u8_to_u32(hdr->keyType,BE);
|
||||||
|
|
||||||
return (pubk_types)u8_to_u32(certcore->KeyType,BE);
|
|
||||||
}
|
}
|
||||||
u8 *GetCertPubk(u8 *cert)
|
u8 *GetCertPubk(u8 *cert)
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
if(!GetCertHdr(cert))
|
||||||
u32 SigPadding = 0;
|
return NULL;
|
||||||
GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
|
return ((u8*)GetCertHdr(cert)) + sizeof(cert_hdr);
|
||||||
if(!SigSize || !SigPadding) return 0;
|
|
||||||
return (cert+4+SigSize+SigPadding+sizeof(Cert_Struct));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyCert(u8 *cert, u8 *pubk)
|
bool VerifyCert(u8 *cert, u8 *pubk)
|
||||||
{
|
{
|
||||||
u32 SigSize = 0;
|
if(!GetCertHdr(cert))
|
||||||
u32 SigPadding = 0;
|
return false;
|
||||||
GetCertSigSectionSizes(&SigSize,&SigPadding,cert);
|
u8 *signature = (cert+sizeof(u32));
|
||||||
if(!SigSize || !SigPadding) return 0;
|
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);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
+14
-15
@@ -2,41 +2,40 @@
|
|||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 Issuer[0x40];
|
u8 issuer[0x40];
|
||||||
u8 KeyType[4];
|
u8 keyType[4];
|
||||||
u8 Name[0x40];
|
u8 name[0x40];
|
||||||
u8 Unknown[4];
|
u8 id[4];
|
||||||
} Cert_Struct;
|
} cert_hdr;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 Modulus[0x200];
|
u8 modulus[0x200];
|
||||||
u8 PubExponent[4];
|
u8 pubExponent[4];
|
||||||
u8 Padding[0x34];
|
u8 padding[0x34];
|
||||||
} rsa_4096_pubk_struct;
|
} rsa_4096_pubk_struct;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 Modulus[0x100];
|
u8 modulus[0x100];
|
||||||
u8 PubExponent[4];
|
u8 pubExponent[4];
|
||||||
u8 Padding[0x34];
|
u8 padding[0x34];
|
||||||
} rsa_2048_pubk_struct;
|
} rsa_2048_pubk_struct;
|
||||||
|
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 PubK[0x3C];
|
u8 pubK[0x3C];
|
||||||
u8 Padding[0x3C];
|
u8 padding[0x3C];
|
||||||
} ecc_pubk_struct;
|
} ecc_pubk_struct;
|
||||||
|
|
||||||
// Cert Sizes
|
// Cert Sizes
|
||||||
u32 GetCertSize(u8 *cert);
|
u32 GetCertSize(u8 *cert);
|
||||||
void GetCertSigSectionSizes(u32 *SigSize, u32 *SigPadding, u8 *cert);
|
|
||||||
u32 GetCertPubkSectionSize(pubk_types type);
|
u32 GetCertPubkSectionSize(pubk_types type);
|
||||||
|
|
||||||
// Issuer/Name Functions
|
// Issuer/Name Functions
|
||||||
u8 *GetCertIssuer(u8 *cert);
|
u8 *GetCertIssuer(u8 *cert);
|
||||||
u8 *GetCertName(u8 *cert);
|
u8 *GetCertName(u8 *cert);
|
||||||
int GenCertChildIssuer(u8 *dest, u8 *cert);
|
void GenCertChildIssuer(u8 *dest, u8 *cert);
|
||||||
|
|
||||||
// Pubk
|
// Pubk
|
||||||
pubk_types GetCertPubkType(u8 *cert);
|
pubk_types GetCertPubkType(u8 *cert);
|
||||||
|
|||||||
+10
-16
@@ -17,7 +17,6 @@ const int CIA_ALIGN_SIZE = 0x40;
|
|||||||
const int CIA_CONTENT_ALIGN = 0x10;
|
const int CIA_CONTENT_ALIGN = 0x10;
|
||||||
|
|
||||||
// Private Prototypes
|
// Private Prototypes
|
||||||
void InitCiaSettings(cia_settings *set);
|
|
||||||
void FreeCiaSettings(cia_settings *set);
|
void FreeCiaSettings(cia_settings *set);
|
||||||
int GetCiaSettings(cia_settings *ciaset, user_settings *usrset);
|
int GetCiaSettings(cia_settings *ciaset, user_settings *usrset);
|
||||||
|
|
||||||
@@ -53,7 +52,6 @@ int build_CIA(user_settings *usrset)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get Settings
|
// Get Settings
|
||||||
InitCiaSettings(ciaset);
|
|
||||||
result = GetCiaSettings(ciaset,usrset);
|
result = GetCiaSettings(ciaset,usrset);
|
||||||
if(result) goto finish;
|
if(result) goto finish;
|
||||||
|
|
||||||
@@ -96,11 +94,6 @@ finish:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitCiaSettings(cia_settings *set)
|
|
||||||
{
|
|
||||||
memset(set,0,sizeof(cia_settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
void FreeCiaSettings(cia_settings *set)
|
void FreeCiaSettings(cia_settings *set)
|
||||||
{
|
{
|
||||||
if(set->content.filePtrs){
|
if(set->content.filePtrs){
|
||||||
@@ -198,8 +191,7 @@ int GetSettingsFromUsrset(cia_settings *ciaset, user_settings *usrset)
|
|||||||
|
|
||||||
ciaset->tik.formatVersion = 1;
|
ciaset->tik.formatVersion = 1;
|
||||||
|
|
||||||
int result = GenCertChildIssuer(ciaset->tik.issuer,ciaset->keys->certs.xsCert);
|
GenCertChildIssuer(ciaset->tik.issuer,ciaset->keys->certs.xsCert);
|
||||||
if(result) return result;
|
|
||||||
|
|
||||||
// Tmd Stuff
|
// Tmd Stuff
|
||||||
if(usrset->cia.contentId[0] > MAX_U32)
|
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.formatVersion = 1;
|
||||||
ciaset->tmd.accessRights = 0;
|
ciaset->tmd.accessRights = 0;
|
||||||
result = GenCertChildIssuer(ciaset->tmd.issuer,ciaset->keys->certs.cpCert);
|
GenCertChildIssuer(ciaset->tmd.issuer,ciaset->keys->certs.cpCert);
|
||||||
return 0;
|
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)
|
if(IsPatch(GetTidCategory(ciaset->common.titleId))||ciaset->content.IsCfa)
|
||||||
ciaset->tmd.savedataSize = 0;
|
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;
|
u64 size = 0;
|
||||||
GetSaveDataSizeFromString(&size,ciaset->rsf->SystemControlInfo.SaveDataSize,"CIA");
|
GetSaveDataSizeFromString(&size,ciaset->rsf->SystemControlInfo.SaveDataSize,"CIA");
|
||||||
ciaset->tmd.savedataSize = (u32)(size & MAX_U32);
|
ciaset->tmd.savedataSize = (u32)(size & MAX_U32);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ciaset->tmd.savedataSize = (u32)(GetSaveDataSize_frm_exhdr(exhdr) & MAX_U32);
|
ciaset->tmd.savedataSize = 0;
|
||||||
|
|
||||||
if(ciaset->content.IsCfa||ciaset->content.keyNotFound){
|
if(ciaset->content.IsCfa||ciaset->content.keyNotFound){
|
||||||
if(ciaset->common.titleVersion[VER_MAJOR] == MAX_U16){ // '-major' wasn't set
|
if(ciaset->common.titleVersion[VER_MAJOR] == MAX_U16){ // '-major' wasn't set
|
||||||
if(ciaset->content.IsCfa){ // Is a CFA and can be decrypted
|
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)
|
void GetContentHashes(cia_settings *ciaset)
|
||||||
{
|
{
|
||||||
for(int i = 0; i < ciaset->content.count; i++)
|
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)
|
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[0] = (index >> 8) & 0xff;
|
||||||
iv[1] = index & 0xff;
|
iv[1] = index & 0xff;
|
||||||
//Crypting content
|
//Crypting content
|
||||||
AesCbc(title_key,iv,input,output,size,mode);
|
AesCbcCrypt(title_key,iv,input,output,size,mode);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+114
-134
@@ -1,14 +1,24 @@
|
|||||||
#include "lib.h"
|
#include "lib.h"
|
||||||
#include "crypto.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])
|
bool VerifySha256(void *data, u64 size, u8 hash[32])
|
||||||
{
|
{
|
||||||
u8 calchash[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;
|
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){
|
switch(mode){
|
||||||
case(CTR_SHA_1): sha1((u8*)data, size, hash); break;
|
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);
|
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];
|
u8 stream[16];
|
||||||
aes_context aes;
|
aes_context aes;
|
||||||
@@ -37,7 +47,7 @@ void AesCtr(u8 *key, u8 *ctr, u8 *input, u8 *output, u64 length, u64 offset)
|
|||||||
return;
|
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;
|
aes_context aes;
|
||||||
clrmem(&aes,sizeof(aes_context));
|
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)
|
bool RsaKeyInit(rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type)
|
||||||
{
|
|
||||||
rsa_free(&ctx->rsa);
|
|
||||||
}
|
|
||||||
|
|
||||||
int ctr_rsa_init(ctr_rsa_context* ctx, u8 *modulus, u8 *private_exp, u8 *exponent, u8 rsa_type, u8 mode)
|
|
||||||
{
|
{
|
||||||
// Sanity Check
|
// Sanity Check
|
||||||
if(ctx == NULL || modulus == NULL ||(private_exp == NULL && mode == RSAKEY_PRIV) || (exponent == NULL && mode == RSAKEY_PUB))
|
if(!ctx)
|
||||||
return Fail;
|
return false;
|
||||||
rsa_init(&ctx->rsa, RSA_PKCS_V15, 0);
|
|
||||||
|
rsa_init(ctx, RSA_PKCS_V15, 0);
|
||||||
|
|
||||||
u16 n_size = 0;
|
u16 n_size = 0;
|
||||||
u16 d_size = 0;
|
u16 d_size = 0;
|
||||||
u16 e_size = 0;
|
u16 e_size = 0;
|
||||||
|
|
||||||
switch(rsa_type){
|
switch(rsa_type){
|
||||||
case RSA_2048:
|
case RSA_2048:
|
||||||
ctx->rsa.len = 0x100;
|
ctx->len = 0x100;
|
||||||
n_size = 0x100;
|
n_size = 0x100;
|
||||||
d_size = 0x100;
|
d_size = 0x100;
|
||||||
e_size = 3;
|
e_size = 3;
|
||||||
break;
|
break;
|
||||||
case RSA_4096:
|
case RSA_4096:
|
||||||
ctx->rsa.len = 0x200;
|
ctx->len = 0x200;
|
||||||
n_size = 0x200;
|
n_size = 0x200;
|
||||||
d_size = 0x200;
|
d_size = 0x200;
|
||||||
e_size = 3;
|
e_size = 3;
|
||||||
break;
|
break;
|
||||||
default: return Fail;
|
default: return false;
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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:
|
clean:
|
||||||
ctr_rsa_free(ctx);
|
rsa_free(ctx);
|
||||||
return Fail;
|
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;
|
switch(sig_type){
|
||||||
int hashtype, hashlen, sigtype;
|
|
||||||
if(data == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
|
|
||||||
return Fail;
|
|
||||||
|
|
||||||
switch(type){
|
|
||||||
case RSA_4096_SHA1:
|
case RSA_4096_SHA1:
|
||||||
hashtype = CTR_SHA_1;
|
|
||||||
hashlen = 0x14;
|
|
||||||
sigtype = RSA_4096;
|
|
||||||
case RSA_4096_SHA256:
|
case RSA_4096_SHA256:
|
||||||
hashtype = CTR_SHA_256;
|
return RSA_4096;
|
||||||
hashlen = 0x20;
|
|
||||||
sigtype = RSA_4096;
|
|
||||||
break;
|
|
||||||
case RSA_2048_SHA1:
|
case RSA_2048_SHA1:
|
||||||
hashtype = CTR_SHA_1;
|
|
||||||
hashlen = 0x14;
|
|
||||||
sigtype = RSA_2048;
|
|
||||||
case RSA_2048_SHA256:
|
case RSA_2048_SHA256:
|
||||||
hashtype = CTR_SHA_256;
|
return RSA_2048;
|
||||||
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 INVALID_SIG_TYPE;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int ctr_rsa(u8 *hash, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode)
|
u32 GetSigHashType(u32 sig_type)
|
||||||
{
|
{
|
||||||
int result = 0;
|
switch(sig_type){
|
||||||
// Sanity Check
|
case RSA_4096_SHA1:
|
||||||
if(hash == NULL || signature == NULL || modulus == NULL ||(private_exp == NULL && mode == CTR_RSA_SIGN))
|
case RSA_2048_SHA1:
|
||||||
return Fail;
|
case ECC_SHA1:
|
||||||
|
return CTR_SHA_1;
|
||||||
// Getting details from sig type
|
case RSA_4096_SHA256:
|
||||||
int hashtype;
|
case RSA_2048_SHA256:
|
||||||
int hashlen;
|
case ECC_SHA256:
|
||||||
int sigtype;
|
return CTR_SHA_256;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
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
|
* Hacked from rsa.c, polarssl doesn't like generating signatures when only D and N are present
|
||||||
|
|||||||
+19
-38
@@ -14,25 +14,26 @@ typedef enum
|
|||||||
RSA_4096_SHA256 = 0x00010003,
|
RSA_4096_SHA256 = 0x00010003,
|
||||||
RSA_2048_SHA256 = 0x00010004,
|
RSA_2048_SHA256 = 0x00010004,
|
||||||
ECC_SHA256 = 0x00010005
|
ECC_SHA256 = 0x00010005
|
||||||
} sig_types;
|
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
RSA_2048 = 0,
|
|
||||||
RSA_4096 = 1,
|
|
||||||
ECC = 2,
|
|
||||||
} ctr_sig_types;
|
} ctr_sig_types;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
CTR_RSA_VERIFY = 0,
|
CTR_RSA_VERIFY,
|
||||||
CTR_RSA_SIGN = 1,
|
CTR_RSA_SIGN,
|
||||||
} ctr_rsa_functions;
|
} ctr_rsa_mode;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
CTR_SHA_1 = 1,
|
RSA_4096,
|
||||||
CTR_SHA_256 = 256,
|
RSA_2048,
|
||||||
|
ECC,
|
||||||
|
INVALID_SIG_TYPE,
|
||||||
|
} sig_types;
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
CTR_SHA_1,
|
||||||
|
CTR_SHA_256,
|
||||||
} ctr_sha_modes;
|
} ctr_sha_modes;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
@@ -46,42 +47,22 @@ typedef enum
|
|||||||
{
|
{
|
||||||
ENC,
|
ENC,
|
||||||
DEC
|
DEC
|
||||||
} aescbcmode;
|
} aes_mode;
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
RSAKEY_INVALID,
|
|
||||||
RSAKEY_PRIV,
|
|
||||||
RSAKEY_PUB
|
|
||||||
} rsakeytype;
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
rsa_context rsa;
|
|
||||||
} ctr_rsa_context;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
// SHA
|
// SHA
|
||||||
bool VerifySha256(void *data, u64 size, u8 hash[32]);
|
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
|
// AES
|
||||||
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);
|
||||||
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);
|
||||||
// RSA
|
// RSA
|
||||||
void ctr_rsa_free(ctr_rsa_context* ctx);
|
int RsaSignVerify(void *data, u64 len, u8 *sign, u8 *mod, u8 *priv_exp, u32 sig_type, u8 rsa_mode);
|
||||||
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 );
|
|
||||||
|
|
||||||
// Signature Functions
|
|
||||||
int ctr_sig(void *data, u64 size, u8 *signature, u8 *modulus, u8 *private_exp, u32 type, u8 mode);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -75,7 +75,7 @@ int GenerateExeFS_Header(exefs_buildctx *ctx, u8 *outbuff)
|
|||||||
memcpy(exefs->fileHdr[i].name,ctx->fileName[i],8);
|
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].offset,ctx->fileOffset[i],LE);
|
||||||
u32_to_u8(exefs->fileHdr[i].size,ctx->fileSize[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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+6
-6
@@ -53,16 +53,16 @@ int get_ExHeaderARM9AccessControlInfo(exhdr_ARM9AccessControlInfo *arm9, rsf_set
|
|||||||
/* ExHeader Signature Functions */
|
/* ExHeader Signature Functions */
|
||||||
int SignAccessDesc(access_descriptor *acexDesc, keys_struct *keys)
|
int SignAccessDesc(access_descriptor *acexDesc, keys_struct *keys)
|
||||||
{
|
{
|
||||||
u8 *AccessDesc = (u8*) &acexDesc->ncchRsaPubKey;
|
u8 *data = (u8*) &acexDesc->ncchRsaPubKey;
|
||||||
u8 *Signature = (u8*) &acexDesc->signature;
|
u8 *sign = (u8*) &acexDesc->signature;
|
||||||
return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.acexPub,keys->rsa.acexPvt,RSA_2048_SHA256,CTR_RSA_SIGN);
|
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)
|
int CheckAccessDescSignature(access_descriptor *acexDesc, keys_struct *keys)
|
||||||
{
|
{
|
||||||
u8 *AccessDesc = (u8*) &acexDesc->ncchRsaPubKey;
|
u8 *data = (u8*) &acexDesc->ncchRsaPubKey;
|
||||||
u8 *Signature = (u8*) &acexDesc->signature;
|
u8 *sign = (u8*) &acexDesc->signature;
|
||||||
return ctr_sig(AccessDesc,0x300,Signature,keys->rsa.acexPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
|
return RsaSignVerify(data,0x300,sign,keys->rsa.acexPub,NULL,RSA_2048_SHA256,CTR_RSA_VERIFY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ExHeader Build Functions */
|
/* ExHeader Build Functions */
|
||||||
|
|||||||
+9
-9
@@ -34,22 +34,22 @@ bool IsValidProductCode(char *ProductCode, bool FreeProductCode);
|
|||||||
// Code
|
// Code
|
||||||
int SignCFA(ncch_hdr *hdr, keys_struct *keys)
|
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)
|
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)
|
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 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -500,13 +500,13 @@ int FinaliseNcch(ncch_settings *set)
|
|||||||
|
|
||||||
// Taking Hashes
|
// Taking Hashes
|
||||||
if(set->cryptoDetails.exhdrSize)
|
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)
|
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)
|
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)
|
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
|
// Signing NCCH
|
||||||
int sig_result = Good;
|
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];
|
u8 ctr[0x10];
|
||||||
GetNcchAesCounter(ctr,titleId,type);
|
GetNcchAesCounter(ctr,titleId,type);
|
||||||
AesCtr(key,ctr,buffer,buffer,size,src_pos);
|
AesCtrCrypt(key,ctr,buffer,buffer,size,src_pos);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
+5
-6
@@ -10,7 +10,6 @@
|
|||||||
#include "cardinfo.h"
|
#include "cardinfo.h"
|
||||||
#include "titleid.h"
|
#include "titleid.h"
|
||||||
|
|
||||||
|
|
||||||
const int NCCH0_OFFSET = 0x4000;
|
const int NCCH0_OFFSET = 0x4000;
|
||||||
const int CCI_BLOCK_SIZE = 0x200;
|
const int CCI_BLOCK_SIZE = 0x200;
|
||||||
|
|
||||||
@@ -288,15 +287,15 @@ int ProcessCiaForCci(cci_settings *set)
|
|||||||
|
|
||||||
int ImportCciNcch(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)
|
if(set->content.dataType == infile_ncch)
|
||||||
return ImportNcchForCci(set);
|
return ImportNcchForCci(set);
|
||||||
else if(set->content.dataType == infile_cia)
|
else if(set->content.dataType == infile_cia)
|
||||||
return ProcessCiaForCci(set);
|
return ProcessCiaForCci(set);
|
||||||
else
|
else
|
||||||
fprintf(stderr,"[CCI ERROR] Unrecognised input data type\n");
|
fprintf(stderr,"[CCI ERROR] Unrecognised input data type\n");
|
||||||
|
|
||||||
if(set->rsf->SystemControlInfo.SaveDataSize)
|
|
||||||
GetSaveDataSizeFromString(&set->romInfo.saveSize,set->rsf->SystemControlInfo.SaveDataSize,"CCI");
|
|
||||||
|
|
||||||
return FAILED_TO_IMPORT_FILE;
|
return FAILED_TO_IMPORT_FILE;
|
||||||
}
|
}
|
||||||
@@ -594,7 +593,7 @@ int GenCciHdr(cci_settings *set)
|
|||||||
SetCciNcchInfo(hdr,set);
|
SetCciNcchInfo(hdr,set);
|
||||||
|
|
||||||
// Sign Header
|
// 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -467,7 +467,7 @@ void GenIvfcHashTree(romfs_buildctx *ctx)
|
|||||||
for(u32 j = 0; j < numHashes; j++){
|
for(u32 j = 0; j < numHashes; j++){
|
||||||
u8 *datapos = (u8*)(ctx->level[i+1].pos + ROMFS_BLOCK_SIZE * j);
|
u8 *datapos = (u8*)(ctx->level[i+1].pos + ROMFS_BLOCK_SIZE * j);
|
||||||
u8 *hashpos = (u8*)(ctx->level[i].pos + 0x20 * 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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-7
@@ -15,9 +15,8 @@ int CryptTitleKey(u8 *input, u8 *output, u8 *titleId, keys_struct *keys, u8 mode
|
|||||||
|
|
||||||
int BuildTicket(cia_settings *set)
|
int BuildTicket(cia_settings *set)
|
||||||
{
|
{
|
||||||
int result = 0;
|
if(SetupTicketBuffer(set))
|
||||||
result = SetupTicketBuffer(set);
|
return MEM_ERROR;
|
||||||
if(result) return result;
|
|
||||||
|
|
||||||
// Setting Ticket Struct Ptrs
|
// Setting Ticket Struct Ptrs
|
||||||
buffer_struct *tik = &set->ciaSections.tik;
|
buffer_struct *tik = &set->ciaSections.tik;
|
||||||
@@ -31,8 +30,7 @@ int BuildTicket(cia_settings *set)
|
|||||||
SetContentIndexHeader(idxHdr,set);
|
SetContentIndexHeader(idxHdr,set);
|
||||||
SetContentIndexData(idxData,set);
|
SetContentIndexData(idxData,set);
|
||||||
|
|
||||||
result = SignTicketHeader(tik,set->keys);
|
return SignTicketHeader(tik,set->keys);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int SetupTicketBuffer(cia_settings *set)
|
int SetupTicketBuffer(cia_settings *set)
|
||||||
@@ -83,7 +81,7 @@ int SignTicketHeader(buffer_struct *tik, keys_struct *keys)
|
|||||||
clrmem(sig,sizeof(tik_signature));
|
clrmem(sig,sizeof(tik_signature));
|
||||||
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
|
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)
|
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);
|
memcpy(iv,titleId,0x8);
|
||||||
|
|
||||||
//Crypting TitleKey
|
//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
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
+4
-3
@@ -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);
|
u32_to_u8(hdr->accessRights,ciaset->tmd.accessRights,BE);
|
||||||
u16_to_u8(hdr->titleVersion,ciaset->tmd.version,BE);
|
u16_to_u8(hdr->titleVersion,ciaset->tmd.version,BE);
|
||||||
u16_to_u8(hdr->contentCount,ciaset->content.count,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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +70,8 @@ int SignTMDHeader(tmd_hdr *hdr, tmd_signature *sig, keys_struct *keys)
|
|||||||
{
|
{
|
||||||
clrmem(sig,sizeof(tmd_signature));
|
clrmem(sig,sizeof(tmd_signature));
|
||||||
u32_to_u8(sig->sigType,RSA_2048_SHA256,BE);
|
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)
|
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);
|
clrmem(info_record,sizeof(tmd_content_info_record)*0x40);
|
||||||
u16_to_u8(info_record->contentIndexOffset,0x0,BE);
|
u16_to_u8(info_record->contentIndexOffset,0x0,BE);
|
||||||
u16_to_u8(info_record->contentCommandCount,ContentCount,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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user