Skip to content

Commit fbc8f2e

Browse files
authored
Added more ES functions pt.2 (#193)
* add korean common key check * formal certificates check for DiVerifyWithTicketView
1 parent 841442b commit fbc8f2e

2 files changed

Lines changed: 113 additions & 31 deletions

File tree

gc/ogc/es.h

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,11 @@ distribution.
5050
#define ES_CERT_RSA2048 1
5151
#define ES_CERT_ECDSA 2
5252

53+
#define ES_KEY_NANDFS 2 /* !? */
5354
#define ES_KEY_COMMON 4
55+
#define ES_KEY_BACKUP 5
5456
#define ES_KEY_SDCARD 6
57+
#define ES_KEY_KOREAN 11
5558

5659
#ifdef __cplusplus
5760
extern "C" {
@@ -269,7 +272,12 @@ s32 ES_GetStoredTMD(u64 titleID, signed_blob *stmd, u32 size);
269272
s32 ES_GetTitleContentsCount(u64 titleID, u32 *num);
270273
s32 ES_GetTitleContents(u64 titleID, u32 *contents, u32 num);
271274
s32 ES_GetTMDViewSize(u64 titleID, u32 *size);
272-
s32 ES_GetTMDView(u64 titleID, u8 *data, u32 size);
275+
s32 ES_GetTMDView(u64 titleID, tmd_view *view, u32 size);
276+
s32 ES_GetConsumptionCount(u64 ticketID, u32 *n_limits);
277+
s32 ES_GetConsumption(u64 ticketID, tiklimit *limits, u32 n_limits);
278+
s32 ES_DiGetTMDViewSize(const signed_blob *s_tmd, u32 tmd_size, u32 *view_size);
279+
s32 ES_DiGetTMDView(const signed_blob *s_tmd, u32 tmd_size, tmd_view *view, u32 view_size);
280+
s32 ES_DiGetTicketView(const signed_blob *s_tik, tikview *view);
273281
s32 ES_GetNumSharedContents(u32 *cnt);
274282
s32 ES_GetSharedContents(sha1 *contents, u32 cnt);
275283
s32 ES_LaunchTitle(u64 titleID, const tikview *view);
@@ -278,29 +286,35 @@ s32 ES_Identify(const signed_blob *certificates, u32 certificates_size, const si
278286
s32 ES_DiVerifyWithTicketView(const signed_blob *certificates, u32 certificates_size, const signed_blob *s_tmd, u32 tmd_size, const tikview *ticket_view, u32 *keynum);
279287
s32 ES_AddTicket(const signed_blob *tik, u32 tik_size, const signed_blob *certificates, u32 certificates_size, const signed_blob *crl, u32 crl_size);
280288
s32 ES_DeleteTicket(const tikview *view);
281-
s32 ES_AddTitleTMD(const signed_blob *tmd, u32 tmd_size);
289+
s32 ES_ExportTitleInit(u64 titleID, signed_blob *tmd_out, u32 tmd_size);
290+
s32 ES_ExportContentBegin(u64 titleID, u32 cid);
291+
s32 ES_ExportContentData(s32 cfd, void *data, u32 data_size);
292+
s32 ES_ExportContentEnd(s32 cfd);
293+
s32 ES_ExportTitleDone(void);
294+
s32 ES_ReimportTitleInit(const signed_blob *tmd, u32 tmd_size);
282295
s32 ES_AddTitleStart(const signed_blob *tmd, u32 tmd_size, const signed_blob *certificatess, u32 certificatess_size, const signed_blob *crl, u32 crl_size);
283296
s32 ES_AddContentStart(u64 titleID, u32 cid);
284-
s32 ES_AddContentData(s32 cid, u8 *data, u32 data_size);
297+
s32 ES_AddContentData(s32 cid, const void *data, u32 data_size);
285298
s32 ES_AddContentFinish(u32 cid);
286299
s32 ES_AddTitleFinish(void);
287300
s32 ES_AddTitleCancel(void);
288301
s32 ES_ImportBoot(const signed_blob *tik, u32 tik_size,const signed_blob *tik_certs, u32 tik_certs_size,const signed_blob *tmd, u32 tmd_size,const signed_blob *tmd_certs, u32 tmd_certs_size,const u8 *content, u32 content_size);
289302
s32 ES_OpenContent(u16 index);
290-
s32 ES_OpenTitleContent(u64 titleID, tikview *views, u16 index);
291-
s32 ES_ReadContent(s32 cfd, u8 *data, u32 data_size);
303+
s32 ES_OpenTitleContent(u64 titleID, const tikview *views, u16 index);
304+
s32 ES_ReadContent(s32 cfd, void *data, u32 data_size);
292305
s32 ES_SeekContent(s32 cfd, s32 where, s32 whence);
293306
s32 ES_CloseContent(s32 cfd);
294307
s32 ES_DeleteTitle(u64 titleID);
295308
s32 ES_DeleteTitleContent(u64 titleID);
296-
s32 ES_Encrypt(u32 keynum, u32 *iv, void *source, u32 size, void *dest);
297-
s32 ES_Decrypt(u32 keynum, u32 *iv, void *source, u32 size, void *dest);
298-
s32 ES_Sign(void *source, u32 size, u8 *ap_signature, signed_blob *ap_certificate);
299-
s32 ES_VerifySign(void *source, u32 size, u8 *ap_signature, signed_blob *certificates, u32 certificates_size);
309+
s32 ES_Encrypt(u32 keynum, u32 *iv, const void *source, u32 size, void *dest);
310+
s32 ES_Decrypt(u32 keynum, u32 *iv, const void *source, u32 size, void *dest);
311+
s32 ES_Sign(const void *source, u32 size, u8 *ap_signature, signed_blob *ap_certificate);
312+
s32 ES_VerifySign(const void *source, u32 size, const u8 *ap_signature, const signed_blob *certificates, u32 certificates_size);
300313
s32 ES_GetDeviceCert(u8 *outbuf);
301314
s32 ES_GetDeviceID(u32 *device_id);
302315
s32 ES_GetBoot2Version(u32 *version);
303-
signed_blob *ES_NextCert(const signed_blob *certs);
316+
s32 ES_CheckHasKoreanKey(void);
317+
const signed_blob *ES_NextCert(const signed_blob *certs);
304318

305319
#ifdef __cplusplus
306320
}

libogc/es.c

Lines changed: 89 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -67,12 +67,12 @@ distribution.
6767
#define IOCTL_ES_GETVIEWS 0x13
6868
#define IOCTL_ES_GETTMDVIEWCNT 0x14
6969
#define IOCTL_ES_GETTMDVIEWS 0x15
70-
//#define IOCTL_ES_GETCONSUMPTION 0x16
70+
#define IOCTL_ES_GETCONSUMPTION 0x16
7171
#define IOCTL_ES_DELETETITLE 0x17
7272
#define IOCTL_ES_DELETETICKET 0x18
73-
//#define IOCTL_ES_DIGETTMDVIEWSIZE 0x19
74-
//#define IOCTL_ES_DIGETTMDVIEW 0x1A
75-
//#define IOCTL_ES_DIGETTICKETVIEW 0x1B
73+
#define IOCTL_ES_DIGETTMDVIEWSIZE 0x19
74+
#define IOCTL_ES_DIGETTMDVIEW 0x1A
75+
#define IOCTL_ES_DIGETTICKETVIEW 0x1B
7676
#define IOCTL_ES_DIVERIFY 0x1C
7777
#define IOCTL_ES_GETTITLEDIR 0x1D
7878
#define IOCTL_ES_GETDEVICECERT 0x1E
@@ -102,6 +102,7 @@ distribution.
102102
#define IOCTL_ES_GETSHAREDCONTENTCNT 0x36
103103
#define IOCTL_ES_GETSHAREDCONTENTS 0x37
104104
#define IOCTL_ES_DIVERIFYWITHTIKVIEW 0x3B
105+
#define IOCTL_ES_CHECKHASKOREANKEY 0x45
105106

106107
#define ES_HEAP_SIZE 0x800
107108

@@ -350,7 +351,7 @@ s32 ES_GetNumStoredTMDContents(const signed_blob *stmd, u32 tmd_size, u32 *cnt)
350351
if(__es_fd<0) return ES_ENOTINIT;
351352
if(!cnt) return ES_EINVAL;
352353
if(!stmd || !IS_VALID_SIGNATURE(stmd)) return ES_EINVAL;
353-
if(!ISALIGNED(stmd, 64)) return ES_EALIGN; /* !? passed directly to VerifyContainer */
354+
if(!ISALIGNED(stmd, 64)) return ES_EALIGN; /* !? passed directly to VerifyContainer -> passed directly to IOSC_GenerateHash */
354355

355356
ret = IOS_IoctlvFormat(__es_hid,__es_fd,IOCTL_ES_GETSTOREDCONTENTCNT,"d:i",stmd,tmd_size,&cntct);
356357

@@ -413,14 +414,74 @@ s32 ES_GetTMDViewSize(u64 titleID, u32 *size)
413414
return ret;
414415
}
415416

416-
s32 ES_GetTMDView(u64 titleID, u8 *data, u32 size)
417+
s32 ES_GetTMDView(u64 titleID, tmd_view *view, u32 size)
417418
{
418419
if(__es_fd<0) return ES_ENOTINIT;
419420
if(size <= 0) return ES_EINVAL;
420-
if(!data) return ES_EINVAL;
421-
if(!ISALIGNED(data, 4)) return ES_EALIGN;
421+
if(!view) return ES_EINVAL;
422+
if(!ISALIGNED(view, 4)) return ES_EALIGN;
423+
424+
return IOS_IoctlvFormat(__es_hid,__es_fd,IOCTL_ES_GETTMDVIEWS,"qi:d",titleID,size,view,size);
425+
}
426+
427+
s32 ES_GetConsumptionCount(u64 ticketID, u32 *n_limits)
428+
{
429+
s32 ret;
430+
u32 _n_limits = 0;
431+
432+
if (__es_fd < 0) return ES_ENOTINIT;
433+
if (!n_limits) return ES_EINVAL;
434+
435+
ret = IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_GETCONSUMPTION, "q:di", ticketID, NULL, 0, &_n_limits);
436+
*n_limits = _n_limits;
437+
438+
return ret;
439+
}
440+
441+
s32 ES_GetConsumption(u64 ticketID, tiklimit *limits, u32 n_limits)
442+
{
443+
if (__es_fd < 0) return ES_ENOTINIT;
444+
if (!n_limits || !limits) return ES_EINVAL;
445+
if (!ISALIGNED(limits, 4)) return ES_EALIGN;
446+
447+
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_GETCONSUMPTION, "q:di", ticketID, limits, n_limits * sizeof(tiklimit), &n_limits);
448+
}
449+
450+
s32 ES_DiGetTMDViewSize(const signed_blob *s_tmd, u32 tmd_size, u32 *view_size)
451+
{
452+
s32 ret;
453+
u32 size = 0;
454+
455+
if (__es_fd < 0) return ES_ENOTINIT;
456+
if (s_tmd && tmd_size != SIGNED_TMD_SIZE(s_tmd)) return ES_EINVAL;
457+
if (!size) return ES_EINVAL;
458+
if (!ISALIGNED(s_tmd, 4)) return ES_EALIGN;
459+
460+
if (!s_tmd) tmd_size = 0;
461+
462+
ret = IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_DIGETTMDVIEWSIZE, "d:i", s_tmd, tmd_size, &size);
463+
*view_size = size;
464+
465+
return ret;
466+
}
467+
468+
s32 ES_DiGetTMDView(const signed_blob *s_tmd, u32 tmd_size, tmd_view *view, u32 view_size)
469+
{
470+
if (__es_fd < 0) return ES_ENOTINIT;
471+
if (s_tmd && tmd_size != SIGNED_TMD_SIZE(s_tmd)) return ES_EINVAL;
472+
if (view_size < sizeof(tmd_view)) return ES_EINVAL;
473+
if (!ISALIGNED(s_tmd, 4) || !ISALIGNED(view, 4)) return ES_EALIGN;
422474

423-
return IOS_IoctlvFormat(__es_hid,__es_fd,IOCTL_ES_GETTMDVIEWS,"qi:d",titleID,size,data,size);
475+
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_DIGETTMDVIEW, "di:d", s_tmd, (s_tmd == NULL ? 0 : tmd_size), &view_size, view, view_size);
476+
}
477+
478+
s32 ES_DiGetTicketView(const signed_blob *s_tik, tikview *view)
479+
{
480+
if (__es_fd < 0) return ES_ENOTINIT;
481+
if (!view) return ES_EINVAL;
482+
if (!ISALIGNED(s_tik, 4) || !ISALIGNED(view, 4)) return ES_EALIGN;
483+
484+
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_DIGETTICKETVIEW, "d:d", s_tik, (s_tik == NULL ? 0 : STD_SIGNED_TIK_SIZE), view, sizeof(tikview));
424485
}
425486

