Secure Modules Functions

Depending on the F00D SELF that is currently loaded, different commands are handled.

Request Buffer
Each request that is made sends a page aligned buffer that has a max size of a page. After as 64 byte header common to all commands, the data afterwards is specific to each command. The documentation for each command below specifies the data that goes after the header. The special command id of -1 is used to shut down the currently loaded F00D SELF.

Physical Address List
A common format used in these requests is a list of physical address and size. This simple structure is defined below. See sceKernelVARangeToPARangeForDriver for information on creating this list.

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.

kprx_auth_sm.self
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 paddr list is generated from it.

0x10001 sceSblAuthMgrAuthHeaderForKernel
Used by sceSblAuthMgrAuthHeaderForKernel.

Checks 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  in F00D memory space.

0x20001 sceSblAuthMgrSetupAuthSegmentForKernel
Used by sceSblAuthMgrSetupAuthSegmentForKernel.

Set the program segment to decrypt. This corresponds to the segment index in the ELF program headers in the SELF header passed in with the command above.

0x30001 sceSblAuthMgrLoadBlockForKernel
Used by sceSblAuthMgrAuthSegmentForKernel.

Decrypt a buffer from the SELF corresponding to the program segment number passed in above. The segment is read in  bytes chunks and is decrypted in place (the input buffer will contain the decrypted data). A paddr list is generated from the buffer. The input buffer and output buffer can be the same.

0x40001 sceSblAuthMgrGetEKcForDriver
Decrypts provided buffer in ECB mode using one of three keys (NPDRM keys ?).

Used by sceSblAuthMgrGetEKcForDriver for getting klicensee?

0x50001 sceSblAuthMgrSetDmac5KeyForKernel
Used by sceSblAuthMgrSetDmac5KeyForKernel to set key for decryption.

This uses an unknown secret to derive the final key, then writes it into dmac5 keyring.

0x60001 sceSblAuthMgrClearDmac5KeyForKernel
Used by sceSblAuthMgrClearDmac5KeyForKernel for clearing the Dmac5 Key.

This function writes zeroes into dmac5 keyring.

0x70001 sceSblAuthMgrDecBindDataForDriver
Used by sceSblAuthMgrDecBindDataForDriver and SceNpDrm for gamecard binding data used in conjunction with the RIF license file on the gamecard for deriving the klicensee.

0x80001 sceSblAuthMgrVerifySpsfoForDriver
Used by sceSblAuthMgrVerifySpsfoForDriver.

0x1 check_activation_code_1
Only on pre 2.10.

Verify SceKitActivationData derived from AFV.

Use "internal" keys (?internal kits maybe? Not used on PDEL kernel).

0x2 check_activation_code_2
Only on pre 2.10.

Verify SceKitActivationData derived from AFV.

Use PDEL/PTEL keys. (maybe also latest DEM)

0x4 check_cmac
Verify ?NVS? activation data. Maybe checks CMAC.

0x5 gen_act_cmac
Only on pre 2.10.

Get activation data. The returned data is written to NVS at offset 0x520 or 0x530.

0x7
Only on pre 2.10.

Check if activation is valid. The input activation data is read from NVS at offset 0x520.

0xA gen_activation_with_sig
Introduced in 2.10.

Check if new activation is valid. Extended activation check with a signature. This is ran when installing a new afv.

0xB check_activation_with_sig
Introduced in 2.10.

Check if current activation is valid. Extended activation check with signature. This is ran on boot.

0x1 ConsoleId
Returns the console's ConsoleId.

Used in sceSblAimgrGetConsoleIdForDriver.

0x2 OpenPsId
Returns the console's OpenPsId.

Used in sceSblAimgrGetOpenPsIdForDriver.

0x3 VisibleId
Returns the console's VisibleId.

Used in sceSblAimgrGetVisibleIdForDriver.

0x4 PsCode
Returns the console's PsCode.

Used in sceSblAimgrGetPscode2ForDriver.

0x5 PassPhrase
Used in sceSblSsCreatePassPhraseForDriver.

0x10006
Seems to be called on init and before resume of PSP.

