SLSK
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | 0x64B2C8E5 magic
|
0x4 | 0x4 | Offset to code |
0x8 | 0x4 | Size of plaintext version string, 0 on 0.931, 0x10 on other |
0xC | 0x4 | Size of unknown block, only seen as 0 |
0x10 | 0x4 | Code size |
0x14 | 0x2 | AES key revision, possible values 0 to 5 |
0x16 | 0x2 | Public key revision, possible values 0 to 15 |
0x18 | 0x8 | Unknown/zero |
0x20 | 0x20 | sha256 hash of decrypted body |
0x40 | 0x10 | Version in ASCII, not present on 0.931 |
0x50 (0x40 on 0.931) | 0x90 | Zero |
0xE0 (0xD0 on 0.931) | Until Data | Encrypted Header |
Encrypted Header
At offset 0xE0 there is a 0x1E0 sized buffer that is speculated to be an encrypted header. For any given firmware version, secure_kernel.enc/second_loader.enc and secure_kernel.enp/second_loader.enp share the first 0xC0 bytes. For non-retail PUPs, each SLSK share the first 0xC0 bytes as observed in 0.931, 0.995, 1.000.41. Similarly in retail PUPs, each SLSK also share the first 0xC0 bytes as observed in 1.05 and 3.60. However, the bytes differ from retail and non-retail SLSK.
There is likely a 0xC0 sized "common" header that is shared by every firmware and by both secure_kernel and second_loader but different between retail and non-retail builds. Then there is likely a 0x20 byte section that is unique per SLSK (maybe contains version, size, load offset, etc). Then a 0x100 byte RSA-2048 signature of the header.
Signature
The last 0x340 bytes of each SLSK is not personalized. For both secure_kernel and second_loader, both the enc and enp variants share the last 0x340 bytes (although they differ from each other and across firmwares). This is likely the signature and might also contain certificates.