Secure Monitor

From Nintendo Switch Brew
Revision as of 04:49, 13 March 2018 by SciresM (talk | contribs) (I see.)
Jump to navigation Jump to search

Secure Monitor Calls

The secure monitor provides two top level handlers of which each provides a range of sub handlers.

Secure Monitor Calls follow the ARM SMC calling convention up to a small change:

Bit number Bit mask Description
31 0x80000000 Set to 0 means Yielding Call; Set to 1 means Fast Call.
30 0x40000000 Set to 0 means SMC32 convention; Set to 1 means SMC64.
29-24 0x3F000000 Service Call ranges.
23-16 0x00FF0000 Must be zero.
15-8 0x0000FF00 Argument type. This is different from the ARM SMC calling convention.
7-0 0x000000FF Function number within the range call type.

If bit n is set in the argument type then parameter Xn is treated as a pointer and the kernel will setup address translation for it in svcCallSecureMonitor.

SMC arguments are passed using registers X0-X7 with X0 always sending the call sub-id and returning the result of the call.

ID 0

Functions exposed to user-mode processes using svcCallSecureMonitor.

Sub-ID Name In Out
0xC3000401 SetConfig
0xC3000002 GetConfig (Same as ID 1, Sub-ID 4)
0xC3000003 CheckStatus
0xC3000404 GetResult
0xC3000E05 ExpMod
0xC3000006 GetRandomBytes (Same as ID 1, Sub-ID 5)
0xC3000007 #GenerateAesKek
0xC3000008 #LoadAesKey
0xC3000009 #CryptAes
0xC300000A #GenerateSpecificAesKey
0xC300040B #ComputeCmac
[1.0.0-4.1.0] 0xC300100C #LoadRsaOaepKey
[5.0.0+] 0xC300D60C #EncryptRsaKeyForImport
[1.0.0-4.1.0] 0xC300100D #DecryptRsaPrivateKey
[1.0.0-4.1.0] 0xC300100E #LoadSecureExpModKey
0xC300060F #SecureExpMod
0xC3000610 #UnwrapRsaOaepWrappedTitleKey
0xC3000011 #LoadTitleKey
0xC3000012 [2.0.0+] UnwrapAesWrappedTitleKey

The overall concept here is the following:

  • All key material (AES and RSA) is stored in userspace, but it's encrypted with random AES kek's ("key encryption keys").
  • Each kek is generated as a function of an access key (picked at random).
  • The kek is generated differently depending on the #CryptoUsecase the key is used for.
    • This means: Each key is "locked" to the #CryptoUsecase it was designated for.
    • You can use a key for a different usecase, but you will only get garbage output.
  • After the kek has been generated, it is wrapped with a session-specific key and given back to userspace.
    • This means: Plaintext kek keys never leave TrustZone.
    • Further, this means: Actual AES/RSA keys never leave TrustZone.

Note: The CryptoUsecase_TitleKey represents a RSA wrapped AES key.

GenerateAesKek

Takes an "access key" as input, an #CryptoUsecase.

Returns a session-unique kek for said usecase.

LoadAesKey

Takes a session kek created with #GenerateAesKek, and a wrapped AES key.

The session kek must have been created with CryptoUsecase_Aes.

CryptAes

Encrypts/decrypts using Aes (CTR and CBC).

Key must be set prior using one of the #LoadAesKey, #GenerateSpecificAesKey or #LoadRsaWrappedAesKey commands.

GenerateSpecificAesKey

Todo: This one seems unrelated to #CryptoUsecase.

LoadRsaOaepKey

Takes a session kek created with #GenerateAesKek, a wrapped AES key, and a wrapped RSA private key.

The session kek must have been created with CryptoUsecase_RsaOaep.

This function was removed in 5.0.0, and replaced with #EncryptRsaKeyForImport.

EncryptRsaKeyForImport

Takes in two session keks created with #GenerateAesKek, two wrapped AES keys, an enum member, and a wrapped RSA private key.

Decrypts and validates the wrapped RSA private key with the first kek/wrapped key, and re-encrypts it with the second if valid.

The re-encrypted key is then passed to the user, for use with #DecryptRsaPrivateKey.

DecryptRsaPrivateKey

