Skip to content

Instantly share code, notes, and snippets.

@joel16
Last active June 18, 2022 12:18
Show Gist options
  • Save joel16/97925b58cd37cb0d0b3e789a6145066b to your computer and use it in GitHub Desktop.
Save joel16/97925b58cd37cb0d0b3e789a6145066b to your computer and use it in GitHub Desktop.
sceOpenPSIDGetProductCode impl
// Structs and comments taken from uOFW's chkreg pull request #91 https://github.com/uofw/uofw/pull/91
s32 sceIdStorageLookup(u16 key, u32 offset, void *pBuf, u32 len);
/**
* This structure contains console specific information. It is a subset of the ::SceConsoleId.
* Check <openpsid_kernel.h> for possible member values.
*/
typedef struct {
/* Company code. Set to 1. */
u16 companyCode; // 0
/* Product code. */
u16 productCode; // 2
/* Product sub code. */
u16 productSubCode; // 4
/* Factory code. */
u16 factoryCode; // 6
} ScePsCode; // size = 8
/**
* This structure represents a unique per-console identifier. It contains console specific information and can be used,
* for example, for DRM purposes and simple PSP hardware model checks.
*
* @remark On the PSP, Sony uses the term "PSID" (not to mixup with the term "OpenPSID" which represents a different set of
* unique identifier bits). On later consoles, like the PS Vita and PS4, Sony uses the term "ConsoleId" for this set of
* identifier bits. To be consistent within the PS family, we are going with the term "ConsoleId" here, even though APIs like
* sceOpenPSIDGetPSID() (which returns the ConsoleId) will remain as originally named by Sony.
*/
typedef struct {
/* Unknown. On retail set to 0. */
u16 unk0; // 0
/* Company code. Set to 1. */
u16 companyCode; // 2
/* Product code. */
u16 productCode; // 4
/* Product sub code. */
u16 productSubCode; // 6
/* Upper two bit of PsFlags. */
u8 psFlagsMajor : 2; // 8
/* Factory code. */
u8 factoryCode : 6; // 8
u8 uniqueIdMajor : 2; // 9
/* Lower six bit of the PsFlags. Contain the QA flag, if set. */
u8 psFlagsMinor : 6; // 9
u8 uniqueIdMinor[6]; // 10
} SceConsoleId; // size = 16
/*
* This structure contains the ConsoleId (termed "PSID" on the PSP) and an ECDSA signature used to verify the correctness of the
* ConsoleId.
* The ConsoleId is used, for example, in PSN DRM, DNAS and system configuration (with its derived PSCode).
*/
typedef struct {
/* Unique per-console identifier. */
SceConsoleId consoleId; // 0
/* Contains the public key of the certificate. No padding. */
u8 plantextPublicKey[0x28]; // 16
/* The 'r' part of the ECDSA signature pair (r, s). */
u8 r[0x14]; // 56
/* The 's' part of the ECDSA signature pair (r, s). */
u8 s[0x14]; // 76
/* The ECDSA public key (can be used to verify ECDSA signature rs). */
u8 publicKey[0x28]; // 96
/* Contains the encrypted private key of the certificate (with padding). */
u8 encPrivateKey[0x20]; // 136
/* Hash of previous data. */
u8 hash[0x10]; // 168
} SceIdStorageConsoleIdCertificate; // size = 184
SceUID g_semaId; //0x00004540
SceIdStorageConsoleIdCertificate g_ConsoleIdCertificate;
// Subroutine sub_000001C4 - Address 0x000001C4
s32 sceOpenPSIDLookupAndVerifyConsoleIdCertificate(void)
{
s32 ret = 0;
/* Obtain a ConsoleId certificate. TODO: Use include/idstorage.h for these values once chkreg gets merged */
ret = sceIdStorageLookup(0x100, 0x38, &g_ConsoleIdCertificate, KIRK_CERT_LEN);
if (ret < 0) {
ret = sceIdStorageLookup(0x120, 0x38, &g_ConsoleIdCertificate, KIRK_CERT_LEN);
if (ret < 0) {
return 0xC0520002;
}
}
ret = sceUtilsBufferCopyWithRange(NULL, 0, (u8 *)&g_ConsoleIdCertificate, KIRK_CERT_LEN, KIRK_CMD_CERT_VER);
if (ret != 0) {
return 0xC0520001;
}
return 0;
}
// Subroutine sceOpenPSID_B29330DE - Address 0x00000580
s32 sceOpenPSIDGetProductCode(ScePsCode *pPsCode)
{
s32 status1;
s32 status2;
status1 = 0x80000023;
if (pspK1StaBufOk(pPsCode, 2) >= 0) {
status1 = 0x80000041;
/* Allow only one access at a time. */
status2 = sceKernelWaitSema(g_semaId, 1, NULL);
if (status2 == 0) {
if (((status1 = sceOpenPSIDLookupAndVerifyConsoleIdCertificate()) == 0)) {
pPsCode->productCode = g_ConsoleIdCertificate.consoleId.productCode;
}
/* Release acquired sema resource. */
status2 = sceKernelSignalSema(g_semaId, 1);
if (status2 != 0) {
status1 = 0x80000041;
}
}
}
return status1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment