Cryptosystem: Difference between revisions
 Document SSK generation.  | 
				 →Versions:  Add first byte of K4 pubkey  | 
				||
| (32 intermediate revisions by 9 users not shown) | |||
| Line 1: | Line 1: | ||
= 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   | 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) &   |        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 45: | Line 45: | ||
       encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER))  |        encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER))  | ||
       setKeyslot(KEYSLOT_SSK, keyBuffer); SSK = keyBuffer.  |        setKeyslot(KEYSLOT_SSK, keyBuffer); // SSK = keyBuffer.  | ||
   }  |    }  | ||
= Falcon coprocessor =  | |||
The falcon processor (TSEC)   | 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.  | ||
= 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"  | |||
|-  | |||
! 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  | ||
! Per-console  | ! Per-console  | ||
! Per-firmware  | ! Per-firmware  | ||
|-  | |-  | ||
|   | | 12  | ||
|   | | MasterKey  | ||
| [[Package1  | | [[Package1#Package1ldr|Package1ldr]]  | ||
|   | |||
| 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]]  | ||
| 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]]  | ||
|   | | 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  | ||
|   | | Yes  | ||
| No  | | No  | ||
|-  | |-  | ||
| Line 99: | Line 197: | ||
| SecureStorageKey  | | SecureStorageKey  | ||
| Bootrom  | | Bootrom  | ||
| 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(  |    package1_key    /* slot11 */ = aes_unwrap(f5b1eadb.., sbk)  | ||
   master_key      /* slot12 */ = aes_unwrap(bct->pubkey[0] == 0x11 ?   |    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(  | |||
   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(  |    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]].  | ||
===  | === 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  | ||
|}  | |}  | ||
==   | 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] 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  | |||
| 0x6D  | |||
| 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 =  | |||
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.  | ||