Changes

Jump to navigation Jump to search
8,290 bytes added ,  22:29, 7 November 2020
→‎Versions: fix M1-M4
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 6: Line 6:     
Reads from both of these keyslots are disabled by the bootROM.
 
Reads from both of these keyslots are disabled by the bootROM.
These keys is stored in fuses, and can no longer be accessed after bootrom.
+
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, and SSK console-unique. But we don't know this is the case.
+
SBK is '''unique''' per console, and not shared among consoles as originally believed.
   −
== Falcon coprocessor ==
+
The SSK is derived on boot via the SBK, the 32-bit console-unique "Device Key", and hardware information stored in fuses.
The falcon processor (TSEC) stores 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.
+
Pseudocode for the derivation is as follows:
 +
  void generateSSK() {
 +
      char keyBuffer[0x10]; // Used to store keydata
 +
      uint hwInfoBuffer[4]; // Used to store info about hardware from fuses
 +
      uint deviceKey = getDeviceKey(); // Reads 32-bit device key from FUSE_PRIVATE_KEY4.
 +
      for (int i = 0; i < 4; i++) { // Keybuffer = deviceKey || deviceKey || deviceKey || deviceKey
 +
          ((uint *)keyBuffer)[i] = deviceKey;
 +
      }
 +
     
 +
      encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, deviceKey || {...})
 +
     
 +
      // Set up Hardware info buffer
 +
      uint vendor_code = *((uint *)0x7000FA00) & 0x0000000F; // FUSE_VENDOR_CODE
 +
      uint fab_code    = *((uint *)0x7000FA04) & 0x0000003F; // FUSE_FAB_CODE
 +
      uint lot_code_0  = *((uint *)0x7000FA08) & 0xFFFFFFFF; // FUSE_LOT_CODE_0
 +
      uint lot_code_1  = *((uint *)0x7000FA0C) & 0x0FFFFFFF; // FUSE_LOT_CODE_1
 +
      uint wafer_id    = *((uint *)0x7000FA10) & 0x0000003F; // FUSE_WAFER_ID
 +
      uint x_coord    = *((uint *)0x7000FA14) & 0x000001FF; // FUSE_X_COORDINATE
 +
      uint y_coord    = *((uint *)0x7000FA18) & 0x000001FF; // FUSE_Y_COORDINATE
 +
      uint unk_hw_fuse = *((uint *)0x7000FA20) & 0x0000003F; // Unknown cached fuse.
 +
     
 +
      // HARDWARE_INFO_BUFFER = unk_hw_fuse || Y_COORD || X_COORD || WAFER_ID || LOT_CODE || FAB_CODE || VENDOR_ID
 +
      hwInfoBuffer[0] = (lot_code_1 << 30) | (wafer_id << 24) | (x_coord << 15) | (y_coord << 6) | unk_hw_fuse;
 +
      hwInfoBuffer[1] = (lot_code_0 << 26) | (lot_code_1 >> 2);
 +
      hwInfoBuffer[2] = (fab_code << 26) | (lot_code_0 >> 6);
 +
      hwInfoBuffer[3] = vendor_code;
 +
     
 +
      for (int i = 0; i < 0x10; i++) { // keyBuffer = XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER)
 +
          keyBuffer[i] ^= ((char *)hwInfoBuffer)[i];
 +
      }
 +
     
 +
      encryptWithSBK(keyBuffer); // keyBuffer = AES-ECB(SBK, XOR(AES-ECB(SBK, deviceKey || {...}), HARDWARE_INFO_BUFFER))
 +
     
 +
      setKeyslot(KEYSLOT_SSK, keyBuffer); // SSK = keyBuffer.
 +
  }
 +
 +
= Falcon coprocessor =
 +
The falcon processor (TSEC) generates a special console-unique key (that will be referred to as the "tsec key").
   −
The tsec key is the source of all per-console entropy, because SSK is not used on retail.
+
This is presumably using data stored in fuses that only microcode authenticated by NVidia has access to.
 
  −
== Package1 ==
  −
 
  −
=== Key generation ===
      +
= Package1ldr =
 +
== Key table ==
 +
[1.0.0-3.0.2] During package1ldr:
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 26: Line 61:  
! Name
 
! Name
 
! Set by
 
! Set by
! Cleared by
   
! Per-console
 
! Per-console
 
! Per-firmware
 
! Per-firmware
Line 32: Line 66:  
| 11
 
| 11
 
| Package1Key
 
| Package1Key
| [[Package1]]
+
| [[Package1#Package1ldr|Package1ldr]]
| [[Package1]]
   
| No
 
| No
 
| Yes
 
| Yes
 +
|-
 +
| 14
 +
| SecureBootKey
 +
| Bootrom
 +
| Yes
 +
| No
 +
|-
 +
| 15
 +
| SecureStorageKey
 +
| Bootrom
 +
| Yes
 +
| No
 +
|}
 +
 +
[1.0.0-3.0.2] After package1ldr:
 +
{| 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
Line 46: Line 100:  
| 13
 
| 13
 
| PerConsoleKey
 
| PerConsoleKey
| [[Package1]]
+
| [[Package1#Package1ldr|Package1ldr]]
| Forever
+
| Yes
 +
| No
 +
|}
 +
 
 +
[4.0.0+] After package1ldr (Secure Monitor boot):
 +
{| class="wikitable" border="1"
 +
|-
 +
! Keyslot
 +
! Name
 +
! Set by
 +
! Per-console
 +
! Per-firmware
 +
|-
 +
| 12
 +
| MasterKey
 +
| [[Package1#Package1ldr|Package1ldr]]
 +
| No
 +
| Yes, on security updates
 +
|-
 +
| 13
 +
| PerConsoleKeyForFirmwareSpecificPerConsoleKeyGen
 +
| [[Package1#Package1ldr|Package1ldr]]
 
| Yes
 
| Yes
 
| No
 
| 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
 +
| 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
 
| 14
 
| SecureBootKey
 
| SecureBootKey
 
| Bootrom
 
| Bootrom
| [[Package1]]
+
| Yes
| No
   
| No
 
| No
 
|-
 
|-
Line 61: 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 85: 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 98: 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 120: 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.

Navigation menu