Difference between revisions of "Package1 TSEC Firmware"
(Created page with "TSEC is a nvidia falcon processor with crypto extensions. Firmware can be disassembled with [http://envytools.readthedocs.io/en/latest/ envytools'] [https://github.com/envyto...") |
(No difference)
|
Revision as of 19:42, 11 August 2017
TSEC is a nvidia falcon processor with crypto extensions.
Firmware can be disassembled with envytools' envydis:
envydis -i tsec_fw.bin -m falcon -V fuc5 -F crypt
Note that the instruction set has variable length instructions, and the disassembler is not very good at detecting locations it should start disassembling from. One needs to disassemble multiple sub-regions and join them together.
Additional Notes on Crypto Extensions
mwk shared additional info learned from RE of falcon processors over the years, which hasn't made it into envytools documentation yet:
cxset
cxset instruction provides a way to change behavior of a variable amount of successively executed DMA-related instructions.
for example: 000000de: f4 3c 02 cxset 0x2
can be read as: dma_override(type=crypto_reg, count=2)
The argument to cxset specifies the type of behavior change in the top 3 bits, and the number of DMA-related instructions the effect lasts for in the lower 5 bits.
Override Types
Unlisted values are unknown, but probably do something.
Value | Effect |
---|---|
0b000 | falcon data mem <-> falcon $cX register |
0b001 | external mem <-> crypto input/output stream |
DMA-Related Instructions
At least the following instructions may have changed behavior, and count against the cxset "count" argument: xdwait
, xdst
, xdld
.
For example, if override type=0b000, then the "length" argument to xdst
is instead treated as the index of the target $cX register.
Annotated Assembly
Keep in mind the architecture is not officially documented, so some things may be incorrect.
00000000: 4d 00 42 mov $r13 0x4200 ; UC_CAPS 00000003: cf dd 00 iord $r13 I[$r13] 00000006: b6 d5 09 shr b32 $r13 0x9 00000009: f1 d4 ff 01 and $r13 0x1ff 0000000d: b6 d4 08 shl b32 $r13 0x8 ; r13 = falcon data segment size 00000010: fe d4 00 mov $sp $r13 ; put stack top all the way at the end 00000013: 7e 19 00 00 lcall 0x19 00000017: f8 02 exit 00000019: 0f f0 C mov $r15 -0x10 0000001b: f5 30 e4 fe add $sp -0x11c 0000001f: f9 82 mpush $r8 00000021: fe 49 01 mov $r9 $sp 00000024: 90 99 c4 add b32 $r9 $r9 0xc4 00000027: ff 9f 34 and $r3 $r9 $r15 ; r3 = (sp + 0xc4) & ~0xf 0000002a: 92 99 8b sub b32 $r9 $r9 0x8b 0000002d: 85 00 03 00 mov $r5 0x300 00000031: ff 9f 44 and $r4 $r9 $r15 ; r4 = (sp + 0x39) & ~0xf 00000034: b2 5b mov b32 $r11 $r5 00000036: 0c 7c mov $r12 0x7c 00000038: b2 3a mov b32 $r10 $r3 0000003a: 7e 0b 02 00 lcall 0x20b ; memcpy_i2d(dst=r3{local}, src=0x300, len=0x7c) 0000003e: 98 3c 1d ld b32 $r12 D[$r3+TSecLoaderInfo.secure_loader_len] ; r12 = 0x600 00000041: 95 59 08 shr b32 $r9 $r5 0x8 00000044: 8b 00 04 00 mov $r11 0x400 00000048: b0 91 09 st b32 D[$sp+0x24] $r9 0000004b: bd a4 clear b32 $r10 ; temp copy for next step 0000004d: 7e 0b 02 00 lcall 0x20b ; memcpy_i2d(dst=0, src=0x400, len=0x600) 00000051: 98 3c 1d ld b32 $r12 D[$r3+TSecLoaderInfo.secure_loader_len] ; r12 = 0x600 00000054: b2 5a mov b32 $r10 $r5 00000056: bd b4 clear b32 $r11 00000058: b2 5d mov b32 $r13 $r5 0000005a: 0e 01 mov $r14 0x1 ; copy the code originally @ I:0x400 to I:0x300 and mark secret 0000005c: 7e c2 01 00 lcall 0x1c2 ; memcpy_d2i_ex(dst_page_offset=0x300, src=0, len=0x600, dst=0x300, is_secret=1) 00000060: 89 00 00 06 mov $r9 0x60000 ; will be used as size bits for xdst @ 000000e1 00000064: 90 4f 20 add b32 $r15 $r4 0x20 ; TSecLoaderInfo.field_20 00000067: bd 64 clear b32 $r6 00000069: ff f9 75 or $r7 $r15 $r9 0000006c: bd 24 clear b32 $r2 ; loop_count = 0 0000006e: bd 94 clear b32 $r9 00000070: bd 84 clear b32 $r8 ; ext_offset = 0 00000072: 3e 78 00 00 lbra 0x78 loop_set_ignored_cmd: 00000076: b2 19 B mov b32 $r9 $r1 ; i guess this is because SCRATCH0 retains the old cmd loop: 00000078: 90 22 01 B add b32 $r2 $r2 0x1 0000007b: 8f 01 09 3d mov $r15 0x3d0901 ; 4000001 0000007f: a6 2f cmp b32 $r2 $r15 00000081: f4 1b 17 bra ne 0x98 ; for (u32 r2 = 0; r2 < 4000000; r2++) { set_status_c0_loop_expired: 00000084: df c0 c0 c0 c0 mov $r15 0xc0c0c0c0 00000089: 49 00 11 mov $r9 0x1100 0000008c: fa 9f 00 iowr I[$r9] $r15 ; SCRATCH1 = 0xc0c0c0c0 0000008f: d0 c0 c0 c0 c0 mov $r0 0xc0c0c0c0 00000094: 3e 0c 01 00 lbra 0x10c ; -> writeback_key_and_ret read_next_command: 00000098: 4f 00 10 B mov $r15 0x1000 0000009b: ff f8 1f iord $r1 I[$r15+$r8*0x4] ; r1 = SCRATCH0 (cmd) 0000009e: b3 14 64 18 bra b32 $r1 0x64 ne 0xb6 ; -> dispatch_command handle_command_0x64: 000000a2: df b0 b0 b0 b0 mov $r15 0xb0b0b0b0 000000a7: 49 00 11 mov $r9 0x1100 000000aa: fa 9f 00 iowr I[$r9] $r15 ; SCRATCH1 = 0xb0b0b0b0 000000ad: d0 b0 b0 b0 b0 mov $r0 0xb0b0b0b0 000000b2: 3e 0c 01 00 lbra 0x10c ; -> writeback_key_and_ret dispatch_command: 000000b6: a6 19 B cmp b32 $r1 $r9 000000b8: f4 0b c0 bra e 0x78 ; if (cmd == ignored_cmd) continue; 000000bb: b3 10 00 3b bra b32 $r1 0x0 e 0xf6 ; if (cmd == 0) set_status_b0_ok_and_continue; 000000bf: b0 16 03 cmp b32 $r1 0x3 000000c2: f4 0c 56 bra a 0x118 ; if (cmd > 3) return BAD_CMD; 000000c5: b2 4a mov b32 $r10 $r4 000000c7: b2 3b mov b32 $r11 $r3 000000c9: 0c 7c mov $r12 0x7c ; make another copy of the ldr_info (secure_loader will zero it before return) 000000cb: 7e 37 02 00 lcall 0x237 ; memcpy_d2d(dst=r4{local}, src=r3{local}, len=0x7c) 000000cf: 98 49 1d ld b32 $r9 D[$r4+TSecLoaderInfo.secure_loader_len] ; code_size = 0x600 000000d2: b4 f0 09 ld b32 $r15 D[$sp+0x24] ; secure_loader_dst_page = 0x300 >> 8 000000d5: b6 94 10 shl b32 $r9 0x10 000000d8: fd 9f 05 or $r9 $r15 000000db: fe 9a 00 mov $cauth $r9 ; cauth = (code_size << 16) | secure_loader_dst_page 000000de: f4 3c 02 cxset 0x2 ; dma_override(type=crypto_reg, count=2) 000000e1: fa 87 06 xdst $r8 $r7 ; crypto_reg_load(crypto_reg=$c6, local_address=r4+0x20) 000000e4: f8 03 xdwait 000000e6: b2 6c mov b32 $r12 $r6 000000e8: b2 4a mov b32 $r10 $r4 000000ea: b2 1b mov b32 $r11 $r1 000000ec: 06 01 mov $r6 0x1 ; set loader_called=1 for next iterations 000000ee: f9 55 call $r5 ; secure_loader_thunk(ldr_info{r4 local}, cmd, skip_copy_and_decrypt=loader_called) 000000f0: b2 a0 mov b32 $r0 $r10 000000f2: b3 a4 00 09 bra b32 $r10 0x0 ne 0xfb ; if (rv != 0) { SCRATCH1 = rv; return; } set_status_b0_ok_and_continue: 000000f6: d0 b0 b0 b0 b0 B mov $r0 0xb0b0b0b0 ; else { SCRATCH1 = 0xb0b0b0b0; continue; } write_status_and_key: // returns if status != 0xb0b0b0b0 000000fb: 49 00 11 B mov $r9 0x1100 000000fe: fa 90 00 iowr I[$r9] $r0 ; SCRATCH1 = rv 00000101: df b0 b0 b0 b0 mov $r15 0xb0b0b0b0 00000106: a6 0f cmp b32 $r0 $r15 00000108: f5 0b 6e ff bra e 0x76 ; -> loop_set_ignored_cmd (continue) writeback_key_and_ret: 0000010c: b2 3a B mov b32 $r10 $r3 ; somehow secure_payload writes back to this..? 0000010e: 7e 77 01 00 lcall 0x177 ; write128_via_SOR(r3{local}) 00000112: b2 0a mov b32 $r10 $r0 00000114: fb 83 1c 01 mpopaddret $r8, 0x11c ; was: mpopunk [unknown: 00 80 1c 01] set_status_d0_bad_cmd: 00000118: d0 d0 d0 d0 d0 B mov $r0 0xd0d0d0d0 ; rv = 0xd0d0d0d0 0000011d: 3e fb 00 00 lbra 0xfb // wait_1c000() // 0x1c000 == mmio + 0x700 while (((*(u32 *)0x1c000 >> 12) & 7) == 1) { ; // expect it to clear to 0 } 00000121: 8f 00 c0 01 C mov $r15 0x1c000 00000125: cf f9 00 B iord $r9 I[$r15] 00000128: c7 9a 4c extr $r10 $r9 0xc:0xe 0000012b: b3 a0 01 fa bra b32 $r10 0x1 e 0x125 0000012f: f8 00 ret // write_1c000_indirect(addr=r10, val=r11) 00000131: f9 12 C mpush $r1 00000133: b2 a0 mov b32 $r0 $r10 00000135: b2 b1 mov b32 $r1 $r11 00000137: 7e 21 01 00 lcall 0x121 0000013b: 09 01 mov $r9 0x1 0000013d: b3 a4 00 2d bra b32 $r10 0x0 ne 0x16a ; if (wait_1c000() != STATUS_OK) return 1; 00000141: 89 00 c1 01 mov $r9 0x1c100 00000145: fa 90 00 iowr I[$r9] $r0 ; 0x1c100 = addr 00000148: b8 99 00 01 00 add b32 $r9 $r9 0x100 0000014d: fa 91 00 iowr I[$r9] $r1 ; 0x1c200 = val 00000150: df f2 00 00 80 mov $r15 0x800000f2 00000155: b8 99 00 02 02 sub b32 $r9 $r9 0x200 0000015a: fa 9f 00 iowr I[$r9] $r15 ; 0x1c000 = 0x800000f2 0000015d: 7e 21 01 00 lcall 0x121 ; wait_1c000() 00000161: b0 a6 00 cmp b32 $r10 0x0 00000164: f0 9c 0b xbit $r9 $flags z 00000167: f0 96 01 xor $r9 0x1 ; return (wait_1c000() == STATUS_OK) ? 0 : 1; 0000016a: b2 9a B mov b32 $r10 $r9 0000016c: fb 11 mpopret $r1 // write_1c300(val=r10) ; unused function? 0000016e: 89 00 c3 01 mov $r9 0x1c300 00000172: fa 9a 00 iowr I[$r9] $r10 ; 0x1c300 = r10 00000175: f8 00 ret // throw the key material in "random" HDCP key regs... void write128_via_SOR(u32 *data) { 0x1c300 = 0xfff; if (write_1c000_indirect(0x545801e8, data[0])) { return; } if (write_1c000_indirect(0x5458021c, data[1])) { return; } if (write_1c000_indirect(0x54580208, data[2])) { return; } if (write_1c000_indirect(0x5458020c, data[3])) { return; } } 00000177: f9 02 C mpush $r0 00000179: 4f ff 0f mov $r15 0xfff 0000017c: b2 a0 mov b32 $r0 $r10 0000017e: 89 00 c3 01 mov $r9 0x1c300 00000182: fa 9f 00 iowr I[$r9] $r15 00000185: bf ab ld b32 $r11 D[$r10] 00000187: da e8 01 58 54 mov $r10 0x545801e8 0000018c: 7e 31 01 00 lcall 0x131 00000190: b3 a4 00 30 bra b32 $r10 0x0 ne 0x1c0 00000194: 98 0b 01 ld b32 $r11 D[$r0+0x4] 00000197: da 1c 02 58 54 mov $r10 0x5458021c 0000019c: 7e 31 01 00 lcall 0x131 000001a0: b3 a4 00 20 bra b32 $r10 0x0 ne 0x1c0 000001a4: 98 0b 02 ld b32 $r11 D[$r0+0x8] 000001a7: da 08 02 58 54 mov $r10 0x54580208 000001ac: 7e 31 01 00 lcall 0x131 000001b0: b3 a4 00 10 bra b32 $r10 0x0 ne 0x1c0 000001b4: 98 0b 03 ld b32 $r11 D[$r0+0xc] 000001b7: da 0c 02 58 54 mov $r10 0x5458020c 000001bc: 7e 31 01 00 lcall 0x131 000001c0: fb 01 B mpopret $r0 // memcpy_d2i_ex(dst_page_offset=r10, src=r11, len=r12, dst=r13, is_secret=r14) 000001c2: f9 02 C mpush $r0 000001c4: b2 b0 mov b32 $r0 $r11 ; src, data 000001c6: b2 cb mov b32 $r11 $r12 ; len, bytes 000001c8: b2 dc mov b32 $r12 $r13 ; dst, insn 000001ca: 33 00 00 0a bra b8 $r0 0x0 e 0x1d4 ; assert((src & 0xff) == 0) 000001ce: f8 02 exit 000001d0: 3e d0 01 00 B lbra 0x1d0 000001d4: 33 b0 00 0a B bra b8 $r11 0x0 e 0x1de ; assert((len & 0xff) == 0) 000001d8: f8 02 exit 000001da: 3e da 01 00 B lbra 0x1da 000001de: 33 c0 00 0a B bra b8 $r12 0x0 e 0x1e8 ; assert((dst & 0xff) == 0) 000001e2: f8 02 exit 000001e4: 3e e4 01 00 B lbra 0x1e4 000001e8: b3 e0 00 0d B bra b32 $r14 0x0 e 0x1f5 000001ec: d9 00 00 00 11 mov $r9 0x11000000 000001f1: 3e fa 01 00 lbra 0x1fa 000001f5: d9 00 00 00 01 B mov $r9 0x1000000 000001fa: ff a9 95 B or $r9 $r10 $r9 000001fd: 4f 00 60 mov $r15 0x6000 ; 00000200: fa f9 00 iowr I[$r15] $r9 ; CODE_INDEX = r10 | AUTO_INC_WRITE | ((r14) ? SECRET : 0) 00000203: b2 0a mov b32 $r10 $r0 00000205: 7e 4f 02 00 lcall 0x24f ; memcpy_d2i(src=r10, len=r11, dst=r12) 00000209: fb 01 mpopret $r0 // memcpy_i2d(dst=r10, src=r11, len=r12) CODE_INDEX = r11 | 0x2000000; // AUTO_INC_READ for (u32 r14 = 0; r14 < r12; r14 += 4) { r10[r14] = CODE; } 0000020b: d9 00 00 00 02 C mov $r9 0x2000000 00000210: fd b9 05 or $r11 $r9 00000213: 49 00 60 mov $r9 0x6000 00000216: fa 9b 00 iowr I[$r9] $r11 ; CODE_INDEX = r11 | 0x2000000 00000219: bd e4 clear b32 $r14 ; r14 = 0 0000021b: 4b 00 61 mov $r11 0x6100 0000021e: bd d4 clear b32 $r13 ; r13 = 0 00000220: 3e 30 02 00 lbra 0x230 00000224: ff bd ff B iord $r15 I[$r11+$r13*0x4] ; r15 = CODE 00000227: 95 e9 02 shr b32 $r9 $r14 0x2 ; r9 = r14 / 2 0000022a: 90 ee 04 add b32 $r14 $r14 0x4 ; r14 += 4 0000022d: bc af 99 st b32 D[$r10+$r9*0x4] $r15 ; [r10 + r9 * 4] = r15 00000230: a6 ec B cmp b32 $r14 $r12 00000232: f4 08 f2 bra b 0x224 00000235: f8 00 ret // memcpy_d2d(dst=r10, src=r11, len=r12) 00000237: 3e 48 02 00 C lbra 0x248 0000023b: bf bf B ld b32 $r15 D[$r11] 0000023d: b6 b0 04 add b32 $r11 0x4 00000240: b6 c2 04 sub b32 $r12 0x4 00000243: a0 af st b32 D[$r10] $r15 00000245: b6 a0 04 add b32 $r10 0x4 00000248: b3 c4 00 f3 B bra b32 $r12 0x0 ne 0x23b 0000024c: f8 00 ret ; for some reason there is this extra byte here 0000024e: 01 // memcpy_d2i(src=r10, len=r11, dst=r12) // caller sets CODE_INDEX to initial page offset 0000024f: f9 32 mpush $r3 00000251: 4d 00 61 mov $r13 0x6100 ; CODE 00000254: 4e 00 62 mov $r14 0x6200 ; CODE_VIRT_ADDR 00000257: 3e 82 02 00 lbra 0x282 0000025b: c4 c0 ff B and $r0 $r12 0xff 0000025e: f4 0b 2a bra e 0x288 00000261: 98 a0 00 B ld b32 $r0 D[$r10] 00000264: 98 a1 01 ld b32 $r1 D[$r10+0x4] 00000267: 98 a2 02 ld b32 $r2 D[$r10+0x8] 0000026a: 98 a3 03 ld b32 $r3 D[$r10+0xc] 0000026d: f6 d0 00 iowr I[$r13] $r0 00000270: f6 d1 00 iowr I[$r13] $r1 00000273: f6 d2 00 iowr I[$r13] $r2 00000276: f6 d3 00 iowr I[$r13] $r3 00000279: b6 a0 10 add b32 $r10 0x10 0000027c: b6 b2 10 sub b32 $r11 0x10 0000027f: b6 c0 10 add b32 $r12 0x10 00000282: b3 b4 00 d9 B bra b32 $r11 0x0 ne 0x25b 00000286: fb 31 mpopret $r3 00000288: 95 c0 08 B shr b32 $r0 $r12 0x8 0000028b: f6 e0 00 iowr I[$r14] $r0 ; write next page base and continue 0000028e: 3e 61 02 00 lbra 0x261 ; this shit gets copied to 00000019's stack struct TSecLoaderInfo { u8 derived_key[16]; // written by the secure payload and then written back for bpmp to pass to SE u8 field_10[16]; // mac of unauthenticated code (which loads secure_loader). checked by secure_loader u8 field_20[16]; // used for auth of secure_loader code pages u8 field_30[16]; // used for auth of secure_payload code pages u8 field_40[16]; // IV to decrypt secure_payload u8 key_name_0[16]; // arg0 for secure_payload(cmd=1) u8 key_name_1[16]; // arg0 for secure_payload(cmd=2) u32 secure_loader_offset; // points to this info header (consumes 0x100 bytes). secure_loader relocated here u32 secure_loader_len; // size of secure_loader code after this 0x100 byte header u32 secure_payload_len; }; 00000300 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000310 f1 40 c7 6e 6c 0c 6d 59 a8 26 44 ca d0 85 2f f1 |.@.nl.mY.&D.../.| 00000320 9c 8b 75 d3 df 0b f0 6c 95 fc 91 c0 76 1e f0 62 |..u....l....v..b| 00000330 89 2a 36 22 8d 49 e0 48 4d 48 0c b0 ac da 02 34 |.*6".I.HMH.....4| 00000340 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................| 00000350 48 4f 56 49 5f 45 4b 53 5f 30 31 00 00 00 00 00 |HOVI_EKS_01.....| 00000360 48 4f 56 49 5f 43 4f 4d 4d 4f 4e 5f 30 31 00 00 |HOVI_COMMON_01..| 00000370 00 03 00 00 00 06 00 00 00 05 00 00 // u32 secure_loader_thunk(TSecLoaderInfo *info=r10, cmd=r11, skip_load_and_decrypt=r12) ; this is just a thunk that (tries to) sanitize state before running secure code ; originally @ I:0x400, gets copied twice and winds up executed @ I:0x300 00000300: f4 32 10 bclr $flags ie0 ; some re-init code since this can be called by attackers! 00000303: f4 32 11 bclr $flags ie1 00000306: f4 32 12 bclr $flags ie2 00000309: f4 3c 80 cxset 0x80 ; dma_override(type=0b100, count=0) ; clear overrides? 0000030c: fe ae 01 mov $r14 $cauth 0000030f: f0 ea 13 bclr $r14 0x13 00000312: fe ea 00 mov $cauth $r14 ; cauth &= ~(1 << 19) 00000315: 0e 00 mov $r14 0x0 00000317: fe eb 00 mov $xtargets $r14 ; xtargets = 0 0000031a: f8 03 xdwait 0000031c: f8 07 xcwait 0000031e: f4 3c 02 cxset 0x2 ; dma_override(type=crypto_reg, count=2) 00000321: 0e 00 mov $r14 0x0 00000323: fa ee 06 xdst $r14 $r14 ; $c0 = ? 00000326: f8 03 xdwait 00000328: f5 3c 00 ac cxor $c0 $c0 0000032c: f5 3c 01 84 cmov $c1 $c0 00000330: f5 3c 02 84 cmov $c2 $c0 00000334: f5 3c 03 84 cmov $c3 $c0 00000338: f5 3c 04 84 cmov $c4 $c0 0000033c: f5 3c 05 84 cmov $c5 $c0 00000340: f5 3c 07 84 cmov $c7 $c0 00000344: 8e 00 0e 02 mov $r14 0x20e00 00000348: cf ef 00 iord $r15 I[$r14] 0000034b: f0 fa 10 bclr $r15 0x10 0000034e: fa ef 00 iowr I[$r14] $r15 ; 0x20e00 &= ~0x10 00000351: 8e 00 06 01 mov $r14 0x10600 00000355: cf ef 00 iord $r15 I[$r14] 00000358: f0 f9 00 bset $r15 0x0 0000035b: fa ef 00 iowr I[$r14] $r15 ; 0x10600 |= 1 0000035e: cf ef 00 B iord $r15 I[$r14] 00000361: f0 f4 02 and $r15 0x2 00000364: f4 0b fa bra e 0x35e ; while (0x10600 & 2) == 0 00000367: 4e 00 42 mov $r14 0x4200 0000036a: cf ee 00 iord $r14 I[$r14] ; UC_CAPS 0000036d: b6 e5 09 shr b32 $r14 0x9 00000370: f1 e4 ff 01 and $r14 0x1ff 00000374: b6 e4 08 shl b32 $r14 0x8 ; r14 = falcon data segment size 00000377: fe 4f 01 mov $r15 $sp 0000037a: a4 fe cmpu b32 $r15 $r14 0000037c: f4 18 51 bra ae 0x3cd ; if (sp >= DATA_SEG_SIZE) exit; 0000037f: b1 f4 00 08 cmpu b32 $r15 0x800 00000383: f4 08 4a bra b 0x3cd ; if (sp < 0x800) exit; 00000386: f9 82 mpush $r8 00000388: 7e cf 03 00 lcall 0x3cf ; call the real entrypoint @ secure_loader 0000038c: fb 80 mpop $r8 0000038e: f5 3c 00 e0 ??? [unknown: 00 00 00 e0] [unknown instruction] ; this is some "cocmd" insn -> "mwk: chmod IIRC, it modifies the ACLs" 00000392: f5 3c 00 ac cxor $c0 $c0 ; we're done... clear some state 00000396: f5 3c 11 ac cxor $c1 $c1 0000039a: f5 3c 22 ac cxor $c2 $c2 0000039e: f5 3c 33 ac cxor $c3 $c3 000003a2: f5 3c 44 ac cxor $c4 $c4 000003a6: f5 3c 55 ac cxor $c5 $c5 000003aa: f5 3c 66 ac cxor $c6 $c6 000003ae: f5 3c 77 ac cxor $c7 $c7 000003b2: 09 00 mov $r9 0x0 000003b4: 0b 00 mov $r11 0x0 000003b6: 0c 00 mov $r12 0x0 000003b8: 0d 00 mov $r13 0x0 000003ba: 0e 00 mov $r14 0x0 000003bc: 0f 00 mov $r15 0x0 000003be: fc f0 pop $r15 ; pop THE RETURN ADDRESS!! 000003c0: 4b 00 03 mov $r11 0x300 000003c3: f0 b3 01 sethi $r11 0x10000 ; confusing disassembler! this is |= (1 << 16) 000003c6: 0c 00 mov $r12 0x0 000003c8: fa bc 00 iowr I[$r11] $r12 ; 0x10300 = 0 000003cb: f9 f4 bra $r15 ; -> return..? 000003cd: f8 02 B exit // u32 secure_loader(TSecLoaderInfo *info=r10, cmd=r11, skip_load_and_decrypt=r12) 000003cf: f4 30 e0 C add $sp -0x20 000003d2: f9 42 mpush $r4 ; sp -= 0x14 000003d4: b2 c4 mov b32 $r4 $r12 000003d6: 98 ac 1c ld b32 $r12 D[$r10+TSecLoaderInfo.secure_loader_offset] 000003d9: f4 30 fc add $sp -0x4 000003dc: b2 a2 mov b32 $r2 $r10 000003de: b2 b3 mov b32 $r3 $r11 000003e0: bd a4 clear b32 $r10 000003e2: bd b4 clear b32 $r11 ; copy all insn memory before the secure_loader to D:0 000003e4: 7e 3f 05 00 lcall 0x53f ; memcpy_i2d(dst=0, src=0, len=secure_loader_offset) 000003e8: bd a4 clear b32 $r10 000003ea: bd b4 clear b32 $r11 000003ec: 7e 47 06 00 lcall 0x647 ; key_init(hdr_type=CODE_SIG, key_type=ENCRYPT) 000003f0: 98 21 1c ld b32 $r1 D[$r2+TSecLoaderInfo.secure_loader_offset] 000003f3: 09 f0 mov $r9 -0x10 000003f5: fe 40 01 mov $r0 $sp 000003f8: 90 00 28 add b32 $r0 $r0 0x28 000003fb: b2 1b mov b32 $r11 $r1 000003fd: fd 09 04 and $r0 $r9 00000400: b2 0a mov b32 $r10 $r0 ; unauth_code_mac = (sp + 0x28) & ~0xf 00000402: 7e 88 06 00 lcall 0x688 ; crypto_688(unauth_code_mac{local}, secure_loader_offset) 00000406: bd 94 clear b32 $r9 00000408: b2 1b mov b32 $r11 $r1 0000040a: b2 0c mov b32 $r12 $r0 0000040c: bd a4 clear b32 $r10 0000040e: b2 0d mov b32 $r13 $r0 00000410: 0e 02 mov $r14 0x2 00000412: b0 91 00 st b32 D[$sp] $r9 ; arg on the stack ; crypto_6b9(buf_in=0, buf_in_len=secure_loader_offset, iv=unauth_code_mac, buf_out=unauth_code_mac, mode=2, some_bool=0) 00000415: 7e b9 06 00 lcall 0x6b9 00000419: b2 0a mov b32 $r10 $r0 0000041b: 90 2b 10 add b32 $r11 $r2 0x10 ; TSecLoaderInfo.field_10 0000041e: 0c 10 mov $r12 0x10 00000420: 7e 9a 05 00 lcall 0x59a ; r10 = memcmp(p1=unauth_code_mac{local}, p2=&info->field_10, len=0x10) 00000424: b3 a0 00 0d bra b32 $r10 0x0 e 0x431 00000428: da ef be ad de mov $r10 0xdeadbeef 0000042d: 3e f0 04 00 lbra 0x4f0 ; if mac failure, return 0xdeadbeef 00000431: 49 00 42 B mov $r9 0x4200 ; UC_CAPS 00000434: cf 99 00 iord $r9 I[$r9] ; useless code? 00000437: 98 2f 1d ld b32 $r15 D[$r2+TSecLoaderInfo.secure_loader_len] 0000043a: 98 29 1c ld b32 $r9 D[$r2+TSecLoaderInfo.secure_loader_offset] 0000043d: bc f9 10 add b32 $r1 $r15 $r9 ; r1 = 0x600 + 0x300 = 0x900 00000440: b3 44 00 4c bra b32 $r4 0x0 ne 0x48c ; skip load_and_decrypt_payload? 00000444: 98 20 1e ld b32 $r0 D[$r2+TSecLoaderInfo.secure_payload_len] ; 0x500 00000447: fe 49 01 mov $r9 $sp 0000044a: a6 09 cmp b32 $r0 $r9 0000044c: f4 18 40 bra ae 0x48c ; if (secure_payload_len >= sp): skip load_and_decrypt_payload ??? load_and_decrypt_payload: ; copy payload to D:0, decrypt it, copy as secret to I:0x900, then clear the copy at D:0 0000044f: b2 0c mov b32 $r12 $r0 00000451: b8 1b 00 01 00 add b32 $r11 $r1 0x100 ; r11 = 0xa00 (payload_addr) 00000456: 7e 3f 05 00 lcall 0x53f ; memcpy_i2d(dst=0, src=0xa00, len=secure_payload_len) 0000045a: 0a 01 mov $r10 0x1 0000045c: b2 ab mov b32 $r11 $r10 0000045e: 7e 47 06 00 lcall 0x647 ; key_init(hdr_type=CODE_ENC, key_type=DECRYPT) 00000462: b2 0b mov b32 $r11 $r0 00000464: 90 2c 40 add b32 $r12 $r2 0x40 ; TSecLoaderInfo.field_40 00000467: bd d4 clear b32 $r13 00000469: bd e4 clear b32 $r14 0000046b: bd a4 clear b32 $r10 0000046d: b0 41 00 st b32 D[$sp] $r4 ; always zero. arg on the stack ; crypto_6b9(buf_in=0, buf_in_len=secure_payload_len, iv=info->field_40, buf_out=0, mode=0, some_bool=0) 00000470: 7e b9 06 00 lcall 0x6b9 00000474: b2 1a mov b32 $r10 $r1 00000476: bd b4 clear b32 $r11 00000478: b2 0c mov b32 $r12 $r0 0000047a: b2 1d mov b32 $r13 $r1 0000047c: 0e 01 mov $r14 0x1 0000047e: 7e f6 04 00 lcall 0x4f6 ; memcpy_d2i_ex(dst_page_offset=0x900, src=0, len=secure_payload_len, dst=0x900, is_secret=1) 00000482: b2 0c mov b32 $r12 $r0 00000484: bd a4 clear b32 $r10 00000486: bd b4 clear b32 $r11 00000488: 7e 6b 05 00 lcall 0x56b ; memset(dst=0, val=0, len=secure_payload_len) auth_and_exec_payload: 0000048c: f4 3c 02 B cxset 0x2 ; dma_override(type=crypto_reg, count=2) 0000048f: 8f 00 00 06 mov $r15 0x60000 00000493: 90 29 30 add b32 $r9 $r2 0x30 ; TSecLoaderInfo.field_30 00000496: fd 9f 05 or $r9 $r15 00000499: bd f4 clear b32 $r15 0000049b: fa f9 06 xdst $r15 $r9 ; crypto_reg_load(crypto_reg=$c6, local_address=&info->field_30) 0000049e: f8 03 xdwait 000004a0: fe a4 01 mov $r4 $cauth ; save cauth 000004a3: 98 29 1e ld b32 $r9 D[$r2+TSecLoaderInfo.secure_payload_len] 000004a6: 95 1f 08 shr b32 $r15 $r1 0x8 000004a9: b6 94 10 shl b32 $r9 0x10 000004ac: fd f9 05 or $r15 $r9 000004af: fe fa 00 mov $cauth $r15 ; cauth = (secure_payload_len << 16) | (secure_payload_dst >> 8) 000004b2: b3 34 01 0d bra b32 $r3 0x1 ne 0x4bf handle_cmd_1: 000004b6: b2 3b mov b32 $r11 $r3 000004b8: 90 2a 50 add b32 $r10 $r2 0x50 ; TSecLoaderInfo.key_name_0 000004bb: 3e dd 04 00 lbra 0x4dd ; status = secure_payload(&info->key_name_0, cmd=1) 000004bf: b3 34 02 0d B bra b32 $r3 0x2 ne 0x4cc handle_cmd_2: 000004c3: b2 3b mov b32 $r11 $r3 000004c5: 90 2a 60 add b32 $r10 $r2 0x60 ; TSecLoaderInfo.key_name_1 000004c8: 3e dd 04 00 lbra 0x4dd ; status = secure_payload(&info->key_name_1, cmd=2) 000004cc: b3 30 03 0d B bra b32 $r3 0x3 e 0x4d9 handle_invalid_cmd: 000004d0: d0 d0 d0 d0 d0 mov $r0 0xd0d0d0d0 000004d5: 3e e1 04 00 lbra 0x4e1 ; status = 0xd0d0d0d0; handle_cmd_3: 000004d9: b2 3b B mov b32 $r11 $r3 000004db: b2 2a mov b32 $r10 $r2 000004dd: f9 15 B call $r1 ; status = secure_payload(info, cmd=3) 000004df: b2 a0 mov b32 $r0 $r10 000004e1: b2 2a B mov b32 $r10 $r2 000004e3: bd b4 clear b32 $r11 000004e5: 0c 7c mov $r12 0x7c ; clear our copy of the info header 000004e7: 7e 6b 05 00 lcall 0x56b ; memset(dst=info, val=0, len=0x7c) 000004eb: fe 4a 00 mov $cauth $r4 ; restore cauth 000004ee: b2 0a mov b32 $r10 $r0 ; return status 000004f0: f4 30 04 B add $sp 0x4 000004f3: fb 45 20 mpopaddret $r4 0x20 // memcpy_d2i_ex(dst_page_offset=r10, src=r11, len=r12, dst=r13, is_secret=r14) 000004f6: f9 02 C mpush $r0 000004f8: b2 b0 mov b32 $r0 $r11 000004fa: b2 cb mov b32 $r11 $r12 000004fc: b2 dc mov b32 $r12 $r13 000004fe: 33 00 00 0a bra b8 $r0 0x0 e 0x508 00000502: f8 02 exit 00000504: 3e 04 05 00 B lbra 0x504 00000508: 33 b0 00 0a B bra b8 $r11 0x0 e 0x512 0000050c: f8 02 exit 0000050e: 3e 0e 05 00 B lbra 0x50e 00000512: 33 c0 00 0a B bra b8 $r12 0x0 e 0x51c 00000516: f8 02 exit 00000518: 3e 18 05 00 B lbra 0x518 0000051c: b3 e0 00 0d B bra b32 $r14 0x0 e 0x529 00000520: d9 00 00 00 11 mov $r9 0x11000000 00000525: 3e 2e 05 00 lbra 0x52e 00000529: d9 00 00 00 01 B mov $r9 0x1000000 0000052e: ff a9 95 B or $r9 $r10 $r9 00000531: 4f 00 60 mov $r15 0x6000 ; CODE_INDEX 00000534: fa f9 00 iowr I[$r15] $r9 00000537: b2 0a mov b32 $r10 $r0 00000539: 7e 88 08 00 lcall 0x888 ; memcpy_d2i(src=r10, len=r11, dst=r12) 0000053d: fb 01 mpopret $r0 // memcpy_i2d(dst=r10, src=r11, len=r12) 0000053f: d9 00 00 00 02 C mov $r9 0x2000000 00000544: fd b9 05 or $r11 $r9 00000547: 49 00 60 mov $r9 0x6000 ; CODE_INDEX 0000054a: fa 9b 00 iowr I[$r9] $r11 0000054d: bd e4 clear b32 $r14 0000054f: 4b 00 61 mov $r11 0x6100 ; CODE 00000552: bd d4 clear b32 $r13 00000554: 3e 64 05 00 lbra 0x564 00000558: ff bd ff B iord $r15 I[$r11+$r13*0x4] 0000055b: 95 e9 02 shr b32 $r9 $r14 0x2 0000055e: 90 ee 04 add b32 $r14 $r14 0x4 00000561: bc af 99 st b32 D[$r10+$r9*0x4] $r15 00000564: a6 ec B cmp b32 $r14 $r12 00000566: f4 08 f2 bra b 0x558 00000569: f8 00 ret // memset(dst=r10, val=r11, len=r12) 0000056b: 3e 81 05 00 C lbra 0x581 0000056f: b5 ab 00 B st b32 D[$r10] $r11 00000572: b5 ab 01 st b32 D[$r10+0x4] $r11 00000575: b5 ab 02 st b32 D[$r10+0x8] $r11 00000578: b5 ab 03 st b32 D[$r10+0xc] $r11 0000057b: b6 a0 10 add b32 $r10 0x10 0000057e: b6 c2 10 sub b32 $r12 0x10 00000581: b0 c6 10 B cmp b32 $r12 0x10 00000584: f4 18 eb bra ae 0x56f 00000587: 3e 93 05 00 lbra 0x593 0000058b: a0 ab B st b32 D[$r10] $r11 0000058d: b6 a0 04 add b32 $r10 0x4 00000590: b6 c2 04 sub b32 $r12 0x4 00000593: b3 c4 00 f8 B bra b32 $r12 0x0 ne 0x58b 00000597: f8 00 ret ; another extra 0x01 byte following a ret 00000599: 01 // int memcmp(p1=r10, p2=r11, len=r12) // NOT TIMING INVARIANT 0000059a: 3e b0 05 00 lbra 0x5b0 0000059e: bf ad B ld b32 $r13 D[$r10] 000005a0: bf be ld b32 $r14 D[$r11] 000005a2: a6 de cmp b32 $r13 $r14 000005a4: f4 1b 14 bra ne 0x5b8 000005a7: b6 a0 04 add b32 $r10 0x4 000005aa: b6 b0 04 add b32 $r11 0x4 000005ad: b6 c2 04 sub b32 $r12 0x4 000005b0: b3 c4 00 ee B bra b32 $r12 0x0 ne 0x59e 000005b4: 0a 00 mov $r10 0x0 000005b6: f8 00 ret 000005b8: 0a 01 B mov $r10 0x1 000005ba: f8 00 ret ; again, the floating 0x01 byte... 000005bc: 01 // these xfers are for crypto stuff. size is in bits! // crypto_reg_store(crypto_reg=r10, local_addr=r11) 000005bd: f4 3c 02 C cxset 0x2 ; dma_override(type=crypto_reg, count=2) 000005c0: b6 a4 10 shl b32 $r10 0x10 000005c3: fd ba 05 or $r11 $r10 000005c6: fa bb 05 xdld $r11 $r11 000005c9: f8 03 xdwait 000005cb: f8 00 ret // crypto_reg_load(crypto_reg=r10, local_addr=r11) // read from local_addr into $cX 000005cd: f4 3c 02 C cxset 0x2 ; dma_override(type=crypto_reg, count=2) 000005d0: b6 a4 10 shl b32 $r10 0x10 000005d3: fd ba 05 or $r11 $r10 000005d6: fa bb 06 xdst $r11 $r11 000005d9: f8 03 xdwait 000005db: f8 00 ret // get_type_string(buf=r10, type=r11) 000005dd: c4 a9 0f C and $r9 $r10 0xf 000005e0: f4 0b 09 bra e 0x5e9 000005e3: f8 02 exit ; assert r10 16byte aligned 000005e5: 3e e5 05 00 B lbra 0x5e5 000005e9: b3 b0 00 0c B bra b32 $r11 0x0 e 0x5f5 000005ed: b3 b4 01 3e bra b32 $r11 0x1 ne 0x62b 000005f1: 3e 10 06 00 lbra 0x610 ; if (r11 == 0) { "CODE_SIG_01" 000005f5: d9 43 4f 44 45 B mov $r9 0x45444f43 ; "CODE" 000005fa: a0 a9 st b32 D[$r10] $r9 000005fc: d9 5f 53 49 47 mov $r9 0x4749535f ; "_SIG" 00000601: b5 ab 03 st b32 D[$r10+0xc] $r11 00000604: b5 a9 01 st b32 D[$r10+0x4] $r9 00000607: 89 5f 30 31 mov $r9 0x31305f ; "_01" 0000060b: b5 a9 02 st b32 D[$r10+0x8] $r9 0000060e: f8 00 ret ; } else if (r11 == 1) { "CODE_ENC_01" 00000610: d9 43 4f 44 45 B mov $r9 0x45444f43 ; "CODE" 00000615: a0 a9 st b32 D[$r10] $r9 00000617: d9 5f 45 4e 43 mov $r9 0x434e455f ; "_ENC" 0000061c: b5 a9 01 st b32 D[$r10+0x4] $r9 0000061f: 89 5f 30 31 mov $r9 0x31305f ; "_01" 00000623: b5 a9 02 st b32 D[$r10+0x8] $r9 00000626: bd 94 clear b32 $r9 00000628: b5 a9 03 st b32 D[$r10+0xc] $r9 ; } 0000062b: f8 00 B ret ; unused function? 0000062d: f9 02 mpush $r0 0000062f: b2 b0 mov b32 $r0 $r11 00000631: b2 ab mov b32 $r11 $r10 00000633: 0a 04 mov $r10 0x4 00000635: 7e cd 05 00 lcall 0x5cd ; crypto_reg_load(crypto_reg=$c4, local_addr=r11) 00000639: b3 00 00 08 bra b32 $r0 0x0 e 0x641 0000063d: b3 04 03 08 bra b32 $r0 0x3 ne 0x645 00000641: f5 3c 44 c8 B ckexp $c4 $c4 00000645: fb 01 B mpopret $r0 // key_init(hdr_type=r10, key_type=r11) // hdr_type 0: CODE_SIG, 1: CODE_ENC // key_type 0: ENCRYPT, 1: DECRYPT // leaves the key material in c4, then other funcs use that 00000647: 09 f0 mov $r9 -0x10 00000649: f4 30 e0 add $sp -0x20 0000064c: f9 12 mpush $r1 0000064e: b2 b1 mov b32 $r1 $r11 00000650: fe 40 01 mov $r0 $sp 00000653: b2 ab mov b32 $r11 $r10 ; r11 = hdr_type 00000655: 90 00 18 add b32 $r0 $r0 0x18 00000658: fd 09 04 and $r0 $r9 ; r0 = (sp + 0x18) & ~0xf 0000065b: b2 0a mov b32 $r10 $r0 0000065d: 7e dd 05 00 lcall 0x5dd ; get_type_string(buf=r0{local}, type=hdr_type) 00000661: b2 0b mov b32 $r11 $r0 00000663: bd a4 clear b32 $r10 00000665: 7e cd 05 00 lcall 0x5cd ; crypto_reg_load(crypto_reg=$c0, r0{local}) 00000669: f5 3c 61 c2 csecret $c1 0x26 ; c1 = hw_secrets[0x26]. whatever that means! kfuse data? 0000066d: f5 3c 01 c4 ckeyreg $c1 ; ACTIVE_KEY_REG = c1 00000671: f5 3c 01 d0 cenc $c1 $c0 ; c1 = Aes128EcbEncrypt(key=c1, data=c0) 00000675: f5 3c 11 dc csigenc $c1 $c1 ; c1 = EncryptSig(key=c1) this the sig supplied when our code page was auth'd (info.field_20) 00000679: f5 3c 14 84 cmov $c4 $c1 ; c4 = c1 0000067d: b3 10 00 08 bra b32 $r1 0x0 e 0x685 ; check key_type 00000681: f5 3c 44 c8 ckexp $c4 $c4 ; do key expansion if DEC, else skip 00000685: fb 15 20 B mpopaddret $r1 0x20 // crypto_688(buf=r10, in_word=r11) 00000688: f9 02 mpush $r0 0000068a: bd 94 clear b32 $r9 0000068c: b2 a0 mov b32 $r0 $r10 0000068e: a0 a9 st b32 D[$r10] $r9 00000690: b5 a9 02 st b32 D[$r10+0x8] $r9 00000693: b5 a9 01 st b32 D[$r10+0x4] $r9 00000696: 7d b3 hswap b16 $r11 00000698: bd b3 hswap b32 $r11 0000069a: 7d b3 hswap b16 $r11 0000069c: b5 ab 03 st b32 D[$r10+0xc] $r11 ; r10 = 0 || 0 || 0 || bswap32(in_word) 0000069f: 0a 03 mov $r10 0x3 ; input num_bytes = 4 000006a1: b2 0b mov b32 $r11 $r0 000006a3: 7e cd 05 00 lcall 0x5cd ; crypto_reg_load(crypto_reg=$c3, local_addr=buf) 000006a7: f5 3c 04 c4 ckeyreg $c4 000006ab: f5 3c 35 d0 cenc $c5 $c3 ; c5 = Aes128EcbEncrypt(key=c4, data=c3) 000006af: 0a 05 mov $r10 0x5 ; output num_bytes = 16 000006b1: b2 0b mov b32 $r11 $r0 000006b3: 7e bd 05 00 lcall 0x5bd ; crypto_reg_store(crypto_reg=$c5, local_addr=buf) 000006b7: fb 01 mpopret $r0 // crypto_6b9(buf_in=r10, buf_in_len=r11, iv=r12, buf_out=r13, mode=r14, some_bool=[sp]) 000006b9: f9 52 mpush $r5 000006bb: b2 b3 mov b32 $r3 $r11 000006bd: b2 d4 mov b32 $r4 $r13 000006bf: b2 cb mov b32 $r11 $r12 000006c1: b2 e2 mov b32 $r2 $r14 000006c3: b4 50 07 ld b32 $r5 D[$sp+0x1c] 000006c6: b2 a1 mov b32 $r1 $r10 000006c8: b2 d0 mov b32 $r0 $r13 000006ca: b3 34 00 0a bra b32 $r3 0x0 ne 0x6d4 ; assert buf_in_len != 0 000006ce: f8 02 exit 000006d0: 3e d0 06 00 B lbra 0x6d0 000006d4: c4 39 0f B and $r9 $r3 0xf 000006d7: f4 0b 09 bra e 0x6e0 ; assert (buf_in_len & 0xf) == 0 000006da: f8 02 exit 000006dc: 3e dc 06 00 B lbra 0x6dc 000006e0: c4 a9 0f B and $r9 $r10 0xf 000006e3: f4 0b 09 bra e 0x6ec ; assert (buf_in & 0xf) == 0 000006e6: f8 02 exit 000006e8: 3e e8 06 00 B lbra 0x6e8 000006ec: c4 49 0f B and $r9 $r4 0xf 000006ef: f4 0b 09 bra e 0x6f8 ; assert (buf_out & 0xf) == 0 000006f2: f8 02 exit 000006f4: 3e f4 06 00 B lbra 0x6f4 000006f8: b3 b0 00 0e B bra b32 $r11 0x0 e 0x706 ; if present, use 16byte iv set_iv_to_input: 000006fc: 0a 05 mov $r10 0x5 000006fe: 7e cd 05 00 lcall 0x5cd ; crypto_reg_load(crypto_reg=$c5, local_addr=iv) 00000702: 3e 0a 07 00 lbra 0x70a set_iv_zero: 00000706: f5 3c 55 ac B cxor $c5 $c5 set_active_key_c4: 0000070a: f5 3c 04 c4 B ckeyreg $c4 mode_dispatch: 0000070e: b3 20 02 50 bra b32 $r2 0x2 e 0x75e 00000712: b0 26 02 cmp b32 $r2 0x2 00000715: f4 0c 10 bra a 0x725 00000718: b3 20 00 2a bra b32 $r2 0x0 e 0x742 0000071c: b3 2d 01 6a 01 bra b32 $r2 0x1 ne 0x886 00000721: 3e 32 07 00 lbra 0x732 00000725: b3 20 03 5d B bra b32 $r2 0x3 e 0x782 00000729: b3 2d 04 5d 01 bra b32 $r2 0x4 ne 0x886 0000072e: 3e 72 07 00 lbra 0x772 00000732: f5 3c 40 94 B cs0begin 0x4 00000736: f5 3c 03 88 cxsin $c3 0000073a: f5 3c 53 ac cxor $c3 $c5 0000073e: 3e 7a 07 00 lbra 0x77a 00000742: f5 3c 50 94 B cs0begin 0x5 00000746: f5 3c 03 88 cxsin $c3 0000074a: f5 3c 32 d4 cdec $c2 $c3 0000074e: f5 3c 25 ac cxor $c5 $c2 00000752: f5 3c 05 8c cxsout $c5 00000756: f5 3c 35 84 cmov $c5 $c3 0000075a: 3e 75 08 00 lbra 0x875 0000075e: f5 3c 30 94 B cs0begin 0x3 00000762: f5 3c 03 88 cxsin $c3 00000766: f5 3c 35 ac cxor $c5 $c3 0000076a: f5 3c 55 d0 cenc $c5 $c5 0000076e: 3e 75 08 00 lbra 0x875 00000772: f5 3c 30 94 B cs0begin 0x3 00000776: f5 3c 03 88 cxsin $c3 0000077a: f5 3c 35 d0 B cenc $c5 $c3 0000077e: 3e 8e 07 00 lbra 0x78e 00000782: f5 3c 30 94 B cs0begin 0x3 00000786: f5 3c 03 88 cxsin $c3 0000078a: f5 3c 35 d4 cdec $c5 $c3 0000078e: f5 3c 05 8c B cxsout $c5 00000792: 3e 75 08 00 lbra 0x875 00000796: 95 3f 04 B shr b32 $r15 $r3 0x4 00000799: b0 f6 10 cmp b32 $r15 0x10 0000079c: f4 0d 05 bra be 0x7a1 0000079f: 0f 10 mov $r15 0x10 000007a1: 92 f9 01 B sub b32 $r9 $r15 0x1 000007a4: fd 9f 04 and $r9 $r15 000007a7: f4 0b 05 bra e 0x7ac 000007aa: 0f 01 mov $r15 0x1 000007ac: 94 fe 04 B shl b32 $r14 $r15 0x4 000007af: ff 01 f5 or $r15 $r0 $r1 000007b2: 92 e9 01 sub b32 $r9 $r14 0x1 000007b5: fd 9f 04 and $r9 $r15 000007b8: f4 1b 68 bra ne 0x820 000007bb: b3 e0 40 41 bra b32 $r14 0x40 e 0x7fc 000007bf: b1 e6 40 00 cmp b32 $r14 0x40 000007c3: f4 0c 0b bra a 0x7ce 000007c6: b3 e4 20 5a bra b32 $r14 0x20 ne 0x820 000007ca: 3e 0e 08 00 lbra 0x80e 000007ce: b3 ea 80 00 1c B bra b32 $r14 0x80 e 0x7ea 000007d3: b3 ee 00 01 4d bra b32 $r14 0x100 ne 0x820 000007d8: b2 1f mov b32 $r15 $r1 000007da: f0 f3 06 sethi $r15 0x60000 000007dd: b2 09 mov b32 $r9 $r0 000007df: f0 93 06 sethi $r9 0x60000 000007e2: f5 3c 00 99 cs0exec 0x10 000007e6: 3e 30 08 00 lbra 0x830 000007ea: b2 1f B mov b32 $r15 $r1 000007ec: f0 f3 05 sethi $r15 0x50000 000007ef: b2 09 mov b32 $r9 $r0 000007f1: f0 93 05 sethi $r9 0x50000 000007f4: f5 3c 80 98 cs0exec 0x8 000007f8: 3e 30 08 00 lbra 0x830 000007fc: b2 1f B mov b32 $r15 $r1 000007fe: f0 f3 04 sethi $r15 0x40000 00000801: b2 09 mov b32 $r9 $r0 00000803: f0 93 04 sethi $r9 0x40000 00000806: f5 3c 40 98 cs0exec 0x4 0000080a: 3e 30 08 00 lbra 0x830 0000080e: b2 1f B mov b32 $r15 $r1 00000810: f0 f3 03 sethi $r15 0x30000 00000813: b2 09 mov b32 $r9 $r0 00000815: f0 93 03 sethi $r9 0x30000 00000818: f5 3c 20 98 cs0exec 0x2 0000081c: 3e 30 08 00 lbra 0x830 00000820: b2 1f B mov b32 $r15 $r1 00000822: f0 f3 02 sethi $r15 0x20000 00000825: b2 09 mov b32 $r9 $r0 00000827: f0 93 02 sethi $r9 0x20000 0000082a: f5 3c 10 98 cs0exec 0x1 0000082e: 0e 10 mov $r14 0x10 00000830: b3 54 01 0b B bra b32 $r5 0x1 ne 0x83b 00000834: f4 3c a1 cxset 0xa1 ; dma_override(type=0b101, count=1) 00000837: 3e 3e 08 00 lbra 0x83e 0000083b: f4 3c 21 B cxset 0x21 ; dma_override(type=0b001, count=1) 0000083e: fa ff 06 B xdst $r15 $r15 00000841: b3 20 02 1e bra b32 $r2 0x2 e 0x85f 00000845: b3 54 01 0b bra b32 $r5 0x1 ne 0x850 00000849: f4 3c a2 cxset 0xa2 ; dma_override(type=0b101, count=2) 0000084c: 3e 53 08 00 lbra 0x853 00000850: f4 3c 22 B cxset 0x22 ; dma_override(type=0b001, count=2) 00000853: fa 99 05 B xdld $r9 $r9 00000856: f8 03 xdwait 00000858: bc 0e 00 add b32 $r0 $r0 $r14 0000085b: 3e 6f 08 00 lbra 0x86f 0000085f: b3 54 01 0b B bra b32 $r5 0x1 ne 0x86a 00000863: f4 3c a1 cxset 0xa1 ; dma_override(type=0b101, count=1) 00000866: 3e 6d 08 00 lbra 0x86d 0000086a: f4 3c 21 B cxset 0x21 ; dma_override(type=0b001, count=1) 0000086d: f8 03 B xdwait 0000086f: bc 1e 10 B add b32 $r1 $r1 $r14 00000872: bb 3e 02 sub b32 $r3 $r14 00000875: b3 3d 00 21 ff B bra b32 $r3 0x0 ne 0x796 0000087a: b3 24 02 0c bra b32 $r2 0x2 ne 0x886 0000087e: b2 4b mov b32 $r11 $r4 00000880: 0a 05 mov $r10 0x5 00000882: 7e bd 05 00 lcall 0x5bd ; crypto_reg_store(crypto_reg=$c5, local_addr=r11) 00000886: fb 51 B mpopret $r5 // memcpy_d2i(src=r10, len=r11, dst=r12) 00000888: f9 32 mpush $r3 0000088a: 4d 00 61 mov $r13 0x6100 ; CODE 0000088d: 4e 00 62 mov $r14 0x6200 ; CODE_VIRT_ADDR 00000890: 3e bb 08 00 lbra 0x8bb 00000894: c4 c0 ff B and $r0 $r12 0xff 00000897: f4 0b 2a bra e 0x8c1 0000089a: 98 a0 00 B ld b32 $r0 D[$r10] 0000089d: 98 a1 01 ld b32 $r1 D[$r10+0x4] 000008a0: 98 a2 02 ld b32 $r2 D[$r10+0x8] 000008a3: 98 a3 03 ld b32 $r3 D[$r10+0xc] 000008a6: f6 d0 00 iowr I[$r13] $r0 000008a9: f6 d1 00 iowr I[$r13] $r1 000008ac: f6 d2 00 iowr I[$r13] $r2 000008af: f6 d3 00 iowr I[$r13] $r3 000008b2: b6 a0 10 add b32 $r10 0x10 000008b5: b6 b2 10 sub b32 $r11 0x10 000008b8: b6 c0 10 add b32 $r12 0x10 000008bb: b3 b4 00 d9 B bra b32 $r11 0x0 ne 0x894 000008bf: fb 31 mpopret $r3 000008c1: 95 c0 08 B shr b32 $r0 $r12 0x8 000008c4: f6 e0 00 iowr I[$r14] $r0 000008c7: 3e 9a 08 00 lbra 0x89a ; encrypted secure_payload 00000a00 ca e0 f8 6a d9 72 ba 7b eb 25 b3 a8 42 98 75 38 |...j.r.{.%..B.u8| 00000a10 25 ed 0c 3f 80 56 22 01 8a 19 87 8a fe 6d 9e 4f |%..?.V"......m.O| 00000a20 dd 80 11 e9 5a 48 40 c4 1a ed c2 7f ed 7f b3 43 |....ZH@........C| 00000a30 14 bb 58 53 09 2a 45 12 3a b4 b6 44 6a ef 19 1b |..XS.*E.:..Dj...| 00000a40 55 2a 99 69 68 06 5c 1b ab df c2 00 ee a9 e1 b0 |U*.ih.\.........| 00000a50 c6 aa 5c 54 3a 5d 7d 7d 79 30 50 69 b5 61 be 1d |..\T:]}}y0Pi.a..| 00000a60 6f a3 2e ec f1 95 c6 6d 62 22 43 5c 36 a4 0e c4 |o......mb"C\6...| 00000a70 94 e6 37 4e 41 80 d4 6f 27 80 1c 5e 94 cb d6 d4 |..7NA..o'..^....| 00000a80 6d f7 0f 26 68 6c fa d7 b4 63 23 f7 19 2f b5 49 |m..&hl...c#../.I| 00000a90 87 13 59 d0 be 85 00 9e 1e 7e 07 50 1b bc 5c ec |..Y......~.P..\.| 00000aa0 2b 1a 81 62 02 f3 83 58 cd 9a b4 7a 1e 11 94 3e |+..b...X...z...>| 00000ab0 bf c6 69 fa 41 91 76 c3 4d a4 4e 1a d5 bf 29 37 |..i.A.v.M.N...)7| 00000ac0 36 74 8d 1c 54 89 ec 47 45 3e 20 f4 69 96 25 fe |6t..T..GE> .i.%.| 00000ad0 74 83 64 44 7a 4c 83 a9 b3 c2 1a 1c a9 59 e9 99 |t.dDzL.......Y..| 00000ae0 89 ba a3 8f ed 26 b6 f7 a2 f4 b2 a7 f0 ab ea 7f |.....&..........| 00000af0 ea d2 55 0c 64 36 7b 23 c2 a6 69 86 d4 a3 93 33 |..U.d6{#..i....3| 00000b00 a3 7e 39 ad 6e a3 72 76 b4 b0 82 b4 67 30 8a 48 |.~9.n.rv....g0.H| 00000b10 9e dc 94 b3 29 85 22 ca 7b 55 24 33 9c 01 a2 0d |....).".{U$3....| 00000b20 10 06 6f f9 01 7a 23 0f 99 37 9f bb 2b a4 3a fc |..o..z#..7..+.:.| 00000b30 a4 a0 d5 06 b4 e0 61 44 01 48 b0 75 3f ac a1 25 |......aD.H.u?..%| 00000b40 4b 85 bf b7 a4 21 f2 82 09 2e 72 61 c7 69 92 11 |K....!....ra.i..| 00000b50 a6 81 2f e1 c2 e8 aa 41 da 62 a7 a0 6c be 74 a6 |../....A.b..l.t.| 00000b60 cb 9b 20 c4 65 ed fb 3c 3d d0 9a c8 4e b0 91 f5 |.. .e..<=...N...| 00000b70 a9 3f e0 9c 7b 6f 21 78 d2 4f 50 a5 b0 61 05 93 |.?..{o!x.OP..a..| 00000b80 b0 4b 60 98 6d 56 cc 07 a7 d5 61 4c d2 9e 23 0f |.K`.mV....aL..#.| 00000b90 cd d9 bf c8 ef 05 a9 24 72 6d 50 7f f7 be fd bf |.......$rmP.....| 00000ba0 7c a5 df 4d bb 8d f3 05 2a 48 40 88 34 6d e7 d0 ||..M....*H@.4m..| 00000bb0 03 b7 4b b1 db df 09 ff 20 94 c0 3b 10 01 ed c8 |..K..... ..;....| 00000bc0 a9 d2 0f cd 1d 06 92 0f 4c cc 01 c0 e8 d3 d3 5b |........L......[| 00000bd0 34 2e 61 20 dd 2c 09 83 6a e3 3b b4 6d d5 34 99 |4.a .,..j.;.m.4.| 00000be0 7b 22 cd 23 e1 f1 a9 c4 50 07 31 fd 97 18 54 3f |{".#....P.1...T?| 00000bf0 ba 88 70 27 89 b4 74 5a 36 bf 73 37 d3 bc 00 86 |..p'..tZ6.s7....| 00000c00 14 8d 3d e1 30 ac af 6d 72 df 9a 28 b0 98 e7 89 |..=.0..mr..(....| 00000c10 55 88 60 55 48 a1 ef f9 79 15 6b f0 db 48 4b 9f |U.`UH...y.k..HK.| 00000c20 6a ca 6c 29 a2 0c 97 e7 12 05 76 e5 a2 8e ed 15 |j.l)......v.....| 00000c30 83 14 28 39 fc 98 fa 5d 1d 76 9b ab 3f 06 ea 43 |..(9...].v..?..C| 00000c40 f8 09 d5 d6 a2 85 ff 5f 5f d0 41 60 68 9a 76 23 |.......__.A`h.v#| 00000c50 af 18 b8 76 16 3a 8c 83 cd bc 06 5a a7 44 8f 86 |...v.:.....Z.D..| 00000c60 54 73 e4 11 d0 2b 34 85 34 b2 ee 07 83 a1 57 e8 |Ts...+4.4.....W.| 00000c70 0b 83 a6 7d bc 4b 2f ca 5e a0 21 ed 82 6a bd 8d |...}.K/.^.!..j..| 00000c80 91 a6 79 5b 53 d8 09 0d 6a d8 7d f9 2f 0c a2 71 |..y[S...j.}./..q| 00000c90 98 37 c7 93 b9 fc 0c af 24 29 66 cc a9 ed 8a 2b |.7......$)f....+| 00000ca0 cf e2 5a f1 95 ec 27 95 79 2b b3 e5 7b 14 99 a3 |..Z...'.y+..{...| 00000cb0 ca be 0f fe 37 c6 04 a4 61 6f 2a 0f 90 d3 f9 88 |....7...ao*.....| 00000cc0 c3 0c e2 bc 09 20 47 19 53 89 1e e6 18 01 02 51 |..... G.S......Q| 00000cd0 43 ea b3 c0 04 4f a2 53 74 30 41 2b ec c6 54 4f |C....O.St0A+..TO| 00000ce0 65 50 fa 6c f7 d9 bf 45 7c 23 8f 38 3a 89 e0 fd |eP.l...E|#.8:...| 00000cf0 d4 48 71 b8 86 65 87 42 01 00 23 22 b6 e7 08 c3 |.Hq..e.B..#"....| 00000d00 1a c8 c1 4e 69 78 6d 68 c5 9f de 64 85 be 94 52 |...Nixmh...d...R| 00000d10 fb 7c c5 9e 97 4a e3 aa 2c 6c 49 e6 5d af 1e 2c |.|...J..,lI.]..,| 00000d20 a0 29 3c bb f4 94 5f fb 66 49 e7 30 0e 6b e0 9d |.)<..._.fI.0.k..| 00000d30 bf 28 25 e8 97 8f 17 c4 87 f3 95 ce be ad 87 b9 |.(%.............| 00000d40 d1 e4 0c 9e 12 cf f9 9c ac 8c 6f 77 2a 8a b5 b3 |..........ow*...| 00000d50 19 7c ea bf b8 c4 0e e0 0f 73 8a 34 8d a9 73 2d |.|.......s.4..s-| 00000d60 97 cd 72 51 43 82 e9 bc af 4c 34 6c b9 3e ec cc |..rQC....L4l.>..| 00000d70 e3 e5 7d 06 72 a8 8e ee 2c 11 a1 40 eb 20 0f 77 |..}.r...,..@. .w| 00000d80 b1 27 b4 3b 82 b6 ec 85 f6 5b 35 48 e4 46 51 e5 |.'.;.....[5H.FQ.| 00000d90 2a 31 ce e0 e8 04 04 91 d0 db 46 a0 57 19 26 02 |*1........F.W.&.| 00000da0 d6 c6 dd b9 ce c6 cf bf 55 e5 35 96 71 d3 9c d5 |........U.5.q...| 00000db0 e0 a7 ec fe e3 8b 7d 9a 28 32 b5 b0 b7 c8 21 38 |......}.(2....!8| 00000dc0 9e 6e be 08 6f 62 cd ee b0 a1 79 e2 a0 2b 6e 22 |.n..ob....y..+n"| 00000dd0 6b 2b 00 7f 49 57 4a 23 28 99 75 b5 40 01 c7 9f |k+..IWJ#(.u.@...| 00000de0 2d e7 85 1b 5a 4e 55 3c ce d6 c7 7b 85 ec 52 ff |-...ZNU<...{..R.| 00000df0 23 87 38 cf 44 e1 95 bb 9c e5 44 05 3d f6 f1 85 |#.8.D.....D.=...| 00000e00 78 a3 7d 19 44 43 3b d4 fa db 9a bd 81 85 34 fd |x.}.DC;.......4.| 00000e10 ba c7 9b f5 96 1a 73 c1 46 7c 39 ec 37 56 81 ca |......s.F|9.7V..| 00000e20 0e a9 30 7f 82 3c f7 49 85 c7 dc 2e 34 50 78 c1 |..0..<.I....4Px.| 00000e30 da d5 d2 14 b6 d3 05 5c be b8 d9 ca 96 bd 52 8b |.......\......R.| 00000e40 c1 40 41 56 14 0f 16 aa 3e 07 bb 52 d5 1a 94 0f |.@AV....>..R....| 00000e50 5f 53 e5 46 dc 12 b1 74 05 70 6b 16 17 a7 94 ec |_S.F...t.pk.....| 00000e60 c0 5f 5e 0e 88 b1 45 e2 08 19 63 e4 b9 12 0d ca |._^...E...c.....| 00000e70 05 8d 42 64 39 37 3d fb 5c d1 d3 27 e7 c5 67 1b |..Bd97=.\..'..g.| 00000e80 21 61 64 5e a1 5f 6e f6 7b a1 bd 37 35 3a 3a 90 |!ad^._n.{..75::.| 00000e90 8e 65 78 e9 4b 04 87 6f fa be 82 63 12 5d 46 b8 |.ex.K..o...c.]F.| 00000ea0 32 f8 10 67 f9 4b 1f 40 33 f4 b6 50 2d 76 34 bc |2..g.K.@3..P-v4.| 00000eb0 e3 49 ee a7 d5 84 31 4e f3 1e 5b d8 a4 8a f5 12 |.I....1N..[.....| 00000ec0 80 1a 4b c6 ab 16 31 48 23 ea 1b 72 c4 f6 7c 2d |..K...1H#..r..|-| 00000ed0 ef 7a e7 54 65 cc 19 9f f6 7a fe d7 35 de d7 ab |.z.Te....z..5...| 00000ee0 94 7f 7e 5e 47 2a 19 78 95 e2 91 37 bd c9 e9 e9 |..~^G*.x...7....| 00000ef0 9f 55 b8 00 69 c2 b3 50 ea b4 f9 48 f3 d2 78 c6 |.U..i..P...H..x.|