https://wiki.henkaku.xyz/vita/api.php?action=feedcontributions&user=St4rk&feedformat=atom
Vita Development Wiki - User contributions [en]
2024-03-28T16:34:00Z
User contributions
MediaWiki 1.35.13
https://wiki.henkaku.xyz/vita/index.php?title=Secure_Modules_Functions&diff=2631
Secure Modules Functions
2017-02-08T04:22:20Z
<p>St4rk: /* mgkm_sm.self - update information, need more REing. */</p>
<hr />
<div>Depending on the F00D SELF that is currently loaded, different commands are handled.<br />
<br />
== Request Buffer ==<br />
<br />
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 shut down the currently loaded F00D SELF.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0 || 0x4 || Size of buffer<br />
|-<br />
| 0x4 || 0x4 || Command ID<br />
|-<br />
| 0x8 || 0x4 || Return value (output)<br />
|-<br />
| 0xC || 0x34 || Unknown/Unused<br />
|-<br />
| 0x40 || Variable (max 0xFC0) || Command specific buffer<br />
|-<br />
|}<br />
<br />
=== Physical Address List ===<br />
<br />
A common format used in these requests is a list of physical address and size. This simple structure is defined below. See [[SceSysmem#get_paddr_list]] for information on creating this list.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0 || 0x4 || Physical Address<br />
|-<br />
| 0x4 || 0x4 || Size<br />
|-<br />
|}<br />
<br />
This data format is used when passing large buffers of data to F00D. This is because the memory manager in kernel could allocate contiguous virtual addresses that corresponds to varying physical addresses.<br />
<br />
== kprx_auth_sm.self ==<br />
<br />
This is a special SELF that is found in the boot [[SLB2]] partition. The raw (encrypted) SELF is found in secure world memory (placed there by an early bootloader). It is used to decrypt SELFs for ARM. The SELF header is passed into a page aligned buffer and a [[F00D Commands#Physical Address List|paddr list]] is generated from it.<br />
<br />
=== 0x10001 ===<br />
<br />
Parses the SELF header for decryption. The header is copied to the F00D private memory region first (on 1.69 with 0x1000 sized header, it is at <code>0x00811CC0</code> in F00D memory space.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || 0x1 if user SELF, otherwise 0x0<br />
|-<br />
| 0x48 || 0x8 || <code>0x2808000000000001LL</code><br />
|-<br />
| 0x50 || 0x8 || <code>0xF000C000000080LL</code><br />
|-<br />
| 0x58 || 0x8 || <code>0xFFFFFFFF00000000LL</code><br />
|-<br />
| 0x60 || 0x10 || Unknown<br />
|-<br />
| 0x70 || 0x8 || <code>0xC300003800980LL</code><br />
|-<br />
| 0x78 || 0x8 || <code>0x8009800000LL</code><br />
|-<br />
| 0x80 || 0x8 || Unknown<br />
|-<br />
| 0x88 || 0x8 || <code>0xFFFFFFFF00000000LL</code><br />
|-<br />
| 0x90 || 0x8 || Unknown<br />
|-<br />
| 0x98 || 0x40 || Not used<br />
|-<br />
| 0xD8 || 0x60 || Return data (0x90 length overwriting) ?<br />
|-<br />
| 0x138 || 0x10 || Copy of data at <code>0x68</code><br />
|-<br />
| 0x148 || 0x10 || Unknown<br />
|-<br />
| 0x158 || 0x4 || <code>0x10</code><br />
|-<br />
| 0x15C || 0xC || Unknown<br />
|-<br />
| 0x168 || 0x4 || [[F00D Commands#SELF Path Code|SELF path code]]<br />
|-<br />
| 0x16C || 0x4 || Unknown<br />
|-<br />
| 0x170 || 0x4 || Number of paddr list entries for buffer<br />
|-<br />
| 0x174 || 0x4 || Physical address of paddr list<br />
|-<br />
|}<br />
<br />
==== SELF Path Code ====<br />
<br />
This code is found by the path the SELF was loaded from. It's used by F00D to check if the SELF being loaded from an allowed partition. A path that does not start with any of the following will have <code>0</code> returned as the code. It could also be used to select the key used in decryption.<br />
<br />
{| class="wikitable sortable"<br />
|-<br />
! Path !! Code<br />
|-<br />
| sd0: || 1<br />
|-<br />
| os0: || 2<br />
|-<br />
| vs0: || 3<br />
|-<br />
| vd0: || 4<br />
|-<br />
| tm0: || 5<br />
|-<br />
| ur0: || 6<br />
|-<br />
| host0: || 7<br />
|-<br />
| ud0: || 11<br />
|-<br />
| ux0:app || 23<br />
|-<br />
| ux0:patch || 24<br />
|-<br />
| ux0:data || 25<br />
|-<br />
| ux0:user || 0<br />
|-<br />
| ux0: || 12<br />
|-<br />
| gro0:app || 13<br />
|-<br />
| grw0:patch || 14<br />
|-<br />
| sa0: || 15<br />
|-<br />
| mfa0: || 16<br />
|-<br />
| mfb0: || 17<br />
|-<br />
| lma0: || 18<br />
|-<br />
| lmb0: || 19<br />
|-<br />
| lmc0: || 20<br />
|-<br />
| lmd0: || 21<br />
|-<br />
| pd0: || 22<br />
|-<br />
|}<br />
<br />
=== 0x20001 ===<br />
<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Segment number<br />
|-<br />
| 0x44 || 0x4 || Return value. <code>0x1</code> if not compressed, <code>0x2</code> is compressed.<br />
|-<br />
| 0x48 || 0x8 || Unknown<br />
|-<br />
|}<br />
<br />
=== 0x30001 ===<br />
<br />
Decrypt a buffer from the SELF corresponding to the program segment number passed in above. The segment is read in <code>0x10000</code> chunks and is decrypted in place (the input buffer will contain the decrypted data). A [[F00D Commands#Physical Address List|paddr list]] is generated from the buffer. The input buffer and output buffer can be the same.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Number of entries in input paddr list<br />
|-<br />
| 0x44 || 0x4 || Physical address of the input paddr list<br />
|-<br />
| 0x48 || 0x4 || Number of entries in output paddr list<br />
|-<br />
| 0x4C || 0x4 || Physical address of the output paddr list<br />
|-<br />
|}<br />
<br />
=== 0x40001 sceSblAuthMgrGetEKc ===<br />
Decrypts provided buffer in ECB mode using one of three keys.<br />
<br />
Used by [[SceSblAuthMgr]] for getting some key?<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x100 || Data Buffer (under 0x100 bytes)<br />
|-<br />
| 0x140 || 0x4 || Data Size - must be under 0x100<br />
|-<br />
| 0x144 || 0x4 || Key ID (0,1,2)<br />
|-<br />
| 0x148 || 0x4 || Set to 0<br />
|-<br />
| 0x14C || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x50001 sceSblAuthMgrSetDmac5Key ===<br />
Used by [[SceSblAuthMgr]] to set key for decryption.<br />
<br />
This uses an unknown secret to derive the final key, then writes it into dmac5 keyring.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8-0x10 || Key (64/128/196/256 bits)<br />
|-<br />
| 0x140 || 0x4 || Key size (in bytes)<br />
|-<br />
| 0x144 || 0x4 || Key ID<br />
|-<br />
| 0x148 || 0x4 || Slot ID<br />
|-<br />
| 0x14C || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x60001 sceSblAuthMgrClearDmac5Key ===<br />
Used by [[SceSblAuthMgr]] for clearing the Dmac5 Key.<br />
<br />
This function writes zeroes into dmac5 keyring.<br />
<br />
=== 0x70001 sceSblAuthMgrDecBindData ===<br />
Used by [[SceSblAuthMgr]] and [[SceNpdrm]] for game card binding data used in conjunction with the RIF license file on the gamecard in deriving the per game klicensee key.<br />
<br />
=== 0x80001 ===<br />
Used by [[SceSblAuthMgr]] for used by the VSH function _vshSblAuthMgrVerifySpsfo.<br />
<br />
== act_sm.self ==<br />
<br />
=== 0x2 ===<br />
<br />
Verify afv data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x1 || Format version<br />
|-<br />
| 0x45 || 0x3 || Unused<br />
|-<br />
| 0x48 || 0x4 || Issue number (increment each activation, prevent rollback)<br />
|-<br />
| 0x4C || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x50 || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x54 || 0x10 || Activation key<br />
|-<br />
| 0x64 || 0x1C || Unused<br />
|-<br />
| 0x80 || 0x40 || Encrypted Data (I think 0x20 byte data + 0x20 byte HMAC)<br />
|-<br />
|}<br />
<br />
=== 0x4 ===<br />
<br />
Verify activation data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x4 || Issue number<br />
|-<br />
| 0x48 || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x4C || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x50 || 0x10 || Unknown (see below)<br />
|-<br />
|}<br />
<br />
=== 0x5 ===<br />
<br />
Get activation data. The returned data is sent to Syscon at offset 0x520.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x4 || Issue number<br />
|-<br />
| 0x48 || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x4C || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x50 || 0x10 || Unknown (returned data)<br />
|-<br />
|}<br />
<br />
=== 0x7 ===<br />
<br />
Check if activation is valid. The activation data is read from Syscon at offset 0x520.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Current time unix timestamp<br />
|-<br />
| 0x48 || 0x8 || Unknown<br />
|-<br />
| 0x50 || 0x20 || Activation data<br />
|-<br />
|}<br />
<br />
=== 0xA ===<br />
<br />
Introduced in 2.12. Check if new activation is valid. Extended activation check with a signature. This is ran when installing a new afv.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x80 || Same buffer as command 0x2 (new activation data)<br />
|-<br />
| 0xC0 || 0x100 || Signature over new activation data<br />
|-<br />
| 0x1C0 || 0x80 || Same buffer as command 0x2 (previous activation data)<br />
|-<br />
| 0x240 || 0x100 || Signature over previous activation data<br />
|-<br />
| 0x340 || 0x20 || Same buffer as command 0x4 (new activation buffer from syscon)<br />
|-<br />
|}<br />
<br />
=== 0xB ===<br />
<br />
Introduced in 2.12. Check if current activation is valid. Extended activation check with signature. This is ran on boot.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Current time<br />
|-<br />
| 0x48 || 0x8 || Some return value<br />
|-<br />
| 0x50 || 0x8 || Unknown<br />
|-<br />
| 0x58 || 0x20 || Same buffer as command 0x4 (activation buffer from syscon)<br />
|-<br />
| 0x78 || 0x80 || Same buffer as command 0x2<br />
|-<br />
| 0xF8 || 0x100 || Signature over activation data<br />
|-<br />
|}<br />
<br />
== aimgr_sm.self ==<br />
<br />
=== 0x1 ===<br />
<br />
Returns 16 byte console id (used in vshSblAimgrGetConsoleId)<br />
<br />
=== 0x3 ===<br />
<br />
Used in vshSblAimgrGetVisibleId<br />
<br />
=== 0x2 ===<br />
<br />
Returns the console's OpenPSID. Also known as the "activation key" for PDEL and PTEL.<br />
<br />
=== 0x4 ===<br />
<br />
Used in vshSblAimgrGetPscode2<br />
<br />
== compat_sm.self ==<br />
<br />
=== 0x10006 ===<br />
Seems to be called on init and before resume of PSP<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x20006 ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Set to 0<br />
|-<br />
| 0x44 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
== encdec_w_portability_sm.self ==<br />
This seem to be used to do some kind of key derivation. May also be used as a general purpose encryption engine.<br />
<br />
=== 0x1000A ===<br />
<br />
Encrypt data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Key ID (max 0x0A)<br />
|-<br />
| 0x44 || 0x4 || Output Length<br />
|-<br />
| 0x48 || 0x20 || Output<br />
|-<br />
| 0x68 || 0x4 || Input Length (max 0x20)<br />
|-<br />
| 0x6C || 0x20 || Input<br />
|-<br />
| 0x8C || 0x10 || IV<br />
|-<br />
|}<br />
<br />
=== 0x2000A ===<br />
<br />
Decrypt data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Key ID (max 0xA)<br />
|-<br />
| 0x44 || 0x4 || Input Length (max 0x20)<br />
|-<br />
| 0x48 || 0x20 || Input<br />
|-<br />
| 0x68 || 0x4 || Output Length<br />
|-<br />
| 0x6C || 0x20 || Output<br />
|-<br />
| 0x8C || 0x10 || IV<br />
|-<br />
|}<br />
<br />
<br />
Return of 0x800f0002 means invalid service ID. For encdec_w_portability_sm, only 0x1000A and 0x2000A are supported.<br />
<br />
Return of 0x800f1716 means invalid key slot. Valid key slots are only 1-10.<br />
<br />
== gcauthmgr_sm.self ==<br />
<br />
=== 0x1000B ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Set to 1<br />
|-<br />
| 0x44 || 0x4 || GC Command<br />
|-<br />
| 0x48 || 0x800 || GC Buffer (Input/Output)<br />
|-<br />
| 0x848 || 0x4 || Unknown GC param<br />
|-<br />
| 0x84C || 0x4 || GC Buffer Length/Written<br />
|-<br />
| 0x850 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
Supported GC commands and structures<br />
<br />
==== 0x4 ====<br />
Original PSP Kirk 4 service for encrypting data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x4 || Set to 5<br />
|-<br />
| 0x4|| 0x4 || 0<br />
|-<br />
| 0x8|| 0x4|| 0<br />
|-<br />
| 0xC || 0x4 || Key Slot (1-0x7F not all available)<br />
|-<br />
| 0x10|| 0x4 || Data Length<br />
|-<br />
| 0x14|| 0x7EC || Data to encrypt<br />
|-<br />
|}<br />
<br />
==== 0x7 ====<br />
Original PSP Kirk 7 service for decrypting data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x4 || Set to 4<br />
|-<br />
| 0x4|| 0x4 || 0<br />
|-<br />
| 0x8|| 0x4|| 0<br />
|-<br />
| 0xC || 0x4 || Key Slot (1-0x7F not all available)<br />
|-<br />
| 0x10|| 0x4 || Data Length<br />
|-<br />
| 0x14|| 0x7EC || Data to encrypt<br />
|-<br />
|}<br />
<br />
==== 0xC ====<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Private Key<br />
|-<br />
| 0x14|| 0x14 || Public Key X component<br />
|-<br />
| 0x28|| 0x14|| Public Key Y component<br />
|-<br />
|}<br />
<br />
==== 0xD ====<br />
Original PSP Kirk 0xD service for multiplying a 160bit ECC curve point with a value. Call with a multiplier, then a x and y point value.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Multiplier Value<br />
|-<br />
| 0x14|| 0x14 || Point X component<br />
|-<br />
| 0x28|| 0x14|| Point Y component<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || New Point X component<br />
|-<br />
| 0x14|| 0x14 || New Point Y component<br />
|-<br />
|}<br />
<br />
==== 0xE ====<br />
Original PSP Kirk 0xE service for 160bit Random number generation. Call with an empty buffer, the result structure is below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Cryptographic Random Number<br />
|-<br />
|}<br />
<br />
==== 0x10 ====<br />
Original PSP Kirk 0x10 service for 160bit ECC signing. Call and return structure below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x20 || Encrypted private key (see kirk-engine implementation for fuse_id process for encryption)<br />
|-<br />
| 0x20|| 0x14 || SHA1 hash of the content you want signed<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x14|| 0x14 || ECC Signature S component<br />
|-<br />
|}<br />
<br />
==== 0x11 ====<br />
Original PSP Kirk 0x11 service for 160bit ECC signature verification. Call with the below structure, then function will return pass or fail.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Public Key X component<br />
|-<br />
| 0x14|| 0x14 || Public Key Y component<br />
|-<br />
| 0x28|| 0x14 || SHA1 hash of the content that is signed<br />
|-<br />
| 0x3C|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x50|| 0x14 || ECC Signature S component<br />
|-<br />
<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x14|| 0x14 || ECC Signature S component<br />
|-<br />
|}<br />
<br />
==== 0x14 ====<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Private Key<br />
|-<br />
| 0x1C|| 0x1C || Public Key X component<br />
|-<br />
| 0x38|| 0x1C|| Public Key Y component<br />
|-<br />
|}<br />
<br />
==== 0x15 ====<br />
New Vita Kirk 0x15 service for multiplying a 224bit ECC curve point with a value. Call with a multiplier, then a x and y point value.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Multiplier Value<br />
|-<br />
| 0x1C|| 0x1C || Point X component<br />
|-<br />
| 0x38|| 0x1C|| Point Y component<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || New Point X component<br />
|-<br />
| 0x1C|| 0x1C || New Point Y component<br />
|-<br />
|}<br />
<br />
==== 0x16 ====<br />
New Vita Kirk 0x16 service for 160bit Random number generation. Call with an empty buffer, the result structure is below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Cryptographic Random Number<br />
|-<br />
|}<br />
<br />
==== 0x17 ====<br />
New Vita Kirk 0x17 service. Unknown, but buffer length is 0x3C. Almost certainly a 224bit version of 0x10<br />
<br />
==== 0x18 ====<br />
New Vita Kirk 0x18 service. Unknown, but buffer length is 0x8C. Almost certainly a 224bit version of 0x11<br />
<br />
==== 0x19 ====<br />
New Vita Kirk 0x19 service. Unknown, but buffer length is 0xE8. Related to IdStorage somehow. Almost certainly a 224bit version of 0x12<br />
<br />
==== 0x1B ====<br />
New Vita Kirk 0x1B service. This service is related to SceSdif and is used by SceSblGcAuthMgr.<br />
This service is part of SD MMC CMD56 custom initialization protocol.<br />
This is a data validation service with no response. Size of request is 0x53.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x10 || cmd56 packet7 chunk<br />
|-<br />
| 0x30|| 0x23 || cmd56 packet8 chunk<br />
|-<br />
|}<br />
<br />
==== 0x1C ====<br />
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. <br />
This is a data generation service. Size of request is 0x40. Size of response is 0x33.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x20 || cmd56 packet8 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x01 || command<br />
|-<br />
| 0x01|| 0x01 || unknown<br />
|-<br />
| 0x02|| 0x01 || size<br />
|-<br />
| 0x03|| 0x30 || data<br />
|-<br />
|}<br />
<br />
==== 0x1D ====<br />
New Vita Kirk 0x1D service. This service is related to SceSdif and is used by SceSblGcAuthMgr. <br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x10 || cmd56 packet13 chunk<br />
|-<br />
| 0x60|| 0x43 || cmd56 packet14 chunk<br />
|-<br />
|}<br />
<br />
==== 0x1E ====<br />
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.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x01 || parameter (value 2 or 3)<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x01 || command<br />
|-<br />
| 0x01|| 0x01 || unknown<br />
|-<br />
| 0x02|| 0x01 || size<br />
|-<br />
| 0x03|| 0x30 || data<br />
|-<br />
|}<br />
<br />
==== 0x1F ====<br />
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.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x20 || cmd56 packet15 chunk<br />
|-<br />
| 0x70|| 0x43 || cmd56 packet16 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || unknown<br />
|-<br />
|}<br />
<br />
==== 0x20 ====<br />
New 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 validation service. Size of request is 0x116. Size of response is 0x34.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x20 || cmd56 packet17 chunk<br />
|-<br />
| 0x70|| 0x43 || cmd56 packet18 chunk<br />
|-<br />
| 0xB3|| 0x10 || cmd56 packet19 chunk<br />
|-<br />
| 0xC3|| 0x53 || cmd56 packet20 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x34 || unknown<br />
|-<br />
|}<br />
<br />
==== 0x21 ====<br />
New Vita Kirk 0x21 service. Unknown, but buffer length is 0x34. <br />
<br />
==== 0x22 ====<br />
New Vita Kirk 0x22 service. Unknown, but buffer length is 0x3C. <br />
<br />
==== 0x23 ====<br />
New Vita Kirk 0x23 service. Unknown, but buffer length is 0x20.<br />
<br />
== pm_sm.self ==<br />
<br />
=== 0x1 (sceSblPmMgrGetProductModeFromNVS) ===<br />
<br />
=== 0x2 ===<br />
=== 0x3 ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || arg1 (6 or 14)<br />
|-<br />
| 0x44 || 0x4 || arg2 (1 when arg1 in [4, 6, 12]; 2 when arg in [14]; otherwise undefined)<br />
|}<br />
<br />
=== 0x4 ===<br />
=== 0x5 ===<br />
=== 0x6 ===<br />
=== 0x7 ===<br />
=== 0x8 (sceSblPmMgrGetProductModeFromNVS) ===<br />
<br />
=== 0x9 ===<br />
=== 0xA ===<br />
<br />
== qaf_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== rmauth_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== spkg_verifier_sm_w_key_2.self ==<br />
<br />
=== 0xE0002 ===<br />
<br />
Used to decrypt lists stored in updates. Same format as [[F00D Commands#0x40002|0x40002]].<br />
<br />
== update_service_sm.self ==<br />
<br />
This is used by [[SceSblSsUpdateMgr]] to decrypt update packages extracted from [[PUP]] files. Both 0x40002 and 0x50002 reference buffers in the following way: an inner paddr list is generated for the buffer containing the data to encrypt/decrypt, then an outer paddr list is generated for the inner list. That means there's two levels of indirection in the paddr list.<br />
<br />
=== 0x10002 ===<br />
<br />
Verify PUP header.<br />
<br />
=== 0x20002 ===<br />
<br />
Verify PUP segment.<br />
<br />
=== 0x30002 ===<br />
<br />
Verify watermark.<br />
<br />
=== 0x40002 ===<br />
<br />
Decrypt package. Allocate a page aligned buffer and read the complete pkg file into the buffer. The buffer is decrypted in place.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8 || Set to 0x0<br />
|-<br />
| 0x48 || 0x8 || Set to 0x1<br />
|-<br />
| 0x50 || 0x14 || <code>struct paddr_list_req</code> for Paddr list below<br />
|-<br />
| 0x64 || 0x14 || <code>struct paddr_list_req</code> for pkg buffer<br />
|-<br />
| 0x78 || Variable (max 0xF48) || Copy of paddr list for pkg buffer (contents described at 0x50)<br />
|-<br />
|}<br />
<br />
=== 0x50002 ===<br />
<br />
Re-encrypt enp files<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8 || Unknown/Zero<br />
|-<br />
| 0x48 || 0x8 || Set to 1<br />
|-<br />
| 0x50 || 0x14 || <code>struct paddr_list_req</code> for paddr list copied to 0x78. Only count field is used.<br />
|-<br />
| 0x64 || 0x14 || <code>struct paddr_list_req</code> for inner paddr list. Not used.<br />
|-<br />
| 0x78 || Variable (max 0xF88) || Paddr list to paddr list to encrypt<br />
|-<br />
|}<br />
<br />
=== 0x60002 ===<br />
=== 0x70002 ===<br />
=== 0x80002 ===<br />
=== 0x90002 ===<br />
<br />
=== 0xA0002 ===<br />
<br />
Verify additional data.<br />
<br />
=== 0xB0002 ===<br />
=== 0xC0002 ===<br />
=== 0xD0002 ===<br />
<br />
== utoken_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== mgkm_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
These commands seems to be used to set keys (on FW 1.50, there are debug strings referencing this part of code as "call_set_key_command") on [[Dmac5|Dmac5]], this key seems to be used to do stuff with TripleDES and another unknown encrypt algorithm. <br />
<br />
<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceSysmem&diff=2624
SceSysmem
2017-02-07T05:24:18Z
<p>St4rk: </p>
<hr />
<div>SceSysmem is a kernel module that acts as the heart of the kernel. It exports multiple libraries for different functionalities (one of the few modules that do so). SceSysmem is the first module that is loaded in the [[Boot Sequence|kernel load sequence]] and its libraries are imported by almost all other modules. See [[Memory]] for more details on the memory subsystem.<br />
<br />
== Module ==<br />
This module exists in both non-secure and secure world. The non-secure world SELF can be found in <code>os0:kd/sysmem.skprx</code>. It also can be found in the [[Boot Sequence|Boot Image]].<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceSysmem || Non-secure || Kernel || 0xB93950C6<br />
|-<br />
| 3.60 || SceSysmem || ? || Kernel || 0x3380B323<br />
|-<br />
| 3.61 || SceSysmem || Non-secure || Kernel || 0x3380B323<br />
|-<br />
| 1.69 || SceSysmem || Secure || Kernel || 0x502BE0E5<br />
|}<br />
<br />
== Libraries ==<br />
This module only exports kernel libraries.<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysmemForKernel|SceSysmemForKernel]] || Non-secure || Kernel || 0x63A519E5<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysmemForKernel|SceSysmemForKernel]] || ? || Kernel || 0x63A519E5<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysmemForDriver|SceSysmemForDriver]] || Non-secure || Kernel || 0x6F25E18A<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysmemForDriver|SceSysmemForDriver]] || ? || Kernel || 0x6F25E18A<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysmem|SceSysmem]] || Non-secure || User || 0x37FE725A<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysmem|SceSysmem]] || ? || User || 0x37FE725A<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysmemForDebugger|SceSysmemForDebugger]] || Non-secure || Kernel || 0xC7309957<br />
|-<br />
| 1.69 || [[SceSysmem#SceDipsw|SceDipsw]] || Non-secure || User || 0xB36D5922<br />
|-<br />
| 3.60 || [[SceSysmem#SceDipsw|SceDipsw]] || ? || User || 0xB36D5922<br />
|-<br />
| 1.69 || [[SceSysmem#SceDipswForDriver|SceDipswForDriver]] || Non-secure || Kernel || 0xC9E26388<br />
|-<br />
| 3.60 || [[SceSysmem#SceDipswForDriver|SceDipswForDriver]] || ? || Kernel || 0xC9E26388<br />
|-<br />
| 1.69 || [[SceSysmem#SceUartForKernel|SceUartForKernel]] || Non-secure || Kernel || 0xC03DBE40<br />
|-<br />
| 3.60 || [[SceSysmem#SceUartForKernel|SceUartForKernel]] || ? || Kernel || 0xC03DBE40<br />
|-<br />
| 1.69 || [[SceSysmem#SceCpu|SceCpu]] || Non-secure || User || 0x45265161<br />
|-<br />
| 3.60 || [[SceSysmem#SceCpu|SceCpu]] || ? || User || 0x45265161<br />
|-<br />
| 1.69 || [[SceSysmem#SceCpuForKernel|SceCpuForKernel]] || Non-secure || Kernel || 0x54BF2BAB<br />
|-<br />
| 3.60 || [[SceSysmem#SceCpuForKernel|SceCpuForKernel]] || ? || Kernel || 0x54BF2BAB<br />
|-<br />
| 1.69 || [[SceSysmem#SceCpuForDriver|SceCpuForDriver]] || Non-secure || Kernel || 0x40ECDB0E<br />
|-<br />
| 3.60 || [[SceSysmem#SceCpuForDriver|SceCpuForDriver]] || ? || Kernel || 0x40ECDB0E<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysclibForKernel|SceSysclibForKernel]] || Non-secure || Kernel || 0x24878615<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysclibForDriver|SceSysclibForDriver]] || Non-secure || Kernel || 0x7EE45391<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysclibForDriver|SceSysclibForDriver]] || ? || Kernel || 0x7EE45391<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysrootForKernel|SceSysrootForKernel]] || Non-secure || Kernel || 0x3691DA45<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysrootForKernel|SceSysrootForKernel]] || ? || Kernel || 0x3691DA45<br />
|-<br />
| 1.69 || [[SceSysmem#SceKernelUtilsForDriver|SceKernelUtilsForDriver]] || Non-secure || Kernel || 0x496AD8B4<br />
|-<br />
| 3.60 || [[SceSysmem#SceKernelUtilsForDriver|SceKernelUtilsForDriver]] || ? || Kernel || 0x496AD8B4<br />
|-<br />
| 1.69 || [[SceSysmem#SceZlibForDriver|SceZlibForDriver]] || Non-secure || Kernel || 0xE241534E<br />
|-<br />
| 1.69 || [[SceSysmem#SceKernelSuspendForDriver|SceKernelSuspendForDriver]] || Non-secure || Kernel || 0x7290B21C<br />
|-<br />
| 3.60 || [[SceSysmem#SceKernelSuspendForDriver|SceKernelSuspendForDriver]] || ? || Kernel || 0x7290B21C<br />
|-<br />
| 1.69 || [[SceSysmem#SceQafMgrForDriver|SceQafMgrForDriver]] || Non-secure || Kernel || 0x4E29D3B6<br />
|-<br />
| 3.60 || [[SceSysmem#SceQafMgrForDriver|SceQafMgrForDriver]] || ? || Kernel || 0x4E29D3B6<br />
|-<br />
| 1.69 || [[SceSysmem#ScePmMgrForDriver|ScePmMgrForDriver]] || Non-secure || Kernel || 0xF13F32F9<br />
|-<br />
| 3.60 || [[SceSysmem#ScePmMgrForDriver|ScePmMgrForDriver]] || ? || Kernel || 0xF13F32F9<br />
|-<br />
| 1.69 || [[SceSysmem#SceSblAIMgrForDriver|SceSblAIMgrForDriver]] || Non-secure || Kernel || 0xFD00C69A<br />
|-<br />
| 3.60 || [[SceSysmem#SceSblAIMgrForDriver|SceSblAIMgrForDriver]] || ? || Kernel || 0xFD00C69A<br />
|-<br />
| 1.69 || [[SceSysmem#SceProcEventForDriver|SceProcEventForDriver]] || Non-secure || Kernel || 0x887F19D0<br />
|-<br />
| 3.60 || [[SceSysmem#SceProcEventForDriver|SceProcEventForDriver]] || ? || Kernel || 0x887F19D0<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysrootForDriver|SceSysrootForDriver]] || Non-secure || Kernel || 0x2ED7F97A<br />
|-<br />
| 3.60 || [[SceSysmem#SceSysrootForDriver|SceSysrootForDriver]] || ? || Kernel || 0x2ED7F97A<br />
|-<br />
| 3.60 || [[SceSysmem#SceDebugLed|SceDebugLed]] || ? || ? || 0xAE004C0A<br />
|-<br />
| 3.60 || [[SceSysmem#SceDebugLedForDriver|SceDebugLedForDriver]] || ? || Kernel || 0x7BC05EAD<br />
|-<br />
| 3.60 || [[SceSysmem#SceDebugForKernel|SceDebugForKernel]] || ? || Kernel || 0x88C17370<br />
|-<br />
| 3.60 || [[SceSysmem#SceDebugForDriver|SceDebugForDriver]] || ? || Kernel || 0x88758561<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysmemForTZS|SceSysmemForTZS]] || Secure || Kernel || 0x8680060<br />
|-<br />
| 1.69 || [[SceSysmem#SceDipswForTZS|SceDipswForTZS]] || Secure || Kernel || 0x9DBF584C<br />
|-<br />
| 1.69 || [[SceSysmem#SceCpuForTZS|SceCpuForTZS]] || Secure || Kernel || 0xC516B23E<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysclibForTZS|SceSysclibForTZS]] || Secure || Kernel || 0xC839BB78<br />
|-<br />
| 1.69 || [[SceSysmem#SceSysrootForTZS|SceSysrootForTZS]] || Secure || Kernel || 0xFEFF641D<br />
|-<br />
| 1.69 || [[SceSysmem#SceQafMgrForTZS|SceQafMgrForTZS]] || Secure || Kernel || 0x637069DD<br />
|-<br />
| 1.69 || [[SceSysmem#ScePmMgrForTZS|ScePmMgrForTZS]] || Secure || Kernel || 0x27F1AFD8<br />
|-<br />
| 1.69 || [[SceSysmem#SceSblAIMgrForTZS|SceSblAIMgrForTZS]] || Secure || Kernel || 0x60D19047<br />
|}<br />
<br />
== Memory Block Type ==<br />
The <code>type</code> parameter indicates what kind of memory to allocate. Here is a mapping of <code>type</code> flags to ARM MMU flags. Higher bits are used for other options including where to allocate from. Not all flag values are valid, there is a table of valid types in the kernel. You cannot, for example, allocate RWX memory.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Mask !! Value !! Description<br />
|-<br />
| 0x10000 || 0x10000 || Global. <code>nG</code> bit NOT set<br />
|-<br />
| 0xFF00 || 0x800 || <code>B</code> bit set. Sharable device memory.<br />
|-<br />
| 0xFF00 || 0x2000 || <code>TEX[2]</code> and <code>TEX[0]</code> bit set. Outer cache Write-back, Write-Allocate. Inner cache non-cachable.<br />
|-<br />
| 0xFF00 || 0x4000 || <code>TEX[2]</code> and <code>B</code> bit set. Outer cache non-cachable. Inner cache Write-back, Write-Allocate<br />
|-<br />
| 0xFF00 || 0x8000 || <code>TEX[0]</code> bit set. <code>S</code> bit unset. Outer and inner non-cachable. Not sharable.<br />
|-<br />
| 0xFF00 || 0xD000 || <code>TEX[0]</code> bit set. <code>C,B</code> bits set. Outer and inner Write-back, Write-Allocate.<br />
|-<br />
| 0xFF || 0x4 || <code>AP[2:0] = 5</code>, <code>XN=1</code>. Privileged RO, User NA.<br />
|-<br />
| 0xFF || 0x5 || <code>AP[2:0] = 5</code>. Privileged RX, User NA.<br />
|-<br />
| 0xFF || 0x6 || <code>AP[2:0] = 1</code>, <code>XN=1</code>. Privileged RW, User NA.<br />
|-<br />
| 0xFF || 0x7 || <code>AP[2:0] = 1</code>. Privileged RWX, User NA. (Never used)<br />
|-<br />
| 0xFF || 0x50 || <code>AP[2:0] = 7</code>. Privileged RX, User RX.<br />
|-<br />
| 0xFF || 0x60 || <code>AP[2:0] = 3</code>, <code>XN=1</code>. Privileged RW, User RW.<br />
|-<br />
| 0xFF || 0x40 || <code>AP[2:0] = 7</code>, <code>XN=1</code>. Privileged RO, User RO.<br />
|-<br />
|}<br />
<br />
== SceSysmemForKernel ==<br />
<br />
==== sceKernelAllocMemBlockForKernel ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xC94850C9<br />
|-<br />
| 1.69 (secure)<br />
| 0x402EB970<br />
|}<br />
<source lang="c"><br />
struct SceKernelAllocMemKernelBlockOpt<br />
{<br />
uint32_t size; // 0x34<br />
uint32_t unk;<br />
uint32_t attr;<br />
uint32_t unk2;<br />
uint32_t paddr;<br />
uint32_t align;<br />
uint32_t unk3[3];<br />
uint32_t processid;<br />
uint32_t unk4[3];<br />
};<br />
int sceKernelAllocMemBlockForKernel(const char *name, int32_t type, uint32_t vsize, struct SceKernelAllocMemKernelBlockOpt *pOpt);<br />
</source><br />
<br />
The interface is the same as the user version of this call, however more types can be specified and more options are in the pOpt argument.<br />
<br />
To allocate a kernel RW block of memory, specify <code>type = 0x6020D006</code>.<br />
<br />
To allocate a block of memory with a specific physical address, specify <code>type = 0x20100206</code>, <code>pOpt->attr = 2</code>, and <code>pOpt->paddr = physical address</code>.<br />
<br />
To allocate a block of memory that is kernel executable, specify <code>type = 0x1020D005</code>.<br />
<br />
To allocate a block of memory inside the CDRAM, specify <code>type = 0x40404006</code>.<br />
<br />
==== Unrestricted Write for Process ====<br />
Unrestricted memcpy to the virtual address space for process <code>pid</code>. Both <code>dst</code> and <code>src</code> must be in the address space of <code>pid</code> but <code>src</code> must also be accessible in the address space of the caller. This is normally used for resolving stubs in module loads.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x30931572<br />
|}<br />
<source lang="c">int unrestricted_memcpy_for_pid(int pid, void *dst, void *src, size_t len);</source><br />
<br />
== SceSysmemForDriver ==<br />
<br />
==== sceKernelMemcpyKernelToUser ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x6D88EF8A<br />
|}<br />
<source lang="c">int sceKernelMemcpyKernelToUser(uint32_t uaddr, const void *kaddr, uint32_t len);</source><br />
==== sceKernelMemcpyUserToKernel ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xBC996A7A<br />
|}<br />
<source lang="c">int sceKernelMemcpyUserToKernel(void *kaddr, uint32_t uaddr, uint32_t len);</source><br />
<br />
==== sceKernelMemcpyUserToKernelForPid ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 3.60 (non-secure)<br />
| 0x605275F8<br />
|}<br />
<source lang="c">int sceKernelMemcpyUserToKernelForPid(int pid, void *kaddr, uint32_t uaddr, uint32_t len);</source><br />
<br />
Same as above, but copies from the specified process.<br />
<br />
==== strncpyKernelToUser ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x80BD6FEB<br />
|}<br />
<source lang="c">int strncpyKernelToUser(uint32_t uaddr, const void *kaddr, uint32_t maxlen);</source><br />
==== strncpyUserToKernel ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xDB3EC244<br />
|}<br />
<source lang="c">int strncpyUserToKernel(void *kaddr, uint32_t uaddr, uint32_t maxlen);</source><br />
==== strnlenUserSrc ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xB429D419<br />
|}<br />
<source lang="c">int strnlenUserSrc(uint32_t uaddr, uint32_t maxlen);</source><br />
==== get_paddr ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x8D160E65<br />
|-<br />
| 1.69 (secure)<br />
| 0x1DEADF6C<br />
|}<br />
<source lang="c">int get_paddr(void *vaddr, void **result);</source><br />
<br />
This will write the physical address for a virtual address <code>vaddr</code> to memory pointed to by <code>result</code>. Returns <0 on error, values >=0 indicate success.<br />
<br />
==== get paddr list ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xE68BEEBD<br />
|}<br />
<source lang="c"><br />
struct addr_pair<br />
{<br />
uint32_t addr;<br />
uint32_t length;<br />
};<br />
struct paddr_list_req<br />
{<br />
uint32_t size; // 0x14<br />
uint32_t output_buffer_size;<br />
uint32_t unk;<br />
uint32_t ret_count;<br />
struct addr_pair *output_buffer;<br />
};<br />
input.addr = vaddr;<br />
input.length = length;<br />
int get_paddr_list(struct addr_pair *input, struct paddr_list_req *req);<br />
</source><br />
<br />
This function takes in two parameters: an array of length 2 specifying the virtual address and the size of the block of memory and a request information. The function will write into <code>output_buffer</code> an array of <code>addr_pair</code> that encompasses the block of memory specified in the input. <code>req->ret_count</code> will contain the number of entries written. If <code>output_buffer</code> is null, it will just write the count.<br />
<br />
==== sceKernelGetMemBlockBaseForDriver ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xA841EDDA<br />
|}<br />
<source lang="c">int sceKernelGetMemBlockBaseForDriver(int blkid, void **base);</source><br />
<br />
==== sceKernelFindMemBlockByAddrForDriver ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x8A1742F6<br />
|}<br />
<source lang="c">int sceKernelFindMemBlockByAddrForDriver(void *base, int);</source><br />
<br />
==== Remap Block ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.05 (non-secure)<br />
| 0x8d332ae1<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xDFE2C8CB<br />
|}<br />
<source lang="c">int sysmem_remap(int blkid, int type);</source><br />
<br />
This is used to remap RW memory as RX. To do this, first allocate a memory block of type <code>0x1020D006</code>. After you are done writing, call this with <code>type</code> set to <code>0x1020D005</code>.<br />
<br />
==== Create Heap Pool ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x9328E0E8<br />
|}<br />
<source lang="c"><br />
typedef struct {<br />
int size; // 28<br />
int flags; // usually 0x1 <br />
int unk;<br />
int unk;<br />
int block_type;<br />
int unk;<br />
int unk;<br />
} pool_arg_t;<br />
int heap_pool_create(const char *name, int size, pool_arg_t *opt); // opt can be NULL<br />
</source><br />
<br />
The heap pool is thread safe.<br />
<br />
==== Destroy Heap Pool ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xD6437637<br />
|}<br />
<source lang="c"><br />
int heap_pool_destroy(int pool_uid);<br />
</source><br />
<br />
==== Alloc from Heap Pool ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x7B4CB60A<br />
|}<br />
<source lang="c"><br />
void *heap_pool_malloc(int pool_uid);<br />
</source><br />
<br />
==== Free from Heap Pool ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x3EBCE343<br />
|}<br />
<source lang="c"><br />
int heap_pool_free(int pool_uid, void *ptr);<br />
</source><br />
<br />
==== Map User to Kernel ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x7D4F8B5F<br />
|}<br />
Permission is either "1" for read only, no execute or "2"/"3" for read write, no execute. Type is either 0, 1, or 17 and affects the block type. 0 is default. This will allocate kernel memory starting at kernel_page. To get the same memory as the user pointer, add the kernel_offset. kernel_size is how much is allocated.<br />
<source lang="c"><br />
int map_user_to_kernel(int permission, int type, void *user_buf, int size, void **kernel_page, int *kernel_size, int *kernel_offset);<br />
</source><br />
<br />
==== Switch TTB to PID ====<br />
Changes the TTBR to point to the tables for a given PID.<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x6F2ACDAE<br />
|-<br />
| 3.60 (non-secure)<br />
| N/A<br />
|}<br />
<source lang="c"><br />
int switch_ttb(int pid);<br />
</source><br />
<br />
==== Write to RO for PID ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x571D2739<br />
|}<br />
<source lang="c"><br />
int write_to_ro(int pid, void *dst, const void *src, int size);<br />
</source><br />
<br />
==== Write to RX for PID ====<br />
Same as write to RO but does a cache flush.<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x30931572<br />
|}<br />
<source lang="c"><br />
int write_to_rx(int pid, void *dst, const void *src, int size);<br />
</source><br />
<br />
==== Find Int for PID ====<br />
Looks for an integer in user space.<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x8334454F<br />
|}<br />
<source lang="c"><br />
int find_int(int pid, void *haystack, int needle, int size);<br />
</source><br />
<br />
==== strnlen for PID ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x9929EB07<br />
|}<br />
<source lang="c"><br />
int user_strnlen(int pid, char *ptr, int size);<br />
</source><br />
<br />
==== strncpy for PID ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x75AAF178<br />
|}<br />
<source lang="c"><br />
int user_strncpy(int pid, char *dst, const char *kern_src, int size);<br />
</source><br />
<br />
==== memcpyk2u unchecked for PID ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xFED82F2D<br />
|}<br />
<source lang="c"><br />
int user_memcpyk2u(int pid, void *dst, const void *kern_src, int size);<br />
</source><br />
<br />
==== memcpyk2u checked for PID ====<br />
This will not crash on invalid user pointers, but instead return error.<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x6B825479<br />
|}<br />
<source lang="c"><br />
int user_safe_memcpyk2u(int pid, void *dst, const void *kern_src, int size);<br />
</source><br />
<br />
==== memcpyu2u for PID ====<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x8E086C33<br />
|}<br />
<source lang="c"><br />
int user_memcpyu2u(int pid, void *dst, const void *src, int size);<br />
</source><br />
<br />
== SceSysmem ==<br />
<br />
The SceSysmem library is responsible for both low-level and high-level memory management. There are functions for allocating raw blocks of memory (similar to Linux <code>sbrk</code>) as well as functions for maintaining a heap-like structure (similar to <code>malloc</code>) for kernel, however [[SceLibKernel]] implements a proper heap and that is used for user code.<br />
<br />
=== sceKernelGetMemBlockInfoByRange ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6F3DB4<br />
|}<br />
=== sceKernelSyncVMDomain ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x19D2A81A<br />
|}<br />
=== sceKernelRemapMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3B29E0F5<br />
|}<br />
=== sceKernelGetMemBlockInfoByAddr ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x4010AD65<br />
|}<br />
=== sceKernelMapMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x7B763A21<br />
|}<br />
=== sceKernelGetSubbudgetInfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x832B4A65<br />
|}<br />
=== sceKernelGetFreeMemorySize ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x87CC580B<br />
|}<br />
=== sceKernelOpenMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x8EB8DFBB<br />
|}<br />
=== sceKernelOpenVMDomain ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x9CA3EB2B<br />
|}<br />
=== sceKernelFindMemBlockByAddr ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA33B99D1<br />
|}<br />
=== sceKernelFreeMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA91E15EE<br />
|}<br />
=== sceKernelCloseMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB680E3A0<br />
|}<br />
=== sceKernelGetMemBlockBase ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB8EF5818<br />
|}<br />
=== sceKernelAllocMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB9D5EBDE<br />
|}<br />
=== sceKernelPartialMapMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xC0A59868<br />
|}<br />
=== sceKernelPartialUnmapMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xCA99929B<br />
|}<br />
=== sceKernelCloseVMDomain ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD6CA56CA<br />
|}<br />
=== sceKernelAllocMemBlockForVM ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE2D7E137<br />
|}<br />
=== sceKernelUnmapMemBlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xEE30D976<br />
|}<br />
<br />
== SceDipsw ==<br />
== SceCpu ==<br />
This library provides wrapper for much ARM CP15 co-processor access as well as low level support of spinlocks and other synchronization primitives.<br />
== SceSysclib ==<br />
The C standard library for use in the kernel only. (User code have [[SceLibKernel]], which confusingly is user-only code). Include standard string functions (no insecure variants like <code>strcpy</code>).<br />
=== strcmp ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x0B33BC43<br />
|}<br />
=== strncmp ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x12cee649<br />
|}<br />
=== strstr ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x1304A69D<br />
|}<br />
=== rshift ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x1D89F6C0<br />
|}<br />
=== memcpy ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x40c88316<br />
|}<br />
=== strchr ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x38463759<br />
|}<br />
=== memset2 ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x502B000D<br />
|}<br />
<br />
=== memmove ===<br />
On 1.69, this seems to be implemented incorrectly.<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x6CC9C1A1<br />
|}<br />
=== strrchr ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0x7F0E0835<br />
|}<br />
=== strncat ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xA1D1C32C<br />
|}<br />
=== strtol ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xAB77C5AA<br />
|}<br />
=== snprintf ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xAE7A8981<br />
|}<br />
=== sceKernelStackCheckFail ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xb997493d<br />
|}<br />
=== strnlen ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xCD4BD884<br />
|}<br />
=== strlen ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xCFC6A9AC<br />
|}<br />
=== memcmp ===<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69 (non-secure)<br />
| 0xF939E83D<br />
|}<br />
<br />
== SceDipsw ==<br />
<br />
=== sceKernelCheckDipsw ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x1C783FB2<br />
|}<br />
=== sceKernelClearDipsw ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x800EDCC1<br />
|}<br />
=== sceKernelSetDipsw ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x817053D4<br />
|}<br />
== SceDipswForDriver ==<br />
== SceUartForKernel ==<br />
== SceCpu ==<br />
<br />
<br />
=== sceKernelCpuId ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x2704CFEE<br />
|}<br />
== SceCpuForKernel ==<br />
==== Unrestricted Write for Kernel ====<br />
Unrestricted memcpy by first setting the <code>DACR</code> register to <code>0xFFFFFFFF</code> and then doing a memcpy.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version<br />
! NID<br />
|-<br />
| 1.69<br />
| 0x8C683DEC<br />
|}<br />
<source lang="c">int unrestricted_memcpy_for_kernel(void *dst, void *src, size_t len);</source><br />
<br />
== SceCpuForDriver ==<br />
=== SceCpuForDriver_BF82DEB2_lock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xBF82DEB2<br />
|}<br />
<br />
<source lang="c">int SceCpuForDriver_BF82DEB2_lock(int *addr);</source><br />
<br />
=== SceCpuForDriver_D6ED0C46_unlock ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xD6ED0C46<br />
|}<br />
<br />
<source lang="c">int SceCpuForDriver_D6ED0C46_unlock(int *addr);</source><br />
<br />
These two functions implement a simple mutual exclusive access on a resource addr using LDREX/STREX.<br />
<br />
<hr><br />
<br />
=== SceCpuForDriver_D32ACE9E_lock_int ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0xD32ACE9E<br />
|}<br />
<br />
<source lang="c">int SceCpuForDriver_D32ACE9E_lock_int(int *addr);</source><br />
<br />
=== SceCpuForDriver_7BB9D5DF_unlock_int ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0x7BB9D5DF<br />
|}<br />
<br />
<source lang="c">void SceCpuForDriver_7BB9D5DF_unlock_int(int *addr, int prev_state);</source><br />
<br />
Same as the pair above, but while mutex is held, interrupts are disabled. Used like this:<br />
<source lang="c"><br />
int prev_state = SceCpuForDriver_D32ACE9E_lock_int(mutex);<br />
// do work<br />
SceCpuForDriver_7BB9D5DF_unlock_int(mutex, prev_state);<br />
</source><br />
<br />
<hr><br />
=== SceCpuForDriver_4C38CE4D_lock_int_2 ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0x4C38CE4D<br />
|}<br />
<br />
=== SceCpuForDriver_9EC91017_unlock_int_2 ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0x9EC91017<br />
|}<br />
<br />
<br />
Same as the pair above, but stores 0x80000000 as the addr value instead of LR.<br />
<br />
<hr><br />
=== SceCpuForDriver_821FC0EE_disable_irq ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x821FC0EE<br />
|}<br />
<br />
<source lang="c">int SceCpuForDriver_821FC0EE_disable_irq(void);</source><br />
<br />
Disables irq (but not fiq) and returns previous interrupt bit status (so either 0 or 0x80).<br />
<br />
=== SceCpuForDriver_F5BAD43B_restore_irq ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xF5BAD43B<br />
|}<br />
<br />
<source lang="c">void SceCpuForDriver_F5BAD43B_restore_irq(int previous_state);</source><br />
<br />
Restores previous irq state, pass either 0 or 0x80.<br />
<br />
=== SceCpuForDriver_5E4D5DE1_get_multproc_id_reg ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.50 || 0x5E4D5DE1<br />
|}<br />
<br />
Return the CPU ID of the current core. <br />
<br />
== SceSysclibForKernel ==<br />
== SceSysclibForDriver ==<br />
=== __aeabi_uidiv ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0xA9FF1205<br />
|}<br />
<br />
=== __aeabi_uidivmod ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0xA46CB7DE<br />
|}<br />
<br />
=== memcpy ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x40C88316<br />
|}<br />
<br />
=== memset ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x0AB9BF5C<br />
|}<br />
<br />
=== strchr ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.35 || 0x38463759<br />
|}<br />
<br />
=== strncmp ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x12CEE649<br />
|}<br />
<br />
== SceSysrootForKernel ==<br />
<br />
=== sceSysrootGetElfInfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xF10AB792<br />
|}<br />
<br />
<source lang="c"><br />
typedef struct elf_info_pair<br />
{<br />
uint32_t size; // 0x0C<br />
char* elf_data; <br />
uint32_t elf_size;<br />
} elf_info_pair;<br />
<br />
int sceSysrootGetElfInfo(int index, elf_info_pair* state);<br />
</source><br />
<br />
== SceKernelUtilsForDriver ==<br />
Crypto utilities<br />
<br />
=== AES Init ===<br />
This sets up the AES engine. <code>ctx</code> is a 960 byte buffer (int 1.69). <code>blocksize</code> and <code>keysize</code> is the security in bits. 128/196/256 are supported values.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF12B6451<br />
|}<br />
<source lang="c">int aes_init(void *ctx, int blocksize, int keysize, const char *key);</source><br />
<br />
=== AES Encrypt ===<br />
Encrypt with AES. There are two functions that are the same on 1.69.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xC2A61770<br />
|-<br />
| 1.69 || 0x302947B6<br />
|}<br />
<source lang="c">int aes_encrypt(void *ctx, const char *src, char *dst);</source><br />
<br />
=== AES Decrypt ===<br />
Decrypt with AES.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD8678061<br />
|}<br />
<source lang="c">int aes_decrypt(void *ctx, const char *src, char *dst);</source><br />
<br />
== SceZlibForDriver ==<br />
[http://www.zlib.net/ zlib] compression library.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Firmware !! zlib version<br />
|-<br />
| 1.60 || 1.2.5<br />
|}<br />
<br />
=== inflate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xE4F34A68<br />
|}<br />
<br />
=== deflate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xE859D60F<br />
|}<br />
<br />
=== deflateReset ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x68CFEA45<br />
|}<br />
<br />
=== crc32 ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0xE0CE06C0<br />
|}<br />
<br />
=== adler32 ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x98619620<br />
|}<br />
<br />
=== inflateSetDictionary ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.60 || 0x7B16DBD6<br />
|}<br />
<br />
== SceKernelSuspendForDriver ==<br />
<br />
Libraries can register callbacks for handling suspend/resume related events.<br />
<br />
=== Register Callback ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x04C05D10<br />
|}<br />
<source lang="c"><br />
typedef struct {<br />
uint32_t size; // 24<br />
uint32_t unk1;<br />
uint32_t unk2;<br />
uint32_t unk3;<br />
uint32_t unk4;<br />
uint32_t unk5;<br />
} suspend_args_t;<br />
typedef int (suspend_callback_t)(int resume, int eventid, suspend_args_t *args, void *opt);<br />
int suspend_register_callback(const char *name, suspend_callback_t *callback_func, void *opt);<br />
</source><br />
Registers a function for handling suspend/resume. <code>resume</code> is 0 if we are currently suspending and 1 if we are currently resuming. <code>opt</code> is passed from the registration. Registration <br />
adds an entry to a linked list and returns the block id for the new entry.<br />
<br />
=== Unregister ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xDD61D621<br />
|}<br />
<source lang="c"><br />
int suspend_unregister(int id);<br />
</source><br />
<br />
Call with the id returned from <code>suspend_register_callback</code> to remove the entry from the linked list and free the memory.<br />
<br />
=== Make Callback ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD4622EA8<br />
|}<br />
<source lang="c"><br />
int suspend_make_callback(int resume, int eventid, suspend_args_t *args, int stop_on_error);<br />
</source><br />
<br />
This will go through the linked list and call each callback. If <code>stop_on_error</code> is set, then the first callback that returns a negative value will stop the call chain and return the block id of the callback that broke the chain. Otherwise, this function will invoke each callback and return zero.<br />
<br />
=== Reset auto-suspend timer ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xE0489831<br />
|}<br />
<source lang="c"><br />
int reset_autosuspend_timer(int unk);<br />
</source><br />
<br />
== SceQafMgrForDriver ==<br />
Provides many device permission checks including Vita model checks, running app privilege checks, and so on.<br />
== ScePmMgrForDriver ==<br />
== SceSblAIMgrForDriver ==<br />
== SceProcEventForDriver ==<br />
== SceSysrootForDriver ==<br />
== SceDebugLed ==<br />
== SceDebugLedForDriver ==<br />
== SceDebugForKernel ==<br />
== SceDebugForDriver ==<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Secure_Modules_Functions&diff=2623
Secure Modules Functions
2017-02-07T05:11:37Z
<p>St4rk: </p>
<hr />
<div>Depending on the F00D SELF that is currently loaded, different commands are handled.<br />
<br />
== Request Buffer ==<br />
<br />
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 shut down the currently loaded F00D SELF.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0 || 0x4 || Size of buffer<br />
|-<br />
| 0x4 || 0x4 || Command ID<br />
|-<br />
| 0x8 || 0x4 || Return value (output)<br />
|-<br />
| 0xC || 0x34 || Unknown/Unused<br />
|-<br />
| 0x40 || Variable (max 0xFC0) || Command specific buffer<br />
|-<br />
|}<br />
<br />
=== Physical Address List ===<br />
<br />
A common format used in these requests is a list of physical address and size. This simple structure is defined below. See [[SceSysmem#get_paddr_list]] for information on creating this list.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0 || 0x4 || Physical Address<br />
|-<br />
| 0x4 || 0x4 || Size<br />
|-<br />
|}<br />
<br />
This data format is used when passing large buffers of data to F00D. This is because the memory manager in kernel could allocate contiguous virtual addresses that corresponds to varying physical addresses.<br />
<br />
== kprx_auth_sm.self ==<br />
<br />
This is a special SELF that is found in the boot [[SLB2]] partition. The raw (encrypted) SELF is found in secure world memory (placed there by an early bootloader). It is used to decrypt SELFs for ARM. The SELF header is passed into a page aligned buffer and a [[F00D Commands#Physical Address List|paddr list]] is generated from it.<br />
<br />
=== 0x10001 ===<br />
<br />
Parses the SELF header for decryption. The header is copied to the F00D private memory region first (on 1.69 with 0x1000 sized header, it is at <code>0x00811CC0</code> in F00D memory space.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || 0x1 if user SELF, otherwise 0x0<br />
|-<br />
| 0x48 || 0x8 || <code>0x2808000000000001LL</code><br />
|-<br />
| 0x50 || 0x8 || <code>0xF000C000000080LL</code><br />
|-<br />
| 0x58 || 0x8 || <code>0xFFFFFFFF00000000LL</code><br />
|-<br />
| 0x60 || 0x10 || Unknown<br />
|-<br />
| 0x70 || 0x8 || <code>0xC300003800980LL</code><br />
|-<br />
| 0x78 || 0x8 || <code>0x8009800000LL</code><br />
|-<br />
| 0x80 || 0x8 || Unknown<br />
|-<br />
| 0x88 || 0x8 || <code>0xFFFFFFFF00000000LL</code><br />
|-<br />
| 0x90 || 0x8 || Unknown<br />
|-<br />
| 0x98 || 0x40 || Not used<br />
|-<br />
| 0xD8 || 0x60 || Return data (0x90 length overwriting) ?<br />
|-<br />
| 0x138 || 0x10 || Copy of data at <code>0x68</code><br />
|-<br />
| 0x148 || 0x10 || Unknown<br />
|-<br />
| 0x158 || 0x4 || <code>0x10</code><br />
|-<br />
| 0x15C || 0xC || Unknown<br />
|-<br />
| 0x168 || 0x4 || [[F00D Commands#SELF Path Code|SELF path code]]<br />
|-<br />
| 0x16C || 0x4 || Unknown<br />
|-<br />
| 0x170 || 0x4 || Number of paddr list entries for buffer<br />
|-<br />
| 0x174 || 0x4 || Physical address of paddr list<br />
|-<br />
|}<br />
<br />
==== SELF Path Code ====<br />
<br />
This code is found by the path the SELF was loaded from. It's used by F00D to check if the SELF being loaded from an allowed partition. A path that does not start with any of the following will have <code>0</code> returned as the code. It could also be used to select the key used in decryption.<br />
<br />
{| class="wikitable sortable"<br />
|-<br />
! Path !! Code<br />
|-<br />
| sd0: || 1<br />
|-<br />
| os0: || 2<br />
|-<br />
| vs0: || 3<br />
|-<br />
| vd0: || 4<br />
|-<br />
| tm0: || 5<br />
|-<br />
| ur0: || 6<br />
|-<br />
| host0: || 7<br />
|-<br />
| ud0: || 11<br />
|-<br />
| ux0:app || 23<br />
|-<br />
| ux0:patch || 24<br />
|-<br />
| ux0:data || 25<br />
|-<br />
| ux0:user || 0<br />
|-<br />
| ux0: || 12<br />
|-<br />
| gro0:app || 13<br />
|-<br />
| grw0:patch || 14<br />
|-<br />
| sa0: || 15<br />
|-<br />
| mfa0: || 16<br />
|-<br />
| mfb0: || 17<br />
|-<br />
| lma0: || 18<br />
|-<br />
| lmb0: || 19<br />
|-<br />
| lmc0: || 20<br />
|-<br />
| lmd0: || 21<br />
|-<br />
| pd0: || 22<br />
|-<br />
|}<br />
<br />
=== 0x20001 ===<br />
<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Segment number<br />
|-<br />
| 0x44 || 0x4 || Return value. <code>0x1</code> if not compressed, <code>0x2</code> is compressed.<br />
|-<br />
| 0x48 || 0x8 || Unknown<br />
|-<br />
|}<br />
<br />
=== 0x30001 ===<br />
<br />
Decrypt a buffer from the SELF corresponding to the program segment number passed in above. The segment is read in <code>0x10000</code> chunks and is decrypted in place (the input buffer will contain the decrypted data). A [[F00D Commands#Physical Address List|paddr list]] is generated from the buffer. The input buffer and output buffer can be the same.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Number of entries in input paddr list<br />
|-<br />
| 0x44 || 0x4 || Physical address of the input paddr list<br />
|-<br />
| 0x48 || 0x4 || Number of entries in output paddr list<br />
|-<br />
| 0x4C || 0x4 || Physical address of the output paddr list<br />
|-<br />
|}<br />
<br />
=== 0x40001 sceSblAuthMgrGetEKc ===<br />
Decrypts provided buffer in ECB mode using one of three keys.<br />
<br />
Used by [[SceSblAuthMgr]] for getting some key?<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x100 || Data Buffer (under 0x100 bytes)<br />
|-<br />
| 0x140 || 0x4 || Data Size - must be under 0x100<br />
|-<br />
| 0x144 || 0x4 || Key ID (0,1,2)<br />
|-<br />
| 0x148 || 0x4 || Set to 0<br />
|-<br />
| 0x14C || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x50001 sceSblAuthMgrSetDmac5Key ===<br />
Used by [[SceSblAuthMgr]] to set key for decryption (?).<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8-0x10 || Key (64/128/196/256 bits)<br />
|-<br />
| 0x140 || 0x4 || Key size (in bytes)<br />
|-<br />
| 0x144 || 0x4 || Key ID<br />
|-<br />
| 0x148 || 0x4 || Slot ID<br />
|-<br />
| 0x14C || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x60001 sceSblAuthMgrClearDmac5Key ===<br />
Used by [[SceSblAuthMgr]] for clearing the Dmac5 Key<br />
<br />
=== 0x70001 sceSblAuthMgrDecBindData ===<br />
Used by [[SceSblAuthMgr]] and [[SceNpdrm]] for game card binding data used in conjunction with the RIF license file on the gamecard in deriving the per game klicensee key.<br />
<br />
=== 0x80001 ===<br />
Used by [[SceSblAuthMgr]] for used by the VSH function _vshSblAuthMgrVerifySpsfo.<br />
<br />
== act_sm.self ==<br />
<br />
=== 0x2 ===<br />
<br />
Verify afv data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x1 || Format version<br />
|-<br />
| 0x45 || 0x3 || Unused<br />
|-<br />
| 0x48 || 0x4 || Issue number (increment each activation, prevent rollback)<br />
|-<br />
| 0x4C || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x50 || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x54 || 0x10 || Activation key<br />
|-<br />
| 0x64 || 0x1C || Unused<br />
|-<br />
| 0x80 || 0x40 || Encrypted Data (I think 0x20 byte data + 0x20 byte HMAC)<br />
|-<br />
|}<br />
<br />
=== 0x4 ===<br />
<br />
Verify activation data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x4 || Issue number<br />
|-<br />
| 0x48 || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x4C || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x50 || 0x10 || Unknown (see below)<br />
|-<br />
|}<br />
<br />
=== 0x5 ===<br />
<br />
Get activation data. The returned data is sent to Syscon at offset 0x520.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Magic "act\0"<br />
|-<br />
| 0x44 || 0x4 || Issue number<br />
|-<br />
| 0x48 || 0x4 || Start validity time unix timestamp<br />
|-<br />
| 0x4C || 0x4 || End validity time unix timestamp<br />
|-<br />
| 0x50 || 0x10 || Unknown (returned data)<br />
|-<br />
|}<br />
<br />
=== 0x7 ===<br />
<br />
Check if activation is valid. The activation data is read from Syscon at offset 0x520.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Current time unix timestamp<br />
|-<br />
| 0x48 || 0x8 || Unknown<br />
|-<br />
| 0x50 || 0x20 || Activation data<br />
|-<br />
|}<br />
<br />
=== 0xA ===<br />
<br />
Introduced in 2.12. Check if new activation is valid. Extended activation check with a signature. This is ran when installing a new afv.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x80 || Same buffer as command 0x2 (new activation data)<br />
|-<br />
| 0xC0 || 0x100 || Signature over new activation data<br />
|-<br />
| 0x1C0 || 0x80 || Same buffer as command 0x2 (previous activation data)<br />
|-<br />
| 0x240 || 0x100 || Signature over previous activation data<br />
|-<br />
| 0x340 || 0x20 || Same buffer as command 0x4 (new activation buffer from syscon)<br />
|-<br />
|}<br />
<br />
=== 0xB ===<br />
<br />
Introduced in 2.12. Check if current activation is valid. Extended activation check with signature. This is ran on boot.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Current time<br />
|-<br />
| 0x48 || 0x8 || Some return value<br />
|-<br />
| 0x50 || 0x8 || Unknown<br />
|-<br />
| 0x58 || 0x20 || Same buffer as command 0x4 (activation buffer from syscon)<br />
|-<br />
| 0x78 || 0x80 || Same buffer as command 0x2<br />
|-<br />
| 0xF8 || 0x100 || Signature over activation data<br />
|-<br />
|}<br />
<br />
== aimgr_sm.self ==<br />
<br />
=== 0x1 ===<br />
<br />
Returns 16 byte console id (used in vshSblAimgrGetConsoleId)<br />
<br />
=== 0x3 ===<br />
<br />
Used in vshSblAimgrGetVisibleId<br />
<br />
=== 0x2 ===<br />
<br />
Returns the console's OpenPSID. Also known as the "activation key" for PDEL and PTEL.<br />
<br />
=== 0x4 ===<br />
<br />
Used in vshSblAimgrGetPscode2<br />
<br />
== compat_sm.self ==<br />
<br />
=== 0x10006 ===<br />
Seems to be called on init and before resume of PSP<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Unknown<br />
|-<br />
| 0x44 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
=== 0x20006 ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Set to 0<br />
|-<br />
| 0x44 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
== encdec_w_portability_sm.self ==<br />
This seem to be used to do some kind of key derivation. May also be used as a general purpose encryption engine.<br />
<br />
=== 0x1000A ===<br />
<br />
Encrypt data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Key ID (max 0x0A)<br />
|-<br />
| 0x44 || 0x4 || Output Length<br />
|-<br />
| 0x48 || 0x20 || Output<br />
|-<br />
| 0x68 || 0x4 || Input Length (max 0x20)<br />
|-<br />
| 0x6C || 0x20 || Input<br />
|-<br />
| 0x8C || 0x10 || IV<br />
|-<br />
|}<br />
<br />
=== 0x2000A ===<br />
<br />
Decrypt data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Key ID (max 0xA)<br />
|-<br />
| 0x44 || 0x4 || Input Length (max 0x20)<br />
|-<br />
| 0x48 || 0x20 || Input<br />
|-<br />
| 0x68 || 0x4 || Output Length<br />
|-<br />
| 0x6C || 0x20 || Output<br />
|-<br />
| 0x8C || 0x10 || IV<br />
|-<br />
|}<br />
<br />
<br />
Return of 0x800f0002 means invalid service ID. For encdec_w_portability_sm, only 0x1000A and 0x2000A are supported.<br />
<br />
Return of 0x800f1716 means invalid key slot. Valid key slots are only 1-10.<br />
<br />
== gcauthmgr_sm.self ==<br />
<br />
=== 0x1000B ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x4 || Set to 1<br />
|-<br />
| 0x44 || 0x4 || GC Command<br />
|-<br />
| 0x48 || 0x800 || GC Buffer (Input/Output)<br />
|-<br />
| 0x848 || 0x4 || Unknown GC param<br />
|-<br />
| 0x84C || 0x4 || GC Buffer Length/Written<br />
|-<br />
| 0x850 || 0x4 || Set to 0<br />
|-<br />
|}<br />
<br />
Supported GC commands and structures<br />
<br />
==== 0x4 ====<br />
Original PSP Kirk 4 service for encrypting data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x4 || Set to 5<br />
|-<br />
| 0x4|| 0x4 || 0<br />
|-<br />
| 0x8|| 0x4|| 0<br />
|-<br />
| 0xC || 0x4 || Key Slot (1-0x7F not all available)<br />
|-<br />
| 0x10|| 0x4 || Data Length<br />
|-<br />
| 0x14|| 0x7EC || Data to encrypt<br />
|-<br />
|}<br />
<br />
==== 0x7 ====<br />
Original PSP Kirk 7 service for decrypting data<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x4 || Set to 4<br />
|-<br />
| 0x4|| 0x4 || 0<br />
|-<br />
| 0x8|| 0x4|| 0<br />
|-<br />
| 0xC || 0x4 || Key Slot (1-0x7F not all available)<br />
|-<br />
| 0x10|| 0x4 || Data Length<br />
|-<br />
| 0x14|| 0x7EC || Data to encrypt<br />
|-<br />
|}<br />
<br />
==== 0xC ====<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Private Key<br />
|-<br />
| 0x14|| 0x14 || Public Key X component<br />
|-<br />
| 0x28|| 0x14|| Public Key Y component<br />
|-<br />
|}<br />
<br />
==== 0xD ====<br />
Original PSP Kirk 0xD service for multiplying a 160bit ECC curve point with a value. Call with a multiplier, then a x and y point value.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Multiplier Value<br />
|-<br />
| 0x14|| 0x14 || Point X component<br />
|-<br />
| 0x28|| 0x14|| Point Y component<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || New Point X component<br />
|-<br />
| 0x14|| 0x14 || New Point Y component<br />
|-<br />
|}<br />
<br />
==== 0xE ====<br />
Original PSP Kirk 0xE service for 160bit Random number generation. Call with an empty buffer, the result structure is below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Cryptographic Random Number<br />
|-<br />
|}<br />
<br />
==== 0x10 ====<br />
Original PSP Kirk 0x10 service for 160bit ECC signing. Call and return structure below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x20 || Encrypted private key (see kirk-engine implementation for fuse_id process for encryption)<br />
|-<br />
| 0x20|| 0x14 || SHA1 hash of the content you want signed<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x14|| 0x14 || ECC Signature S component<br />
|-<br />
|}<br />
<br />
==== 0x11 ====<br />
Original PSP Kirk 0x11 service for 160bit ECC signature verification. Call with the below structure, then function will return pass or fail.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || Public Key X component<br />
|-<br />
| 0x14|| 0x14 || Public Key Y component<br />
|-<br />
| 0x28|| 0x14 || SHA1 hash of the content that is signed<br />
|-<br />
| 0x3C|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x50|| 0x14 || ECC Signature S component<br />
|-<br />
<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x14 || ECC Signature R component<br />
|-<br />
| 0x14|| 0x14 || ECC Signature S component<br />
|-<br />
|}<br />
<br />
==== 0x14 ====<br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Private Key<br />
|-<br />
| 0x1C|| 0x1C || Public Key X component<br />
|-<br />
| 0x38|| 0x1C|| Public Key Y component<br />
|-<br />
|}<br />
<br />
==== 0x15 ====<br />
New Vita Kirk 0x15 service for multiplying a 224bit ECC curve point with a value. Call with a multiplier, then a x and y point value.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Multiplier Value<br />
|-<br />
| 0x1C|| 0x1C || Point X component<br />
|-<br />
| 0x38|| 0x1C|| Point Y component<br />
|-<br />
|}<br />
<br />
Result<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || New Point X component<br />
|-<br />
| 0x1C|| 0x1C || New Point Y component<br />
|-<br />
|}<br />
<br />
==== 0x16 ====<br />
New Vita Kirk 0x16 service for 160bit Random number generation. Call with an empty buffer, the result structure is below.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x0|| 0x1C || Cryptographic Random Number<br />
|-<br />
|}<br />
<br />
==== 0x17 ====<br />
New Vita Kirk 0x17 service. Unknown, but buffer length is 0x3C. Almost certainly a 224bit version of 0x10<br />
<br />
==== 0x18 ====<br />
New Vita Kirk 0x18 service. Unknown, but buffer length is 0x8C. Almost certainly a 224bit version of 0x11<br />
<br />
==== 0x19 ====<br />
New Vita Kirk 0x19 service. Unknown, but buffer length is 0xE8. Related to IdStorage somehow. Almost certainly a 224bit version of 0x12<br />
<br />
==== 0x1B ====<br />
New Vita Kirk 0x1B service. This service is related to SceSdif and is used by SceSblGcAuthMgr.<br />
This service is part of SD MMC CMD56 custom initialization protocol.<br />
This is a data validation service with no response. Size of request is 0x53.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x10 || cmd56 packet7 chunk<br />
|-<br />
| 0x30|| 0x23 || cmd56 packet8 chunk<br />
|-<br />
|}<br />
<br />
==== 0x1C ====<br />
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. <br />
This is a data generation service. Size of request is 0x40. Size of response is 0x33.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x20 || cmd56 packet8 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x01 || command<br />
|-<br />
| 0x01|| 0x01 || unknown<br />
|-<br />
| 0x02|| 0x01 || size<br />
|-<br />
| 0x03|| 0x30 || data<br />
|-<br />
|}<br />
<br />
==== 0x1D ====<br />
New Vita Kirk 0x1D service. This service is related to SceSdif and is used by SceSblGcAuthMgr. <br />
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.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x10 || cmd56 packet13 chunk<br />
|-<br />
| 0x60|| 0x43 || cmd56 packet14 chunk<br />
|-<br />
|}<br />
<br />
==== 0x1E ====<br />
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.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x01 || parameter (value 2 or 3)<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x01 || command<br />
|-<br />
| 0x01|| 0x01 || unknown<br />
|-<br />
| 0x02|| 0x01 || size<br />
|-<br />
| 0x03|| 0x30 || data<br />
|-<br />
|}<br />
<br />
==== 0x1F ====<br />
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.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x20 || cmd56 packet15 chunk<br />
|-<br />
| 0x70|| 0x43 || cmd56 packet16 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || unknown<br />
|-<br />
|}<br />
<br />
==== 0x20 ====<br />
New 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 validation service. Size of request is 0x116. Size of response is 0x34.<br />
<br />
Request:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x20 || cmd56 packet6 chunk<br />
|-<br />
| 0x20|| 0x30 || cmd56 packet9 chunk<br />
|-<br />
| 0x50|| 0x20 || cmd56 packet17 chunk<br />
|-<br />
| 0x70|| 0x43 || cmd56 packet18 chunk<br />
|-<br />
| 0xB3|| 0x10 || cmd56 packet19 chunk<br />
|-<br />
| 0xC3|| 0x53 || cmd56 packet20 chunk<br />
|-<br />
|}<br />
<br />
Response:<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x00|| 0x34 || unknown<br />
|-<br />
|}<br />
<br />
==== 0x21 ====<br />
New Vita Kirk 0x21 service. Unknown, but buffer length is 0x34. <br />
<br />
==== 0x22 ====<br />
New Vita Kirk 0x22 service. Unknown, but buffer length is 0x3C. <br />
<br />
==== 0x23 ====<br />
New Vita Kirk 0x23 service. Unknown, but buffer length is 0x20.<br />
<br />
== pm_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
=== 0x3 ===<br />
=== 0x4 ===<br />
=== 0x5 ===<br />
=== 0x6 ===<br />
=== 0x7 ===<br />
=== 0x8 ===<br />
=== 0x9 ===<br />
=== 0xA ===<br />
<br />
== qaf_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== rmauth_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== spkg_verifier_sm_w_key_2.self ==<br />
<br />
=== 0xE0002 ===<br />
<br />
Used to decrypt lists stored in updates. Same format as [[F00D Commands#0x40002|0x40002]].<br />
<br />
== update_service_sm.self ==<br />
<br />
This is used by [[SceSblSsUpdateMgr]] to decrypt update packages extracted from [[PUP]] files. Both 0x40002 and 0x50002 reference buffers in the following way: an inner paddr list is generated for the buffer containing the data to encrypt/decrypt, then an outer paddr list is generated for the inner list. That means there's two levels of indirection in the paddr list.<br />
<br />
=== 0x10002 ===<br />
<br />
Verify PUP header.<br />
<br />
=== 0x20002 ===<br />
<br />
Verify PUP segment.<br />
<br />
=== 0x30002 ===<br />
<br />
Verify watermark.<br />
<br />
=== 0x40002 ===<br />
<br />
Decrypt package. Allocate a page aligned buffer and read the complete pkg file into the buffer. The buffer is decrypted in place.<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8 || Set to 0x0<br />
|-<br />
| 0x48 || 0x8 || Set to 0x1<br />
|-<br />
| 0x50 || 0x14 || <code>struct paddr_list_req</code> for Paddr list below<br />
|-<br />
| 0x64 || 0x14 || <code>struct paddr_list_req</code> for pkg buffer<br />
|-<br />
| 0x78 || Variable (max 0xF48) || Copy of paddr list for pkg buffer (contents described at 0x50)<br />
|-<br />
|}<br />
<br />
=== 0x50002 ===<br />
<br />
Re-encrypt enp files<br />
<br />
{| class="wikitable"<br />
|-<br />
! Offset !! Size !! Description<br />
|-<br />
| 0x40 || 0x8 || Unknown/Zero<br />
|-<br />
| 0x48 || 0x8 || Set to 1<br />
|-<br />
| 0x50 || 0x14 || <code>struct paddr_list_req</code> for paddr list copied to 0x78. Only count field is used.<br />
|-<br />
| 0x64 || 0x14 || <code>struct paddr_list_req</code> for inner paddr list. Not used.<br />
|-<br />
| 0x78 || Variable (max 0xF88) || Paddr list to paddr list to encrypt<br />
|-<br />
|}<br />
<br />
=== 0x60002 ===<br />
=== 0x70002 ===<br />
=== 0x80002 ===<br />
=== 0x90002 ===<br />
<br />
=== 0xA0002 ===<br />
<br />
Verify additional data.<br />
<br />
=== 0xB0002 ===<br />
=== 0xC0002 ===<br />
=== 0xD0002 ===<br />
<br />
== utoken_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
== mgkm_sm.self ==<br />
<br />
=== 0x1 ===<br />
=== 0x2 ===<br />
<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Cmep&diff=2496
Cmep
2017-01-28T22:44:35Z
<p>St4rk: /* Extra ports */</p>
<hr />
<div>This processor is hypothesized to perform most of the cryptography tasks including storing and handing of [[Keys|keys]]. There is little information about it though. The [[F00D Processor]] (named after the <code>e_machine</code> field of the ELF headers) is likely a custom [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP] core.<br />
<br />
== Communication ==<br />
Communication seems to go through some sort of FIFO register.<br />
<br />
=== Write ===<br />
To write, put the double word into <code>0xE0000010</code>. Next read <code>0xE0000010</code> until it returns 0, which indicates the data was read by the F00D processor.<br />
<br />
=== Read ===<br />
To read, get a double word from <code>0xE0000000</code>. If it returns 0, no data is available. Otherwise, acknowledge that the data has been read by putting the same data into <code>0xE0000000</code>.<br />
<br />
=== Extra ports ===<br />
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Port<br />
! Read<br />
! Write<br />
! Used by<br />
|-<br />
| 0xE0000004<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000008<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE000000C<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000014<br />
| YES<br />
| YES<br />
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]<br />
|-<br />
| 0xE0000018<br />
| YES<br />
| YES<br />
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]<br />
|-<br />
| 0xE000001C<br />
| YES<br />
| YES<br />
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]<br />
|-<br />
| 0xE0000054<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE0000058<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE000005C<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE0010000<br />
| YES<br />
| YES<br />
| Used by F00D Command 0 to prepare F00D to receive an address that contains the secure kernel enp.<br />
|-<br />
| 0xE0010004<br />
| YES<br />
| ?<br />
| Used by F00D Command 0 to check if the value written in <code>0xE0010000</code> is okay (it should return a value <= 0)<br />
|-<br />
<br />
|}<br />
<br />
== Protocol ==<br />
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Bit End<br />
! Bit Start<br />
! Name<br />
! Description<br />
|-<br />
| 31<br />
| 23<br />
| ?<br />
| ?<br />
|-<br />
| 22<br />
| 19<br />
| flag?<br />
| b1010, b0010, b0001<br />
|-<br />
| 18<br />
| 13<br />
| ?<br />
| Always 0<br />
|-<br />
| 12<br />
| 8<br />
| ID<br />
| [[F00D Processor#Command ID|Command ID]]<br />
|-<br />
| 7<br />
| 1<br />
| ?<br />
| Always 0<br />
|-<br />
| 0<br />
| 0<br />
| Valid<br />
| Set 1 to indicate command is valid<br />
|-<br />
|}<br />
<br />
=== Command ID ===<br />
There are a total of 14 commands. Below are notes on different commands. Commands pass data through the 0x100 shared buffer (set up in command 0).<br />
<br />
==== 0x0 ====<br />
<br />
This command is used to setup a shared buffer with F00D. First F00D will write in <code>0xE0000000</code> either 0x200 or 0x600 (and if an error happened, 0x400 ?). If the value 0x600 is written, it will first setup a buffer that contains the f00d secure kernel enp. First it will write 0x1 to <code>0xE0010000</code> and after that 0x0 to <code>0xE0010000</code>, next, it will wait <code>0xE0010000</code> return 0 and <code>0xE0010004</code> return a value <= 0x0. If everything goes alright, it will clear the low 2 bits of the f00d secure kernel enp address (normally at 0x1F850000) and OR it with 0x1 and then write it to <code>0xE0000010</code>. After it, the process is the same that the 0x200. If the value 0x200 is written, it will set the 0x100 sized shared buffer. First the physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written. <br />
<br />
==== 0x1 ====<br />
<br />
This command is called by a function inside the SceSblSmSchedForTZS_0xE72F2886 or SceSblSmsched_start (if an error happened while SceSblSmsched is initializing). This command seem to be used to ask the f00d to remove all resource allocated (like shared memory address, secure module loaded, etc), and probably power off or reset it.<br />
<br />
==== 0x2 ====<br />
<br />
Load sm.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for sm elf<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| ctx_0x4<br />
|-<br />
| 0x10<br />
| 0x4<br />
| ctx_0x8<br />
|-<br />
| 0x14<br />
| 0x4<br />
| ctx_0xC<br />
|-<br />
| 0x1C<br />
| 0x4<br />
| field_60: system version (2)<br />
|-<br />
| 0x20<br />
| 0x4<br />
| partition ID<br />
|}<br />
<br />
==== 0x3 ====<br />
<br />
Load previously suspended sm<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for suspend buffer<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| delayed_cmd<br />
|}<br />
<br />
==== 0x4 ====<br />
<br />
Suspend current sm<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for suspend buffer<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| delayed_cmd<br />
|}<br />
<br />
==== 0x5 ====<br />
<br />
Kill current sm<br />
<br />
==== 0x6 ====<br />
<br />
?<br />
<br />
==== 0x7 ====<br />
<br />
Unused.<br />
<br />
==== 0x8 ====<br />
<br />
Unused.<br />
<br />
==== 0x9 ====<br />
<br />
Set a 0x80 sized shared buffer.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| paddr<br />
|-<br />
| 0x4<br />
| 0x4<br />
| length<br />
|}<br />
<br />
==== 0xA ====<br />
<br />
Set the [[SCE]] encrypted revocation list.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for revocation list<br />
|}<br />
<br />
==== 0xB ====<br />
<br />
==== 0xC ====<br />
<br />
==== 0xD ====<br />
<br />
==== 0xE ====<br />
<br />
==== 0xF ====<br />
<br />
==== 0x10 ====<br />
<br />
== Interrupts ==<br />
<br />
There are 4 interrupts that f00d sends. There are only two interrupt handles, however.<br />
<br />
* <code>cry2arm0</code>: handles interrupt 200. This is notifications about current sm status changes (loaded, unloaded, suspended, etc)<br />
* <code>cry2arm123</code>: handles interrupts 201, 202, 203. This interrupt is sent once an sm command has finished processing (see below).<br />
<br />
== Executing sm commands ==<br />
<br />
When sm is loaded, you can execute a [[F00D_Commands|command it provides]] by writing into registers 0xE0000014, 0xE0000018, 0xE000001C paddr to the command buffer OR'd with 1.<br />
<br />
Command buffer structure:<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of header + data<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Command ID<br />
|-<br />
| 0x8<br />
| 0x4<br />
| unk1<br />
|-<br />
| 0xC<br />
| 0x4<br />
| unk2<br />
|-<br />
| 0x10<br />
| 0x30<br />
| padding<br />
|-<br />
| 0x40<br />
| variable, max=0x1000-0x40<br />
| data buffer<br />
|}<br />
<br />
Once result is available, ARM will get an interrupt 201-203. Read status code from 0xE0000004 (or 0xE0000008, 0xE000000C) and confirm you received it by writing it back to the same register.<br />
<br />
Possible results:<br />
<br />
* 1: command executed successfully<br />
* 3: invalid command ID<br />
* 5: invalid command buffer paddr (e.g. trying to pass secure memory)<br />
* 9: SCE_SBL_ERROR_COMMON_EIO<br />
<br />
== Memory ==<br />
<br />
<code>kprx_auth_sm.self</code> is allowed access to <code>0x1F000000</code>, <code>0x1F840000</code>, <code>0x20000000</code>, and <code>0x40300000</code>. The address checks is likely done in software. F00D has it's own private 128KB memory from <code>0x00800000</code> to <code>0x00820000</code>. F00D SELFs are typically loaded to <code>0x0080B000</code>.</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Cmep&diff=2495
Cmep
2017-01-28T22:34:54Z
<p>St4rk: </p>
<hr />
<div>This processor is hypothesized to perform most of the cryptography tasks including storing and handing of [[Keys|keys]]. There is little information about it though. The [[F00D Processor]] (named after the <code>e_machine</code> field of the ELF headers) is likely a custom [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP] core.<br />
<br />
== Communication ==<br />
Communication seems to go through some sort of FIFO register.<br />
<br />
=== Write ===<br />
To write, put the double word into <code>0xE0000010</code>. Next read <code>0xE0000010</code> until it returns 0, which indicates the data was read by the F00D processor.<br />
<br />
=== Read ===<br />
To read, get a double word from <code>0xE0000000</code>. If it returns 0, no data is available. Otherwise, acknowledge that the data has been read by putting the same data into <code>0xE0000000</code>.<br />
<br />
=== Extra ports ===<br />
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Port<br />
! Read<br />
! Write<br />
! Used by<br />
|-<br />
| 0xE0000004<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000008<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE000000C<br />
| YES<br />
| ?<br />
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000014<br />
| YES<br />
| YES<br />
| SMC 0x12d, 0x133, 0x134, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000018<br />
| YES<br />
| YES<br />
| SMC 0x12d, 0x133, 0x134, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE000001C<br />
| YES<br />
| YES<br />
| SMC 0x12d, 0x133, 0x134, 0x13B Interrupt 0xC8<br />
|-<br />
| 0xE0000054<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE0000058<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE000005C<br />
| ?<br />
| YES<br />
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8<br />
|-<br />
| 0xE0010000<br />
| YES<br />
| YES<br />
| Used by F00D Command 0 to prepare F00D to receive an address that contains the secure kernel enp.<br />
|-<br />
| 0xE0010004<br />
| YES<br />
| ?<br />
| Used by F00D Command 0 to check if the value written in <code>0xE0010000</code> is okay (it should return a value <= 0)<br />
|-<br />
<br />
|}<br />
<br />
== Protocol ==<br />
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Bit End<br />
! Bit Start<br />
! Name<br />
! Description<br />
|-<br />
| 31<br />
| 23<br />
| ?<br />
| ?<br />
|-<br />
| 22<br />
| 19<br />
| flag?<br />
| b1010, b0010, b0001<br />
|-<br />
| 18<br />
| 13<br />
| ?<br />
| Always 0<br />
|-<br />
| 12<br />
| 8<br />
| ID<br />
| [[F00D Processor#Command ID|Command ID]]<br />
|-<br />
| 7<br />
| 1<br />
| ?<br />
| Always 0<br />
|-<br />
| 0<br />
| 0<br />
| Valid<br />
| Set 1 to indicate command is valid<br />
|-<br />
|}<br />
<br />
=== Command ID ===<br />
There are a total of 14 commands. Below are notes on different commands. Commands pass data through the 0x100 shared buffer (set up in command 0).<br />
<br />
==== 0x0 ====<br />
<br />
This command is used to setup a shared buffer with F00D. First F00D will write in <code>0xE0000000</code> either 0x200 or 0x600 (and if an error happened, 0x400 ?). If the value 0x600 is written, it will first setup a buffer that contains the f00d secure kernel enp. First it will write 0x1 to <code>0xE0010000</code> and after that 0x0 to <code>0xE0010000</code>, next, it will wait <code>0xE0010000</code> return 0 and <code>0xE0010004</code> return a value <= 0x0. If everything goes alright, it will clear the low 2 bits of the f00d secure kernel enp address (normally at 0x1F850000) and OR it with 0x1 and then write it to <code>0xE0000010</code>. After it, the process is the same that the 0x200. If the value 0x200 is written, it will set the 0x100 sized shared buffer. First the physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written. <br />
<br />
==== 0x1 ====<br />
<br />
This command is called by a function inside the SceSblSmSchedForTZS_0xE72F2886 or SceSblSmsched_start (if an error happened while SceSblSmsched is initializing). This command seem to be used to ask the f00d to remove all resource allocated (like shared memory address, secure module loaded, etc), and probably power off or reset it.<br />
<br />
==== 0x2 ====<br />
<br />
Load sm.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for sm elf<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| ctx_0x4<br />
|-<br />
| 0x10<br />
| 0x4<br />
| ctx_0x8<br />
|-<br />
| 0x14<br />
| 0x4<br />
| ctx_0xC<br />
|-<br />
| 0x1C<br />
| 0x4<br />
| field_60: system version (2)<br />
|-<br />
| 0x20<br />
| 0x4<br />
| partition ID<br />
|}<br />
<br />
==== 0x3 ====<br />
<br />
Load previously suspended sm<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for suspend buffer<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| delayed_cmd<br />
|}<br />
<br />
==== 0x4 ====<br />
<br />
Suspend current sm<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for suspend buffer<br />
|-<br />
| 0x8<br />
| 0x4<br />
| buf_0x40: some 0x40 buffer<br />
|-<br />
| 0xC<br />
| 0x4<br />
| delayed_cmd<br />
|}<br />
<br />
==== 0x5 ====<br />
<br />
Kill current sm<br />
<br />
==== 0x6 ====<br />
<br />
?<br />
<br />
==== 0x7 ====<br />
<br />
Unused.<br />
<br />
==== 0x8 ====<br />
<br />
Unused.<br />
<br />
==== 0x9 ====<br />
<br />
Set a 0x80 sized shared buffer.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| paddr<br />
|-<br />
| 0x4<br />
| 0x4<br />
| length<br />
|}<br />
<br />
==== 0xA ====<br />
<br />
Set the [[SCE]] encrypted revocation list.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| num_paddrs<br />
|-<br />
| 0x4<br />
| 0x4<br />
| paddr_list for revocation list<br />
|}<br />
<br />
==== 0xB ====<br />
<br />
==== 0xC ====<br />
<br />
==== 0xD ====<br />
<br />
==== 0xE ====<br />
<br />
==== 0xF ====<br />
<br />
==== 0x10 ====<br />
<br />
== Interrupts ==<br />
<br />
There are 4 interrupts that f00d sends. There are only two interrupt handles, however.<br />
<br />
* <code>cry2arm0</code>: handles interrupt 200. This is notifications about current sm status changes (loaded, unloaded, suspended, etc)<br />
* <code>cry2arm123</code>: handles interrupts 201, 202, 203. This interrupt is sent once an sm command has finished processing (see below).<br />
<br />
== Executing sm commands ==<br />
<br />
When sm is loaded, you can execute a [[F00D_Commands|command it provides]] by writing into registers 0xE0000014, 0xE0000018, 0xE000001C paddr to the command buffer OR'd with 1.<br />
<br />
Command buffer structure:<br />
<br />
{| class='wikitable'<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x4<br />
| Size of header + data<br />
|-<br />
| 0x4<br />
| 0x4<br />
| Command ID<br />
|-<br />
| 0x8<br />
| 0x4<br />
| unk1<br />
|-<br />
| 0xC<br />
| 0x4<br />
| unk2<br />
|-<br />
| 0x10<br />
| 0x30<br />
| padding<br />
|-<br />
| 0x40<br />
| variable, max=0x1000-0x40<br />
| data buffer<br />
|}<br />
<br />
Once result is available, ARM will get an interrupt 201-203. Read status code from 0xE0000004 (or 0xE0000008, 0xE000000C) and confirm you received it by writing it back to the same register.<br />
<br />
Possible results:<br />
<br />
* 1: command executed successfully<br />
* 3: invalid command ID<br />
* 5: invalid command buffer paddr (e.g. trying to pass secure memory)<br />
* 9: SCE_SBL_ERROR_COMMON_EIO<br />
<br />
== Memory ==<br />
<br />
<code>kprx_auth_sm.self</code> is allowed access to <code>0x1F000000</code>, <code>0x1F840000</code>, <code>0x20000000</code>, and <code>0x40300000</code>. The address checks is likely done in software. F00D has it's own private 128KB memory from <code>0x00800000</code> to <code>0x00820000</code>. F00D SELFs are typically loaded to <code>0x0080B000</code>.</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceNpDrm&diff=2300
SceNpDrm
2016-12-31T00:55:04Z
<p>St4rk: /* RIF */</p>
<hr />
<div>== Module ==<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceNpDrm || Non-secure || Kernel || 0xACCB4845<br />
|}<br />
<br />
== Libraries ==<br />
<br />
=== Known NIDs ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrm|SceNpDrm]] || Non-secure || User || 0xF2799B1B<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmForDriver|SceNpDrmForDriver]] || Non-secure || Kernel || 0xD84DC44A<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmPackage|SceNpDrmPackage]] || Non-secure || User || 0x88514DB2<br />
|}<br />
<br />
== SceNpDrm ==<br />
<br />
=== _sceNpDrmCheckDrmReset ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x4458812B<br />
|}<br />
=== _sceNpDrmRemoveActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x507D06A6<br />
|}<br />
=== _sceNpDrmGetRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB8C5DA7C<br />
|}<br />
=== _sceNpDrmGetRifNameForInstall ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD312424D<br />
|}<br />
=== _sceNpDrmGetRifInfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE8343660<br />
|}<br />
=== _sceNpDrmGetFixedRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE935B0FC<br />
|}<br />
=== _sceNpDrmCheckActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xFEEBCD62<br />
|}<br />
== SceNpDrmForDriver ==<br />
<br />
=== SceNpDrmCheckRifForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xDB406EAE<br />
|}<br />
<br />
== SceNpDrmPackage ==<br />
<br />
=== _sceNpDrmPackageTransform ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x567DCA1<br />
|}<br />
=== _sceNpDrmPackageInstallFinished ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6896EAF2<br />
|}<br />
=== _sceNpDrmPackageCheck ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA1D885FA<br />
|}<br />
=== sceNpDrmPackageIsGameExist ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB9337914<br />
|}<br />
=== _sceNpDrmPackageInstallStarted ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xCEC18DA4<br />
|}<br />
=== _sceNpDrmPackageDecrypt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD6F05ACC<br />
|}<br />
=== sceNpDrmPackageInstallOngoing ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xED0471FE<br />
|}<br />
<br />
== Package integrity checks ==<br />
=== Disable hash/signature verification ===<br />
To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like <code>if ( (v62 & 7) == 3 )</code>; below you will see the assignment <code>check_func = &off_81009CFC;</code>. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.<br />
<br />
Note that on 1.60 this module sometimes is loaded at different addresses between reboots.<br />
<br />
=== Allow debug packages to be installed ===<br />
Find the function that calls SceSblAIMgrForDriver_D78B04A2; patch it to always return 1. On 1.60 it's at 0x81002d64.<br />
<br />
Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.<br />
<br />
== RIF ==<br />
The RIF files are used as the eboot.bin DRM. For each installed PKG and Game Card you will have an unique RIF file with proper information that will be used when you open the game to verify if you own the game(to PKG) and decrypt the eboot.bin. The RIF files may hold important information as PSN Account ID, the key used to decrypt one of the SELF encrypt layers [...]. <br />
<br />
PS Vita supports two different RIF file format. The first format (License Type 0) seems to be used by licenses with 0x97 bytes size and the second (License Type 1) seems to be used by RIF files with 0x200 bytes size. The difference between them is just the signature verification. License Type 0 only uses ECDSA Signature, the License Type 1 uses the ECDSA Signature verification and an extra RSA signature verification.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Name<br />
! Offset<br />
! Size<br />
|-<br />
| Version<br />
| 0x0<br />
| 0x4<br />
|-<br />
| License Type<br />
| 0x4<br />
| 0x4<br />
|-<br />
| PSN Account ID<br />
| 0x8<br />
| 0x8<br />
|- <br />
| Content ID<br />
| 0x10<br />
| 0x30<br />
|- <br />
| Unknown<br />
| 0x40<br />
| 0x10<br />
|- <br />
| RIF Key <br />
| 0x50<br />
| 0x10<br />
|- <br />
| License start time<br />
| 0x60<br />
| 0x8<br />
|-<br />
| License expiration time<br />
| 0x68<br />
| 0x8<br />
|- <br />
| ECDSA Signature<br />
| 0x70<br />
| 0x28<br />
|- <br />
| Unknown<br />
| 0x98<br />
| 0x68<br />
|- <br />
| RSA Signature<br />
| 0x100<br />
| 0x100<br />
|-<br />
|}<br />
<br />
<br />
<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceNpDrm&diff=2299
SceNpDrm
2016-12-31T00:36:37Z
<p>St4rk: </p>
<hr />
<div>== Module ==<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceNpDrm || Non-secure || Kernel || 0xACCB4845<br />
|}<br />
<br />
== Libraries ==<br />
<br />
=== Known NIDs ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrm|SceNpDrm]] || Non-secure || User || 0xF2799B1B<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmForDriver|SceNpDrmForDriver]] || Non-secure || Kernel || 0xD84DC44A<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmPackage|SceNpDrmPackage]] || Non-secure || User || 0x88514DB2<br />
|}<br />
<br />
== SceNpDrm ==<br />
<br />
=== _sceNpDrmCheckDrmReset ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x4458812B<br />
|}<br />
=== _sceNpDrmRemoveActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x507D06A6<br />
|}<br />
=== _sceNpDrmGetRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB8C5DA7C<br />
|}<br />
=== _sceNpDrmGetRifNameForInstall ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD312424D<br />
|}<br />
=== _sceNpDrmGetRifInfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE8343660<br />
|}<br />
=== _sceNpDrmGetFixedRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE935B0FC<br />
|}<br />
=== _sceNpDrmCheckActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xFEEBCD62<br />
|}<br />
== SceNpDrmForDriver ==<br />
<br />
=== SceNpDrmCheckRifForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xDB406EAE<br />
|}<br />
<br />
== SceNpDrmPackage ==<br />
<br />
=== _sceNpDrmPackageTransform ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x567DCA1<br />
|}<br />
=== _sceNpDrmPackageInstallFinished ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6896EAF2<br />
|}<br />
=== _sceNpDrmPackageCheck ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA1D885FA<br />
|}<br />
=== sceNpDrmPackageIsGameExist ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB9337914<br />
|}<br />
=== _sceNpDrmPackageInstallStarted ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xCEC18DA4<br />
|}<br />
=== _sceNpDrmPackageDecrypt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD6F05ACC<br />
|}<br />
=== sceNpDrmPackageInstallOngoing ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xED0471FE<br />
|}<br />
<br />
== Package integrity checks ==<br />
=== Disable hash/signature verification ===<br />
To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like <code>if ( (v62 & 7) == 3 )</code>; below you will see the assignment <code>check_func = &off_81009CFC;</code>. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.<br />
<br />
Note that on 1.60 this module sometimes is loaded at different addresses between reboots.<br />
<br />
=== Allow debug packages to be installed ===<br />
Find the function that calls SceSblAIMgrForDriver_D78B04A2; patch it to always return 1. On 1.60 it's at 0x81002d64.<br />
<br />
Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.<br />
<br />
== RIF ==<br />
The RIF files are used as the PKG file's DRM. For each installed PKG you will have an specific RIF file with the proper information. The RIF files holds important information as PSN Account ID, the key used to decrypt one of the SELF encrypt layers [...]. <br />
<br />
PS Vita supports two different RIF file format. The first format (License Type 0) seems to be used by licenses with 0x97 bytes size and the second (License Type 1) seems to be used by RIF files with 0x200 bytes size. The difference between them is just the signature verification. License Type 0 only uses ECDSA Signature, the License Type 1 uses the ECDSA Signature verification and an extra RSA signature verification.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Name<br />
! Offset<br />
! Size<br />
|-<br />
| Version<br />
| 0x0<br />
| 0x4<br />
|-<br />
| License Type<br />
| 0x4<br />
| 0x4<br />
|-<br />
| PSN Account ID<br />
| 0x8<br />
| 0x8<br />
|- <br />
| Content ID<br />
| 0x10<br />
| 0x30<br />
|- <br />
| Unknown<br />
| 0x40<br />
| 0x10<br />
|- <br />
| RIF Key <br />
| 0x50<br />
| 0x10<br />
|- <br />
| License start time<br />
| 0x60<br />
| 0x8<br />
|-<br />
| License expiration time<br />
| 0x68<br />
| 0x8<br />
|- <br />
| ECDSA Signature<br />
| 0x70<br />
| 0x28<br />
|- <br />
| Unknown<br />
| 0x98<br />
| 0x68<br />
|- <br />
| RSA Signature<br />
| 0x100<br />
| 0x100<br />
|-<br />
|}<br />
<br />
<br />
<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Cmep&diff=2289
Cmep
2016-12-28T04:41:06Z
<p>St4rk: /* Command ID */</p>
<hr />
<div>This processor is hypothesized to perform most of the cryptography tasks including storing and handing of [[Keys|keys]]. There is little information about it though. The [[F00D Processor]] (named after the <code>e_machine</code> field of the ELF headers) is likely a custom [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP] core.<br />
<br />
== Communication ==<br />
Communication seems to go through some sort of FIFO register.<br />
<br />
=== Write ===<br />
To write, put the double word into <code>0xE0000010</code>. Next read <code>0xE0000010</code> until it returns 0, which indicates the data was read by the F00D processor.<br />
<br />
=== Read ===<br />
To read, get a double word from <code>0xE0000000</code>. If it returns 0, no data is available. Otherwise, acknowledge that the data has been read by putting the same data into <code>0xE0000000</code>.<br />
<br />
=== Extra ports ===<br />
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Port<br />
! Read<br />
! Write<br />
|-<br />
| 0xE0000004<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000008<br />
| YES<br />
| ?<br />
|-<br />
| 0xE000000C<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000014<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000018<br />
| YES<br />
| YES<br />
|-<br />
| 0xE000001C<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000054<br />
| ?<br />
| YES<br />
|-<br />
| 0xE0000058<br />
| ?<br />
| YES<br />
|-<br />
| 0xE000005C<br />
| ?<br />
| YES<br />
|-<br />
| 0xE0010000<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0010004<br />
| YES<br />
| ?<br />
|-<br />
<br />
|}<br />
<br />
== Protocol ==<br />
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Bit End<br />
! Bit Start<br />
! Name<br />
! Description<br />
|-<br />
| 31<br />
| 23<br />
| ?<br />
| ?<br />
|-<br />
| 22<br />
| 22<br />
| ?<br />
| ?<br />
|-<br />
| 21<br />
| 21<br />
| ?<br />
| ?<br />
|-<br />
| 20<br />
| 18<br />
| flag?<br />
| ?<br />
|-<br />
| 17<br />
| 13<br />
| ?<br />
| Always 0<br />
|-<br />
| 12<br />
| 8<br />
| ID<br />
| [[F00D Processor#Command ID|Command ID]]<br />
|-<br />
| 7<br />
| 1<br />
| ?<br />
| Always 0<br />
|-<br />
| 0<br />
| 0<br />
| Valid<br />
| Set 1 to indicate command is valid<br />
|-<br />
|}<br />
<br />
=== Command ID ===<br />
There are a total of 14 commands. Below are notes on different commands.<br />
<br />
<br />
{| class='wikitable'<br />
|-<br />
! ID<br />
! Description<br />
|-<br />
| 0x0<br />
|Seems to be used to set the 0x100 sized shared buffer. First the physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written.<br />
|-<br />
| 0x1 <br />
| May be used to reset F00D processor.<br />
|-<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x3<br />
| ?<br />
|-<br />
| 0x4<br />
| ?<br />
|-<br />
| 0x5<br />
| ?<br />
|-<br />
| 0x6<br />
| ?<br />
|-<br />
| 0x9<br />
| Seems to be used to set a 0x80 sized shared buffer.<br />
|-<br />
| 0xA<br />
| Seems to set the [[SCE]] encrypted revocation list.<br />
|-<br />
|-<br />
| 0xB<br />
| ?<br />
|-<br />
|-<br />
| 0xC<br />
| ?<br />
|-<br />
|-<br />
| 0xD<br />
| ?<br />
|-<br />
|-<br />
| 0xE<br />
| ?<br />
|-<br />
|-<br />
| 0xF<br />
| ?<br />
|-<br />
|}<br />
<br />
== Memory ==<br />
<br />
<code>kprx_auth_sm.self</code> is allowed access to <code>0x1F000000</code>, <code>0x1F840000</code>, <code>0x20000000</code>, and <code>0x40300000</code>. The address checks is likely done in software. F00D has it's own private 128KB memory from <code>0x00800000</code> to <code>0x00820000</code>. F00D SELFs are typically loaded to <code>0x0080B000</code>.</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Cmep&diff=2288
Cmep
2016-12-28T02:33:32Z
<p>St4rk: /* Extra ports */</p>
<hr />
<div>This processor is hypothesized to perform most of the cryptography tasks including storing and handing of [[Keys|keys]]. There is little information about it though. The [[F00D Processor]] (named after the <code>e_machine</code> field of the ELF headers) is likely a custom [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP] core.<br />
<br />
== Communication ==<br />
Communication seems to go through some sort of FIFO register.<br />
<br />
=== Write ===<br />
To write, put the double word into <code>0xE0000010</code>. Next read <code>0xE0000010</code> until it returns 0, which indicates the data was read by the F00D processor.<br />
<br />
=== Read ===<br />
To read, get a double word from <code>0xE0000000</code>. If it returns 0, no data is available. Otherwise, acknowledge that the data has been read by putting the same data into <code>0xE0000000</code>.<br />
<br />
=== Extra ports ===<br />
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Port<br />
! Read<br />
! Write<br />
|-<br />
| 0xE0000004<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000008<br />
| YES<br />
| ?<br />
|-<br />
| 0xE000000C<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000014<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000018<br />
| YES<br />
| YES<br />
|-<br />
| 0xE000001C<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000054<br />
| ?<br />
| YES<br />
|-<br />
| 0xE0000058<br />
| ?<br />
| YES<br />
|-<br />
| 0xE000005C<br />
| ?<br />
| YES<br />
|-<br />
| 0xE0010000<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0010004<br />
| YES<br />
| ?<br />
|-<br />
<br />
|}<br />
<br />
== Protocol ==<br />
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Bit End<br />
! Bit Start<br />
! Name<br />
! Description<br />
|-<br />
| 31<br />
| 23<br />
| ?<br />
| ?<br />
|-<br />
| 22<br />
| 22<br />
| ?<br />
| ?<br />
|-<br />
| 21<br />
| 21<br />
| ?<br />
| ?<br />
|-<br />
| 20<br />
| 18<br />
| flag?<br />
| ?<br />
|-<br />
| 17<br />
| 13<br />
| ?<br />
| Always 0<br />
|-<br />
| 12<br />
| 8<br />
| ID<br />
| [[F00D Processor#Command ID|Command ID]]<br />
|-<br />
| 7<br />
| 1<br />
| ?<br />
| Always 0<br />
|-<br />
| 0<br />
| 0<br />
| Valid<br />
| Set 1 to indicate command is valid<br />
|-<br />
|}<br />
<br />
=== Command ID ===<br />
Below are notes on different commands.<br />
<br />
==== 0x0 ====<br />
Seems to be used to set the 0x100 sized shared buffer. First the physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written.<br />
<br />
==== 0x1 ====<br />
May be used to reset F00D processor.<br />
<br />
==== 0x9 ====<br />
Seems to be used to set a 0x80 sized shared buffer.<br />
<br />
==== 0xA ====<br />
Seems to set the [[SCE]] encrypted revocation list.<br />
<br />
== Memory ==<br />
<br />
<code>kprx_auth_sm.self</code> is allowed access to <code>0x1F000000</code>, <code>0x1F840000</code>, <code>0x20000000</code>, and <code>0x40300000</code>. The address checks is likely done in software. F00D has it's own private 128KB memory from <code>0x00800000</code> to <code>0x00820000</code>. F00D SELFs are typically loaded to <code>0x0080B000</code>.</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Cmep&diff=2287
Cmep
2016-12-26T04:08:50Z
<p>St4rk: </p>
<hr />
<div>This processor is hypothesized to perform most of the cryptography tasks including storing and handing of [[Keys|keys]]. There is little information about it though. The [[F00D Processor]] (named after the <code>e_machine</code> field of the ELF headers) is likely a custom [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP] core.<br />
<br />
== Communication ==<br />
Communication seems to go through some sort of FIFO register.<br />
<br />
=== Write ===<br />
To write, put the double word into <code>0xE0000010</code>. Next read <code>0xE0000010</code> until it returns 0, which indicates the data was read by the F00D processor.<br />
<br />
=== Read ===<br />
To read, get a double word from <code>0xE0000000</code>. If it returns 0, no data is available. Otherwise, acknowledge that the data has been read by putting the same data into <code>0xE0000000</code>.<br />
<br />
=== Extra ports ===<br />
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Port<br />
! Read<br />
! Write<br />
|-<br />
| 0xE0000004<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000008<br />
| YES<br />
| ?<br />
|-<br />
| 0xE000000C<br />
| YES<br />
| ?<br />
|-<br />
| 0xE0000014<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000018<br />
| YES<br />
| YES<br />
|-<br />
| 0xE000001C<br />
| YES<br />
| YES<br />
|-<br />
| 0xE0000054<br />
| ?<br />
| YES<br />
|-<br />
| 0xE0000058<br />
| ?<br />
| YES<br />
|-<br />
| 0xE000005C<br />
| ?<br />
| YES<br />
|-<br />
|}<br />
<br />
<br />
<br />
== Protocol ==<br />
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.<br />
<br />
{| class='wikitable'<br />
|-<br />
! Bit End<br />
! Bit Start<br />
! Name<br />
! Description<br />
|-<br />
| 31<br />
| 23<br />
| ?<br />
| ?<br />
|-<br />
| 22<br />
| 22<br />
| ?<br />
| ?<br />
|-<br />
| 21<br />
| 21<br />
| ?<br />
| ?<br />
|-<br />
| 20<br />
| 18<br />
| flag?<br />
| ?<br />
|-<br />
| 17<br />
| 13<br />
| ?<br />
| Always 0<br />
|-<br />
| 12<br />
| 8<br />
| ID<br />
| [[F00D Processor#Command ID|Command ID]]<br />
|-<br />
| 7<br />
| 1<br />
| ?<br />
| Always 0<br />
|-<br />
| 0<br />
| 0<br />
| Valid<br />
| Set 1 to indicate command is valid<br />
|-<br />
|}<br />
<br />
=== Command ID ===<br />
Below are notes on different commands.<br />
<br />
==== 0x0 ====<br />
Seems to be used to set the 0x100 sized shared buffer. First the physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written.<br />
<br />
==== 0x1 ====<br />
May be used to reset F00D processor.<br />
<br />
==== 0x9 ====<br />
Seems to be used to set a 0x80 sized shared buffer.<br />
<br />
==== 0xA ====<br />
Seems to set the [[SCE]] encrypted revocation list.<br />
<br />
== Memory ==<br />
<br />
<code>kprx_auth_sm.self</code> is allowed access to <code>0x1F000000</code>, <code>0x1F840000</code>, <code>0x20000000</code>, and <code>0x40300000</code>. The address checks is likely done in software. F00D has it's own private 128KB memory from <code>0x00800000</code> to <code>0x00820000</code>. F00D SELFs are typically loaded to <code>0x0080B000</code>.</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceNetPs&diff=2278
SceNetPs
2016-12-02T22:05:53Z
<p>St4rk: </p>
<hr />
<div>== Module ==<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceNetPs || Non-secure || Kernel || 0x32573904<br />
|}<br />
<br />
== Libraries ==<br />
<br />
=== Known NIDs ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceNetPs#SceNetPsForDriver|SceNetPsForDriver]] || Non-secure || Kernel || 0xB2A5C920<br />
|-<br />
| 1.69 || [[SceNetPs#SceNetPsForSyscalls|SceNetPsForSyscalls]] || Non-secure || User || 0x2CBED2C6<br />
|}<br />
<br />
== SceNetPsForDriver ==<br />
<br />
=== sceNetListenForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x080C7992<br />
|}<br />
=== sceNetConnectForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x13491DA1<br />
|}<br />
=== sceNetCloseForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x21F4428D<br />
|}<br />
=== sceNetRecvFromForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x49B1669C<br />
|}<br />
=== sceNetSetsockoptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x4BF5FAB4<br />
|}<br />
=== sceNetBindForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x84AB650F<br />
|}<br />
=== sceNetAcceptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x880A5423<br />
|}<br />
=== sceNetGetsocknameForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x8F1BB0E7<br />
|}<br />
=== sceNetGetsockoptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x92EE24A6<br />
|}<br />
=== sceNetSendtoForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xAB746734<br />
|}<br />
=== sceNetGetPeerNameForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xB949AFD5<br />
|}<br />
=== sceNetSocketForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xEB95B024<br />
|}<br />
=== sceNetShutdownForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xEEB19FB6<br />
|}<br />
<br />
== SceNetPsForSyscalls ==<br />
<br />
=== sceNetSyscallSetsockopt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x10DE34EA<br />
|}<br />
=== sceNetSyscallRecvfrom ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x144C9758<br />
|}<br />
=== sceNetSyscallConnect ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x14A4DE52<br />
|}<br />
=== sceNetSyscallClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x1EBC2E28<br />
|}<br />
=== sceNetSyscallDumpClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x263E52FD<br />
|}<br />
=== sceNetSyscallBind ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x267F1EF9<br />
|}<br />
=== sceNetSyscallIoctl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x310F0725<br />
|}<br />
=== sceNetSyscallRecvmsg ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x32C1AE45<br />
|}<br />
=== sceNetSyscallSendto ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x39796C01<br />
|}<br />
=== sceNetSyscallDumpRead ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3CBE7071<br />
|}<br />
=== sceNetSyscallSysctl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3D7495B0<br />
|}<br />
=== sceNetSyscallDumpCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3FC34171<br />
|}<br />
=== sceNetSyscallAccept ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x45EAAD89<br />
|}<br />
=== sceNetSyscallDumpAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x5CD20B54<br />
|}<br />
=== sceNetSyscallGetsockname ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6AA945D9<br />
|}<br />
=== sceNetSyscallEpollClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x75E82300<br />
|}<br />
=== sceNetSyscallSocket ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x81A120BE<br />
|}<br />
=== sceNetSyscallDescriptorClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x854AFB6F<br />
|}<br />
=== sceNetSyscallGetIfList ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x878274CE<br />
|}<br />
=== sceNetSyscallIcmConnect ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x8C3FBC87<br />
|}<br />
=== sceNetSyscallEpollAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x94C3AE47<br />
|}<br />
=== sceNetSyscallShutdown ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA4014519<br />
|}<br />
=== sceNetSyscallDescriptorCtl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA7064C2C<br />
|}<br />
=== sceNetSyscallEpollCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA98AEF04<br />
|}<br />
=== sceNetSyscallSendmsg ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xAEC6BE5D<br />
|}<br />
=== sceNetSyscallListen ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xAEEB7CA0<br />
|}<br />
=== sceNetSyscallDescriptorCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB518A2DE<br />
|}<br />
=== sceNetSyscallGetsockopt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xBC472DC5<br />
|}<br />
=== sceNetSyscallGetpeername ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xBD7B0213<br />
|}<br />
=== sceNetSyscallEpollCtl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xDF30BE68<br />
|}<br />
=== sceNetSyscallControl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xEA0C1B71<br />
|}<br />
=== sceNetSyscallGetSockinfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF7748E56<br />
|}<br />
=== sceNetSyscallSocketAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF9203B48<br />
|}<br />
=== sceNetSyscallEpollWait ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF933D6FC<br />
|}<br />
<br />
== Custom malloc()/free() implementation ==<br />
<br />
This module contains a custom malloc() and free() implementation. In 3.35 <code>void *malloc(int size, char flags, int align)</code> is located at offset 0x57b8 and <code>void free(void *ptr)</code> at 0x5a40. Another way to find them is search for immediate value 0x4D61416B, one will be in a data segment and referenced by malloc, another is an immediate value used from free.<br />
<br />
Here's an illustration of how allocated/free chunks work:<br />
<br />
[[File:scenet-malloc.png]]<br />
<br />
The primary problem with exploiting heap overflows are the red "heap cookies": <code>BuSy</code>, <code>MaAk</code>, <code>FrEe</code>. When a chunk is allocated and the freelist is iterated it checks for the presence of "FrEe" on every iterated chunk. When a chunk is freed, it checks for "BuSy" and "MaAk". If cookies don't match, the code does an <code>*(int*)0 = 0</code> which crashes the system.<br />
<br />
Note that "MaAk" is appended right after the user provided "size" bytes, so it might not be aligned.<br />
<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceNpDrm&diff=2277
SceNpDrm
2016-12-02T21:57:18Z
<p>St4rk: </p>
<hr />
<div>== Module ==<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceNpDrm || Non-secure || Kernel || 0xACCB4845<br />
|}<br />
<br />
== Libraries ==<br />
<br />
=== Known NIDs ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrm|SceNpDrm]] || Non-secure || User || 0xF2799B1B<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmForDriver|SceNpDrmForDriver]] || Non-secure || Kernel || 0xD84DC44A<br />
|-<br />
| 1.69 || [[SceNpDrm#SceNpDrmPackage|SceNpDrmPackage]] || Non-secure || User || 0x88514DB2<br />
|}<br />
<br />
== SceNpDrm ==<br />
<br />
=== _sceNpDrmCheckDrmReset ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x4458812B<br />
|}<br />
=== _sceNpDrmRemoveActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x507D06A6<br />
|}<br />
=== _sceNpDrmGetRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB8C5DA7C<br />
|}<br />
=== _sceNpDrmGetRifNameForInstall ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD312424D<br />
|}<br />
=== _sceNpDrmGetRifInfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE8343660<br />
|}<br />
=== _sceNpDrmGetFixedRifName ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xE935B0FC<br />
|}<br />
=== _sceNpDrmCheckActData ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xFEEBCD62<br />
|}<br />
== SceNpDrmForDriver ==<br />
<br />
=== SceNpDrmCheckRifForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xDB406EAE<br />
|}<br />
<br />
== SceNpDrmPackage ==<br />
<br />
=== _sceNpDrmPackageTransform ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x567DCA1<br />
|}<br />
=== _sceNpDrmPackageInstallFinished ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6896EAF2<br />
|}<br />
=== _sceNpDrmPackageCheck ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA1D885FA<br />
|}<br />
=== sceNpDrmPackageIsGameExist ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB9337914<br />
|}<br />
=== _sceNpDrmPackageInstallStarted ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xCEC18DA4<br />
|}<br />
=== _sceNpDrmPackageDecrypt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xD6F05ACC<br />
|}<br />
=== sceNpDrmPackageInstallOngoing ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xED0471FE<br />
|}<br />
<br />
== Package integrity checks ==<br />
=== Disable hash/signature verification ===<br />
To find the function responsible for package verification search for immediate 0x7F504B47 ('.PKG'). Inside it does a lot of stuff including determining the function that will do signature checks. Find the condition that looks like <code>if ( (v62 & 7) == 3 )</code>; below you will see the assignment <code>check_func = &off_81009CFC;</code>. To bypass signature checks you need to patch two functions located at this offset and offset+4, making them behave as "return 1" is enough. For reference, on 1.60 the functions are sub_81000310 and sub_81000AA4. sub_81000310 is the only function in this module that calls SceSblGcAuthMgrPkgForDriver_E459A9A8_imp.<br />
<br />
Note that on 1.60 this module sometimes is loaded at different addresses between reboots.<br />
<br />
=== Allow debug packages to be installed ===<br />
Find the function that calls SceSblAIMgrForDriver_D78B04A2; patch it to always return 1. On 1.60 it's at 0x81002d64.<br />
<br />
Search for immediate 0x80870003, there should be two matches. Replace both with "MOV Reg, #0". On 1.60 the locations are 0x810035fe and 0x81004856.<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=SceNetPs&diff=2276
SceNetPs
2016-12-02T21:48:27Z
<p>St4rk: </p>
<hr />
<div>== Module ==<br />
<br />
=== Known NIDs ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Privilege !! NID<br />
|-<br />
| 1.69 || SceNetPs || Non-secure || Kernel || 0x32573904<br />
|}<br />
<br />
== Libraries ==<br />
<br />
=== Known NIDs ===<br />
<br />
{| class="wikitable"<br />
|-<br />
! Version !! Name !! World !! Visibility !! NID<br />
|-<br />
| 1.69 || [[SceNetPs#SceNetPsForDriver|SceNetPsForDriver]] || Non-secure || Kernel || 0xB2A5C920<br />
|-<br />
| 1.69 || [[SceNetPs#SceNetPsForSyscalls|SceNetPsForSyscalls]] || Non-secure || User || 0x2CBED2C6<br />
|}<br />
<br />
== SceNetPsForDriver ==<br />
<br />
=== sceNetListenForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x080C7992<br />
|}<br />
=== sceNetConnectForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x13491DA1<br />
|}<br />
=== sceNetCloseForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x21F4428D<br />
|}<br />
=== sceNetRecvFromForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x49B1669C<br />
|}<br />
=== sceNetSetsockoptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x4BF5FAB4<br />
|}<br />
=== sceNetBindForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x84AB650F<br />
|}<br />
=== sceNetAcceptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x880A5423<br />
|}<br />
=== sceNetGetsocknameForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x8F1BB0E7<br />
|}<br />
=== sceNetGetsockoptForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0x92EE24A6<br />
|}<br />
=== sceNetSendtoForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xAB746734<br />
|}<br />
=== sceNetGetPeerNameForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xB949AFD5<br />
|}<br />
=== sceNetSocketForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xEB95B024<br />
|}<br />
=== sceNetShutdownForDriver ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 3.60 || 0xEEB19FB6<br />
|}<br />
<br />
<br />
== SceNetPsForSyscalls ==<br />
<br />
=== sceNetSyscallSetsockopt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x10DE34EA<br />
|}<br />
=== sceNetSyscallRecvfrom ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x144C9758<br />
|}<br />
=== sceNetSyscallConnect ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x14A4DE52<br />
|}<br />
=== sceNetSyscallClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x1EBC2E28<br />
|}<br />
=== sceNetSyscallDumpClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x263E52FD<br />
|}<br />
=== sceNetSyscallBind ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x267F1EF9<br />
|}<br />
=== sceNetSyscallIoctl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x310F0725<br />
|}<br />
=== sceNetSyscallRecvmsg ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x32C1AE45<br />
|}<br />
=== sceNetSyscallSendto ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x39796C01<br />
|}<br />
=== sceNetSyscallDumpRead ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3CBE7071<br />
|}<br />
=== sceNetSyscallSysctl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3D7495B0<br />
|}<br />
=== sceNetSyscallDumpCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x3FC34171<br />
|}<br />
=== sceNetSyscallAccept ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x45EAAD89<br />
|}<br />
=== sceNetSyscallDumpAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x5CD20B54<br />
|}<br />
=== sceNetSyscallGetsockname ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x6AA945D9<br />
|}<br />
=== sceNetSyscallEpollClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x75E82300<br />
|}<br />
=== sceNetSyscallSocket ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x81A120BE<br />
|}<br />
=== sceNetSyscallDescriptorClose ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x854AFB6F<br />
|}<br />
=== sceNetSyscallGetIfList ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x878274CE<br />
|}<br />
=== sceNetSyscallIcmConnect ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x8C3FBC87<br />
|}<br />
=== sceNetSyscallEpollAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0x94C3AE47<br />
|}<br />
=== sceNetSyscallShutdown ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA4014519<br />
|}<br />
=== sceNetSyscallDescriptorCtl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA7064C2C<br />
|}<br />
=== sceNetSyscallEpollCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xA98AEF04<br />
|}<br />
=== sceNetSyscallSendmsg ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xAEC6BE5D<br />
|}<br />
=== sceNetSyscallListen ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xAEEB7CA0<br />
|}<br />
=== sceNetSyscallDescriptorCreate ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xB518A2DE<br />
|}<br />
=== sceNetSyscallGetsockopt ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xBC472DC5<br />
|}<br />
=== sceNetSyscallGetpeername ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xBD7B0213<br />
|}<br />
=== sceNetSyscallEpollCtl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xDF30BE68<br />
|}<br />
=== sceNetSyscallControl ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xEA0C1B71<br />
|}<br />
=== sceNetSyscallGetSockinfo ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF7748E56<br />
|}<br />
=== sceNetSyscallSocketAbort ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF9203B48<br />
|}<br />
=== sceNetSyscallEpollWait ===<br />
{| class="wikitable"<br />
|-<br />
! Version !! NID<br />
|-<br />
| 1.69 || 0xF933D6FC<br />
|}<br />
<br />
== Custom malloc()/free() implementation ==<br />
<br />
This module contains a custom malloc() and free() implementation. In 3.35 <code>void *malloc(int size, char flags, int align)</code> is located at offset 0x57b8 and <code>void free(void *ptr)</code> at 0x5a40. Another way to find them is search for immediate value 0x4D61416B, one will be in a data segment and referenced by malloc, another is an immediate value used from free.<br />
<br />
Here's an illustration of how allocated/free chunks work:<br />
<br />
[[File:scenet-malloc.png]]<br />
<br />
The primary problem with exploiting heap overflows are the red "heap cookies": <code>BuSy</code>, <code>MaAk</code>, <code>FrEe</code>. When a chunk is allocated and the freelist is iterated it checks for the presence of "FrEe" on every iterated chunk. When a chunk is freed, it checks for "BuSy" and "MaAk". If cookies don't match, the code does an <code>*(int*)0 = 0</code> which crashes the system.<br />
<br />
Note that "MaAk" is appended right after the user provided "size" bytes, so it might not be aligned.<br />
<br />
<br />
[[Category:Modules]]<br />
[[Category:Kernel]]</div>
St4rk
https://wiki.henkaku.xyz/vita/index.php?title=Packages&diff=2271
Packages
2016-11-29T16:37:01Z
<p>St4rk: /* AES Keys */</p>
<hr />
<div>PKG files for PSVita are essentially the same structure as PS3 and PSP game PKG files with different AES, RSA and ECC keys.<br />
<br />
== AES Keys ==<br />
There now are 5 AES keys used for the decryption of game PKG files.<br />
<br />
*PSP : <code>{ 0x07, 0xf2, 0xc6, 0x82, 0x90, 0xb5, 0x0d, 0x2c, 0x33, 0x81, 0x8d, 0x70, 0x9b, 0x60, 0xe6, 0x2b };</code><br />
*PS3 : <code>{ 0x2e, 0x7b, 0x71, 0xd7, 0xc9, 0xc9, 0xa1, 0x4e, 0xa3, 0x22, 0x1f, 0x18, 0x88, 0x28, 0xb8, 0xf8 };</code><br />
*PSV2: <code>{ 0xE3, 0x1A, 0x70, 0xC9, 0xCE, 0x1D, 0xD7, 0x2B, 0xF3, 0xC0, 0x62, 0x29, 0x63, 0xF2, 0xEC, 0xCB };</code><br />
*PSV3: <code>{ 0x42, 0x3A, 0xCA, 0x3A, 0x2B, 0xD5, 0x64, 0x9F, 0x96, 0x86, 0xAB, 0xAD, 0x6F, 0xD8, 0x80, 0x1F };</code><br />
*PSV4: <code>{ 0xAF, 0x07, 0xFD, 0x59, 0x65, 0x25, 0x27, 0xBA, 0xF1, 0x33, 0x89, 0x66, 0x8B, 0x17, 0xD9, 0xEA };</code><br />
<br />
The overall algorithm is the same as PSP with one exception. On the PSP, the file table and the data is AES CTR encrypted using the 0x10 bytes from offset +0x70 in the file as the IV along with the PSP AES Key. On the PSVita for type 2,3 and 4, they first encrypt the 0x10 bytes at +0x70 to create a new AES session key, then do the normal AES_CTR with +0x70 as the IV and the new session key as the AES CTR key.<br />
<br />
<br />
At offset +0xE7 in the PKG file is a version byte. This is only in the PSP type PKG files inside the .ext section. If its type 1, the use the PSP key as normal, if its type 2, use the PSV2 key with the new session key step, and if its type 3, use the PSV3, etc.<br />
<br />
== Installing ==<br />
<br />
Package Installer uses SceNpDrm to decrypt/extract the game package into a temporary directory. Then it calls ScePromoterUtil NID 0x86641BC6 on 1.69 and NID 0x716C81F4 on 1.80+ to "promote" (aka install) the files into the right directory in ux0. ScePromoterUtil is just a wrapper for a SceShellSvc call, so SceShell actually moves the files, then adds the LiveArea bubble and updates app.db accordingly. In theory you can use SceNpDrm and ScePromoterUtil separately and package your games in an alternative format.<br />
<br />
[[Category:Formats]]</div>
St4rk