Line 1: |
Line 1: |
− | == BootROM ==
| + | = BootROM = |
| The bootrom initializes two keyslots in the hardware engine: | | The bootrom initializes two keyslots in the hardware engine: |
| | | |
Line 8: |
Line 8: |
| The SBK is stored in [[Fuses#FUSE_PRIVATE_KEY|FUSE_PRIVATE_KEY]], which are locked to read out only FFs after the bootrom finishes. | | The SBK is stored in [[Fuses#FUSE_PRIVATE_KEY|FUSE_PRIVATE_KEY]], which are locked to read out only FFs after the bootrom finishes. |
| | | |
− | SBK should be shared amongst all consoles, but we don't know this is the case. | + | SBK is '''unique''' per console, and not shared among consoles as originally believed. |
| | | |
| The SSK is derived on boot via the SBK, the 32-bit console-unique "Device Key", and hardware information stored in fuses. | | The SSK is derived on boot via the SBK, the 32-bit console-unique "Device Key", and hardware information stored in fuses. |
Line 25: |
Line 25: |
| // Set up Hardware info buffer | | // Set up Hardware info buffer |
| uint vendor_code = *((uint *)0x7000FA00) & 0x0000000F; // FUSE_VENDOR_CODE | | uint vendor_code = *((uint *)0x7000FA00) & 0x0000000F; // FUSE_VENDOR_CODE |
− | uint fab_code = *((uint *)0x7000FA04) & 0x0000000F; // FUSE_FAB_CODE | + | uint fab_code = *((uint *)0x7000FA04) & 0x0000003F; // FUSE_FAB_CODE |
| uint lot_code_0 = *((uint *)0x7000FA08) & 0xFFFFFFFF; // FUSE_LOT_CODE_0 | | uint lot_code_0 = *((uint *)0x7000FA08) & 0xFFFFFFFF; // FUSE_LOT_CODE_0 |
| uint lot_code_1 = *((uint *)0x7000FA0C) & 0x0FFFFFFF; // FUSE_LOT_CODE_1 | | uint lot_code_1 = *((uint *)0x7000FA0C) & 0x0FFFFFFF; // FUSE_LOT_CODE_1 |
Line 48: |
Line 48: |
| } | | } |
| | | |
− | == Falcon coprocessor ==
| + | = Falcon coprocessor = |
− | The falcon processor (TSEC) stores a special console-unique key (that will be referred to as the "tsec key"). | + | The falcon processor (TSEC) generates a special console-unique key (that will be referred to as the "tsec key"). |
| | | |
− | This is presumably stored in fuses that only microcode authenticated by NVidia has access to. | + | This is presumably using data stored in fuses that only microcode authenticated by NVidia has access to. |
| | | |
− | The tsec key is the source of all per-console entropy, because SSK is not used on retail.
| + | = Package1ldr = |
| + | == Key table == |
| + | [1.0.0-3.0.2] During package1ldr: |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Keyslot |
| + | ! Name |
| + | ! Set by |
| + | ! Per-console |
| + | ! Per-firmware |
| + | |- |
| + | | 11 |
| + | | Package1Key |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | No |
| + | | Yes |
| + | |- |
| + | | 14 |
| + | | SecureBootKey |
| + | | Bootrom |
| + | | Yes |
| + | | No |
| + | |- |
| + | | 15 |
| + | | SecureStorageKey |
| + | | Bootrom |
| + | | Yes |
| + | | No |
| + | |} |
| | | |
− | == Package1 == | + | [1.0.0-3.0.2] After package1ldr: |
− | | + | {| class="wikitable" border="1" |
− | === Key generation ===
| + | |- |
| + | ! Keyslot |
| + | ! Name |
| + | ! Set by |
| + | ! Per-console |
| + | ! Per-firmware |
| + | |- |
| + | | 12 |
| + | | MasterKey |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | No |
| + | | Yes, on security updates |
| + | |- |
| + | | 13 |
| + | | PerConsoleKey |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | Yes |
| + | | No |
| + | |} |
| | | |
| + | [4.0.0+] After package1ldr (Secure Monitor boot): |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 64: |
Line 111: |
| ! Name | | ! Name |
| ! Set by | | ! Set by |
− | ! Cleared by
| |
| ! Per-console | | ! Per-console |
| ! Per-firmware | | ! Per-firmware |
| |- | | |- |
− | | 11 | + | | 12 |
− | | Package1Key | + | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
− | | [[Package1]] | |
| | No | | | No |
| + | | Yes, on security updates |
| + | |- |
| + | | 13 |
| + | | PerConsoleKeyForFirmwareSpecificPerConsoleKeyGen |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| + | | No |
| + | |- |
| + | | 14 |
| + | | StaticKeyForFirmwareSpecificPerConsoleKeyGen |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | No |
| + | | Yes, on security updates |
| + | |- |
| + | | 15 |
| + | | PerConsoleKey |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | Yes |
| + | | No |
| + | |} |
| + | |
| + | [4.0.0+] After package1ldr (Secure Monitor runtime): |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Keyslot |
| + | ! Name |
| + | ! Set by |
| + | ! Per-console |
| + | ! Per-firmware |
| |- | | |- |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
− | | Forever
| |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
| |- | | |- |
| | 13 | | | 13 |
| + | | FirmwareSpecificPerConsoleKey |
| + | | Secure Monitor init |
| + | | Yes |
| + | | Yes, on security updates |
| + | |- |
| + | | 15 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
− | | Forever | + | | Yes |
| + | | No |
| + | |} |
| + | |
| + | [6.2.0+] After package1ldr/TSEC Payload (Secure Monitor boot): |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Keyslot |
| + | ! Name |
| + | ! Set by |
| + | ! Per-console |
| + | ! Per-firmware |
| + | |- |
| + | | 12 |
| + | | TsecKey |
| + | | [[TSEC#Payload|Package1ldr TSEC Firmware]] |
| | Yes | | | Yes |
| | No | | | No |
| + | |- |
| + | | 13 |
| + | | TsecRootKey |
| + | | [[TSEC#Payload|Package1ldr TSEC Firmware]] |
| + | | No |
| + | | Unknown |
| |- | | |- |
| | 14 | | | 14 |
| | SecureBootKey | | | SecureBootKey |
| | Bootrom | | | Bootrom |
− | | [[Package1]] | + | | Yes |
− | | No
| |
| | No | | | No |
| |- | | |- |
Line 99: |
Line 197: |
| | SecureStorageKey | | | SecureStorageKey |
| | Bootrom | | | Bootrom |
− | | [[Package1]]
| |
| | Yes | | | Yes |
| | No | | | No |
| |} | | |} |
| | | |
| + | == Key generation == |
| Note: aes_unwrap(wrapped_key, wrap_key) is just another name for a single AES-128 block decryption. | | Note: aes_unwrap(wrapped_key, wrap_key) is just another name for a single AES-128 block decryption. |
| | | |
| If bit0 of 0x7000FB94 is clear, it will initialize keys like this (probably used for internal development units only): | | If bit0 of 0x7000FB94 is clear, it will initialize keys like this (probably used for internal development units only): |
| // Final keys: | | // Final keys: |
− | package1_key /* slot11 */ = aes_unwrap(f5baeadb.., sbk) | + | package1_key /* slot11 */ = aes_unwrap(f5b1eadb.., sbk) |
− | master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x11 ? aff11423.. : 5e177ee1.., aes_unwrap(5ff9c2d9.., sbk)) | + | master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x11 ? simpleseed_dev0 : simpleseed_dev1, aes_unwrap(5ff9c2d9.., sbk)) |
| per_console_key /* slot13 */ = aes_unwrap(4f025f0e..., aes_unwrap(6e4a9592.., ssk)) | | per_console_key /* slot13 */ = aes_unwrap(4f025f0e..., aes_unwrap(6e4a9592.., ssk)) |
| + | |
| + | [4.0.0+] Above method was removed. |
| | | |
| Normal key generation looks like this on 1.0.0/2.0.0: | | Normal key generation looks like this on 1.0.0/2.0.0: |
− | keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(df206f59.., tsec_key /* slot13 */, sbk /* slot14 */) | + | |
| + | keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */) |
| cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key) | | cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key) |
| | | |
Line 123: |
Line 224: |
| // Final keys: | | // Final keys: |
| package1_key /* slot11 */ = keyblob[0x80:0x90] | | package1_key /* slot11 */ = keyblob[0x80:0x90] |
− | master_key /* slot12 */ = aes_unwrap(is_debug ? 0542a0fd.. : d8a2410a.., keyblob+0x20) | + | master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x4f ? normalseed_dev : normalseed_retail, keyblob+0x20) |
| per_console_key /* slot13 */ = aes_unwrap(4f025f0e.., keyblob_key) | | per_console_key /* slot13 */ = aes_unwrap(4f025f0e.., keyblob_key) |
| + | |
| + | .. and on 3.0.0, they moved keyslots around a little to generate the same per-console key as 1.0.0: |
| + | |
| + | old_keyblob_key /* slot10 */ = aes_unwrap(aes_unwrap(df206f59.., tsec_key /* slot13 */), sbk /* slot14 */) |
| + | keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */) |
| + | cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key) |
| + | |
| + | if aes_cmac(buf=keyblob+0x10, len=0xA0, cmac_key) != keyblob[0:0x10]: |
| + | panic() |
| + | |
| + | aes_ctr_decrypt(buf=keyblob+0x20, len=0x90, iv=keyblob+0x10 key=keyblob_key) |
| + | |
| + | // Final keys: |
| + | package1_key /* slot11 */ = keyblob[0x80:0x90] |
| + | master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x4f ? normalseed_dev : normalseed_retail, keyblob+0x20) |
| + | per_console_key /* slot13 */ = aes_unwrap(4f025f0e.., old_keyblob_key) |
| + | |
| + | .. and on 4.0.0 it was further moved around: |
| + | |
| + | keyblob_key /* slot13 */ = aes_unwrap(aes_unwrap(wrapped_keyblob_key, tsec_key /* slot13 */), sbk /* slot14 */) |
| + | cmac_key /* slot11 */ = aes_unwrap(59c7fb6f.., keyblob_key) |
| + | |
| + | if aes_cmac(buf=keyblob+0x10, len=0xA0, cmac_key) != keyblob[0:0x10]: |
| + | panic() |
| + | |
| + | aes_ctr_decrypt(buf=keyblob+0x20, len=0x90, iv=keyblob+0x10 key=keyblob_key) |
| + | |
| + | // Final keys: |
| + | package1_key /* slot11 */ = keyblob[0x80:0x90] |
| + | master_key /* slot12 */ = aes_unwrap(normalseed_retail, keyblob+0x20) |
| + | new_master_key /* slot14 */ = aes_unwrap(2dc1f48d.., keyblob+0x20) |
| + | new_per_console_key /* slot13 */ = aes_unwrap(0c9109db.., old_keyblob_key) |
| + | per_console_key /* slot15 */ = aes_unwrap(4f025f0e.., old_keyblob_key) |
| + | |
| + | .. and on 6.2.0, they moved key generation out of package1ldr, and into the Secure Monitor's boot section: |
| + | |
| + | clear_keyslots_other_than_12_13_and_14() |
| + | |
| + | old_keyblob_key /* slot15 */ = aes_unwrap(aes_unwrap(df206f59.., tsec_key /* slot12 */), sbk /* slot14 */) |
| + | /* Previously, master_kek was stored at keyblob+0x20) */ |
| + | master_kek /* slot13 */ = aes_unwrap(374b7729.. /* probably firmware specific */, tsec_root_key /* slot13 */) |
| + | |
| + | clear_keyslot(12) |
| + | |
| + | // Final keys: |
| + | new_master_key /* slot12 */ = aes_unwrap(2dc1f48d.., master_kek) |
| + | master_key /* slot13 */ = aes_unwrap(normalseed_retail, master_kek) |
| + | new_per_console_key /* slot14 */ = aes_unwrap(0c9109db.., old_keyblob_key) |
| + | per_console_key /* slot15 */ = aes_unwrap(4f025f0e.., old_keyblob_key) |
| + | |
| | | |
| SBK and SSK keyslots are cleared after keys have been generated. | | SBK and SSK keyslots are cleared after keys have been generated. |
Line 136: |
Line 287: |
| 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. | | 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. |
| | | |
− | Dumping the SBK and TSEC key of any single system should be enough to derive all key material on the system. | + | Dumping the SBK and TSEC key of any single system should be enough to derive all key material on the system, prior to 6.2.0. |
| | | |
| The key-derivation is described in more detail [[Package1#Key_generation|here]]. | | The key-derivation is described in more detail [[Package1#Key_generation|here]]. |
| | | |
− | ==== Table of used keyblobs ==== | + | === Keyblob === |
| + | There are 32 keyblobs written to NAND at factory, with each keyblob encrypted with a console-unique key derived from the console's SBK, the console's tsec key, and a constant specific to each keyblob. |
| + | |
| + | Despite being encrypted with console unique keys, though, the decrypted keyblob contents are shared for all consoles. |
| + | |
| + | Used keyblobs are as follows: |
| | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
Line 158: |
Line 314: |
| | 3.0.1-3.0.2 | | | 3.0.1-3.0.2 |
| | 3 | | | 3 |
| + | | 1 |
| + | |- |
| + | | 4.0.0-4.1.0 |
| + | | 4 |
| + | | 1 |
| + | |- |
| + | | 5.0.0-5.1.0 |
| + | | 5 |
| + | | 1 |
| + | |- |
| + | | 6.0.0-6.1.0 |
| + | | 6 |
| | 1 | | | 1 |
| |} | | |} |
| | | |
− | == Bootloader stage 1 == | + | Starting from 6.2.0, key generation no longer uses keyblobs. |
− | It is currently unknown what key generation the stage 2 bootloader does.
| + | |
| + | === Seeds === |
| + | normalseed_retail = d8a2410a... |
| + | |
| + | [1.0.0] wrapped_keyblob_key = df206f59... |
| + | [1.0.0] simpleseed_dev0 = aff11423... |
| + | [1.0.0] simpleseed_dev1 = 5e177ee1... |
| + | [1.0.0] normalseed_dev = 0542a0fd... |
| + | |
| + | [3.0.0] wrapped_keyblob_key = 0c25615d... |
| + | [3.0.0] simpleseed_dev0 = de00216a... |
| + | [3.0.0] simpleseed_dev1 = 2db7c0a1... |
| + | [3.0.0] normalseed_dev = 678c5a03... |
| + | |
| + | [3.0.1] wrapped_keyblob_key = 337685ee... |
| + | [3.0.1] simpleseed_dev0 = e045f5ba... |
| + | [3.0.1] simpleseed_dev1 = 84d92e0d... |
| + | [3.0.1] normalseed_dev = cd88155b... |
| + | |
| + | [4.0.0] wrapped_keyblob_key = 2d1f4880... |
| + | |
| + | === Versions === |
| + | The key generation system has historically been revised several times. Each version is bound to a specific BCT public key and can be identified by its first byte as follows: |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Version |
| + | ! BCT public key's first byte |
| + | ! Description |
| + | |- |
| + | | K1 |
| + | | 0x11 |
| + | | Erista prototype development |
| + | |- |
| + | | K2 |
| + | | 0xFB |
| + | | Erista prototype development |
| + | |- |
| + | | K3 |
| + | | 0x4F |
| + | | Erista prototype development |
| + | |- |
| + | | K4 |
| + | | |
| + | | Erista prototype retail |
| + | |- |
| + | | K5 |
| + | | 0x37 |
| + | | Erista development |
| + | |- |
| + | | K6 |
| + | | 0xF7 |
| + | | Erista retail |
| + | |- |
| + | | M1 |
| + | | 0x19 |
| + | | Mariko prototype development |
| + | |- |
| + | | M2 |
| + | | 0xC3 |
| + | | Mariko development |
| + | |- |
| + | | M3 |
| + | | 0xDD |
| + | | Mariko prototype retail (pre-6.0.0) |
| + | |- |
| + | | M4 |
| + | | 0x9B |
| + | | Mariko retail |
| + | |} |
| + | |
| + | = Secure Monitor Init = |
| + | On all versions, the key to decrypt [[Package2]] is generated by decrypting a constant seed with the master key. The key is erased after use. |
| + | |
| + | Additionally, starting from 4.0.0, the Secure Monitor init will decrypt another constant seed successively with a special per console key and a special static key passed by package1loader, to generate the firmware specific per-console key. The operation will erase these special keys passed by package1loader. |
| | | |
− | == Secure Monitor ==
| + | = Secure Monitor = |
| The secure monitor performs some runtime cryptographic operations. See [[SMC]] for what operations it provides. | | The secure monitor performs some runtime cryptographic operations. See [[SMC]] for what operations it provides. |