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 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.
| |
− | | |
− | == Package1 ==
| |
− | | |
− | === Key table during package1 ===
| |
| | | |
| + | = Package1ldr = |
| + | == Key table == |
| + | [1.0.0-3.0.2] During package1ldr: |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 69: |
Line 66: |
| | 11 | | | 11 |
| | Package1Key | | | Package1Key |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes | | | Yes |
Line 76: |
Line 73: |
| | SecureBootKey | | | SecureBootKey |
| | Bootrom | | | Bootrom |
− | | No | + | | Yes |
| | No | | | No |
| |- | | |- |
Line 86: |
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 98: |
Line 94: |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
Line 104: |
Line 100: |
| | 13 | | | 13 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |} | | |} |
| | | |
− | === [4.0.0]+ Key table after package1 ===
| + | [4.0.0+] After package1ldr (Secure Monitor boot): |
− | | |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 121: |
Line 116: |
| | 12 | | | 12 |
| | MasterKey | | | MasterKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
| |- | | |- |
| | 13 | | | 13 |
− | | PerConsoleKey_40 | + | | PerConsoleKeyForFirmwareSpecificPerConsoleKeyGen |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |- | | |- |
| | 14 | | | 14 |
− | | MasterKey_40 | + | | StaticKeyForFirmwareSpecificPerConsoleKeyGen |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | No | | | No |
| | Yes, on security updates | | | Yes, on security updates |
Line 139: |
Line 134: |
| | 15 | | | 15 |
| | PerConsoleKey | | | PerConsoleKey |
− | | [[Package1]] | + | | [[Package1#Package1ldr|Package1ldr]] |
| | Yes | | | Yes |
| | No | | | No |
| |} | | |} |
| | | |
| + | [4.0.0+] After package1ldr (Secure Monitor runtime): |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Keyslot |
| + | ! Name |
| + | ! Set by |
| + | ! Per-console |
| + | ! Per-firmware |
| + | |- |
| + | | 12 |
| + | | MasterKey |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | No |
| + | | Yes, on security updates |
| + | |- |
| + | | 13 |
| + | | FirmwareSpecificPerConsoleKey |
| + | | Secure Monitor init |
| + | | Yes |
| + | | Yes, on security updates |
| + | |- |
| + | | 15 |
| + | | PerConsoleKey |
| + | | [[Package1#Package1ldr|Package1ldr]] |
| + | | 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 |
| + | | 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 154: |
Line 209: |
| master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x11 ? simpleseed_dev0 : simpleseed_dev1, 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: |
Line 185: |
Line 242: |
| master_key /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x4f ? normalseed_dev : normalseed_retail, keyblob+0x20) | | 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) | | 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) |
| | | |
| | | |
Line 197: |
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]]. |
| | | |
− | ==== Seeds ==== | + | === 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" |
| + | |- |
| + | ! 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... |
| + | |
| [1.0.0] wrapped_keyblob_key = df206f59... | | [1.0.0] wrapped_keyblob_key = df206f59... |
| [1.0.0] simpleseed_dev0 = aff11423... | | [1.0.0] simpleseed_dev0 = aff11423... |
| [1.0.0] simpleseed_dev1 = 5e177ee1... | | [1.0.0] simpleseed_dev1 = 5e177ee1... |
| [1.0.0] normalseed_dev = 0542a0fd... | | [1.0.0] normalseed_dev = 0542a0fd... |
− | [1.0.0] normalseed_retail = d8a2410a...
| |
| | | |
| [3.0.0] wrapped_keyblob_key = 0c25615d... | | [3.0.0] wrapped_keyblob_key = 0c25615d... |
Line 212: |
Line 343: |
| [3.0.0] simpleseed_dev1 = 2db7c0a1... | | [3.0.0] simpleseed_dev1 = 2db7c0a1... |
| [3.0.0] normalseed_dev = 678c5a03... | | [3.0.0] normalseed_dev = 678c5a03... |
− | [3.0.0] normalseed_retail = d8a2410a...
| |
| | | |
| [3.0.1] wrapped_keyblob_key = 337685ee... | | [3.0.1] wrapped_keyblob_key = 337685ee... |
Line 218: |
Line 348: |
| [3.0.1] simpleseed_dev1 = 84d92e0d... | | [3.0.1] simpleseed_dev1 = 84d92e0d... |
| [3.0.1] normalseed_dev = cd88155b... | | [3.0.1] normalseed_dev = cd88155b... |
− | [3.0.1] normalseed_retail = d8a2410a... | + | |
| + | [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 |
| |- | | |- |
− | | 1.0.0-2.3.0 | + | | K6 |
− | | 1 | + | | 0xF7 |
− | | 1 | + | | Erista retail |
| |- | | |- |
− | | 3.0.0 | + | | M1 |
− | | 2 | + | | 0xDD |
− | | 1 | + | | Mariko prototype development |
| |- | | |- |
− | | 3.0.1-3.0.2 | + | | M2 |
− | | 3 | + | | 0xC3 |
− | | 1 | + | | Mariko development |
| |- | | |- |
− | | 4.0.0 | + | | M3 |
− | | 4 | + | | 0x9B |
− | | 1 | + | | Mariko retail |
| |} | | |} |
| | | |
− | == Bootloader stage 1 == | + | = Secure Monitor Init = |
− | It is currently unknown what key generation the stage 2 bootloader does.
| + | 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. |