TSEC Firmware: Difference between revisions
Created page with "= Boot Process = TSEC is configured and initialized by the first bootloader during key generation. [6.2.0+] TSEC is now configured at the end of the first bootloader's main f..." |
No edit summary |
||
Line 199: | Line 199: | ||
Stored inside the first bootloader, this firmware binary is split into 4 blobs (names are unofficial): [[#Boot|Boot]] (unencrypted and unauthenticated code), [[#KeygenLdr|KeygenLdr]] (unencrypted and authenticated code), [[#Keygen|Keygen]] (encrypted and authenticated code) and [[#Key data|key data]]. | Stored inside the first bootloader, this firmware binary is split into 4 blobs (names are unofficial): [[#Boot|Boot]] (unencrypted and unauthenticated code), [[#KeygenLdr|KeygenLdr]] (unencrypted and authenticated code), [[#Keygen|Keygen]] (encrypted and authenticated code) and [[#Key data|key data]]. | ||
[6.2.0+] There are now | [6.2.0+] There are now 2 new blobs (names are unofficial): [[#SecureBootLdr|SecureBootLdr]] (unencrypted and unauthenticated code), [[#SecureBoot|SecureBoot]] (part unencrypted and unauthenticated code, part encrypted and authenticated code) and [[#Key data|key data]]. | ||
Firmware can be disassembled with [http://envytools.readthedocs.io/en/latest/ envytools'] [https://github.com/envytools/envytools/tree/master/envydis envydis]: | Firmware can be disassembled with [http://envytools.readthedocs.io/en/latest/ envytools'] [https://github.com/envytools/envytools/tree/master/envydis envydis]: | ||
Line 211: | Line 211: | ||
Before returning, this stage writes back to the host (using MMIO registers) and sets the 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 [[# | [6.2.0+] During this stage, [[#Key data|key data]] is loaded and execution jumps to [[#SecureBoot|SecureBootLdr]]. | ||
=== Initialization === | === Initialization === | ||
Line 327: | Line 327: | ||
return boot_res; | return boot_res; | ||
[6.2.0+] Falcon reads the [[#Key data|key data]] and jumps to [[# | [6.2.0+] Falcon reads the [[#Key data|key data]] and jumps to [[#SecureBootLdr|SecureBootLdr]]. | ||
u8 key_data_buf[0x84]; | u8 key_data_buf[0x84]; | ||
Line 912: | Line 912: | ||
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. | 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. | ||
== | == SecureBootLdr == | ||
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 key has been generated, execution returns to this stage which then parses and executes [[# | After the TSEC key has been generated, execution returns to this stage which then parses and executes [[#SecureBoot|SecureBoot]]. | ||
=== Main === | === Main === | ||
Line 987: | Line 987: | ||
u32 blob0_size = *(u32 *)(key_data_buf + 0x70); | u32 blob0_size = *(u32 *)(key_data_buf + 0x70); | ||
// Read the | // Read the SecureBoot blob's Falcon header from memory | ||
u32 blob4_flcn_hdr_addr = (((blob0_size + blob1_size) + 0x100) + blob2_size); | u32 blob4_flcn_hdr_addr = (((blob0_size + blob1_size) + 0x100) + blob2_size); | ||
read_code(flcn_hdr_buf, blob4_flcn_hdr_addr, 0x18); | read_code(flcn_hdr_buf, blob4_flcn_hdr_addr, 0x18); | ||
Line 996: | Line 996: | ||
u32 flcn_hdr_size = *(u32 *)(flcn_hdr_buf + 0x0C); | u32 flcn_hdr_size = *(u32 *)(flcn_hdr_buf + 0x0C); | ||
// Read the | // Read the SecureBoot blob's Falcon OS header from memory | ||
u32 blob4_flcn_os_hdr_addr = ((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_hdr_size); | u32 blob4_flcn_os_hdr_addr = ((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_hdr_size); | ||
read_code(flcn_os_hdr_buf, blob4_flcn_os_hdr_addr, 0x10); | read_code(flcn_os_hdr_buf, blob4_flcn_os_hdr_addr, 0x10); | ||
Line 1,006: | Line 1,006: | ||
u32 flcn_os_size = *(u32 *)(flcn_os_hdr_buf + 0x04); | u32 flcn_os_size = *(u32 *)(flcn_os_hdr_buf + 0x04); | ||
// Read the | // Read the SecureBoot blob's Falcon OS image from memory | ||
u32 blob4_flcn_os_addr = ((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_code_hdr_size); | u32 blob4_flcn_os_addr = ((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_code_hdr_size); | ||
read_code(boot_base_addr, blob4_flcn_os_hdr_addr, flcn_os_size); | read_code(boot_base_addr, blob4_flcn_os_hdr_addr, flcn_os_size); | ||
// Upload the | // Upload the SecureBoot's Falcon OS image boot stub code segment into Falcon's CODE region | ||
u32 blob4_flcn_os_boot_virt_addr = 0; | u32 blob4_flcn_os_boot_virt_addr = 0; | ||
u32 blob4_flcn_os_boot_size = 0x100; | u32 blob4_flcn_os_boot_size = 0x100; | ||
Line 1,018: | Line 1,018: | ||
flcn_os_size = *(u32 *)(flcn_os_hdr_buf + 0x04); | flcn_os_size = *(u32 *)(flcn_os_hdr_buf + 0x04); | ||
// Upload the | // Upload the SecureBoot blob's Falcon OS encrypted image code segment into Falcon's CODE region | ||
u32 blob4_flcn_os_img_virt_addr = 0x100; | u32 blob4_flcn_os_img_virt_addr = 0x100; | ||
u32 blob4_flcn_os_img_size = (flcn_os_size - 0x100); | u32 blob4_flcn_os_img_size = (flcn_os_size - 0x100); | ||
Line 1,033: | Line 1,033: | ||
u32 flcn_os_code_size = *(u32 *)(flcn_os_hdr_buf + 0x08); | u32 flcn_os_code_size = *(u32 *)(flcn_os_hdr_buf + 0x08); | ||
// Read the | // Read the SecureBoot blob's falcon OS image's hash from memory | ||
u32 blob4_flcn_os_img_hash_addr = (((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_code_hdr_size) + flcn_os_code_size); | u32 blob4_flcn_os_img_hash_addr = (((((blob0_size + blob1_size) + 0x100) + blob2_size) + flcn_code_hdr_size) + flcn_os_code_size); | ||
read_code(0, blob4_flcn_os_img_hash_addr, 0x10); | read_code(0, blob4_flcn_os_img_hash_addr, 0x10); | ||
Line 1,044: | Line 1,044: | ||
u32 data_addr = 0x10; | u32 data_addr = 0x10; | ||
// Clear all data except the first 0x10 bytes ( | // Clear all data except the first 0x10 bytes (SecureBoot blob's Falcon OS image's hash) | ||
for (int data_word_count = 0x04; data_word_count < data_seg_size; data_word_count++) | for (int data_word_count = 0x04; data_word_count < data_seg_size; data_word_count++) | ||
{ | { | ||
Line 1,065: | Line 1,065: | ||
csigclr(); | csigclr(); | ||
// Jump to | // Jump to SecureBoot | ||
exec_payload(); | exec_payload(); | ||
return 0xB0B0B0B0; | return 0xB0B0B0B0; | ||
== | == SecureBoot == | ||
This stage prepares the stack then authenticates, decrypts and executes the | This stage prepares the stack then authenticates, decrypts and executes the SecureBoot blob's Falcon OS image. | ||
=== Main === | === Main === | ||
Line 1,082: | Line 1,082: | ||
*(u32 *)sp = data_seg_size; | *(u32 *)sp = data_seg_size; | ||
// Jump to the | // Jump to the SecureBoot blob's Falcon OS image boot stub | ||
exec_flcn_os_boot(); | exec_flcn_os_boot(); | ||
Line 1,132: | Line 1,132: | ||
*(u8 *)flags_ie1 = 0; | *(u8 *)flags_ie1 = 0; | ||
// Jump to the | // Jump to the SecureBoot blob's Falcon OS image | ||
exec_flcn_os_img(); | exec_flcn_os_img(); | ||
Line 1,187: | Line 1,187: | ||
| 0x7C | | 0x7C | ||
| 0x04 | | 0x04 | ||
| [6.2.0+] blob3 ([[# | | [6.2.0+] blob3 ([[#SecureBootLdr|SecureBootLdr]]) size | ||
|- | |- | ||
| 0x80 | | 0x80 | ||
| 0x04 | | 0x04 | ||
| [6.2.0+] blob4 ([[# | | [6.2.0+] blob4 ([[#SecureBoot|SecureBoot]]) size | ||
|} | |} |