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 48: |
Line 48: |
| } | | } |
| | | |
− | == Falcon coprocessor ==
| + | = Falcon coprocessor = |
| The falcon processor (TSEC) generates 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 using data 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. |
| | | |
− | == Package1 == | + | = Package1ldr = |
− | | + | == Key table == |
− | === Key table during package1 ===
| + | [1.0.0-3.0.2] During package1ldr: |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 67: |
Line 66: |
| | 11 | | | 11 |
| | Package1Key | | | Package1Key |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes | | | Yes |
Line 84: |
Line 83: |
| |} | | |} |
| | | |
− | === [1.0.0-3.0.2] Key table after package1 ===
| + | [1.0.0-3.0.2] After package1ldr: |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 96: |
Line 94: |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
Line 102: |
Line 100: |
| | 13 | | | 13 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |} | | |} |
| | | |
− | === [4.0.0]+ Key table after package1 (Secure Monitor boot) ===
| + | [4.0.0+] After package1ldr (Secure Monitor boot): |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 119: |
Line 116: |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
| |- | | |- |
| | 13 | | | 13 |
− | | PerConsoleKeyForNewPerConsoleKeyGen | + | | PerConsoleKeyForFirmwareSpecificPerConsoleKeyGen |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |- | | |- |
| | 14 | | | 14 |
− | | StaticKeyForNewPerConsoleKeyGen | + | | StaticKeyForFirmwareSpecificPerConsoleKeyGen |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
Line 137: |
Line 134: |
| | 15 | | | 15 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |} | | |} |
| | | |
− | === [4.0.0]+ Key table after package1 (Secure Monitor runtime) ===
| + | [4.0.0+] After package1ldr (Secure Monitor runtime): |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 154: |
Line 150: |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
| |- | | |- |
| | 13 | | | 13 |
− | | NewPerConsoleKey | + | | FirmwareSpecificPerConsoleKey |
| | Secure Monitor init | | | Secure Monitor init |
| | Yes | | | Yes |
Line 166: |
Line 162: |
| | 15 | | | 15 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | 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 |
| + | | No |
| + | |- |
| + | | 13 |
| + | | TsecRootKey |
| + | | [[TSEC#Payload|Package1ldr TSEC Firmware]] |
| + | | No |
| + | | Unknown |
| + | |- |
| + | | 14 |
| + | | SecureBootKey |
| + | | Bootrom |
| + | | Yes |
| + | | No |
| + | |- |
| + | | 15 |
| + | | SecureStorageKey |
| + | | Bootrom |
| + | | Yes |
| + | | No |
| + | |} |
| | | |
− | | + | == Key generation == |
− | === 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. |
| | | |
Line 217: |
Line 245: |
| .. and on 4.0.0 it was further moved around: | | .. and on 4.0.0 it was further moved around: |
| | | |
− | old_keyblob_key /* slot15 */ = 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 */) | | 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 232: |
Line 259: |
| new_per_console_key /* slot13 */ = aes_unwrap(0c9109db.., old_keyblob_key) | | new_per_console_key /* slot13 */ = aes_unwrap(0c9109db.., old_keyblob_key) |
| per_console_key /* slot15 */ = aes_unwrap(4f025f0e.., 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 243: |
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]]. |
| | | |
− | ==== Keyblob ====
| + | === 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. | | 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. | | Despite being encrypted with console unique keys, though, the decrypted keyblob contents are shared for all consoles. |
| | | |
− | ==== Seeds ==== | + | Used keyblobs are as follows: |
| + | |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! System version |
| + | ! Used keyblob |
| + | ! Used master static key encryption key in keyblob |
| + | |- |
| + | | 1.0.0-2.3.0 |
| + | | 1 |
| + | | 1 |
| + | |- |
| + | | 3.0.0 |
| + | | 2 |
| + | | 1 |
| + | |- |
| + | | 3.0.1-3.0.2 |
| + | | 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 |
| + | |} |
| + | |
| + | Starting from 6.2.0, key generation no longer uses keyblobs. |
| + | |
| + | === Seeds === |
| normalseed_retail = d8a2410a... | | normalseed_retail = d8a2410a... |
| | | |
Line 272: |
Line 351: |
| [4.0.0] wrapped_keyblob_key = 2d1f4880... | | [4.0.0] wrapped_keyblob_key = 2d1f4880... |
| | | |
− | ==== Table of used keyblobs ==== | + | === 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" | | {| class="wikitable" border="1" |
| |- | | |- |
− | ! System version | + | ! Version |
− | ! Used keyblob | + | ! BCT public key's first byte |
− | ! Used master static key encryption key in keyblob | + | ! 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 |
| |- | | |- |
− | | 1.0.0-2.3.0 | + | | M1 |
− | | 1 | + | | 0x19 |
− | | 1 | + | | Mariko prototype development |
| |- | | |- |
− | | 3.0.0 | + | | M2 |
− | | 2 | + | | 0xC3 |
− | | 1 | + | | Mariko development |
| |- | | |- |
− | | 3.0.1-3.0.2 | + | | M3 |
− | | 3
| + | | 0xDD |
− | | 1
| + | | Mariko prototype retail (pre-6.0.0) |
| |- | | |- |
− | | 4.0.0 | + | | M4 |
− | | 4 | + | | 0x9B |
− | | 1 | + | | Mariko retail |
| |} | | |} |
| | | |
− | == Secure Monitor Init ==
| + | = 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. | | 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 a new per-console key. The operation will erase these special keys passed by package1loader. | + | 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. |