Compare commits

...

4 Commits

Author SHA1 Message Date
shchmue
b150d20957
Merge pull request #19 from HookedBehemoth/master
Fix ticket listing and minor libnx update
2020-03-16 15:27:35 -06:00
HookedBehemoth
d91923accc Fix ticket listing and minor libnx update 2020-03-16 00:25:15 +01:00
shchmue
9bbef1cc69
Merge pull request #18 from HookedBehemoth/master
update for new ipc and libnx changes
2019-10-30 15:10:37 -06:00
HookedBehemoth
b85a2e6631 update for new ipc and libnx changes 2019-10-30 12:19:45 +01:00
7 changed files with 105 additions and 219 deletions

View File

@ -35,7 +35,6 @@
extern "C" {
#include "nx/es.h"
#include "nx/set_ext.h"
}
#define TITLEKEY_BUFFER_SIZE 0x40000
@ -486,7 +485,7 @@ void KeyCollection::derive_keys() {
FRESULT fr;
FIL save_file;
fsOpenBisStorage(&storage, FsBisStorageId_System);
fsOpenBisStorage(&storage, FsBisPartitionId_System);
if (f_mount(&fs, "", 1) ||
f_chdir("/save") ||
f_open(&save_file, "8000000000000043", FA_READ | FA_OPEN_EXISTING))
@ -592,7 +591,7 @@ void KeyCollection::get_titlekeys() {
esInitialize();
esCountCommonTicket(&common_count);
esCountPersonalizedTicket(&personalized_count);
NcmNcaId common_rights_ids[common_count], personalized_rights_ids[personalized_count];
RightsId common_rights_ids[common_count], personalized_rights_ids[personalized_count];
esListCommonTicket(&ids_written, common_rights_ids, sizeof(common_rights_ids));
esListPersonalizedTicket(&ids_written, personalized_rights_ids, sizeof(personalized_rights_ids));
esExit();
@ -620,15 +619,15 @@ void KeyCollection::get_titlekeys() {
}
// get extended eticket RSA key from PRODINFO
u8 eticket_data[0x244] = {};
SetCalRsa2048DeviceKey eticket_data = {};
setcalInitialize();
setcalGetEticketDeviceKey(eticket_data);
setcalGetEticketDeviceKey(&eticket_data);
setcalExit();
byte_vector dec_keypair = eticket_rsa_kek.aes_decrypt_ctr(
byte_vector(eticket_data + 0x14, eticket_data + 0x244),
byte_vector(eticket_data + 4, eticket_data + 0x14)
byte_vector(eticket_data.key + 0x10, eticket_data.key + 0x240),
byte_vector(eticket_data.key, eticket_data.key + 0x10)
);
// public exponent must be 65537 == 0x10001 (big endian)
@ -646,7 +645,7 @@ void KeyCollection::get_titlekeys() {
// map of all found rights ids and corresponding titlekeys
std::unordered_map<std::string, std::string> titlekeys;
fsOpenBisStorage(&storage, FsBisStorageId_System);
fsOpenBisStorage(&storage, FsBisPartitionId_System);
if (f_mount(&fs, "", 1) || f_chdir("/save")) return;
if (f_open(&save_file, "80000000000000e1", FA_READ | FA_OPEN_EXISTING)) return;
while ((common_count != 0) && (titlekeys_dumped < common_count)) {

View File

@ -30,7 +30,7 @@ void KeyLocation::get_from_memory(u64 tid, u8 seg_mask) {
// if not a kernel process, get pid from pm:dmnt
if ((tid > 0x0100000000000005) && (tid != 0x0100000000000028)) {
u64 pid;
pmdmntGetTitlePid(&pid, tid);
pmdmntGetProcessId(&pid, tid);
if (R_FAILED(svcDebugActiveProcess(&debug_handle, pid)) ||
R_FAILED(svcGetDebugEvent(reinterpret_cast<u8 *>(&d), debug_handle)))
@ -101,7 +101,7 @@ void KeyLocation::get_from_memory(u64 tid, u8 seg_mask) {
void KeyLocation::get_keyblobs() {
FsStorage boot0;
fsOpenBisStorage(&boot0, FsBisStorageId_Boot0);
fsOpenBisStorage(&boot0, FsBisPartitionId_BootPartition1Root);
data.resize(0x200 * KNOWN_KEYBLOBS);
fsStorageRead(&boot0, KEYBLOB_OFFSET, data.data(), data.size());
fsStorageClose(&boot0);

View File

@ -1,170 +1,64 @@
#include "es.h"
#include <switch/arm/atomics.h>
#include "../service_guard.h"
#include <switch/kernel/ipc.h>
#include <switch/services/sm.h>
static Service g_esSrv;
static u64 g_esRefCnt;
Result esInitialize() {
atomicIncrement64(&g_esRefCnt);
if (serviceIsActive(&g_esSrv))
return 0;
NX_GENERATE_SERVICE_GUARD(es);
Result _esInitialize() {
return smGetService(&g_esSrv, "es");
}
void esExit()
void _esCleanup() {
serviceClose(&g_esSrv);
}
Result esCountCommonTicket(u32 *out_count)
{
if (atomicDecrement64(&g_esRefCnt) == 0) {
serviceClose(&g_esSrv);
}
u32 num_tickets;
Result rc = serviceDispatchOut(&g_esSrv, 9, num_tickets);
if (R_SUCCEEDED(rc) && out_count) *out_count = num_tickets;
return rc;
}
Result esCountCommonTicket(u32 *num_tickets)
Result esCountPersonalizedTicket(u32 *out_count)
{
IpcCommand c;
ipcInitialize(&c);
u32 num_tickets;
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 9;
Result rc = serviceIpcDispatch(&g_esSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 num_tickets;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*num_tickets = resp->num_tickets;
}
}
Result rc = serviceDispatchOut(&g_esSrv, 10, num_tickets);
if (R_SUCCEEDED(rc) && out_count) *out_count = num_tickets;
return rc;
}
Result esCountPersonalizedTicket(u32 *num_tickets)
Result esListCommonTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize)
{
IpcCommand c;
ipcInitialize(&c);
u32 num_rights_ids_written;
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 10;
Result rc = serviceIpcDispatch(&g_esSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 num_tickets;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
*num_tickets = resp->num_tickets;
}
}
Result rc = serviceDispatchOut(&g_esSrv, 11, num_rights_ids_written,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { outBuf, bufSize } },
);
if (R_SUCCEEDED(rc) && numRightsIdsWritten) *numRightsIdsWritten = num_rights_ids_written;
return rc;
}
Result esListCommonTicket(u32 *numRightsIdsWritten, NcmNcaId *outBuf, size_t bufSize) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, outBuf, bufSize, BufferType_Normal);
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize)
{
u32 num_rights_ids_written;
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 11;
Result rc = serviceIpcDispatch(&g_esSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 num_rights_ids_written;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (numRightsIdsWritten) *numRightsIdsWritten = resp->num_rights_ids_written;
}
}
Result rc = serviceDispatchOut(&g_esSrv, 12, num_rights_ids_written,
.buffer_attrs = { SfBufferAttr_HipcMapAlias | SfBufferAttr_Out },
.buffers = { { outBuf, bufSize } },
);
if (R_SUCCEEDED(rc) && numRightsIdsWritten) *numRightsIdsWritten = num_rights_ids_written;
return rc;
}
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, NcmNcaId *outBuf, size_t bufSize) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, outBuf, bufSize, BufferType_Normal);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 12;
Result rc = serviceIpcDispatch(&g_esSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
u32 num_rights_ids_written;
} *resp = r.Raw;
rc = resp->result;
if (R_SUCCEEDED(rc)) {
if (numRightsIdsWritten) *numRightsIdsWritten = resp->num_rights_ids_written;
}
}
return rc;
}

