/* hdcp reference (hdcp2) -- named functions * generated by fw/ta_re.py -- do not edit * reference: hdcp2.elf * functions: 102 total in build, 101 named, 1 anonymous * porting tiers: {"DISPATCH": 0, "EXACT": 99, "FUZZY": 0, "MNEM": 0, "ambiguous": 2, "cmd_protos": 0, "comments": 584, "dispatch_conflict": 0, "none": 1, "protos": 99, "relabelled": 0, "types": 1} * * Addresses are omitted and functions are ordered by NAME so that the same * function lines up across versions. See the .index.json sidecar for * name -> address. * * CAUTION on ported names: a name is only an identity claim at tier=EXACT. * At tier=MNEM/FUZZY the bytes differ from the reference, so any ADDRESS or * CONTENT HASH embedded in the name (e.g. *_4025F8, gcp_lib__*) still * refers to the REFERENCE build and does not describe this one. */ /* ==== TA_CreateEntryPoint [tier=EXACT size=16] ==== */ int __fastcall TA_CreateEntryPoint() { bzero_core(result: (_DWORD *)dword_4013AC, a2: 0x1820u); return 0; } /* ==== TA_InvokeCommandEntryPoint [tier=EXACT size=444] ==== */ // GP TA_InvokeCommandEntryPoint - the TA's real command surface. Validates that // params[0] has type 7 (TEE_PARAM_TYPE_MEMREF_INOUT) and that params[0].size <= 0x2817, // then dispatches on commandID. int __fastcall TA_InvokeCommandEntryPoint( int *sessionContext, unsigned int commandID, unsigned int paramTypes, int *params) { void (__fastcall *v4)(int, int); // r4 int v5; // r5 void (__fastcall *v6)(int, int); // r4 struct hdcp_req *v7; // r6 int session; // r0 void (__fastcall *v9)(int, int); // r4 void (__fastcall *v10)(int, int); // r4 unsigned int v11; // r4 bool v12; // zf unsigned int v13; // r0 void (__fastcall *v14)(int, int); // r7 if ( (paramTypes & 0xF) == 7 && params != nullptr ) { // a2 if ( (unsigned int)params[1] > 0x2817 ) { v7 = (struct hdcp_req *)*params; if ( *params != 0 ) // switch 19 cases { // switch jump switch ( v7->cmd_id ) { case 1u: session = hdcp1_create_session(a1: v7->argA, a2: (struct hdcp1_session_req *)v7->argB);// jumptable 00401414 case 1 goto LABEL_26; case 2u: session = hdcp1_destroy_session(a1: (unsigned int *)v7->argA);// jumptable 00401414 case 2 goto LABEL_26; case 3u: session = hdcp1_first_part_authentication( a1: (struct hdcp1_auth_req *)v7->argA, a2: (int *)v7->argB, a3: (unsigned __int8)paramTypes, a4: (int)params); // int goto LABEL_26; case 4u: session = hdcp1_second_part_authentication(a1: (int *)v7->argA, a2: (int *)v7->argB);// jumptable 00401414 case 4 goto LABEL_26; case 5u: session = hdcp1_enable_encryption( a1: (unsigned int *)v7->argA, a2: 10263, a3: (unsigned __int8)paramTypes, a4: (int)params); // jumptable 00401414 case 5 goto LABEL_26; case 6u: session = hdcp1_enable_dp_stream_encryption(a1: (unsigned int *)v7->argA);// jumptable 00401414 case 6 goto LABEL_26; case 7u: session = hdcp1_get_encryption_status( a1: (unsigned int *)v7->argA, a2: v7->argB, a3: (unsigned __int8)paramTypes, a4: (int)params); // unsigned int * goto LABEL_26; case 9u: session = hdcp2_destroy_session(a1: (unsigned int *)v7->argA);// jumptable 00401414 case 9 goto LABEL_26; case 0xBu: session = hdcp2_prepare_process_auth_message(a1: (unsigned int *)v7->argA);// jumptable 00401414 case 11 goto LABEL_26; case 0xCu: session = hdcp2_get_encryption_status( a1: (unsigned int *)v7->argA, a2: (int *)v7->argB, a3: (unsigned __int8)paramTypes, a4: (int)params); // unsigned int * goto LABEL_26; case 0xEu: session = hdcp2_create_session(a1: (__int64 *)v7->argA, a2: (int *)v7->argB);// jumptable 00401414 case 14 goto LABEL_26; case 0xFu: session = hdcp2_process_auth_message_v2(a1: (int *)v7->argA, a2: (struct hdcp2_auth_msg *)v7->argB);// jumptable 00401414 case 15 goto LABEL_26; case 0x10u: session = hdcp2_enable_dp_stream_encryption(a1: (unsigned int *)v7->argA);// jumptable 00401414 case 16 goto LABEL_26; case 0x11u: session = hdcp_close_all_sessions();// jumptable 00401414 case 17 goto LABEL_26; case 0x12u: session = hdcp_set_protection(a1: (int *)v7->argA, a2: (int)v7->argB);// jumptable 00401414 case 18 goto LABEL_26; case 0x13u: session = hdcp_get_srm_status(a1: (int)v7->argB);// jumptable 00401414 case 19 LABEL_26: v11 = session; v12 = session == 0; v5 = 0; v13 = 0; if ( !v12 ) goto LABEL_27; goto LABEL_30; default: v10 = (void (__fastcall *)(int, int))off_401570;// jumptable 00401414 default case, cases 8,10,13 off_401570(a1: 4, a2: 61440); // a2 v10(a1: 4, a2: 0xFFFF); // a2 v10(a1: 4, a2: 0); // a2 v11 = 1; v5 = dword_401574; LABEL_27: v14 = (void (__fastcall *)(int, int))off_401570; off_401570(a1: 4, a2: 61440); // a2 v14(a1: 4, a2: HIWORD(v11)); // a1 v14(a1: 4, a2: (unsigned __int16)v11);// a1 if ( v7->cmd_id <= 0xFFFE ) disp_log_event(a1: 4, a2: (unsigned __int16)v7->cmd_id);// a1 v13 = v11; LABEL_30: v7->status = v13; break; } } else { v9 = (void (__fastcall *)(int, int))off_401570; off_401570(a1: 4, a2: 61440); // a2 v9(a1: 4, a2: 0xFFFF); // a2 v9(a1: 4, a2: 0); // a2 return dword_401574; } } else { v4 = (void (__fastcall *)(int, int))off_401570; off_401570(a1: 4, a2: 61440); // a2 v4(a1: 4, a2: 0xFFFF); // a2 v4(a1: 4, a2: 16); // a2 return dword_401574 + 16; } } else { v6 = (void (__fastcall *)(int, int))off_401570; off_401570(a1: 4, a2: 61440); // a2 v6(a1: 4, a2: 0xFFFF); // a2 v6(a1: 4, a2: 6); // a2 return dword_401574 + 6; } return v5; } /* ==== TA_OpenSessionEntryPoint [tier=EXACT size=4] ==== */ int __fastcall TA_OpenSessionEntryPoint(unsigned int paramTypes, int *params, int *sessionContext) { return 0; } /* ==== buffer_copy_bounded [tier=EXACT size=90] ==== */ int __fastcall buffer_copy_bounded(int *a1, int a2, unsigned int a3, int a4) { int *v4; // r8 int result; // r0 int v6; // r6 char *v7; // r5 unsigned int v8; // r4 char v9; // t1 _BYTE v10[516]; // [sp+0h] [bp-208h] BYREF int v11; // [sp+204h] [bp-4h] v4 = off_4027DC; v11 = *off_4027DC; if ( a3 <= 0x200 ) goto LABEL_4; while ( 1 ) { result = *v4 - v11; if ( *v4 == v11 ) break; ((void (__fastcall *)(int))loc_404338)(a1: result); LABEL_4: v6 = a2; v7 = v10; v8 = a3; bzero(result: &v10[a3], a2: 512 - a3); sub_401058(); // unsigned int while ( v8 != 0 ) { v9 = *v7++; *(_BYTE *)(v6 - 1 + v8--) = v9; } } return result; } /* ==== bzero [tier=EXACT size=68] ==== */ _BYTE *__fastcall bzero(_BYTE *result, unsigned int a2) { int v2; // r12 _BYTE *v3; // r0 if ( a2 >= 4 ) { if ( ((unsigned __int8)result & 3) != 0 ) { v2 = 4 - ((unsigned __int8)result & 3); if ( v2 != 2 ) *result++ = 0; if ( v2 >= 2 ) *(_WORD *)result = 0; } JUMPOUT(0x40118C); } if ( __CFSHL__(a2, 31) ) { *result = 0; v3 = result + 1; *v3 = 0; result = v3 + 1; } if ( (a2 & 1) != 0 ) *result++ = 0; return result; } /* ==== bzero_core [tier=EXACT size=78] ==== */ _DWORD *__fastcall bzero_core(_DWORD *result, unsigned int a2) { bool v2; // cf unsigned int v3; // r1 _DWORD *v4; // r0 int v5; // r1 int v6; // r1 v2 = a2 >= 0x20; v3 = a2 - 32; do { if ( !v2 ) break; *result = 0; result[1] = 0; result[2] = 0; result[3] = 0; v4 = result + 4; *v4 = 0; v4[1] = 0; v4[2] = 0; v4[3] = 0; result = v4 + 4; v2 = v3 >= 0x20; v3 -= 32; } while ( v2 ); v2 = __CFSHL__(v3, 28); v5 = v3 << 28; if ( v2 ) { *result = 0; result[1] = 0; result[2] = 0; result[3] = 0; result += 4; } if ( v5 < 0 ) { *result = 0; result[1] = 0; result += 2; } v2 = __CFSHL__(v5, 2); v6 = 4 * v5; if ( v2 ) *result++ = 0; if ( v6 != 0 ) { if ( v6 < 0 ) { *(_WORD *)result = 0; result = (_DWORD *)((char *)result + 2); } if ( (v6 & 0x40000000) != 0 ) { *(_BYTE *)result = 0; return (_DWORD *)((char *)result + 1); } } return result; } /* ==== ct_memcmp [tier=EXACT size=26] ==== */ int __fastcall ct_memcmp(char *a1, char *a2, int a3) { unsigned __int8 v3; // r3 char v4; // r4 char v5; // t1 char v6; // t1 v3 = 0; while ( a3 != 0 ) { v5 = *a1++; v4 = v5; --a3; v6 = *a2++; v3 |= v4 ^ v6; } return v3; } /* ==== disp_auth_msg_get [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x200. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_auth_msg_get(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_auth_msg_put [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x201. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_auth_msg_put(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_get_link_status [tier=EXACT size=46] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x161. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_get_link_status(int a1, int a2, int a3, int a4) { _DWORD v9[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_compute_ri [tier=EXACT size=36] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x185. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_compute_ri(int a1, int a2, int a3) { _DWORD v8[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_disable [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x189. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_disable(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_enable_encryption [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x187. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_enable_encryption(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_enable_stream_enc [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x188. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_enable_stream_enc(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_init [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x180. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_init(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_read_bksv [tier=EXACT size=36] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x183. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_read_bksv(int a1, int a2, int a3) { _DWORD v8[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_read_caps [tier=EXACT size=36] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x182. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_read_caps(int a1, int a2, int a3) { _DWORD v8[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_read_ri [tier=EXACT size=44] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x186. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_read_ri(int a1, int a2, int a3) { int v8; // [sp+0h] [bp-18h] BYREF bzero_core(result: &v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_read_status [tier=EXACT size=44] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x18E. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_read_status(int a1, int a2, int a3, int a4) { _DWORD v9[3]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_setup [tier=EXACT size=36] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x184. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_setup(int a1, int a2, int a3) { _DWORD v8[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_teardown [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x18F. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_teardown(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_verify_v [tier=EXACT size=38] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x18C. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_verify_v(int a1, int a2, int a3, int a4) { _DWORD v9[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_write_an [tier=EXACT size=38] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x181. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_write_an(int a1, int a2) { int v7; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: &v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp1_write_v [tier=EXACT size=38] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x18A. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp1_write_v(int a1, int a2) { int v7; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: &v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_disable [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A2. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_disable(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_enable_stream_enc [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A6. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_enable_stream_enc(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_init [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A0. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_init(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_msg_state [tier=EXACT size=36] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A1. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_msg_state(int a1, int a2, int a3) { _DWORD v8[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_set_caps [tier=EXACT size=34] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A3. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_set_caps(int a1, int a2) { _DWORD v7[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_set_receiver_id [tier=EXACT size=34] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A4. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_set_receiver_id(int a1, int a2) { _DWORD v7[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_set_topology [tier=EXACT size=44] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A7. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_set_topology(int a1, int a2, int a3, int a4) { _DWORD v9[3]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_stream_manage [tier=EXACT size=34] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A5. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_stream_manage(int a1, int a2) { _DWORD v7[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_hdcp2_teardown [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x1A8. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_hdcp2_teardown(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_link_reset [tier=EXACT size=34] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x160. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_link_reset(int a1, int a2) { _DWORD v7[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_log_event [tier=EXACT size=46] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x208. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_log_event(int a1, int a2) { int v7; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: &v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_revocation_check_ksv [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x307. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_revocation_check_ksv(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_session_open [tier=EXACT size=34] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x103. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_session_open(int a1, int a2) { _DWORD v7[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_srm_check_receiver_id [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x303. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_srm_check_receiver_id(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_srm_query [tier=EXACT size=32] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x302. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_srm_query(int a1) { _DWORD v6[6]; // [sp+0h] [bp-18h] BYREF bzero_core(result: v6, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_srm_read [tier=EXACT size=38] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x300. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_srm_read(int a1, int a2, int a3, int a4) { _DWORD v9[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== disp_srm_store [tier=EXACT size=38] ==== */ // RPC to the display service (SVC 0xF2, target process 2), opcode 0x308. // Frame is 0x18 bytes: {u32 opcode; u32 arg1; u32 arg2}. The name reflects the calling // context in this TA; the exact hardware operation on the service side is not verified // from this image alone. int __fastcall disp_srm_store(int a1, int a2, int a3, int a4) { _DWORD v9[7]; // [sp+0h] [bp-1Ch] BYREF bzero_core(result: v9, a2: 0x18u); __asm { SVC 0xF2 } return 2; } /* ==== gp_asym_verify [tier=EXACT size=58] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0xB. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_asym_verify(int a1, int a2, int a3, int a4) { __asm { SVC 0xF2 } return 1; } /* ==== gp_cipher_do_final [tier=EXACT size=52] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x10. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_cipher_do_final(int a1, int a2, int a3, int a4) { __asm { SVC 0xF2 } return 1; } /* ==== gp_cipher_init [tier=EXACT size=46] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x5. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_cipher_init(int a1, int a2, int a3) { _DWORD v8[10]; // [sp+10h] [bp+10h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 1; } /* ==== gp_cipher_update [tier=EXACT size=50] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x7. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_cipher_update(int a1, int a2, int a3, int a4) { __asm { SVC 0xF2 } return 1; } /* ==== gp_digest_do_final [tier=EXACT size=66] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x8. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_digest_do_final(int a1, int a2, int a3, int a4) { __asm { SVC 0xF2 } return 1; } /* ==== gp_mac_init [tier=EXACT size=46] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0xE. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_mac_init(int a1, int a2, int a3) { _DWORD v8[10]; // [sp+10h] [bp+10h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 1; } /* ==== gp_mac_update [tier=EXACT size=50] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0xD. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_mac_update(int a1, int a2, int a3, int a4) { __asm { SVC 0xF2 } return 1; } /* ==== gp_object_allocate [tier=EXACT size=50] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x30. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_object_allocate(int a1, int a2, int a3) { _DWORD v8[12]; // [sp+8h] [bp+8h] BYREF bzero_core(result: v8, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== gp_object_free [tier=EXACT size=38] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x31. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_object_free(int a1) { _DWORD v6[12]; // [sp+8h] [bp-78h] BYREF bzero_core(result: v6, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== gp_operation_allocate [tier=EXACT size=60] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x1. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_operation_allocate(int a1, int a2, int a3, int a4) { _DWORD v9[12]; // [sp+8h] [bp-78h] BYREF bzero_core(result: v9, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== gp_operation_free [tier=EXACT size=36] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x2. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_operation_free(int a1) { _DWORD v6[12]; // [sp+8h] [bp-78h] BYREF bzero_core(result: v6, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== gp_populate_transient_object [tier=EXACT size=52] ==== */ // TEE_PopulateTransientObject: SVC 0xF2 -> SYS_DRV gp_crypto_dispatch opcode 0x33. // Identified from call sites passing (objHandle, TEE_Attribute{0xC0000000, ptr, len}, 1). int __fastcall gp_populate_transient_object(int a1, int a2, int a3) { _DWORD v8[10]; // [sp+10h] [bp+10h] BYREF bzero_core(result: v8, a2: 0x18u); __asm { SVC 0xF2 } return 1; } /* ==== gp_populate_transient_object_op35 [tier=EXACT size=42] ==== */ // SVC 0xF2 -> SYS_DRV gp_crypto_dispatch opcode 0x35. int __fastcall gp_populate_transient_object_op35(int a1, int a2) { _DWORD v7[28]; // [sp+10h] [bp-70h] BYREF bzero_core(result: v7, a2: 0x18u); __asm { SVC 0xF2 } return 1; } /* ==== gp_set_operation_key [tier=EXACT size=42] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x3. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall gp_set_operation_key(int a1, int a2) { _DWORD v7[12]; // [sp+8h] [bp-78h] BYREF bzero_core(result: v7, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== hdcp1_create_session [tier=EXACT size=298] ==== */ int __fastcall hdcp1_create_session(unsigned __int8 *a1, struct hdcp1_session_req *a2) { int v3; // r6 int v4; // r9 int v5; // r6 _DWORD *v6; // r1 int i; // r0 int v8; // r4 int j; // r7 int v10; // r5 __int16 v12; // r0^2 int v13; // r1 char v14; // [sp+6h] [bp-26h] BYREF char v15; // [sp+7h] [bp-25h] BYREF int v16; // [sp+8h] [bp-24h] BYREF char v17; // [sp+Ch] [bp-20h] int v18; // [sp+10h] [bp-1Ch] BYREF char v19; // [sp+14h] [bp-18h] int v20; // [sp+18h] [bp-14h] BYREF int v21; // [sp+1Ch] [bp-10h] __int64 v22; // [sp+20h] [bp-Ch] BYREF v3 = 2; v22 = 0; v20 = 0; v21 = 0; v19 = 0; v18 = 0; v17 = 0; v16 = 0; if ( a1 != nullptr && a2 != nullptr ) { v4 = dword_40237C; v5 = *a1; v6 = (_DWORD *)(dword_40237C + 4); *(_DWORD *)a2 = 0xFFFF; for ( i = 0; ; ++i ) { if ( i == 8 ) { v8 = 0; for ( j = 0; ; ++j ) { if ( v8 == 5216 ) return 3; v10 = v4 + v8; if ( *(_DWORD *)(v4 + v8 + 8) == 0 ) break; v8 += 652; } bzero_core(result: (_DWORD *)(v10 + 4), a2: 0x288u); *(_DWORD *)(v4 + v8) = 1; *(_DWORD *)(v10 + 4) = v5; *(_DWORD *)(v10 + 8) = 1; *(_DWORD *)a2 = j; if ( disp_session_open(a1: v5, a2: v10 + 16) != 0 || disp_hdcp1_init(a1: *(_DWORD *)(v10 + 4)) != 0 )// a1 { v3 = 4; } else { // a3 if ( disp_hdcp1_read_caps(a1: *(_DWORD *)(v10 + 4), a2: (int)&v15, a3: (int)&v14) == 0 && disp_hdcp1_read_bksv(a1: *(_DWORD *)(v10 + 4), a2: (int)&v22, a3: (int)&v20) == 0 && disp_hdcp1_setup(a1: *(_DWORD *)(v10 + 4), a2: (int)&v18, a3: (int)&v16) == 0 ) { v12 = HIWORD(v20); v13 = v21; *((_WORD *)a2 + 9) = v20; *((_WORD *)a2 + 11) = v13; *(_QWORD *)((char *)a2 + 4) = v22; // a4 *((_WORD *)a2 + 12) = HIWORD(v13); // unsigned int *((_WORD *)a2 + 10) = v12; // int * sub_401058(); // result sub_401058(); // unsigned int v3 = 0; *((_BYTE *)a2 + 17) = v15; *((_BYTE *)a2 + 31) = v14; return v3; } v3 = 1; } hdcp_session_teardown(a1: (_DWORD *)(v4 + v8)); return v3; } if ( v6[1] != 0 && *v6 == v5 ) break; v6 += 163; } *(_DWORD *)a2 = i; return 3; } return v3; } /* ==== hdcp1_destroy_session [tier=EXACT size=30] ==== */ int __fastcall hdcp1_destroy_session(unsigned int *a1) { unsigned int v1; // r0 if ( a1 == nullptr ) return 2; v1 = *a1; if ( v1 <= 7 ) return hdcp_session_teardown(a1: (_DWORD *)(dword_401D44 + 652 * v1)); else return 1; } /* ==== hdcp1_enable_dp_stream_encryption [tier=EXACT size=70] ==== */ int __fastcall hdcp1_enable_dp_stream_encryption(unsigned int *a1) { unsigned int v1; // r1 if ( a1 == nullptr ) return 2; v1 = *a1; return *a1 > 7 || *(_DWORD *)(dword_401D44 + 652 * v1 + 8) != 1 || *(_DWORD *)(dword_401D44 + 652 * v1) != 1 || *(_DWORD *)(dword_401D44 + 652 * v1 + 16) != 5 || disp_hdcp1_enable_stream_enc(a1: a1[1]) != 0;// a1 } /* ==== hdcp1_enable_encryption [tier=EXACT size=64] ==== */ int __fastcall hdcp1_enable_encryption(unsigned int *a1, int a2, int a3, int a4) { unsigned int v4; // r0 if ( a1 == nullptr ) return 2; v4 = *a1; return v4 > 7 || *(_DWORD *)(dword_401D44 + 652 * v4 + 8) != 1 || *(_DWORD *)(dword_401D44 + 652 * v4) != 1 || disp_hdcp1_enable_encryption(a1: *(_DWORD *)(dword_401D44 + 652 * v4 + 4)) != 0;// a1 } /* ==== hdcp1_first_part_authentication [tier=EXACT size=550] ==== */ int __fastcall hdcp1_first_part_authentication(struct hdcp1_auth_req *a1, int *a2, int a3, int a4) { int v4; // r7 unsigned int session_idx; // r8 int v6; // r9 int *v7; // r10 int v8; // r11 int *v9; // r6 int v11; // r3 int status; // r5 int v13; // r1 unsigned int v14; // r10 int v15; // t1 int v16; // r0 int i; // r1 int v19; // r0 int v20; // r1 int v21; // r1 int v22; // [sp+8h] [bp-2BCh] int v23; // [sp+Ch] [bp-2B8h] int v24; // [sp+10h] [bp-2B4h] char v25[4]; // [sp+18h] [bp-2ACh] BYREF char v26[4]; // [sp+1Ch] [bp-2A8h] BYREF int v27; // [sp+20h] [bp-2A4h] BYREF char v28; // [sp+24h] [bp-2A0h] int v29; // [sp+28h] [bp-29Ch] BYREF char v30; // [sp+2Ch] [bp-298h] int v31; // [sp+30h] [bp-294h] char v32; // [sp+34h] [bp-290h] int v33; // [sp+38h] [bp-28Ch] char v34; // [sp+3Ch] [bp-288h] int v35; // [sp+40h] [bp-284h] BYREF char v36; // [sp+44h] [bp-280h] char v37[635]; // [sp+45h] [bp-27Fh] BYREF int v38; // [sp+2C0h] [bp-4h] v9 = off_401CD8; v38 = *off_401CD8; v33 = 0; v34 = 0; v31 = 0; v32 = 0; if ( a1 == nullptr ) { status = 2; goto LABEL_15; } session_idx = *(_DWORD *)a1; v11 = *((unsigned __int8 *)a1 + 9); v33 = *((_DWORD *)a1 + 1); v34 = *((_BYTE *)a1 + 8); v32 = *((_BYTE *)a1 + 13); v31 = v11 | (*((unsigned __int8 *)a1 + 10) << 8) | ((*((unsigned __int8 *)a1 + 11) | (*((unsigned __int8 *)a1 + 12) << 8)) << 16); if ( session_idx <= 7 ) { v6 = dword_40237C; if ( *(_DWORD *)(dword_40237C + 652 * session_idx + 8) == 1 ) { status = 1; if ( *(_DWORD *)(dword_40237C + 652 * session_idx) != 1 ) goto LABEL_15; v8 = *((unsigned __int16 *)a1 + 9); v4 = *((unsigned __int16 *)a1 + 8); v13 = *((unsigned __int8 *)a1 + 14); // a2 *a2 = 1; v14 = v6 + 652 * session_idx; v15 = *(_DWORD *)(v14 + 4); // a1 v7 = (int *)(v14 + 4); if ( disp_hdcp1_write_an(a1: v15, a2: v13) != 0 ) { LABEL_6: v16 = *v7; // a1 LABEL_7: disp_link_reset(a1: v16, a2: 0); // a2 } else { v24 = v4; v4 = v6 + 652 * session_idx + 64; for ( i = 0; i != 4; ++i ) *(_DWORD *)(v4 + 4 * i) = 0; v30 = v34; v29 = v33; if ( disp_srm_query(a1: (int)&v29) == 0 ) goto LABEL_18; // a1 LABEL_13: disp_link_reset(a1: *v7, a2: 0); // a2 *a2 = 10; } } } LABEL_14: status = 1; LABEL_15: while ( *v9 != v38 ) { ((void (__fastcall *)(int))loc_404338)(a1: *v9 - v38); LABEL_18: v23 = v8; if ( *(_DWORD *)v4 != 0 || *(_DWORD *)(v4 + 4) != 0 || *(_DWORD *)(v4 + 8) != 0 || *(_DWORD *)(v4 + 12) != 0 ) { v19 = disp_hdcp1_teardown(a1: v4); // a1 if ( v19 != 0 ) v19 = 17; } else { v19 = 0; } v8 = (int)&v35; v22 = v19; bzero(result: v37, a2: 0x27Bu); v36 = v34; // a3 v35 = v33; status = 1; if ( disp_hdcp1_read_status(a1: *v7, a2: (int)&v35, a3: 1, a4: v4) == 0 )// a1 { v8 = v6 + 652 * session_idx; if ( *(_DWORD *)(v8 + 16) != 2 ) goto LABEL_28; v30 = v32; v29 = v31; if ( disp_srm_query(a1: (int)&v29) != 0 ) goto LABEL_13; // a1 v36 = v32; // a3 v35 = v31; status = 1; if ( disp_hdcp1_read_status(a1: *v7, a2: (int)&v35, a3: 1, a4: v4) == 0 )// a1 { LABEL_28: *(_BYTE *)(v8 + 56) = v34; *(_DWORD *)(v8 + 52) = v33; sub_401058(); // result v29 = v33; v30 = v34; v28 = v32; v27 = v31; v20 = disp_hdcp1_compute_ri(a1: *v7, a2: (int)&v29, a3: (int)&v27);// a1 v16 = *v7; // a1 if ( v20 != 0 ) goto LABEL_7; if ( disp_hdcp1_read_ri(a1: v16, a2: v24, a3: v23) != 0 ) goto LABEL_6; // a3 if ( disp_get_link_status(a1: *v7, a2: v6 + 652 * session_idx + 20, a3: (int)v26, a4: (int)v25) != 0 ) goto LABEL_14; // a2 v21 = 2; if ( *(_DWORD *)(v6 + 652 * session_idx + 20) == 1 ) v21 = 4; *a2 = v21; status = v22; } } } return status; } /* ==== hdcp1_get_encryption_status [tier=EXACT size=104] ==== */ int __fastcall hdcp1_get_encryption_status(unsigned int *a1, _DWORD *a2, int a3, int a4) { int result; // r0 unsigned int v7; // r0 int link_status; // r1 bool v9; // zf int v10; // [sp+8h] [bp-10h] _BYTE v11[4]; // [sp+Ch] [bp-Ch] BYREF int v12; // [sp+10h] [bp-8h] BYREF _BYTE v13[4]; // [sp+14h] [bp-4h] BYREF result = 2; if ( a1 != nullptr && a2 != nullptr ) { v7 = *a1; *a2 = 0; if ( v7 <= 7 && *(_DWORD *)(dword_4020DC + 652 * v7 + 8) == 1 && *(_DWORD *)(dword_4020DC + 652 * v7) == 1 ) { link_status = disp_get_link_status( a1: *(_DWORD *)(dword_4020DC + 652 * v7 + 4), a2: (int)v13, a3: (int)&v12, a4: (int)v11); // a1 result = 0; if ( link_status == 0 ) { v9 = v12 == 3; if ( v12 == 3 ) v9 = v10 == 1; if ( v9 ) { *a2 = 1; return 0; } } } else { return 1; } } return result; } /* ==== hdcp1_second_part_authentication [tier=EXACT size=372] ==== */ // HDCP1 second-part authentication: copies a 0x2A0-byte request, walks the KSV list // (5-byte Key Selection Vectors, count = BINFO>>2 capped at 0x9E) and checks each one // through the display service (RPC 0x307, receiver-ID/SRM revocation check). int __fastcall hdcp1_second_part_authentication(int *a1, int *r1_0) { int *v2; // r8 int result; // r0 unsigned int v6; // r5 unsigned int v7; // r0 unsigned int v8; // r7 unsigned int i; // r9 unsigned __int8 *v10; // r1 int v11; // r0 int v12; // r4 int v13; // r2 int v14; // r3 unsigned int v15; // r1 int v16; // r5 int *v17; // r5 int v18; // t1 int v19; // r1 int v20; // [sp+0h] [bp-53Ch] BYREF int v21; // [sp+18h] [bp-524h] BYREF unsigned __int8 v22; // [sp+1Ch] [bp-520h] unsigned int v23; // [sp+298h] [bp-2A4h] BYREF unsigned __int16 a2; // [sp+29Ch] [bp-2A0h] _BYTE a2_2[638]; // [sp+29Eh] [bp-29Eh] BYREF int a3; // [sp+51Ch] [bp-20h] int v27; // [sp+538h] [bp-4h] v2 = off_4027DC; v27 = *off_4027DC; bzero_core(result: &v23, a2: 0x2A0u); if ( a1 == nullptr ) { result = 2; goto LABEL_20; } memcpy_aligned(result: (int *)&v23, a2: a1, a3: 0x2A0u);// result if ( (unsigned int)a3 >> 2 > 0x9E ) { result = 5; goto LABEL_20; } v6 = v23; if ( v23 > 7 || *(_DWORD *)(dword_4020DC + 652 * v23 + 8) != 1 || *(_DWORD *)(dword_4020DC + 652 * v23) != 1 ) goto LABEL_19; v7 = (unsigned __int16)a3; *r1_0 = 3; v8 = udiv32(a1: v7, a2: 5u); for ( i = 0; i < v8; ++i ) { v10 = &a2_2[5 * i]; v11 = *v10; v12 = v10[3]; v13 = v10[1]; v14 = v10[2]; v22 = v10[4]; v21 = v11 | (v13 << 8) | ((v14 | (v12 << 8)) << 16); if ( disp_revocation_check_ksv(a1: (int)&v21) != 0 ) goto LABEL_22; // a1 if ( disp_srm_query(a1: (int)&v21) != 0 ) // a1 { disp_link_reset(a1: *(_DWORD *)(dword_4020DC + 652 * v6 + 4), a2: 0);// a1 result = 1; v19 = 10; goto LABEL_24; } } v15 = 640 - 5 * v8; if ( (5 * v8) >> 7 > 4 ) v15 = 0; bzero(result: (_BYTE *)&v21 + 5 * v8, a2: v15); sub_401058(); // unsigned int v16 = dword_4020DC + 652 * v6; v18 = *(_DWORD *)(v16 + 4); // a1 v17 = (int *)(v16 + 4); if ( disp_hdcp1_read_status(a1: v18, a2: (int)&v21, a3: (unsigned __int8)v8, a4: (int)(v17 + 15)) != 0 ) goto LABEL_19; // a4 if ( disp_hdcp1_write_v(a1: *v17, a2) != 0 || (sub_401058(), disp_hdcp1_verify_v(a1: *v17, a2: (int)a2_2, a3, a4: (int)&v20) != 0) )// a4 { disp_link_reset(a1: *v17, a2: 0); // a2 LABEL_19: result = 1; goto LABEL_20; } *r1_0 = 4; result = 0; LABEL_20: while ( *v2 != v27 ) { ((void (__fastcall *)(int, int))loc_404338)(a1: result, a2: *v2 - v27); LABEL_22: result = 0; v19 = 9; LABEL_24: *r1_0 = v19; } return result; } /* ==== hdcp2_build_tx_message [tier=EXACT size=190] ==== */ // Build the next HDCP 2.2 message to transmit. a2 = message id; *a5 receives // (msg_id, length) and *a6 the status. Ids per the HDCP 2.2 specification: // 2 AKE_Init 4 AKE_No_Stored_km 5 AKE_Stored_km 9 LC_Init // 11 SKE_Send_Eks 15 RepeaterAuth_Send_Ack 16 RepeaterAuth_Stream_Manage int __fastcall hdcp2_build_tx_message(_DWORD *a1, int a2, _BYTE *a3, int *r3_0, int *a4, int *a5) { int v6; // r0 *a4 = 1; a4[1] = 0; *a5 = 2; // switch 19 cases switch ( a2 ) { case 1: v6 = 2; // jumptable 004020FA case 1 goto LABEL_6; case 2: return hdcp2_tx_AKE_Init((struct hdcp2_session *)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 2 case 3: case 6: case 7: case 8: case 10: case 12: case 13: case 17: case 18: goto LABEL_5; // switch jump case 4: return hdcp2_tx_AKE_No_Stored_km((int)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 4 case 5: return hdcp2_tx_AKE_Stored_km(a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 5 case 9: return hdcp2_tx_LC_Init(a1, a2: a3, a3: r3_0, a4, a5);// jumptable 004020FA case 9 case 11: return hdcp2_tx_SKE_Send_Eks((struct hdcp2_session *)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 11 case 14: return hdcp2_tx_msg14((int)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 14 case 15: return hdcp2_tx_RepeaterAuth_Send_Ack((int)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 15 case 16: return hdcp2_tx_RepeaterAuth_Stream_Manage( (struct hdcp2_session *)a1, a2: (int *)a3, a3: (unsigned int *)r3_0, a4, a5); // jumptable 004020FA case 16 case 19: return hdcp2_tx_msg19((int)a1, a2: (int)a3, a3: (unsigned int)r3_0, a4, a5);// jumptable 004020FA case 19 default: if ( a2 == 129 ) // jumptable 004020FA default case return hdcp2_tx_msg129((int)a1, a2: a3, a3: (unsigned int)r3_0, a4, a5); LABEL_5: a1[6] = 7; // jumptable 004020FA cases 3,6-8,10,12,13,17,18 v6 = 105; LABEL_6: *a5 = v6; return 0; } } /* ==== hdcp2_create_session [tier=EXACT size=152] ==== */ int __fastcall hdcp2_create_session(__int64 *a1, int *a2) { int result; // r0 int v4; // r3 _DWORD *v5; // r5 __int64 v6; // kr00_8 int i; // r2 int v8; // r6 int *v9; // r6 int v10; // r1 result = 2; if ( a1 != nullptr && a2 != nullptr ) { v4 = dword_401F54; v5 = (_DWORD *)(dword_4020DC + 1268); v6 = *a1; // a1 for ( i = 1; ; ++i ) { if ( i == 8 ) return 3; if ( *(_DWORD *)((char *)v5 + dword_401F54) == 0 ) break; v5 += 163; } v8 = dword_401F58; *a2 = i; *(_DWORD *)((char *)v5 + v8) = v6; *(_DWORD *)((char *)v5 + v4) = 1; *(_DWORD *)((char *)v5 + dword_401F5C) = 2; if ( disp_hdcp2_init(a1: v6) != 0 ) return 17; v9 = v5 - 153; if ( HIDWORD(v6) == 1 ) { v10 = 0; } else { v10 = 1; if ( HIDWORD(v6) != 2 ) v6 = 0x200000002LL; } *(_DWORD *)((char *)v5 + dword_401F60) = v10; *(_DWORD *)((char *)v5 + dword_401F64) = v6; if ( disp_hdcp2_set_caps(a1: *v9, a2: SHIDWORD(v6)) != 0 || disp_session_open(a1: *v9, a2: (int)(v5 - 150)) != 0 )// a2 { return 17; } else { *(_DWORD *)((char *)v5 + dword_401F68) = 0; *(v5 - 6) = -1; *(v5 - 5) = 0; *v5 = 0; return 0; } } return result; } /* ==== hdcp2_destroy_session [tier=EXACT size=90] ==== */ int __fastcall hdcp2_destroy_session(unsigned int *a1) { unsigned int v1; // r0 _DWORD *v2; // r5 int v3; // r2 bool v4; // zf int v5; // r4 int v7; // r6 if ( a1 == nullptr ) return 2; v1 = *a1; if ( v1 > 7 ) return 1; v2 = (_DWORD *)(dword_4020DC + 652 * v1); v3 = v2[2]; v4 = v3 == 1; if ( v3 == 1 ) v4 = *v2 == 2; if ( !v4 ) return 1; v7 = dword_4020DC + 652 * v1; v5 = disp_hdcp2_teardown(a1: v7 + 616); // a1 if ( disp_hdcp2_disable(a1: *(_DWORD *)(v7 + 4)) != 0 )// a1 return 20; bzero_core(result: v2, a2: 0x28Cu); if ( v5 != 0 ) return 17; return v5; } /* ==== hdcp2_enable_dp_stream_encryption [tier=EXACT size=70] ==== */ int __fastcall hdcp2_enable_dp_stream_encryption(unsigned int *a1) { unsigned int v1; // r1 if ( a1 == nullptr ) return 2; v1 = *a1; return *a1 > 7 || *(_DWORD *)(dword_40237C + 652 * v1 + 8) != 1 || *(_DWORD *)(dword_40237C + 652 * v1) != 2 || *(_DWORD *)(dword_40237C + 652 * v1 + 16) != 5 || disp_hdcp2_enable_stream_enc(a1: a1[1]) != 0;// a1 } /* ==== hdcp2_get_encryption_status [tier=EXACT size=114] ==== */ int __fastcall hdcp2_get_encryption_status(unsigned int *a1, int *a2, int a3, int a4) { int result; // r0 unsigned int v7; // r0 int link_status; // r1 bool v9; // zf int v10; // r1 int v11; // r0 int v12; // [sp+8h] [bp-10h] int v13; // [sp+Ch] [bp-Ch] BYREF int v14; // [sp+10h] [bp-8h] BYREF _BYTE v15[4]; // [sp+14h] [bp-4h] BYREF result = 2; if ( a1 != nullptr && a2 != nullptr ) { v7 = *a1; a2[1] = 0; if ( v7 <= 7 && *(_DWORD *)(dword_40237C + 652 * v7 + 8) == 1 && *(_DWORD *)(dword_40237C + 652 * v7) == 2 ) { link_status = disp_get_link_status( a1: *(_DWORD *)(dword_40237C + 652 * v7 + 4), a2: (int)v15, a3: (int)&v14, a4: (int)&v13); // a1 result = 0; if ( link_status == 0 ) { v9 = v14 == 3; if ( v14 == 3 ) v9 = v12 == 1; if ( v9 ) { v10 = v13; v11 = 1; a2[1] = 1; if ( v10 == 2 ) v11 = 2; *a2 = v11; return 0; } } } else { return 1; } } return result; } /* ==== hdcp2_prepare_process_auth_message [tier=EXACT size=694] ==== */ int __fastcall hdcp2_prepare_process_auth_message(unsigned int *a1) { unsigned int v1; // r7 int v2; // r8 int *v3; // r6 int v5; // r4 int v6; // r0 int v7; // r0 unsigned __int8 *v9; // r0 int v10; // r1 int i; // r1 unsigned int v12; // r4 char v13; // [sp+7h] [bp-89h] BYREF int v14; // [sp+8h] [bp-88h] BYREF int v15; // [sp+Ch] [bp-84h] _DWORD v16[2]; // [sp+10h] [bp-80h] BYREF _DWORD v17[16]; // [sp+38h] [bp-58h] BYREF _DWORD v18[2]; // [sp+78h] [bp-18h] BYREF int v19; // [sp+80h] [bp-10h] int v20; // [sp+84h] [bp-Ch] int v21; // [sp+8Ch] [bp-4h] v3 = off_403EAC; v21 = *off_403EAC; bzero_core(result: v16, a2: 0x28u); v19 = 0; v20 = 0; v18[0] = 0; v18[1] = 0; v14 = 0; v15 = 0; v13 = 0; bzero_core(result: v17, a2: 0x40u); if ( a1 != nullptr ) { v1 = *a1; if ( *a1 <= 7 && (v2 = dword_4034DC, *(_DWORD *)(dword_4034DC + 652 * v1 + 8) == 1) && *(_DWORD *)(dword_4034DC + 652 * v1) == 2 ) { // a1 if ( disp_auth_msg_get(a1: (int)v16) != 0 ) { v5 = 17; } else { v5 = 18; // switch 43 cases switch ( v16[1] ) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: case 0xB: case 0xC: case 0xE: case 0xF: case 0x11: case 0x12: case 0x13: case 0x14: case 0x15: case 0x16: case 0x18: case 0x19: case 0x1A: case 0x1B: case 0x1C: case 0x1D: case 0x1E: case 0x1F: case 0x20: case 0x21: case 0x22: case 0x23: case 0x24: case 0x25: case 0x26: case 0x28: case 0x2A: case 0x2B: goto LABEL_19; // switch jump case 0x10: v6 = sysdrv_rpc_1087(a1: (int)&v13);// jumptable 00402FE4 case 16 if ( v6 == dword_403264 || v6 == 0 ) goto LABEL_19; goto LABEL_14; case 0x17: v7 = sysdrv_rpc_1087(a1: (int)&v13);// jumptable 00402FE4 case 23 if ( v7 != dword_403264 && v7 != 0 ) goto LABEL_14; goto LABEL_19; case 0x27: bzero_core(result: v17, a2: 0x40u); // jumptable 00402FE4 case 39 goto LABEL_20; default: break; } } } else { LABEL_14: v5 = 1; } } else { v5 = 2; } while ( *v3 != v21 ) // jumptable 00402FE4 default case, cases 10,13,41 { ((void (__fastcall *)(int))loc_404338)(a1: *v3 - v21);// jumptable 00402FE4 case 24 LABEL_19: sub_401058(); // unsigned int LABEL_20: if ( disp_auth_msg_put(a1: (int)v17) != 0 ) // a1 { v5 = 18; } else { v9 = (unsigned __int8 *)(v2 + 652 * v1); v10 = v9[582]; v15 = v9[585] | (v9[586] << 8) | ((v9[587] | (v9[588] << 8)) << 16); v14 = v9[581] | (v10 << 8) | ((v9[583] | (v9[584] << 8)) << 16);// a4 sub_401058(); // unsigned int for ( i = 0; i != 16; ++i ) *((_BYTE *)v18 + i) ^= *((_BYTE *)&v17[8] + i); v12 = v2 + 652 * v1; if ( disp_hdcp2_msg_state(a1: *(_DWORD *)(v12 + 4), a2: (int)v18, a3: (int)&v14) != 0 )// a1 { v5 = 19; } else { *(_BYTE *)(v12 + 589) = 1; v5 = 0; } bzero_core(result: v17, a2: 0x40u); v19 = 0; v20 = 0; v18[0] = 0; v18[1] = 0; } } return v5; } /* ==== hdcp2_process_auth_message_v2 [tier=EXACT size=476] ==== */ int __fastcall hdcp2_process_auth_message_v2(int *a1, struct hdcp2_auth_msg *a2) { int *v2; // r7 _DWORD *v3; // r10 int v4; // r11 int v7; // r6 int v8; // r0 bool v9; // zf int v11; // r2 int *v12; // r2 int v13; // t1 int *v14; // r8 int v15; // r2 int v16; // r1 int v17; // r1 int v18; // r2 int v19; // r0 int *v20; // [sp+8h] [bp-26Ch] int v21; // [sp+Ch] [bp-268h] BYREF int v22; // [sp+10h] [bp-264h] BYREF int v23; // [sp+14h] [bp-260h] BYREF int v24; // [sp+18h] [bp-25Ch] BYREF int v25; // [sp+1Ch] [bp-258h] BYREF int v26[2]; // [sp+20h] [bp-254h] BYREF int v27[2]; // [sp+28h] [bp-24Ch] BYREF int v28; // [sp+30h] [bp-244h] int v29; // [sp+38h] [bp-23Ch] int v30; // [sp+264h] [bp-10h] int v31; // [sp+268h] [bp-Ch] int v32; // [sp+270h] [bp-4h] v32 = dword_404334; bzero_core(result: v27, a2: 0x244u); v7 = 2; v26[0] = 0; v26[1] = 0; if ( a1 != nullptr && a2 != nullptr ) { v2 = v27; memcpy_aligned(result: v27, a2: a1, a3: 0x244u);// result a1 = (int *)v27[0]; if ( v27[0] <= 7u ) { v4 = dword_40237C; v3 = (_DWORD *)(dword_40237C + 652 * v27[0]); v8 = v3[2]; v9 = v8 == 1; if ( v8 == 1 ) v9 = *v3 == 2; if ( v9 ) goto LABEL_11; } v7 = 1; } while ( dword_404334 != v32 ) { ((void (__fastcall *)(int))loc_404338)(a1: dword_404334 - v32); LABEL_11: v11 = v4 + 652 * (_DWORD)a1; v7 = 0; *((_DWORD *)a2 + 9) = 100; *((_DWORD *)a2 + 1) = 0; *((_DWORD *)a2 + 2) = 0; *((_DWORD *)a2 + 3) = 0; *((_DWORD *)a2 + 4) = 0; *((_DWORD *)a2 + 5) = 100; *((_DWORD *)a2 + 6) = 100; *((_DWORD *)a2 + 7) = 100; *((_DWORD *)a2 + 8) = 100; v13 = *(_DWORD *)(v11 + 24); v12 = (int *)(v11 + 24); if ( v13 != 7 ) { v14 = v2 + 1; v20 = v12; v25 = 100; v23 = 100; v24 = 100; v7 = hdcp2_process_rx_message(a1: (int)v3, a2: v2 + 1, a3: (unsigned __int8 *)v2 + 28, a4: 0x220u, a5: &v25); if ( v7 != 0 || (v7 = hdcp2_process_rx_message( a1: (int)v3, a2: v2 + 3, a3: (unsigned __int8 *)v14 + v28 + 24, a4: 544 - v28, a5: &v24)) != 0 ) { v15 = v24; *((_DWORD *)a2 + 5) = v25; *((_DWORD *)a2 + 6) = v15; *((_DWORD *)a2 + 7) = 100; LABEL_15: v2 = v20; v21 = 100; v22 = 100; LABEL_16: *v2 = 7; goto LABEL_17; } v7 = hdcp2_process_rx_message( a1: (int)v3, a2: v2 + 5, a3: (unsigned __int8 *)v14 + v28 + v29 + 24, a4: 544 - (v28 + v29), a5: &v23); v17 = v23; v18 = v24; *((_DWORD *)a2 + 5) = v25; *((_DWORD *)a2 + 6) = v18; *((_DWORD *)a2 + 7) = v17; if ( v7 != 0 ) goto LABEL_15; v19 = v4 + 652 * (_DWORD)a1; *((_DWORD *)a2 + 1) = *(_DWORD *)(v19 + 36); *((_DWORD *)a2 + 2) = *(_DWORD *)(v19 + 40); *((_DWORD *)a2 + 3) = *(unsigned __int8 *)(v19 + 44); *((_DWORD *)a2 + 4) = *(unsigned __int8 *)(v19 + 45); v21 = 100; v22 = 100; v7 = hdcp2_build_tx_message(a1: v3, a2: v30, a3: (_BYTE *)a2 + 56, a4: (int *)0xA8, a5: v26, a6: &v22); *((_QWORD *)a2 + 5) = *(_QWORD *)v26; v2 = v20; *((_DWORD *)a2 + 8) = v22; if ( v7 != 0 ) goto LABEL_16; if ( v26[1] >= 0xA8u ) { v7 = 21; *((_DWORD *)a2 + 9) = 101; goto LABEL_16; } v7 = hdcp2_build_tx_message( a1: v3, a2: v31, a3: (_BYTE *)a2 + v26[1] + 56, a4: (int *)(168 - v26[1]), a5: (int *)a2 + 12, a6: &v21); *((_DWORD *)a2 + 9) = v21; if ( v7 != 0 ) goto LABEL_16; if ( *v20 == 8 ) { v16 = 3; goto LABEL_30; } if ( *v20 == 6 ) { v16 = 1; LABEL_30: v7 = 0; goto LABEL_18; } v7 = 0; LABEL_17: v16 = 0; // a2 LABEL_18: if ( disp_link_reset(a1: *(_DWORD *)(v4 + 652 * (_DWORD)a1 + 4), a2: v16) != 0 )// a1 v7 = 17; else *(_DWORD *)a2 = *v2; } } return v7; } /* ==== hdcp2_process_rx_message [tier=EXACT size=226] ==== */ // Process a received HDCP 2.2 message. a2 = (expected_msg_id, expected_len), // a3 = received buffer (a3[0] is the message id), a4 = available length. // Rejects a mismatch between expected and received id (status 102) and a short // buffer (101). Message ids follow the HDCP 2.2 specification: // 3 AKE_Send_Cert 6 AKE_Send_rrx 7 AKE_Send_H_prime // 8 AKE_Send_Pairing_Info 10 LC_Send_L_prime // 12 RepeaterAuth_Send_ReceiverID_List 13 RTT_Ready // 17 RepeaterAuth_Stream_Ready 18 Receiver_AuthStatus int __fastcall hdcp2_process_rx_message(int a1, int *a2, unsigned __int8 *a3, unsigned int r3_0, int *a4) { unsigned int v5; // r5 int v6; // r1 int v7; // r1 int v8; // r0 v5 = a2[1]; if ( v5 <= r3_0 ) { v7 = *a2; if ( v7 == 1 ) { v8 = 2; } else if ( v7 == *a3 ) // switch 18 cases { // switch jump switch ( v7 ) { case 3: return hdcp2_rx_AKE_Send_Cert((struct hdcp2_session *)a1, a2: a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 3 case 6: return hdcp2_rx_AKE_Send_rrx(a1, a2: (char *)a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 6 case 7: return hdcp2_rx_AKE_Send_H_prime((struct hdcp2_session *)a1, a2: (int *)(a3 + 1), a3: v5 - 1, a4);// jumptable 0040293E case 7 case 8: return hdcp2_rx_AKE_Send_Pairing_Info((struct hdcp2_session *)a1, a2: (int *)(a3 + 1), a3: v5 - 1, a4);// jumptable 0040293E case 8 case 10: return hdcp2_rx_LC_Send_L_prime(a1, a2: (char *)a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 10 case 12: return hdcp2_rx_RepeaterAuth_ReceiverID_List((struct hdcp2_session *)a1, a2: (char *)a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 12 case 13: v6 = 1; // jumptable 0040293E case 13 if ( a1 == 0 || a4 == nullptr ) return v6; *a4 = 100; if ( v5 == 1 ) { v6 = 0; *a4 = 0; return v6; } *(_DWORD *)(a1 + 24) = 7; v8 = 109; break; case 17: JUMPOUT(0x402E90); case 18: return hdcp2_rx_Receiver_AuthStatus(a1, a2: a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 18 case 20: return hdcp2_rx_msg20(a1, a2: a3 + 1, a3: v5 - 1, a4);// jumptable 0040293E case 20 default: v8 = 105; // jumptable 0040293E default case, cases 4,5,9,11,14-16,19 break; } } else { *(_DWORD *)(a1 + 24) = 7; v8 = 102; } v6 = 0; *a4 = v8; } else { *(_DWORD *)(a1 + 24) = 7; *a4 = 101; return 21; } return v6; } /* ==== hdcp2_rx_AKE_Send_Cert [tier=EXACT size=464] ==== */ int __fastcall hdcp2_rx_AKE_Send_Cert(struct hdcp2_session *a1, unsigned __int8 *a2, int a3, int *a4) { int *v4; // r4 unsigned __int8 *v5; // r6 int v6; // r7 int *v7; // r9 bool v9; // zf int result; // r0 int v11; // r0 unsigned __int8 v12; // r10 unsigned __int8 v13; // lr unsigned __int8 v14; // r2 unsigned __int8 v15; // r8 unsigned __int8 v16; // r12 unsigned __int8 v17; // r7 unsigned __int8 v18; // r3 int v19; // r1 int v20; // r2 int v21; // r1 int v22; // r2 int v23; // r0 int v24; // r1 int v25; // [sp+0h] [bp-B0h] BYREF unsigned __int8 v26; // [sp+4h] [bp-ACh] int v27; // [sp+8h] [bp-A8h] BYREF unsigned __int8 v28; // [sp+Ch] [bp-A4h] char v29[159]; // [sp+Dh] [bp-A3h] BYREF int v30; // [sp+ACh] [bp-4h] v7 = off_403224; v9 = a1 == nullptr; v30 = *off_403224; result = 1; if ( !v9 ) { v5 = a2; if ( a2 != nullptr ) { v4 = a4; if ( a4 != nullptr ) { *a4 = 100; if ( a1->field10 == 6 ) { if ( a3 == 523 ) { v5 = a2 + 1; v6 = 1; if ( *a2 == 0 ) { LABEL_8: if ( ((int (__fastcall *)(unsigned __int8 *, int))loc_404118)(a1: v5, a2: 522) == 0 ) goto LABEL_18; a1->field18[0] = 7; v11 = 103; goto LABEL_15; } LABEL_7: BYTE1(a1->field18[5]) = 1; v6 = 2; goto LABEL_8; } } else if ( a3 == 533 ) { if ( a2[530] == 2 ) { a1->field18[3] = 22; v12 = a2[526]; // int * v13 = a2[522]; v14 = a2[528]; v15 = a2[524]; v16 = a2[525]; v17 = a2[529]; v18 = a2[523]; // a4 a1->field107[5] = a2[527]; a1->field107[1] = v18; a1->field107[4] = v12; a1->field107[6] = v14; a1->field107[7] = v17; // unsigned int a1->field107[0] = v13; a1->field107[2] = v15; a1->field107[3] = v16; sub_401058(); // result v6 = 1; if ( v5[532] << 31 == 0 ) goto LABEL_8; goto LABEL_7; } a1->field18[0] = 7; v11 = 104; LABEL_15: *v4 = v11; result = 0; goto LABEL_16; } a1->field18[0] = 7; v11 = 109; goto LABEL_15; } } } LABEL_16: while ( *v7 != v30 ) { ((void (__fastcall *)(int, int))loc_404338)(a1: result, a2: *v7 - v30); LABEL_18: sub_401058(); // unsigned int sub_401058(); // unsigned int sub_401058(); // unsigned int a1->field4F[5] = v5[136] >> 4; if ( disp_hdcp2_set_receiver_id(a1: a1->field04, a2: v6) != 0 ) goto LABEL_21; // a1 v19 = v5[1]; v20 = v5[2] | (v5[3] << 8); v26 = v5[4]; v25 = *v5 | (v19 << 8) | (v20 << 16); if ( disp_srm_check_receiver_id(a1: (int)&v25) != 0 )// a1 { a1->field18[0] = 7; *v4 = 112; goto LABEL_21; } v6 = (int)&a1->field254[5]; if ( a1->field254[5] != 0 && disp_hdcp2_teardown(a1: (int)&a1->field254[5]) != 0 ) goto LABEL_21; // a1 bzero(result: v29, a2: 0x9Bu); v21 = v5[1]; v22 = v5[2] | (v5[3] << 8); v28 = v5[4]; v27 = *v5 | (v21 << 8) | (v22 << 16); v23 = disp_hdcp2_set_topology(a1: a1->field04, a2: (int)&v27, a3: 1, a4: (int)&a1->field254[5]);// a3 if ( v23 != 0 ) { if ( v23 == 23 ) { v24 = 112; a1->field18[0] = 7; result = 17; goto LABEL_31; } LABEL_21: result = 17; } else { if ( receiver_id_lookup((int)a1) == 0 ) a1->field18[4] = 1; v24 = 0; result = 0; LABEL_31: *v4 = v24; } } return result; } /* ==== hdcp2_rx_AKE_Send_H_prime [tier=EXACT size=558] ==== */ int __fastcall hdcp2_rx_AKE_Send_H_prime(struct hdcp2_session *a1, int *a2, int a3, int *a4) { unsigned __int8 *v4; // r7 int v9; // r4 bool v10; // zf unsigned int v12; // r0 char v13; // r4 int v14; // r1 int v15; // r2 int v16; // r0 int v17; // r1 int v18; // r2 int v19; // r0 int v20; // [sp+4h] [bp-13Ch] int v21; // [sp+8h] [bp-138h] BYREF int v22; // [sp+Ch] [bp-134h] BYREF _DWORD v23[2]; // [sp+10h] [bp-130h] BYREF int v24; // [sp+18h] [bp-128h] int v25; // [sp+1Ch] [bp-124h] _DWORD v26[2]; // [sp+20h] [bp-120h] BYREF int v27; // [sp+28h] [bp-118h] int v28; // [sp+2Ch] [bp-114h] int v29; // [sp+30h] [bp-110h] BYREF int v30; // [sp+34h] [bp-10Ch] char v31; // [sp+38h] [bp-108h] char v32; // [sp+39h] [bp-107h] char v33; // [sp+3Ah] [bp-106h] char v34; // [sp+3Bh] [bp-105h] __int16 v35; // [sp+3Ch] [bp-104h] int v36; // [sp+138h] [bp-8h] _DWORD v37[2]; // [sp+140h] [bp+0h] BYREF int v38; // [sp+148h] [bp+8h] int v39; // [sp+14Ch] [bp+Ch] int v40; // [sp+160h] [bp+20h] v4 = (unsigned __int8 *)v37; v40 = dword_404334; bzero_core(result: v37, a2: 0x20u); bzero_core(result: &v29, a2: 0x10Cu); v9 = 2; v27 = 0; v28 = 0; v24 = 0; v25 = 0; v26[0] = 0; v26[1] = 0; v23[0] = 0; v23[1] = 0; v21 = 0; v22 = 0; if ( a1 == nullptr ) goto LABEL_6; v10 = a2 == nullptr; if ( a2 != nullptr ) v10 = a4 == nullptr; if ( v10 ) goto LABEL_6; while ( 1 ) { v12 = a1->field18[3]; v13 = v12 - 20; if ( v12 - 20 > 0x17 ) { v9 = 1; goto LABEL_6; } *a4 = 100; if ( a3 != 32 ) { v9 = 0; a1->field18[0] = 7; *a4 = 109; goto LABEL_6; } a3 = (int)a1->field192; v14 = a1->field192[0]; v37[1] = a1->field192[2] | (a1->field192[3] << 16);// a4 v37[0] = v14 | (a1->field192[1] << 16); if ( a1->field18[3] < 0x16 ) { v38 = 0; v39 = 0; } else { v38 = a1->field107[0] | (a1->field107[1] << 8) | ((a1->field107[2] | (a1->field107[3] << 8)) << 16); v39 = a1->field107[4] | (a1->field107[5] << 8) | ((a1->field107[6] | (a1->field107[7] << 8)) << 16); } sub_401058(); // unsigned int if ( ((int (__fastcall *)(unsigned __int8 *, int, _DWORD *, int *))loc_40332C)(a1: v4, a2: 32, a3: v26, a4: &v22) != 0 || (HIBYTE(v39) ^= 1u, ((int (__fastcall *)(_DWORD *, int, _DWORD *, int *))loc_40332C)(a1: v37, a2: 32, a3: v23, a4: &v21) != 0) ) { bzero_core(result: v37, a2: 0x20u); v9 = 12; v27 = 0; v28 = 0; v23[0] = 0; v23[1] = 0; v26[0] = 0; v26[1] = 0; v24 = 0; v25 = 0; goto LABEL_6; } v4 = &a1->pad10F[3]; // unsigned int v20 = v22; // int * sub_401058(); // result sub_401058(); // result v15 = *(unsigned __int16 *)a3; v16 = a1->field192[2] | (a1->field192[3] << 16); v17 = a1->field192[1]; v30 = v16; v29 = v15 | (v17 << 16); if ( a1->field10 == 6 ) { v18 = a1->field4F[5]; HIBYTE(v30) = BYTE1(a1->field18[5]) ^ HIBYTE(v16); if ( v18 != 1 ) { a3 = 8; goto LABEL_25; } v31 = v13; v32 = 0; v35 = 256; v34 = 3; v33 = a1->field18[5]; } else { sub_401058(); // unsigned int sub_401058(); // unsigned int } a3 = 14; LABEL_25: sub_401058(); // unsigned int sub_401058(); // unsigned int v36 = 32; v9 = 0; if ( ((int (__fastcall *)(int *, int, _DWORD, _DWORD, _DWORD, int, int))loc_403FF4)( a1: &v29, a2: a3, a3: 0, a4: 0, a5: 0, a6: v20, a7: v21) != 0 ) { a1->field18[0] = 7; v19 = 106; } else { v19 = 0; } *a4 = v19; bzero_core(result: v37, a2: 0x20u); v27 = 0; v28 = 0; v23[0] = 0; v23[1] = 0; v26[0] = 0; v26[1] = 0; v24 = 0; v25 = 0; bzero_core(result: &v29, a2: 0x10Cu); LABEL_6: if ( dword_404334 == v40 ) return v9; ((void (__fastcall *)(int))loc_404338)(a1: dword_404334 - v40); } } /* ==== hdcp2_rx_AKE_Send_Pairing_Info [tier=EXACT size=208] ==== */ int __fastcall hdcp2_rx_AKE_Send_Pairing_Info(struct hdcp2_session *a1, int *a2, int a3, int *a4) { int result; // r0 unsigned __int16 v7; // r7 unsigned int v8; // r3 unsigned __int16 v9; // r12 unsigned __int16 v10; // lr unsigned int v11; // r6 unsigned int v12; // r3 unsigned __int8 v13; // r12 unsigned __int8 v14; // r4 unsigned __int8 v15; // r7 unsigned __int8 v16; // r6 unsigned __int8 v17; // r2 int v18; // r0 result = 1; if ( a1 != nullptr && a2 != nullptr && a4 != nullptr ) { if ( a3 == 16 ) { *a4 = 100; v7 = a1->field192[2]; v8 = a1->field192[3]; v9 = a1->field192[1]; a1->field225[4] = v7; v10 = a1->field192[0]; v11 = v8 >> 8; a1->field225[6] = v8; a1->field225[5] = HIBYTE(v7); a1->field225[3] = HIBYTE(v9); a1->field225[1] = HIBYTE(v10); v12 = a1->field18[3]; // a4 a1->field225[2] = v9; a1->field225[0] = v10; a1->field225[7] = v11; if ( v12 < 0x16 ) { a1->field225[8] = 0; a1->field225[12] = 0; a1->field225[15] = 0; a1->field225[14] = 0; a1->field225[13] = 0; a1->field225[11] = 0; a1->field225[10] = 0; a1->field225[9] = 0; } else { v13 = a1->field107[1]; a1->field225[12] = a1->field107[4]; a1->field225[8] = a1->field107[0]; v14 = a1->field107[6]; v15 = a1->field107[2]; v16 = a1->field107[3]; v17 = a1->field107[5]; a1->field225[15] = a1->field107[7]; a1->field225[14] = v14; a1->field225[13] = v17; a1->field225[11] = v16; a1->field225[10] = v15; a1->field225[9] = v13; } sub_401058(); // unsigned int stream_slot_alloc((int)a1); // int v18 = 0; } else { a1->field18[0] = 7; v18 = 109; } *a4 = v18; return 0; } return result; } /* ==== hdcp2_rx_AKE_Send_rrx [tier=EXACT size=94] ==== */ int __fastcall hdcp2_rx_AKE_Send_rrx(int a1, char *a2, int a3, int *a4) { int v4; // r4 char v5; // r4 char v6; // r12 char v7; // r7 char v8; // r6 char v9; // lr char v10; // r5 char v11; // r2 char *v12; // r1 char *v13; // r0 int v14; // r0 v4 = 1; if ( a1 != 0 && a2 != nullptr && a4 != nullptr ) { if ( a3 == 8 ) { *a4 = 100; v5 = a2[4]; v6 = *a2; v7 = a2[1]; v8 = a2[2]; v9 = a2[3]; v10 = a2[6]; v11 = a2[7]; *(_BYTE *)(a1 + 268) = a2[5]; v12 = (char *)(a1 + 267); *(_BYTE *)(a1 + 264) = v7; v13 = (char *)(a1 + 263); *v12 = v5; v12 += 2; *v13 = v6; v13 += 2; *v12 = v10; *v13 = v8; v13[1] = v9; v14 = 0; v12[1] = v11; } else { *(_DWORD *)(a1 + 24) = 7; v14 = 109; } v4 = 0; *a4 = v14; } return v4; } /* ==== hdcp2_rx_LC_Send_L_prime [tier=EXACT size=90] ==== */ int __fastcall hdcp2_rx_LC_Send_L_prime(int a1, char *a2, int a3, int *a4) { int result; // r0 int v7; // r0 bool v8; // zf char *v9; // r0 int v10; // r2 int v11; // r0 result = 1; if ( a1 == 0 || a2 == nullptr || a4 == nullptr ) return result; *a4 = 100; v7 = *(_DWORD *)(a1 + 16); v8 = v7 == 6; if ( v7 == 6 ) v8 = *(_BYTE *)(a1 + 44) == 1; if ( v8 ) { if ( a3 == 16 ) { v9 = (char *)(a1 + 370); v10 = 16; goto LABEL_9; } LABEL_13: v11 = 109; goto LABEL_14; } if ( a3 != 32 ) goto LABEL_13; v9 = (char *)(a1 + 370); v10 = 32; LABEL_9: if ( ct_memcmp(a1: v9, a2, a3: v10) != 0 ) { v11 = 106; LABEL_14: *a4 = v11; return 0; } result = 0; *a4 = 0; if ( *(_BYTE *)(a1 + 45) == 0 ) { *(_DWORD *)(a1 + 24) = 8; return 0; } return result; } /* ==== hdcp2_rx_Receiver_AuthStatus [tier=EXACT size=60] ==== */ int __fastcall hdcp2_rx_Receiver_AuthStatus(int a1, _BYTE *a2, int a3, int *a4) { int v4; // r4 int v5; // r2 bool v6; // zf int v7; // r1 v4 = 1; if ( a1 != 0 && a2 != nullptr && a4 != nullptr ) { if ( a3 == 3 ) { *a4 = 100; v5 = (unsigned __int8)a2[1]; v6 = v5 == 4; if ( v5 != 4 ) v6 = *a2 == 0; if ( v6 ) { if ( a2[2] == 0 ) { v7 = 0; LABEL_14: v4 = 0; *a4 = v7; return v4; } v7 = 111; } else { v7 = 110; } } else { v7 = 109; } *(_DWORD *)(a1 + 24) = 7; goto LABEL_14; } return v4; } /* ==== hdcp2_rx_RepeaterAuth_ReceiverID_List [tier=EXACT size=1032] ==== */ int __fastcall hdcp2_rx_RepeaterAuth_ReceiverID_List(struct hdcp2_session *a1, char *a2, unsigned int a3, int *a4) { int *v4; // r11 int v9; // r3 int result; // r0 unsigned int v11; // r8 unsigned int v12; // r10 int v13; // r9 unsigned int v14; // r0 bool v15; // zf int v16; // r0 unsigned int v17; // r0 unsigned int v18; // r1 int field38; // r8 int v20; // r7 __int64 v21; // r2 char *v22; // r0 unsigned int v23; // r1 unsigned int v24; // r8 int v25; // r7 unsigned int v26; // r1 int v27; // r0 int v28; // r1 unsigned int v29; // r2 int v30; // r1 char *v31; // r1 unsigned int v32; // r3 unsigned int v33; // r7 unsigned int i; // r7 unsigned __int8 *v35; // r1 int v36; // r0 int v37; // r2 int v38; // r3 int v39; // r1 unsigned int field04; // r0 int v41; // r0 char v42; // [sp+4h] [bp-210h] int v43; // [sp+8h] [bp-20Ch] int v44; // [sp+Ch] [bp-208h] int v45; // [sp+10h] [bp-204h] int v46; // [sp+14h] [bp-200h] int v47; // [sp+18h] [bp-1FCh] BYREF unsigned __int16 v48; // [sp+1Ch] [bp-1F8h] BYREF unsigned int v49; // [sp+20h] [bp-1F4h] BYREF unsigned __int8 v50; // [sp+24h] [bp-1F0h] _BYTE v51[155]; // [sp+25h] [bp-1EFh] BYREF _DWORD v52[8]; // [sp+C0h] [bp-154h] BYREF int v53[8]; // [sp+E0h] [bp-134h] BYREF _DWORD v54[58]; // [sp+100h] [bp-114h] BYREF int v55[10]; // [sp+1E8h] [bp-2Ch] BYREF int v56; // [sp+210h] [bp-4h] v4 = off_40394C; v56 = *off_40394C; v48 = 0; bzero_core(result: v54, a2: 0x10Cu); result = 1; if ( a1 == nullptr || a2 == nullptr || a4 == nullptr ) goto LABEL_33; *a4 = 100; if ( a1->field246[7] != 0 ) { // a1 if ( disp_hdcp2_disable(a1: a1->field04) != 0 ) { result = 20; goto LABEL_33; } a1->field246[7] = 0; } if ( a1->field10 != 6 ) { if ( a3 == 176 ) { v42 = *a2; v13 = (unsigned __int8)a2[1]; // unsigned int buffer_copy_bounded(a1: (int *)a2, a2: (int)&v48, a3: 2u, a4: v9);// int * v14 = v48; v11 = (v48 & 8) != 0; a1->field18[7] = v11; a1->field3C[2] = (v14 & 2) != 0; a1->field3C[1] = v14 & 1; a1->field3C[0] = (v14 >> 9) & 7; a1->field38 = (v14 >> 4) & 0x1F; v12 = (v14 & 4) != 0; a1->field18[6] = v12; v44 = (unsigned __int8)a2[2]; // int * v46 = (unsigned __int8)a2[3]; v45 = (unsigned __int8)a2[4]; v43 = 16; // result sub_401058(); // unsigned int sub_401058(); // unsigned int a3 = v13 << 8; goto LABEL_17; } goto LABEL_27; } if ( a1->field18[3] != 20 ) { if ( a3 <= 1 ) goto LABEL_27; v11 = (unsigned __int8)a2[1]; a1->field18[7] = v11; v12 = (unsigned __int8)*a2; a1->field18[6] = v12; a1->field38 = a2[2]; a1->field3C[0] = (unsigned __int8)a2[3]; a1->field3C[1] = (unsigned __int8)a2[5]; a1->field3C[2] = (unsigned __int8)a2[4]; if ( a2[1] != 0 || *a2 != 0 ) { LABEL_30: a1->field18[0] = 7; v16 = 107; goto LABEL_31; } if ( 5 * (unsigned __int8)a2[2] + 25 == a3 ) { v44 = (unsigned __int8)a2[6]; v46 = (unsigned __int8)a2[7]; // int * v45 = (unsigned __int8)a2[8]; v43 = 16; // result sub_401058(); // unsigned int sub_401058(); // unsigned int a3 = 0; v42 = 0; goto LABEL_17; } LABEL_27: a1->field18[0] = 7; v16 = 109; goto LABEL_31; } if ( a3 <= 1 ) goto LABEL_27; v11 = (unsigned __int8)a2[1]; a1->field18[7] = v11; v12 = (unsigned __int8)*a2; a1->field18[6] = v12; a1->field38 = a2[2]; a1->field3C[0] = (unsigned __int8)a2[3]; if ( a2[1] != 0 || *a2 != 0 ) goto LABEL_30; if ( 5 * (unsigned __int8)a2[2] + 36 != a3 ) goto LABEL_27; a3 = 0; // result v43 = 32; a1->field3C[3] = 0; // unsigned int sub_401058(); sub_401058(); // unsigned int v42 = 0; v44 = 0; v46 = 0; v45 = 0; LABEL_17: v15 = v11 == 0; if ( v11 == 0 ) v15 = v12 == 0; if ( !v15 ) goto LABEL_30; if ( a1->field3C[1] == 0 && a1->field3C[2] == 0 ) goto LABEL_35; if ( a1->field18[1] - 1 > 1 ) goto LABEL_35; a1->field18[2] = 0; // a2 if ( disp_hdcp2_set_caps(a1: a1->field04, a2: 1) == 0 ) goto LABEL_35; // a1 LABEL_25: result = 17; LABEL_33: while ( *v4 != v56 ) { ((void (__fastcall *)(int, int))loc_404338)(a1: result, a2: *v4 - v56); LABEL_35: v17 = v44 | (v46 << 8) | (v45 << 16); v18 = a1->field3C[3]; if ( v17 != 0 && v18 == 0 || v18 == 1 && v17 < a1->field254[0] ) { a1->field18[0] = 7; v16 = 108; LABEL_31: *a4 = v16; LABEL_32: result = 0; } else { field38 = a1->field38; a1->field254[0] = v17; a1->field3C[3] = 1; v20 = 5 * field38; // result sub_401058(); // unsigned int if ( a1->field10 == 6 ) { v21 = *(_QWORD *)&a1->field18[6]; *((_BYTE *)v54 + 5 * field38) = a1->field3C[0]; v22 = (char *)v54 + v20; v23 = a1->field18[3]; v22[2] = BYTE4(v21); v22[1] = field38; v22[3] = v21; if ( v23 == 20 ) { v24 = v43; a3 = (unsigned int)v54; v25 = v20 + 4; goto LABEL_48; } v29 = a1->field3C[2]; a3 = (unsigned int)v54; v22[5] = *(_QWORD *)&a1->field3C[1]; v27 = 9; *((_BYTE *)&v54[1] + v20) = v29; // a4 v28 = 6; v24 = v43; } else { v24 = v43; v26 = a3 >> 8; *((_BYTE *)v54 + v20) = v42 | a3; a3 = (unsigned int)v54; *((_BYTE *)v54 + v20 + 1) = v26; v27 = 5; v28 = 2; } v30 = v28 + v20; v25 = v20 + v27; *((_BYTE *)v54 + v30) = v44; v31 = (char *)v54 + v30; v31[2] = v45; v31[1] = v46; LABEL_48: sub_401058(); // unsigned int v55[8] = v24; memcpy_aligned(result: v55, a2: v53, a3: v24);// unsigned int if ( ((int (__fastcall *)(_DWORD *, int, _DWORD *, int *, int))loc_403FF4)( a1: v54, a2: v25, a3: v52, a4: &v47, a5: 32) != 0 ) { a1->field18[0] = 7; *a4 = 106; bzero_core(result: v52, a2: 0x20u); bzero_core(result: v54, a2: 0x10Cu); goto LABEL_32; } if ( v47 == 32 ) { v32 = v52[5]; a3 = v52[6]; v33 = v52[7]; a1->field254[1] = v52[4]; a1->field254[2] = v32; a1->field254[3] = a3; a1->field254[4] = v33; } bzero_core(result: v52, a2: 0x20u); bzero_core(result: v54, a2: 0x10Cu); for ( i = 0; i < a1->field38; ++i ) { v35 = &a1->pad55[5 * i]; v36 = *v35; a3 = v35[3]; v37 = v35[1]; v38 = v35[2]; v50 = v35[4]; v49 = v36 | (v37 << 8) | ((v38 | (a3 << 8)) << 16); if ( disp_srm_check_receiver_id(a1: (int)&v49) != 0 ) goto LABEL_60; // a1 } if ( disp_hdcp2_teardown(a1: (int)&a1->field254[5]) != 0 ) goto LABEL_25; // a1 bzero(result: v51, a2: 0x9Bu); v39 = a1->field4F[0]; v50 = a1->field4F[4]; field04 = a1->field04; // a1 v49 = v39 | (a1->field4F[1] << 8) | ((a1->field4F[2] | (a1->field4F[3] << 8)) << 16); v41 = disp_hdcp2_set_topology(a1: field04, a2: (int)&v49, a3: 1, a4: (int)&a1->field254[5]);// a3 if ( v41 != 0 || (a3 = a1->field38, sub_401058(), (v41 = disp_hdcp2_set_topology(a1: a1->field04, a2: (int)&v49, a3, a4: (int)&a1->field254[5])) != 0) )// a4 { if ( v41 != 23 ) goto LABEL_25; LABEL_60: a1->field18[0] = 7; *a4 = 112; goto LABEL_25; } result = 0; *a4 = 0; } } return result; } /* ==== hdcp2_rx_msg20 [tier=EXACT size=90] ==== */ int __fastcall hdcp2_rx_msg20(int a1, _BYTE *a2, int a3, int *a4) { int v4; // r4 int v5; // r2 bool v6; // zf unsigned int v7; // r2 int v8; // r0 v4 = 1; if ( a1 != 0 && a2 != nullptr && a4 != nullptr ) { if ( a3 == 5 ) { *a4 = 100; v5 = (unsigned __int8)a2[1]; v6 = v5 == 6; if ( v5 != 6 ) v6 = *a2 == 0; if ( v6 ) { v7 = (unsigned __int8)a2[2]; if ( v7 >= 4 ) { *(_DWORD *)(a1 + 24) = 7; v8 = 104; } else { *(_DWORD *)(a1 + 36) = v7 + 20; if ( a2[3] == 0 && a2[4] == 1 ) *(_BYTE *)(a1 + 44) = 1; v8 = 0; } } else { *(_DWORD *)(a1 + 24) = 7; v8 = 110; } } else { *(_DWORD *)(a1 + 24) = 7; v8 = 109; } v4 = 0; *a4 = v8; } return v4; } /* ==== hdcp2_tx_AKE_Init [tier=EXACT size=146] ==== */ int __fastcall hdcp2_tx_AKE_Init(struct hdcp2_session *a1, _BYTE *a2, unsigned int a3, _DWORD *a4, _DWORD *a5) { int result; // r0 unsigned int field10; // r1 unsigned int v9; // r7 unsigned __int16 v10; // r3 unsigned __int16 v11; // r0 unsigned __int16 v12; // r1 unsigned __int16 v13; // r2 result = 1; if ( a1 != nullptr && a2 != nullptr && a4 != nullptr && a5 != nullptr ) { field10 = a1->field10; v9 = 12; *a4 = 2; if ( field10 == 6 ) v9 = 9; a4[1] = v9; *a5 = 100; if ( v9 <= a3 ) { *a2 = 2; gp_populate_transient_object_op35(a1: (int)a1->field192, a2: 8);// a2 v10 = a1->field192[0]; v11 = a1->field192[1]; v12 = a1->field192[3]; v13 = a1->field192[2]; a2[1] = v10; a2[5] = v13; a2[7] = v12; a2[3] = v11; a2[8] = HIBYTE(v12); a2[4] = HIBYTE(v11); a2[6] = HIBYTE(v13); a2[2] = HIBYTE(v10); if ( a1->field10 != 6 ) { a1->field4C = 2; a2[9] = 2; } *a5 = 0; LOWORD(a1->field18[5]) = 0; a1->field18[3] = 0; a1->field18[4] = 0; a1->field18[0] = 6; return 0; } else { *a5 = 101; return 21; } } return result; } /* ==== hdcp2_tx_AKE_No_Stored_km [tier=EXACT size=226] ==== */ // HDCP 2.2 AKE_No_Stored_km: builds the 128-byte Ekpub(km) (RSA-OAEP over the receiver's // 1024-bit public key from the certificate). int __fastcall hdcp2_tx_AKE_No_Stored_km(int a1, _BYTE *a2, unsigned int a3, _QWORD *a4, _DWORD *a5) { int v9; // r7 bool v10; // zf int v12; // [sp+4h] [bp-120h] BYREF _DWORD v13[32]; // [sp+8h] [bp-11Ch] BYREF _DWORD v14[36]; // [sp+88h] [bp-9Ch] BYREF __int16 v15; // [sp+118h] [bp-Ch] char v16; // [sp+11Ah] [bp-Ah] int v17; // [sp+120h] [bp-4h] v17 = dword_404334; bzero_core(result: v14, a2: 0x93u); bzero_core(result: v13, a2: 0x80u); v12 = 128; v9 = 1; if ( a1 == 0 ) goto LABEL_6; v10 = a2 == nullptr; if ( a2 != nullptr ) v10 = a4 == nullptr; if ( v10 ) goto LABEL_6; while ( 1 ) { if ( a5 != nullptr ) { *a4 = 0x8100000004LL; *a5 = 100; if ( a3 < 0x81 ) { v9 = 21; *a5 = 101; } else { *a2++ = 4; if ( *(_DWORD *)(a1 + 40) == 0 ) gp_populate_transient_object_op35(a1: a1 + 338, a2: 16);// a2 sub_401058(); // unsigned int sub_401058(); // unsigned int v15 = *(_WORD *)(a1 + 546); v16 = *(_BYTE *)(a1 + 548); if ( ((int (__fastcall *)(_DWORD *, int, _DWORD *, int *))loc_403EB0)(a1: v14, a2: 147, a3: v13, a4: &v12) != 0 ) { v9 = 11; } else { sub_401058(); // unsigned int v9 = 0; *a5 = 0; } bzero_core(result: v14, a2: 0x93u); } } LABEL_6: if ( dword_404334 == v17 ) break; ((void (__fastcall *)(int))loc_404338)(a1: dword_404334 - v17); } return v9; } /* ==== hdcp2_tx_AKE_Stored_km [tier=EXACT size=90] ==== */ int __fastcall hdcp2_tx_AKE_Stored_km(_DWORD *a1, _BYTE *a2, unsigned int a3, _DWORD *a4, int *a5) { int result; // r0 int v7; // r1 result = 1; if ( a1 != nullptr && a2 != nullptr && a4 != nullptr && a5 != nullptr ) { *a4 = 5; a4[1] = 33; *a5 = 100; if ( a3 < 0x21 ) { result = 21; v7 = 101; } else if ( a1[10] == 1 ) { *a2 = 5; sub_401058(); // unsigned int sub_401058(); // unsigned int v7 = 0; result = 0; } else { result = 0; v7 = 1; } *a5 = v7; } return result; } /* ==== hdcp2_tx_LC_Init [tier=EXACT size=360] ==== */ int __fastcall hdcp2_tx_LC_Init(_DWORD *a1, _BYTE *a2, int *a3, _DWORD *a4, int *a5) { int v9; // r7 __int16 v10; // r3 __int16 v11; // r0 __int16 v12; // r1 __int16 v13; // r2 _BYTE *v14; // r6 int i; // r2 int v16; // r2 int v17; // r0 int v18; // r1 int v19; // r1 int v20; // r2 bool v21; // zf int j; // r1 char *v23; // r2 int v24; // r0 int v25; // r0 int v27; // [sp+4h] [bp-138h] BYREF _DWORD v28[8]; // [sp+8h] [bp-134h] BYREF _DWORD v29[68]; // [sp+28h] [bp-114h] BYREF int v30; // [sp+138h] [bp-4h] v30 = dword_404334; bzero_core(result: v29, a2: 0x10Cu); bzero_core(result: v28, a2: 0x20u); v9 = 1; v27 = 0; if ( a1 == nullptr || a2 == nullptr || a4 == nullptr || a5 == nullptr ) goto LABEL_18; *a4 = 9; a4[1] = 9; *a5 = 100; if ( (unsigned int)a3 < 9 ) { v9 = 21; *a5 = 101; goto LABEL_18; } *a2 = 9; a3 = a5; // a2 gp_populate_transient_object_op35(a1: (int)a1 + 410, a2: 8);// a1 v10 = *((_WORD *)a1 + 205); // a4 v11 = *((_WORD *)a1 + 206); v12 = *((_WORD *)a1 + 208); v13 = *((_WORD *)a1 + 207); a2[1] = v10; v14 = a2 + 1; v14[4] = v13; v14 += 4; *((_WORD *)v14 + 1) = v12; *(v14 - 2) = v11; v14[1] = HIBYTE(v13); *(v14 - 1) = HIBYTE(v11); // int * *(v14 - 3) = HIBYTE(v10); sub_401058(); // unsigned int for ( i = 0; i != 8; ++i ) *((_BYTE *)&v28[6] + i) ^= *((_BYTE *)a1 + i + 263); a4 = (_DWORD *)32; // unsigned int sub_401058(); v16 = *((unsigned __int16 *)a1 + 205); v17 = *((unsigned __int16 *)a1 + 207) | (*((unsigned __int16 *)a1 + 208) << 16); v18 = *((unsigned __int16 *)a1 + 206); v29[1] = v17; v19 = v16 | (v18 << 16); v20 = a1[4]; v29[0] = v19; v21 = v20 == 6; if ( v20 == 6 ) v21 = *((_BYTE *)a1 + 44) == 1; if ( v21 ) goto LABEL_21; LABEL_13: for ( j = 8; ; j = 16 ) { v23 = (char *)a1 + 370; a1 = v29; v29[66] = 0; v24 = ((int (__fastcall *)(_DWORD *, int, char *, int *, _DWORD *))loc_403FF4)( a1: v29, a2: j, a3: v23, a4: &v27, a5: a4); v9 = v24 | v27 ^ 0x20; v25 = v9; if ( v9 != 0 ) v25 = 106; *a3 = v25; bzero_core(result: v28, a2: 0x20u); bzero_core(result: v29, a2: 0x10Cu); if ( v9 != 0 ) v9 = 6; LABEL_18: if ( dword_404334 == v30 ) break; v17 = ((int (__fastcall *)(int))loc_404338)(a1: dword_404334 - v30); LABEL_21: if ( a1[9] < 0x16u ) goto LABEL_13; v29[2] = v19; v29[3] = v17; } return v9; } /* ==== hdcp2_tx_RepeaterAuth_Send_Ack [tier=EXACT size=64] ==== */ int __fastcall hdcp2_tx_RepeaterAuth_Send_Ack(int a1, _BYTE *a2, unsigned int a3, _DWORD *a4, int *a5) { int result; // r0 int v7; // r1 result = 1; if ( a1 != 0 && a2 != nullptr && a4 != nullptr && a5 != nullptr ) { *a4 = 15; a4[1] = 17; *a5 = 100; // a4 if ( a3 < 0x11 ) { result = 21; v7 = 101; } else { *a2 = 15; sub_401058(); // unsigned int v7 = 0; result = 0; } *a5 = v7; } return result; } /* ==== hdcp2_tx_RepeaterAuth_Stream_Manage [tier=EXACT size=452] ==== */ int __fastcall hdcp2_tx_RepeaterAuth_Stream_Manage( struct hdcp2_session *a1, int *a2, unsigned int *a3, _QWORD *a4, int *a5) { int *v5; // r5 int v6; // r6 unsigned int *v7; // r7 _DWORD *v8; // r8 int *v9; // r10 struct hdcp2_session *v10; // r4 bool v11; // zf int result; // r0 unsigned int field250; // r2 int v14; // r1 char *v15; // r5 int v16; // r11 _BYTE *v17; // r1 char *v18; // r0 int v19; // r2 char v20; // t1 _DWORD v21[6]; // [sp+0h] [bp-3Ch] BYREF _DWORD v22[8]; // [sp+18h] [bp-24h] BYREF int v23; // [sp+38h] [bp-4h] v10 = a1; v11 = a1 == nullptr; v23 = dword_404334; result = 2; if ( !v11 ) { v5 = a2; if ( a2 != nullptr ) { v6 = (int)a4; if ( a4 != nullptr ) { v9 = a5; if ( a5 != nullptr ) { if ( v10->field18[2] <= 2 ) { v7 = a3; if ( v10->field10 == 6 ) { *a4 = 0x1400000010LL; *a5 = 100; if ( (unsigned int)a3 < 0x14 ) { result = 21; v14 = 101; } else { v6 = 1; v10->field250 = (v10->field250 + 1) & 0xFFFFFF; *(_BYTE *)a2 = 16; *((_BYTE *)a2 + 1) = v10->field250 >> 2; *((_BYTE *)a2 + 2) = v10->field250 >> 1; field250 = v10->field250; *((_BYTE *)a2 + 5) = 2; v14 = 0; *((_BYTE *)v5 + 4) = 0; *((_BYTE *)v5 + 3) = field250; LOBYTE(field250) = v10->field18[2]; *((_BYTE *)v5 + 6) = 0; v15 = (char *)v5 + 6; v15[7] = 0; v5 = (int *)(v15 + 7); *((_BYTE *)v5 - 3) = 16; *((_BYTE *)v5 + 6) = 0; *((_WORD *)v5 + 2) = 17; *((_BYTE *)v5 + 3) = 1; *((_BYTE *)v5 + 2) = 0; *((_BYTE *)v5 + 1) = 0; *((_BYTE *)v5 - 1) = field250; *((_BYTE *)v5 - 2) = 17; *((_BYTE *)v5 - 4) = 0; *((_BYTE *)v5 - 5) = 0; *((_BYTE *)v5 - 6) = 0; v10->fieldF9 = 0; v10 = (struct hdcp2_session *)((char *)v10 + 249); *(_WORD *)((char *)&v10[-1].field254[5] + 1) = 4368; v10->field0D = 14; result = 0; HIBYTE(v10[-1].field254[5]) = field250; LOBYTE(v10->field04) = 17; *(_WORD *)((char *)&v10->field04 + 1) = 0; v10->field02 = 0; v10->field03 = 1; v10->field01 = 0; *(_WORD *)((char *)&v10[-1].field254[4] + 1) = 0; *(_WORD *)((char *)&v10[-1].field254[4] + 3) = 0; } *a5 = v14; } else { v8 = v21; bzero_core(result: v21, a2: 0x14u); *(_QWORD *)v6 = 0x1A00000010LL; *a5 = 100; if ( (unsigned int)v7 < 0x1A ) { *a5 = 101; result = 21; } else { v7 = v22; v10->field250 = (v10->field250 + 1) & 0xFFFFFF; *(_BYTE *)v5 = 16; *((_BYTE *)v5 + 1) = v10->field250 >> 2; *((_BYTE *)v5 + 2) = v10->field250 >> 1; *((_BYTE *)v5 + 3) = v10->field250; if ( disp_hdcp2_stream_manage(a1: v10->field04, a2: (int)v22) == 0 ) goto LABEL_18; // a1 result = 17; } } } else { result = 1; } } } } } while ( dword_404334 != v23 ) { ((void (__fastcall *)(int, int))loc_404338)(a1: result, a2: dword_404334 - v23); LABEL_18: v16 = v22[0]; if ( v22[0] <= 0xAu ) { v17 = (char *)v8 + 1; *((_BYTE *)v5 + 4) = 0; v18 = (char *)(v7 + 1); v19 = v16; *((_BYTE *)v5 + 5) = v16; while ( v19 != 0 ) { v20 = *v18++; --v19; *(v17 - 1) = v20; *v17 = v10->field18[2]; v17 += 2; } v5 = v21; // result sub_401058(); // unsigned int v10->field106 = 2 * v16; // result sub_401058(); // int * *(_DWORD *)(v6 + 4) = 2 * v16 + 6; result = 0; *v9 = 0; } else { result = 23; } } return result; } /* ==== hdcp2_tx_SKE_Send_Eks [tier=EXACT size=786] ==== */ int __fastcall hdcp2_tx_SKE_Send_Eks(struct hdcp2_session *a1, _BYTE *a2, unsigned int a3, int *a4, _DWORD *a5) { int *v5; // r5 _DWORD *v6; // r10 int v11; // r6 bool v12; // zf unsigned int v14; // r2 int v15; // r0 int i; // r2 int v17; // r2 int v18; // r3 unsigned int v19; // r7 int j; // r1 int *v21; // r4 int *v22; // r0 char v23; // t1 unsigned __int8 *v24; // r6 unsigned __int8 v25; // r2 unsigned __int8 v26; // r5 unsigned __int8 v27; // r12 unsigned __int8 v28; // lr unsigned __int8 v29; // r0 unsigned __int8 v30; // r3 int v31; // r3 int v32; // r2 int v33; // r1 _DWORD *v34; // r1 unsigned __int8 v35; // r2 unsigned __int8 v36; // r0 unsigned __int8 v37; // r3 unsigned __int8 v38; // r1 unsigned __int8 v39; // r5 unsigned __int8 v40; // r6 _BYTE *v41; // r8 int v42; // [sp+8h] [bp-19Ch] BYREF unsigned int v43; // [sp+Ch] [bp-198h] BYREF _DWORD v44[8]; // [sp+10h] [bp-194h] BYREF _DWORD v45[2]; // [sp+30h] [bp-174h] BYREF _DWORD v46[66]; // [sp+38h] [bp-16Ch] BYREF int v47[4]; // [sp+140h] [bp-64h] BYREF int v48[2]; // [sp+150h] [bp-54h] BYREF int v49; // [sp+158h] [bp-4Ch] int v50; // [sp+15Ch] [bp-48h] int v51[2]; // [sp+160h] [bp-44h] BYREF int v52; // [sp+168h] [bp-3Ch] int v53; // [sp+16Ch] [bp-38h] int v54; // [sp+170h] [bp-34h] BYREF int v55; // [sp+174h] [bp-30h] int v56; // [sp+178h] [bp-2Ch] unsigned int v57; // [sp+17Ch] [bp-28h] _DWORD v58[2]; // [sp+180h] [bp-24h] BYREF int v59; // [sp+188h] [bp-1Ch] unsigned int v60; // [sp+18Ch] [bp-18h] int v61; // [sp+1A0h] [bp-4h] v5 = off_403EAC; v6 = v58; v61 = *off_403EAC; bzero_core(result: v58, a2: 0x20u); v11 = 1; v56 = 0; v57 = 0; v52 = 0; v53 = 0; v49 = 0; v50 = 0; v54 = 0; v55 = 0; v51[0] = 0; v51[1] = 0; v43 = 0; v48[0] = 0; v48[1] = 0; memset(v47, 0, sizeof(v47)); if ( a1 == nullptr ) goto LABEL_6; v12 = a2 == nullptr; if ( a2 != nullptr ) v12 = a4 == nullptr; if ( v12 ) goto LABEL_6; while ( 1 ) { if ( a5 == nullptr ) goto LABEL_6; *a4 = 11; v14 = 25; *a5 = 100; if ( a1->field18[3] > 0x16 ) v14 = 57; a4[1] = v14; if ( v14 > a3 ) { v11 = 21; *a5 = 101; goto LABEL_6; } *a2 = 11; gp_populate_transient_object_op35(a1: (int)a1->pad235, a2: 16);// a1 v58[1] = a1->field192[2] | (a1->field192[3] << 16); v58[0] = a1->field192[0] | (a1->field192[1] << 16); if ( a1->field18[3] < 0x16 ) { v59 = 0; v60 = 0; LOBYTE(v15) = 2; } else { v59 = a1->field107[0] | (a1->field107[1] << 8) | ((a1->field107[2] | (a1->field107[3] << 8)) << 16); v60 = a1->field107[4] | (a1->field107[5] << 8) | ((a1->field107[6] | (a1->field107[7] << 8)) << 16); v15 = HIBYTE(v60) ^ 2; } a4 = &v54; HIBYTE(v60) = v15; // int * sub_401058(); // result for ( i = 0; i != 8; ++i ) *((_BYTE *)&v56 + i) ^= a1->pad19A[i]; v17 = v55; v18 = v56; a3 = v57; v6[4] = v54; v6[5] = v17; v6[6] = v18; v6[7] = a3; if ( ((int (__fastcall *)(_DWORD *, int, int *, unsigned int *))loc_40332C)(a1: v6, a2: 32, a3: v51, a4: &v43) == 0 ) { v19 = v43; memcpy_aligned(result: v48, a2: v51, a3: v43);// unsigned int for ( j = 0; j != 8; ++j ) *((_BYTE *)&v49 + j) ^= a1->field107[j]; v21 = v47; sub_401058(); // result v22 = v48; while ( v19 != 0 ) { v23 = *(_BYTE *)v22; v22 = (int *)((char *)v22 + 1); --v19; *(_BYTE *)v21 ^= v23; v21 = (int *)((char *)v21 + 1); } v24 = &a1->pad235[16]; gp_populate_transient_object_op35(a1: (int)&a1->pad235[16], a2: 8);// a1 if ( a1->field10 != 6 || a1->field18[3] < 0x17 ) { sub_401058(); // unsigned int a4 = (int *)*v24; v35 = a1->field246[3]; v36 = a1->field246[4]; v37 = a1->field246[5]; v38 = a1->field246[6]; v39 = a1->field246[0]; a3 = a1->field246[1]; v40 = a1->field246[2]; a2[17] = (_BYTE)a4; v41 = a2 + 17; v41[4] = v35; a2 = v41 + 4; a2[1] = v36; *(a2 - 1) = v40; v11 = 0; a2[2] = v37; a2[3] = v38; *(a2 - 2) = a3; *(a2 - 3) = v39; *a5 = 0; goto LABEL_33; } bzero_core(result: v46, a2: 0x100u); v42 = 0; bzero_core(result: v44, a2: 0x20u); sub_401058(); // unsigned int a3 = *v24; v25 = a1->field246[3]; v26 = a1->field246[4]; v27 = a1->field246[5]; a4 = (int *)a1->field246[6]; v28 = a1->field246[0]; v29 = a1->field246[1]; v30 = a1->field246[2]; a2[17] = a3; a2[21] = v25; v6 = a2 + 21; a2[24] = (_BYTE)a4; a2[23] = v27; a2[22] = v26; a2[20] = v30; a2[19] = v29; a2[18] = v28; v31 = a1->field246[2]; // a4 v32 = a1->field246[1]; v33 = a1->field246[0]; v45[1] = a1->field246[3] | (a1->field246[4] << 8) | ((a1->field246[5] | (a1->field246[6] << 8)) << 16); v45[0] = *v24 | (v33 << 8) | ((v32 | (v31 << 8)) << 16);// int * sub_401058(); // unsigned int v46[64] = 0; if ( ((int (__fastcall *)(_DWORD *, int, _DWORD *, int *, int))loc_403FF4)( a1: v45, a2: 8, a3: v44, a4: &v42, a5: 32) != 0 ) { v34 = a5; } else { v34 = a5; if ( v42 == 32 ) { a4 = v44; *a5 = 0; sub_401058(); // unsigned int sub_401058(); // unsigned int LABEL_38: v5 = &dword_404334; v11 = 0; goto LABEL_34; } } *v34 = 106; goto LABEL_38; } v11 = 14; LABEL_33: v5 = (int *)loc_404110; LABEL_34: bzero_core(result: v58, a2: 0x20u); v56 = 0; v57 = 0; v51[0] = 0; v51[1] = 0; v48[0] = 0; v48[1] = 0; v54 = 0; v55 = 0; v52 = 0; v53 = 0; v49 = 0; v50 = 0; LABEL_6: if ( *v5 == v61 ) return v11; ((void (__fastcall *)(int))loc_404338)(a1: *v5 - v61); } } /* ==== hdcp2_tx_msg129 [tier=EXACT size=62] ==== */ int __fastcall hdcp2_tx_msg129(int a1, _BYTE *a2, unsigned int a3, _DWORD *a4, int *a5) { int result; // r0 int v7; // r1 result = 2; if ( a1 != 0 && a2 != nullptr && a4 != nullptr && a5 != nullptr ) { if ( *(_DWORD *)(a1 + 32) <= 2u ) { *a4 = 129; a4[1] = 2; *a5 = 100; if ( a3 < 2 ) { result = 21; v7 = 101; } else { *a2 = -127; a2[1] = *(_DWORD *)(a1 + 32); v7 = 0; result = 0; } *a5 = v7; } else { return 1; } } return result; } /* ==== hdcp2_tx_msg14 [tier=EXACT size=64] ==== */ int __fastcall hdcp2_tx_msg14(int a1, _BYTE *a2, unsigned int a3, _DWORD *a4, int *a5) { int result; // r0 int v7; // r1 result = 1; if ( a1 != 0 && a2 != nullptr && a4 != nullptr && a5 != nullptr ) { *a4 = 14; a4[1] = 17; *a5 = 100; // a4 if ( a3 < 0x11 ) { result = 21; v7 = 101; } else { *a2 = 14; sub_401058(); // unsigned int v7 = 0; result = 0; } *a5 = v7; } return result; } /* ==== hdcp2_tx_msg19 [tier=EXACT size=66] ==== */ int __fastcall hdcp2_tx_msg19(int a1, int a2, unsigned int a3, _DWORD *a4, int *a5) { int result; // r0 int v7; // r2 result = 1; if ( a1 != 0 && a2 != 0 && a4 != nullptr && a5 != nullptr ) { *a4 = 19; a4[1] = 6; *a5 = 100; if ( a3 < 6 ) { result = 21; v7 = 101; } else { *(_BYTE *)(a2 + 5) = 1; v7 = 0; *(_BYTE *)a2 = 19; *(_WORD *)(a2 + 3) = 3; *(_BYTE *)(a2 + 2) = 6; *(_BYTE *)(a2 + 1) = 0; *(_DWORD *)(a1 + 36) = 20; result = 0; } *a5 = v7; } return result; } /* ==== hdcp_TA_CloseSessionEntryPoint [tier=ENTRY size=2] ==== */ void hdcp_TA_CloseSessionEntryPoint() { ; } /* ==== hdcp_TA_DestroyEntryPoint [tier=ENTRY size=2] ==== */ void hdcp_TA_DestroyEntryPoint() { ; } /* ==== hdcp_close_all_sessions [tier=EXACT size=146] ==== */ int __fastcall hdcp_close_all_sessions() { int v0; // r7 int v1; // r4 int v2; // r8 int v3; // r5 int v4; // r0 int v5; // r9 int v6; // r6 int v7; // r6 v0 = dword_4034DC; v1 = 0; v2 = 0; while ( v1 != 5216 ) { v3 = v0 + v1; if ( *(_DWORD *)(v0 + v1 + 8) == 1 ) { v4 = *(_DWORD *)(v0 + v1); if ( v4 == 2 ) { v7 = disp_hdcp2_teardown(a1: v3 + 616); // a1 if ( disp_hdcp2_disable(a1: *(_DWORD *)(v3 + 4)) != 0 )// a1 { v2 = 20; } else { bzero_core(result: (_DWORD *)(v0 + v1), a2: 0x28Cu); if ( v7 != 0 ) v2 = 17; } } else if ( v4 == 1 ) { v5 = disp_hdcp1_teardown(a1: v3 + 64); // a1 v6 = disp_hdcp1_disable(a1: *(_DWORD *)(v3 + 4));// a1 if ( disp_link_reset(a1: *(_DWORD *)(v3 + 4), a2: 0) != 0 )// a2 { v2 = 1; } else { bzero_core(result: (_DWORD *)(v0 + v1), a2: 0x28Cu); if ( (v6 | v5) != 0 ) v2 = 1; } } } v1 += 652; } return v2; } /* ==== hdcp_get_srm_status [tier=EXACT size=32] ==== */ int __fastcall hdcp_get_srm_status(int a1) { if ( a1 != 0 ) return 8 * (disp_srm_read(a1, a2: 5120, a3: a1 + 4, a4: a1 + 8) != 0);// a2 else return 5; } /* ==== hdcp_session_teardown [tier=EXACT size=84] ==== */ int __fastcall hdcp_session_teardown(_DWORD *a1) { int v2; // r0 bool v3; // zf int v4; // r5 int v5; // r8 __int64 v6; // r6 v2 = a1[2]; v3 = v2 == 1; if ( v2 == 1 ) v3 = *a1 == 1; v4 = !v3; v5 = disp_hdcp1_teardown(a1: (int)(a1 + 16)); // a1 HIDWORD(v6) = disp_hdcp1_disable(a1: a1[1]); // a1 LODWORD(v6) = disp_link_reset(a1: a1[1], a2: 0);// a2 bzero_core(result: a1, a2: 0x28Cu); if ( v5 != 0 ) v4 = 17; if ( v6 != 0 ) return 1; return v4; } /* ==== hdcp_set_protection [tier=EXACT size=34] ==== */ int __fastcall hdcp_set_protection(int *a1, int a2) { if ( a1 != nullptr && *a1 != 0 ) return 8 * (disp_srm_store(a1: *a1, a2: (int)(a1 + 1), a3: a2 + 4, a4: a2) != 0);// a1 else return 5; } /* ==== memcmp_be [tier=EXACT size=88] ==== */ int __fastcall memcmp_be(unsigned int *a1, unsigned int *a2, unsigned int a3) { unsigned int v3; // r4 unsigned int v4; // r3 int v6; // r3 int v7; // t1 int v8; // t1 int v9; // r3 int v10; // r3 int v11; // t1 int v12; // t1 if ( ((unsigned int)a1 | (unsigned int)a2) << 30 == 0 ) { while ( a3 >= 4 ) { v3 = *a1++; v4 = *a2++; a3 -= 4; if ( v3 != v4 ) { if ( bswap32(v3) <= bswap32(v4) ) return -1; else return 1; } } } if ( a3 == 0 ) return 0; if ( a3 << 31 == 0 ) goto LABEL_11; ++a3; do { v11 = *(unsigned __int8 *)a1; a1 = (unsigned int *)((char *)a1 + 1); v10 = v11; v12 = *(unsigned __int8 *)a2; a2 = (unsigned int *)((char *)a2 + 1); v9 = v10 - v12; if ( v9 != 0 ) break; a3 -= 2; if ( a3 == 0 ) break; LABEL_11: v7 = *(unsigned __int8 *)a1; a1 = (unsigned int *)((char *)a1 + 1); v6 = v7; v8 = *(unsigned __int8 *)a2; a2 = (unsigned int *)((char *)a2 + 1); v9 = v6 - v8; } while ( v9 == 0 ); return v9; } /* ==== memcpy_aligned [tier=EXACT size=100] ==== */ int *__fastcall memcpy_aligned(int *result, int *a2, unsigned int a3) { int v3; // r3 unsigned int i; // r2 int *v5; // r1 int v6; // r3 int v7; // r4 int v8; // r12 int v9; // lr int *v10; // r0 int v11; // r4 int v12; // r12 int v13; // lr int v14; // r4 int v15; // r12 int v16; // lr int v17; // r4 int v18; // t1 bool v19; // cf bool v20; // nf int v21; // r2 __int16 v22; // t1 v19 = a3 >= 0x20; for ( i = a3 - 32; v19; i -= 32 ) { v6 = *a2; v7 = a2[1]; v8 = a2[2]; v9 = a2[3]; v5 = a2 + 4; *result = v6; result[1] = v7; result[2] = v8; result[3] = v9; v10 = result + 4; v3 = *v5; v11 = v5[1]; v12 = v5[2]; v13 = v5[3]; a2 = v5 + 4; *v10 = v3; v10[1] = v11; v10[2] = v12; v10[3] = v13; result = v10 + 4; v19 = i >= 0x20; } if ( __CFSHL__(i, 28) ) { v3 = *a2; v14 = a2[1]; v15 = a2[2]; v16 = a2[3]; a2 += 4; *result = v3; result[1] = v14; result[2] = v15; result[3] = v16; result += 4; } if ( (i & 8) != 0 ) { v3 = *a2; v17 = a2[1]; a2 += 2; *result = v3; result[1] = v17; result += 2; } if ( __CFSHL__(i, 30) ) { v18 = *a2++; LOWORD(v3) = v18; *result++ = v18; } if ( i << 30 != 0 ) { v19 = __CFSHL__(i, 31); v21 = i << 31; v20 = v21 < 0; if ( v19 ) { v22 = *(_WORD *)a2; a2 = (int *)((char *)a2 + 2); LOWORD(v3) = v22; } if ( v21 < 0 ) LOBYTE(v21) = *(_BYTE *)a2; if ( v19 ) { *(_WORD *)result = v3; result = (int *)((char *)result + 2); } if ( v20 ) { *(_BYTE *)result = v21; return (int *)((char *)result + 1); } } return result; } /* ==== receiver_id_lookup [tier=EXACT size=88] ==== */ int __fastcall receiver_id_lookup(int a1) { int v2; // r7 unsigned int *i; // r5 v2 = 16; for ( i = (unsigned int *)(dword_40237C + 5216); ; i += 15 ) { if ( v2 == 0 ) return 1; if ( i[14] != 0 && memcmp_be(a1: i, a2: (unsigned int *)(a1 + 79), a3: 5u) == 0 ) break; --v2; } sub_401058(); // unsigned int sub_401058(); // unsigned int sub_401058(); // unsigned int return 0; } /* ==== stream_slot_alloc [tier=EXACT size=88] ==== */ int __fastcall stream_slot_alloc(int a1) { int v1; // r4 int i; // r0 v1 = dword_4034DC + 5216; for ( i = 16; ; --i ) { if ( i == 0 ) return 1; if ( *(_DWORD *)(v1 + 56) == 0 ) break; v1 += 60; } sub_401058(); // unsigned int sub_401058(); // unsigned int sub_401058(); // unsigned int sub_401058(); // unsigned int *(_DWORD *)(v1 + 56) = 1; return 0; } /* ==== sysdrv_rpc_1087 [tier=EXACT size=56] ==== */ // Call into SYS_DRV via SVC 0xF2 (target process 1), opcode 0x1087. // Opcodes below 0x1000 are handled by gp_crypto_dispatch in sys_drv2.elf - this is the // GlobalPlatform Cryptographic Operations API. Frame is 0x80 bytes: frame[0]=opcode, // frame[1]=msg class, arguments from frame[14]. int __fastcall sysdrv_rpc_1087(int a1) { _DWORD v6[12]; // [sp+8h] [bp-78h] BYREF bzero_core(result: v6, a2: 0x20u); __asm { SVC 0xF2 } return 1; } /* ==== ta_main_loop [tier=EXACT size=148] ==== */ // TA main loop (never returns). Waits for a command with SVC 0xF0, reads the command id // from frame[0] and vectors through ta_entry_tbl, then returns the result with SVC 0xF1. // For command 3 (invoke) it marshals the GP arguments: // r0 = frame[3] (commandID) r1 = &frame[4] (TEE_Param params[4]) // r2 = &frame[2] (sessionContext) void __fastcall __noreturn ta_main_loop(int *a1) { int v6; // r1 void (__cdecl *v7)(); // r12 while ( 1 ) { __asm { SVC 0xF0 } v6 = *a1; if ( *a1 == 1 ) { v7 = (void (__cdecl *)())loc_404340; } else { switch ( v6 ) { case 2: v7 = (void (__cdecl *)())loc_404344; break; case 3: v7 = (void (__cdecl *)())loc_404348; break; case 4: v7 = (void (__cdecl *)())loc_40434C; break; case 5: v7 = (void (__cdecl *)())loc_404350; break; default: while ( 1 ) ; } } v7(); __asm { SVC 0xF1 } } } /* ==== udiv32 [tier=EXACT size=36] ==== */ unsigned int __fastcall udiv32(unsigned int a1, unsigned int a2) { bool v2; // cf BOOL v3; // r2 bool v4; // cf int v5; // r2 bool v6; // cf bool v7; // cf int v8; // r2 bool v9; // cf int v10; // r2 bool v11; // cf bool v12; // cf unsigned int v14; // r1 int v15; // r2 char v16; // cf bool v17; // cf int v18; // r2 bool v19; // cf int v20; // r2 bool v21; // cf int v22; // r2 bool v23; // cf int v24; // r2 bool v25; // cf int v26; // r2 bool v27; // cf int v28; // off bool v29; // cf unsigned int v30; // r1 int v31; // r2 v31 = 0; if ( a1 >> 2 < a2 ) { LABEL_18: v12 = a1 >> 1 >= a2; if ( a1 >> 1 >= a2 ) a1 -= 2 * a2; return v31 + v12 + v31 + (a1 >= a2) + v31 + v12 + v31; } if ( a1 >> 5 < a2 ) { LABEL_11: v7 = a1 >> 4 >= a2; if ( a1 >> 4 >= a2 ) a1 -= 16 * a2; v8 = v31 + v7 + v31; v9 = a1 >> 3 >= a2; if ( a1 >> 3 >= a2 ) a1 -= 8 * a2; v10 = v8 + v9 + v8; v11 = a1 >> 2 >= a2; if ( a1 >> 2 >= a2 ) a1 -= 4 * a2; v31 = v10 + v11 + v10; goto LABEL_18; } if ( a1 >> 8 < a2 ) { v2 = a1 >> 7 >= a2; if ( a1 >> 7 >= a2 ) a1 -= a2 << 7; v3 = v2; v4 = a1 >> 6 >= a2; if ( a1 >> 6 >= a2 ) a1 -= a2 << 6; v5 = v3 + v4 + v3; v6 = a1 >> 5 >= a2; if ( a1 >> 5 >= a2 ) a1 -= 32 * a2; v31 = v5 + v6 + v5; goto LABEL_11; } v14 = a2 << 6; v15 = -67108864; if ( a1 >> 8 < v14 ) goto LABEL_28; v14 <<= 6; v15 = -1048576; if ( a1 >> 8 < v14 ) goto LABEL_28; v14 <<= 6; v15 = -16384; if ( a1 >> 8 >= v14 ) { v14 <<= 6; v15 = -256; } v16 = v14 == 0; if ( v14 != 0 ) { do { if ( v16 ) v14 >>= 6; LABEL_28: v17 = a1 >> 7 >= v14; if ( a1 >> 7 >= v14 ) a1 -= v14 << 7; v18 = v15 + v17 + v15; v19 = a1 >> 6 >= v14; if ( a1 >> 6 >= v14 ) a1 -= v14 << 6; v20 = v18 + v19 + v18; v21 = a1 >> 5 >= v14; if ( a1 >> 5 >= v14 ) a1 -= 32 * v14; v22 = v20 + v21 + v20; v23 = a1 >> 4 >= v14; if ( a1 >> 4 >= v14 ) a1 -= 16 * v14; v24 = v22 + v23 + v22; v25 = a1 >> 3 >= v14; if ( a1 >> 3 >= v14 ) a1 -= 8 * v14; v26 = v24 + v25 + v24; v27 = a1 >> 2 >= v14; if ( a1 >> 2 >= v14 ) a1 -= 4 * v14; v28 = v27 + v26; v16 = __CFADD__(v27, v26) | __CFADD__(v26, v28); v15 = v26 + v28; } while ( v16 ); v29 = a1 >> 1 >= v14; if ( a1 >> 1 >= v14 ) a1 -= 2 * v14; return v15 + v29 + v15 + (a1 >= v14) + v15 + v29 + v15; } else { v30 = a1 & 0x80000000; if ( (int)a1 > 0 ) return 0x7FFFFFFF; return v30; } }