On FW 3.73-CEX (simplified):

If there was an error:

0x20006
Seems it is not present on 3.73-CEX.

0x30006
On 3.73-CEX (simplified):

If there was an error:

encdec_w_portability_sm.self
This seems to be used to do some kind of key derivation. May also be used as a general purpose encryption engine.

0x1000A EncryptWithPortability
Encrypt data. Actually it always returns, so it does nothing and is never used.

0x2000A DecryptWithPortability
Used by sceSblSsDecryptWithPortabilityForDriver.

Decrypt data by using AES-256-CBC with an internal key selected by.

Return value of 0x800f0002 means invalid service ID. For encdec_w_portability_sm, only commmands 0x1000A and 0x2000A are supported.

Return value of 0x800f1716 means invalid argument such as invalid key ID. Valid key IDs are only 1-20.

0x1000B
This is one of variable sized buffers that can be placed inside Request_Buffer

Type definition is located here sm_comm_context

Supported GC commands and structures

0x4 kirk_encrypt
Original PSP Kirk 4 service for encrypting data.

Does not use any specific data structure in.

Just encrypts data located in.

Uses one set of keys.

Available  values are (key is encrypted with key from keyslot 0x345 and put into keyslot 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83

Special  0x100 is available. Uses keys from keyslots 0x601 and 0x602.

Key 0x601 is scrambled and used as seed.

Key 0x602 is scrambled and used as key.

seed is aes cbc encrypted with key to produce resulting key.

0x7 kirk_decrypt
Original PSP Kirk 7 service for decrypting data

Does not use any specific data structure in.

Just decrypts data located in.

Uses two sets of keys.

Available key ids are (key is encrypted with key from keyslot 0x345 and put into keyslot 0x21): 0x02, 0x03, 0x04, 0x05, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x38, 0x39, 0x3A, 0x80, 0x81, 0x82, 0x83

Available  values are (key is encrypted with key from keyslot 0x340 and put into keyslot 0x10): 0x44, 0x53, 0x57, 0x63, 0x64, 0x68, 0xC0, 0xC1, 0xC2, 0xC3

Special  0x100 is available. Uses keys from keyslots 0x601 and 0x602 (will be documented later).

Key 0x601 is scrambled and used as seed.

Key 0x602 is scrambled and used as key.

seed is aes cbc encrypted with key to produce resulting key.

0xC kirk_ecc160_generate_keys
Original PSP Kirk 0xC service for Generating a 160bit ECC private/public keypair. Call with an empty buffer of length 0x3C. The structure below is the return structure.

Private key  is obtained by:

1. Generating 0x40 sized random number rng.

2. dA = rng mod N

Public key  us obtained by:

Qa = dA * G

Output:

0xD kirk_ecc160_multiply
Original PSP Kirk 0xD service for multiplying a 160bit ECC curve point with a value. Call with a multiplier, x and y point value.

Input:

Output:

0xE kirk_ecc160_generate_random
Original PSP Kirk 0xE service for 160bit Random number generation. Call with an empty buffer, the result structure is below.

Output:

0x10 kirk_ecc160_sign
Original PSP Kirk 0x10 service for 160bit ECC signing.

Specific  is used for signing.

For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).

is obtained by:

1. Generating 0x40 sized random number rng.

2. nonce = rng mod N

Input:

Output:

0x11 kirk_ecc160_verify
Original PSP Kirk 0x11 service for 160bit ECC signature verification. Call with the below structure, then function will return pass or fail.

Input size is 0x64 bytes.

Input:

No output.

0x12 verify_cmac_signature
This function checks that CMAC of  equals.

CMAC value of  is calculated using key from keyslot 0x212.

is decrypted using a key from keyslot 0x0.

Key in keyslot 0x0 is derived using key from keyslot 0x204 with static seed value.

Input:

0x14 kirk_ecc224_generate_keys
New Vita Kirk 0x14 service for Generating a 224bit ECC private/public keypair. Call with an empty buffer of length 0x54. The structure below is the return structure.

Private key  is obtained by:

1. Generating 0x40 sized random number rng.

