TSEC: Difference between revisions
merging |
|||
Line 1: | Line 1: | ||
Like most Tegra based devices, the Switch's GPU also includes a Falcon microprocessor. | Like most Tegra based devices, the Switch's GPU also includes a Falcon microprocessor. | ||
TSEC is a NVIDIA Falcon microprocessor with crypto extensions. | |||
= Driver = | = Driver = | ||
A host driver for communicating with the Falcon is mapped to physical address 0x54500000 with a total size of 0x40000 bytes and exposes several registers. | A host driver for communicating with the TSEC/Falcon is mapped to physical address 0x54500000 with a total size of 0x40000 bytes and exposes several registers. | ||
== Registers == | == Registers == | ||
Line 285: | Line 286: | ||
return; | return; | ||
= Firmware = | = TSEC Firmware = | ||
The actual code loaded into | The actual code loaded into TSEC is assembled in NVIDIA's proprietary fuc5 ISA using crypto extensions. | ||
Stored inside the first bootloader, this firmware binary is split into 4 blobs: Stage0, Stage1, Stage2 and key data. | Stored inside the first bootloader, this firmware binary is split into 4 blobs: Stage0, Stage1, Stage2 and key data. | ||
Firmware can be disassembled with http:x//envytools.readthedocs.io/en/latest/" envytools' https:x//github.com/envytools/envytools/tree/master/envydis envydis: | |||
<code>envydis -i tsec_fw.bin -m falcon -V fuc5 -F crypt</code> | |||
Note that the instruction set has variable length instructions, and the disassembler is not very good at detecting locations it should start disassembling from. One needs to disassemble multiple sub-regions and join them together. | |||
== Stage 0 == | == Stage 0 == | ||
Line 613: | Line 620: | ||
== Key data == | == Key data == | ||
Small buffer stored after Stage 0's code and used across all stages. | Small buffer stored after Stage 0's code and used across all stages. | ||
== Notes == | |||
https:x//wiki.0x04.net/wiki/Marcin_Ko%C5%9Bcielnicki mwk shared additional info learned from RE of falcon processors over the years, which hasn't made it into envytools documentation yet: | |||
=== cxset === | |||
cxset instruction provides a way to change behavior of a variable amount of successively executed DMA-related instructions. | |||
for example: <code>000000de: f4 3c 02 cxset 0x2</code> | |||
can be read as: <code>dma_override(type=crypto_reg, count=2)</code> | |||
The argument to cxset specifies the type of behavior change in the top 3 bits, and the number of DMA-related instructions the effect lasts for in the lower 5 bits. | |||
==== Override Types ==== | |||
Unlisted values are unknown, but probably do something. | |||
{| class=wikitable | |||
! Value || Effect | |||
|- | |||
| 0b000 || falcon data mem <-> falcon $cX register | |||
|- | |||
| 0b001 || external mem <-> crypto input/output stream | |||
|} | |||
==== DMA-Related Instructions ==== | |||
At least the following instructions may have changed behavior, and count against the cxset "count" argument: <code>xdwait</code>, <code>xdst</code>, <code>xdld</code>. | |||
For example, if override type=0b000, then the "length" argument to <code>xdst</code> is instead treated as the index of the target $cX register. | |||
=== Register ACLs === | |||
Falcon tracks permission metadata about each crypto reg. Permissions include read/write ability per execution mode, as well as ability to use the reg for encrypt/decrypt, among other permissions. Permissions are propagated when registers are referenced by instructions (e.g. moving a value from read-protected $cX to $cY will result in $cY also being read-protected). | |||
=== Authenticated Mode Entry/Exit === | |||
Entry to Authenticated Mode always sets $pc to the address supplied in $cauth (ie the base of the signature-checked region). This takes effect when trying to branch to any address within the range covered by $cauth. | |||
Exit from Authenticated Mode must poke a special register (this seems to be I[0x10300] = 0) before leaving authenticated code pages. Failure to do this would result in the Falcon core halting. |