TSEC: Difference between revisions

6.2.0 changes
No edit summary
Line 5: Line 5:


== Registers ==
== Registers ==
Registers from 0x54500000 to 0x54501000 are used to configure values for the host interface (HOST1X).
Registers from 0x54500000 to 0x54501000 are used to configure the host interface (HOST1X).


Registers from 0x54501000 to 0x54502000 are a MMIO window for communicating with the Falcon microprocessor. From this range, the subset of registers from 0x54501400 to 0x54501FE8 are specific to the TSEC.
Registers from 0x54501000 to 0x54502000 are a MMIO window for communicating with the Falcon microprocessor. From this range, the subset of registers from 0x54501400 to 0x54501FE8 are specific to the TSEC and are subdivided into:
* 0x54501400 to 0x54501500: SCP (secure crypto processor?).
* 0x54501500 to 0x54501600: Unknown.
* 0x54501600 to 0x54501700: MCCIF (Memory Controller Client Interface).
* 0x54501700 to 0x54501800: DMA.
* 0x54501800 to 0x54501900: TEGRA (miscellaneous interfaces).  


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 80: Line 85:
| [[#FALCON_IRQDEST|FALCON_IRQDEST]]
| [[#FALCON_IRQDEST|FALCON_IRQDEST]]
| 0x5450101C
| 0x5450101C
| 0x04
|-
| FALCON_PERIODIC_PERIOD
| 0x54501020
| 0x04
|-
| FALCON_PERIODIC_TIME
| 0x54501024
| 0x04
|-
| FALCON_PERIODIC_ENABLE
| 0x54501028
| 0x04
|-
| FALCON_TIME_LOW
| 0x5450102C
| 0x04
|-
| FALCON_TIME_HIGH
| 0x54501030
| 0x04
|-
| FALCON_WATCHDOG_TIME
| 0x54501034
| 0x04
|-
| FALCON_WATCHDOG_ENABLE
| 0x54501038
| 0x04
| 0x04
|-
|-
Line 106: Line 139:
| 0x04
| 0x04
|-
|-
| FALCON_SCRATCH2
| FALCON_CMDCTX
| 0x54501080
| 0x54501058
| 0x04
| 0x04
|-
|-
| FALCON_SCRATCH3
| FALCON_STATUS_MASK
| 0x54501084
| 0x5450105C
| 0x04
| 0x04
|-
|-
| FALCON_CGCTL
| FALCON_VM_SUPERVISOR
| 0x545010A0
| 0x54501060
| 0x04
| 0x04
|-
|-
| FALCON_ENGCTL
| FALCON_FIFO_DATA
| 0x545010A4
| 0x54501064
| 0x04
| 0x04
|-
|-
| [[#FALCON_CPUCTL|FALCON_CPUCTL]]
| FALCON_FIFO_CMD
| 0x54501100
| 0x54501068
| 0x04
| 0x04
|-
|-
| [[#FALCON_BOOTVEC|FALCON_BOOTVEC]]
| FALCON_FIFO_DATA_WR
| 0x54501104
| 0x5450106C
| 0x04
| 0x04
|-
|-
| FALCON_HWCFG
| FALCON_FIFO_OCCUPIED
| 0x54501108
| 0x54501070
| 0x04
| 0x04
|-
|-
| [[#FALCON_DMACTL|FALCON_DMACTL]]
| FALCON_FIFO_ACK
| 0x5450110C
| 0x54501074
| 0x04
|-
| FALCON_FIFO_LIMIT
| 0x54501078
| 0x04
| 0x04
|-
|-
| [[#FALCON_DMATRFBASE|FALCON_DMATRFBASE]]
| FALCON_SUBENGINE_RESET
| 0x54501110
| 0x5450107C
| 0x04
| 0x04
|-
|-
| [[#FALCON_DMATRFMOFFS|FALCON_DMATRFMOFFS]]
| FALCON_SCRATCH2
| 0x54501114
| 0x54501080
| 0x04
| 0x04
|-
|-
| [[#FALCON_DMATRFCMD|FALCON_DMATRFCMD]]
| FALCON_SCRATCH3
| 0x54501118
| 0x54501084
| 0x04
| 0x04
|-
|-
| [[#FALCON_DMATRFFBOFFS|FALCON_DMATRFFBOFFS]]
| FALCON_PM_TRIGGER
| 0x5450111C
| 0x54501088
| 0x04
| 0x04
|-
|-
| FALCON_CPUCTL_ALIAS
| FALCON_PM_MODE
| 0x54501130
| 0x5450108C
| 0x04
| 0x04
|-
|-
| FALCON_IMFILLRNG1
| FALCON_DEBUG1
| 0x54501154
| 0x54501090
| 0x04
| 0x04
|-
|-
| FALCON_IMFILLCTL
| FALCON_DEBUGINFO
| 0x54501158
| 0x54501094
| 0x04
| 0x04
|-
|-
| FALCON_EXTERRADDR
| FALCON_BREAKPOINT0
| 0x54501168
| 0x54501098
| 0x04
| 0x04
|-
|-
| FALCON_EXTERRSTAT
| FALCON_BREAKPOINT1
| 0x5450116C
| 0x5450109C
| 0x04
| 0x04
|-
|-
| FALCON_CG2
| FALCON_CGCTL
| 0x5450117C
| 0x545010A0
| 0x04
| 0x04
|-
|-
| FALCON_CODE_INDEX
| FALCON_ENGCTL
| 0x54501180
| 0x545010A4
| 0x04
| 0x04
|-
|-
| FALCON_CODE
| FALCON_PM_SEL
| 0x54501184
| 0x545010A8
| 0x04
| 0x04
|-
|-
| FALCON_CODE_VIRT_ADDR
| FALCON_HOST_IO_INDEX
| 0x54501188
| 0x545010AC
| 0x04
| 0x04
|-
|-
| FALCON_DATA_INDEX0
| [[#FALCON_CPUCTL|FALCON_CPUCTL]]
| 0x545011C0
| 0x54501100
| 0x04
| 0x04
|-
|-
| FALCON_DATA0
| [[#FALCON_BOOTVEC|FALCON_BOOTVEC]]
| 0x545011C4
| 0x54501104
| 0x04
| 0x04
|-
|-
| FALCON_DATA_INDEX1
| FALCON_HWCFG
| 0x545011C8
| 0x54501108
| 0x04
| 0x04
|-
|-
| FALCON_DATA1
| [[#FALCON_DMACTL|FALCON_DMACTL]]
| 0x545011CC
| 0x5450110C
| 0x04
| 0x04
|-
|-
| FALCON_DATA_INDEX2
| [[#FALCON_DMATRFBASE|FALCON_DMATRFBASE]]
| 0x545011D0
| 0x54501110
| 0x04
| 0x04
|-
|-
| FALCON_DATA2
| [[#FALCON_DMATRFMOFFS|FALCON_DMATRFMOFFS]]
| 0x54501114
| 0x04
|-
| [[#FALCON_DMATRFCMD|FALCON_DMATRFCMD]]
| 0x54501118
| 0x04
|-
| [[#FALCON_DMATRFFBOFFS|FALCON_DMATRFFBOFFS]]
| 0x5450111C
| 0x04
|-
| FALCON_DMATRFSTAT
| 0x54501120
| 0x04
|-
| FALCON_CRYPTTRFSTAT
| 0x54501124
| 0x04
|-
| FALCON_CPUSTAT
| 0x54501128
| 0x04
|-
| FALCON_HWCFG_ALIAS
| 0x5450112C
| 0x04
|-
| FALCON_CPUCTL_ALIAS
| 0x54501130
| 0x04
|-
| FALCON_TLB_CMD
| 0x54501140
| 0x04
|-
| FALCON_TLB_CMD_RES
| 0x54501144
| 0x04
|-
| FALCON_BRANCH_HISTORY_CTRL
| 0x54501148
| 0x04
|-
| FALCON_BRANCH_HISTORY_PC
| 0x5450114C
| 0x04
|-
| FALCON_IMFILLRNG0
| 0x54501150
| 0x04
|-
| FALCON_IMFILLRNG1
| 0x54501154
| 0x04
|-
| FALCON_IMFILLCTL
| 0x54501158
| 0x04
|-
| FALCON_EXTERRWIN
| 0x54501160
| 0x04
|-
| FALCON_EXTERRCFG
| 0x54501164
| 0x04
|-
| FALCON_EXTERRADDR
| 0x54501168
| 0x04
|-
| FALCON_EXTERRSTAT
| 0x5450116C
| 0x04
|-
| FALCON_CG2
| 0x5450117C
| 0x04
|-
| FALCON_CODE_INDEX
| 0x54501180
| 0x04
|-
| FALCON_CODE
| 0x54501184
| 0x04
|-
| FALCON_CODE_VIRT_ADDR
| 0x54501188
| 0x04
|-
| FALCON_DATA_INDEX0
| 0x545011C0
| 0x04
|-
| FALCON_DATA0
| 0x545011C4
| 0x04
|-
| FALCON_DATA_INDEX1
| 0x545011C8
| 0x04
|-
| FALCON_DATA1
| 0x545011CC
| 0x04
|-
| FALCON_DATA_INDEX2
| 0x545011D0
| 0x04
|-
| FALCON_DATA2
| 0x545011D4
| 0x545011D4
| 0x04
| 0x04
Line 274: Line 423:
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK0
| TSEC_SCP_UNK0
| 0x54501400
| 0x54501400
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK1
| TSEC_SCP_UNK1
| 0x54501404
| 0x54501404
| 0x04
| 0x04
Line 290: Line 439:
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK2
| TSEC_SCP_UNK2
| 0x54501410
| 0x54501410
| 0x04
| 0x04
Line 298: Line 447:
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK3
| TSEC_SCP_UNK3
| 0x54501420
| 0x54501420
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK4
| TSEC_SCP_UNK4
| 0x54501428
| 0x54501428
| 0x04
| 0x04
|-
|-
| TSEC_SCP_CTL_UNK5
| TSEC_SCP_UNK5
| 0x54501430
| 0x54501430
| 0x04
| 0x04
|-
|-
| TSEC_SCP_UNK0
| TSEC_SCP_UNK6
| 0x54501454
| 0x54501454
| 0x04
| 0x04
|-
|-
| TSEC_SCP_UNK1
| TSEC_SCP_UNK7
| 0x54501458
| 0x54501458
| 0x04
| 0x04
|-
|-
| TSEC_SCP_UNK2
| TSEC_SCP_UNK8
| 0x54501470
| 0x54501470
| 0x04
| 0x04
|-
|-
| TSEC_SCP_UNK3
| TSEC_SCP_UNK9
| 0x54501480
| 0x54501480
| 0x04
| 0x04
|-
|-
| TSEC_SCP_UNK4
| TSEC_SCP_UNK10
| 0x54501490
| 0x54501490
| 0x04
| 0x04
Line 366: Line 515:
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_MCCIF_UNK0
| TSEC_MCCIF_UNK0
| 0x54501600
| 0x54501600
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_MCCIF_FIFOCTRL
| TSEC_MCCIF_FIFOCTRL
| 0x54501604
| 0x54501604
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_MCCIF_UNK1
| TSEC_MCCIF_UNK1
| 0x54501608
| 0x54501608
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_MCCIF_UNK2
| TSEC_MCCIF_UNK2
| 0x5450160C
| 0x5450160C
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_UNK0
| TSEC_MCCIF_UNK3
| 0x54501630
| 0x54501630
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_UNK1
| TSEC_MCCIF_UNK4
| 0x54501634
| 0x54501634
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_UNK2
| TSEC_MCCIF_UNK5
| 0x54501640
| 0x54501640
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_UNK3
| [[#TSEC_MCCIF_UNK6|TSEC_MCCIF_UNK6]]
| 0x54501644
| 0x54501644
| 0x04
| 0x04
|-
|-
| TSEC_TFBIF_UNK4
| [[#TSEC_MCCIF_UNK7|TSEC_MCCIF_UNK7]]
| 0x54501648
| 0x54501648
| 0x04
| 0x04
Line 586: Line 735:
| TSEC_SCP_CTL_PKEY_LOADED
| TSEC_SCP_CTL_PKEY_LOADED
|}
|}
=== TSEC_MCCIF_UNK6 ===
Used to control accesses to DRAM.
[6.0.0+] The nvhost_tsec firmware sets this register to 0x10 or 0x111110 before reading memory from the GPU UCODE carveout.
=== TSEC_MCCIF_UNK7 ===
Used to control accesses to DRAM.
[6.0.0+] The nvhost_tsec firmware sets this register to (data_size << 4) before reading memory from the GPU UCODE carveout.


=== TSEC_DMA_CMD ===
=== TSEC_DMA_CMD ===
Line 792: Line 951:
  deadlock();
  deadlock();


== Device key generation ==
== TSEC key generation ==
The TSEC device key is generated by reading SOR1 registers modified by the Falcon CPU.
The TSEC key is generated by reading SOR1 registers modified by the Falcon CPU.
  // Clear magic value in host1x scratch space
  // Clear magic value in host1x scratch space
  *(u32 *)0x50003300 = 0;
  *(u32 *)0x50003300 = 0;
   
   
  // Read TSEC device key
  // Read TSEC key
  u32 tsec_device_key[4];  
  u32 tsec_key[4];  
  tsec_device_key[0] = *(u32 *)NV_SOR_DP_HDCP_BKSV_LSB;
  tsec_key[0] = *(u32 *)NV_SOR_DP_HDCP_BKSV_LSB;
  tsec_device_key[1] = *(u32 *)NV_SOR_TMDS_HDCP_BKSV_LSB;
  tsec_key[1] = *(u32 *)NV_SOR_TMDS_HDCP_BKSV_LSB;
  tsec_device_key[2] = *(u32 *)NV_SOR_TMDS_HDCP_CN_MSB;
  tsec_key[2] = *(u32 *)NV_SOR_TMDS_HDCP_CN_MSB;
  tsec_device_key[3] = *(u32 *)NV_SOR_TMDS_HDCP_CN_LSB;
  tsec_key[3] = *(u32 *)NV_SOR_TMDS_HDCP_CN_LSB;
   
   
  // Clear SOR1 registers
  // Clear SOR1 registers
Line 813: Line 972:
     out_size = 0x10;
     out_size = 0x10;
   
   
  // Copy back the TSEC device key
  // Copy back the TSEC key
  memcpy(out_buf, tsec_device_key, out_size);
  memcpy(out_buf, tsec_key, out_size);


[6.2.0+] This is now done inside an encrypted TSEC payload.
[6.2.0+] This is now done inside an encrypted TSEC payload.
Line 860: Line 1,019:
== Boot ==
== Boot ==
During this stage, [[#Key data|key data]] is loaded and [[#KeygenLdr|KeygenLdr]] is authenticated, loaded and executed.
During this stage, [[#Key data|key data]] is loaded and [[#KeygenLdr|KeygenLdr]] is authenticated, loaded and executed.
Before returning, this stage writes back to the host (using MMIO registers) and sets the device key used by the first bootloader.
Before returning, this stage writes back to the host (using MMIO registers) and sets the key used by the first bootloader.


[6.2.0+] During this stage, [[#Key data|key data]] is loaded and execution jumps to [[#Loader|Loader]].
[6.2.0+] During this stage, [[#Key data|key data]] is loaded and execution jumps to [[#Loader|Loader]].
Line 876: Line 1,035:


=== Main ===
=== Main ===
Falcon reads the [[#Key data|key data]], authenticates, loads and executes [[#KeygenLdr|KeygenLdr]] and finally sets the device key.
Falcon reads the [[#Key data|key data]] and then authenticates, loads and executes [[#KeygenLdr|KeygenLdr]] which sets the TSEC key.
  u32 boot_base_addr = 0;
  u32 boot_base_addr = 0;
  u8 key_data_buf[0x7C];
  u8 key_data_buf[0x7C];
Line 972: Line 1,131:
  }
  }
   
   
  // Write TSEC device key to registers
  // Overwrite the TSEC key in SOR1 registers
  set_device_key(key_data_buf);
  // This has no effect because the KeygenLdr locks out the TSEC DMA engine
tsec_set_key(key_data_buf);
   
   
  return boot_res;
  return boot_res;
Line 997: Line 1,157:
  return 0;
  return 0;


==== set_device_key ====
==== tsec_set_key ====
This method takes '''key_data_buf''' as argument and writes the TSEC key to SOR1 registers.
This method takes '''key_data_buf''' (a 16 bytes buffer) as argument and writes its contents to SOR1 registers.
  // This is TSEC_MMIO + 0x1000 + (0x1C300 / 0x40)
  // This is TSEC_MMIO + 0x1000 + (0x1C300 / 0x40)
  *(u32 *)TSEC_DMA_UNK = 0xFFF;
  *(u32 *)TSEC_DMA_UNK = 0xFFF;
Line 1,270: Line 1,430:
  else if (key_version == 0x02)         // Use HOVI_COMMON_01
  else if (key_version == 0x02)         // Use HOVI_COMMON_01
   hovi_key_addr = key_buf + 0x60;
   hovi_key_addr = key_buf + 0x60;
  else if (key_version == 0x03)         // Use empty key
  else if (key_version == 0x03)         // Use debug key (empty)
   hovi_key_addr = key_buf + 0x00;
   hovi_key_addr = key_buf + 0x00;
  else
  else
Line 1,560: Line 1,720:


== Keygen ==
== Keygen ==
This stage is decrypted by [[#KeygenLdr|KeygenLdr]] using a key generated by encrypting a seed with an hardware secret. It will generate the final TSEC device key.
This stage is decrypted by [[#KeygenLdr|KeygenLdr]] using a key generated by encrypting a seed with an hardware secret. It will generate the final TSEC key.


== Loader ==
== Loader ==
This stage starts by authenticating and executing [[#KeygenLdr|KeygenLdr]] which in turn authenticates, decrypts and executes [[#Keygen|Keygen]] (both blobs remain unchanged from previous firmware versions).
This stage starts by authenticating and executing [[#KeygenLdr|KeygenLdr]] which in turn authenticates, decrypts and executes [[#Keygen|Keygen]] (both blobs remain unchanged from previous firmware versions).
After the TSEC device key has been generated, execution returns to this stage which then parses and executes [[#Payload|Payload]].
After the TSEC key has been generated, execution returns to this stage which then parses and executes [[#Payload|Payload]].


=== Main ===
=== Main ===
Line 1,774: Line 1,934:
   
   
  // fuc5 crypt cauth instruction
  // fuc5 crypt cauth instruction
  // Set auth_addr to 0x100, auth_size to 0x1300 and some unknown flags
  // Set auth_addr to 0x100, auth_size to 0x1300,
// bit 16 (is_secret) and bit 17 (is_encrypted)
  cauth((0x02 << 0x10) | (0x01 << 0x10) | (0x1300 << 0x10) | (0x100 >> 0x08));
  cauth((0x02 << 0x10) | (0x01 << 0x10) | (0x1300 << 0x10) | (0x100 >> 0x08));
   
   
Line 1,796: Line 1,957:
| 0x00
| 0x00
| 0x10
| 0x10
| Empty
| Debug key (empty)
|-
|-
| 0x10
| 0x10