2. dA = rng mod N

Public key  us obtained by:

Qa = dA * G

Output:

0x15 kirk_ecc224_multiply
New Vita Kirk 0x15 service for multiplying a 224bit ECC curve point with a value. Call with a multiplier, x and y point value.

Input:

Output:

0x16 kirk_ecc224_generate_random
New Vita Kirk 0x16 service for 224bit Random number generation. Call with an empty buffer, the result structure is below.

Output:

0x17 kirk_ecc224_sign
New Vita Kirk 0x17 service for 224bit ECC signing.

Specific  is used for signing.

For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).

is obtained by:

1. Generating 0x40 sized random number rng.

2. nonce = rng mod N

Input:

Output:

0x18 kirk_ecc224_verify
New Vita Kirk 0x18 service for 224bit ECDSA signature verification. Call with the below structure, then function will return pass or fail.

Input:

0x19 verify_cmac_signature
This function checks that CMAC of  equals.

CMAC value of  is calculated using key from keyslot 0x212.

is decrypted using a key from keyslot 0x0.

Key in keyslot 0x0 is derived using key from keyslot 0x204 with static seed value.

This function is related to IdStorage somehow.

Input:

0x1B check_gc_authenticity
New Vita Kirk 0x1B service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service with no response. Size of request is 0x53.

- packet 7 should contain challenge0 for the card that can be encrypted (by card) with key_id and master_key.

- packet 8 should contain encrypted message which can be decrypted (by vita) with key_id and master_key.

- part of message should be card_challenge0.

- another part of the message should be equal to challenge0.

- this way we know that card knows how to properly encrypt.

- kirk service 1B will decrypt packet 8 with key_id and master_key

- then it will verify challenge0

0x1C generate_vita_authenticity_proof
New Vita Kirk 0x1C service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x40. Size of response is 0x33.

- kirk service 1C will generate packet 9

- it will decrypt packet 8 to retrieve challenge0 and card_challenge0

- then challenge0 and card_challenge0 will be tweaked

- then it will generate secondary_key0

- then packet 9 will be encrypted with key_id and master_key

- packet 9 should contain encrypted message which can be decrypted (by card) with key_id and master_key.

- message should have secondary_key0, tweaked challenge0 and tweaked card_challenge0.

- this way card will know that we know how to properly encrypt the data and we know the layout of the data because we tweak and reorder certain fields.

Request:

Response:

0x1D challenge_handshake
New Vita Kirk 0x1D service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service with no response. Size of request is 0xA3.

- packet 13 should contain challenge1 for the card that can be encrypted (by card) with key_id and master_key.

- packet 14 should contain challenge1 and master_key that are encrypted (by card) with key_id and master_key

- kirk service 1D will decrypt secondary_key0 from packet 9 with key_id and master_key

- then it will decrypt packet 14

- then it will verify challenge1 in packet 13 against decrypted packet 14

- then it will verify master_key in packet 6 against decrypted packet 14

0x1E generate_packets_15_17_with_cmac_signature
New Vita Kirk 0x1E service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data generation service. Size of request is 0x51. Size of response is 0x33.

- kirk service 0x1E will generate packet 15

- it will decrypt secondary_key0 from packet 9 with key_id and master_key

- then it will generate secondary_key1

- then it will create a buffer with tweaked secondary_key1 and tweak_padding

- then it will encrypt the buffer using secondary_key0

- then it will create cmd56 input like buffer with encrypted buffer

- then it will calculate cmac of cmd56 like buffer using secondary_key0

- encrypted buffer and cmac will be the resulting data of packet 15

Request:

Response:

0x1F decrypt_packet_16
New Vita Kirk 0x1F service. This service is related to SceSdif and is used by SceSblGcAuthMgr. This service is part of SD MMC CMD56 custom initialization protocol. This is a data validation service. Size of request is 0xB3. Size of response is 0x20.

- kirk service 0x1E will decrypt secondary_key0 from packet 9 with key_id and master_key

- then it will combine data from packet 16 into a cmd56 like buffer

- then it will calculate cmac of that cmd56 like buffer using secondary_key0

