2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
2012-07-27 19:26:49 +02:00
|
|
|
#include <malloc.h>
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "channel_launcher.h"
|
2012-10-13 00:25:22 +02:00
|
|
|
#include "booter/external_booter.hpp"
|
2012-12-08 17:17:35 +01:00
|
|
|
#include "gecko/gecko.hpp"
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "loader/disc.h"
|
|
|
|
#include "loader/fs.h"
|
|
|
|
#include "loader/fst.h"
|
|
|
|
#include "loader/utils.h"
|
2012-12-09 21:21:47 +01:00
|
|
|
#include "loader/sys.h"
|
2012-12-08 22:16:05 +01:00
|
|
|
#include "memory/mem2.hpp"
|
2012-08-21 18:33:44 +02:00
|
|
|
#include "memory/memory.h"
|
2012-08-05 15:48:15 +02:00
|
|
|
#include "unzip/lz77.h"
|
2012-08-12 23:26:24 +02:00
|
|
|
#include "types.h"
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
bool Identify_GenerateTik(signed_blob **outbuf, u32 *outlen)
|
|
|
|
{
|
2012-12-08 22:16:05 +01:00
|
|
|
signed_blob *buffer = (signed_blob*)MEM2_memalign(32, STD_SIGNED_TIK_SIZE);
|
2012-07-27 19:26:49 +02:00
|
|
|
if(!buffer)
|
|
|
|
return false;
|
2012-01-21 21:57:41 +01:00
|
|
|
memset(buffer, 0, STD_SIGNED_TIK_SIZE);
|
|
|
|
|
2012-12-08 22:16:05 +01:00
|
|
|
sig_rsa2048 *signature = (sig_rsa2048*)buffer;
|
2012-01-21 21:57:41 +01:00
|
|
|
signature->type = ES_SIG_RSA2048;
|
|
|
|
|
|
|
|
tik *tik_data = (tik *)SIGNATURE_PAYLOAD(buffer);
|
|
|
|
strcpy(tik_data->issuer, "Root-CA00000001-XS00000003");
|
|
|
|
memset(tik_data->cidx_mask, 0xFF, 32);
|
|
|
|
|
|
|
|
*outbuf = buffer;
|
|
|
|
*outlen = STD_SIGNED_TIK_SIZE;
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-07-10 13:25:27 +02:00
|
|
|
bool Identify(u64 titleid)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
char filepath[ISFS_MAXPATH] ATTRIBUTE_ALIGN(32);
|
2012-05-20 14:34:48 +02:00
|
|
|
|
2018-11-26 00:37:55 +01:00
|
|
|
gprintf("Reading TMD for %08lx %08lx...", TITLE_UPPER(titleid), TITLE_LOWER(titleid));
|
2020-03-19 23:38:32 +01:00
|
|
|
snprintf(filepath, ISFS_MAXPATH, "/title/%08lx/%08lx/content/title.tmd", TITLE_UPPER(titleid), TITLE_LOWER(titleid));
|
2012-01-21 21:57:41 +01:00
|
|
|
u32 tmdSize;
|
2012-11-12 21:12:00 +01:00
|
|
|
u8 *tmdBuffer = ISFS_GetFile(filepath, &tmdSize, -1);
|
2012-01-21 21:57:41 +01:00
|
|
|
if (tmdBuffer == NULL || tmdSize == 0)
|
|
|
|
{
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Failed!\n");
|
2012-01-21 21:57:41 +01:00
|
|
|
return false;
|
|
|
|
}
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Success!\n");
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
u32 tikSize;
|
|
|
|
signed_blob *tikBuffer = NULL;
|
|
|
|
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Generating fake ticket...");
|
2012-12-08 22:16:05 +01:00
|
|
|
if(!Identify_GenerateTik(&tikBuffer, &tikSize))
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Failed!\n");
|
2012-01-21 21:57:41 +01:00
|
|
|
return false;
|
|
|
|
}
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Success!\n");
|
2012-01-21 21:57:41 +01:00
|
|
|
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Reading certs...");
|
2012-12-08 22:16:05 +01:00
|
|
|
memset(filepath, 0, ISFS_MAXPATH);
|
2012-11-12 21:12:00 +01:00
|
|
|
strcpy(filepath, "/sys/cert.sys");
|
2012-12-08 22:16:05 +01:00
|
|
|
|
|
|
|
u32 certSize = 0;
|
2012-11-12 21:12:00 +01:00
|
|
|
u8 *certBuffer = ISFS_GetFile(filepath, &certSize, -1);
|
2012-01-21 21:57:41 +01:00
|
|
|
if (certBuffer == NULL || certSize == 0)
|
|
|
|
{
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Failed!\n");
|
2012-07-27 19:26:49 +02:00
|
|
|
free(tmdBuffer);
|
|
|
|
free(tikBuffer);
|
2012-01-21 21:57:41 +01:00
|
|
|
return false;
|
|
|
|
}
|
2012-05-20 14:34:48 +02:00
|
|
|
gprintf("Success!\n");
|
|
|
|
|
|
|
|
gprintf("ES_Identify\n");
|
2012-12-08 22:16:05 +01:00
|
|
|
u32 keyId = 0;
|
|
|
|
DCFlushRange(tmdBuffer, tmdSize);
|
|
|
|
DCFlushRange(tikBuffer, tikSize);
|
|
|
|
DCFlushRange(certBuffer, certSize);
|
|
|
|
s32 ret = ES_Identify((signed_blob*)certBuffer, certSize, (signed_blob*)tmdBuffer, tmdSize, tikBuffer, tikSize, &keyId);
|
|
|
|
if(ret < 0)
|
2012-01-21 21:57:41 +01:00
|
|
|
{
|
|
|
|
switch(ret)
|
|
|
|
{
|
|
|
|
case ES_EINVAL:
|
|
|
|
gprintf("Error! ES_Identify (ret = %d;) Data invalid!\n", ret);
|
|
|
|
break;
|
|
|
|
case ES_EALIGN:
|
|
|
|
gprintf("Error! ES_Identify (ret = %d;) Data not aligned!\n", ret);
|
|
|
|
break;
|
|
|
|
case ES_ENOTINIT:
|
|
|
|
gprintf("Error! ES_Identify (ret = %d;) ES not initialized!\n", ret);
|
|
|
|
break;
|
|
|
|
case ES_ENOMEM:
|
|
|
|
gprintf("Error! ES_Identify (ret = %d;) No memory!\n", ret);
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
gprintf("Error! ES_Identify (ret = %d)\n", ret);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2017-09-22 00:03:41 +02:00
|
|
|
gprintf("AHBPROT: %d, Key ID: %u\n", AHBPROT_Patched(), keyId);
|
2012-07-27 19:26:49 +02:00
|
|
|
free(tmdBuffer);
|
|
|
|
free(tikBuffer);
|
|
|
|
free(certBuffer);
|
2012-01-21 21:57:41 +01:00
|
|
|
|
|
|
|
return ret < 0 ? false : true;
|
|
|
|
}
|