SPL services: Difference between revisions
No edit summary |
|||
(19 intermediate revisions by 5 users not shown) | |||
Line 1: | Line 1: | ||
SPL ("Secure Platform services") is responsible for handling all cryptographic operations within the system and relaying them to the [[SMC|Secure Monitor]] when necessary. | |||
During [1.0.0-3.0.2], the only existing services were "csrng" and "spl:". However, in [4.0.0+] the "spl:" service was refactored and split into new services with different permission levels. Each service exposes the IPC command list differently in order to prevent cryptographic operations to take place in the wrong context. | |||
= csrng = | = csrng = | ||
This is "nn::spl::detail::IRandomInterface". | This is "nn::spl::detail::IRandomInterface". | ||
Line 6: | Line 10: | ||
! Cmd || Name | ! Cmd || Name | ||
|- | |- | ||
| 0 || [[# | | 0 || [[#GenerateRandomBytes]] | ||
|} | |} | ||
== | == GenerateRandomBytes == | ||
Takes a type- | Takes a type-0xA buffer and fills it with random data from [[SMC#GetRandomBytes|GetRandomBytes SMC]]. Same command for "spl:" and "csrng" services, except for buffer-type. | ||
= spl: = | = spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu = | ||
These are "nn::spl::detail::IGeneralInterface", "nn::spl::detail::ICryptoInterface", "nn::spl::detail::IFsInterface", "nn::spl::detail::ISslInterface", "nn::spl::detail::IEsInterface" and "nn::spl::detail::IManuInterface". | |||
[2.0.0+] Where previously only one AES | [2.0.0+] Where previously only one AES keyslot was used, there is now support for 4 of them. | ||
[2.0.0+] When the session closes, all AES | [2.0.0+] When the session closes, all allocated AES keyslots are automatically freed. | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
|- | |- | ||
! Cmd || Name || | ! Cmd || Name || Permissions | ||
|- | |- | ||
| | | 0 || [[#GetConfig]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 1 || [[#ExpMod]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 2 || [[#GenerateAesKek]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 3 || [[#LoadAesKey]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 4 || [[#GenerateAesKey]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 5 || [[#SetConfig]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 7 || [[#GenerateRandomBytes]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| 9 || [[#ImportLotusKey]] || spl:fs | |||
|- | |- | ||
| | | 10 || [[#DecryptLotusMessage]] || spl:fs | ||
|- | |- | ||
| | | 11 || [[#IsDevelopment]] || spl:, spl:mig, spl:fs, spl:ssl spl:es, spl:manu | ||
|- | |- | ||
| | | 12 || [[#GenerateSpecificAesKey]] || spl:fs | ||
|- | |- | ||
| | | 13 || [[#DecryptRsaPrivateKey]] || spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 14 || [[#DecryptAesKey]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 15 || [[#CryptAesCtr]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 16 || [[#ComputeCmac]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 17 || [[#ImportEsKey]] || spl:es | ||
|- | |- | ||
| | | 18 || [[#UnwrapTitleKey]] || spl:es | ||
|- | |- | ||
| | | 19 || [[#LoadTitleKey]] || spl:fs | ||
|- | |- | ||
| | | 20 || [2.0.0+] [[#UnwrapCommonTitleKey]] || spl:es | ||
|- | |- | ||
| | | 21 || [2.0.0+] [[#AllocateAesKeyslot]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 22 || [2.0.0+] [[#FreeAesKeyslot]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 23 || [2.0.0+] [[#GetAesKeyslotAvailableEvent]] || spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 24 || [3.0.0+] [[#SetBootReason]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 25 || [3.0.0+] [[#GetBootReason]] || spl:, spl:mig, spl:fs, spl:ssl, spl:es, spl:manu | ||
|- | |- | ||
| | | 26 || [5.0.0+] ImportSslKey || spl:ssl | ||
|- | |- | ||
| 27 || [5.0.0+] SslExpMod || spl:ssl | |||
|- | |- | ||
| | | 28 || [5.0.0+] ImportDrmKey || spl:es | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | | 29 || [5.0.0+] DrmExpMod || spl:es | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | | 30 || [5.0.0+] ReEncryptRsaPrivateKey || spl:manu | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | | 31 || [5.0.0+] GetPackage2Hash || spl:fs | ||
| | |||
| | |||
| | |||
|- | |- | ||
| | | 31 || [6.0.0+] UnwrapElicenseKey || spl:es | ||
| | |||
| | |||
| | |||
|- | |- | ||
| 32 || [6.0.0+] [[#LoadElicenseKey]] || spl:es | |||
|} | |} | ||
== GetConfig == | |||
Wrapper for [[SMC#GetConfig|GetConfig SMC]]. | |||
Takes a u32 ('''ConfigItem'''), and returns one or more u64s ('''ConfigVal'''). | |||
== | == ExpMod == | ||
Wrapper for [[SMC#ExpMod|ExpMod SMC]]. | |||
Takes one type-10 (C descriptor) buffer ('''data_out_buf''') and 3 type-9 (X descriptor) buffers ('''data_in_buf''', '''exp_in_buf''' and '''mod_in_buf'''). | Takes one type-10 (C descriptor) buffer ('''data_out_buf''') and 3 type-9 (X descriptor) buffers ('''data_in_buf''', '''exp_in_buf''' and '''mod_in_buf'''). | ||
Line 219: | Line 105: | ||
== GenerateAesKek == | == GenerateAesKek == | ||
Wrapper for [[SMC#GenerateAesKek|GenerateAesKek SMC]]. | |||
Takes a 16-byte EKS ('''Encryption Key Source''') and two words ('''KeyGeneration''' and '''option''') as input. | Takes a 16-byte EKS ('''Encryption Key Source''') and two words ('''KeyGeneration''' and '''option''') as input. | ||
Returns a scrambled sealed KEK ('''Key Encryption Key''' used as '''key_x'''). | Returns a scrambled sealed KEK ('''Key Encryption Key''' used as '''key_x'''). | ||
== LoadAesKey == | == LoadAesKey == | ||
Wrapper for [[SMC#LoadAesKey|LoadAesKey SMC]]. | |||
Takes a u32 ('''keyslot''') and two 16-byte keys ('''key_x''' and '''key_y'''). | Takes a u32 ('''keyslot''') and two 16-byte keys ('''key_x''' and '''key_y'''). | ||
Sets the specified '''keyslot''' with a key generated from '''key_x''' and '''key_y'''. | Sets the specified '''keyslot''' with a key generated from '''key_x''' and '''key_y'''. | ||
[2.0.0+] Now verifies that the | [2.0.0+] Now verifies that the keyslot in use (0..3) is allocated by the current spl session, otherwise errors with 0xD21A. Previously, keyslot was hardcoded to 0. | ||
== GenerateAesKey == | == GenerateAesKey == | ||
Takes a 16-byte KEK ('''key_x''') and a 16-byte encrypted key ('''enc_key'''). | Takes a 16-byte KEK ('''key_x''') and a 16-byte encrypted key ('''enc_key'''). | ||
Generates a new key by decrypting '''enc_key''' with a key generated from the supplied '''key_x''' and a fixed '''key_y'''. | Generates a new key by decrypting (AES-ECB) '''enc_key''' with a key generated from the supplied '''key_x''' and a fixed '''key_y''' set with [[SMC#LoadAesKey|LoadAesKey SMC]]. | ||
[2.0.0+] Previously, it always used | [2.0.0+] Previously, it always used keyslot 0. Now it tries to allocate a keyslot to be used and returns 0xD01A if they're all busy. When the command is done, the keyslot is released. | ||
== SetConfig == | == SetConfig == | ||
Wrapper for [[SMC#SetConfig|SetConfig SMC]]. | |||
Takes a u32 ('''ConfigItem''') and a u64 ('''ConfigVal'''). | Takes a u32 ('''ConfigItem''') and a u64 ('''ConfigVal'''). | ||
Line 245: | Line 136: | ||
! ConfigItem || Name | ! ConfigItem || Name | ||
|- | |- | ||
| 13 || | | 13 || IsChargerHiZModeEnabled | ||
|} | |} | ||
Any other '''ConfigItem''', besides 13, can't be set. | Any other '''ConfigItem''', besides 13, can't be set. | ||
== | == ImportLotusKey == | ||
Wrapper for [[SMC#ImportLotusKey|ImportLotusKey SMC]]. | |||
Takes one type-9 (X descriptor) buffer ('''enc_privk_in_buf'''), a 16-byte KEK ('''key_x'''), a 16-byte key ('''key_y''') and a u32 ('''version'''). | Takes one type-9 (X descriptor) buffer ('''enc_privk_in_buf'''), a 16-byte KEK ('''key_x'''), a 16-byte key ('''key_y''') and a u32 ('''version'''). | ||
'''version''' is 0 for normal keys or 1 for extended keys. | '''version''' is 0 for normal keys or 1 for extended keys. | ||
Line 256: | Line 149: | ||
Decrypts '''enc_privk_in_buf''' with a key generated from '''key_x''' and '''key_y''' and imports it for later usage. | Decrypts '''enc_privk_in_buf''' with a key generated from '''key_x''' and '''key_y''' and imports it for later usage. | ||
[5.0.0+] The '''version''' param was removed, and this now calls [[SMC#ReEncryptRsaPrivateKey|ReEncryptRsaPrivateKey SMC]] instead. | |||
== DecryptLotusMessage == | |||
Takes 3 type-9 (X descriptor) buffers ('''data_in_buf''', '''mod_in_buf''' and '''label_hash_in_buf'''). | |||
Uses [[SMC#SecureExpMod|SecureExpMod SMC]] to decrypt '''data_in_buf''' using the private key imported with [[#ImportLotusKey]] and the supplied '''mod_in_buf''' and '''label_hash_in_buf'''. | |||
== IsDevelopment == | == IsDevelopment == | ||
Line 271: | Line 164: | ||
== GenerateSpecificAesKey == | == GenerateSpecificAesKey == | ||
Wrapper for [[SMC#GenerateSpecificAesKey|GenerateSpecificAesKey SMC]]. | |||
Takes a 16-byte seed ('''key_seed''') and two words ('''KeyGeneration''' and '''option''') as input. | Takes a 16-byte seed ('''key_seed''') and two words ('''KeyGeneration''' and '''option''') as input. | ||
Returns a scrambled key ('''key_a'''). | Returns a scrambled key ('''key_a'''). | ||
== | == DecryptRsaPrivateKey == | ||
Wrapper for [[SMC#DecryptRsaPrivateKey|DecryptRsaPrivateKey SMC]]. | |||
Takes one type-10 (C descriptor) buffer ('''dec_privk_out_buf'''), one type-9 (X descriptor) buffer ('''enc_privk_in_buf'''), a 16-byte KEK ('''key_x'''), a 16-byte key ('''key_y''') and a u32 ('''version'''). | Takes one type-10 (C descriptor) buffer ('''dec_privk_out_buf'''), one type-9 (X descriptor) buffer ('''enc_privk_in_buf'''), a 16-byte KEK ('''key_x'''), a 16-byte key ('''key_y''') and a u32 ('''version'''). | ||
'''version''' is 0 for normal keys or 1 for extended keys. | '''version''' is 0 for normal keys or 1 for extended keys. | ||
Line 283: | Line 179: | ||
Used by [[SSL_services|SSL]]-sysmodule for TLS client-privk. | Used by [[SSL_services|SSL]]-sysmodule for TLS client-privk. | ||
[5.0.0+] The '''version''' param was removed, and this now calls [[SMC#DecryptOrImportRsaPrivateKey|DecryptOrImportRsaPrivateKey SMC]] instead. | |||
== DecryptAesKey == | == DecryptAesKey == | ||
Takes a 16-byte encrypted key ('''enc_key''') and two words ('''KeyGeneration''' and '''option''') as input. | Takes a 16-byte encrypted key ('''enc_key''') and two words ('''KeyGeneration''' and '''option''') as input. | ||
Decrypts '''enc_key''' with a key generated from fixed '''key_x''' and '''key_y''' and returns a 16-byte decrypted key ('''dec_key'''). | Decrypts (AES-ECB) '''enc_key''' with a key generated from fixed '''key_x''' and '''key_y''' set with [[SMC#LoadAesKey|LoadAesKey SMC]] and returns a 16-byte decrypted key ('''dec_key'''). | ||
[2.0.0+] Introduced same | [2.0.0+] Introduced same keyslot allocation code as for [[#GenerateAesKey]]. | ||
== | == CryptAesCtr == | ||
Takes a type-0x46 (B descriptor) buffer ('''data_out_buf'''), a u32 ('''keyslot'''), a type-0x45 (A descriptor) buffer ('''data_in_buf''') and a 16-byte CTR ('''aes_ctr'''). | Takes a type-0x46 (B descriptor) buffer ('''data_out_buf'''), a u32 ('''keyslot'''), a type-0x45 (A descriptor) buffer ('''data_in_buf''') and a 16-byte CTR ('''aes_ctr'''). | ||
Uses [[SMC#ComputeAes|ComputeAes SMC]] to decrypt '''data_in_buf''' into '''data_out_buf''', using the key set in the specified '''keyslot'''. | |||
[2.0.0+] Verifies the | [2.0.0+] Verifies the keyslot was allocated in the current session. | ||
== ComputeCmac == | == ComputeCmac == | ||
Wrapper for [[SMC#ComputeCmac|ComputeCmac SMC]]. | |||
Takes one type-9 (X descriptor) buffer ('''data_in_buf''') and a u32 ('''type?'''). | Takes one type-9 (X descriptor) buffer ('''data_in_buf''') and a u32 ('''type?'''). | ||
Returns a 16-byte CMAC calculated over '''data_in_buf'''. | Returns a 16-byte CMAC calculated over '''data_in_buf'''. | ||
[2.0.0+] Verifies the | [2.0.0+] Verifies the keyslot was allocated in the current session. | ||
== | == ImportEsKey == | ||
Takes one type-9 (X descriptor) buffer ( | Wrapper for [[SMC#ImportEsKey|ImportEsKey SMC]]. | ||
Takes one type-9 (X descriptor) buffer (enc_privk_in_buf), a 16-byte KEK (key_x), a 16-byte key (key_y) and a u32 (version). version is 0 for normal keys or 1 for extended keys. | |||
Decrypts enc_privk_in_buf with a key generated from key_x and key_y and imports it for later usage. | |||
[5.0.0+] The '''version''' param was removed, and this now calls [[SMC#ReEncryptRsaPrivateKey|ReEncryptRsaPrivateKey SMC]] instead. | |||
== UnwrapTitleKey == | |||
Wrapper for [[SMC#UnwrapTitleKey|UnwrapTitleKey SMC]]. | |||
Takes one type-10 (C descriptor) buffer ('''data_out_buf''') and 3 type-9 (X descriptor) buffers ('''data_in_buf''', '''mod_in_buf''' and '''label_hash_in_buf'''). | |||
[3.0.0+] Now takes an additional 4-bytes of input. | |||
Decrypts '''data_in_buf''' using the private key imported with [[# | Decrypts '''data_in_buf''' into '''data_out_buf''' using the private key imported with [[#ImportEsKey]] and the supplied '''mod_in_buf'''. Afterwards, verifies RSA-OAEP encoding using '''label_hash_in_buf'''. | ||
Returns an u32 ('''dec_data_size'''). | |||
== LoadTitleKey == | == LoadTitleKey == | ||
Wrapper for [[SMC#LoadTitleKey|LoadTitleKey SMC]]. | |||
Takes a u32 ('''keyslot''') and a 16-byte sealed titlekey. | Takes a u32 ('''keyslot''') and a 16-byte sealed titlekey. | ||
Sets the specified '''keyslot''' with the titlekey. | Sets the specified '''keyslot''' with the titlekey. | ||
[2.0.0+] Verifies the | [2.0.0+] Verifies the keyslot was allocated in the current session. | ||
== UnwrapCommonTitleKey == | |||
Wrapper for [[SMC#UnwrapCommonTitleKey|UnwrapCommonTitleKey SMC]]. | |||
Takes a 16-byte EKS ('''Encryption Key Source'''). | Takes a 16-byte EKS ('''Encryption Key Source'''). | ||
[3.0.0+] Now takes an additional 4-bytes of input. | |||
Returns a sealed titlekey. | Returns a sealed titlekey. | ||
== | == AllocateAesKeyslot == | ||
Returns | Returns an allocated keyslot, or 0xD01A if all keyslots are taken. You need to allocate a keyslot before using AES functions. | ||
== | == FreeAesKeyslot == | ||
Takes a single u32 and | Takes a single u32 and frees the keyslot. The keyslot must have been allocated by current session otherwise 0xD21A will be returned. | ||
== | == GetAesKeyslotAvailableEvent == | ||
Returns an event handle for synchronizing with the | Returns an event handle for synchronizing with the AES keyslots. | ||
== | == SetBootReason == | ||
Sets a static dword in spl .bss to the | Sets a static dword in spl .bss to the input u32 '''BootReason'''. | ||
[4.0.0+] returns 0xD41A if a value has been previously set without being [[# | [4.0.0+] returns 0xD41A if a value has been previously set without being [[#GetBootReason|gotten]]. | ||
== | == GetBootReason == | ||
Returns the static dword in spl .bss that can be set via [[# | Returns the static dword '''BootReason''' in spl .bss that can be set via [[#SetBootReason]]. | ||
[4.0.0+] returns 0xD61A if a value has not previously been set, and unsets the value after getting it. | [4.0.0+] returns 0xD61A if a value has not previously been set, and unsets the value after getting it. | ||
== LoadElicenseKey == | |||
Same as [[#LoadTitleKey|LoadTitleKey]]. | |||
[[Category:Services]] |