- then it will verify calculated cmac against cmac from packet 16

- then it will decrypt secondary_key1 and tweak_padding from packet 15

- then it will decrypt secondary_key1 and unknown data from packet 16

- then it will verify decrypted secondary_key1 from packet 15 against decrypted secondary_key1 from packet 16

- then it will verify that decrypted tweak_padding from packet 15 is properly tweaked

- then it will return unknown decrypted data from packet 16

Request:

Response:

0x20 get_klicensee_keys_with_rif_cmac_signature
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 generation service. Size of request is 0x116. Size of response is 0x34.

Generated data is used to obtain klicensee using sceSblAuthMgrDecBindDataForDriver

Request:

Response:

0x21 kirk_ecc160_sign
New Vita Kirk 0x21 service for 160bit ECC signing.

Specific  is used for signing.

For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).

is obtained by:

1. Generating 0x40 sized seed which is derived from message hash and static private key using hmac256 and sha256.

2. nonce = seed mod N

Input:

Output:

0x22 kirk_ecc224_sign_sceebootpbp
New Vita Kirk 0x22 service for 224bit ECC signing.

Specific  is used for signing.

For example if you will implement it with openssl it will be used to calculate precomputed parts of signing operation (kinv and rp).

is obtained by:

1. Generating 0x40 sized seed which is derived from message hash and one of two static private keys using hmac256 and sha256. Key can be selected with key id 0 or 1.

Private key 0 is only used for signing __sceebootpbp files for firmware versions before 1.8X, otherwise private key 1 is used for signing __sceebootpbp.

2. nonce = seed mod N

Input:

Output:

0x23 generate_cmac_signature
New Vita Kirk 0x23 service.

Input:

Output:

pm_sm.self
sceSblPmMgrAuthEtoIForDriver uses "sd0:sm/pm_sm_sd.self" whilst other PmSm functions use "os0:sm/pm_sm.self".

Services 9 and 0xA appeared on 1.03 (maybe 1.00). They are not present on 0.990 and earlier.

0x1 get_product_mode
Used by sceSblPmMgrGetProductModeFromNVS.

Data size is 0x28 bytes. (0x20 bytes used)

Input: 0x20 buffer read from NVS at offset 0.

0x2 set_product_mode
Used by sceSblPmMgrSetProductMode.

Data size is 0x28 bytes. (0x20 bytes used)

Input: 0x20 bytes buffer read from NVS at offset 0, to which is written the new product mode to set.

Output data: 0x20 buffer to write to NVS at offset 0.

0x3 gen_req_hello
Input: 0x30 bytes buffer.

This is the first JIG auth command. The 0x28 buffer content is for the first time set by this service.

0x4 gen_challenge
Input: 0x30 bytes buffer.

0x5 check_response
Input: 0x30 bytes buffer.

Returns 0 on success, doesn't modify the input buffer.

0x6 gen_req_result
Input: 0x30 bytes buffer.

0x7 check_result
Input: 0x30 bytes buffer.

Returns 0 on success, doesn't modify the input buffer.

0x8
Used on 1.03+ by sceSblPmMgrGetProductModeFromNVS.

Input: 0x70 bytes buffer.

0x9 gen_jig_message
Only on 1.03+.

Input: 0x10C bytes buffer.

0xA check_jig_response
Only on 1.03+.

Input: 0x10C bytes buffer.

0x0
Decrypt or check QAF Token. Used on 1.03 PDEL.

0x4 decrypt QAF version
Input: 0x20 buffer read from NVS offset 0x2A0.

Output: QAF version in this buffer of size 0x20:

0x5 encrypt QAF version
Input QAF version in this buffer of size 0x20:

Output of size 0x20 is then written to NVS offset 0x2A0.

0x6 check_flag (decrypt)
Input: 0x20 buffer read from NVS at offset 0.

Returns error if flag is bad, 0 on success.

Output

0x7 set_flag (encrypt)
Input: 0x20 buffer.

Output: 0x20 encrypted buffer that can be written to NVS at offset 0.

