Cmep: Difference between revisions

From Vita Development Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
 
(15 intermediate revisions by 2 users not shown)
Line 1: Line 1:
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 a [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP-c5] core.
Cmep, also named Cry, is a processor in the PS Vita responsible for most of the cryptography tasks including storing and handing of the most secure keys. Cmep was named "F00D" by Team Molecule after the <code>e_machine</code> field of the ELF headers, but its official name is CMeP (standing for either Crypto MeP or Control MeP). Cmep is a [http://en.wikipedia.org/wiki/Media-embedded_processor Toshiba MeP-c5] core.


You can find an open source f00d protocol implementation at https://github.com/xyzz/f00d
More information can be found in Toshiba documentations. For example: https://toshiba.semicon-storage.com/info/docget.jsp?did=14997&prodName=TMPV7504XBG.


== Communication ==
== Devices ==
Communication seems to go through some sort of FIFO register.


=== Write ===
See [[Physical_Memory#Cmep registers]] and [[Cmep registers]] for physical memory mapping.
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.


=== Read ===
== Reset ==
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>.


=== Extra ports ===
Although the MeP architecture documentations specify that with EVM=0 the reset/NMI vector base is at 0x00000000, it is observed that the vector base is actually at 0x00040000. However, EVA/IVA still works as expected when EVM=1. Both [[Secure Kernel]] and [[Second Loader]] set EVM=0 at the start. This is likely a modified hardware behavior and the vector base remapping might be done when the [[First Loader]] is unmapped.
In addition to the 0xE0000000 and 0xE0000010, the communication with F00D seems to happen with other ports too.


{| class='wikitable'
== Protocol ==
|-
! Port
! Read
! Write
! Used by
|-
| 0xE0000004
| YES
| ?
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8
|-
| 0xE0000008
| YES
| ?
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8
|-
| 0xE000000C
| YES
| ?
| SMC 0x12d, 0x136, 0x137, 0x13B Interrupt 0xC8
|-
| 0xE0000014
| YES
| YES
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]
|-
| 0xE0000018
| YES
| YES
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]
|-
| 0xE000001C
| YES
| YES
| Used to send commands to f00d secure module, see [[F00D Processor#Executing sm commands|Executing sm commands]]
|-
| 0xE0000054
| ?
| YES
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8
|-
| 0xE0000058
| ?
| YES
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8
|-
| 0xE000005C
| ?
| YES
| SMC 0x12d, 0x135, 0x13B, Interrupt 0xC8
|-
| 0xE0010000
| YES
| YES
| Used by F00D Command 0 to prepare F00D to receive an address that contains the secure kernel enp.
|-
| 0xE0010004
| YES
| ?
| Used by F00D Command 0 to check if the value written in <code>0xE0010000</code> is okay (it should return a value <= 0)
|-
 
|}


== Protocol ==
A 32-bit command buffer is defined below. The command is sent to Cmep with the method listed above.
A 32-bit command buffer is defined below. The command is sent to the F00D processor with the method listed above.


{| class='wikitable'
{| class='wikitable'
Line 91: Line 23:
|-
|-
| 31
| 31
| 23
| 16
| ?
| Size
| ?
| Size of the command buffer
|-
| 22
| 19
| flag?
| b1010, b0010, b0001
|-
|-
| 18
| 18
| 13
| 13
| ?
| -
| Always 0
| Always 0
|-
|-
Line 108: Line 35:
| 8
| 8
| ID
| ID
| [[F00D Processor#Command ID|Command ID]]
| [[#Command ID|Command ID]]
|-
|-
| 7
| 7
| 1
| 1
| ?
| -
| Always 0
| Always 0
|-
|-
Line 118: Line 45:
| 0
| 0
| Valid
| Valid
| Set 1 to indicate command is valid
| Set to 1
|-
|-
|}
|}


=== Command ID ===
=== Command ID ===
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).


==== 0x0 ====
There are a total of 17 commands. Commands pass data through the 0x100 shared buffer that is setup in command 0.
 
==== Command 0 ====


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.  
This command is used to setup a shared buffer with Cmep. Firstly, Cmep will write in <code>0xE0000000</code> either 0x200 or 0x600 (and if an error happened, 0x400?). If the value 0x600 is written, it will setup a buffer that contains the secure_kernel.enp. It will write 1 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 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. The physical address of the buffer is written to <code>0xE0000010</code> and then command 0x0 is written.  


==== 0x1 ====
==== Command 1 ====


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.
This command is called by a subroutine of [[SceSblSmsched#sceSblSmSchedStopForTZS]] or [[SceSblSmsched]] module_start (if an error happened while [[SceSblSmsched]] was initializing). This command seems to be used to ask Cmep to remove all allocated resources (like shared memory address, loaded Secure Module, etc), and probably power off or reset it.


==== 0x2 ====
==== Command 2 ====


Load sm.
Load a [[Secure Modules|Secure Module]].


{| class='wikitable'
{| class='wikitable'
Line 149: Line 77:
| 0x4
| 0x4
| 0x4
| 0x4
| paddr_list for sm elf
| paddr_list for [[Secure Modules|Secure Module]] ELF
|-
|-
| 0x8
| 0x8
Line 173: Line 101:
| 0x20
| 0x20
| 0x4
| 0x4
| partition ID
| partition ID, ?Media Type?
|}
|}


==== 0x3 ====
==== Command 3 ====


Load previously suspended sm
Load the previously suspended [[Secure Modules|Secure Module]].


{| class='wikitable'
{| class='wikitable'
Line 203: Line 131:
|}
|}


==== 0x4 ====
==== Command 4 ====


Suspend current sm
Suspend the current [[Secure Modules|Secure Module]].


{| class='wikitable'
{| class='wikitable'
Line 230: Line 158:
|}
|}


==== 0x5 ====
==== Command 5 ====


Kill current sm
Kill the current [[Secure Modules|Secure Module]].


==== 0x6 ====
==== Command 6 ====


Force stop? Called from <code>sceSblSmSchedDeleteAll</code>.
Force stop? Called from [[SceSblSmsched|sceSblSmSchedDeleteAll]].


==== 0x7 ====
==== Command 7 ====


Unused.
Unused.


==== 0x8 ====
==== Command 8 ====


Unused.
Unused.


==== 0x9 ====
==== Command 9 ====


Set a 0x80 sized shared buffer.
Set a 0x80 sized shared buffer.
This seems like a SceKernelPARange.


{| class='wikitable'
{| class='wikitable'
Line 258: Line 188:
| 0x0
| 0x0
| 0x4
| 0x4
| paddr
| PA
|-
|-
| 0x4
| 0x4
Line 265: Line 195:
|}
|}


==== 0xA ====
==== Command 10 ====


Set the [[SCE]] encrypted revocation list.
Set the encrypted signed revoke list.


{| class='wikitable'
{| class='wikitable'
Line 281: Line 211:
| 0x4
| 0x4
| 0x4
| 0x4
| paddr_list for revocation list
| paddr_list for signed revoke list
|}
|}


==== 0xB ====
==== Command 11 ====


==== 0xC ====
==== Command 12 ====


==== 0xD ====
==== Command 13 ====


==== 0xE ====
==== Command 14 ====


==== 0xF ====
==== Command 15 ====


==== 0x10 ====
==== Command 16 ====


=== Interrupts ===
=== Interrupts ===


There are 4 interrupts that f00d sends. There are only two interrupt handles, however.
There are 4 interrupts that Cmep sends. There are only two interrupt handles, however.


* <code>cry2arm0</code>: handles interrupt 200. This is notifications about current sm status changes (loaded, unloaded, suspended, etc)
* <code>cry2arm0</code>: handles interrupt 200. This is notifications about current [[Secure Modules|Secure Module]] status changes (loaded, unloaded, suspended, etc.)
* <code>cry2arm123</code>: handles interrupts 201, 202, 203. This interrupt is sent once an sm command has finished processing (see below).
* <code>cry2arm123</code>: handles interrupts 201, 202, 203. This interrupt is sent once an [[Secure Modules|Secure Module]] function has finished processing (see below).


=== Executing sm commands ===
=== Executing Secure Module functions ===


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.
You can find an open source ARM TrustZone<->Cmep protocol implementation at https://github.com/xyzz/f00d. It allows calling [[Secure Modules|Secure Modules]] commands with a maximum of control over the sent data, received data and timing.


Command buffer structure:
When a [[Secure Modules|Secure Module]] is loaded, you can execute [[Secure Modules Functions|functions]] it provides by writing into registers 0xE0000014, 0xE0000018, 0xE000001C the physical address of the [[Secure Modules Functions#Request_Buffer|request buffer]] OR'd with 1.
 
{| class='wikitable'
|-
! Offset
! Size
! Description
|-
| 0x0
| 0x4
| Size of header + data
|-
| 0x4
| 0x4
| Command ID
|-
| 0x8
| 0x4
| unk1
|-
| 0xC
| 0x4
| unk2
|-
| 0x10
| 0x30
| padding
|-
| 0x40
| variable, max=0x1000-0x40
| data buffer
|}


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.
Once result is available, ARM will get an interrupt 201-203. Read status code from 0xE0000004 or 0xE0000008 or 0xE000000C and confirm you received it by writing it back to the same register.


Possible results:
Possible results:


* 1: command executed successfully
* 1: command executed successfully
* 3: invalid command ID
* 3: invalid function ID
* 5: invalid command buffer paddr (e.g. trying to pass secure memory)
* 5: invalid function buffer physical address (e.g. trying to pass secure memory)
* 9: SCE_SBL_ERROR_COMMON_EIO
* 9: SCE_SBL_ERROR_COMMON_EIO


== Memory ==
== Memory ==


<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>.
Cmep has its own private 128kB memory from <code>0x00800000</code> to <code>0x00820000</code>. [[Secure Kernel]] is loaded to <code>0x00800000</code>. [[Secure Modules]] are typically loaded to <code>0x0080B000</code>.


== Task states ==
== Secure Modules Task states ==


ARM secure world implements a scheduler for SM tasks. Normally, only one task can run on f00d at a time. The external scheduler running on ARM allows to have multiple tasks at once. The following provides an explanation of various states the task can be in.
ARM [[TrustZone]] implements a scheduler for [[Secure Modules]] tasks. Normally, only one task can run on Cmep at a time. The external [[Secure Modules]] scheduler running on ARM allows to have multiple tasks at once. The following provides an explanation of various states the task can be in.


{| class='wikitable'
{| class='wikitable'
Line 398: Line 297:
| ?
| ?
|}
|}
== Related pages ==
* [[Cmep basics]]
* [[Cmep registers]]
* [[Cmep Key Ring Base]]
* [[Secure Block]]
* [[First Loader]]
* [[Second Loader]]
* [[Secure Kernel]]
* [[Secure Modules]]
* [[Secure Modules Functions]]
* [[Ernie Secure]]

Latest revision as of 23:43, 16 July 2023

Cmep, also named Cry, is a processor in the PS Vita responsible for most of the cryptography tasks including storing and handing of the most secure keys. Cmep was named "F00D" by Team Molecule after the e_machine field of the ELF headers, but its official name is CMeP (standing for either Crypto MeP or Control MeP). Cmep is a Toshiba MeP-c5 core.

More information can be found in Toshiba documentations. For example: https://toshiba.semicon-storage.com/info/docget.jsp?did=14997&prodName=TMPV7504XBG.

Devices

See Physical_Memory#Cmep registers and Cmep registers for physical memory mapping.

Reset

Although the MeP architecture documentations specify that with EVM=0 the reset/NMI vector base is at 0x00000000, it is observed that the vector base is actually at 0x00040000. However, EVA/IVA still works as expected when EVM=1. Both Secure Kernel and Second Loader set EVM=0 at the start. This is likely a modified hardware behavior and the vector base remapping might be done when the First Loader is unmapped.

Protocol

A 32-bit command buffer is defined below. The command is sent to Cmep with the method listed above.

Bit End Bit Start Name Description
31 16 Size Size of the command buffer
18 13 - Always 0
12 8 ID Command ID
7 1 - Always 0
0 0 Valid Set to 1

Command ID

There are a total of 17 commands. Commands pass data through the 0x100 shared buffer that is setup in command 0.

Command 0

This command is used to setup a shared buffer with Cmep. Firstly, Cmep will write in 0xE0000000 either 0x200 or 0x600 (and if an error happened, 0x400?). If the value 0x600 is written, it will setup a buffer that contains the secure_kernel.enp. It will write 1 to 0xE0010000 and after that 0x0 to 0xE0010000, next, it will wait 0xE0010000 return 0 and 0xE0010004 return a value <= 0x0. If everything goes alright, it will clear the low 2 bits of the secure_kernel.enp address (normally at 0x1F850000) and OR it with 0x1 and then write it to 0xE0000010. After it, the process is the same that the 0x200. If the value 0x200 is written, it will set the 0x100-sized shared buffer. The physical address of the buffer is written to 0xE0000010 and then command 0x0 is written.

Command 1

This command is called by a subroutine of SceSblSmsched#sceSblSmSchedStopForTZS or SceSblSmsched module_start (if an error happened while SceSblSmsched was initializing). This command seems to be used to ask Cmep to remove all allocated resources (like shared memory address, loaded Secure Module, etc), and probably power off or reset it.

Command 2

Load a Secure Module.

Offset Size Description
0x0 0x4 num_paddrs
0x4 0x4 paddr_list for Secure Module ELF
0x8 0x4 buf_0x40: some 0x40 buffer
0xC 0x4 ctx_0x4
0x10 0x4 ctx_0x8
0x14 0x4 ctx_0xC
0x1C 0x4 field_60: system version (2)
0x20 0x4 partition ID, ?Media Type?

Command 3

Load the previously suspended Secure Module.

Offset Size Description
0x0 0x4 num_paddrs
0x4 0x4 paddr_list for suspend buffer
0x8 0x4 buf_0x40: some 0x40 buffer
0xC 0x4 delayed_cmd

Command 4

Suspend the current Secure Module.

Offset Size Description
0x0 0x4 num_paddrs
0x4 0x4 paddr_list for suspend buffer
0x8 0x4 buf_0x40: some 0x40 buffer
0xC 0x4 delayed_cmd

Command 5

Kill the current Secure Module.

Command 6

Force stop? Called from sceSblSmSchedDeleteAll.

Command 7

Unused.

Command 8

Unused.

Command 9

Set a 0x80 sized shared buffer.

This seems like a SceKernelPARange.

Offset Size Description
0x0 0x4 PA
0x4 0x4 length

Command 10

Set the encrypted signed revoke list.

Offset Size Description
0x0 0x4 num_paddrs
0x4 0x4 paddr_list for signed revoke list

Command 11

Command 12

Command 13

Command 14

Command 15

Command 16

Interrupts

There are 4 interrupts that Cmep sends. There are only two interrupt handles, however.

  • cry2arm0: handles interrupt 200. This is notifications about current Secure Module status changes (loaded, unloaded, suspended, etc.)
  • cry2arm123: handles interrupts 201, 202, 203. This interrupt is sent once an Secure Module function has finished processing (see below).

Executing Secure Module functions

You can find an open source ARM TrustZone<->Cmep protocol implementation at https://github.com/xyzz/f00d. It allows calling Secure Modules commands with a maximum of control over the sent data, received data and timing.

When a Secure Module is loaded, you can execute functions it provides by writing into registers 0xE0000014, 0xE0000018, 0xE000001C the physical address of the request buffer OR'd with 1.

Once result is available, ARM will get an interrupt 201-203. Read status code from 0xE0000004 or 0xE0000008 or 0xE000000C and confirm you received it by writing it back to the same register.

Possible results:

  • 1: command executed successfully
  • 3: invalid function ID
  • 5: invalid function buffer physical address (e.g. trying to pass secure memory)
  • 9: SCE_SBL_ERROR_COMMON_EIO

Memory

Cmep has its own private 128kB memory from 0x00800000 to 0x00820000. Secure Kernel is loaded to 0x00800000. Secure Modules are typically loaded to 0x0080B000.

Secure Modules Task states

ARM TrustZone implements a scheduler for Secure Modules tasks. Normally, only one task can run on Cmep at a time. The external Secure Modules scheduler running on ARM allows to have multiple tasks at once. The following provides an explanation of various states the task can be in.

ID Description
1 Created / Suspended (Unloaded)
2 Running
3 Errored (Unloaded)
4 ? (Unloaded)
5 ? (Unloaded)
6 Start/resume requested
7 Suspending
8 ?
9 ?
10 ?
11 Suspend requested
12 ?

Related pages