Secure Modules Functions: Difference between revisions
CelesteBlue (talk | contribs) |
|||
(309 intermediate revisions by 8 users not shown) | |||
Line 1: | Line 1: | ||
Depending on the | Depending on the [[Secure_Modules|Secure Modules]] that is currently loaded, different commands are handled. | ||
== Request Buffer == | == Request Buffer == | ||
Each request that is made sends a page aligned buffer that has a max size of a page. After as 64 byte header common to all commands, the data afterwards is specific to each command. The documentation for each command below specifies the data that goes after the header. The special command id of -1 (<code>0xFFFFFFFF</code>) is used to | Each request that is made sends a page aligned buffer that has a max size of a page. After as 64 byte header common to all commands, the data afterwards is specific to each command. The documentation for each command below specifies the data that goes after the header. The special command id of -1 (<code>0xFFFFFFFF</code>) is used to stop the current loaded [[Secure_Modules|Secure Module]]. | ||
{| class= | Command buffer structure (as seen on FWs 3.60-3.73): | ||
{| class='wikitable' | |||
|- | |- | ||
! Offset | ! Offset | ||
! Size | |||
! Description | |||
|- | |- | ||
| 0x0 | | 0x0 | ||
| 0x4 | |||
| Size of the structure (header + data) | |||
|- | |- | ||
| 0x4 | | 0x4 | ||
| 0x4 | |||
| Command ID | |||
|- | |- | ||
| 0x8 | | 0x8 | ||
| 0x4 | |||
| Command return value is written here by the SM | |||
|- | |- | ||
| 0xC || | | 0xC | ||
| 0x4 | |||
| unk2 | |||
|- | |- | ||
| | | 0x10 | ||
| 0x30 | |||
| padding | |||
|- | |- | ||
| 0x40 | |||
| variable, chosen by NS Kernel, max=0x1000-0x40 | |||
| data buffer | |||
|} | |} | ||
On FW 0.931, and maybe in later prototype FWs, the data buffer is located at offset 0x10 instead of 0x40. Thus we can wonder why has been added the 0x30 bytes padding. | |||
A common format used in these requests is a list of | === Physical Address Vector === | ||
A common format used in these requests is the Physical Address Vector which is a list of Physical Address Ranges. The simple structure of Physical Address Range is defined below. See [[SceSysmem#sceKernelVARangeToPARangeForDriver|sceKernelVARangeToPARangeForDriver]] for information on creating this vector. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 32: | Line 51: | ||
|- | |- | ||
| 0x4 || 0x4 || Size | | 0x4 || 0x4 || Size | ||
|} | |} | ||
This data format is used when passing large buffers of data to | This data format is used when passing large buffers of data to [[CMeP]]. The reason is that the memory manager in kernel could allocate contiguous virtual addresses that corresponds to varying physical addresses. | ||
== kprx_auth_sm.self == | == kprx_auth_sm.self == | ||
[[Kprx auth sm]] is a special SM stored in the [[SLB2]] partition. The raw (encrypted) SELF is stored in ARM [[TrustZone]] memory. It is placed there by an early bootloader. | |||
kprx_auth_sm is used to decrypt SELF and SPSFO files for ARM. The CF header is passed into a page aligned buffer and a [[#Physical Address Vector|PA vector]] is generated from it. | |||
=== 0x10001 === | === 0x10001 - sceSblAuthMgrAuthHeader === | ||
Used by [[SceSblAuthMgr#sceSblAuthMgrAuthHeaderForKernel|sceSblAuthMgrAuthHeaderForKernel]]. | |||
Checks the SELF header for decryption. The header is copied to the cmep private memory region first (on FW 1.69 with 0x1000 sized header, it is at <code>0x00811CC0</code> in cmep memory space. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x130 || [[SceSblSsSmComm#Types|SceSblSmCommContext130]] | ||
|- | |- | ||
| | | 0x130 || 0x4 || Number of PA vector entries for buffer | ||
|- | |- | ||
| | | 0x134 || 0x4 || Physical address of PA vector | ||
|} | |||
=== 0x20001 - sceSblAuthMgrSetupAuthSegment === | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrSetupAuthSegmentForKernel|sceSblAuthMgrSetupAuthSegmentForKernel]]. | |||
Set the program segment to decrypt. This corresponds to the segment index in the ELF program headers in the SELF header passed in with the command above. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || Segment number | ||
|- | |- | ||
| | | 0x4 || 0x4 || Return value. <code>1</code> if not compressed, <code>2</code> if compressed. | ||
|- | |- | ||
| | | 0x8 || 0x8 || Unknown | ||
|} | |||
=== 0x30001 - sceSblAuthMgrLoadBlock === | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrAuthSegmentForKernel|sceSblAuthMgrAuthSegmentForKernel]]. | |||
Decrypt a buffer from the SELF corresponding to the program segment number passed in above. The segment is read in <code>0x10000</code> bytes chunks and is decrypted in place (the input buffer will contain the decrypted data). A [[Secure Modules Functions#Physical Address Vector|PA vector]] is generated from the buffer. The input buffer and output buffer can be the same. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || Number of entries in input PA vector | ||
|- | |- | ||
| | | 0x4 || 0x4 || Physical address of the input PA vector | ||
|- | |- | ||
| | | 0x8 || 0x4 || Number of entries in output PA vector | ||
|- | |- | ||
| | | 0xC || 0x4 || Physical address of the output PA vector | ||
|} | |||
=== 0x40001 - sceSblAuthMgrGetEKc === | |||
Decrypts provided buffer in AES ECB mode using one of three keys (NPDRM keys ?). | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrGetEKcForDriver|sceSblAuthMgrGetEKcForDriver]] for getting klicensee. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x100 || Data Buffer | ||
|- | |- | ||
| | | 0x100 || 0x4 || Data Size. Max value is 0x100. | ||
|- | |- | ||
| | | 0x104 || 0x4 || Key ID. Must be 0, 1 or 2. | ||
|- | |- | ||
| | | 0x108 || 0x4 || Set to 0 | ||
|- | |- | ||
| 0x10C || 0x4 || Set to 0 | |||
|} | |} | ||
=== | === 0x50001 - sceSblAuthMgrSetDmac5Key === | ||
Used by [[SceSblAuthMgr#sceSblAuthMgrSetDmac5KeyForKernel|sceSblAuthMgrSetDmac5KeyForKernel]] to set a key in DMAC5 keyring for decryption. | |||
{| class="wikitable | This SM function uses AES128ECB or AES128CBC and hardcoded AES keys and IVs to encrypt the provided key into the final DMAC5 key. Then it writes the final DMAC5 key into the chosen [[DMAC#DMAC5|Dmac5]] keyring. | ||
Input/output size is 0x110 bytes. Buffer is untouched by the SM function as it makes an internal copy. | |||
{| class="wikitable" | |||
|- | |- | ||
! | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x20 || Key. Key that will be encrypted with kprx_auth_sm hardcoded keys and written to DMAC5 keyring. | ||
|- | |- | ||
| | | 0x20 || 0xE0 || Reserved. | ||
|- | |- | ||
| | | 0x100 || 0x4 || Key size (in bytes). Usually 0x10 or 0x20 bytes. Not used in kprx_auth_sm function 0x60001 as it entirely clears selected 0x20 bytes DMAC5 keyring. | ||
|- | |- | ||
| | | 0x104 || 0x4 || Mode. Affects both AES mode (ECB or CBC), AES key and IV and data size (0x10 or 0x20 bytes). Possible values: 0 (aes128ecb on 0x10 bytes), 0x10000 (aes128ecb on 0x10 bytes), 0x10001 (aes128ecb on 0x10 bytes, requires QA flag 0xF mask 1), 0x20000 (aes128cbc on 0x10 bytes), 0x20001 (aes128cbc on 0x20 bytes). | ||
|- | |- | ||
| | | 0x108 || 0x4 || Destination DMAC5 Keyring ID. Possible values: 0-0x1A, 0x1C-0x1F. 0x1B is forbidden by kprx_auth_sm for unknown reason. | ||
|- | |- | ||
| | | 0x10C || 0x4 || Unused. Key size & 0xF. Should be 0. | ||
|} | |||
=== 0x60001 - sceSblAuthMgrClearDmac5Key === | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrClearDmac5KeyForKernel|sceSblAuthMgrClearDmac5KeyForKernel]] to clear the Dmac5 Key. | |||
This function writes zeroes into the chosen [[DMAC#DMAC5|DMAC5]] keyring. | |||
Input/output size is 0x110 bytes. Buffer is untouched by the SM function as it makes an internal copy. | |||
It has exactly same structure as kprx_auth_sm function 0x50001 and is parsed in the same kprx_auth_sm subroutine function. | |||
=== 0x70001 - sceSblAuthMgrDecBindData === | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]] and [[SceNpDrm]] for gamecard binding data used in conjunction with the RIF license file on the gamecard for deriving the klicensee. | |||
Input/output size is 0x18 bytes. Buffer is untouched by the SM function as it makes an internal copy, however encrypted bind data at specified physical address will be decrypted after SM function execution. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x8 || Bind data PA Range. Must be 0x40-byte aligned and of maximum length 0x1000 bytes. | ||
|- | |- | ||
| | | 0x8 || 0x8 || Seed PA Range. Must be 0x40-byte aligned and of maximum length 0x1000 bytes. | ||
|- | |- | ||
| | | 0x10 || 0x4 || HMAC-SHA256 Key revision. Only revision 0 is supported on FW 3.60. | ||
|- | |- | ||
| | | 0x14 || 0x4 || Unknown. Must be zero on FW 3.60. | ||
|} | |||
Algorithm: | |||
* Compute HMAC-SHA256 of seed. It gives a 0x20-byte digest. | |||
* First 0x10 bytes of the digest make the AES128CBC key and last 0x10 bytes make the AES128CBC IV. | |||
* AES128CBC decrypt bind data. | |||
=== 0x80001 - sceSblAuthMgrVerifySpsfo === | |||
Used by [[SceSblAuthMgr#sceSblAuthMgrVerifySpsfoForDriver|sceSblAuthMgrVerifySpsfoForDriver]]. | |||
== applier_sm.self == | |||
applier_sm is used to decrypt and even encrypt SELFs for ARM. It is only present in some old prototype System Software builds like 0.931.010. | |||
=== 0x10001 - sceSblApplierSmOpen === | |||
=== 0x20001 - sceSblApplierSmClose === | |||
=== 0x30001 - sceSblApplierSmSetupSegment === | |||
=== 0x40007 - sceSblApplierSmDecryptSegment === | |||
=== 0x50007 - sceSblApplierSmEncryptSegment === | |||
=== 0x60007 - sceSblApplierSmVerifySegment === | |||
== act_sm.self == | |||
=== 0x1 - check_activation_code_1 === | |||
Removed on FW 2.10. | |||
Checks SceKitActivationData read from sd0:/act.dat. | |||
Uses different keys (AES256CBC and AES256CMAC) than check_activation_code_2. | |||
Used only on TOOL rev 3. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x80 || Input: [[SceSblSsMgr|SceKitActivationData]] | ||
|} | |||
=== 0x2 - check_activation_code_2 === | |||
Removed on FW 2.10. | |||
Checks SceKitActivationData read from sd0:VITA.ACT. | |||
Uses different keys (AES256CBC and AES256CMAC) than check_activation_code_1. | |||
Used on any Kit other than TOOL rev 3 (uses command 1), TEST, TOOL rev 4, Manufacturing Mode and QA flagged (bypasses activation). | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x80 || Input: [[SceSblSsMgr|SceKitActivationData]] | ||
|} | |||
=== 0x4 - check_nvs_cmac === | |||
Not present on FW 0.931. | |||
Checks NVS activation data authenticity using CMAC. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x20 || Input: [[SceSblSsMgr|SceNVSKitActivationData]] | |||
|} | |} | ||
=== | === 0x5 - gen_nvs_cmac === | ||
Removed on FW 2.10. | |||
Generate CMAC of NVS activation data. The returned data is written to NVS at offset 0x520 or 0x530. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 157: | Line 272: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Magic "act\0" | ||
|- | |- | ||
| | | 0x4 || 0x4 || Issue number | ||
|- | |- | ||
| | | 0x8 || 0x4 || Start validity time unix timestamp | ||
|- | |- | ||
| 0xC || 0x4 || End validity time unix timestamp | |||
|- | |||
| 0x10 || 0x10 || Output: CMAC of the 0x10 input bytes | |||
|} | |} | ||
=== | === 0x7 === | ||
Removed on FW 2.10. | |||
Check if activation is valid. The input activation data is read from NVS at offset 0x520. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 173: | Line 293: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x10 || [[SceSblSsMgr|SceNVSKitActivationData]] without CMAC | ||
| | |||
|- | |- | ||
| 0x10 || 0x20 || [[SceSblSsMgr|SceNVSKitActivationData]] | |||
|} | |} | ||
=== | === 0xA - gen_activation_with_sig === | ||
Introduced in FW 2.10. | |||
Check if new activation is valid. Extended activation check with a signature. This is ran when installing a new afv. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 192: | Line 308: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x80 || Input: [[SceSblSsMgr#|SceKitActivationData]] (new activation data) | ||
|- | |- | ||
| | | 0x80 || 0x100 || Input: RSA signature over new activation data | ||
|- | |- | ||
| | | 0x180 || 0x80 || Input: [[SceSblSsMgr|SceKitActivationData]] (previous activation data) | ||
|- | |- | ||
| | | 0x200 || 0x100 || Input: RSA signature over previous activation data | ||
|- | |- | ||
| 0x300 || 0x20 || Output: [[SceSblSsMgr|SceNVSKitActivationData]] | |||
|} | |} | ||
=== | === 0xB - check_activation_with_sig === | ||
This | Introduced in FW 2.10. | ||
Check if Kit Activation Data is valid and not expired. Extended activation check with signature. This command is ran on boot. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 213: | Line 329: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Input: Previous return value | ||
|- | |- | ||
| | | 0x4 || 0x4 || Input: Current time | ||
|- | |- | ||
| | | 0x8 || 0x4 || Output: License Status | ||
|- | |- | ||
| | | 0xC || 0x4 || Output: Expire Date | ||
|- | |- | ||
| | | 0x10 || 0x8 || Reserved | ||
|- | |- | ||
| 0x18 || 0x20 || Input: [[SceSblSsMgr|SceNVSKitActivationData]] (read from NVS offset 0x520) | |||
|- | |||
| 0x38 || 0x80 || Input: [[SceSblSsMgr|SceKitActivationData]] (read from tm0:activate/act.dat) | |||
|- | |||
| 0xB8 || 0x100 || Input: RSA signature over activation data (read from tm0:activate/actsig.dat) | |||
|} | |} | ||
=== | == aimgr_sm.self == | ||
Used | |||
=== 0x1 - GetConsoleId === | |||
Returns the console's [[ConsoleId]]. | |||
Used in [[SceSblSsMgr#sceSblAimgrGetConsoleIdForDriver|sceSblAimgrGetConsoleIdForDriver]]. | |||
=== 0x2 - GetOpenPsId === | |||
Returns the console's [[OpenPsId]]. | |||
Used in [[SceSblSsMgr#sceSblAimgrGetOpenPsIdForDriver|sceSblAimgrGetOpenPsIdForDriver]]. | |||
=== 0x3 - GetVisibleId === | |||
Returns the console's [[VisibleId]]. | |||
Used in [[SceSblSsMgr#sceSblAimgrGetVisibleIdForDriver|sceSblAimgrGetVisibleIdForDriver]]. | |||
=== 0x4 - GetPsCode === | |||
Returns the console's [[PsCode]]. | |||
Used in [[SceSblSsMgr#sceSblAimgrGetPscode2ForDriver|sceSblAimgrGetPscode2ForDriver]]. | |||
Used | |||
=== | === 0x5 - CreatePassPhrase === | ||
Creates NP passphrase (per-console and per NP account). | |||
Used in [[SceSblSsMgr#sceSblSsCreatePassPhraseForDriver|sceSblSsCreatePassPhraseForDriver]]. | |||
Input size is 0x220 bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 244: | Line 384: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x8 || Secure Tick | ||
|- | |- | ||
| | | 0x8 || 0x4 || Unknown. Maybe version or reserved. ex: 0. | ||
|- | |- | ||
| | | 0xC || 0x4 || Arguments size in usermode (0x18 bytes) | ||
|- | |- | ||
| | | 0x10 || 0x10 || NP Account ID in ASCII | ||
|- | |- | ||
| | | 0x10 || 0x200 || IdStorage leaf 0x44 (contains PS Vita IDPS Certificate) | ||
|} | |||
Output size is 0x220 bytes. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x8 || Secure Tick | ||
|- | |- | ||
| | | 0x8 || 0x4 || Unknown. Maybe version or reserved. ex: 0. | ||
|- | |- | ||
| | | 0xC || 0x4 || Arguments size in usermode (0x18 bytes) | ||
|- | |- | ||
| 0x10 || 0x10 || NP Account ID in ASCII | |||
|- | |||
| 0x20 || 0x200 || NP PassPhrase | |||
|} | |} | ||
== | == compat_sm.self == | ||
Compat SM functions only works on DEX and CEX units, or on units in Manufacturing Mode or with a certain QA Flag. This is why most DevKit units don't have access to PSPEmu. | |||
=== 0x10006 - sceCompatSecLoadSCBootCode === | |||
Load Secure CPU Boot Code. PSP main CPU (Tachyon codename) is an Allegrex 32-bit little-endian RISC CPU with FPU and VFPU, 1 ~ 333MHz, MIPS III-based. | |||
Called on init and before resume of PSP. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 272: | Line 426: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Boot/resume cookie. Pass 0 when cold booting, <code>resume_handler ^ magic</code> when resuming | ||
|- | |||
| 0x4 || 0x4 || Set to 0 (unused) | |||
|} | |||
On FW 3.73 (simplified): | |||
<source lang="C"> | |||
*(u32 *)SceSonyRegbus_e8000004 = 4; | |||
syncm(); | |||
memcpy(SceCompatSharedSram_e8100000, g_pre_ipl, 0x1000); // PRE-IPL | |||
memcpy(SceCompatSharedSram_e8100fc0, g_challenge, 0x40); // Challenge (IPL XOR key) | |||
memcpy(SceCompatSharedSram_e8100fbc, &cookie, 4); // Boot/resume cookie | |||
syncm(); | |||
*(u32 *)SceSonyRegbus_e8000004 = 0; | |||
</source> | |||
If an error occurs during SCBootCode loading: | |||
<source lang="c"> | |||
memset(SceCompatSharedSram_e8100000, 0, 0x1000); // PRE-IPL | |||
syncm(); | |||
*(u32 *)SceSonyRegbus_e8000004 = 10; | |||
</source> | |||
The cookie, which represents the address where PRE-IPL will jump to when resuming, is passed by MIPS to ARM (written to <code>0xBFC001FC</code>) just before suspending, and it is calculated the same way as [https://github.com/mathieulh/Utopia_PSP/blob/master/371_main.bin.c#L409 on actual PSP], only that using <source lang="c">u8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0xde, 0xf0 };</source> as input to the SHA1, instead of the MAC address. | |||
=== 0x20006 - sceCompatSecSetSSRAMAcl === | |||
Set Shared Static Random Access Memory Access-control list. | |||
Removed since FW 3.50 and replaced by command 0x30006. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || Set to 0 | ||
|- | |- | ||
| | | 0x4 || 0x4 || Set to 0 | ||
|} | |||
=== 0x30006 - sceCompatSecSetSSRAMAcl2 === | |||
Set Shared Static Random Access Memory Access-control list 2. | |||
Appeared on FW 3.50 as replacement for command 0x20006. This change is related to the huge memory management improvement since FW 3.50. See [https://www.neogaf.com/threads/ps-vita-system-software-3-50-adds-30-more-memory-for-game-use.1028194/ PS Vita System software 3.50 adds 30% more memory for game use]. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x4 || Unused | |||
|} | |} | ||
=== | On 3.73-CEX (simplified): | ||
<source lang="c"> | |||
*(u32 *)SceSonyRegbus_e8000004 = 4; | |||
syncm(); | |||
ret = memcmp(SceCompatSharedSram_e8100fc0, g_challenge_result, 0x40); // Check challenge output | |||
if (ret == 0) { | |||
// Success!! | |||
} | |||
syncm(); | |||
*(u32 *)SceSonyRegbus_e8000004 = 10; | |||
</source> | |||
== encdec_w_portability_sm.self == | |||
This seems to be used to do some kind of key derivation. May also be used as a general purpose encryption engine. | |||
=== 0x1000A - EncryptWithPortability === | |||
Encrypt data. Actually it always returns <code>0x800F1725</code>, so it does nothing and is never used. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 292: | Line 505: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Key ID (max 0xA) | ||
|- | |- | ||
| | | 0x4 || 0x4 || Output Length | ||
|- | |- | ||
| | | 0x8 || 0x20 || Output | ||
|- | |- | ||
| | | 0x28 || 0x4 || Input Length (max 0x20) | ||
|- | |- | ||
| | | 0x2C || 0x20 || Input | ||
|- | |- | ||
| 0x4C || 0x10 || IV | |||
|} | |} | ||
=== | === 0x2000A - DecryptWithPortability === | ||
Used by [[SceSblSsMgr#sceSblSsDecryptWithPortabilityForDriver|sceSblSsDecryptWithPortabilityForDriver]]. | |||
Decrypt data by using AES-256-CBC with an internal key selected by <code>key_id</code>. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 312: | Line 528: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Key ID (1 - 20) | ||
|- | |||
| 0x4 || 0x4 || Input Length (max 0x20) | |||
|- | |- | ||
| | | 0x8 || 0x20 || Input | ||
|- | |- | ||
| | | 0x28 || 0x4 || Output Length (must match Input Length) | ||
|- | |- | ||
| | | 0x2C || 0x20 || Output | ||
|- | |- | ||
| 0x4C || 0x10 || IV | |||
|} | |} | ||
=== | Return value of 0x800f0002 means invalid service ID. For encdec_w_portability_sm, only commmands 0x1000A and 0x2000A are supported. | ||
Return value of 0x800f1716 means invalid argument such as invalid key ID. Valid key IDs are only 1-20. | |||
== gcauthmgr_sm.self == | |||
=== 0x1000B === | |||
Execute KIRK services. | |||
This is one of the variable sized buffers that can be placed inside [[#Request_Buffer|Request_Buffer]]. | |||
Response value returned to Kernel comes from [[#Request_Buffer|Request Buffer]] at offset 8. | |||
<source lang="C"> | |||
// gc_param is generated by game card and has value 0x01 | |||
typedef struct SceSblSmCommGcData { // size is 0x814 | |||
int unk_0; // 1 | |||
int command; | |||
char data[0x800]; | |||
int key_id; | |||
int size; | |||
int unk_810; // 0 | |||
} SceSblSmCommGcData; | |||
</source> | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 330: | Line 571: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Set to 1 | ||
|- | |- | ||
| | | 0x4 || 0x4 || Command (0x4, 0x7, 0xC etc.) | ||
|- | |- | ||
| | | 0x8 || 0x800 || Data Buffer (Input/Output) | ||
|- | |- | ||
| | | 0x808 || 0x4 || Key ID (different meaning for different commands. usually used to select one of specific static keys) | ||
|- | |- | ||
| | | 0x80C || 0x4 || Data Buffer Length - Input/Written - Output | ||
|- | |- | ||
| 0x810 || 0x4 || Set to 0 | |||
|} | |} | ||
=== | Following are the supported Kirk services. | ||
==== 0x4 - encrypt_with_portability ==== | |||
Original PSP Kirk 4 service for encrypting data. | |||
Does not use any specific data structure in <code>Data Buffer</code>. | |||
Just encrypts data located in <code>Data Buffer</code>. | |||
Uses one set of keys. | |||
Available <code>Key ID</code> values are (key is encrypted with key from keyring 0x345 and put into keyring 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83. | |||
Special <code>Key ID</code> 0x100 is available. Uses keys from keyrings 0x601 and 0x602. | |||
Key 0x601 is scrambled and used as seed. | |||
Key 0x602 is scrambled and used as key. | |||
Seed is aes cbc encrypted with key to produce resulting key. | |||
==== 0x7 - decrypt_with_portability ==== | |||
Original PSP Kirk 7 service for decrypting data. | |||
Does not use any specific data structure in <code>Data Buffer</code>. | |||
Just decrypts data located in <code>Data Buffer</code>. | |||
Uses two sets of keys. | |||
Available key ids are (key is encrypted with key from keyring 0x345 and put into keyring 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83. | |||
Available <code>Key ID</code> values are (key is encrypted with key from keyring 0x340 and put into keyring 0x10): 0x44, 0x53, 0x57, 0x63, 0x64, 0x68, 0xC0, 0xC1, 0xC2, 0xC3. | |||
Special <code>Key ID</code> 0x100 is available. Uses keys from keyrings 0x601 and 0x602 (will be documented later). | |||
Key 0x601 is scrambled and used as seed. | |||
Key 0x602 is scrambled and used as key. | |||
Seed is aes cbc encrypted with key to produce resulting key. | |||
==== 0xC - ecc160_generate_keys ==== | |||
Original PSP Kirk 0xC service for Generating a 160bit ECC private/public keypair. Call with an empty buffer of length 0x3C. The structure below is the return structure. | |||
Private key <code>dA</code> is obtained by: | |||
1. Generating 0x40 sized random number rng. | |||
2. dA = rng mod N | |||
Public key <code>Qa</code> us obtained by: | |||
Qa = dA * G | |||
Output: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x14 || Private Key | ||
|- | |- | ||
| | | 0x14 || 0x14 || Public Key X component | ||
|- | |- | ||
| | | 0x28 || 0x14 || Public Key Y component | ||
|} | |||
==== 0xD - ecc160_multiply ==== | |||
Original PSP Kirk 0xD service for multiplying a 160bit ECC curve point with a value. Call with a multiplier, x and y point value. | |||
Input: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x14 || Multiplier Value | ||
|- | |- | ||
| | | 0x14 || 0x14 || Point X component | ||
|- | |- | ||
| | | 0x28 || 0x14 || Point Y component | ||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x14 || New Point X component | |||
|- | |||
| 0x14 || 0x14 || New Point Y component | |||
|} | |} | ||
== | ==== 0xE - ecc160_prngen ==== | ||
Original PSP Kirk 0xE service for 160bit Random number generation. Call with an empty buffer. | |||
{| class="wikitable" | |||
|- | |||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x14 || Output: Pseudo Random Number | |||
|} | |||
=== | ==== 0x10 - ecc160_sig_gen ==== | ||
Original PSP Kirk 0x10 service for 160bit ECC signing. | |||
Specific <code>nonce</code> is used for signing. | |||
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp). | |||
<code>nonce</code> is obtained by: | |||
1. Generating 0x40 sized random number rng. | |||
2. nonce = rng mod N | |||
= | Input: | ||
{| class="wikitable" | |||
|- | |||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x20 || Encrypted private key | |||
|- | |||
| 0x20 || 0x14 || SHA1 hash of the content to sign | |||
|} | |||
Output: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x14 || ECC Signature R component | ||
|- | |- | ||
| 0x14 || 0x14 || ECC Signature S component | |||
|} | |} | ||
=== | ==== 0x11 - ecc160_sig_verify ==== | ||
Original PSP Kirk 0x11 service for 160bit ECC signature verification. Call with the below structure, then function will return pass or fail. | |||
Input size is 0x64 bytes. | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x14 || Public Key X component | ||
|- | |||
| 0x14 || 0x14 || Public Key Y component | |||
|- | |||
| 0x28 || 0x14 || SHA1 hash of the signed content | |||
|- | |- | ||
| | | 0x3C || 0x14 || ECC Signature R component | ||
|- | |- | ||
| 0x50 || 0x14 || ECC Signature S component | |||
|} | |} | ||
== | No output. | ||
This | |||
==== 0x12 - cert_verify ==== | |||
This function checks that CMAC of <code>Message</code> equals <code>Encrypted CMAC value</code>. | |||
CMAC value of <code>Message</code> is calculated using key from keyring 0x212. | |||
<code>Encrypted CMAC value</code> is decrypted using a key from keyring 0x0. | |||
Key in keyring 0x0 is derived using key from keyring 0x204 with static seed value. | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0xA8 || Message | ||
|- | |- | ||
| | | 0xA8 || 0x10 || Encrypted CMAC value | ||
|} | |||
==== 0x14 - ecc224_generate_keys ==== | |||
New Vita Kirk 0x14 service for generating a 224bit ECC private/public keypair. Call with an empty buffer of length 0x54. The structure below is the return structure. | |||
Private key <code>dA</code> is obtained by: | |||
1. Generating 0x40 sized random number rng. | |||
2. dA = rng mod N | |||
Public key <code>Qa</code> us obtained by: | |||
Qa = dA * G | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x1C || Private Key | ||
|- | |- | ||
| | | 0x1C || 0x1C || Public Key X component | ||
|- | |- | ||
| 0x38 || 0x1C || Public Key Y component | |||
|} | |} | ||
=== | ==== 0x15 - ecc224_multiply ==== | ||
New Vita Kirk 0x15 service for multiplying a 224bit ECC curve point with a value. Call with a multiplier, x and y point value. | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x1C || Multiplier Value | ||
|- | |- | ||
| | | 0x1C || 0x1C || Point X component | ||
|- | |||
| 0x38 || 0x1C || Point Y component | |||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x1C || New Point X component | ||
|- | |- | ||
| | | 0x1C || 0x1C || New Point Y component | ||
|} | |||
==== 0x16 - ecc224_prngen ==== | |||
New Vita Kirk 0x16 service for 224bit Random number generation. Call with an empty buffer. | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x1C || Output: Pseudo Random Number | |||
|} | |} | ||
==== 0x17 - ecc224_sig_gen ==== | |||
New Vita Kirk 0x17 service for 224bit ECC signing. | |||
Specific <code>nonce</code> is used for signing. | |||
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp). | |||
<code>nonce</code> is obtained by: | |||
1. Generating 0x40 sized random number rng. | |||
= | 2. nonce = rng mod N | ||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x20 || Encrypted private key | ||
|- | |- | ||
| | | 0x20 || 0x1C || SHA224 hash of the content you want signed | ||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x1C || ECC Signature R component | ||
|- | |- | ||
| 0x1C || 0x1C || ECC Signature S component | |||
|} | |} | ||
==== 0x18 - ecc224_sig_verify ==== | |||
New Vita Kirk 0x18 service for 224bit ECDSA signature verification. Call with the below structure, then function will return pass or fail. | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| 0x0|| | | 0x0 || 0x1C || Public Key X component | ||
|- | |- | ||
| | | 0x1C || 0x1C || Public Key Y component | ||
|- | |- | ||
| | | 0x38 || 0x1C || SHA224 hash of the content that is signed | ||
|- | |- | ||
| | | 0x54 || 0x1C || ECC Signature R component | ||
|- | |- | ||
| | | 0x70 || 0x1C || ECC Signature S component | ||
|} | |||
==== 0x19 - cert_verify_new ==== | |||
This function checks that CMAC of <code>Message</code> equals <code>Encrypted CMAC value</code>. | |||
CMAC value of <code>Message</code> is calculated using key from keyring 0x212. | |||
<code>Encrypted CMAC value</code> is decrypted using a key from keyring 0x0. | |||
Key in keyring 0x0 is derived using key from keyring 0x204 with static seed value. | |||
This function is used to verify PS Vita new IdStorage Certificates. | |||
Input: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0xE8 || Input: Certificate | |||
|} | |} | ||
==== | ==== 0x1B - check_gc_authenticity ==== | ||
New Vita Kirk 0x1B service. This service is related to SceSdif and is used by SceSblGcAuthMgr. | |||
This service is part of SD MMC CMD56 custom initialization protocol. | |||
This is a data validation service with no response. Size of request is 0x53. | |||
- packet 7 should contain challenge0 for the card that can be encrypted (by card) with key_id and master_key. | |||
- packet 8 should contain encrypted message which can be decrypted (by vita) with key_id and master_key. | |||
- part of message should be card_challenge0. | |||
- another part of the message should be equal to challenge0. | |||
- this way we know that card knows how to properly encrypt. | |||
- Kirk service 1B will decrypt packet 8 with key_id and master_key | |||
- then it will verify challenge0 | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 515: | Line 930: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| | | 0x20 || 0x10 || cmd56 packet7 chunk | ||
|- | |- | ||
| | | 0x30 || 0x23 || cmd56 packet8 chunk | ||
|} | |||
==== 0x1C - generate_vita_authenticity_proof ==== | |||
New Vita Kirk 0x1C service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. | |||
This is a data generation service. Size of request is 0x40. Size of response is 0x33. | |||
- Kirk service 1C will generate packet 9 | |||
- it will decrypt packet 8 to retrieve challenge0 and card_challenge0 | |||
- then challenge0 and card_challenge0 will be tweaked | |||
- then it will generate secondary_key0 | |||
- then packet 9 will be encrypted with key_id and master_key | |||
- packet 9 should contain encrypted message which can be decrypted (by card) with key_id and master_key. | |||
- message should have secondary_key0, tweaked challenge0 and tweaked card_challenge0. | |||
- this way card will know that we know how to properly encrypt the data and we know the layout of the data because we tweak and reorder certain fields. | |||
Request: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| 0x20 || 0x20 || cmd56 packet8 chunk | |||
|} | |} | ||
Response: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x01 || command | ||
|- | |- | ||
| | | 0x01 || 0x01 || unknown | ||
|- | |- | ||
| | | 0x02 || 0x01 || size | ||
|- | |- | ||
| 0x03 || 0x30 || packet 9 chunk | |||
|} | |} | ||
==== | ==== 0x1D - challenge_handshake ==== | ||
New Vita Kirk 0x1D service. This service is related to SceSdif and is used by SceSblGcAuthMgr. | |||
This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service with no response. Size of request is 0xA3. | |||
- packet 13 should contain challenge1 for the card that can be encrypted (by card) with key_id and master_key. | |||
- packet 14 should contain challenge1 and master_key that are encrypted (by card) with key_id and master_key. | |||
- Kirk service 0x1D will decrypt secondary_key0 from packet 9 with key_id and master_key | |||
- then it will decrypt packet 14 | |||
- then it will verify challenge1 in packet 13 against decrypted packet 14 | |||
- then it will verify master_key in packet 6 against decrypted packet 14 | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 551: | Line 1,003: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| | | 0x20 || 0x30 || cmd56 packet9 chunk | ||
|- | |- | ||
| | | 0x50 || 0x10 || cmd56 packet13 chunk | ||
|- | |- | ||
| 0x60 || 0x43 || cmd56 packet14 chunk | |||
|} | |} | ||
==== 0x1E - generate_packets_15_17_with_cmac_signature ==== | |||
New Vita Kirk 0x1E service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x51. Size of response is 0x33. | |||
- Kirk service 0x1E will generate packet 15 | |||
- it will decrypt secondary_key0 from packet 9 with key_id and master_key | |||
- then it will generate secondary_key1 | |||
- then it will create a buffer with tweaked secondary_key1 and tweak_padding | |||
- then it will encrypt the buffer using secondary_key0 | |||
- then it will create cmd56 input like buffer with encrypted buffer | |||
- then it will calculate cmac of cmd56 like buffer using secondary_key0 | |||
- encrypted buffer and cmac will be the resulting data of packet 15 | |||
Request: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| | | 0x20 || 0x30 || cmd56 packet9 chunk | ||
|- | |- | ||
| 0x50 || 0x01 || parameter (value 2 or 3) | |||
|} | |} | ||
Response: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x01 || command | ||
|- | |||
| 0x01 || 0x01 || unknown | |||
|- | |||
| 0x02 || 0x01 || size | |||
|- | |- | ||
| 0x03 || 0x30 || packet 15/17 chunk | |||
|} | |} | ||
==== | ==== 0x1F - decrypt_packet_16 ==== | ||
New Vita Kirk 0x1F service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service. Size of request is 0xB3. Size of response is 0x20. | |||
- Kirk service 0x1E will decrypt secondary_key0 from packet 9 with key_id and master_key | |||
- then it will combine data from packet 16 into a cmd56 like buffer | |||
- then it will calculate cmac of that cmd56 like buffer using secondary_key0 | |||
- then it will verify calculated cmac against cmac from packet 16 | |||
- then it will decrypt secondary_key1 and tweak_padding from packet 15 | |||
- then it will decrypt secondary_key1 and unknown data from packet 16 | |||
- then it will verify decrypted secondary_key1 from packet 15 against decrypted secondary_key1 from packet 16 | |||
- then it will verify that decrypted tweak_padding from packet 15 is properly tweaked | |||
- then it will return unknown decrypted data from packet 16 | |||
Request: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| 0x20|| | | 0x20 || 0x30 || cmd56 packet9 chunk | ||
|- | |- | ||
| 0x50 || 0x20 || cmd56 packet15 chunk | |||
|- | |||
| 0x70 || 0x43 || cmd56 packet16 chunk | |||
|} | |} | ||
Response: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || decrypted packet16 chunk | ||
|} | |} | ||
==== | ==== 0x20 - get_hash_from_gamecard_packets ==== | ||
New PS Vita Kirk 0x20 service. This service is related to [[SceSdif]] and is used by [[SceSblGcAuthMgr]]. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x116 bytes. Size of response is 0x34 bytes. | |||
Generated data is used to obtain [[SceNpDrm#Obtaining_klicensee|klicensee]] using [[SceSblAuthMgr#sceSblAuthMgrDecBindDataForDriver|sceSblAuthMgrDecBindDataForDriver]]. | |||
Request: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || cmd56 packet6 chunk | ||
|- | |- | ||
| | | 0x20 || 0x30 || cmd56 packet9 chunk | ||
|- | |- | ||
| | | 0x50 || 0x20 || cmd56 packet17 chunk | ||
|- | |- | ||
| | | 0x70 || 0x43 || cmd56 packet18 chunk | ||
|- | |- | ||
| | | 0xB3 || 0x10 || cmd56 packet19 chunk | ||
|- | |- | ||
| 0xC3 || 0x53 || cmd56 packet20 chunk | |||
|} | |} | ||
Response: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x00 || 0x20 || SHA-256 digest of a 0x40 bytes buffer. Used to obtain [[SceNpDrm#Obtaining_klicensee|klicensee]]. | ||
|- | |- | ||
| 0x20 || 0x14 || SHA-1 digest of a 0x20 bytes buffer. Checked to be identical to [[SceNpDrm#RIF|RIF file]] at offset 0xE0. | |||
|} | |} | ||
==== | ==== 0x21 - ecc160_hmac_sha256_sig_gen ==== | ||
New Vita Kirk 0x21 service for 160bit ECC signing. | |||
Specific <code>nonce</code> is used for signing. | |||
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp). | |||
<code>nonce</code> is obtained by: | |||
1. Generating 0x40 sized seed which is derived from message hash and static private key using hmac256 and sha256. | |||
2. nonce = seed mod N | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| 0x0|| | | 0x0 || 0x20 || unknown, must be zeroes | ||
|- | |||
| 0x20 || 0x14 || Message hash | |||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x14 || ECC Signature R component | ||
|- | |- | ||
| 0x14 || 0x14 || ECC Signature S component | |||
|} | |} | ||
==== | ==== 0x22 - ecc224_sceebootpbp_sig_gen ==== | ||
New Vita Kirk | |||
New Vita Kirk 0x22 service for 224bit ECC signing. | |||
Specific <code>nonce</code> is used for signing. | |||
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp). | |||
<code>nonce</code> is obtained by: | |||
1. Generating 0x40 sized seed which is derived from message hash and one of two static private keys using hmac256 and sha256. Key can be selected with key id 0 or 1. | |||
Private key 0 is only used for signing __sceebootpbp files for firmware versions before 1.8X, otherwise private key 1 is used for signing __sceebootpbp. | |||
2. nonce = seed mod N | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| 0x0|| | | 0x0 || 0x20 || unknown, must be zeroes | ||
|- | |- | ||
| 0x1C|| | | 0x20 || 0x1C || message hash | ||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x1C || ECC Signature R component | |||
|- | |||
| 0x1C || 0x1C || ECC Signature S component | |||
|} | |} | ||
==== 0x23 - generate_cmac_signature ==== | |||
New Vita Kirk 0x23 service. | |||
It encrypts the plain message with AES128CBC, static key and null IV, then calculates the AES128CMAC of the encrypted message with another static key. | |||
Input: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| 0x0|| | | 0x0 || 0x10 || Plain message | ||
|} | |||
Output: | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x10 || Encrypted message | |||
|- | |||
| 0x10 || 0x10 || Encrypted message CMAC | |||
|} | |} | ||
==== | == pm_sm.self == | ||
[[SceSblPostSsMgr#sceSblPmMgrAuthEtoIForDriver|sceSblPmMgrAuthEtoIForDriver]] uses "sd0:sm/pm_sm_sd.self" whilst other PmSm functions use "os0:sm/pm_sm.self". | |||
Services 8, 9 and 0xA appeared on FW 1.03 (maybe 1.00). They are not present on FW 0.990 and earlier. | |||
Keyset must be between 0-12 on FW 0.931. Keyset 14 is present on FWs 3.600.011-3.740.011. | |||
=== 0x1 - get_product_mode === | |||
Used by sceSblPmMgrGetProductModeFromNVS. | |||
Data size is 0x28 bytes. | |||
Input: 0x20 buffer read from NVS at offset 0. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x4 || Output: Product Mode | |||
|- | |- | ||
| | | 0x4 || 0x4 || Reserved | ||
|- | |- | ||
| 0x8 || 0x20 || Input: NVS block read at offset 0 | |||
|} | |} | ||
==== | === 0x2 - set_product_mode === | ||
Used by sceSblPmMgrSetProductMode. | |||
Data size is 0x28 bytes. | |||
Input: 0x20 bytes buffer read from NVS at offset 0, to which is written the new product mode to set. | |||
Output data: 0x20 buffer to write to NVS at offset 0. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Input: Product Mode | ||
|- | |- | ||
| | | 0x4 || 0x4 || Reserved | ||
|- | |- | ||
| 0x8 || 0x20 || Input and output: NVS block read/written at offset 0 | |||
|} | |} | ||
=== | === 0x3 - gen_req_hello === | ||
This command gets the Ernie secure packet for the first JIG auth command. | |||
Data size is 0x30 bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Input: keyset (6, 14) | ||
|- | |- | ||
| | | 0x4 || 0x4 || Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) | ||
|- | |- | ||
| 0x8 || 0x28 || Output: Ernie secure packet | |||
|} | |} | ||
=== 0x4 - gen_challenge === | |||
Data size is 0x30 bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | |||
|- | |- | ||
| 0x0 || 0x4 || Input: keyset (6, 14) | |||
|- | |- | ||
| | | 0x4 || 0x4 || Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) | ||
|- | |- | ||
| | | 0x8 || 0x28 || Input and output: Ernie secure packet | ||
|} | |||
=== 0x5 - check_response === | |||
Returns 0 on success. | |||
Data size is 0x30 bytes. | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || input: keyset (6, 14) | ||
|- | |- | ||
| | | 0x4 || 0x4 || input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) | ||
|- | |- | ||
| 0x8 || 0x28 || input: Ernie secure packet | |||
|} | |} | ||
=== | === 0x6 - gen_req_result === | ||
Encrypts Ernie secure packet for step 4 with the chosen keyset. | |||
Data size is 0x30 bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Input: keyset (4, 6 on FW 0.931-3.60) | ||
|- | |- | ||
| | | 0x4 || 0x4 || Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) | ||
|- | |- | ||
| | | 0x8 || 0x28 || Input and output: Ernie secure packet | ||
|} | |||
=== 0x7 - check_result === | |||
Returns 0 on success. | |||
Data size is 0x30 bytes. | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || Input: keyset (4, 6, 14) | ||
|- | |- | ||
| 0x4 || 0x4 || Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) | |||
|- | |||
| 0x8 || 0x28 || Input: Ernie secure packet | |||
|} | |} | ||
=== | === 0x8 - run_pm_command === | ||
Not present in old FWs. | |||
Used on FW 1.03+ by sceSblPmMgrGetProductModeFromNVS. | |||
Data size is 0x70 bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x4 || Input: Command (0: gen_get_mgmt_data_req, 1: get_mgmt_data, 3: decrypt_response, 4: set_product_mode, 5: set_product_mode_off, 7: set_sd_mode_off) | |||
|- | |- | ||
| 0x4 || 0x4 || Reserved | |||
|- | |- | ||
| | | 0x8 || 0x4 || Input and output: product mode | ||
|- | |- | ||
| | | 0xC || 0x4 || Input and output: unknown Mgmt Data | ||
|- | |- | ||
| | | 0x10 || 0x30 || Input and output: Ernie secure packet for setting Product Mode | ||
|- | |- | ||
| 0x40 || 0x30 || Input and output: Ernie secure packet for getting Product mode | |||
|} | |} | ||
=== 0x9 - gen_jig_message === | |||
Only on FW 1.03+. | |||
Data size is 0x10C bytes. | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Input: keyset_flag (0x48 for keyset 4, 0x49 for keyset 12) | ||
|- | |- | ||
| | | 0x4 || 0x4 || Reserved | ||
|- | |- | ||
| | | 0x8 || 0x104 || Output: jig_message | ||
|} | |||
=== 0xA - check_jig_response === | |||
Only on FW 1.03+. | |||
Returns 0 on success. | |||
Data size is 0x10C bytes. | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |- | ||
| | | 0x0 || 0x4 || Input: keyset_flag (0x48 for keyset 4, 0x49 for keyset 12) | ||
|- | |- | ||
| 0x4 || 0x4 || Reserved | |||
|- | |||
| 0x8 || 0x104 || Input: jig_response | |||
|} | |} | ||
==== | == qaf_sm.self == | ||
=== 0x0 === | |||
Decrypt or check QAF Token. Used on 1.03 PDEL. | |||
=== 0x1 === | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Type !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || in || unk | ||
|- | |- | ||
| | | 0x4 || 0x4 || N/A || unk | ||
|- | |- | ||
| | | 0x8 || 0x4 || out || some data | ||
|- | |- | ||
| | | 0xC || 0x4 || out || some data | ||
|- | |- | ||
| 0x40 || 0x30 || in || Syscon secure packet data | |||
|} | |} | ||
=== 0x2 === | |||
=== 0x3 === | |||
=== 0x4 - decrypt_qafv === | |||
Input: 0x20 buffer read from NVS offset 0x2A0. | |||
Output: QAF version in this buffer of size 0x20: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Magic | ||
|- | |||
| 0x4 || 0x4 || QAF version | |||
|- | |||
| 0x8 || 0x8 || Reserved | |||
|- | |- | ||
| 0x10 || 0x10 || CMAC | |||
|} | |} | ||
=== | === 0x5 - encrypt_qafv === | ||
Input QAF version in this buffer of size 0x20: | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x4 || Magic | ||
|- | |- | ||
| | | 0x4 || 0x4 || QAF version | ||
|- | |- | ||
| | | 0x8 || 0x8 || Reserved | ||
|- | |- | ||
| | | 0x10 || 0x10 || CMAC | ||
|} | |||
Output of size 0x20 is then written to NVS offset 0x2A0. | |||
=== 0x6 - check_flag (decrypt) === | |||
Input: 0x20 buffer read from NVS at offset 0. | |||
Returns error if flag is bad, 0 on success. | |||
Output | |||
=== 0x7 - set_flag (encrypt) === | |||
Input: 0x20 buffer. | |||
Output: 0x20 encrypted buffer that can be written to NVS at offset 0. | |||
=== 0xC - check_qaftoken === | |||
{| class="wikitable" | |||
|- | |- | ||
! Offset !! Size !! Type !! Description | |||
|- | |- | ||
| | | 0x0 || 0x80 || in || Qa Flags token | ||
|- | |- | ||
| 0x80 || 0x100 || in || RSA signature | |||
|} | |} | ||
=== 0xD - get_qaftoken === | |||
{| class="wikitable" | {| class="wikitable" | ||
|- | |- | ||
! Offset !! Size !! Type !! Description | |||
|- | |||
| 0x0 || 0x80 || inout || Qa Flags token | |||
|- | |||
| 0x80 || 0x100 || in || RSA signature | |||
|} | |||
== rmauth_sm.self == | |||
Removable Media (Memory Card) authentication. Used by [[SceMsif]]. | |||
=== 0x1 - get_key_master_gen_no === | |||
Response (size 0x20 bytes): | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x10 || unknown | ||
|- | |- | ||
| 0x10 || 0x4 || Returned ID? | |||
|- | |||
| 0x14 || 0xC || unknown | |||
|} | |} | ||
==== | === 0x2 - set_index_key === | ||
Scrambles and sets the [[DMAC#DMAC5_Key_Ring|DMAC5 keyring 0x1C]] key. | |||
The scrambling process consists of encrypting the first and second halves of the key seed with a private internal (could be considered as a couple of 0x10 keys) <code>rmmauth_sm</code> key using AES128-CBC. | |||
= | Request (size 0x20 bytes): | ||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |||
| 0x00|| 0x20 || Key seed | |||
|} | |||
=== 0x3 === | === 0x3 === | ||
?clear_index_key? | |||
Clears the [[DMAC#DMAC5_Key_Ring|DMAC5 keyring 0x1C]] key (to 0). | |||
== | == spkg_verifier_sm_w_key_2.self == | ||
This is an extension of update_service_sm.self. It was added to support command 0xE0002. | |||
== | === 0xE0002 - sceSblUsSmAuthSpkgWithKey2 === | ||
Used to decrypt downloaded lists (SPKGs). Same format as [[#0x40002|0x40002]]. | |||
Lists URLS: | |||
<source> | |||
.list_0_version:0000000125.list_0_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_vita.dat | |||
.list_1_version:0000000111.list_1_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_emu.dat | |||
.list_2_version:0000000001.list_2_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_teleport.dat | |||
</source> | |||
== update_service_sm.self == | == update_service_sm.self == | ||
This is used by [[ | This is used by [[SceSblUpdateMgr]] to decrypt update packages extracted from [[PUP]] files. | ||
<s>Both 0x40002 and 0x50002 reference buffers in the following way: an inner PA vector is generated for the buffer containing the data to encrypt/decrypt, then an outer PA vector is generated for the inner list. That means that there are two levels of indirection in the PA vector.</s> | |||
Services with PA vectors to pass data to cmep decide whether to use normal vectors or deep vectors depending on the flag of the argument. | |||
=== 0x10002 - sceSblUsSmAuthPupHeader === | |||
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_HEADER. | |||
Checks PUP header (with hash check). | |||
Input data size: 0xFC0. | |||
Input: PA vector of the PUP header including the PUP Hash (size: 0x80 + segment_num * 0x20 + segment_num * 0x40 + 0x20) | |||
=== 0x20002 - sceSblUsSmAuthPupSegment === | |||
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_SEGMENT. | |||
Checks PUP segment HMAC-SHA256 hash. | |||
Input data size: 0xFC0. | |||
=== 0x30002 - sceSblUsSmAuthPupWatermark === | |||
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_WM. | |||
Decrypt | Checks PUP watermark. | ||
Input data size: 0xFC0. | |||
Input data: a packet embedding at least two physical addresses (?in a PA vector?): PUP Watermark (0x1000 bytes) and PUP Hash (0x20 bytes). | |||
=== 0x40002 - sceSblUsSmAuthSpkg === | |||
SCE_SBL_SM_COMM_FID_SM_AUTH_SPKG. | |||
Decrypt a SPKG. Allocate a page aligned buffer and read the complete SPKG file into the buffer. The buffer is decrypted in place. | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 917: | Line 1,609: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x8 || Set to 0x0 | ||
|- | |- | ||
| | | 0x8 || 0x8 || Set to 0x1 | ||
|- | |- | ||
| | | 0x10 || 0x14 || <code>struct paddr_list_req</code> for PA vector below | ||
|- | |- | ||
| | | 0x24 || 0x14 || <code>struct paddr_list_req</code> for pkg buffer | ||
|- | |- | ||
| 0x38 || Variable (max 0xF88(0x1F1 entry)) || Copy of PA vector for pkg buffer (contents described at 0x50) | |||
|} | |} | ||
=== 0x50002 === | === 0x50002 - sceSblUsSmEncryptIndividualSLSK === | ||
Re-encrypt enp files | SCE_SBL_SM_COMM_FID_SM_ENCIND_SLSK. | ||
Re-encrypt individual SLSK files (.enp files). | |||
{| class="wikitable" | {| class="wikitable" | ||
Line 937: | Line 1,630: | ||
! Offset !! Size !! Description | ! Offset !! Size !! Description | ||
|- | |- | ||
| | | 0x0 || 0x8 || Unknown/Zero | ||
|- | |- | ||
| | | 0x8 || 0x8 || Set to 1 | ||
|- | |- | ||
| | | 0x10 || 0x14 || <code>struct paddr_list_req</code> for PA vector copied to 0x78. Only count field is used. | ||
|- | |- | ||
| | | 0x24 || 0x14 || <code>struct paddr_list_req</code> for inner PA vector. Not used. | ||
|- | |- | ||
| 0x38 || Variable (max 0xF88(0x1F1 entry)) || Outer PA vector. PA vector to PA vector to encrypt. | |||
|} | |} | ||
== | Each inner PA vector is first copied to temporary cmep memory, then they all are checked for validity at once. Maximum size of inner PA vector is 0xFF7 (so probably 0xFF7 / 8 * 8 = 0xFF0). Any higher length results in <code>SCE_SBL_ERROR_SL_ENOMEM = 0x800F020C</code> error. | ||
=== | How it works: | ||
* first, all inner entries are checked for validity, if something is invalid, bail out <code>SCE_SBL_ERROR_SL_EINVAL 0x800f0216</code> | |||
* start at last outer entry and move towards the first | |||
* if current entry looks valid (length >= 8), proceed to inner physical address encryption | |||
* if no valid entries found, error=<code>SCE_SBL_ERROR_SL_EINVAL 0x800f0216</code> | |||
* if multiple valid entries found, error=<code>SCE_SBL_ERROR_SL_EIO 0x800f0205</code> (???) (but the first one found is always encrypted) | |||
* if only one valid entry is found, return success | |||
Bugs(?): | |||
* encrypting same physical address twice or more times within a single inner PA vector always results in same output, no matter what input was, reproducible with length=0x10 or less | |||
* sum(inner list sizes) must be <= 0xFF0, but there is no overflow check, a large inner list causes cmep to overwrite memory with data like: | |||
<pre> | |||
00:00:26 0 // this is physical address 0x1F000000 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 2000 | |||
00:00:26 8 | |||
00:00:26 812d40 | |||
00:00:26 0 | |||
00:00:26 1f000020 // this is physical address 0x1F00001C | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 2000 | |||
00:00:26 8 | |||
00:00:26 812d40 | |||
00:00:26 0 | |||
00:00:26 1f000040 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 2000 | |||
00:00:26 8 | |||
00:00:26 812d40 | |||
00:00:26 0 | |||
00:00:26 1f000060 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 0 | |||
00:00:26 2000 | |||
00:00:26 8 | |||
00:00:26 812d40 | |||
00:00:26 0 | |||
00:00:26 1f000080 | |||
</pre> | |||
=== 0x60002 - sceSblUsSmSnvsEncryptSectors === | |||
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_SECTORS. | |||
The input is plain SNVS sectors read from NVS. | |||
Calculates a XTS encrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 bytes in size, but the (size in cmep packet + 4) derives the XTS size and memcpy. | |||
The result is XTS encrypted SNVS sectors. | |||
Data size is (8 bytes + sectors size). | |||
<source lang="C"> | |||
typedef struct data { // size is variable, at least 0x28 bytes | |||
int sectors_index; // input: between 1 and 20 (SNVS sectors) | |||
int sectors_count; // input | |||
char sectors[0x20 * sectors_count]; // input: read from NVS. | |||
} data; | |||
</source> | |||
=== 0x70002 - sceSblUsSmSnvsDecryptSectors === | |||
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_SECTORS. | |||
The input is XTS encrypted sectors. | |||
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 in size, but the (size in cmep packet + 4) derives the XTS size and memcpy. | |||
The result is plain sectors. | |||
Data size is (8 bytes + sectors size). | |||
<source lang="C"> | |||
typedef struct data { // size is variable, at least 0x28 bytes | |||
int sectors_index; // input: between 1 and 20 (SNVS sectors) | |||
int sectors_count; // input | |||
char sectors[0x20 * sectors_count]; // input: read from NVS. | |||
} data; | |||
</source> | |||
=== 0x80002 - sceSblUsSmSnvsEncryptMgmtData === | |||
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_MGMT. | |||
The input are the new status and flags, and the current Mgmt Data sector read from NVS at offset 0. | |||
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in. If ok, then it uses the seed 0xACA9B1AC to recalculate the block, generate a new hmac, and xts encrypt the block. | |||
The result is a new Mgmt Data sector, which is to be written to NVS at offset 0. | |||
Data size is 0x28 bytes. | |||
<source lang="C"> | |||
typedef struct data { // size is 0x28 bytes | |||
int status; // input | |||
char flags[4]; // input | |||
char sector[0x20]; // input: read from NVS at offset 0. Likely to be 0x10 bytes of data followed by 0x10 bytes of HMAC. | |||
} data; | |||
</source> | |||
=== 0x90002 - sceSblUsSmSnvsDecryptMgmtData === | |||
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_MGMT. | |||
The input is the current Mgmt Data sector read from NVS at offset 0. | |||
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in. | |||
The result is the current status and flags. | |||
Data size is 0x28 bytes. | |||
<source lang="C"> | |||
typedef struct data { // size is 0x28 bytes | |||
int status; // output | |||
char flags[4]; // output | |||
char sector[0x20]; // input: read from NVS at offset 0. Likely to be 0x10 bytes of data followed by 0x10 bytes of HMAC. | |||
} data; | |||
</source> | |||
<source lang="C"> | |||
// SCE_SBL_SS_SNVS_FLAGS | |||
#define SCE_SBL_SS_SNVS_UPDATER_FLAG_INDEX 0 | |||
</source> | |||
If flags[SCE_SBL_SS_SNVS_UPDATER_FLAG_INDEX] is not set, updater init is skipped: | |||
<source lang="C"> | |||
if (((byte)flags & 1) == 0) | |||
sceKernelPrintfLevelForDriver(2, "skip init for updater\n"); | |||
else { | |||
sceKernelPrintfLevelForDriver(2, "do init for updater\n"); | |||
if (SpkgInfoUtilInitForUpdater(&status, &flags) != 0) | |||
sceKernelPrintfLevelForDriver(2,"SpkgInfoUtilInitForUpdater() failure = 0x%x\n",iVar2); | |||
} | |||
</source> | |||
=== 0xA0002 - sceSblUsSmAuthAdditionalSign === | |||
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_AS. | |||
Checks PUP Additional Signatures. | |||
=== 0xB0002 - sceSblUsSmSnvsEncryptDecryptSector === | |||
Added on FW 1.03. Usage similar to pm_sm command 8. | |||
Data size is 0x88 bytes. | |||
<source lang="C"> | |||
typedef struct data { // size is 0x88 | |||
uint mode; // 0 before read, 1 after read, 2 before write, 3 after write | |||
uint sector_index; // between 1 and 20 (SNVS sectors) | |||
char base_buf[0x20]; // input: full of 0xdeadbeef | |||
char inter_buf[0x30]; // output: input for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver | |||
char final_buf[0x30]; // input: output for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver | |||
} data; | |||
</source> | |||
Usage: | |||
* 1) sceSblSmCommCallFunc(id, 0xB0002, &response, data, 0x88); | |||
For read: | |||
* 2) sceSysconSnvsReadDataForDriver(data + 0x28, 0x10, data + 0x58, 0x30); | |||
For write: | |||
* 2) sceSysconSnvsWriteDataForDriver(data + 0x28, 0x30, data + 0x58, 0x10); | |||
* 3) sceSblSmCommCallFunc(id, 0xB0002, &response, data, 0x88); | |||
=== 0xC0002 - sceSblUsSmSnvsEncryptDecryptMgmtData === | |||
Added on FW 1.03. Usage similar to pm_sm command 8. | |||
Data size is 0x70 bytes. | |||
<source lang="C"> | |||
typedef struct data { // Size is 0x70 bytes on FW 3.60 | |||
int mode; // ex: 0 before read, 1 after read, 2 before write, 3 after write | |||
int sector_count; // always 0 (Mgmt Data) | |||
int status; // not set for read, set for write | |||
int flags; // not set for read, set for write | |||
char unk_10[0x30]; // output: input for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver | |||
char unk_40[0x30]; // input: output for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver | |||
} data; | |||
</source> | |||
Usage: | |||
* 1) sceSblSmCommCallFunc(id, 0xC0002, &response, data, 0x70); | |||
For write: | |||
* 2) sceSysconSnvsWriteDataForDriver(data + 0x10, 0x30, data + 0x40, 0x10); | |||
For read: | |||
* 2) sceSysconSnvsReadDataForDriver(data + 0x10, 0x10, data + 0x40, 0x30); | |||
* 3) sceSblSmCommCallFunc(id, 0xC0002, &response, data, 0x70); | |||
=== 0xD0002 === | === 0xD0002 === | ||
Syscon update related. Usage is to proxy encrypted data cmep <=> Syscon. | |||
Data size is 0x58 bytes. | |||
<source lang="C"> | |||
typedef struct data { // Size is 0x58 bytes on FW 3.60 | |||
int mode; // ex: 0, 1, 2, 3, 4 | |||
int unk_4; // Maybe unused | |||
char unk_8[0x28]; // input: syscon command 0xD2 output | |||
char unk_30[0x28]; // output: syscon command 0xD2 input | |||
} data; | |||
</source> | |||
Usage: | |||
* 1) sceSblSmCommCallFunc(id, 0xD0002, &response, data, 0x58); | |||
For modes 0, 1 and 3: | |||
* 2) memcpy(data + 8, data + 0x30, 0x28); SceSysconForDriver_4D03754A(data + 8, 0x28, data + 0x30, 0x28); // Calls Syscon command 0xD0. | |||
* 3) sceSblSmCommCallFunc(id, 0xD0002, &response, data, 0x58); | |||
Mode: | |||
* 0 - Do init 0x28 buffer. | |||
* 1 - Do Bigmac unknown crypto with some blob. | |||
* 2 - Do Bigmac unknown crypto with some blob. | |||
* 3 - Do Bigmac unknown crypto with some blob. | |||
* 4 - Do some working. And reset Syscon ticket count with Bigmac PRNG (keyring 0x512). | |||
== utoken_sm.self == | == utoken_sm.self == | ||
=== 0x1 === | === 0x1 - check_utoken === | ||
=== 0x2 === | |||
Checks [[SceSblPostSsMgr#Types|SceUtoken]] buffer. | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x4 || Physical address of [[SceSblPostSsMgr#Types|SceUtoken]] buffer | |||
|- | |||
| 0x4 || 0x4 || Size of [[SceSblPostSsMgr#Types|SceUtoken]] buffer (usually 0x800) | |||
|- | |||
| 0x8 || 0x4 || Time (got using [[SceRtc#sceRtcGetCurrentSecureTickForDriver|sceRtcGetCurrentSecureTickForDriver]] or 0xFFFFFFFF (-1) | |||
|- | |||
| 0xC || 0x10 || [[OpenPsId]] | |||
|} | |||
=== 0x2 - decrypt_utoken === | |||
Decrypt [[SceSblPostSsMgr#Types|SceUtoken]] buffer, in order to get UT Flags. | |||
{| class="wikitable" | |||
! Offset !! Size !! Description | |||
|- | |||
| 0x0 || 0x4 || Physical address of [[SceSblPostSsMgr#Types|SceUtoken]] buffer | |||
|- | |||
| 0x4 || 0x4 || Size of [[SceSblPostSsMgr#Types|SceUtoken]] buffer (usually 0x800) | |||
|- | |||
| 0x8 || 0x4 || Time (got using [[SceRtc#sceRtcGetCurrentSecureTickForDriver|sceRtcGetCurrentSecureTickForDriver]] or 0xFFFFFFFF (-1)) | |||
|- | |||
| 0xC || 0x10 || [[OpenPsId]] | |||
|} | |||
== mgkm_sm.self == | == mgkm_sm.self == | ||
=== 0x1 === | Magic Gate Key Manager secure module. | ||
=== 0x2 === | |||
Present on 0.931-3.73. Commands are almost the same on any FW, only KEY_31 varies. | |||
0 | |||
These commands are used to set keys (as seen on FWs from 0.940 to 3.60) to [[DMAC#DMAC5||DMAC5]] registers in NS memory. These keys are used in to do encryption stuff with AES-ECB and TripleDES-ECB algorithms through [[DMAC#DMAC5||DMAC5]]. | |||
On FW 0.940, commands 1 and 2 are only called by SceSblMgKeyMgrForDriver_1C5388D0 which consists of: | |||
<source lang="C"> | |||
int SceSblMgKeyMgrForDriver_1C5388D0(void *in, void *out) { | |||
int ret; | |||
uint8_t tmp_buffer[16]; | |||
ret = call_cmd_1(); | |||
if ((ret == 0) && (ret = call_cmd_2(), ret == 0)) { | |||
aesECBDec16B(in, tmp_buffer, 0x1E); | |||
aesECBEnc16B(tmp_buffer, out, 0x1F); | |||
} | |||
return ret; | |||
} | |||
</source> | |||
=== 0x1 - set_key_31 === | |||
<source lang="C"> | |||
memset(buffer, 0, 0x20); | |||
memcpy(buffer, KEY_31, 0x10); | |||
bigmac_memcpy(0xE04E0000 + 0x1F * 0x20, buffer, 0x20); | |||
</source> | |||
=== 0x2 - set_key_30 === | |||
<source lang="C"> | |||
memset(buffer, 0, 0x20); | |||
memcpy(buffer, pOpenPsId, 0x10); | |||
memcpy(buffer + 0x10, KEY_30_SEED, 0x10); | |||
bigmac_sha256(buffer, buffer, 0x20); | |||
bigmac_memcpy(0xE04E0000 + 0x1E * 0x20, buffer, 0x20); | |||
</source> | |||
=== 0x3 - unset_key_31 === | |||
<source lang="C"> | |||
memset(buffer, 0, 0x20); | |||
bigmac_memcpy(0xE04E0000 + 0x1F * 0x20, buffer, 0x20); | |||
</source> | |||
=== 0x4 - unset_key_30 === | |||
<source lang="C"> | |||
memset(buffer, 0, 0x20); | |||
bigmac_memcpy(0xE04E0000 + 0x1E * 0x20, buffer, 0x20); | |||
</source> | |||
[[Category: | [[Category:Cmep]] | ||
[[Category:Library]] |
Latest revision as of 21:55, 10 January 2024
Depending on the Secure Modules that is currently loaded, different commands are handled.
Request Buffer
Each request that is made sends a page aligned buffer that has a max size of a page. After as 64 byte header common to all commands, the data afterwards is specific to each command. The documentation for each command below specifies the data that goes after the header. The special command id of -1 (0xFFFFFFFF
) is used to stop the current loaded Secure Module.
Command buffer structure (as seen on FWs 3.60-3.73):
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Size of the structure (header + data) |
0x4 | 0x4 | Command ID |
0x8 | 0x4 | Command return value is written here by the SM |
0xC | 0x4 | unk2 |
0x10 | 0x30 | padding |
0x40 | variable, chosen by NS Kernel, max=0x1000-0x40 | data buffer |
On FW 0.931, and maybe in later prototype FWs, the data buffer is located at offset 0x10 instead of 0x40. Thus we can wonder why has been added the 0x30 bytes padding.
Physical Address Vector
A common format used in these requests is the Physical Address Vector which is a list of Physical Address Ranges. The simple structure of Physical Address Range is defined below. See sceKernelVARangeToPARangeForDriver for information on creating this vector.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Physical Address |
0x4 | 0x4 | Size |
This data format is used when passing large buffers of data to CMeP. The reason is that the memory manager in kernel could allocate contiguous virtual addresses that corresponds to varying physical addresses.
kprx_auth_sm.self
Kprx auth sm is a special SM stored in the SLB2 partition. The raw (encrypted) SELF is stored in ARM TrustZone memory. It is placed there by an early bootloader.
kprx_auth_sm is used to decrypt SELF and SPSFO files for ARM. The CF header is passed into a page aligned buffer and a PA vector is generated from it.
0x10001 - sceSblAuthMgrAuthHeader
Used by sceSblAuthMgrAuthHeaderForKernel.
Checks the SELF header for decryption. The header is copied to the cmep private memory region first (on FW 1.69 with 0x1000 sized header, it is at 0x00811CC0
in cmep memory space.
Offset | Size | Description |
---|---|---|
0x0 | 0x130 | SceSblSmCommContext130 |
0x130 | 0x4 | Number of PA vector entries for buffer |
0x134 | 0x4 | Physical address of PA vector |
0x20001 - sceSblAuthMgrSetupAuthSegment
Used by sceSblAuthMgrSetupAuthSegmentForKernel.
Set the program segment to decrypt. This corresponds to the segment index in the ELF program headers in the SELF header passed in with the command above.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Segment number |
0x4 | 0x4 | Return value. 1 if not compressed, 2 if compressed.
|
0x8 | 0x8 | Unknown |
0x30001 - sceSblAuthMgrLoadBlock
Used by sceSblAuthMgrAuthSegmentForKernel.
Decrypt a buffer from the SELF corresponding to the program segment number passed in above. The segment is read in 0x10000
bytes chunks and is decrypted in place (the input buffer will contain the decrypted data). A PA vector is generated from the buffer. The input buffer and output buffer can be the same.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Number of entries in input PA vector |
0x4 | 0x4 | Physical address of the input PA vector |
0x8 | 0x4 | Number of entries in output PA vector |
0xC | 0x4 | Physical address of the output PA vector |
0x40001 - sceSblAuthMgrGetEKc
Decrypts provided buffer in AES ECB mode using one of three keys (NPDRM keys ?).
Used by sceSblAuthMgrGetEKcForDriver for getting klicensee.
Offset | Size | Description |
---|---|---|
0x0 | 0x100 | Data Buffer |
0x100 | 0x4 | Data Size. Max value is 0x100. |
0x104 | 0x4 | Key ID. Must be 0, 1 or 2. |
0x108 | 0x4 | Set to 0 |
0x10C | 0x4 | Set to 0 |
0x50001 - sceSblAuthMgrSetDmac5Key
Used by sceSblAuthMgrSetDmac5KeyForKernel to set a key in DMAC5 keyring for decryption.
This SM function uses AES128ECB or AES128CBC and hardcoded AES keys and IVs to encrypt the provided key into the final DMAC5 key. Then it writes the final DMAC5 key into the chosen Dmac5 keyring.
Input/output size is 0x110 bytes. Buffer is untouched by the SM function as it makes an internal copy.
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | Key. Key that will be encrypted with kprx_auth_sm hardcoded keys and written to DMAC5 keyring. |
0x20 | 0xE0 | Reserved. |
0x100 | 0x4 | Key size (in bytes). Usually 0x10 or 0x20 bytes. Not used in kprx_auth_sm function 0x60001 as it entirely clears selected 0x20 bytes DMAC5 keyring. |
0x104 | 0x4 | Mode. Affects both AES mode (ECB or CBC), AES key and IV and data size (0x10 or 0x20 bytes). Possible values: 0 (aes128ecb on 0x10 bytes), 0x10000 (aes128ecb on 0x10 bytes), 0x10001 (aes128ecb on 0x10 bytes, requires QA flag 0xF mask 1), 0x20000 (aes128cbc on 0x10 bytes), 0x20001 (aes128cbc on 0x20 bytes). |
0x108 | 0x4 | Destination DMAC5 Keyring ID. Possible values: 0-0x1A, 0x1C-0x1F. 0x1B is forbidden by kprx_auth_sm for unknown reason. |
0x10C | 0x4 | Unused. Key size & 0xF. Should be 0. |
0x60001 - sceSblAuthMgrClearDmac5Key
Used by sceSblAuthMgrClearDmac5KeyForKernel to clear the Dmac5 Key.
This function writes zeroes into the chosen DMAC5 keyring.
Input/output size is 0x110 bytes. Buffer is untouched by the SM function as it makes an internal copy.
It has exactly same structure as kprx_auth_sm function 0x50001 and is parsed in the same kprx_auth_sm subroutine function.
0x70001 - sceSblAuthMgrDecBindData
Used by sceSblAuthMgrDecBindDataForDriver and SceNpDrm for gamecard binding data used in conjunction with the RIF license file on the gamecard for deriving the klicensee.
Input/output size is 0x18 bytes. Buffer is untouched by the SM function as it makes an internal copy, however encrypted bind data at specified physical address will be decrypted after SM function execution.
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Bind data PA Range. Must be 0x40-byte aligned and of maximum length 0x1000 bytes. |
0x8 | 0x8 | Seed PA Range. Must be 0x40-byte aligned and of maximum length 0x1000 bytes. |
0x10 | 0x4 | HMAC-SHA256 Key revision. Only revision 0 is supported on FW 3.60. |
0x14 | 0x4 | Unknown. Must be zero on FW 3.60. |
Algorithm:
- Compute HMAC-SHA256 of seed. It gives a 0x20-byte digest.
- First 0x10 bytes of the digest make the AES128CBC key and last 0x10 bytes make the AES128CBC IV.
- AES128CBC decrypt bind data.
0x80001 - sceSblAuthMgrVerifySpsfo
Used by sceSblAuthMgrVerifySpsfoForDriver.
applier_sm.self
applier_sm is used to decrypt and even encrypt SELFs for ARM. It is only present in some old prototype System Software builds like 0.931.010.
0x10001 - sceSblApplierSmOpen
0x20001 - sceSblApplierSmClose
0x30001 - sceSblApplierSmSetupSegment
0x40007 - sceSblApplierSmDecryptSegment
0x50007 - sceSblApplierSmEncryptSegment
0x60007 - sceSblApplierSmVerifySegment
act_sm.self
0x1 - check_activation_code_1
Removed on FW 2.10.
Checks SceKitActivationData read from sd0:/act.dat.
Uses different keys (AES256CBC and AES256CMAC) than check_activation_code_2.
Used only on TOOL rev 3.
Offset | Size | Description |
---|---|---|
0x0 | 0x80 | Input: SceKitActivationData |
0x2 - check_activation_code_2
Removed on FW 2.10.
Checks SceKitActivationData read from sd0:VITA.ACT.
Uses different keys (AES256CBC and AES256CMAC) than check_activation_code_1.
Used on any Kit other than TOOL rev 3 (uses command 1), TEST, TOOL rev 4, Manufacturing Mode and QA flagged (bypasses activation).
Offset | Size | Description |
---|---|---|
0x0 | 0x80 | Input: SceKitActivationData |
0x4 - check_nvs_cmac
Not present on FW 0.931.
Checks NVS activation data authenticity using CMAC.
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | Input: SceNVSKitActivationData |
0x5 - gen_nvs_cmac
Removed on FW 2.10.
Generate CMAC of NVS activation data. The returned data is written to NVS at offset 0x520 or 0x530.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Magic "act\0" |
0x4 | 0x4 | Issue number |
0x8 | 0x4 | Start validity time unix timestamp |
0xC | 0x4 | End validity time unix timestamp |
0x10 | 0x10 | Output: CMAC of the 0x10 input bytes |
0x7
Removed on FW 2.10.
Check if activation is valid. The input activation data is read from NVS at offset 0x520.
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | SceNVSKitActivationData without CMAC |
0x10 | 0x20 | SceNVSKitActivationData |
0xA - gen_activation_with_sig
Introduced in FW 2.10.
Check if new activation is valid. Extended activation check with a signature. This is ran when installing a new afv.
Offset | Size | Description |
---|---|---|
0x0 | 0x80 | Input: SceKitActivationData (new activation data) |
0x80 | 0x100 | Input: RSA signature over new activation data |
0x180 | 0x80 | Input: SceKitActivationData (previous activation data) |
0x200 | 0x100 | Input: RSA signature over previous activation data |
0x300 | 0x20 | Output: SceNVSKitActivationData |
0xB - check_activation_with_sig
Introduced in FW 2.10.
Check if Kit Activation Data is valid and not expired. Extended activation check with signature. This command is ran on boot.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: Previous return value |
0x4 | 0x4 | Input: Current time |
0x8 | 0x4 | Output: License Status |
0xC | 0x4 | Output: Expire Date |
0x10 | 0x8 | Reserved |
0x18 | 0x20 | Input: SceNVSKitActivationData (read from NVS offset 0x520) |
0x38 | 0x80 | Input: SceKitActivationData (read from tm0:activate/act.dat) |
0xB8 | 0x100 | Input: RSA signature over activation data (read from tm0:activate/actsig.dat) |
aimgr_sm.self
0x1 - GetConsoleId
Returns the console's ConsoleId.
Used in sceSblAimgrGetConsoleIdForDriver.
0x2 - GetOpenPsId
Returns the console's OpenPsId.
Used in sceSblAimgrGetOpenPsIdForDriver.
0x3 - GetVisibleId
Returns the console's VisibleId.
Used in sceSblAimgrGetVisibleIdForDriver.
0x4 - GetPsCode
Returns the console's PsCode.
Used in sceSblAimgrGetPscode2ForDriver.
0x5 - CreatePassPhrase
Creates NP passphrase (per-console and per NP account).
Used in sceSblSsCreatePassPhraseForDriver.
Input size is 0x220 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Secure Tick |
0x8 | 0x4 | Unknown. Maybe version or reserved. ex: 0. |
0xC | 0x4 | Arguments size in usermode (0x18 bytes) |
0x10 | 0x10 | NP Account ID in ASCII |
0x10 | 0x200 | IdStorage leaf 0x44 (contains PS Vita IDPS Certificate) |
Output size is 0x220 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Secure Tick |
0x8 | 0x4 | Unknown. Maybe version or reserved. ex: 0. |
0xC | 0x4 | Arguments size in usermode (0x18 bytes) |
0x10 | 0x10 | NP Account ID in ASCII |
0x20 | 0x200 | NP PassPhrase |
compat_sm.self
Compat SM functions only works on DEX and CEX units, or on units in Manufacturing Mode or with a certain QA Flag. This is why most DevKit units don't have access to PSPEmu.
0x10006 - sceCompatSecLoadSCBootCode
Load Secure CPU Boot Code. PSP main CPU (Tachyon codename) is an Allegrex 32-bit little-endian RISC CPU with FPU and VFPU, 1 ~ 333MHz, MIPS III-based.
Called on init and before resume of PSP.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Boot/resume cookie. Pass 0 when cold booting, resume_handler ^ magic when resuming
|
0x4 | 0x4 | Set to 0 (unused) |
On FW 3.73 (simplified):
*(u32 *)SceSonyRegbus_e8000004 = 4; syncm(); memcpy(SceCompatSharedSram_e8100000, g_pre_ipl, 0x1000); // PRE-IPL memcpy(SceCompatSharedSram_e8100fc0, g_challenge, 0x40); // Challenge (IPL XOR key) memcpy(SceCompatSharedSram_e8100fbc, &cookie, 4); // Boot/resume cookie syncm(); *(u32 *)SceSonyRegbus_e8000004 = 0;
If an error occurs during SCBootCode loading:
memset(SceCompatSharedSram_e8100000, 0, 0x1000); // PRE-IPL syncm(); *(u32 *)SceSonyRegbus_e8000004 = 10;
The cookie, which represents the address where PRE-IPL will jump to when resuming, is passed by MIPS to ARM (written to 0xBFC001FC
) just before suspending, and it is calculated the same way as on actual PSP, only that using
u8 data[] = { 0x12, 0x34, 0x56, 0x78, 0x9a, 0x00, 0xde, 0xf0 };
as input to the SHA1, instead of the MAC address.
0x20006 - sceCompatSecSetSSRAMAcl
Set Shared Static Random Access Memory Access-control list.
Removed since FW 3.50 and replaced by command 0x30006.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Set to 0 |
0x4 | 0x4 | Set to 0 |
0x30006 - sceCompatSecSetSSRAMAcl2
Set Shared Static Random Access Memory Access-control list 2.
Appeared on FW 3.50 as replacement for command 0x20006. This change is related to the huge memory management improvement since FW 3.50. See PS Vita System software 3.50 adds 30% more memory for game use.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Unused |
On 3.73-CEX (simplified):
*(u32 *)SceSonyRegbus_e8000004 = 4; syncm(); ret = memcmp(SceCompatSharedSram_e8100fc0, g_challenge_result, 0x40); // Check challenge output if (ret == 0) { // Success!! } syncm(); *(u32 *)SceSonyRegbus_e8000004 = 10;
encdec_w_portability_sm.self
This seems to be used to do some kind of key derivation. May also be used as a general purpose encryption engine.
0x1000A - EncryptWithPortability
Encrypt data. Actually it always returns 0x800F1725
, so it does nothing and is never used.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Key ID (max 0xA) |
0x4 | 0x4 | Output Length |
0x8 | 0x20 | Output |
0x28 | 0x4 | Input Length (max 0x20) |
0x2C | 0x20 | Input |
0x4C | 0x10 | IV |
0x2000A - DecryptWithPortability
Used by sceSblSsDecryptWithPortabilityForDriver.
Decrypt data by using AES-256-CBC with an internal key selected by key_id
.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Key ID (1 - 20) |
0x4 | 0x4 | Input Length (max 0x20) |
0x8 | 0x20 | Input |
0x28 | 0x4 | Output Length (must match Input Length) |
0x2C | 0x20 | Output |
0x4C | 0x10 | IV |
Return value of 0x800f0002 means invalid service ID. For encdec_w_portability_sm, only commmands 0x1000A and 0x2000A are supported.
Return value of 0x800f1716 means invalid argument such as invalid key ID. Valid key IDs are only 1-20.
gcauthmgr_sm.self
0x1000B
Execute KIRK services.
This is one of the variable sized buffers that can be placed inside Request_Buffer.
Response value returned to Kernel comes from Request Buffer at offset 8.
// gc_param is generated by game card and has value 0x01 typedef struct SceSblSmCommGcData { // size is 0x814 int unk_0; // 1 int command; char data[0x800]; int key_id; int size; int unk_810; // 0 } SceSblSmCommGcData;
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Set to 1 |
0x4 | 0x4 | Command (0x4, 0x7, 0xC etc.) |
0x8 | 0x800 | Data Buffer (Input/Output) |
0x808 | 0x4 | Key ID (different meaning for different commands. usually used to select one of specific static keys) |
0x80C | 0x4 | Data Buffer Length - Input/Written - Output |
0x810 | 0x4 | Set to 0 |
Following are the supported Kirk services.
0x4 - encrypt_with_portability
Original PSP Kirk 4 service for encrypting data.
Does not use any specific data structure in Data Buffer
.
Just encrypts data located in Data Buffer
.
Uses one set of keys.
Available Key ID
values are (key is encrypted with key from keyring 0x345 and put into keyring 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83.
Special Key ID
0x100 is available. Uses keys from keyrings 0x601 and 0x602.
Key 0x601 is scrambled and used as seed.
Key 0x602 is scrambled and used as key.
Seed is aes cbc encrypted with key to produce resulting key.
0x7 - decrypt_with_portability
Original PSP Kirk 7 service for decrypting data.
Does not use any specific data structure in Data Buffer
.
Just decrypts data located in Data Buffer
.
Uses two sets of keys.
Available key ids are (key is encrypted with key from keyring 0x345 and put into keyring 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83.
Available Key ID
values are (key is encrypted with key from keyring 0x340 and put into keyring 0x10): 0x44, 0x53, 0x57, 0x63, 0x64, 0x68, 0xC0, 0xC1, 0xC2, 0xC3.
Special Key ID
0x100 is available. Uses keys from keyrings 0x601 and 0x602 (will be documented later).
Key 0x601 is scrambled and used as seed.
Key 0x602 is scrambled and used as key.
Seed is aes cbc encrypted with key to produce resulting key.
0xC - ecc160_generate_keys
Original PSP Kirk 0xC service for Generating a 160bit ECC private/public keypair. Call with an empty buffer of length 0x3C. The structure below is the return structure.
Private key dA
is obtained by:
1. Generating 0x40 sized random number rng.
2. dA = rng mod N
Public key Qa
us obtained by:
Qa = dA * G
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | Private Key |
0x14 | 0x14 | Public Key X component |
0x28 | 0x14 | Public Key Y component |
0xD - ecc160_multiply
Original PSP Kirk 0xD service for multiplying a 160bit ECC curve point with a value. Call with a multiplier, x and y point value.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | Multiplier Value |
0x14 | 0x14 | Point X component |
0x28 | 0x14 | Point Y component |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | New Point X component |
0x14 | 0x14 | New Point Y component |
0xE - ecc160_prngen
Original PSP Kirk 0xE service for 160bit Random number generation. Call with an empty buffer.
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | Output: Pseudo Random Number |
0x10 - ecc160_sig_gen
Original PSP Kirk 0x10 service for 160bit ECC signing.
Specific nonce
is used for signing.
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).
nonce
is obtained by:
1. Generating 0x40 sized random number rng.
2. nonce = rng mod N
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | Encrypted private key |
0x20 | 0x14 | SHA1 hash of the content to sign |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | ECC Signature R component |
0x14 | 0x14 | ECC Signature S component |
0x11 - ecc160_sig_verify
Original PSP Kirk 0x11 service for 160bit ECC signature verification. Call with the below structure, then function will return pass or fail.
Input size is 0x64 bytes.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | Public Key X component |
0x14 | 0x14 | Public Key Y component |
0x28 | 0x14 | SHA1 hash of the signed content |
0x3C | 0x14 | ECC Signature R component |
0x50 | 0x14 | ECC Signature S component |
No output.
0x12 - cert_verify
This function checks that CMAC of Message
equals Encrypted CMAC value
.
CMAC value of Message
is calculated using key from keyring 0x212.
Encrypted CMAC value
is decrypted using a key from keyring 0x0.
Key in keyring 0x0 is derived using key from keyring 0x204 with static seed value.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0xA8 | Message |
0xA8 | 0x10 | Encrypted CMAC value |
0x14 - ecc224_generate_keys
New Vita Kirk 0x14 service for generating a 224bit ECC private/public keypair. Call with an empty buffer of length 0x54. The structure below is the return structure.
Private key dA
is obtained by:
1. Generating 0x40 sized random number rng.
2. dA = rng mod N
Public key Qa
us obtained by:
Qa = dA * G
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | Private Key |
0x1C | 0x1C | Public Key X component |
0x38 | 0x1C | Public Key Y component |
0x15 - ecc224_multiply
New Vita Kirk 0x15 service for multiplying a 224bit ECC curve point with a value. Call with a multiplier, x and y point value.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | Multiplier Value |
0x1C | 0x1C | Point X component |
0x38 | 0x1C | Point Y component |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | New Point X component |
0x1C | 0x1C | New Point Y component |
0x16 - ecc224_prngen
New Vita Kirk 0x16 service for 224bit Random number generation. Call with an empty buffer.
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | Output: Pseudo Random Number |
0x17 - ecc224_sig_gen
New Vita Kirk 0x17 service for 224bit ECC signing.
Specific nonce
is used for signing.
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).
nonce
is obtained by:
1. Generating 0x40 sized random number rng.
2. nonce = rng mod N
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | Encrypted private key |
0x20 | 0x1C | SHA224 hash of the content you want signed |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | ECC Signature R component |
0x1C | 0x1C | ECC Signature S component |
0x18 - ecc224_sig_verify
New Vita Kirk 0x18 service for 224bit ECDSA signature verification. Call with the below structure, then function will return pass or fail.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | Public Key X component |
0x1C | 0x1C | Public Key Y component |
0x38 | 0x1C | SHA224 hash of the content that is signed |
0x54 | 0x1C | ECC Signature R component |
0x70 | 0x1C | ECC Signature S component |
0x19 - cert_verify_new
This function checks that CMAC of Message
equals Encrypted CMAC value
.
CMAC value of Message
is calculated using key from keyring 0x212.
Encrypted CMAC value
is decrypted using a key from keyring 0x0.
Key in keyring 0x0 is derived using key from keyring 0x204 with static seed value.
This function is used to verify PS Vita new IdStorage Certificates.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0xE8 | Input: Certificate |
0x1B - check_gc_authenticity
New Vita Kirk 0x1B service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service with no response. Size of request is 0x53.
- packet 7 should contain challenge0 for the card that can be encrypted (by card) with key_id and master_key.
- packet 8 should contain encrypted message which can be decrypted (by vita) with key_id and master_key.
- part of message should be card_challenge0.
- another part of the message should be equal to challenge0.
- this way we know that card knows how to properly encrypt.
- Kirk service 1B will decrypt packet 8 with key_id and master_key
- then it will verify challenge0
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x10 | cmd56 packet7 chunk |
0x30 | 0x23 | cmd56 packet8 chunk |
0x1C - generate_vita_authenticity_proof
New Vita Kirk 0x1C service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x40. Size of response is 0x33.
- Kirk service 1C will generate packet 9
- it will decrypt packet 8 to retrieve challenge0 and card_challenge0
- then challenge0 and card_challenge0 will be tweaked
- then it will generate secondary_key0
- then packet 9 will be encrypted with key_id and master_key
- packet 9 should contain encrypted message which can be decrypted (by card) with key_id and master_key.
- message should have secondary_key0, tweaked challenge0 and tweaked card_challenge0.
- this way card will know that we know how to properly encrypt the data and we know the layout of the data because we tweak and reorder certain fields.
Request:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x20 | cmd56 packet8 chunk |
Response:
Offset | Size | Description |
---|---|---|
0x00 | 0x01 | command |
0x01 | 0x01 | unknown |
0x02 | 0x01 | size |
0x03 | 0x30 | packet 9 chunk |
0x1D - challenge_handshake
New Vita Kirk 0x1D service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service with no response. Size of request is 0xA3.
- packet 13 should contain challenge1 for the card that can be encrypted (by card) with key_id and master_key.
- packet 14 should contain challenge1 and master_key that are encrypted (by card) with key_id and master_key.
- Kirk service 0x1D will decrypt secondary_key0 from packet 9 with key_id and master_key
- then it will decrypt packet 14
- then it will verify challenge1 in packet 13 against decrypted packet 14
- then it will verify master_key in packet 6 against decrypted packet 14
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x30 | cmd56 packet9 chunk |
0x50 | 0x10 | cmd56 packet13 chunk |
0x60 | 0x43 | cmd56 packet14 chunk |
0x1E - generate_packets_15_17_with_cmac_signature
New Vita Kirk 0x1E service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x51. Size of response is 0x33.
- Kirk service 0x1E will generate packet 15
- it will decrypt secondary_key0 from packet 9 with key_id and master_key
- then it will generate secondary_key1
- then it will create a buffer with tweaked secondary_key1 and tweak_padding
- then it will encrypt the buffer using secondary_key0
- then it will create cmd56 input like buffer with encrypted buffer
- then it will calculate cmac of cmd56 like buffer using secondary_key0
- encrypted buffer and cmac will be the resulting data of packet 15
Request:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x30 | cmd56 packet9 chunk |
0x50 | 0x01 | parameter (value 2 or 3) |
Response:
Offset | Size | Description |
---|---|---|
0x00 | 0x01 | command |
0x01 | 0x01 | unknown |
0x02 | 0x01 | size |
0x03 | 0x30 | packet 15/17 chunk |
0x1F - decrypt_packet_16
New Vita Kirk 0x1F service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service. Size of request is 0xB3. Size of response is 0x20.
- Kirk service 0x1E will decrypt secondary_key0 from packet 9 with key_id and master_key
- then it will combine data from packet 16 into a cmd56 like buffer
- then it will calculate cmac of that cmd56 like buffer using secondary_key0
- then it will verify calculated cmac against cmac from packet 16
- then it will decrypt secondary_key1 and tweak_padding from packet 15
- then it will decrypt secondary_key1 and unknown data from packet 16
- then it will verify decrypted secondary_key1 from packet 15 against decrypted secondary_key1 from packet 16
- then it will verify that decrypted tweak_padding from packet 15 is properly tweaked
- then it will return unknown decrypted data from packet 16
Request:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x30 | cmd56 packet9 chunk |
0x50 | 0x20 | cmd56 packet15 chunk |
0x70 | 0x43 | cmd56 packet16 chunk |
Response:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | decrypted packet16 chunk |
0x20 - get_hash_from_gamecard_packets
New PS Vita Kirk 0x20 service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x116 bytes. Size of response is 0x34 bytes.
Generated data is used to obtain klicensee using sceSblAuthMgrDecBindDataForDriver.
Request:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | cmd56 packet6 chunk |
0x20 | 0x30 | cmd56 packet9 chunk |
0x50 | 0x20 | cmd56 packet17 chunk |
0x70 | 0x43 | cmd56 packet18 chunk |
0xB3 | 0x10 | cmd56 packet19 chunk |
0xC3 | 0x53 | cmd56 packet20 chunk |
Response:
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | SHA-256 digest of a 0x40 bytes buffer. Used to obtain klicensee. |
0x20 | 0x14 | SHA-1 digest of a 0x20 bytes buffer. Checked to be identical to RIF file at offset 0xE0. |
0x21 - ecc160_hmac_sha256_sig_gen
New Vita Kirk 0x21 service for 160bit ECC signing.
Specific nonce
is used for signing.
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).
nonce
is obtained by:
1. Generating 0x40 sized seed which is derived from message hash and static private key using hmac256 and sha256.
2. nonce = seed mod N
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | unknown, must be zeroes |
0x20 | 0x14 | Message hash |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x14 | ECC Signature R component |
0x14 | 0x14 | ECC Signature S component |
0x22 - ecc224_sceebootpbp_sig_gen
New Vita Kirk 0x22 service for 224bit ECC signing.
Specific nonce
is used for signing.
For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).
nonce
is obtained by:
1. Generating 0x40 sized seed which is derived from message hash and one of two static private keys using hmac256 and sha256. Key can be selected with key id 0 or 1.
Private key 0 is only used for signing __sceebootpbp files for firmware versions before 1.8X, otherwise private key 1 is used for signing __sceebootpbp.
2. nonce = seed mod N
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x20 | unknown, must be zeroes |
0x20 | 0x1C | message hash |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x1C | ECC Signature R component |
0x1C | 0x1C | ECC Signature S component |
0x23 - generate_cmac_signature
New Vita Kirk 0x23 service.
It encrypts the plain message with AES128CBC, static key and null IV, then calculates the AES128CMAC of the encrypted message with another static key.
Input:
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | Plain message |
Output:
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | Encrypted message |
0x10 | 0x10 | Encrypted message CMAC |
pm_sm.self
sceSblPmMgrAuthEtoIForDriver uses "sd0:sm/pm_sm_sd.self" whilst other PmSm functions use "os0:sm/pm_sm.self".
Services 8, 9 and 0xA appeared on FW 1.03 (maybe 1.00). They are not present on FW 0.990 and earlier.
Keyset must be between 0-12 on FW 0.931. Keyset 14 is present on FWs 3.600.011-3.740.011.
0x1 - get_product_mode
Used by sceSblPmMgrGetProductModeFromNVS.
Data size is 0x28 bytes.
Input: 0x20 buffer read from NVS at offset 0.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Output: Product Mode |
0x4 | 0x4 | Reserved |
0x8 | 0x20 | Input: NVS block read at offset 0 |
0x2 - set_product_mode
Used by sceSblPmMgrSetProductMode.
Data size is 0x28 bytes.
Input: 0x20 bytes buffer read from NVS at offset 0, to which is written the new product mode to set.
Output data: 0x20 buffer to write to NVS at offset 0.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: Product Mode |
0x4 | 0x4 | Reserved |
0x8 | 0x20 | Input and output: NVS block read/written at offset 0 |
0x3 - gen_req_hello
This command gets the Ernie secure packet for the first JIG auth command.
Data size is 0x30 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset (6, 14) |
0x4 | 0x4 | Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) |
0x8 | 0x28 | Output: Ernie secure packet |
0x4 - gen_challenge
Data size is 0x30 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset (6, 14) |
0x4 | 0x4 | Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) |
0x8 | 0x28 | Input and output: Ernie secure packet |
0x5 - check_response
Returns 0 on success.
Data size is 0x30 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | input: keyset (6, 14) |
0x4 | 0x4 | input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) |
0x8 | 0x28 | input: Ernie secure packet |
0x6 - gen_req_result
Encrypts Ernie secure packet for step 4 with the chosen keyset.
Data size is 0x30 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset (4, 6 on FW 0.931-3.60) |
0x4 | 0x4 | Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) |
0x8 | 0x28 | Input and output: Ernie secure packet |
0x7 - check_result
Returns 0 on success.
Data size is 0x30 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset (4, 6, 14) |
0x4 | 0x4 | Input: keyset_rev (1 when keyset in [4, 6, 12]; 2 when keyset in [14]; otherwise undefined) |
0x8 | 0x28 | Input: Ernie secure packet |
0x8 - run_pm_command
Not present in old FWs.
Used on FW 1.03+ by sceSblPmMgrGetProductModeFromNVS.
Data size is 0x70 bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: Command (0: gen_get_mgmt_data_req, 1: get_mgmt_data, 3: decrypt_response, 4: set_product_mode, 5: set_product_mode_off, 7: set_sd_mode_off) |
0x4 | 0x4 | Reserved |
0x8 | 0x4 | Input and output: product mode |
0xC | 0x4 | Input and output: unknown Mgmt Data |
0x10 | 0x30 | Input and output: Ernie secure packet for setting Product Mode |
0x40 | 0x30 | Input and output: Ernie secure packet for getting Product mode |
0x9 - gen_jig_message
Only on FW 1.03+.
Data size is 0x10C bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset_flag (0x48 for keyset 4, 0x49 for keyset 12) |
0x4 | 0x4 | Reserved |
0x8 | 0x104 | Output: jig_message |
0xA - check_jig_response
Only on FW 1.03+.
Returns 0 on success.
Data size is 0x10C bytes.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Input: keyset_flag (0x48 for keyset 4, 0x49 for keyset 12) |
0x4 | 0x4 | Reserved |
0x8 | 0x104 | Input: jig_response |
qaf_sm.self
0x0
Decrypt or check QAF Token. Used on 1.03 PDEL.
0x1
Offset | Size | Type | Description |
---|---|---|---|
0x0 | 0x4 | in | unk |
0x4 | 0x4 | N/A | unk |
0x8 | 0x4 | out | some data |
0xC | 0x4 | out | some data |
0x40 | 0x30 | in | Syscon secure packet data |
0x2
0x3
0x4 - decrypt_qafv
Input: 0x20 buffer read from NVS offset 0x2A0.
Output: QAF version in this buffer of size 0x20:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Magic |
0x4 | 0x4 | QAF version |
0x8 | 0x8 | Reserved |
0x10 | 0x10 | CMAC |
0x5 - encrypt_qafv
Input QAF version in this buffer of size 0x20:
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Magic |
0x4 | 0x4 | QAF version |
0x8 | 0x8 | Reserved |
0x10 | 0x10 | CMAC |
Output of size 0x20 is then written to NVS offset 0x2A0.
0x6 - check_flag (decrypt)
Input: 0x20 buffer read from NVS at offset 0.
Returns error if flag is bad, 0 on success.
Output
0x7 - set_flag (encrypt)
Input: 0x20 buffer.
Output: 0x20 encrypted buffer that can be written to NVS at offset 0.
0xC - check_qaftoken
Offset | Size | Type | Description |
---|---|---|---|
0x0 | 0x80 | in | Qa Flags token |
0x80 | 0x100 | in | RSA signature |
0xD - get_qaftoken
Offset | Size | Type | Description |
---|---|---|---|
0x0 | 0x80 | inout | Qa Flags token |
0x80 | 0x100 | in | RSA signature |
rmauth_sm.self
Removable Media (Memory Card) authentication. Used by SceMsif.
0x1 - get_key_master_gen_no
Response (size 0x20 bytes):
Offset | Size | Description |
---|---|---|
0x0 | 0x10 | unknown |
0x10 | 0x4 | Returned ID? |
0x14 | 0xC | unknown |
0x2 - set_index_key
Scrambles and sets the DMAC5 keyring 0x1C key.
The scrambling process consists of encrypting the first and second halves of the key seed with a private internal (could be considered as a couple of 0x10 keys) rmmauth_sm
key using AES128-CBC.
Request (size 0x20 bytes):
Offset | Size | Description |
---|---|---|
0x00 | 0x20 | Key seed |
0x3
?clear_index_key?
Clears the DMAC5 keyring 0x1C key (to 0).
spkg_verifier_sm_w_key_2.self
This is an extension of update_service_sm.self. It was added to support command 0xE0002.
0xE0002 - sceSblUsSmAuthSpkgWithKey2
Used to decrypt downloaded lists (SPKGs). Same format as 0x40002.
Lists URLS:
.list_0_version:0000000125.list_0_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_vita.dat .list_1_version:0000000111.list_1_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_emu.dat .list_2_version:0000000001.list_2_url:http://vitacl.ww.dl.playstation.net/vitacl/ww/j/list_launch_teleport.dat
update_service_sm.self
This is used by SceSblUpdateMgr to decrypt update packages extracted from PUP files.
Both 0x40002 and 0x50002 reference buffers in the following way: an inner PA vector is generated for the buffer containing the data to encrypt/decrypt, then an outer PA vector is generated for the inner list. That means that there are two levels of indirection in the PA vector.
Services with PA vectors to pass data to cmep decide whether to use normal vectors or deep vectors depending on the flag of the argument.
0x10002 - sceSblUsSmAuthPupHeader
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_HEADER.
Checks PUP header (with hash check).
Input data size: 0xFC0.
Input: PA vector of the PUP header including the PUP Hash (size: 0x80 + segment_num * 0x20 + segment_num * 0x40 + 0x20)
0x20002 - sceSblUsSmAuthPupSegment
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_SEGMENT.
Checks PUP segment HMAC-SHA256 hash.
Input data size: 0xFC0.
0x30002 - sceSblUsSmAuthPupWatermark
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_WM.
Checks PUP watermark.
Input data size: 0xFC0.
Input data: a packet embedding at least two physical addresses (?in a PA vector?): PUP Watermark (0x1000 bytes) and PUP Hash (0x20 bytes).
0x40002 - sceSblUsSmAuthSpkg
SCE_SBL_SM_COMM_FID_SM_AUTH_SPKG.
Decrypt a SPKG. Allocate a page aligned buffer and read the complete SPKG file into the buffer. The buffer is decrypted in place.
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Set to 0x0 |
0x8 | 0x8 | Set to 0x1 |
0x10 | 0x14 | struct paddr_list_req for PA vector below
|
0x24 | 0x14 | struct paddr_list_req for pkg buffer
|
0x38 | Variable (max 0xF88(0x1F1 entry)) | Copy of PA vector for pkg buffer (contents described at 0x50) |
0x50002 - sceSblUsSmEncryptIndividualSLSK
SCE_SBL_SM_COMM_FID_SM_ENCIND_SLSK.
Re-encrypt individual SLSK files (.enp files).
Offset | Size | Description |
---|---|---|
0x0 | 0x8 | Unknown/Zero |
0x8 | 0x8 | Set to 1 |
0x10 | 0x14 | struct paddr_list_req for PA vector copied to 0x78. Only count field is used.
|
0x24 | 0x14 | struct paddr_list_req for inner PA vector. Not used.
|
0x38 | Variable (max 0xF88(0x1F1 entry)) | Outer PA vector. PA vector to PA vector to encrypt. |
Each inner PA vector is first copied to temporary cmep memory, then they all are checked for validity at once. Maximum size of inner PA vector is 0xFF7 (so probably 0xFF7 / 8 * 8 = 0xFF0). Any higher length results in SCE_SBL_ERROR_SL_ENOMEM = 0x800F020C
error.
How it works:
- first, all inner entries are checked for validity, if something is invalid, bail out
SCE_SBL_ERROR_SL_EINVAL 0x800f0216
- start at last outer entry and move towards the first
- if current entry looks valid (length >= 8), proceed to inner physical address encryption
- if no valid entries found, error=
SCE_SBL_ERROR_SL_EINVAL 0x800f0216
- if multiple valid entries found, error=
SCE_SBL_ERROR_SL_EIO 0x800f0205
(???) (but the first one found is always encrypted) - if only one valid entry is found, return success
Bugs(?):
- encrypting same physical address twice or more times within a single inner PA vector always results in same output, no matter what input was, reproducible with length=0x10 or less
- sum(inner list sizes) must be <= 0xFF0, but there is no overflow check, a large inner list causes cmep to overwrite memory with data like:
00:00:26 0 // this is physical address 0x1F000000 00:00:26 0 00:00:26 0 00:00:26 2000 00:00:26 8 00:00:26 812d40 00:00:26 0 00:00:26 1f000020 // this is physical address 0x1F00001C 00:00:26 0 00:00:26 0 00:00:26 0 00:00:26 2000 00:00:26 8 00:00:26 812d40 00:00:26 0 00:00:26 1f000040 00:00:26 0 00:00:26 0 00:00:26 0 00:00:26 2000 00:00:26 8 00:00:26 812d40 00:00:26 0 00:00:26 1f000060 00:00:26 0 00:00:26 0 00:00:26 0 00:00:26 2000 00:00:26 8 00:00:26 812d40 00:00:26 0 00:00:26 1f000080
0x60002 - sceSblUsSmSnvsEncryptSectors
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_SECTORS.
The input is plain SNVS sectors read from NVS.
Calculates a XTS encrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 bytes in size, but the (size in cmep packet + 4) derives the XTS size and memcpy.
The result is XTS encrypted SNVS sectors.
Data size is (8 bytes + sectors size).
typedef struct data { // size is variable, at least 0x28 bytes int sectors_index; // input: between 1 and 20 (SNVS sectors) int sectors_count; // input char sectors[0x20 * sectors_count]; // input: read from NVS. } data;
0x70002 - sceSblUsSmSnvsDecryptSectors
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_SECTORS.
The input is XTS encrypted sectors.
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 in size, but the (size in cmep packet + 4) derives the XTS size and memcpy.
The result is plain sectors.
Data size is (8 bytes + sectors size).
typedef struct data { // size is variable, at least 0x28 bytes int sectors_index; // input: between 1 and 20 (SNVS sectors) int sectors_count; // input char sectors[0x20 * sectors_count]; // input: read from NVS. } data;
0x80002 - sceSblUsSmSnvsEncryptMgmtData
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_MGMT.
The input are the new status and flags, and the current Mgmt Data sector read from NVS at offset 0.
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in. If ok, then it uses the seed 0xACA9B1AC to recalculate the block, generate a new hmac, and xts encrypt the block.
The result is a new Mgmt Data sector, which is to be written to NVS at offset 0.
Data size is 0x28 bytes.
typedef struct data { // size is 0x28 bytes int status; // input char flags[4]; // input char sector[0x20]; // input: read from NVS at offset 0. Likely to be 0x10 bytes of data followed by 0x10 bytes of HMAC. } data;
0x90002 - sceSblUsSmSnvsDecryptMgmtData
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_MGMT.
The input is the current Mgmt Data sector read from NVS at offset 0.
Calculates a XTS decrypt using the per console keys in keyring 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in.
The result is the current status and flags.
Data size is 0x28 bytes.
typedef struct data { // size is 0x28 bytes int status; // output char flags[4]; // output char sector[0x20]; // input: read from NVS at offset 0. Likely to be 0x10 bytes of data followed by 0x10 bytes of HMAC. } data;
// SCE_SBL_SS_SNVS_FLAGS #define SCE_SBL_SS_SNVS_UPDATER_FLAG_INDEX 0
If flags[SCE_SBL_SS_SNVS_UPDATER_FLAG_INDEX] is not set, updater init is skipped:
if (((byte)flags & 1) == 0) sceKernelPrintfLevelForDriver(2, "skip init for updater\n"); else { sceKernelPrintfLevelForDriver(2, "do init for updater\n"); if (SpkgInfoUtilInitForUpdater(&status, &flags) != 0) sceKernelPrintfLevelForDriver(2,"SpkgInfoUtilInitForUpdater() failure = 0x%x\n",iVar2); }
0xA0002 - sceSblUsSmAuthAdditionalSign
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_AS.
Checks PUP Additional Signatures.
0xB0002 - sceSblUsSmSnvsEncryptDecryptSector
Added on FW 1.03. Usage similar to pm_sm command 8.
Data size is 0x88 bytes.
typedef struct data { // size is 0x88 uint mode; // 0 before read, 1 after read, 2 before write, 3 after write uint sector_index; // between 1 and 20 (SNVS sectors) char base_buf[0x20]; // input: full of 0xdeadbeef char inter_buf[0x30]; // output: input for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver char final_buf[0x30]; // input: output for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver } data;
Usage:
- 1) sceSblSmCommCallFunc(id, 0xB0002, &response, data, 0x88);
For read:
- 2) sceSysconSnvsReadDataForDriver(data + 0x28, 0x10, data + 0x58, 0x30);
For write:
- 2) sceSysconSnvsWriteDataForDriver(data + 0x28, 0x30, data + 0x58, 0x10);
- 3) sceSblSmCommCallFunc(id, 0xB0002, &response, data, 0x88);
0xC0002 - sceSblUsSmSnvsEncryptDecryptMgmtData
Added on FW 1.03. Usage similar to pm_sm command 8.
Data size is 0x70 bytes.
typedef struct data { // Size is 0x70 bytes on FW 3.60 int mode; // ex: 0 before read, 1 after read, 2 before write, 3 after write int sector_count; // always 0 (Mgmt Data) int status; // not set for read, set for write int flags; // not set for read, set for write char unk_10[0x30]; // output: input for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver char unk_40[0x30]; // input: output for sceSysconSnvsReadDataForDriver or sceSysconSnvsWriteDataForDriver } data;
Usage:
- 1) sceSblSmCommCallFunc(id, 0xC0002, &response, data, 0x70);
For write:
- 2) sceSysconSnvsWriteDataForDriver(data + 0x10, 0x30, data + 0x40, 0x10);
For read:
- 2) sceSysconSnvsReadDataForDriver(data + 0x10, 0x10, data + 0x40, 0x30);
- 3) sceSblSmCommCallFunc(id, 0xC0002, &response, data, 0x70);
0xD0002
Syscon update related. Usage is to proxy encrypted data cmep <=> Syscon.
Data size is 0x58 bytes.
typedef struct data { // Size is 0x58 bytes on FW 3.60 int mode; // ex: 0, 1, 2, 3, 4 int unk_4; // Maybe unused char unk_8[0x28]; // input: syscon command 0xD2 output char unk_30[0x28]; // output: syscon command 0xD2 input } data;
Usage:
- 1) sceSblSmCommCallFunc(id, 0xD0002, &response, data, 0x58);
For modes 0, 1 and 3:
- 2) memcpy(data + 8, data + 0x30, 0x28); SceSysconForDriver_4D03754A(data + 8, 0x28, data + 0x30, 0x28); // Calls Syscon command 0xD0.
- 3) sceSblSmCommCallFunc(id, 0xD0002, &response, data, 0x58);
Mode:
- 0 - Do init 0x28 buffer.
- 1 - Do Bigmac unknown crypto with some blob.
- 2 - Do Bigmac unknown crypto with some blob.
- 3 - Do Bigmac unknown crypto with some blob.
- 4 - Do some working. And reset Syscon ticket count with Bigmac PRNG (keyring 0x512).
utoken_sm.self
0x1 - check_utoken
Checks SceUtoken buffer.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Physical address of SceUtoken buffer |
0x4 | 0x4 | Size of SceUtoken buffer (usually 0x800) |
0x8 | 0x4 | Time (got using sceRtcGetCurrentSecureTickForDriver or 0xFFFFFFFF (-1) |
0xC | 0x10 | OpenPsId |
0x2 - decrypt_utoken
Decrypt SceUtoken buffer, in order to get UT Flags.
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Physical address of SceUtoken buffer |
0x4 | 0x4 | Size of SceUtoken buffer (usually 0x800) |
0x8 | 0x4 | Time (got using sceRtcGetCurrentSecureTickForDriver or 0xFFFFFFFF (-1)) |
0xC | 0x10 | OpenPsId |
mgkm_sm.self
Magic Gate Key Manager secure module.
Present on 0.931-3.73. Commands are almost the same on any FW, only KEY_31 varies. 0 These commands are used to set keys (as seen on FWs from 0.940 to 3.60) to |DMAC5 registers in NS memory. These keys are used in to do encryption stuff with AES-ECB and TripleDES-ECB algorithms through |DMAC5.
On FW 0.940, commands 1 and 2 are only called by SceSblMgKeyMgrForDriver_1C5388D0 which consists of:
int SceSblMgKeyMgrForDriver_1C5388D0(void *in, void *out) { int ret; uint8_t tmp_buffer[16]; ret = call_cmd_1(); if ((ret == 0) && (ret = call_cmd_2(), ret == 0)) { aesECBDec16B(in, tmp_buffer, 0x1E); aesECBEnc16B(tmp_buffer, out, 0x1F); } return ret; }
0x1 - set_key_31
memset(buffer, 0, 0x20); memcpy(buffer, KEY_31, 0x10); bigmac_memcpy(0xE04E0000 + 0x1F * 0x20, buffer, 0x20);
0x2 - set_key_30
memset(buffer, 0, 0x20); memcpy(buffer, pOpenPsId, 0x10); memcpy(buffer + 0x10, KEY_30_SEED, 0x10); bigmac_sha256(buffer, buffer, 0x20); bigmac_memcpy(0xE04E0000 + 0x1E * 0x20, buffer, 0x20);
0x3 - unset_key_31
memset(buffer, 0, 0x20); bigmac_memcpy(0xE04E0000 + 0x1F * 0x20, buffer, 0x20);
0x4 - unset_key_30
memset(buffer, 0, 0x20); bigmac_memcpy(0xE04E0000 + 0x1E * 0x20, buffer, 0x20);