Ai
2 Star 1 Fork 0

长江/oscam-nx111

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
module-emulator-irdeto.c 11.57 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602
#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
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/4a02/oscam-nx111.git
git@gitee.com:4a02/oscam-nx111.git
4a02
oscam-nx111
oscam-nx111
master

搜索帮助