426487
s32 ES_GetStoredTMDSize(u64 titleID, u32 *size)
@@ -474,7 +535,7 @@ s32 ES_GetSharedContents(sha1 *contents, u32 cnt)
474535
return IOS_IoctlvFormat(__es_hid,__es_fd,IOCTL_ES_GETSHAREDCONTENTS,"i:d",cnt,contents,sizeof(sha1)*cnt);
475536
}
476537

477-
signed_blob *ES_NextCert(const signed_blob *certs)
538+
const signed_blob *ES_NextCert(const signed_blob *certs)
478539
{
479540
cert_header *cert;
480541
if(!SIGNATURE_SIZE(certs)) return NULL;
@@ -558,7 +619,7 @@ s32 ES_DiVerifyWithTicketView(const signed_blob *certificates, u32 certificates_
558619
if (!s_tmd || !IS_VALID_SIGNATURE(s_tmd) || tmd_size != SIGNED_TMD_SIZE(s_tmd))
559620
return ES_EINVAL;
560621

561-
if (certificates_size && !__ES_sanity_check_certlist(certificates, certificates_size)) // ES_DiVerifyWithTicketView must fetch the system's certificate store for the ticket. It also does not check the size. It does check the pointer though.
622+
if (!certificates || (certificates_size && !__ES_sanity_check_certlist(certificates, certificates_size)) || !ISALIGNED(certificates_size, 64)) // ES will copy our certificates first then read the system's on top of that. So if the size is somehow not a multiple of 64 bytes then, unless you plan to provide the ticket certificates yourself, the function is going to break
562623
return ES_EINVAL;
563624

564625
// Alignment demands according to the actual IPC handler. ES ultimately allocates it's own 64-byte aligned buffer and copies our data.
@@ -630,7 +691,7 @@ s32 ES_ExportContentBegin(u64 titleID, u32 contentID) {
630691
s32 ES_ExportContentData(s32 cfd, void *data, u32 size) {
631692
if (__es_fd < 0) return ES_ENOTINIT;
632693
if (!data || !size) return ES_EINVAL;
633-
if (!ISALIGNED(data, 16) /* passed directly to IOSC_Encrypt */ || !ISALIGNED(size, 32) /* !? ES rounds up data_read to 32 bytes */)
694+
if (!ISALIGNED(data, 32) || !ISALIGNED(size, 32))
634695
return ES_EALIGN;
635696

636697
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_EXPORTCONTENTDATA, "i:d", cfd, data, size);
@@ -690,7 +751,7 @@ s32 ES_AddContentStart(u64 titleID, u32 cid)
690751
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_ADDCONTENTSTART, "qi:", titleID, cid);
691752
}
692753

693-
s32 ES_AddContentData(s32 cfd, u8 *data, u32 data_size)
754+
s32 ES_AddContentData(s32 cfd, const void *data, u32 data_size)
694755
{
695756
if(__es_fd<0) return ES_ENOTINIT;
696757
if(cfd<0) return ES_EINVAL;
@@ -740,14 +801,14 @@ s32 ES_OpenContent(u16 index)
740801
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_OPENCONTENT, "i:", index);
741802
}
742803

