📄 psfdemux_drm.c
字号:
type = DEMUX_WRITE_AES_128BITS_KEY_IV; break; case EMhwlibCipher_RC4: /* 2 */ RMDBGLOG(( ENABLE, "Unimplemented cipher type \n" )); status = RM_NOTIMPLEMENTED; goto error_exit; case EMhwlibCipher_DVD: /* 3 */ RMDBGLOG(( ENABLE, "Unimplemented cipher type \n" )); status = RM_NOTIMPLEMENTED; goto error_exit; case EMhwlibCipher_Multi2: /* 4 */ is_multi2 = TRUE; /* special case */ break; case EMhwlibCipher_DVBCSA: /* 5 */ type = DEMUX_WRITE_DVB_64BITS; break; case EMhwlibCipher_C2: /* 6 */ default: RMDBGLOG(( ENABLE, "Unknow cipher type \n" )); status = RM_NOTIMPLEMENTED; goto error_exit; } if( is_multi2 ) { /* TODO: write key for multi2 DEMUX_WRITE_MULTI2_SYSTEM_KEY, DEMUX_WRITE_MULTI2_256BITS_DATA_KEY, DEMUX_WRITE_MULTI2_DATA_KEY, DEMUX_WRITE_MULTI2_IV, DEMUX_WRITE_MULTI2 */ RMDBGLOG(( ENABLE, "multi2 not implemented \n" )); status = RM_NOTIMPLEMENTED; goto error_exit; } /* Allocate an RUA buffer for XRPC commuication */ xrpc_base_addr = RUAMalloc(pRUA, 0, RUA_DRAM_UNPROTECTED, xrpc_size); if (xrpc_base_addr == 0) { RMDBGLOG(( ENABLE, "RUAMalloc failed\n" )); status = RM_ERROR; goto error_exit; } status = initDemuxWriteKey(xrpc_base_addr,xrpc_size,1); if ( status != RM_OK ) { RMDBGLOG(( ENABLE, "initDemuxWriteKey error \n" )); goto error_exit; }#define GENERATE_KEY#ifdef GENERATE_KEY if( type != DEMUX_WRITE_AES_128BITS_KEY_IV ){ status = RM_NOTIMPLEMENTED; goto error_exit; } /* harded xpu key index and aes key ram key index */ status = generateInternalDemuxAesKey( context->recipher_xpu_key ); if ( status != RM_OK ) { status = RM_ERROR; RMDBGLOG(( ENABLE, "generateDemuxAesKey error \n" )); /* fall through try to terminate the module */ } fprintf(stderr, "generateInternalDemuxAesKey xpu_key %ld %s \n", context->recipher_xpu_key, status == RM_OK ? "OK" : "FAIL"); status = setInternalDemuxAesKey( context->recipher_xpu_key, /* key index in xpu's storage */ key_index ); /* key index in AES cipher's key ram */ fprintf(stderr, "SetInternalDemuxAesKey xpu_index %ld to demux_key %ld %s\n", context->recipher_xpu_key, key_index, status == RM_OK ? "OK" : "FAIL"); if ( status != RM_OK ) { status = RM_ERROR; RMDBGLOG(( ENABLE, "setInternalDemuxAesKey error \n" )); /* fall through try to terminate the module */ }#else status = setDemuxCipherKey( pKey, type, FALSE, key_index ); if ( status != RM_OK ) { status = RM_ERROR; RMDBGLOG(( ENABLE, "setDemuxWriteKey error \n" )); /* fall through try to terminate the module */ }#endif status = termDemuxWriteKey(); if ( status != RM_OK ) { RMDBGLOG(( ENABLE, "termDemuxWriteKey error \n" )); goto error_exit; } error_exit: if( xrpc_base_addr ) RUAFree( pRUA, xrpc_base_addr ); return status;}#endif /* #ifdef USE_XPU_WRITE_KEY *//************************************************************************ * A portion of ARIB STD B25.pdf -- Page 20 ************************************************************************/static RMstatus ParseAribECM(RMuint8 *pBuffer1, RMuint32 size1, RMuint8 *pBuffer2, RMuint32 size2, enum key_type *key_type, RMuint8 *key_code){ /* function assumes to be called on correct ECM boundaries */ RMuint8 * p = 0; if (pBuffer1 && size1) p = pBuffer1; if (*p == 0x80) { *key_type = EVEN_KEY; RMMemcpy(key_code, p + 11, 16); /* No spec, use Arib replace */ } else if (*p == 0x81) { *key_type = ODD_KEY; RMMemcpy(key_code, p + 11, 16); /* No spec, use Arib replace */ } else if (*p == 0x82) { /* DVD-Arib */ *key_type = PAIR_KEY; RMMemcpy(key_code, p + 11, 16); /* odd 8bytes, even 8Bytes */ } else { *key_type = WRONG_KEY; fprintf(stderr, "ParseAribECM table_id=%02x instead of 0x8? !\n", *p); return RM_ERROR; } return RM_OK;}static RMstatus ParseECM(RMuint8 *pBuffer1, RMuint32 size1, RMuint8 *pBuffer2, RMuint32 size2, RMstatus err, RMuint32 mask, void *context_in){ struct context_per_task *context = (struct context_per_task *)context_in; RMuint8 *p; RMuint32 key_i; RMuint32 section_len, ecm_data_compare_len; RMuint8 section_table_entry = (mask == ECM0_SECTION_MASK) ? ECM0_SECTION_ENTRY : ECM1_SECTION_ENTRY; p = pBuffer1; if ( (*p == 0x80) || (*p == 0x81) ) { section_len = ((*(p + 1) & 0x0F) << 8) | *(p + 2); if (section_len > 8) ecm_data_compare_len = RMmin(section_len - 8, 16); else ecm_data_compare_len = 0;#if 0 { RMuint32 i; fprintf(stderr, "[%02X][%d]@0x%lX:\t", *p, section_table_entry, context->file_byte_counter); for (i = 0; i < ecm_data_compare_len; i++) fprintf(stderr, "0x%02X, ", *(p+11+i)); fprintf(stderr, "\n"); }#endif if (context->app_type == dvbcsa_decryption) { /* new key detected, identify based on ecm_data the clear key provided in key specific table */#if 0 // Hard code for wired test stream STREAM-4.ts#if 0 // video uses ecm0 (0x501); audio uses ecm1 (0x502); if (*p == 0x80) { key_i = 0 + ((mask == ECM0_SECTION_MASK) ? 0 : 2); } else { key_i = 1 + ((mask == ECM0_SECTION_MASK) ? 0 : 2); } fprintf(stderr, "ParseECM DVB-CSA new key [%02x] at byte counter = 0x%lx key_position=%ld\n", *p, context->file_byte_counter, key_i); ((struct dvb_csa_key *)context->pkey_table)[key_i].renew = TRUE; ((struct dvb_csa_key *)context->pkey_table)[key_i].ecm_entry = section_table_entry; ((struct dvb_csa_key *)context->pkey_table)[key_i].key_byte_counter = context->file_byte_counter; ((struct dvb_csa_key *)context->pkey_table)[key_i].scrambling = (*p == 0x80) ? EMhwlibScramblingBits_10 : EMhwlibScramblingBits_11;#else // video and audio uses ecm0 (0x501) if (*p == 0x80) { key_i = 0; } else { key_i = 1; } fprintf(stderr, "ParseECM DVB-CSA new key [%02x] at byte counter = 0x%lx key_position=%ld\n", *p, context->file_byte_counter, key_i); ((struct dvb_csa_key *)context->pkey_table)[key_i].renew = TRUE; ((struct dvb_csa_key *)context->pkey_table)[key_i].ecm_entry = section_table_entry; ((struct dvb_csa_key *)context->pkey_table)[key_i].key_byte_counter = context->file_byte_counter; ((struct dvb_csa_key *)context->pkey_table)[key_i].scrambling = (*p == 0x80) ? EMhwlibScramblingBits_10 : EMhwlibScramblingBits_11; ((struct dvb_csa_key *)context->pkey_table)[key_i + 2].renew = TRUE; ((struct dvb_csa_key *)context->pkey_table)[key_i + 2].ecm_entry = section_table_entry + 1; ((struct dvb_csa_key *)context->pkey_table)[key_i + 2].key_byte_counter = context->file_byte_counter; ((struct dvb_csa_key *)context->pkey_table)[key_i + 2].scrambling = (*p == 0x80) ? EMhwlibScramblingBits_10 : EMhwlibScramblingBits_11;#endif#else for (key_i = 0; key_i < context->key_table_size; key_i++) { if (RMMemcmp((void*)(p+11), (void *)((struct dvb_csa_key *)context->pkey_table)[key_i].ecm_data, ecm_data_compare_len)==0) { fprintf(stderr, "ParseECM DVB-CSA new key [%02x] at byte counter = 0x%lx key_position=%ld\n", *p, context->file_byte_counter, key_i); ((struct dvb_csa_key *)context->pkey_table)[key_i].renew = TRUE; ((struct dvb_csa_key *)context->pkey_table)[key_i].ecm_entry = section_table_entry; ((struct dvb_csa_key *)context->pkey_table)[key_i].key_byte_counter = context->file_byte_counter; ((struct dvb_csa_key *)context->pkey_table)[key_i].scrambling = (*p == 0x80) ? EMhwlibScramblingBits_10 : EMhwlibScramblingBits_11; break; } }#endif } else if ((context->app_type == aes_cbc_decryption) || (context->app_type == aes_ecb_decryption) || (context->app_type == aes_nsa_decryption) || (context->app_type == aes_ofb_decryption) ) { /* new key detected, identify based on ecm_data the clear key provided in key specific table */ for (key_i = 0; key_i < context->key_table_size; key_i++) { if (RMMemcmp((void*)(p+11), (void *)((struct aes_key *)context->pkey_table)[key_i].ecm_data, ecm_data_compare_len)==0) { fprintf(stderr, "ParseECM AES new key [%02x] at byte counter = 0x%lx key_position=%ld\n", *p, context->file_byte_counter, key_i); ((struct aes_key *)context->pkey_table)[key_i].renew = TRUE; ((struct aes_key *)context->pkey_table)[key_i].ecm_entry = section_table_entry; ((struct aes_key *)context->pkey_table)[key_i].key_byte_counter = context->file_byte_counter; ((struct aes_key *)context->pkey_table)[key_i].scrambling = (*p == 0x80) ? EMhwlibScramblingBits_10 : EMhwlibScramblingBits_11; break; } } } { /* filter only a new ecm version in hardware section filter - in order to optimize CPU usage on standalone */ /* mask ECM for next parity */ struct DemuxTask_MatchSectionEntry_type section_entry; //fprintf(stderr, "@0x%lX ParseECM tag is 0x%02x for [%d], change to 0x%02x\n", context->file_byte_counter, (*p), section_table_entry, (*p) ^ 1); context->match_section_table[section_table_entry].section_entry.mask[0] = 0xFF; context->match_section_table[section_table_entry].section_entry.comp[0] = (*p) ^ 1; section_entry.Index = context->match_section_table[section_table_entry].index; section_entry.SectionEntry = context->match_section_table[section_table_entry].section_entry; err = RUASetProperty(context->pRUA, context->demux_task, RMDemuxTaskPropertyID_MatchSectionEntry, §ion_entry, sizeof(section_entry), 0); if (RMFAILED(err)) { fprintf(stderr, "decoder: Error RMDemuxTaskPropertyID_MatchSectionEntry"); return RM_ERROR; } } } return RM_OK;}void ECMCallback(RMuint8 *pBuffer1, RMuint32 size1, RMuint8 *pBuffer2, RMuint32 size2, RMstatus err, RMuint32 mask, void *context_in){ RMuint8 key_code[16]; // for both EVEN/ODD key inside ECM packet enum key_type key_type; /* EVEN? ODD? PAIR? or BAD key */ RMuint32 cipher_i; struct context_per_task *context = (struct context_per_task *)context_in; struct arib_key_band *ecm_key = context->arib_key_table; struct dvb_arib_key *key_table = (struct dvb_arib_key *)context->pkey_table; RMuint8 * last_key_code = context->prev_encrypted_key; if (RMFAILED(err)) { RMDBGLOG((ENABLE, "ECMCallback ERROR\n")); return; }#ifdef MULTI2_EIGHT_KEYS // hard code the mapping between section filters and cipher entry because this mapping is hard coded in psfdemux_parsing cipher_i = (mask == ECM0_SECTION_MASK) ? 0 : (mask == ECM1_SECTION_MASK) ? 1 : (mask == (1<<(DATA_SEC+7 ))) ? 2 : (mask == (1<<(DATA_SEC+8 ))) ? 3 : (mask == (1<<(DATA_SEC+9 ))) ? 4 : (mask == (1<<(DATA_SEC+10 ))) ? 5 : (mask == (1<<(DATA_SEC+11 ))) ? 6 : (mask == (1<<(DATA_SEC+12 ))) ? 7 : 0xff; //bad index causes a crash#else //#ifdef MULTI2_EIGHT_KEYS cipher_i = (mask == ECM0_SECTION_MASK) ? 0 : 1; // two pair of keys#endif RMDBGLOG((DISABLE, "ECMCallback for %d\n", cipher_i)); /* * TODO -- * Pass the ECM package to customer's sand box * Fox example: * * TX4939_ECM(pBuffer1, size1, pBuffer2, size2, &key_type, key_code); */ // DVB-Arib: extract EVEV/ODD key from ECM packet ParseAribECM(pBuffer1, size1, pBuffer2, size2, &key_type, key_code); if ((context->app_type == multi2_decryption) && (key_type == PAIR_KEY)) { if(RMMemcmp((void*)last_key_code, (void *)key_code, 16) != 0) { // new key arriaved RMuint32 match; RMuint32 key_i; RMMemcpy(last_key_code, key_code, 16); // find the encrypted key patten in the pattern-clearkey table for( match = 0; match < context->key_table_size; match++ ) { if (RMMemcmp((void*)last_key_code, (void *)key_table[match].pair_key, 16) == 0) { break; // find the real key } } if( match >= context->key_table_size ) { // pattern not found, no clear key RMDBGLOG((KEYDBG, "cannot find pattern 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x \n", key_code[0], key_code[1], key_code[2], key_code[3], key_code[4], key_code[5], key_code[6], key_code[7], key_code[8], key_code[9], key_code[10], key_code[11], key_code[12], key_code[13], key_code[14], key_code[15] )); return; } else{ RMDBGLOG((KEYDBG, "found pattern 0x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x \n", key_code[0], key_code[1], key_code[2], key_code[3], key_code[4], key_code[5], key_code[6], key_code[7], key_code[8], key_code[9], key_code[10], key_code[11], key_code[12], key_code[13], key_code[14], key_code[15] )); } // find which key to load key_i = cipher_i * 2; ecm_key[key_i].index_cipher_table = context->cipher_index[cipher_i]; ecm_key[key_i+1].index_cipher_table = context->cipher_index[cipher_i]; // update system key and iv for all ecm in case they change RMMemcpy(ecm_key[key_i].multi2_key.system_key, key_table[match].sys_key, 32); RMMemcpy(ecm_key[key_i].multi2_key.iv, key_table[match].cbc_iv, 8); RMMemcpy(ecm_key[key_i+1].multi2_key.system_key, key_table[match].sys_key, 32); RMMemcpy(ecm_key[key_i+1].multi2_key.iv, key_table[match].cbc_iv, 8); // Handle EVEN key first -- keep the index of Multi2Table if (RMMemcmp((void*)(ecm_key[key_i].multi2_key.data_key), (void *)(key_table[match].data + 8), 8) != 0) { RMMemcpy(ecm_key[key_i].multi2_key.data_key, (key_table[match].data + 8), 8); RMMemcpy(ecm_key[key_i].cipher_text, (key_table[match].cipher + 32), 32 * sizeof(RMuint32)); ecm_key[key_i].new_key = TRUE; context->ecm = TRUE; // inform the main loop to load the key RMDBGLOG((KEYDBG, "update new even key cipher %ld key %ld\n", context->cipher_index[cipher_i], ecm_key[key_i].multi2_key.key_index)); } // Then handle ODD key -- keep the index of Multi2Table if (RMMemcmp((void*)(ecm_key[key_i+1].multi2_key.data_key), (void *)(key_table[match].data), 8) != 0) { RMMemcpy(ecm_key[key_i+1].multi2_key.data_key, key_table[match].data, 8); RMMemcpy(ecm_key[key_i+1].cipher_text, key_table[match].cipher, 32 * sizeof(RMuint32)); ecm_key[key_i+1].new_key = TRUE; context->ec
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -