oscam-2.26.01-11942-802-wit.../module-emulator-omnicrypt.c
2026-02-17 09:41:05 +00:00

73 lines
1.9 KiB
C
Executable File

#define MODULE_LOG_PREFIX "emu"
#include "globals.h"
#ifdef WITH_EMU
#include "module-emulator-osemu.h"
#include "module-emulator-omnicrypt.h"
#include "oscam-aes.h"
#include "oscam-string.h"
static inline int8_t get_ecm_key(uint16_t provider, uint8_t parity, uint8_t *key)
{
return emu_find_key('O', provider, 0, parity == 0 ? "00" : "01", key, 16, 1, 0, 0, NULL);
}
int8_t omnicrypt_ecm(uint8_t *ecm, uint8_t *dw)
{
uint8_t section_syntax_indicator, session_key[16], session_key_parity, position;
uint16_t private_section_length, session_key_id, payload_length;
struct aes_keys aes;
section_syntax_indicator = ecm[1] >> 7;
if (section_syntax_indicator != 0) // The private_data_bytes immediately follow the private_section_length field
{
cs_log("ECM section syntax indicator %d not supported", section_syntax_indicator);
return EMU_NOT_SUPPORTED;
}
private_section_length = b2i(2, ecm + 1) & 0x0FFF;
if (private_section_length != 0x2D)
{
cs_log("ECM has an unsupported private section length of %d", private_section_length);
return EMU_NOT_SUPPORTED;
}
session_key_parity = ecm[3] & 0x01;
session_key_id = b2i(2, ecm + 4);
if (!get_ecm_key(session_key_id, session_key_parity, session_key))
{
return EMU_KEY_NOT_FOUND;
}
aes_set_key(&aes, (char *)session_key);
payload_length = b2i(2, ecm + 6) & 0x0FFF;
if (payload_length != 0x28)
{
cs_log("ECM has an unsupported payload length of %d", payload_length);
return EMU_NOT_SUPPORTED;
}
for (position = 8; position + 1 < payload_length; position += 4 + 16) // Run twice for odd, even CW
{
uint8_t parity = ecm[position + 1] & 0x01;
uint8_t length = ecm[position + 3];
if (length != 16)
{
cs_log("CW %d has an unsupported length of %d", parity, length);
return EMU_NOT_SUPPORTED;
}
aes_decrypt(&aes, ecm + position + 4, 16);
memcpy(dw + parity * 8, ecm + position + 4, 8); // Copy the first 8 bytes (rest are zeros)
}
return EMU_OK;
}
#endif // WITH_EMU