743-
s32 ES_OpenTitleContent(u64 titleID, tikview *views, u16 index)
804+
s32 ES_OpenTitleContent(u64 titleID, const tikview *views, u16 index)
744805
{
745806
if(__es_fd<0) return ES_ENOTINIT;
746807
if(!ISALIGNED(views, 4)) return ES_EALIGN;
747808
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_OPENTITLECONTENT, "qdi:", titleID, views, sizeof(tikview), index);
748809
}
749810

750-
s32 ES_ReadContent(s32 cfd, u8 *data, u32 data_size)
811+
s32 ES_ReadContent(s32 cfd, void *data, u32 data_size)
751812
{
752813
if(__es_fd<0) return ES_ENOTINIT;
753814
if(cfd<0) return ES_EINVAL;
@@ -782,31 +843,31 @@ s32 ES_DeleteTitleContent(u64 titleID)
782843
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_DELETETITLECONTENT, "q:", titleID);
783844
}
784845

785-
s32 ES_Encrypt(u32 keynum, u32 *iv, void *source, u32 size, void *dest)
846+
s32 ES_Encrypt(u32 keynum, u32 *iv, const void *source, u32 size, void *dest)
786847
{
787848
if (__es_fd < 0)
788849
return ES_ENOTINIT;
789850
if (!iv || !source || !size || !dest)
790851
return ES_EINVAL;
791-
if (!ISALIGNED(iv, 4) || !ISALIGNED(source, 16) || !ISALIGNED(dest, 16) || !ISALIGNED(size, 16))
852+
if (!ISALIGNED(iv, 4) || !ISALIGNED(source, 32) || !ISALIGNED(dest, 32) || !ISALIGNED(size, 16))
792853
return ES_EALIGN;
793854

794855
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_ENCRYPT, "idd:dd", keynum, iv, 0x10, source, size, iv, 0x10, dest, size);
795856
}
796857