View File

@ -3,10 +3,14 @@
#include <switch/types.h>
#include <switch/services/ncm.h>
typedef struct {
u8 c[0x10];
} RightsId;
Result esInitialize();
void esExit();
Result esCountCommonTicket(u32 *num_tickets); //9
Result esCountPersonalizedTicket(u32 *num_tickets); // 10
Result esListCommonTicket(u32 *numRightsIdsWritten, NcmNcaId *outBuf, size_t bufSize);
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, NcmNcaId *outBuf, size_t bufSize);
Result esListCommonTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize);
Result esListPersonalizedTicket(u32 *numRightsIdsWritten, RightsId *outBuf, size_t bufSize);

View File

@ -1,55 +0,0 @@
#include "set_ext.h"
#include <switch/arm/atomics.h>
#include <switch/services/sm.h>
#include <switch/types.h>
static Service g_setcalSrv;
static u64 g_refCntCal;
Result setcalInitialize(void) {
atomicIncrement64(&g_refCntCal);
if (serviceIsActive(&g_setcalSrv))
return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized);
return smGetService(&g_setcalSrv, "set:cal");
}
void setcalExit(void) {
if (atomicDecrement64(&g_refCntCal) == 0) {
serviceClose(&g_setcalSrv);
}
}
Result setcalGetEticketDeviceKey(void *key) {
IpcCommand c;
ipcInitialize(&c);
ipcAddRecvBuffer(&c, key, 0x244, 0);
struct {
u64 magic;
u64 cmd_id;
} *raw;
raw = ipcPrepareHeader(&c, sizeof(*raw));
raw->magic = SFCI_MAGIC;
raw->cmd_id = 21;
Result rc = serviceIpcDispatch(&g_setcalSrv);
if (R_SUCCEEDED(rc)) {
IpcParsedCommand r;
ipcParse(&r);
struct {
u64 magic;
u64 result;
} *resp = r.Raw;
rc = resp->result;
}
return rc;
}

View File

@ -1,12 +0,0 @@
#pragma once
#include <switch/result.h>
Result setcalInitialize(void);
void setcalExit(void);
/**
* @brief Gets the extended ETicket RSA-2048 Key from CAL0
* @param key Pointer to 0x244-byte output buffer.
*/
Result setcalGetEticketDeviceKey(void *key);

56
source/service_guard.h Normal file
View File

@ -0,0 +1,56 @@
#pragma once
#include <switch/types.h>
#include <switch/result.h>
#include <switch/kernel/mutex.h>
#include <switch/sf/service.h>
#include <switch/services/sm.h>
typedef struct ServiceGuard {
Mutex mutex;
u32 refCount;
} ServiceGuard;
NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g)
{
mutexLock(&g->mutex);
return (g->refCount++) == 0;
}
NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void))
{
if (R_FAILED(rc)) {
cleanupFunc();
--g->refCount;
}
mutexUnlock(&g->mutex);
return rc;
}
NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void))
{
mutexLock(&g->mutex);
if (g->refCount && (--g->refCount) == 0)
cleanupFunc();
mutexUnlock(&g->mutex);
}
#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \
\
static ServiceGuard g_##name##Guard; \
NX_INLINE Result _##name##Initialize _paramdecl; \
static void _##name##Cleanup(void); \
\
Result name##Initialize _paramdecl \
{ \
Result rc = 0; \
if (serviceGuardBeginInit(&g_##name##Guard)) \
rc = _##name##Initialize _parampass; \
return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \
} \
\
void name##Exit(void) \
{ \
serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \
}
#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ())