https://switchbrew.org/w/api.php?action=feedcontributions&user=Q&feedformat=atom
Nintendo Switch Brew - User contributions [en]
2024-03-29T14:58:45Z
User contributions
MediaWiki 1.35.8
https://switchbrew.org/w/index.php?title=Memory_layout&diff=3466
Memory layout
2018-01-18T21:01:03Z
<p>Q: 3.0.0 kernel memory layout WIP</p>
<hr />
<div>= Userspace =<br />
The userspace virtual address space can be either 32 or 36 bits. [2.0.0+] introduced support for 38 bit address spaces.<br />
<br />
There are two regions randomized and enforced by the kernel, each one with upper bits random and 2MB-aligned:<br />
* ReservedHeapRegion, available from [[SVC#svcGetInfo]].<br />
* ReservedMapRegion, available from [[SVC#svcGetInfo]].<br />
* [2.0.0+] NewReservedMapRegion, available from [[SVC#svcGetInfo]].<br />
* [2.0.0+] TlsIoRegion, not available to userspace.<br />
<br />
The main binary is placed at an address that is provided to the kernel by Loader via [[SVC#svcCreateProcess]].<br />
<br />
Typically on 2.0.0+ systems, the main binary region has randomness in bits 37-21.<br />
<br />
For the stack mapping region, the userland randomizes a page-offset where to start inside the region. This adds some additional entropy.<br />
<br />
Binaries mapped by RO are mapped randomly everywhere in the entire address space. The base address for each NRO has all bits randomized and are 4K-aligned. This means that typically, on 2.0.0+ systems, bits 37-12 of the NRO base address are random.<br />
<br />
For all binaries(main area / NROs), the R-- section is always located immediately after R-X. The RW- section is always located immediately after the R-- section. Hence, there's no extra randomization / guard-pages for these sections.<br />
<br />
On version [[1.0.0]], the initial binaries loaded into memory by the kernel always have the upper 32-bits as all-zero, so there are 6 fewer bits of layout randomization. <br />
<br />
Binaries loaded within the main-binary-region are loaded into memory in the following order, immediately after each other, for the binaries which exist in [[ExeFS]]:<br />
* rtld<br />
* main<br />
* subsdk*<br />
* sdk<br />
<br />
== ASLR Implementation ==<br />
The kernel uses a MT19937 random number generator, seeded by a [[SMC#GetRandomBytes|smcGetRandomBytes]]<br />
=== 1.0.0 ===<br />
<br />
if (AddressSpaceType == 2) {<br />
BaseAddr = 0x80000000; // 64-bit<br />
RandomMax = 0x6400;<br />
}<br />
else {<br />
BaseAddr = 0x40000000; // 32-bit<br />
RandomMax = 0x200;<br />
}<br />
<br />
if (AddressSpaceType == 4) {<br />
MapRegionSize = 0;<br />
HeapRegionSize = 0x80000000;<br />
}<br />
else {<br />
MapRegionSize = 0x40000000;<br />
HeapRegionSize = 0x40000000;<br />
}<br />
<br />
if (EnableAslr) {<br />
rnd0 = GetRandomRange(0, RandomMax) << 21;<br />
rnd1 = GetRandomRange(0, RandomMax) << 21;<br />
}<br />
else {<br />
rnd0 = rnd1 = 0;<br />
}<br />
<br />
this->MapBaseAddr = BaseAddr + min(rnd0, rnd1)<br />
this->HeapRegionBaseAddr = this->MapBaseAddr + MapRegionSize + max(rnd0, rnd1) - min(rnd0, rnd1)<br />
<br />
= Kernel =<br />
For more details, see [[#Notes]]. Here comes a summary.<br />
<br />
PXN bit is set in the MMU descriptor for userland code pages. This means that userland code pages are not executable in kernel mode (this is equivalent to SMEP on x86).<br />
<br />
For userland pages, the kernel has same access as userland (either both are read-only or both are read-write). It does not have SMAP. The previous rule has one exception: pages that are mapped unreadable in usermode are still forced readable from kernelmode.<br />
<br />
As of [[2.0.0]] KASLR is not used.<br />
<br />
== 1.0.0 ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Virtual || Physical || Size || Attributes || Permissions || Description<br />
|-<br />
| 0xFFFFFFFFBFC00000-0xFFFFFFFFBFC45FFF || 0x800A0000 || 0x46000 || 0x78B || R-X || Kernel .text<br />
|-<br />
| 0xFFFFFFFFBFC46000-0xFFFFFFFFBFC48FFF || 0x800E6000 || 0x3000 || 0x6000000000078B || R-- || Kernel .rodata<br />
|-<br />
| 0xFFFFFFFFBFC49000-0xFFFFFFFFBFC4FFFF || 0x800E9000 || 0x7000 || 0x6000000000070B || RW- || Kernel .data+.bss<br />
|-<br />
| 0xFFFFFFFFBFD72000-0xFFFFFFFFBFD72FFF || 0x6000F000 || 0x1000 || 0x60000000000607 || RW- || Exception vectors<br />
|-<br />
| 0xFFFFFFFFBFDB5000-0xFFFFFFFFBFDB5FFF || 0x60007000 || 0x1000 || 0x60000000000607 || RW- || Flow controller<br />
|-<br />
| 0xFFFFFFFFBFDB7000-0xFFFFFFFFBFDB7FFF || 0x60004000 || 0x1000 || 0x60000000000607 || RW- || Primary ICTLR<br />
|-<br />
| 0xFFFFFFFFBFDB9000-0xFFFFFFFFBFDB9FFF || 0x60001000 || 0x1000 || 0x60000000000607 || RW- || Resource Semaphore<br />
|-<br />
| 0xFFFFFFFFBFDBB000-0xFFFFFFFFBFDBBFFF || 0x70016000 || 0x2000 || 0x60000000000607 || RW- || ATOMICS<br />
|-<br />
| 0xFFFFFFFFBFDBE000-0xFFFFFFFFBFDBEFFF || 0x7000E000 || 0x1000 || 0x60000000000607 || RW- || PMC<br />
|-<br />
| 0xFFFFFFFFBFDC0000-0xFFFFFFFFBFDC0FFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || Clock and reset<br />
|-<br />
| 0xFFFFFFFFBFDC2000-0xFFFFFFFFBFDC2FFF || 0x7001D000 || 0x1000 || 0x60000000000607 || RW- || MC1<br />
|-<br />
| 0xFFFFFFFFBFDC4000-0xFFFFFFFFBFDC4FFF || 0x7001C000 || 0x1000 || 0x60000000000607 || RW- || MC0<br />
|-<br />
| 0xFFFFFFFFBFDC6000-0xFFFFFFFFBFDC6FFF || 0x70019000 || 0x1000 || 0x60000000000607 || RW- || MC<br />
|-<br />
| 0xFFFFFFFFBFDC8000-0xFFFFFFFFBFDC8FFF || 0x70006000 || 0x1000 || 0x60000000000607 || RW- || UART-A<br />
|-<br />
| 0xFFFFFFFFBFDCA000-0xFFFFFFFFBFDCBFFF || 0x80060000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| 0xFFFFFFFFBFDCE000-0xFFFFFFFFBFDCFFFF || 0x80068000 || 0x2000 || 0x6000000000070B || RW- || Kernel main stack (cpu0)<br />
|-<br />
| 0xFFFFFFFFBFDD2000-0xFFFFFFFFBFDD2FFF || 0x80070000 || 0x1000 || 0x6000000000070B || RW- || Kernel runner stack (cpu0)<br />
|-<br />
| 0xFFFFFFFFBFDD4000-0xFFFFFFFFBFDD5FFF || 0x80062000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| 0xFFFFFFFFBFDD8000-0xFFFFFFFFBFDD9FFF || 0x8006A000 || 0x2000 || 0x6000000000070B || RW- || Kernel main stack (cpu1)<br />
|-<br />
| 0xFFFFFFFFBFDDC000-0xFFFFFFFFBFDDCFFF || 0x80071000 || 0x1000 || 0x6000000000070B || RW- || Kernel runner stack (cpu1)<br />
|-<br />
| 0xFFFFFFFFBFDDE000-0xFFFFFFFFBFDDFFFF || 0x80064000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| 0xFFFFFFFFBFDE2000-0xFFFFFFFFBFDE3FFF || 0x8006C000 || 0x2000 || 0x6000000000070B || RW- || Kernel main stack (cpu2)<br />
|-<br />
| 0xFFFFFFFFBFDE6000-0xFFFFFFFFBFDE6FFF || 0x80072000 || 0x1000 || 0x6000000000070B || RW- || Kernel runner stack (cpu2)<br />
|-<br />
| 0xFFFFFFFFBFDE8000-0xFFFFFFFFBFDE9FFF || 0x80066000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| 0xFFFFFFFFBFDEC000-0xFFFFFFFFBFDEDFFF || 0x8006E000 || 0x2000 || 0x6000000000070B || RW- || Kernel main stack (cpu3)<br />
|-<br />
| 0xFFFFFFFFBFDF0000-0xFFFFFFFFBFDF0FFF || 0x80073000 || 0x1000 || 0x6000000000070B || RW- || Kernel runner stack (cpu3)<br />
|-<br />
| 0xFFFFFFFFBFDFB000-0xFFFFFFFFBFDFBFFF || 0x50041000 || 0x1000 || 0x60000000000607 || RW- || ARM Interrupt Distributor<br />
|-<br />
| 0xFFFFFFFFBFDFD000-0xFFFFFFFFBFDFDFFF || 0x50042000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Controller Physical CPU interface<br />
|-<br />
| 0xFFFFFFFFBFDF2000-0xFFFFFFFFBFDF3FFF || 0x80060000+(cpuid*0x2000) || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| 0xFFFFFFFFBFDF6000-0xFFFFFFFFBFDF7FFF || 0x80068000+(cpuid*0x2000) || 0x2000 || 0x6000000000070B || RW- || Kernel main stack (per-core self-mirror)<br />
|-<br />
| 0xFFFFFFFFBFDFF000-0xFFFFFFFFBFDFFFFF || 0x80084000+(cpuid*0x1000) || 0x1000 || 0x6000000000070B || RW- || Kernel runner stack (per-core self-mirror)<br />
|-<br />
| 0xFFFFFFFE00000000-... || 0x80000000 || ... || 0x60000000000709 || RW- || Raw DRAM access<br />
|}<br />
<br />
== 2.0.0 ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Cores || Virtual || Physical || Size || Attributes || Permissions || Description<br />
|-<br />
| All || 0xFFFFFFF7FFC00000-0xFFFFFFF7FFC62FFF || 0x800A0000 || 0x63000 || 0x78B || R-X || [2.0.0] Kernel .text<br />
|-<br />
| All || 0xFFFFFFF7FFC00000-0xFFFFFFF7FFC62FFF || 0x800A0000 || 0x4B000 || 0x78B || R-X || [3.0.0] Kernel .text<br />
|-<br />
| All || 0xFFFFFFF7FFC63000-0xFFFFFFF7FFC65FFF || 0x80103000 || 0x3000 || 0x6000000000078B || R-- || [2.0.0] Kernel .rodata<br />
|-<br />
| All || 0xFFFFFFF7FFC4B000-0xFFFFFFF7FFC4DFFF || 0x800EB000 || 0x3000 || 0x6000000000078B || R-- || [3.0.0] Kernel .rodata<br />
|-<br />
| All || 0xFFFFFFF7FFC66000-0xFFFFFFF7FFC6EFFF || 0x80106000 || 0x9000 || 0x6000000000070B || RW- || [2.0.0] Kernel .data+.bss<br />
|-<br />
| All || 0xFFFFFFF7FFC4E000-0xFFFFFFF7FFC5AFFF || 0x800EE000 || 0xD000 || 0x6000000000070B || RW- || [3.0.0] Kernel .data+.bss<br />
|-<br />
| All || 0xFFFFFFF7FFDC0000-0xFFFFFFF7FFDC0FFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || Clock and Reset<br />
|-<br />
| All || 0xFFFFFFF7FFDC0000-0xFFFFFFF7FFDC0FFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || Clock and Reset<br />
|-<br />
| All || 0xFFFFFFF7FFDC2000-0xFFFFFFF7FFDC2FFF || 0x7001D000 || 0x1000 || 0x60000000000607 || RW- || MC1<br />
|-<br />
| All || 0xFFFFFFF7FFDC4000-0xFFFFFFF7FFDC4FFF || 0x7001C000 || 0x1000 || 0x60000000000607 || RW- || MC0<br />
|-<br />
| All || 0xFFFFFFF7FFDC6000-0xFFFFFFF7FFDC6FFF || 0x70019000 || 0x1000 || 0x60000000000607 || RW- || MC<br />
|-<br />
| All || 0xFFFFFFF7FFDC8000-0xFFFFFFF7FFDC8FFF || 0x70006000 || 0x1000 || 0x60000000000607 || RW- || UART-A<br />
|-<br />
| All || 0xFFFFFFF7FFDCA000-0xFFFFFFF7FFDCAFFF || 0x80060000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDCE000-0xFFFFFFF7FFDCEFFF || 0x80068000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDD2000-0xFFFFFFF7FFDD2FFF || 0x80070000 || 0x1000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDD4000-0xFFFFFFF7FFDD4FFF || 0x80062000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDD8000-0xFFFFFFF7FFDD8FFF || 0x8006A000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDDC000-0xFFFFFFF7FFDDCFFF || 0x80071000 || 0x1000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDDE000-0xFFFFFFF7FFDDEFFF || 0x80064000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDE2000-0xFFFFFFF7FFDE2FFF || 0x8006C000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDE6000-0xFFFFFFF7FFDE6FFF || 0x80072000 || 0x1000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDE8000-0xFFFFFFF7FFDE8FFF || 0x80066000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDEC000-0xFFFFFFF7FFDECFFF || 0x8006E000 || 0x2000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDF0000-0xFFFFFFF7FFDF0FFF || 0x80073000 || 0x1000 || 0x6000000000070B || RW- ||<br />
|-<br />
| All || 0xFFFFFFF7FFDFB000-0xFFFFFFF7FFDFBFFF || 0x50041000 || 0x1000 || 0x60000000000607 || RW- || ARM Interrupt Distributor<br />
|-<br />
| All || 0xFFFFFFF7FFDFD000-0xFFFFFFF7FFDFDFFF || 0x50042000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Controller Physical CPU interface<br />
|-<br />
| All || 0xFFFFFFF800000000-... || 0x80000000 || ... || 0x60000000000709 || RW- || Raw DRAM access<br />
|}<br />
<br />
== 3.0.0 ==<br />
{| class="wikitable" border="1"<br />
|-<br />
! Cores || Virtual || Physical || Size || Attributes || Permissions || Description<br />
|-<br />
| All || 0xFFFFFFF7FFDAC000-0xFFFFFFF7FFDACFFF || 0x60006000 || 0x1000 || 0x60000000000607 || RW- || Clock and Reset<br />
|-<br />
| All || 0xFFFFFFF7FFDAE000-0xFFFFFFF7FFDAEFFF || 0x7001D000 || 0x1000 || 0x60000000000607 || RW- || MC1<br />
|-<br />
| All || 0xFFFFFFF7FFDB0000-0xFFFFFFF7FFDB0FFF || 0x7001C000 || 0x1000 || 0x60000000000607 || RW- || MC0<br />
|-<br />
| All || 0xFFFFFFF7FFDB2000-0xFFFFFFF7FFDB2FFF || 0x70019000 || 0x1000 || 0x60000000000607 || RW- || MC<br />
|-<br />
| All || 0xFFFFFFF7FFDB4000-0xFFFFFFF7FFDB4FFF || 0x70006000 || 0x1000 || 0x60000000000607 || RW- || UART-A<br />
|-<br />
| All || 0xFFFFFFF7FFDFB000-0xFFFFFFF7FFDFBFFF || 0x50041000 || 0x1000 || 0x60000000000607 || RW- || ARM Interrupt Distributor<br />
|-<br />
| All || 0xFFFFFFF7FFDFD000-0xFFFFFFF7FFDFDFFF || 0x50042000 || 0x1000 || 0x60000000000607 || RW- || Interrupt Controller Physical CPU interface<br />
|}<br />
<br />
<br />
The rest are are mapped to core-specific physaddrs, each one is 0x1000-bytes. Descriptor ORR-value = 0x6000000000070B.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Vmem<br />
! Physmem<br />
|-<br />
| 0xFFFFFFF7FFDF7000<br />
| <physaddr from vmem 0xFFFFFFF7FFDF6000> + 0x1000<br />
|-<br />
| 0xFFFFFFF7FFDF3000<br />
| <physaddr from vmem 0xFFFFFFF7FFDF2000> + 0x1000<br />
|-<br />
| 0xFFFFFFF7FFDF6000<br />
| 0x800XX000<br />
|-<br />
| 0xFFFFFFF7FFDF2000<br />
| 0x800XX000<br />
|-<br />
| 0xFFFFFFF7FFDFF000<br />
| 0x800XX000<br />
|-<br />
| 0xFFFFFFF7FFDF9000<br />
| 0x800XX000<br />
|}<br />
<br />
= Secure Monitor =<br />
<br />
== [[1.0.0]] ==<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Vmem<br />
! Physmem<br />
! Size<br />
! Descriptor ORR-value<br />
! Permissions<br />
! Description<br />
|-<br />
| 0x1F0000000<br />
| 0x50041000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| ARM Interrupt Distributor<br />
|-<br />
| 0x1F0002000<br />
| 0x50042000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| Interrupt Controller Physical CPU Interface<br />
|-<br />
| 0x1F0005000<br />
| 0x70006000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| UART-A<br />
|-<br />
| 0x1F0007000<br />
| 0x60006000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| Clock and Reset<br />
|-<br />
| 0x1F0009000<br />
| 0x7000E000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| RTC<br />
|-<br />
| 0x1F000B000<br />
| 0x60005000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TMR<br />
|-<br />
| 0x1F000D000<br />
| 0x6000C000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| System Registers<br />
|-<br />
| 0x1F000F000<br />
| 0x70012000<br />
| 0x2000<br />
| 0x40000000000304<br />
| <br />
| SE<br />
|-<br />
| 0x1F0012000<br />
| 0x700F0000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| SYSCTR0<br />
|-<br />
| 0x1F0014000<br />
| 0x70019000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| MC<br />
|-<br />
| 0x1F0016000<br />
| 0x7000F000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| FUSE<br />
|-<br />
| 0x1F0018000<br />
| 0x70000000<br />
| 0x4000<br />
| 0x40000000000304<br />
| <br />
| MISC<br />
|-<br />
| 0x1F001D000<br />
| 0x60007000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| Flow controller<br />
|-<br />
| 0x1F001F000<br />
| 0x40002000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| IRAM<br />
|-<br />
| 0x1F0021000<br />
| 0x7000D000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| I2C-5<br />
|-<br />
| 0x1F0023000<br />
| 0x6000D000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| GPIO-1<br />
|-<br />
| 0x1F0025000<br />
| 0x7000C000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| I2C<br />
|-<br />
| 0x1F0180000<br />
| 0x40020000<br />
| 0x10000<br />
| 0x40000000000324<br />
| <br />
| IRAM<br />
|-<br />
| 0x1F01A0000<br />
| 0x7C010000<br />
| 0x10000<br />
| 0x40000000000384<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01C3000<br />
| 0x80010000<br />
| 0x10000<br />
| 0x40000000000324<br />
| <br />
| EMEM<br />
|-<br />
| 0x1F01C2000<br />
| 0x8000F000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| EMEM<br />
|-<br />
| 0x1F01E0000<br />
| 0x7C013000<br />
| 0xB000<br />
| 0x304<br />
| <br />
| TZRAM (TrustZone .text)<br />
|-<br />
| 0x1F01F0000<br />
| 0x7C01E000<br />
| 0x2000<br />
| 0x304<br />
| <br />
| TZRAM (Armv8Boot .text)<br />
|-<br />
| 0x1F01F6000<br />
| 0x7C01E000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01F8000<br />
| 0x7C01F000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01FA000<br />
| 0x7C010000<br />
| 0x1000<br />
| 0x304<br />
| <br />
| TZRAM (Exception vectors)<br />
|-<br />
| 0x1F01FC000<br />
| 0x7C011000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01FE000<br />
| 0x7C012000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TZRAM<br />
|}<br />
<br />
== [[2.0.0]] ==<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Vmem<br />
! Physmem<br />
! Size<br />
! Descriptor ORR-value<br />
! Permissions<br />
! Description<br />
|-<br />
| 0x7C010000<br />
| 0x7C010000<br />
| 0x10000<br />
| 0x300<br />
| <br />
| TZRAM<br />
|-<br />
| 0x40020000<br />
| 0x40020000<br />
| 0x20000<br />
| 0x300<br />
| <br />
| iRAM-C<br />
|-<br />
| 0x1F0080000<br />
| 0x50041000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| ARM Interrupt Distributor<br />
|-<br />
| 0x1F0082000<br />
| 0x50042000<br />
| 0x2000<br />
| 0x40000000000304<br />
| <br />
| Interrupt Controller Physical CPU interface<br />
|-<br />
| 0x1F0085000<br />
| 0x70006000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| UART-A<br />
|-<br />
| 0x1F0087000<br />
| 0x60006000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| Clock and Reset<br />
|-<br />
| 0x1F0089000<br />
| 0x7000E000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| RTC<br />
|-<br />
| 0x1F008B000<br />
| 0x60005000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| TMR<br />
|-<br />
| 0x1F008D000<br />
| 0x6000C000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| System Registers<br />
|-<br />
| 0x1F008F000<br />
| 0x70012000<br />
| 0x2000<br />
| 0x40000000000304<br />
| <br />
| SE<br />
|-<br />
| 0x1F0092000<br />
| 0x700F0000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| SYSCTR0<br />
|-<br />
| 0x1F0094000<br />
| 0x70019000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| MC<br />
|-<br />
| 0x1F0096000<br />
| 0x7000F000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| FUSE (0x7000F800)<br />
|-<br />
| 0x1F0098000<br />
| 0x70000000<br />
| 0x4000<br />
| 0x40000000000304<br />
| <br />
| MISC<br />
|-<br />
| 0x1F009D000<br />
| 0x60007000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| Flow Controller<br />
|-<br />
| 0x1F009F000<br />
| 0x40002000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| iRAM-A<br />
|-<br />
| 0x1F00A1000<br />
| 0x7000D000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| I2C5 - SPI 2B-6<br />
|-<br />
| 0x1F00A3000<br />
| 0x6000D000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| GPIO-1 - GPIO-8<br />
|-<br />
| 0x1F00A5000<br />
| 0x7000C000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| I2C-I2C4<br />
|-<br />
| 0x1F00A7000<br />
| 0x6000F000<br />
| 0x1000<br />
| 0x40000000000304<br />
| <br />
| Exception vectors<br />
|-<br />
| 0x1F0180000<br />
| 0x40020000<br />
| 0x10000<br />
| 0x40000000000324<br />
| <br />
| iRAM-C<br />
|-<br />
| 0x1F0190000<br />
| 0x40003000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| iRAM-A<br />
|-<br />
| 0x1F01A0000<br />
| 0x7C010000<br />
| 0x10000<br />
| 0x40000000000380<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01C3000<br />
| 0x80010000<br />
| 0x10000<br />
| 0x40000000000324<br />
| <br />
| EMEM<br />
|-<br />
| 0x1F01C2000<br />
| 0x8000F000<br />
| 0x1000<br />
| 0x40000000000324<br />
| <br />
| EMEM<br />
|-<br />
| 0x1F01E0000<br />
| 0x7C013000<br />
| 0xB000<br />
| 0x300<br />
| <br />
| TZRAM (Secure Monitor)<br />
|-<br />
| 0x1F01F0000<br />
| 0x7C01E000<br />
| 0x2000<br />
| 0x300<br />
| <br />
| TZRAM (Secure Monitor init)<br />
|-<br />
| 0x1F01F6000<br />
| 0x7C01E000<br />
| 0x1000<br />
| 0x40000000000300<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01F8000<br />
| 0x7C01F000<br />
| 0x1000<br />
| 0x40000000000300<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01FA000<br />
| 0x7C010000<br />
| 0x1000<br />
| 0x300<br />
| <br />
| TZRAM (Secure Monitor exception vectors)<br />
|-<br />
| 0x1F01FC000<br />
| 0x7C011000<br />
| 0x1000<br />
| 0x40000000000300<br />
| <br />
| TZRAM<br />
|-<br />
| 0x1F01FE000<br />
| 0x7C012000<br />
| 0x1000<br />
| 0x40000000000300<br />
| <br />
| TZRAM<br />
|}<br />
<br />
= Notes =<br />
== 2.0.0 ==<br />
Granule size for TTBR0*_EL1 is 4KB.<br />
TTBR0_EL1 vmem starts at vaddr 0x0.<br />
vmem end-addr for TTBR1_EL1 is 0xffffffffffffffff. vmem start-addr for TTBR1_EL1 is 0xFFFFFFF000000000.<br />
T0SZ = 31. Hence, bit-size of the TTBR0*_EL1 vmem region is 33. (0x0000000200000000)<br />
T1SZ = 28. Hence, bit-size of the TTBR1*_EL1 vmem region is 36. (0x0000001000000000)<br />
<br />
Note: ARM config for TTBR0 is presumably configured for userland later.<br />
<br />
See arm-doc for "Table D4-25 Translation table entry addresses when using the 4KB translation granule".<br />
<br />
See arm-doc for "Overview of VMSAv8-64 address translation using the 4KB translation granule".<br />
<br />
See arm-doc for "Table D4-11 TCR.TnSZ values and IA ranges, 4K granule with no concatenation of tables".<br />
Both TTBR*_EL1 use "Initial lookup level" 1. Therefore, the TTBR*_EL1 tables are level1.<br />
<br />
Due to T*SZ, Stage1/Stage2 translation for the initial table(level1) are the same, except Stage2 uses hard-coded T0SZ.<br />
Basically, the table is accessed as: ((u64*)tablebase)[<IA[y:30]>], where y = (37-T*SZ)+26. That is, starting at bit "y" ending(inclusive) at bit30. For TTBR0*_EL1, y = 32, while for TTBR1_EL1 y = 35.<br />
Hence, for TTBR0, index=((vaddr>>30) & 0x7), and for TTBR1, index=((vaddr>>30) & 0x3f).<br />
<br />
"Vector Base Address Register (EL1)" = 0xfffffff7ffc50800.<br />
<br />
The table for TTBR0 only contains the following:<br />
* Vmem 0x80000000 is mapped to physmem 0x80000000, using a size loaded from a register. This is only done when: "endaddr = 0x7fffffff + size; if(endaddr >= 0x80000001){...}"<br />
** The size is loaded from: "(u32 *0x70019050 & 0x3fff) << 20;"<br />
** The value written to the MMU-table descriptor is: "physaddr | val | 0x709;". val is 1<<52 when "tmp>>34" is non-zero and when "if((physaddr & 0x3c0000000) == 0)", otherwise val=0. tmp=size at the start and increased by 0xffffffffc0000000 each loop iteration. physaddr is increased by 0x40000000 each loop iteration.<br />
<br />
TTBR1:<br />
* vmem 0xFFFFFFF800000000 is mapped to physmem 0x80000000. Similar to above, except tmp=0 due to wrap-around, etc. This also has usermode/kernel XN enabled in the descriptor ORR-value. The chunksize used when increasing addr is 0xfffffff840000000, with another +=0x40000000 separate from the addr cmp for the loop.<br />
** "endaddr = 0x3fffffff + (<size from above> | 0xfffffff800000000); enaddr = (endaddr & 0xffffffffc0000000)-1; if(endaddr >= 0xfffffff800000001){<map mem>}"<br />
<br />
* Initializes level2 pagetable descriptor for vmem 0xFFFFFFF7C0000000. descriptor = 0x3 | physaddr. physaddr is core-specific.<br />
* Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFC00000. descriptor = 0x3 | physaddr. physaddr is core-specific.<br />
* The content of the pagetable for the following level3 mmutables are not initialized in the main mmutable-init func. descriptor = 0x8007c003(0x3 | <physaddr tablebase>). tablebase=0x8007c000.<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEE00000. physaddr = tablebase + (0x1<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF000000. physaddr = tablebase + (0x2<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF200000. physaddr = tablebase + (0x3<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FFA00000. physaddr = tablebase + (0x7<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FEC00000. physaddr = tablebase.<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF400000. physaddr = tablebase + (0x4<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF600000. physaddr = tablebase + (0x5<<12).<br />
** Initializes level3 pagetable descriptor for vmem 0xFFFFFFF7FF800000. physaddr = tablebase + (0x6<<12).</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3359
Package2
2018-01-02T06:52:37Z
<p>Q: </p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| [[#Public Keys|RSA-2048]] signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY with SHA256)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Section 0 offset<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Section 1 offset<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Section 2 offset<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Section 3 offset<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
The section offsets are relative to a base, which is typically 0x80000000 pointing to the base of DRAM.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
|-<br />
| [[4.1.0]]<br />
| 0x6<br />
| 0x7<br />
| <br />
|}<br />
<br />
= Public Keys =<br />
<br />
=== Exponent ===<br />
0x10001<br />
<br />
=== Retail Modulus ===<br />
8D 13 A7 77 6A E5 DC C0 3B 25 D0 58 E4 20 69 59<br />
55 4B AB 70 40 08 28 07 A8 A7 FD 0F 31 2E 11 FE<br />
47 A0 F9 9D DF 80 DB 86 5A 27 89 CD 97 6C 85 C5<br />
6C 39 7F 41 F2 FF 24 20 C3 95 A6 F7 9D 4A 45 74<br />
8B 5D 28 8A C6 99 35 68 85 A5 64 32 80 9F D3 48<br />
39 A2 1D 24 67 69 DF 75 AC 12 B5 BD C3 29 90 BE<br />
37 E4 A0 80 9A BE 36 BF 1F 2C AB 2B AD F5 97 32<br />
9A 42 9D 09 8B 08 F0 63 47 A3 E9 1B 36 D8 2D 8A<br />
D7 E1 54 11 95 E4 45 88 69 8A 2B 35 CE D0 A5 0B<br />
D5 5D AC DB AF 11 4D CA B8 1E E7 01 9E F4 46 A3<br />
8A 94 6D 76 BD 8A C8 3B D2 31 58 0C 79 A8 26 E9<br />
D1 79 9C CB D4 2B 6A 4F C6 CC CF 90 A7 B9 98 47<br />
FD FA 4C 6C 6F 81 87 3B CA B8 50 F6 3E 39 5D 4D<br />
97 3F 0F 35 39 53 FB FA CD AB A8 7A 62 9A 3F F2<br />
09 27 96 3F 07 9A 91 F7 16 BF C6 3A 82 5A 4B CF<br />
49 50 95 8C 55 80 7E 39 B1 48 05 1E 21 C7 24 4F<br />
<br />
=== Debug Modulus ===<br />
B3 65 54 FB 0A B0 1E 85 A7 F6 CF 91 8E BA 96 99<br />
0D 8B 91 69 2A EE 01 20 4F 34 5C 2C 4F 4E 37 C7<br />
F1 0B D4 CD A1 7F 93 F1 33 59 CE B1 E9 DD 26 E6<br />
F3 BB 77 87 46 7A D6 4E 47 4A D1 41 B7 79 4A 38<br />
06 6E CF 61 8F CD C1 40 0B FA 26 DC C0 34 51 83<br />
D9 3B 11 54 3B 96 27 32 9A 95 BE 1E 68 11 50 A0<br />
6B 10 A8 83 8B F5 FC BC 90 84 7A 5A 5C 43 52 E6<br />
C8 26 E9 FE 06 A0 8B 53 0F AF 1E C4 1C 0B CF 50<br />
1A A4 F3 5C FB F0 97 E4 DE 32 0A 9F E3 5A AA B7<br />
44 7F 5C 33 60 B9 0F 22 2D 33 2A E9 69 79 31 42<br />
8F E4 3A 13 8B E7 26 BD 08 87 6C A6 F2 73 F6 8E<br />
A7 F2 FE FB 6C 28 66 0D BD D7 EB 42 A8 78 E6 B8<br />
6B AE C7 A9 E2 40 6E 89 20 82 25 8E 3C 6A 60 D7<br />
F3 56 8E EC 8D 51 8A 63 3C 04 78 23 0E 90 0C B4<br />
E7 86 3B 4F 8E 13 09 47 32 0E 04 B8 4D 5B B0 46<br />
71 B0 5C F4 AD 63 4F C5 E2 AC 1E C4 33 96 09 7B</div>
Q
https://switchbrew.org/w/index.php?title=Cryptosystem&diff=3358
Cryptosystem
2018-01-02T00:58:21Z
<p>Q: Clarified unique properties</p>
<hr />
<div>== BootROM ==<br />
The bootrom initializes two keyslots in the hardware engine:<br />
<br />
* the SBK (Secure Boot Key) in keyslot 14<br />
* the SSK (Secure Storage Key) in keyslot 15.<br />
<br />
Reads from both of these keyslots are disabled by the bootROM.<br />
The SBK is stored in [[Fuses#FUSE_PRIVATE_KEY|FUSE_PRIVATE_KEY]], which are locked to read out only FFs after the bootrom finishes.<br />
<br />
SBK is '''unique''' per console, and not shared among consoles as originally believed.<br />
<br />
The SSK is derived on boot via the SBK, the 32-bit console-unique "Device Key", and hardware information stored in fuses.<br />
<br />
Pseudocode for the derivation is as follows:<br />
void generateSSK() {<br />
char keyBuffer[0x10]; // Used to store keydata<br />
uint hwInfoBuffer[4]; // Used to store info about hardware from fuses<br />
uint deviceKey = getDeviceKey(); // Reads 32-bit device key from FUSE_PRIVATE_KEY4.<br />
for (int i = 0; i < 4; i++) { // Keybuffer = deviceKey || deviceKey || deviceKey || deviceKey<br />
((uint *)keyBuffer)[i] = deviceKey;<br />
}<br />
<br />
encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, deviceKey || {...})<br />
<br />
// Set up Hardware info buffer<br />
uint vendor_code = *((uint *)0x7000FA00) & 0x0000000F; // FUSE_VENDOR_CODE<br />
uint fab_code = *((uint *)0x7000FA04) & 0x0000003F; // FUSE_FAB_CODE<br />
uint lot_code_0 = *((uint *)0x7000FA08) & 0xFFFFFFFF; // FUSE_LOT_CODE_0<br />
uint lot_code_1 = *((uint *)0x7000FA0C) & 0x0FFFFFFF; // FUSE_LOT_CODE_1<br />
uint wafer_id = *((uint *)0x7000FA10) & 0x0000003F; // FUSE_WAFER_ID<br />
uint x_coord = *((uint *)0x7000FA14) & 0x000001FF; // FUSE_X_COORDINATE<br />
uint y_coord = *((uint *)0x7000FA18) & 0x000001FF; // FUSE_Y_COORDINATE<br />
uint unk_hw_fuse = *((uint *)0x7000FA20) & 0x0000003F; // Unknown cached fuse.<br />
<br />
// HARDWARE_INFO_BUFFER = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID<br />
hwInfoBuffer[0] = (lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | unk_hw_fuse;<br />
hwInfoBuffer[1] = (lot_code_0 << 26) | (lot_code_1 >> 2);<br />
hwInfoBuffer[2] = (fab_code << 26) | (lot_code_0 >> 6);<br />
hwInfoBuffer[3] = vendor_code;<br />
<br />
for (int i = 0; i < 0x10; i++) { // keyBuffer = XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER)<br />
keyBuffer[i] ^= ((char *)hwInfoBuffer)[i];<br />
}<br />
<br />
encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER))<br />
<br />
setKeyslot(KEYSLOT_SSK, keyBuffer); // SSK = keyBuffer.<br />
}<br />
<br />
== Falcon coprocessor ==<br />
The falcon processor (TSEC) stores a special console-unique key (that will be referred to as the "tsec key").<br />
<br />
This is presumably stored in fuses that only microcode authenticated by NVidia has access to.<br />
<br />
The tsec key is the source of all per-console entropy, because SSK is not used on retail.<br />
<br />
== Package1 ==<br />
<br />
=== Key table during package1 ===<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Keyslot<br />
! Name<br />
! Set by<br />
! Per-console<br />
! Per-firmware<br />
|-<br />
| 11<br />
| Package1Key<br />
| [[Package1]]<br />
| No<br />
| Yes<br />
|-<br />
| 14<br />
| SecureBootKey<br />
| Bootrom<br />
| No<br />
| No<br />
|-<br />
| 15<br />
| SecureStorageKey<br />
| Bootrom<br />
| Yes<br />
| No<br />
|}<br />
<br />
=== [1.0.0-3.0.2] Key table after package1 ===<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Keyslot<br />
! Name<br />
! Set by<br />
! Per-console<br />
! Per-firmware<br />
|-<br />
| 12<br />
| MasterKey<br />
| [[Package1]]<br />
| No<br />
| Yes, on security updates<br />
|-<br />
| 13<br />
| PerConsoleKey<br />
| [[Package1]]<br />
| Yes<br />
| No<br />
|}<br />
<br />
=== [4.0.0]+ Key table after package1 ===<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Keyslot<br />
! Name<br />
! Set by<br />
! Per-console<br />
! Per-firmware<br />
|-<br />
| 12<br />
| MasterKey<br />
| [[Package1]]<br />
| No<br />
| Yes, on security updates<br />
|-<br />
| 13<br />
| PerConsoleKey_40<br />
| [[Package1]]<br />
| Yes<br />
| No<br />
|-<br />
| 14<br />
| MasterKey_40<br />
| [[Package1]]<br />
| No<br />
| Yes, on security updates<br />
|-<br />
| 15<br />
| PerConsoleKey<br />
| [[Package1]]<br />
| Yes<br />
| No<br />
|}<br />
<br />
<br />
<br />
=== Key generation ===<br />
Note: aes_unwrap(wrapped_key, wrap_key) is just another name for a single AES-128 block decryption.<br />
<br />
If bit0 of 0x7000FB94 is clear, it will initialize keys like this (probably used for internal development units only):<br />
// Final keys:<br />
package1_key /* slot11 */ = aes_unwrap(f5b1eadb.., sbk)<br />
master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x11 ? simpleseed_dev0 : simpleseed_dev1, aes_unwrap(5ff9c2d9.., sbk))<br />
per_console_key /* slot13 */ = aes_unwrap(4f025f0e..., aes_unwrap(6e4a9592.., ssk))<br />
<br />
[4.0.0+] Above method was removed.<br />
<br />
Normal key generation looks like this on 1.0.0/2.0.0:<br />
<br />
keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */)<br />
cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key)<br />
<br />
if aes_cmac(buf=keyblob+0x10, len=0xA0, cmac_key) != keyblob[0:0x10]:<br />
panic()<br />
<br />
aes_ctr_decrypt(buf=keyblob+0x20, len=0x90, iv=keyblob+0x10 key=keyblob_key)<br />
<br />
// Final keys:<br />
package1_key /* slot11 */ = keyblob[0x80:0x90]<br />
master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x4f ? normalseed_dev : normalseed_retail, keyblob+0x20)<br />
per_console_key /* slot13 */ = aes_unwrap(4f025f0e.., keyblob_key)<br />
<br />
.. and on 3.0.0, they moved keyslots around a little to generate the same per-console key as 1.0.0:<br />
<br />
old_keyblob_key /* slot10 */ = aes_unwrap(aes_unwrap(df206f59.., tsec_key /* slot13 */), sbk /* slot14 */)<br />
keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */)<br />
cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key)<br />
<br />
if aes_cmac(buf=keyblob+0x10, len=0xA0, cmac_key) != keyblob[0:0x10]:<br />
panic()<br />
<br />
aes_ctr_decrypt(buf=keyblob+0x20, len=0x90, iv=keyblob+0x10 key=keyblob_key)<br />
<br />
// Final keys:<br />
package1_key /* slot11 */ = keyblob[0x80:0x90]<br />
master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x4f ? normalseed_dev : normalseed_retail, keyblob+0x20)<br />
per_console_key /* slot13 */ = aes_unwrap(4f025f0e.., old_keyblob_key)<br />
<br />
.. and on 4.0.0 it was further moved around:<br />
<br />
old_keyblob_key /* slot15 */ = aes_unwrap(aes_unwrap(df206f59.., tsec_key /* slot13 */), sbk /* slot14 */)<br />
keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */)<br />
cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key)<br />
<br />
if aes_cmac(buf=keyblob+0x10, len=0xA0, cmac_key) != keyblob[0:0x10]:<br />
panic()<br />
<br />
aes_ctr_decrypt(buf=keyblob+0x20, len=0x90, iv=keyblob+0x10 key=keyblob_key)<br />
<br />
// Final keys:<br />
package1_key /* slot11 */ = keyblob[0x80:0x90]<br />
master_key /* slot12 */ = aes_unwrap(normalseed_retail, keyblob+0x20)<br />
new_master_key /* slot14 */ = aes_unwrap(2dc1f48d.., keyblob+0x20)<br />
new_per_console_key /* slot13 */ = aes_unwrap(0c9109db.., old_keyblob_key)<br />
per_console_key /* slot15 */ = aes_unwrap(4f025f0e.., old_keyblob_key)<br />
<br />
SBK and SSK keyslots are cleared after keys have been generated.<br />
<br />
See table above for which keys are console unique.<br />
<br />
The key used to verify a keyblob's MAC is not the keyblob key but a key derived from it; this is likely part of an attempt to mitigate side-channel attacks as the MAC is an alterable part of the keyblob.<br />
<br />
The bootloader only stores the hardcoded constants for the keyblob used in the current revision. Nintendo are withholding all the future hardcoded constants.<br />
<br />
This means that if you have an attack on the bootloader, you need to re-preform it every time they move to a new keyblob.<br />
<br />
Dumping the SBK and TSEC key of any single system should be enough to derive all key material on the system.<br />
<br />
The key-derivation is described in more detail [[Package1#Key_generation|here]].<br />
<br />
==== Keyblob ====<br />
The keyblob is console unique, and changes with every bootloader update.<br />
<br />
==== Seeds ====<br />
normalseed_retail = d8a2410a...<br />
<br />
[1.0.0] wrapped_keyblob_key = df206f59...<br />
[1.0.0] simpleseed_dev0 = aff11423...<br />
[1.0.0] simpleseed_dev1 = 5e177ee1...<br />
[1.0.0] normalseed_dev = 0542a0fd...<br />
<br />
[3.0.0] wrapped_keyblob_key = 0c25615d... <br />
[3.0.0] simpleseed_dev0 = de00216a...<br />
[3.0.0] simpleseed_dev1 = 2db7c0a1...<br />
[3.0.0] normalseed_dev = 678c5a03...<br />
<br />
[3.0.1] wrapped_keyblob_key = 337685ee... <br />
[3.0.1] simpleseed_dev0 = e045f5ba...<br />
[3.0.1] simpleseed_dev1 = 84d92e0d...<br />
[3.0.1] normalseed_dev = cd88155b...<br />
<br />
[4.0.0] wrapped_keyblob_key = 2d1f4880...<br />
<br />
==== Table of used keyblobs ====<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Used keyblob<br />
! Used master static key encryption key in keyblob<br />
|-<br />
| 1.0.0-2.3.0<br />
| 1<br />
| 1<br />
|-<br />
| 3.0.0<br />
| 2<br />
| 1<br />
|-<br />
| 3.0.1-3.0.2<br />
| 3<br />
| 1<br />
|-<br />
| 4.0.0<br />
| 4<br />
| 1<br />
|}<br />
<br />
== Bootloader stage 1 ==<br />
It is currently unknown what key generation the stage 2 bootloader does.<br />
<br />
== Secure Monitor ==<br />
The secure monitor performs some runtime cryptographic operations. See [[SMC]] for what operations it provides.</div>
Q
https://switchbrew.org/w/index.php?title=User:Q&diff=3355
User:Q
2018-01-01T21:58:56Z
<p>Q: Created blank page</p>
<hr />
<div></div>
Q
https://switchbrew.org/w/index.php?title=Talk:Package2&diff=3354
Talk:Package2
2018-01-01T21:54:58Z
<p>Q: Created page with "Not sure if the RSA public keys have changed over Package1 revisions. Currently working with a 4.1.0 copy, and don't have earlier copies. If anyone could confirm that would be..."</p>
<hr />
<div>Not sure if the RSA public keys have changed over Package1 revisions. Currently working with a 4.1.0 copy, and don't have earlier copies. If anyone could confirm that would be great. -[[User:Q]]</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3353
Package2
2018-01-01T21:38:29Z
<p>Q: Added pub key anchor ref</p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| [[#Public Keys|RSA-2048]] signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY with SHA256)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
|-<br />
| [[4.1.0]]<br />
| 0x6<br />
| 0x7<br />
| <br />
|}<br />
<br />
= Public Keys =<br />
<br />
== Exponent ==<br />
10001<br />
<br />
== 4.1.0 ==<br />
<br />
=== Retail Modulus ===<br />
8D 13 A7 77 6A E5 DC C0 3B 25 D0 58 E4 20 69 59<br />
55 4B AB 70 40 08 28 07 A8 A7 FD 0F 31 2E 11 FE<br />
47 A0 F9 9D DF 80 DB 86 5A 27 89 CD 97 6C 85 C5<br />
6C 39 7F 41 F2 FF 24 20 C3 95 A6 F7 9D 4A 45 74<br />
8B 5D 28 8A C6 99 35 68 85 A5 64 32 80 9F D3 48<br />
39 A2 1D 24 67 69 DF 75 AC 12 B5 BD C3 29 90 BE<br />
37 E4 A0 80 9A BE 36 BF 1F 2C AB 2B AD F5 97 32<br />
9A 42 9D 09 8B 08 F0 63 47 A3 E9 1B 36 D8 2D 8A<br />
D7 E1 54 11 95 E4 45 88 69 8A 2B 35 CE D0 A5 0B<br />
D5 5D AC DB AF 11 4D CA B8 1E E7 01 9E F4 46 A3<br />
8A 94 6D 76 BD 8A C8 3B D2 31 58 0C 79 A8 26 E9<br />
D1 79 9C CB D4 2B 6A 4F C6 CC CF 90 A7 B9 98 47<br />
FD FA 4C 6C 6F 81 87 3B CA B8 50 F6 3E 39 5D 4D<br />
97 3F 0F 35 39 53 FB FA CD AB A8 7A 62 9A 3F F2<br />
09 27 96 3F 07 9A 91 F7 16 BF C6 3A 82 5A 4B CF<br />
49 50 95 8C 55 80 7E 39 B1 48 05 1E 21 C7 24 4F<br />
<br />
=== Debug Modulus ===<br />
B3 65 54 FB 0A B0 1E 85 A7 F6 CF 91 8E BA 96 99<br />
0D 8B 91 69 2A EE 01 20 4F 34 5C 2C 4F 4E 37 C7<br />
F1 0B D4 CD A1 7F 93 F1 33 59 CE B1 E9 DD 26 E6<br />
F3 BB 77 87 46 7A D6 4E 47 4A D1 41 B7 79 4A 38<br />
06 6E CF 61 8F CD C1 40 0B FA 26 DC C0 34 51 83<br />
D9 3B 11 54 3B 96 27 32 9A 95 BE 1E 68 11 50 A0<br />
6B 10 A8 83 8B F5 FC BC 90 84 7A 5A 5C 43 52 E6<br />
C8 26 E9 FE 06 A0 8B 53 0F AF 1E C4 1C 0B CF 50<br />
1A A4 F3 5C FB F0 97 E4 DE 32 0A 9F E3 5A AA B7<br />
44 7F 5C 33 60 B9 0F 22 2D 33 2A E9 69 79 31 42<br />
8F E4 3A 13 8B E7 26 BD 08 87 6C A6 F2 73 F6 8E<br />
A7 F2 FE FB 6C 28 66 0D BD D7 EB 42 A8 78 E6 B8<br />
6B AE C7 A9 E2 40 6E 89 20 82 25 8E 3C 6A 60 D7<br />
F3 56 8E EC 8D 51 8A 63 3C 04 78 23 0E 90 0C B4<br />
E7 86 3B 4F 8E 13 09 47 32 0E 04 B8 4D 5B B0 46<br />
71 B0 5C F4 AD 63 4F C5 E2 AC 1E C4 33 96 09 7B</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3352
Package2
2018-01-01T21:34:26Z
<p>Q: </p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| RSA-2048 signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY with SHA256)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
|-<br />
| [[4.1.0]]<br />
| 0x6<br />
| 0x7<br />
| <br />
|}<br />
<br />
= Public Keys =<br />
<br />
== Exponent ==<br />
10001<br />
<br />
== 4.1.0 ==<br />
<br />
=== Retail Modulus ===<br />
8D 13 A7 77 6A E5 DC C0 3B 25 D0 58 E4 20 69 59<br />
55 4B AB 70 40 08 28 07 A8 A7 FD 0F 31 2E 11 FE<br />
47 A0 F9 9D DF 80 DB 86 5A 27 89 CD 97 6C 85 C5<br />
6C 39 7F 41 F2 FF 24 20 C3 95 A6 F7 9D 4A 45 74<br />
8B 5D 28 8A C6 99 35 68 85 A5 64 32 80 9F D3 48<br />
39 A2 1D 24 67 69 DF 75 AC 12 B5 BD C3 29 90 BE<br />
37 E4 A0 80 9A BE 36 BF 1F 2C AB 2B AD F5 97 32<br />
9A 42 9D 09 8B 08 F0 63 47 A3 E9 1B 36 D8 2D 8A<br />
D7 E1 54 11 95 E4 45 88 69 8A 2B 35 CE D0 A5 0B<br />
D5 5D AC DB AF 11 4D CA B8 1E E7 01 9E F4 46 A3<br />
8A 94 6D 76 BD 8A C8 3B D2 31 58 0C 79 A8 26 E9<br />
D1 79 9C CB D4 2B 6A 4F C6 CC CF 90 A7 B9 98 47<br />
FD FA 4C 6C 6F 81 87 3B CA B8 50 F6 3E 39 5D 4D<br />
97 3F 0F 35 39 53 FB FA CD AB A8 7A 62 9A 3F F2<br />
09 27 96 3F 07 9A 91 F7 16 BF C6 3A 82 5A 4B CF<br />
49 50 95 8C 55 80 7E 39 B1 48 05 1E 21 C7 24 4F<br />
<br />
=== Debug Modulus ===<br />
B3 65 54 FB 0A B0 1E 85 A7 F6 CF 91 8E BA 96 99<br />
0D 8B 91 69 2A EE 01 20 4F 34 5C 2C 4F 4E 37 C7<br />
F1 0B D4 CD A1 7F 93 F1 33 59 CE B1 E9 DD 26 E6<br />
F3 BB 77 87 46 7A D6 4E 47 4A D1 41 B7 79 4A 38<br />
06 6E CF 61 8F CD C1 40 0B FA 26 DC C0 34 51 83<br />
D9 3B 11 54 3B 96 27 32 9A 95 BE 1E 68 11 50 A0<br />
6B 10 A8 83 8B F5 FC BC 90 84 7A 5A 5C 43 52 E6<br />
C8 26 E9 FE 06 A0 8B 53 0F AF 1E C4 1C 0B CF 50<br />
1A A4 F3 5C FB F0 97 E4 DE 32 0A 9F E3 5A AA B7<br />
44 7F 5C 33 60 B9 0F 22 2D 33 2A E9 69 79 31 42<br />
8F E4 3A 13 8B E7 26 BD 08 87 6C A6 F2 73 F6 8E<br />
A7 F2 FE FB 6C 28 66 0D BD D7 EB 42 A8 78 E6 B8<br />
6B AE C7 A9 E2 40 6E 89 20 82 25 8E 3C 6A 60 D7<br />
F3 56 8E EC 8D 51 8A 63 3C 04 78 23 0E 90 0C B4<br />
E7 86 3B 4F 8E 13 09 47 32 0E 04 B8 4D 5B B0 46<br />
71 B0 5C F4 AD 63 4F C5 E2 AC 1E C4 33 96 09 7B</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3351
Package2
2018-01-01T21:23:43Z
<p>Q: Added 4.1.0 min/max ver</p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| RSA-2048 signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY with SHA256)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
|-<br />
| [[4.1.0]]<br />
| 0x6<br />
| 0x7<br />
| <br />
|}</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3350
Package2
2018-01-01T21:04:27Z
<p>Q: Detailed RSA signature more</p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| RSA-2048 signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY with SHA256)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
| <br />
|}</div>
Q
https://switchbrew.org/w/index.php?title=Package2&diff=3339
Package2
2018-01-01T03:43:13Z
<p>Q: Detailed RSA verify</p>
<hr />
<div>Present in the firmware package titles (0100000000000819, 010000000000081A, 010000000000081B and 010000000000081C) and installed into eMMC storage's [[Flash_Filesystem#User_Partitions|BCPKG2 partitions]], "package2" contains the Switch kernel and the built-in system modules.<br />
<br />
= Format =<br />
Package2 is distributed in an already encrypted format. Therefore, it's not additionally encrypted when installed into the flash filesystem.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x100<br />
| RSA-2048 signature (PKCS#1 v2.1 RSASSA-PSS-VERIFY)<br />
|-<br />
| 0x100<br />
| 0x100<br />
| Encrypted header<br />
|-<br />
| 0x200<br />
| Variable<br />
| Encrypted body<br />
|}<br />
<br />
== Encryption ==<br />
Package2's contents are AES-CTR encrypted with a key known only by TrustZone.<br />
<br />
The encrypted header's CTR is stored as it's first 0x10 bytes (offset 0x100).<br />
The encrypted body is divided in up to 4 sections, each one with a CTR stored inside the decrypted header.<br />
<br />
== Header ==<br />
When decrypted, package2's header is as follows.<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Size<br />
! Description<br />
|-<br />
| 0x0<br />
| 0x10<br />
| Decrypted header's CTR<br />
|-<br />
| 0x10<br />
| 0x10<br />
| Section 0 CTR<br />
|-<br />
| 0x20<br />
| 0x10<br />
| Section 1 CTR<br />
|-<br />
| 0x30<br />
| 0x10<br />
| Section 2 CTR<br />
|-<br />
| 0x40<br />
| 0x10<br />
| Section 3 CTR<br />
|-<br />
| 0x50<br />
| 0x4<br />
| Magic "PK21"<br />
|-<br />
| 0x54<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x58<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x5C<br />
| 0x2<br />
| Version. HighByte must be <{maxver} and LowByte must be >{minver}, where {maxver} and {minver} are constants used by TZ updated with each package1 update.<br />
|-<br />
| 0x5E<br />
| 0x2<br />
| ?<br />
|-<br />
| 0x60<br />
| 0x4<br />
| Section 0 size<br />
|-<br />
| 0x64<br />
| 0x4<br />
| Section 1 size<br />
|-<br />
| 0x68<br />
| 0x4<br />
| Section 2 size<br />
|-<br />
| 0x6C<br />
| 0x4<br />
| Section 3 size<br />
|-<br />
| 0x70<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x74<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x78<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x7C<br />
| 0x4<br />
| Unknown<br />
|-<br />
| 0x80<br />
| 0x20<br />
| SHA-256 hash over encrypted section 0<br />
|-<br />
| 0xA0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 1<br />
|-<br />
| 0xC0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 2<br />
|-<br />
| 0xE0<br />
| 0x20<br />
| SHA-256 hash over encrypted section 3<br />
|}<br />
<br />
Each section follows each other immediately and is encrypted with the same key used for encrypting the header.<br />
<br />
== Section 0 ==<br />
When decrypted, this section contains the plaintext Switch kernel binary.<br />
<br />
== Section 1 ==<br />
When decrypted, this section contains the built-in system modules encapsulated in a custom format.<br />
<br />
=== INI1 ===<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "INI1"<br />
|-<br />
| 0x4<br />
| u32<br />
| Size<br />
|-<br />
| 0x8<br />
| u32<br />
| NumberProcesses<br />
|-<br />
| 0xC<br />
| u32<br />
| Zero<br />
|}<br />
<br />
==== KIP1 ====<br />
Kernel internal process?<br />
<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| Magic "KIP1"<br />
|-<br />
| 0x4<br />
| char[12]<br />
| Name<br />
|-<br />
| 0x10<br />
| u64<br />
| TitleId<br />
|-<br />
| 0x18<br />
| u32<br />
| <br />
|-<br />
| 0x1C<br />
| u32<br />
| Flags / etc. Byte3 bit0-2: compression-enable for each section, when set.<br />
|-<br />
| 0x20<br />
| [[#SectionHeader]][3]<br />
| Sections<br />
|-<br />
| 0x50<br />
| char[0x20]<br />
| Padding<br />
|-<br />
| 0x70<br />
| u64[0x20]<br />
| KernelCaps<br />
|}<br />
<br />
===== SectionHeader =====<br />
{| class="wikitable" border="1"<br />
|-<br />
! Offset<br />
! Type<br />
! Description<br />
|-<br />
| 0x0<br />
| u32<br />
| OutOffset<br />
|-<br />
| 0x4<br />
| u32<br />
| DecompressedSize<br />
|-<br />
| 0x8<br />
| u32<br />
| CompressedSize<br />
|-<br />
| 0xC<br />
| u32<br />
| <br />
|}<br />
<br />
===== Compression =====<br />
The compression used here is BLZ, with a modified footer since 3ds. The footer is now 0xC bytes instead of 0x8, and has the form u32 compressed_data_len; u32 initial_index; u32 additional_len_when_uncompressed;<br />
<br />
== Section 2 ==<br />
This section has a valid CTR and SHA-256 hash (over NULL) stored in the package2's header, but it's size is always 0. Likely reserved for future expansion.<br />
<br />
== Section 3 ==<br />
This section is not present (CTR and SHA-256 hash in package2's header are NULL). Likely reserved for future expansion.<br />
<br />
= Versions =<br />
{| class="wikitable" border="1"<br />
|-<br />
! System version<br />
! Package1 maxver constant<br />
! Package1 minver constant<br />
! Package2 version field<br />
|-<br />
| [[2.0.0]]<br />
| 0x3<br />
| 0x4<br />
| <br />
|}</div>
Q