oscam-2.26.01-11942-802-wit.../reader-dgcrypt.c
2026-02-17 10:06:53 +00:00

276 lines
8.6 KiB
C
Executable File

#include "globals.h"
#ifdef READER_DGCRYPT
#include "reader-common.h"
#define DEBUG 0
static const uint8_t dgcrypt_atr[8] = { 0x3B, 0xE9, 0x00, 0x00, 0x81, 0x31, 0xC3, 0x45 };
static const uint8_t cmd_CWKEY[5] = { 0x81, 0xD0, 0x00, 0x01, 0x08 };
static const uint8_t cmd_CAID[5] = { 0x81, 0xC0, 0x00, 0x01, 0x0A };
static const uint8_t cmd_SERIAL[5] = { 0x81, 0xD1, 0x00, 0x01, 0x10 };
static const uint8_t cmd_CARD_ID[5] = { 0x81, 0xD4, 0x00, 0x01, 0x05 };
static const uint8_t cmd_LABEL[5] = { 0x81, 0xD2, 0x00, 0x01, 0x10 };
//static const uint8_t cmd_SUBSYS[5] = { 0x81, 0xDD, 0x00, 0x10, 0x04 };
static const uint8_t cmd_ECM[3] = { 0x80, 0xEA, 0x80 };
static const uint8_t cmd_EMM[3] = { 0x80, 0xEB, 0x80 };
struct dgcrypt_data
{
uint8_t session_key[16];
uint8_t cardid[5];
};
static int32_t dgcrypt_cmd(struct s_reader *rdr, const uint8_t *buf, const int32_t buflen, uint8_t *response, uint16_t *response_length, uint16_t min_response_len)
{
rdr->ifsc = 195;
rdr->ns = 1;
if(DEBUG)
{
char tmp[512];
rdr_log(rdr, "SEND -> %s(%d)", cs_hexdump(1, buf, buflen, tmp, sizeof(tmp)), buflen);
}
int32_t ret = reader_cmd2icc(rdr, buf, buflen, response, response_length);
if(DEBUG)
{
char tmp[512];
rdr_log(rdr, "RECV <- %s(%d) ret=%d", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), *response_length, ret);
}
// reader_cmd2icc retuns ERROR=1, OK=0 - the opposite of OK and ERROR defines in reader-common.h
if(ret)
{
rdr_log(rdr, "ERROR: reader_cmd2icc() ret=%d", ret);
return ERROR;
}
if(*response_length < 2 || *response_length < min_response_len)
{
if (response[0] == 0x6b && response[1] == 0x01) rdr_log(rdr, "ERROR: card has expired, please update your card");
else rdr_log(rdr, "ERROR: response_length=%d < min_response_length=%d", *response_length, min_response_len);
return ERROR; // Response is two short
}
if(response[*response_length - 2] != 0x90 || (response[*response_length - 1] != 0x00 && response[*response_length - 1] != 0x17))
{
rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]);
rdr_log(rdr, "ERROR: response[-1] != 0x00 or 0x17 its 0x%02X", response[*response_length - 1]);
return ERROR; // The reader responded with "command not OK"
}
return OK;
}
static int32_t dgcrypt_card_init(struct s_reader *rdr, ATR *newatr)
{
def_resp
get_atr
if(atr_size < sizeof(dgcrypt_atr))
{ return ERROR; }
// Full ATR: 3B E9 00 00 81 31 C3 45 99 63 74 69 19 99 12 56 10 EC
if(memcmp(atr, dgcrypt_atr, sizeof(dgcrypt_atr)) != 0)
{ return ERROR; }
if(!cs_malloc(&rdr->csystem_data, sizeof(struct dgcrypt_data)))
{ return ERROR; }
struct dgcrypt_data *csystem_data = rdr->csystem_data;
rdr_log(rdr, "[dgcrypt-reader] card detected.");
memset(rdr->sa, 0, sizeof(rdr->sa));
memset(rdr->prid, 0, sizeof(rdr->prid));
memset(rdr->hexserial, 0, sizeof(rdr->hexserial));
rdr->nprov = 1;
// rdr->caid = 0x4ABF;
// Get session key
// Send: 81 D0 00 01 08
// Recv: 32 86 17 D5 2C 66 61 14 90 00
if(!dgcrypt_cmd(rdr, cmd_CWKEY, sizeof(cmd_CWKEY), cta_res, &cta_lr, 8))
{ return ERROR; }
memcpy(csystem_data->session_key + 0, cta_res, 8);
memcpy(csystem_data->session_key + 8, cta_res, 8);
// Get CAID
// Send: 81 C0 00 01 0A
// Recv: 4A BF 90 00
if (!dgcrypt_cmd(rdr, cmd_CAID, sizeof(cmd_CAID), cta_res, &cta_lr, 2))
{ return ERROR; }
rdr->caid = (cta_res[0] << 8) | cta_res[1];
// Get serial number
// Send: 81 D1 00 01 10
// Recv: 00 0D DB 08 71 0D D5 0C 30 30 30 30 30 30 30 30 90 00
if(!dgcrypt_cmd(rdr, cmd_SERIAL, sizeof(cmd_SERIAL), cta_res, &cta_lr, 8))
{ return ERROR; }
memcpy(rdr->hexserial, cta_res + 1, 7);
// Get card id
// Send: 81 D4 00 01 05
// Recv: 00 00 00 76 AC 90 00
if(!dgcrypt_cmd(rdr, cmd_CARD_ID, sizeof(cmd_CARD_ID), cta_res, &cta_lr, 5))
{ return ERROR; }
memcpy(csystem_data->cardid, cta_res, 5);
// Get LABEL
// Send: 81 D2 00 01 10
// Recv: 50 61 79 5F 54 56 5F 43 61 72 64 00 00 00 00 00 90 00
// Txt: P a y _ T V _ C a r d
if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 16))
{ return ERROR; }
char label[17];
memset(label, 0, sizeof(label));
memcpy(label, cta_res, 16);
// Get subsystem - !FIXME! We are not using the answer of this command!
// Send: 81 DD 00 10 04
// Recv: 00 55 00 55 90 00, also 00 8F 00 8F 90 00
// if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 4))
// { return ERROR; }
rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%"PRIu64"} HexSerial: {%02X %02X %02X %02X %02X %02X %02X} Card Id: {%02X %02X %02X %02X %02X} Label: {%s}",
rdr->caid,
b2ll(7, rdr->hexserial),
rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2],
rdr->hexserial[3], rdr->hexserial[4], rdr->hexserial[5], rdr->hexserial[6],
csystem_data->cardid[0], csystem_data->cardid[1], csystem_data->cardid[2], csystem_data->cardid[3], csystem_data->cardid[4],
label);
return OK;
}
static int32_t dgcrypt_do_ecm(struct s_reader *rdr, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
def_resp
uint8_t cmd_buffer[256];
struct dgcrypt_data *csystem_data = rdr->csystem_data;
memcpy(cmd_buffer, er->ecm, er->ecm[2] + 3);
// Replace The first 3 bytes of the ECM with the command
memcpy(cmd_buffer, cmd_ECM, sizeof(cmd_ECM));
// Write ECM
// Send: 80 EA 80 00 55 00 00 3F 90 03 00 00 18 5D 82 4E 01 C4 2D 60 12 ED 34 37 ED 72 .. .. ..
// Recv: 72 25 8D A1 0D 0D D2 44 EE ED 51 2F 3B 5D 19 63 E6 90 00
if(!dgcrypt_cmd(rdr, cmd_buffer, er->ecm[2] + 3, cta_res, &cta_lr, 17))
{ return ERROR; }
if(cta_res[0] != 0x72) // CW response MUST start with 0x72
{ return ERROR; }
int i;
for(i = 0; i < 16; i++)
{
ea->cw[i] = cta_res[1 + i] ^ csystem_data->session_key[i];
}
return OK;
}
static int32_t dgcrypt_do_emm(struct s_reader *rdr, EMM_PACKET *ep)
{
def_resp
uint8_t cmd_buffer[256];
int32_t emm_length = ep->emm[2] + 3 + 2;
// add 2 bytes for header
memcpy(cmd_buffer + 2, ep->emm, emm_length);
// Replace The first 3 bytes of the EMM with the command
memcpy(cmd_buffer, cmd_EMM, sizeof(cmd_EMM));
// Write EMM
// Send: 80 EB 80 00 54 00 00 00 00 76 AC 00 8F 82 4A 90 03 00 00 .. .. ..
// Recv: 90 17
if(!dgcrypt_cmd(rdr, cmd_buffer, emm_length, cta_res, &cta_lr, 2))
{ return ERROR; }
return OK;
}
static int32_t dgcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *rdr)
{
rdr_log_dbg(rdr, D_EMM, "Entered dgcrypt_get_emm_type ep->emm[0]=%x", ep->emm[0]);
char tmp_dbg[10];
struct dgcrypt_data *csystem_data = rdr->csystem_data;
switch(ep->emm[0])
{
case 0x82:
ep->type = UNIQUE;
memset(ep->hexserial, 0, 8);
memcpy(ep->hexserial, ep->emm + 4, 5);
rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE, ep->hexserial = {%s}",
cs_hexdump(1, ep->hexserial, 5, tmp_dbg, sizeof(tmp_dbg)));
rdr_log_dbg_sensitive(rdr, D_EMM, "UNIQUE, csystem_data->cardid = {%s}",
cs_hexdump(1, csystem_data->cardid, 5, tmp_dbg, sizeof(tmp_dbg)));
return (!memcmp(csystem_data->cardid, ep->hexserial, 5));
break;
// Unknown EMM types, but allready subbmited to dev's
// FIXME: Drop EMM's until there are implemented
default:
ep->type = UNKNOWN;
return 1;
}
}
static int32_t dgcrypt_get_emm_filter(struct s_reader *rdr, struct s_csystem_emm_filter **emm_filters, unsigned int *filter_count)
{
struct dgcrypt_data *csystem_data = rdr->csystem_data;
if(*emm_filters == NULL)
{
// need more info
//--|-|len|--|card id 5 byte| const |len|const|--------------
//82 00 54 00 00 00 00 xx xx 00 8f 82 4a 90 03 ... tested, works
//82 00 64 00 00 00 00 00 00 00 8f 82 5a ff ff ... ? filler
//82 00 34 00 00 00 00 xx xx 00 8f 82 2a 90 03 ... ?
//82 00 37 00 00 00 00 xx xx 00 8f 82 2d 90 03 ... ?
const unsigned int max_filter_count = 1; // fixme
if(!cs_malloc(emm_filters, max_filter_count * sizeof(struct s_csystem_emm_filter)))
{
return ERROR;
}
struct s_csystem_emm_filter *filters = *emm_filters;
int32_t idx = 0;
filters[idx].type = EMM_UNIQUE;
filters[idx].enabled = 1;
filters[idx].filter[0] = 0x82;
filters[idx].mask[0] = 0xFF;
memcpy(&filters[idx].filter[2], csystem_data->cardid, 5);
memset(&filters[idx].mask[2], 0xFF, 5);
idx++;
/*
// I've never seen it
filters[idx].type = EMM_GLOBAL;
filters[idx].enabled = 1;
filters[idx].filter[0] = 0x83;
filters[idx].mask[0] = 0xFF;
idx++;
*/
*filter_count = idx;
}
return OK;
}
const struct s_cardsystem reader_dgcrypt =
{
.desc = "dgcrypt",
.caids = (uint16_t[]){ 0x4AB0, 0x4ABF, 0 },
.card_init = dgcrypt_card_init,
.do_emm = dgcrypt_do_emm,
.do_ecm = dgcrypt_do_ecm,
.get_emm_type = dgcrypt_get_emm_type,
.get_emm_filter = dgcrypt_get_emm_filter,
};
#endif