Difference between revisions of "Secure Monitor"
(→Id 1) |
|||
Line 22: | Line 22: | ||
If bit ''n'' is set in the argument type then parameter X''n'' is treated as a pointer and the kernel will setup address translation for it in [[SVC#svcCallSecureMonitor|svcCallSecureMonitor]]. | If bit ''n'' is set in the argument type then parameter X''n'' is treated as a pointer and the kernel will setup address translation for it in [[SVC#svcCallSecureMonitor|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 [[SVC|svcCallSecureMonitor]]. | Functions exposed to user-mode processes using [[SVC|svcCallSecureMonitor]]. | ||
{| class=wikitable | {| class=wikitable | ||
− | ! Sub- | + | ! Sub-ID || Name || In || Out |
|- | |- | ||
| 0xC3000401 || SetConfig || || | | 0xC3000401 || SetConfig || || | ||
|- | |- | ||
− | | 0xC3000002 || GetConfig (Same as | + | | 0xC3000002 || GetConfig (Same as ID 1, Sub-ID 4) || || |
|- | |- | ||
| 0xC3000003 || CheckStatus || || | | 0xC3000003 || CheckStatus || || | ||
Line 38: | Line 40: | ||
| 0xC3000E05 || ExpMod || || | | 0xC3000E05 || ExpMod || || | ||
|- | |- | ||
− | | 0xC3000006 || GetRandomBytes (Same as | + | | 0xC3000006 || GetRandomBytes (Same as ID 1, Sub-ID 5) || || |
|- | |- | ||
| 0xC3000007 || [[#GenerateAesKek]] || || | | 0xC3000007 || [[#GenerateAesKek]] || || | ||
Line 58: | Line 60: | ||
| 0xC300060F || [[#PublicRsa]] || || | | 0xC300060F || [[#PublicRsa]] || || | ||
|- | |- | ||
− | | 0xC3000610 || [[# | + | | 0xC3000610 || [[#UnwrapPreparedAesKey]] || || |
|- | |- | ||
− | | 0xC3000011 || [[# | + | | 0xC3000011 || [[#LoadPreparedAesKey]] || || |
|- | |- | ||
− | | 0xC3000012 || [2.0.0+] | + | | 0xC3000012 || [2.0.0+] GeneratePreparedAesKek || || |
|} | |} | ||
Line 74: | Line 76: | ||
** This means: Plaintext kek keys never leave TrustZone. | ** This means: Plaintext kek keys never leave TrustZone. | ||
** Further, this means: Actual AES/RSA keys never leave TrustZone. | ** Further, this means: Actual AES/RSA keys never leave TrustZone. | ||
+ | |||
+ | Note: | ||
+ | The [[#CryptoUsecase|CryptoUsecase_PreparedAesKey]] represents a RSA wrapped AES key. | ||
=== GenerateAesKek === | === GenerateAesKek === | ||
Line 113: | Line 118: | ||
Key must be set prior using the [[#LoadRsaPublicKey]] command. | Key must be set prior using the [[#LoadRsaPublicKey]] command. | ||
− | === | + | === UnwrapPreparedAesKey === |
Takes a session kek created with [[#GenerateAesKek]], and a wrapped RSA public key. | Takes a session kek created with [[#GenerateAesKek]], and a wrapped RSA public key. | ||
− | Returns a session-unique AES key especially for use in [[# | + | Returns a session-unique AES key especially for use in [[#LoadPreparedAesKey]]. |
− | The session kek must have been created with | + | The session kek must have been created with CryptoUsecase_PreparedAesKey. |
− | === | + | === LoadPreparedAesKey === |
− | Takes a session-unique AES key from [[# | + | Takes a session-unique AES key from [[#UnwrapPreparedAesKey]]. |
=== enum CryptoUsecase === | === enum CryptoUsecase === | ||
Line 133: | Line 138: | ||
| 2 || CryptoUsecase_PublicRsa | | 2 || CryptoUsecase_PublicRsa | ||
|- | |- | ||
− | | 3 || | + | | 3 || CryptoUsecase_PreparedAesKey |
|} | |} | ||
− | == | + | == ID 1 == |
Functions exposed to the kernel internally. | Functions exposed to the kernel internally. | ||
{| class=wikitable | {| class=wikitable | ||
− | ! Sub- | + | ! Sub-ID || Name || In || Out |
|- | |- | ||
− | | 0xC4000001 || CpuSuspend || X1=power_state, X2=entrypoint_addr, X3= | + | | 0xC4000001 || [[#CpuSuspend]] || X1=power_state, X2=entrypoint_addr, X3=context_id || None |
|- | |- | ||
− | | 0x84000002 || CpuOff || None || None | + | | 0x84000002 || [[#CpuOff]] || None || None |
|- | |- | ||
− | | 0xC4000003 || CpuOn || || | + | | 0xC4000003 || [[#CpuOn]] || X1=target_cpu, X2=entrypoint_addr, X3=context_id, X4,X5,X6,X7=0 || X0=result |
|- | |- | ||
− | | 0xC3000004 || GetConfig (Same as | + | | 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 | + | | 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=unk, X2,X3,X4,X5,X6,X7=0 || X0=result | + | | 0xC3000006 || [[#Panic]] || W1=unk, X2,X3,X4,X5,X6,X7=0 || X0=result |
|- | |- | ||
| 0xC3000007 || [2.0.0+] ProtectKernelRegion || || | | 0xC3000007 || [2.0.0+] ProtectKernelRegion || || | ||
Line 158: | Line 163: | ||
| 0xC3000008 || [2.0.0+] ReadWriteRegister || || | | 0xC3000008 || [2.0.0+] ReadWriteRegister || || | ||
|} | |} | ||
+ | |||
+ | === 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 '''unk''' set to 0xF00. | ||
= Errors = | = Errors = | ||
− | 2 | + | {| class=wikitable |
− | 3 | + | ! Value || Description |
+ | |- | ||
+ | | 2 || Invalid input | ||
+ | |- | ||
+ | | 3 || Busy | ||
+ | |} |
Revision as of 20:10, 7 December 2017
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 | ||
0xC300100C | #LoadRsaPrivateKey | ||
0xC300100D | #PrivateRsa | ||
0xC300100E | #LoadRsaPublicKey | ||
0xC300060F | #PublicRsa | ||
0xC3000610 | #UnwrapPreparedAesKey | ||
0xC3000011 | #LoadPreparedAesKey | ||
0xC3000012 | [2.0.0+] GeneratePreparedAesKek |
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_PreparedAesKey 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.
LoadRsaPrivateKey
Takes a session kek created with #GenerateAesKek, and a wrapped RSA private key.
The session kek must have been created with CryptoUsecase_PrivateRsa.
PrivateRsa
Encrypts using Rsa private key.
Key must be set prior using the #LoadRsaPrivateKey command.
LoadRsaPublicKey
Takes a session kek created with #GenerateAesKek, and a wrapped RSA public key.
The session kek must have been created with CryptoUsecase_PublicRsa.
PublicRsa
Encrypts using Rsa public key.
Key must be set prior using the #LoadRsaPublicKey command.
UnwrapPreparedAesKey
Takes a session kek created with #GenerateAesKek, and a wrapped RSA public key.
Returns a session-unique AES key especially for use in #LoadPreparedAesKey.
The session kek must have been created with CryptoUsecase_PreparedAesKey.
LoadPreparedAesKey
Takes a session-unique AES key from #UnwrapPreparedAesKey.
enum CryptoUsecase
Value | Name |
---|---|
0 | CryptoUsecase_Aes |
1 | CryptoUsecase_PrivateRsa |
2 | CryptoUsecase_PublicRsa |
3 | CryptoUsecase_PreparedAesKey |
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=unk, X2,X3,X4,X5,X6,X7=0 | X0=result |
0xC3000007 | [2.0.0+] ProtectKernelRegion | ||
0xC3000008 | [2.0.0+] ReadWriteRegister |
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 unk set to 0xF00.
Errors
Value | Description |
---|---|
2 | Invalid input |
3 | Busy |