代码拉取完成,页面将自动刷新
#define MODULE_LOG_PREFIX "emu"
#include "globals.h"
#ifdef WITH_EMU
#include "cscrypt/des.h"
#include "module-emulator-osemu.h"
#include "oscam-string.h"
static inline void xxor(uint8_t *data, int32_t len, const uint8_t *v1, const uint8_t *v2)
{
uint32_t i;
switch (len)
{
case 16:
for (i = 0; i < 16; ++i)
{
data[i] = v1[i] ^ v2[i];
}
break;
case 8:
for (i = 0; i < 8; ++i)
{
data[i] = v1[i] ^ v2[i];
}
break;
case 4:
for (i = 0; i < 4; ++i)
{
data[i] = v1[i] ^ v2[i];
}
break;
default:
while (len--)
{
*data++ = *v1++ ^ *v2++;
}
break;
}
}
// Irdeto EMU
static int8_t get_key(uint8_t *buf, uint32_t ident, char keyName, uint32_t keyIndex,
uint8_t isCriticalKey, uint32_t *keyRef)
{
char keyStr[EMU_MAX_CHAR_KEYNAME];
if (*keyRef > 0xFF)
{
return 0;
}
snprintf(keyStr, EMU_MAX_CHAR_KEYNAME, "%c%X", keyName, keyIndex);
if (emu_find_key('I', ident, 0, keyStr, buf, 16, *keyRef > 0 ? 0 : isCriticalKey, *keyRef, 0, NULL))
{
(*keyRef)++;
return 1;
}
return 0;
}
static void irdeto2_encrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
{
int32_t i;
const uint8_t *tmp = seed;
uint32_t ks1[32], ks2[32];
des_set_key(key, ks1);
des_set_key(key + 8, ks2);
len &= ~7;
for (i = 0; i + 7 < len; i += 8)
{
xxor(&data[i], 8, &data[i], tmp);
tmp = &data[i];
des(&data[i], ks1, 1);
des(&data[i], ks2, 0);
des(&data[i], ks1, 1);
}
}
static void irdeto2_decrypt(uint8_t *data, const uint8_t *seed, const uint8_t *key, int32_t len)
{
int32_t i, n = 0;
uint8_t buf[2][8];
uint32_t ks1[32], ks2[32];
des_set_key(key, ks1);
des_set_key(key + 8, ks2);
len &= ~7;
memcpy(buf[n], seed, 8);
for (i = 0; i + 7 < len; i += 8, data += 8, n ^= 1)
{
memcpy(buf[1 - n], data, 8);
des(data, ks1, 0);
des(data, ks2, 1);
des(data, ks1, 0);
xxor(data, 8, data, buf[n]);
}
}
static int8_t calculate_hash(const uint8_t *key, const uint8_t *iv, const uint8_t *data, int32_t len)
{
int32_t l, y;
uint8_t cbuff[8];
uint32_t ks1[32], ks2[32];
des_set_key(key, ks1);
des_set_key(key + 8, ks2);
memset(cbuff, 0, sizeof(cbuff));
len -= 8;
for (y = 0; y < len; y += 8)
{
if (y < len - 8)
{
xxor(cbuff, 8, cbuff, &data[y]);
}
else
{
l = len - y;
xxor(cbuff, l, cbuff, &data[y]);
xxor(cbuff + l, 8 - l, cbuff + l, iv + 8);
}
des(cbuff, ks1, 1);
des(cbuff, ks2, 0);
des(cbuff, ks1, 1);
}
return memcmp(cbuff, &data[len], 8) == 0;
}
int8_t irdeto2_ecm(uint16_t caid, uint8_t *oecm, uint8_t *dw)
{
uint8_t keyNr = 0, length, end, key[16], okeySeed[16], keySeed[16], keyIV[16], tmp[16];
uint8_t ecmCopy[EMU_MAX_ECM_LEN], *ecm = oecm;
uint16_t ecmLen = SCT_LEN(ecm);
uint32_t key0Ref, keySeedRef, keyIVRef, ident, i, j, l;
if (ecmLen < 12)
{
return EMU_NOT_SUPPORTED;
}
length = ecm[11];
keyNr = ecm[9];
ident = ecm[8] | caid << 8;
if (ecmLen < length + 12)
{
return EMU_NOT_SUPPORTED;
}
key0Ref = 0;
while (get_key(key, ident, '0', keyNr, 1, &key0Ref))
{
keySeedRef = 0;
while (get_key(okeySeed, ident, 'M', 1, 1, &keySeedRef))
{
keyIVRef = 0;
while (get_key(keyIV, ident, 'M', 2, 1, &keyIVRef))
{
memcpy(keySeed, okeySeed, 16);
memcpy(ecmCopy, oecm, ecmLen);
ecm = ecmCopy;
memset(tmp, 0, 16);
irdeto2_encrypt(keySeed, tmp, key, 16);
ecm += 12;
irdeto2_decrypt(ecm, keyIV, keySeed, length);
i = (ecm[0] & 7) + 1;
end = length - 8 < 0 ? 0 : length - 8;
while (i < end)
{
l = ecm[i + 1] ? (ecm[i + 1] & 0x3F) + 2 : 1;
switch (ecm[i])
{
case 0x10:
case 0x50:
if (l == 0x13 && i <= length - 8 - l)
{
irdeto2_decrypt(&ecm[i + 3], keyIV, key, 16);
}
break;
case 0x78:
if (l == 0x14 && i <= length - 8 - l)
{
irdeto2_decrypt(&ecm[i + 4], keyIV, key, 16);
}
break;
}
i += l;
}
i = (ecm[0] & 7) + 1;
if (calculate_hash(keySeed, keyIV, ecm - 6, length + 6))
{
while (i < end)
{
l = ecm[i + 1] ? (ecm[i + 1] & 0x3F) + 2 : 1;
switch (ecm[i])
{
case 0x78:
{
if (l == 0x14 && i <= length - 8 - l)
{
memcpy(dw, &ecm[i + 4], 16);
for (j = 0; j < 16; j += 4) // fix dw checksum bytes
{
dw[j + 3] = (dw[j] + dw[j + 1] + dw[j + 2]) & 0xFF;
}
return EMU_OK;
}
}
}
i += l;
}
}
}
if (keyIVRef == 0)
{
return EMU_KEY_NOT_FOUND;
}
}
if (keySeedRef == 0)
{
return EMU_KEY_NOT_FOUND;
}
}
if (key0Ref == 0)
{
return EMU_KEY_NOT_FOUND;
}
return EMU_NOT_SUPPORTED;
}
// Irdeto2 EMM EMU
static int8_t do_emm_type_op(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
{
uint8_t tmp[16];
uint32_t end, i, l;
char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
memset(tmp, 0, 16);
irdeto2_encrypt(keySeed, tmp, keyPMK, 16);
irdeto2_decrypt(&emm[startOffset], keyIV, keySeed, length);
i = 16;
end = startOffset + (length - 8 < 0 ? 0 : length - 8);
while (i < end)
{
l = emm[i + 1] ? (emm[i + 1] & 0x3F) + 2 : 1;
switch (emm[i])
{
case 0x10:
case 0x50:
if (l == 0x13 && i <= startOffset + length - 8 - l)
{
irdeto2_decrypt(&emm[i + 3], keyIV, keyPMK, 16);
}
break;
case 0x78:
if (l == 0x14 && i <= startOffset + length - 8 - l)
{
irdeto2_decrypt(&emm[i + 4], keyIV, keyPMK, 16);
}
break;
}
i += l;
}
memmove(emm + 6, emm + 7, emmLen - 7);
i = 15;
end = startOffset + (length - 9 < 0 ? 0 : length - 9);
if (calculate_hash(keySeed, keyIV, emm + 3, emmLen - 4))
{
while (i < end)
{
l = emm[i + 1] ? (emm[i + 1] & 0x3F) + 2 : 1;
switch (emm[i])
{
case 0x10:
case 0x50:
{
if (l == 0x13 && i <= startOffset + length - 9 - l)
{
snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "%02X", emm[i + 2] >> 2);
SAFE_MUTEX_LOCK(&emu_key_data_mutex);
emu_set_key('I', ident, keyName, &emm[i + 3], 16, 1, NULL, NULL);
SAFE_MUTEX_UNLOCK(&emu_key_data_mutex);
(*keysAdded)++;
cs_hexdump(0, &emm[i + 3], 16, keyValue, sizeof(keyValue));
cs_log("Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
}
}
}
i += l;
}
if (*keysAdded > 0)
{
return 0;
}
}
return 1;
}
static int8_t do_emm_type_pmk(uint32_t ident, uint8_t *emm, uint8_t *keySeed, uint8_t *keyIV, uint8_t *keyPMK,
uint16_t emmLen, uint8_t startOffset, uint8_t length, uint32_t *keysAdded)
{
uint32_t end, i, j, l;
char keyName[EMU_MAX_CHAR_KEYNAME], keyValue[36];
irdeto2_decrypt(&emm[startOffset], keyIV, keySeed, length);
i = 13;
end = startOffset + (length - 8 < 0 ? 0 : length - 8);
while (i < end)
{
l = emm[i + 1] ? (emm[i + 1] & 0x3F) + 2 : 1;
switch (emm[i])
{
case 0x10:
case 0x50:
if (l == 0x13 && i <= startOffset + length - 8 - l)
{
irdeto2_decrypt(&emm[i + 3], keyIV, keyPMK, 16);
}
break;
case 0x78:
if (l == 0x14 && i <= startOffset + length - 8 - l)
{
irdeto2_decrypt(&emm[i + 4], keyIV, keyPMK, 16);
}
break;
case 0x68:
if (l == 0x26 && i <= startOffset + length - 8 - l)
{
irdeto2_decrypt(&emm[i + 3], keyIV, keyPMK, 16 * 2);
}
break;
}
i += l;
}
memmove(emm + 7, emm + 9, emmLen - 9);
i = 11;
end = startOffset + (length - 10 < 0 ? 0 : length - 10);
if (calculate_hash(keySeed, keyIV, emm + 3, emmLen - 5))
{
while (i < end)
{
l = emm[i + 1] ? (emm[i + 1] & 0x3F) + 2 : 1;
switch (emm[i])
{
case 0x68:
{
if (l == 0x26 && i <= startOffset + length - 10 - l)
{
for (j = 0; j < 2; j++)
{
snprintf(keyName, EMU_MAX_CHAR_KEYNAME, "M%01X", 3 + j);
SAFE_MUTEX_LOCK(&emu_key_data_mutex);
emu_set_key('I', ident, keyName, &emm[i + 3 + j * 16], 16, 1, NULL, NULL);
SAFE_MUTEX_UNLOCK(&emu_key_data_mutex);
(*keysAdded)++;
cs_hexdump(0, &emm[i + 3 + j * 16], 16, keyValue, sizeof(keyValue));
cs_log("Key found in EMM: I %06X %s %s", ident, keyName, keyValue);
}
}
}
}
i += l;
}
if (*keysAdded > 0)
{
return 0;
}
}
return 1;
}
static const uint8_t fausto_xor[16] =
{
0x22, 0x58, 0xBD, 0x85, 0x2E, 0x8E, 0x52, 0x80,
0xA3, 0x79, 0x98, 0x69, 0x68, 0xE2, 0xD8, 0x4D
};
int8_t irdeto2_emm(uint16_t caid, uint8_t *oemm, uint32_t *keysAdded)
{
uint8_t length, okeySeed[16], keySeed[16], keyIV[16], keyPMK[16], startOffset, emmType;
uint8_t emmCopy[EMU_MAX_EMM_LEN], *emm = oemm;
uint16_t emmLen = SCT_LEN(emm);
uint32_t ident, keySeedRef, keyIVRef, keyPMK0Ref, keyPMK1Ref, keyPMK0ERef, keyPMK1ERef;
if (emmLen < 11)
{
return EMU_NOT_SUPPORTED;
}
if (emm[3] == 0xC3 || emm[3] == 0xCB)
{
emmType = 2;
startOffset = 11;
}
else
{
emmType = 1;
startOffset = 10;
}
ident = emm[startOffset - 2] | caid << 8;
length = emm[startOffset - 1];
if (emmLen < length + startOffset)
{
return EMU_NOT_SUPPORTED;
}
keySeedRef = 0;
while (get_key(okeySeed, ident, 'M', emmType == 1 ? 0 : 0xA, 1, &keySeedRef))
{
keyIVRef = 0;
while (get_key(keyIV, ident, 'M', 2, 1, &keyIVRef))
{
keyPMK0Ref = 0;
keyPMK1Ref = 0;
keyPMK0ERef = 0;
keyPMK1ERef = 0;
while (get_key(keyPMK, ident, 'M', emmType == 1 ? 3 : 0xB, 1, &keyPMK0Ref))
{
memcpy(keySeed, okeySeed, 16);
memcpy(emmCopy, oemm, emmLen);
emm = emmCopy;
if (emmType == 1)
{
if (do_emm_type_op(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0)
{
return EMU_OK;
}
}
else
{
if (do_emm_type_pmk(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0)
{
return EMU_OK;
}
}
}
if (emmType == 1)
{
while (get_key(keyPMK, ident, 'M', 4, 1, &keyPMK1Ref))
{
memcpy(keySeed, okeySeed, 16);
memcpy(emmCopy, oemm, emmLen);
emm = emmCopy;
if (do_emm_type_op(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0)
{
return EMU_OK;
}
}
while (get_key(keyPMK, ident, 'M', 5, 1, &keyPMK0ERef))
{
xxor(keyPMK, 16, keyPMK, fausto_xor);
memcpy(keySeed, okeySeed, 16);
memcpy(emmCopy, oemm, emmLen);
emm = emmCopy;
if (do_emm_type_op(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0)
{
return EMU_OK;
}
}
while (get_key(keyPMK, ident, 'M', 6, 1, &keyPMK1ERef))
{
xxor(keyPMK, 16, keyPMK, fausto_xor);
memcpy(keySeed, okeySeed, 16);
memcpy(emmCopy, oemm, emmLen);
emm = emmCopy;
if (do_emm_type_op(ident, emm, keySeed, keyIV, keyPMK, emmLen, startOffset, length, keysAdded) == 0)
{
return EMU_OK;
}
}
}
if (keyPMK0Ref == 0 && keyPMK1Ref == 0 && keyPMK0ERef == 0 && keyPMK1ERef == 0)
{
return EMU_KEY_NOT_FOUND;
}
}
if (keyIVRef == 0)
{
return EMU_KEY_NOT_FOUND;
}
}
if (keySeedRef == 0)
{
return 2;
}
return EMU_NOT_SUPPORTED;
}
int8_t irdeto2_get_hexserial(uint16_t caid, uint8_t *hexserial)
{
uint32_t i, len;
KeyDataContainer *KeyDB;
KeyData *tmpKeyData;
KeyDB = emu_get_key_container('I');
if (KeyDB == NULL)
{
return 0;
}
for (i = 0; i < KeyDB->keyCount; i++)
{
if (KeyDB->EmuKeys[i].provider >> 8 != caid)
{
continue;
}
if (strcmp(KeyDB->EmuKeys[i].keyName, "MC"))
{
continue;
}
tmpKeyData = &KeyDB->EmuKeys[i];
len = tmpKeyData->keyLength;
if (len > 3)
{ len = 3; }
memcpy(hexserial + (3 - len), tmpKeyData->key, len);
return 1;
}
return 0;
}
#endif // WITH_EMU
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。