rmauth_sm.self
Removable Media (Memory Card) authentication. Used by SceMsif.

0x1 - get_key_master_gen_no
Response (size 0x20 bytes):

0x2 - set_index_key
Scrambles and sets the DMAC5 keyslot 0x1C key. The scrambling process consists of encrypting the first and second halves of the key seed with a private internal (could be considered as a couple of 0x10 keys)  key using AES128-CBC.

Request (size 0x20 bytes):

0x3
?clear_index_key?

Clears the DMAC5 keyslot 0x1C key (to 0).

spkg_verifier_sm_w_key_2.self
This is an extension of update_service_sm.self. It was added to support command 0xE0002.

0xE0002 sceSblUsSmAuthSpkgWithKey2
Used to decrypt downloaded lists (SPKGs). Same format as 0x40002.

Lists URLS:

update_service_sm.self
This is used by SceSblUpdateMgr to decrypt update packages extracted from PUP files. Both 0x40002 and 0x50002 reference buffers in the following way: an inner 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.

0x10002 sceSblUsSmAuthPupHeader
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_HEADER.

Verify PUP header.

Input data size: 0xFF0.

Input: PA vector of the PUP header including the PUP Hash (size: 0x80 + segment_num * 0x60 + 0x20)

0x20002 sceSblUsSmAuthPupSegment
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_SEGMENT.

Verify PUP segment.

Input data size: 0xFF0.

0x30002 sceSblUsSmAuthPupWatermark
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_WM.

Verify PUP watermark.

Input data size: 0xFF0.

Input data: a packet embedding at least two paddr (or PA vectors): PUP Watermark (0x1000 bytes) and PUP Hash (0x20 bytes).

0x40002 sceSblUsSmAuthSpkg
SCE_SBL_SM_COMM_FID_SM_AUTH_SPKG.

Decrypt a SPKG. Allocate a page aligned buffer and read the complete SPKG file into the buffer. The buffer is decrypted in place.

0x50002 sceSblUsSmEncryptIndividualSLSK
SCE_SBL_SM_COMM_FID_SM_ENCIND_SLSK.

Re-encrypt individual SLSK files (.enp files).

Each inner paddr list is first copied to temporary f00d memory, then they all are checked for validity at once. Maximum size of inner list is 0xff7 (so probably 0xff7 / 8 * 8 = 0xff0). Any lengths higher than that result in.

How it works:


 * first, all inner entries are checked for validity, if something's invalid, bail out
 * start at last outer entry and move towards the first
 * if current entry looks valid (length >= 8), proceed to inner paddr encryption
 * if no valid entries found, error=
 * if multiple valid entries found, error= (???) (but the first one found is always encrypted)
 * if only one valid entry is found, return success

Bugs(?):

00:00:26	0 // this is paddr 0x1F000000 00:00:26	0 00:00:26	0 00:00:26	2000 00:00:26	8 00:00:26	812d40 00:00:26	0 00:00:26	1f000020 // this is paddr 0x1F00001C 00:00:26	0 00:00:26	0 00:00:26	0 00:00:26	2000 00:00:26	8 00:00:26	812d40 00:00:26	0 00:00:26	1f000040 00:00:26	0 00:00:26	0 00:00:26	0 00:00:26	2000 00:00:26	8 00:00:26	812d40 00:00:26	0 00:00:26	1f000060 00:00:26	0 00:00:26	0 00:00:26	0 00:00:26	2000 00:00:26	8 00:00:26	812d40 00:00:26	0 00:00:26	1f000080
 * encrypting same paddr twice or more times within a single inner paddr list always results in same output, no matter what input was, reproducible with length=0x10 or less
 * sum(inner list sizes) must be <= 0xFF0, but there's no overflow check, a large inner list causes f00d to overwrite memory with data like:

0x60002 sceSblUsSmSnvsEncryptSectors
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_SECTORS.

The input is plain SNVS sectors read from NVS.

Calculates a XTS Encrypt using the per console keys in keyring slot 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 bytes in size, but the size in F00D packet +4 derives the XTS size and memcpy.

The result is XTS encrypted SNVS sectors.

Data size is 8 bytes + sectors size.

0x70002 sceSblUsSmSnvsDecryptSectors
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_SECTORS.

The input is XTS encrypted sectors.

Calculates a XTS Decrypt using the per console keys in keyring slot 0x502, and 0x503 for the tweak and decryption keys. Appears to be intended for up to 0x3E0 in size, but the size in F00D packet +4 derives the XTS size and memcpy.

The result is plain sectors.

Data size is 8 bytes + sectors size.

0x80002 sceSblUsSmSnvsEncryptMgmtData
SCE_SBL_SM_COMM_FID_SM_SNVS_ENC_MGMT.

The input are the new status and flags, and the current Mgmt Data sector read from NVS at offset 0.

Calculates a XTS Decrypt using the per console keys in keyring slot 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in. If ok, then it uses the seed 0xACA9B1AC to recalculate the block, generate a new hmac, and xts encrypt the block.

The result is a new Mgmt Data sector, which is to be written to NVS at offset 0.

Data size is 0x28 bytes.

0x90002 sceSblUsSmSnvsDecryptMgmtData
SCE_SBL_SM_COMM_FID_SM_SNVS_DEC_MGMT.

The input is the current Mgmt Data sector read from NVS at offset 0.

Calculates a XTS Decrypt using the per console keys in keyring slot 0x502, and 0x503 for the tweak and decryption keys. It then calculates an HMAC using the keyring 0x504 to check the block passed in.

The result is the current status and flags.

Data size is 0x28 bytes.

If flags[SCE_SBL_SS_SNVS_UPDATER_FLAG_INDEX] is not set, updater init is skipped:

0xA0002 sceSblUsSmAuthAdditionalSign
SCE_SBL_SM_COMM_FID_SM_AUTH_PUP_AS.

Verify PUP Additional Signatures.

0xB0002 sceSblUsSmSnvsEncryptDecryptSector
Added on FW 1.03. Usage similar to pm_sm command 8.

Data size is 0x88 bytes.

Usage: For read: For write:
 * 1) sceSblSmCommCallFunc(id, 0xB0002, &f00d_resp, data, 0x88);
 * 2) nvs_read_special(data + 0x28, 0x10, data + 0x58, 0x30)
 * 2) nvs_write_special(data + 0x28, 0x30, data + 0x58, 0x10);
 * 3) sceSblSmCommCallFunc(id, 0xB0002, &f00d_resp, data, 0x88);

0xC0002 sceSblUsSmSnvsEncryptDecryptMgmtData
Added on FW 1.03. Usage similar to pm_sm command 8.

Data size is 0x70 bytes.

Usage: For write: For read:
 * 1) sceSblSmCommCallFunc(id, 0xC0002, &f00d_resp, data, 0x70);
 * 2) nvs_write_special(data + 0x10, 0x30, data + 0x40, 0x10);
 * 2) nvs_read_special(data + 0x10, 0x10, data + 0x40, 0x30);
 * 3) sceSblSmCommCallFunc(id, 0xC0002, &f00d_resp, data, 0x70);

0xD0002
Syscon update related. Usage is to proxy encrypted data F00D <=> Syscon.

Data size is 0x58 bytes.

Usage: For modes 0, 1 and 3:
 * 1) sceSblSmCommCallFunc(id, 0xD0002, &f00d_resp, data, 0x58);
 * 2) memcpy(data + 8, data + 0x30, 0x28); SceSysconForDriver_4D03754A(data + 8, 0x28, data + 0x30, 0x28);
 * 3) sceSblSmCommCallFunc(id, 0xD0002, &f00d_resp, data, 0x58);

0x1 - verify_utoken
Verify SceUtoken buffer.

0x2 - decrypt utoken
Decrypt SceUtoken buffer, in order to get UT Flags.

mgkm_sm.self
MagicGate Key Manager secure module. These commands seem to be used to set keys (on FW 0.990 and 1.50). There are debug strings referencing these F00D commands as "set_key_command") on Dmac5. This key seems to be used to do stuff with TripleDES and another unknown encrypt algorithm.