797-
s32 ES_Decrypt(u32 keynum, u32 *iv, void *source, u32 size, void *dest)
858+
s32 ES_Decrypt(u32 keynum, u32 *iv, const void *source, u32 size, void *dest)
798859
{
799860
if (__es_fd < 0)
800861
return ES_ENOTINIT;
801862
if (!iv || !source || !size || !dest)
802863
return ES_EINVAL;
803-
if (!ISALIGNED(iv, 4) || !ISALIGNED(source, 16) || !ISALIGNED(dest, 16) || !ISALIGNED(size, 16))
864+
if (!ISALIGNED(iv, 4) || !ISALIGNED(source, 32) || !ISALIGNED(dest, 32) || !ISALIGNED(size, 16))
804865
return ES_EALIGN;
805866

806867
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_DECRYPT, "idd:dd", keynum, iv, 0x10, source, size, iv, 0x10, dest, size);
807868
}
808869

809-
s32 ES_Sign(void *data, u32 size, u8 *ap_signature, signed_blob *ap_certificate)
870+
s32 ES_Sign(const void *data, u32 size, u8 *ap_signature, signed_blob *ap_certificate)
810871
{
811872
if (__es_fd < 0) return ES_ENOTINIT;
812873
if (!data || !size || !ap_signature || !ap_certificate) return ES_EINVAL;
@@ -817,7 +878,7 @@ s32 ES_Sign(void *data, u32 size, u8 *ap_signature, signed_blob *ap_certificate)
817878
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_SIGN, "d:dd", data, size, ap_signature, 0x3C, ap_certificate, 0x180);
818879
}
819880

820-
s32 ES_VerifySign(void *data, u32 size, u8 *ap_signature, signed_blob *certificates, u32 certificates_size) {
881+
s32 ES_VerifySign(const void *data, u32 size, const u8 *ap_signature, const signed_blob *certificates, u32 certificates_size) {
821882
if (__es_fd < 0) return ES_ENOTINIT;
822883
if (!data || !size || !ap_signature || !certificates || !certificates_size) return ES_EINVAL;
823884
if (!__ES_sanity_check_certlist(certificates, certificates_size)) return ES_EINVAL;
@@ -863,6 +924,13 @@ s32 ES_GetBoot2Version(u32 *version)
863924
return ret;
864925
}
865926

927+
s32 ES_CheckHasKoreanKey(void)
928+
{
929+
if (__es_fd < 0) return ES_ENOTINIT;
930+
931+
return IOS_IoctlvFormat(__es_hid, __es_fd, IOCTL_ES_CHECKHASKOREANKEY, "");
932+
}
933+
866934
// 64k buffer size for alignment
867935
#define ES_READ_BUF_SIZE 65536
868936

0 commit comments

Comments
 (0)