Takes a session kek created with #GenerateAesKek, a wrapped AES key, an enum member, and a wrapped RSA private key.

The session kek must have been created with CryptoUsecase_RsaPrivate.

[4.0.0+] The SMC handler when certain conditions pass and SMC_ID==0xC300100D now returns error 0x6 instead of calling the handler funcptr.

[5.0.0+] This SMC was extended to import private keys into the security engine instead of decrypting them, when certain enum members are passed.

LoadSecureExpModKey

Takes a session kek created with #GenerateAesKek, and a wrapped RSA key.

The session kek must have been created with CryptoUsecase_RsaSecureExpMod.

This function was removed in 5.0.0, and replaced with #EncryptRsaKeyForImport.

SecureExpMod

Performs an Exp Mod operation using an exponent previously loaded with the #LoadSecureExpModKey command.

UnwrapRsaOaepWrappedTitleKey

Takes an Rsa-Oaep-wrapped TitleKey, an RSA Public Key, and a label hash.

Performs an Exp Mod operation using an exponent previously loaded with the #LoadRsaOaepKey command, and then validates/extracts a Titlekey from the resulting message.

Returns a session-unique AES key especially for use in #LoadTitleKey.

LoadTitleKey

Takes a session-unique AES key from #UnwrapAesWrappedTitleKey or #UnwrapRsaOaepWrappedTitleKey.

enum CryptoUsecase

Value Name
0 CryptoUsecase_Aes
1 CryptoUsecase_RsaPrivate
2 CryptoUsecase_RsaSecureExpMod
3 CryptoUsecase_RsaOaep

ID 1

Functions exposed to the kernel internally.

Sub-ID Name In Out
0xC4000001 #CpuSuspend X1=power_state, X2=entrypoint_addr, X3=context_id None
0x84000002 #CpuOff None None
0xC4000003 #CpuOn X1=target_cpu, X2=entrypoint_addr, X3=context_id, X4,X5,X6,X7=0 X0=result
0xC3000004 #GetConfig (Same as ID 0, Sub-ID 2) W1=config_item, X2,X3,X4,X5,X6,X7=0 X0=result, X1,X2,X3,X4=config_val
0xC3000005 #GetRandomBytes (Same as ID 0, Sub-ID 6) X1=size, X2,X3,X4,X5,X6,X7=0 X0=result, X1,X2,X3,X4,X5,X6,X7=rand_bytes
0xC3000006 #Panic W1=panic_color, X2,X3,X4,X5,X6,X7=0 X0=result
0xC3000007 [2.0.0+] #ProtectKernelRegion X1=carveout_index, X2=region_phys_addr, X3=region_size, X4,X5,X6,X7=0 X0=result
0xC3000008 [2.0.0+] #ReadWriteRegister X1=reg_addr, W2=rw_mask, W3=in_val, X4,X5,X6,X7=0 X0=result, W1=out_val

CpuSuspend

Standard ARM PCSI SMC. Suspends the CPU (CPU0).

The kernel calls this SMC on shutdown with power_state set to 0x0201001B (power level: 0x02==system; power type: 0x01==powerdown; ID: 0x1B).

CpuOff

Standard ARM PCSI SMC. Turns off the CPU (CPU1, CPU2 or CPU3).

CpuOn

Standard ARM PCSI SMC. Turns on the CPU (CPU1, CPU2 or CPU3).

GetConfig

Takes a config_item and returns an associated config_val.

GetRandomBytes

Takes a size and returns rand_bytes.

The kernel limits size to 0x38 (for fitting in return registers).

Panic

Issues a system panic.

The kernel always calls this with panic_color set to 0xF00.

ProtectKernelRegion

Configures memory controller carveout regions.

If carveout_index is 0, region_phys_addr and region_size are used to configure MC_SECURITY_CARVEOUT4. If carveout_index is 1, region_phys_addr and region_size are used to configure MC_SECURITY_CARVEOUT5. Any other carveout_index values are invalid.

The kernel calls this with carveout_index set to 0, region_phys_addr set to 0x80060000 and region_size set to a dynamically calculated size which covers all the kernel and built-in sysmodules' DRAM regions.

ReadWriteRegister

Relays svcReadWriteRegister to the Secure Monitor.

Errors

Value Description
2 Invalid input
3 Busy