oscam-2.26.01-11942-802-wit.../reader-nagracak7.c
2026-02-17 09:41:05 +00:00

1832 lines
49 KiB
C
Executable File

#include "globals.h"
#ifdef READER_NAGRA_MERLIN
#include "cscrypt/bn.h"
#include "cscrypt/idea.h"
#include "csctapi/icc_async.h"
#include "oscam-time.h"
#include "reader-common.h"
#include "reader-nagra-common.h"
#include "oscam-work.h"
#include "cscrypt/des.h"
#include "cscrypt/mdc2.h"
static uint8_t public_exponent[] = { 0x01, 0x00, 0x01 };
static const uint8_t d00ff[] = { 0x00, 0xFF, 0xFF, 0xFF };
// Datatypes
#define SYSID_CAID 0x02
#define IRDINFO 0x03
#define DT05 0x05
#define TIERS 0x0C
static time_t tier_date(uint64_t date, char *buf, int32_t l)
{
time_t ut = +694224000L + (date >> 1);
if(buf)
{
struct tm t;
cs_gmtime_r(&ut, &t);
l = 27;
snprintf(buf, l, "%04d/%02d/%02d", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday);
}
return ut;
}
static void rsa_decrypt(uint8_t *edata50, int len, uint8_t *out, uint8_t *key, int keylen, uint8_t *expo, uint8_t expolen)
{
BN_CTX *ctx0 = BN_CTX_new();
#ifdef WITH_LIBCRYPTO
BN_CTX_start(ctx0);
#endif
BIGNUM *bnN0 = BN_CTX_get(ctx0);
BIGNUM *bnE0 = BN_CTX_get(ctx0);
BIGNUM *bnCT0 = BN_CTX_get(ctx0);
BIGNUM *bnPT0 = BN_CTX_get(ctx0);
BN_bin2bn(&key[0], keylen, bnN0);
BN_bin2bn(&expo[0], expolen, bnE0);
BN_bin2bn(&edata50[0], len, bnCT0);
BN_mod_exp(bnPT0, bnCT0, bnE0, bnN0, ctx0);
memset(out, 0x00, len);
BN_bn2bin(bnPT0, out + (len - BN_num_bytes(bnPT0)));
BN_CTX_end(ctx0);
BN_CTX_free(ctx0);
}
static void addProvider(struct s_reader *reader, uint8_t *cta_res)
{
int i;
bool toadd = true;
for(i = 0; i < reader->nprov; i++)
{
if((cta_res[0] == reader->prid[i][2]) && (cta_res[1] == reader->prid[i][3]))
{
toadd = false;
}
}
if(toadd)
{
reader->prid[reader->nprov][0] = 0;
reader->prid[reader->nprov][1] = 0;
reader->prid[reader->nprov][2] = cta_res[0];
reader->prid[reader->nprov][3] = cta_res[1];
reader->nprov += 1;
}
}
static int32_t get_prov_index(struct s_reader *reader, const uint8_t *provid)
{
int prov;
for(prov = 0; prov < reader->nprov; prov++)
{
if(!memcmp(provid, &reader->prid[prov][2], 2))
{
return (prov);
}
}
return (-1);
}
static void addSA(struct s_reader *reader, uint8_t *cta_res)
{
if((cta_res[0] == 0x83 && cta_res[5] == 0x10) || cta_res[0] == 0x87)
{
int i;
bool toadd = true;
if(reader->evensa)
{
if(cta_res[0] == 0x87)
{
cta_res[4] = 0x00;
}
unsigned long sax = (cta_res[3] << 16) + (cta_res[2] << 8) + (cta_res[1]);
if(sax % 2 != 0)
{
sax--;
cta_res[3] = (sax >> 16) & 0xFF;
cta_res[2] = (sax >> 8) & 0xFF;
cta_res[1] = (sax ) & 0xFF;
}
}
for(i = 0; i < reader->nsa; i++)
{
if((cta_res[1] == reader->sa[i][2]) && (cta_res[2] == reader->sa[i][1]) && (cta_res[3] == reader->sa[i][0]) && (cta_res[4] == reader->sa[i][3]))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 1, "\x00\x00\x00", 3)))
{
reader->sa[reader->nsa][0] = cta_res[3];
reader->sa[reader->nsa][1] = cta_res[2];
reader->sa[reader->nsa][2] = cta_res[1];
reader->sa[reader->nsa][3] = cta_res[4];
reader->nsa += 1;
}
}
}
static void addSAseca(struct s_reader *reader, uint8_t *cta_res)
{
if(cta_res[0] == 0x84)
{
addProvider(reader, cta_res + 1);
if(reader->evensa)
{
unsigned long sax = (cta_res[3] << 16) + (cta_res[4] << 8) + (cta_res[5]);
if(sax % 2 != 0)
{
sax--;
cta_res[3] = (sax >> 16) & 0xFF;
cta_res[4] = (sax >> 8) & 0xFF;
cta_res[5] = (sax ) & 0xFF;
}
}
if(memcmp(cta_res + 3, "\x00\x00\x00", 3))
{
int i;
i = get_prov_index(reader, cta_res + 1);
memcpy(reader->sa[i], cta_res + 3, 3);
}
}
}
static void addemmfilter(struct s_reader *reader, uint8_t *cta_res)
{
if(cta_res[0] == 0x82)
{
reader->emm82 = 1;
}
else if(cta_res[0] == 0x84)
{
int i;
bool toadd = true;
for(i = 0; i < reader->nemm84; i++)
{
if(!memcmp(cta_res, reader->emm84[i], 3))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 1, "\x00\x00", 2)))
{
reader->emm84[reader->nemm84][0] = cta_res[0];
reader->emm84[reader->nemm84][1] = cta_res[1];
reader->emm84[reader->nemm84][2] = cta_res[2];
reader->nemm84 += 1;
}
}
else if(cta_res[0] == 0x83 && cta_res[5] == 0x00)
{
int i;
bool toadd = true;
for(i = 0; i < reader->nemm83u; i++)
{
if(!memcmp(cta_res, reader->emm83u[i], 6))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 1, "\x00\x00\x00\x00", 4)))
{
memcpy(reader->emm83u[reader->nemm83u], cta_res, 6);
reader->nemm83u += 1;
}
}
else if(cta_res[0] == 0x83 && cta_res[5] == 0x10)
{
int i;
bool toadd = true;
if(reader->evensa)
{
unsigned long sax = (cta_res[3] << 16) + (cta_res[2] << 8) + (cta_res[1]);
if(sax % 2 != 0)
{
sax--;
cta_res[3] = (sax >> 16) & 0xFF;
cta_res[2] = (sax >> 8) & 0xFF;
cta_res[1] = (sax ) & 0xFF;
}
}
for(i = 0; i < reader->nemm83s; i++)
{
if(!memcmp(cta_res, reader->emm83s[i], 6))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 1, "\x00\x00\x00", 3)))
{
memcpy(reader->emm83s[reader->nemm83s], cta_res, 6);
reader->nemm83s += 1;
}
}
else if(cta_res[0] == 0x87)
{
int i;
bool toadd = true;
if(reader->evensa)
{
cta_res[4] = 0x00;
unsigned long sax = (cta_res[3] << 16) + (cta_res[2] << 8) + (cta_res[1]);
if(sax % 2 != 0)
{
sax--;
cta_res[3] = (sax >> 16) & 0xFF;
cta_res[2] = (sax >> 8) & 0xFF;
cta_res[1] = (sax ) & 0xFF;
}
}
for(i = 0; i < reader->nemm87; i++)
{
if(!memcmp(cta_res, reader->emm87[i], 6))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 1, "\x00\x00\x00", 3)))
{
memcpy(reader->emm87[reader->nemm87], cta_res, 6);
reader->nemm87 += 1;
}
}
}
static void addemmfilterseca(struct s_reader *reader, uint8_t *cta_res)
{
if(cta_res[0] == 0x83)
{
reader->emm83 = 1;
}
else if(cta_res[0] == 0x82 && cta_res[1] == 0x00 && cta_res[2] == 0x00)
{
int i;
bool toadd = true;
for(i = 0; i < reader->nemm82u; i++)
{
if(!memcmp(cta_res, reader->emm82u[i], 7))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 3, "\x00\x00\x00\x00", 4)))
{
memcpy(reader->emm82u[reader->nemm82u], cta_res, 7);
reader->nemm82u += 1;
}
}
else if(cta_res[0] == 0x84)
{
int i;
bool toadd = true;
if(reader->evensa)
{
unsigned long sax = (cta_res[3] << 16) + (cta_res[4] << 8) + (cta_res[5]);
if(sax % 2 != 0)
{
sax--;
cta_res[3] = (sax >> 16) & 0xFF;
cta_res[4] = (sax >> 8) & 0xFF;
cta_res[5] = (sax ) & 0xFF;
}
}
for(i = 0; i < reader->nemm84s; i++)
{
if(!memcmp(cta_res, reader->emm84s[i], 6))
{
toadd = false;
}
}
if(toadd && (memcmp(cta_res + 3, "\x00\x00\x00", 3)))
{
memcpy(reader->emm84s[reader->nemm84s], cta_res, 6);
reader->nemm84s += 1;
}
}
}
static int32_t ParseDataType(struct s_reader *reader, uint8_t dt, uint8_t *cta_res, uint16_t cta_lr)
{
char ds[27], de[27];
switch(dt)
{
case SYSID_CAID:
{
reader->prid[0][0] = 0x00;
reader->prid[0][1] = 0x00;
reader->prid[0][2] = cta_res[19];
reader->prid[0][3] = cta_res[20];
reader->prid[1][0] = 0x00;
reader->prid[1][1] = 0x00;
reader->prid[1][2] = 0x00;
reader->prid[1][3] = 0x00;
reader->nprov += 1;
reader->caid = (SYSTEM_NAGRA | cta_res[25]);
reader->cak7_emm_caid = (SYSTEM_NAGRA | cta_res[25]);
rdr_log_dbg(reader, D_READER, "EMM CAID : %04X", reader->cak7_emm_caid);
return OK;
}
case IRDINFO: // case 0x03
{
uint16_t chid = 0;
uint32_t id = b2i(0x02, cta_res + 19);
uint32_t start_date = 1;
uint32_t expire_date = 0;
if(cta_res[21] == 0x9C)
{
if((reader->caid == 0x186D) || (reader->caid == 0x187D))
{
const uint8_t timestamp2038[4] = {0xAD, 0x0E, 0x26, 0x01};
expire_date = b2i(0x04, timestamp2038);
}
else
{
expire_date = b2i(0x04, cta_res + 22);
}
}
if((cta_res[21] == 0x01) && (reader->protocol_type == ATR_PROTOCOL_TYPE_T0 ||
((reader->caid == 0x1856 || reader->caid == 0x187D) && cta_res[8] != 0x18)))
{
expire_date = b2i(0x04, cta_res + 22);
}
if (expire_date)
{
reader->card_valid_to = tier_date(expire_date, de, 11);
cs_add_entitlement(reader, reader->caid, id, chid, 0, tier_date(start_date, ds, 11), tier_date(expire_date, de, 11), 4, 1);
rdr_log(reader, "|%04X|%04X |%s |%s |", id, chid, ds, de);
addProvider(reader, cta_res + 19);
}
return OK;
}
case 0x04:
{
if(cta_res[18] != 0x80)
{
addProvider(reader, cta_res + 19);
uint8_t check[] = {0x00, 0x01};
uint8_t checkecmcaid[] = {0xFF, 0x07};
uint8_t emm84g_provid[2];
check[0] = reader->cak7_emm_caid & 0xFF;
int p;
for(p = 23; p < (cta_lr - 6); p++)
{
if(!memcmp(cta_res + p, check, 2))
{
addProvider(reader, cta_res + p + 2);
if(reader->cak7type == 3)
{
addSAseca(reader, cta_res + p + 5);
addemmfilterseca(reader, cta_res + p + 5);
}
else
{
if ((reader->cak7_emm_caid == 0x186A) && ((cta_res + p + 5)[0] == 0x84) && ((cta_res + p + 5)[1] == 0x00))
{
(cta_res + p + 5)[2] = 0xAC;
}
if ((cta_res + p + 5)[0] == 0x84)
{
emm84g_provid[0] = (cta_res + p + 5)[1] & (cta_res + p + 5)[4];
emm84g_provid[1] = (cta_res + p + 5)[2] & (cta_res + p + 5)[5];
addProvider(reader, emm84g_provid);
}
addSA(reader, cta_res + p + 5);
addemmfilter(reader, cta_res + p + 5);
}
}
if((!memcmp(cta_res + p, checkecmcaid, 2)) && ((cta_res + p + 2)[1] == 0x02))
{
reader->caid = (SYSTEM_NAGRA | (cta_res + p + 2)[0]);
rdr_log_dbg(reader, D_READER, "ECM CAID : %04X", reader->caid);
}
}
}
return OK;
}
case 0x09:
{
if((cta_res[19] == cta_res[23]) && (cta_res[20] == cta_res[24]))
{
addProvider(reader, cta_res + 19);
}
return OK;
}
case DT05: // case 0x05
{
memcpy(reader->edata,cta_res + 26, 0x70);
reader->dt5num = cta_res[20];
char tmp[8];
rdr_log(reader, "Card has DT05_%s", cs_hexdump(1, &reader->dt5num, 1, tmp, sizeof(tmp)));
IDEA_KEY_SCHEDULE ks;
if(reader->dt5num == 0x00)
{
rsa_decrypt(reader->edata, 0x70, reader->out, reader->mod1, reader->mod1_length, public_exponent, 3);
memcpy(reader->kdt05_00, &reader->out[18], 0x5C + 2);
memcpy(&reader->kdt05_00[0x5C + 2], cta_res + 26 + 0x70, 6);
memcpy(reader->ideakey1, reader->out, 16);
rdr_log_dump_dbg(reader, D_READER, reader->ideakey1, 16, "IDEAKEY1: ");
memcpy(reader->block3, cta_res + 26 + 0x70 + 6, 8);
idea_set_encrypt_key(reader->ideakey1, &ks);
memset(reader->v, 0, sizeof(reader->v));
idea_cbc_encrypt(reader->block3, reader->iout, 8, &ks, reader->v, IDEA_DECRYPT);
memcpy(&reader->kdt05_00[0x5C + 2 + 6], reader->iout, 8);
uint8_t mdc_hash1[MDC2_DIGEST_LENGTH];
uint8_t check1[0x7E];
memset(check1, 0x00, 0x7E);
memcpy(check1 + 18, reader->kdt05_00, 0x6C);
MDC2_CTX c1;
MDC2_Init(&c1);
MDC2_Update(&c1, check1, 0x7E);
MDC2_Final(&(mdc_hash1[0]), &c1);
rdr_log_dump_dbg(reader, D_READER, mdc_hash1, 16, "MDC_HASH: ");
if(memcmp(mdc_hash1 + 1, reader->ideakey1 + 1, 14) == 0)
{
rdr_log(reader, "DT05_00 is correct");
}
else
{
rdr_log(reader, "DT05_00 error - check MOD1");
}
rdr_log_dump_dbg(reader, D_READER, reader->kdt05_00, sizeof(reader->kdt05_00), "DT05_00: ");
}
if(reader->dt5num == 0x10)
{
rsa_decrypt(reader->edata, 0x70, reader->out, reader->mod1, reader->mod1_length, public_exponent, 3);
memcpy(reader->kdt05_10, &reader->out[16], 6 * 16);
memcpy(reader->ideakey1, reader->out, 16);
memcpy(reader->block3, cta_res + 26 + 0x70, 8);
idea_set_encrypt_key(reader->ideakey1, &ks);
memset(reader->v, 0, sizeof(reader->v));
idea_cbc_encrypt(reader->block3, reader->iout, 8, &ks, reader->v, IDEA_DECRYPT);
memcpy(&reader->kdt05_10[6 * 16], reader->iout, 8);
rdr_log_dump_dbg(reader, D_READER, reader->kdt05_10, sizeof(reader->kdt05_10), "DT05_10: ");
}
if(reader->dt5num == 0x20)
{
rsa_decrypt(reader->edata, 0x70, reader->out, reader->mod2, reader->mod2_length, public_exponent, 3);
memcpy(reader->tmprsa, reader->out, 0x70);
reader->hasunique = 1;
}
return OK;
}
case TIERS: // case 0x0C
{
if(cta_lr >= 0x30)
{
uint16_t chid = b2i(0x02, cta_res + 23);
uint32_t id = b2i(0x02, cta_res + 19);
uint32_t start_date = 0;
uint32_t expire_date1;
uint32_t expire_date2;
uint32_t expire_date = 0;
switch(reader->caid)
{
case 0x1830: // Max TV
case 0x1843: // HD02
case 0x1860: // HD03
start_date = b2i(0x04, cta_res + 42);
expire_date1 = b2i(0x04, cta_res + 28);
expire_date2 = b2i(0x04, cta_res + 46);
expire_date = expire_date1 <= expire_date2 ? expire_date1 : expire_date2;
break;
case 0x1861: // Polsat, Vodafone D08, Movistar Latin America
{
if(!memcmp(reader->rom, "\x44\x4E\x41\x53\x50\x34\x35\x30\x20\x52\x65\x76\x57\x36\x30", 15))
{
start_date = b2i(0x04, cta_res + 53);
expire_date1 = b2i(0x04, cta_res + 39);
expire_date2 = b2i(0x04, cta_res + 57);
expire_date = expire_date1 <= expire_date2 ? expire_date1 : expire_date2;
}
else if(!memcmp(reader->rom, "\x44\x4E\x41\x53\x50\x34\x31\x30\x20\x52\x65\x76\x51\x32\x31", 15))
{
start_date = b2i(0x04, cta_res + 42);
expire_date = b2i(0x04, cta_res + 28);
}
else if(!memcmp(reader->rom, "\x44\x4E\x41\x53\x50\x34\x31\x30\x20\x52\x65\x76\x51\x32\x53", 15))
{
start_date = 1;
expire_date = b2i(0x04, cta_res + 28);
}
else
{
start_date = b2i(0x04, cta_res + 42);
expire_date1 = b2i(0x04, cta_res + 28);
expire_date2 = b2i(0x04, cta_res + 46);
expire_date = expire_date1 <= expire_date2 ? expire_date1 : expire_date2;
}
break;
}
case 0x186A: // HD04, HD05
start_date = b2i(0x04, cta_res + 53);
expire_date1 = b2i(0x04, cta_res + 39);
expire_date2 = b2i(0x04, cta_res + 57);
expire_date = expire_date1 <= expire_date2 ? expire_date1 : expire_date2;
break;
case 0x186D: // HD04H
case 0x187D: // Canal+ reunion
case 0x1884: // nc+
{
if(cta_res[8] == 0x45)
{
start_date = b2i(0x04, cta_res + 47);
expire_date1 = b2i(0x04, cta_res + 39);
expire_date2 = b2i(0x04, cta_res + 51);
expire_date = expire_date1 <= expire_date2 ? expire_date1 : expire_date2;
}
break;
}
case 0x1812:
case 0x1814: // MEO
case 0x1817: // Canal Digitaal
case 0x1818: // TV Vlaanderen
case 0x1819: // Telesat
{
if(cta_res[8] > 0x28)
{
start_date = b2i(0x04, cta_res + 32);
expire_date = b2i(0x04, cta_res + 36);
}
if(cta_res[8] == 0x20)
{
start_date = b2i(0x04, cta_res + 28);
expire_date = b2i(0x04, cta_res + 32);
}
break;
}
case 0x1824:
start_date = 1;
expire_date = b2i(0x04, cta_res + 28);
break;
default: // unknown card
start_date = 1;
expire_date = 0xAD0E2601;
}
cs_add_entitlement(reader, reader->caid, id, chid, 0, tier_date(start_date, ds, 11), tier_date(expire_date, de, 11), 4, 1);
rdr_log(reader, "|%04X|%04X |%s |%s |", id, chid, ds, de);
addProvider(reader, cta_res + 19);
}
return OK;
}
default:
return OK;
}
return ERROR;
}
static int32_t CAK7do_cmd(struct s_reader *reader, uint8_t dt, uint8_t *res, uint16_t *rlen, int32_t sub, uint8_t retlen)
{
uint8_t dtdata[0x10];
memset(dtdata, 0xCC, 0x10);
dtdata[ 7] = 0x04;
dtdata[ 8] = 0x04;
dtdata[ 9] = (sub >> 16) & 0xFF;
dtdata[10] = (sub >> 8) & 0xFF;
dtdata[11] = (sub ) & 0xFF;
dtdata[12] = dt;
do_cak7_cmd(reader, res, rlen, dtdata, sizeof(dtdata), retlen);
return OK;
}
static int32_t CAK7GetDataType(struct s_reader *reader, uint8_t dt)
{
def_resp;
int32_t sub = 0x00;
uint8_t retlen = 0x10;
while(1)
{
CAK7do_cmd(reader, dt, cta_res, &cta_lr, sub, retlen);
rdr_log_dump_dbg(reader, D_READER, cta_res, cta_lr, "Decrypted Answer:");
// hier eigentlich check auf 90 am ende usw... obs halt klarging ...
if(cta_lr == 0)
{
break;
}
if(cta_res[cta_lr - 2] == 0x6F && cta_res[cta_lr - 1] == 0x01)
{
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
break;
}
uint32_t newsub = (cta_res[9] << 16) + (cta_res[10] << 8) + (cta_res[11]);
if(newsub == 0xFFFFFF)
{
break;
}
if(cta_res[12] == dt)
{
uint8_t oretlen = retlen;
retlen = cta_res[13] + 0x10 + 0x2;
while(retlen % 0x10 != 0x00)
{
retlen++;
}
if(retlen == oretlen)
{
sub = newsub + 1;
retlen = 0x10;
ParseDataType(reader, dt, cta_res, cta_lr);
}
}
else
{
break;
}
}
return OK;
}
static void sub_6AD78(uint32_t *dinit) // gbox function
{
double res = *dinit * 16807.0;
*dinit = (uint32_t)(res - (uint32_t)(res / 2147483647.0) * 2147483647.0);
}
static void calc_cak7_exponent(uint32_t *dinit, uint8_t *out, uint8_t len)
{
memset(out, 0x00, len);
sub_6AD78(dinit);
int nR4 = 0;
int nR5 = 0;
while(true)
{
uint32_t nR0 = (uint32_t)* dinit;
int nR3 = nR4 + 3;
nR5 += 4;
if(nR3 > len)
{
break;
}
out[nR5 - 1] = ((nR0 ) & 0xFF);
out[nR5 - 2] = ((nR0 >> 8) & 0xFF);
out[nR5 - 3] = ((nR0 >> 16) & 0xFF);
out[nR5 - 4] = ((nR0 >> 24) & 0xFF);
nR4 += 4;
sub_6AD78(dinit);
}
uint32_t nR0 = (uint32_t)* dinit;
while(nR4 < len)
{
out[nR4] = nR0 & 0xFF;
nR4++;
nR0 >>= 8;
}
out[ 0] &= 0x03;
out[0x10] |= 0x01;
}
static void IdeaDecrypt(unsigned char *data, int len, const unsigned char *key, unsigned char *iv)
{
unsigned char v[8];
if(!iv)
{
memset(v, 0, sizeof(v));
iv = v;
}
IDEA_KEY_SCHEDULE ks;
idea_set_encrypt_key(key, &ks);
idea_cbc_encrypt(data, data, len&~7, &ks, iv, IDEA_DECRYPT);
}
static inline void xor8(uint8_t *data, const uint8_t *v1, const uint8_t *v2)
{
int i;
for(i = 0; i < 8; ++i)
{
data[i] = v1[i] ^ v2[i];
}
}
static void CreateRSAPair60(struct s_reader *reader, const unsigned char *key)
{
unsigned char idata[96];
int i;
for(i = 11; i >= 0; i--)
{
unsigned char *d = &idata[i * 8];
memcpy(d, &key[13], 8);
*d ^= i;
IdeaDecrypt(d, 8, key, 0);
xor8(d, d, &key[13]);
*d ^= i;
}
BN_CTX *ctx5 = BN_CTX_new();
#ifdef WITH_LIBCRYPTO
BN_CTX_start(ctx5);
#endif
BIGNUM *p = BN_CTX_get(ctx5);
BIGNUM *q = BN_CTX_get(ctx5);
BIGNUM *m = BN_CTX_get(ctx5);
BIGNUM *e = BN_CTX_get(ctx5);
BIGNUM *a = BN_CTX_get(ctx5);
BIGNUM *r = BN_CTX_get(ctx5);
// Calculate P
idata[ 0] |= 0x80;
idata[47] |= 1;
BN_bin2bn(idata, 48, p);
BN_add_word(p, (key[21] << 5) | ((key[22] & 0xF0) >> 3));
// Calculate Q
idata[48] |= 0x80;
idata[95] |= 1;
BN_bin2bn(idata + 48, 48, q);
BN_add_word(q, ((key[22] & 0xF) << 9) | (key[23] << 1));
// Calculate M = P * Q
BN_mul(m, p, q, ctx5);
memset(reader->key60, 0x00, 0x60);
BN_bn2bin(m, reader->key60 + (0x60 - BN_num_bytes(m)));
rdr_log_dump_dbg(reader, D_READER, reader->key60, sizeof(reader->key60), "key60: ");
// Calculate D
BN_sub_word(p, 1);
BN_sub_word(q, 1);
BN_mul(e, p, q, ctx5);
BN_bin2bn(public_exponent, 3, a);
BN_mod_inverse(r, a, e, ctx5);
memset(reader->exp60, 0x00, 0x60);
BN_bn2bin(r, reader->exp60 + (0x60 - BN_num_bytes(r)));
rdr_log_dump_dbg(reader, D_READER, reader->exp60, sizeof(reader->exp60), "exp60: ");
BN_CTX_end(ctx5);
BN_CTX_free(ctx5);
}
static void CreateRSAPair68(struct s_reader *reader, const unsigned char *key)
{
unsigned char idata[104];
int i;
for(i = 12; i >= 0; i--)
{
unsigned char *d = &idata[i * 8];
memcpy(d, &key[13], 8);
*d ^= i;
IdeaDecrypt(d, 8, key, 0);
xor8(d, d, &key[13]);
*d ^= i;
}
BN_CTX *ctx6 = BN_CTX_new();
#ifdef WITH_LIBCRYPTO
BN_CTX_start(ctx6);
#endif
BIGNUM *p = BN_CTX_get(ctx6);
BIGNUM *q = BN_CTX_get(ctx6);
BIGNUM *m = BN_CTX_get(ctx6);
BIGNUM *e = BN_CTX_get(ctx6);
BIGNUM *a = BN_CTX_get(ctx6);
BIGNUM *r = BN_CTX_get(ctx6);
// Calculate P
idata[ 0] |= 0x80;
idata[51] |= 1;
BN_bin2bn(idata, 52, p);
BN_add_word(p, (key[21] << 5) | ((key[22] & 0xF0) >> 3));
// Calculate Q
idata[ 52] |= 0x80;
idata[103] |= 1;
BN_bin2bn(idata + 52, 52, q);
BN_add_word(q, ((key[22] & 0xF) << 9) | (key[23] << 1));
// Calculate M = P * Q
BN_mul(m, p, q, ctx6);
memset(reader->key68, 0x00, 0x68);
BN_bn2bin(m, reader->key68 + (0x68 - BN_num_bytes(m)));
rdr_log_dump_dbg(reader, D_READER, reader->key68, sizeof(reader->key68), "key68: ");
// Calculate D
BN_sub_word(p, 1);
BN_sub_word(q, 1);
BN_mul(e, p, q, ctx6);
BN_bin2bn(public_exponent, 3, a);
BN_mod_inverse(r, a, e, ctx6);
memset(reader->exp68, 0x00, 0x68);
BN_bn2bin(r, reader->exp68 + (0x68 - BN_num_bytes(r)));
rdr_log_dump_dbg(reader, D_READER, reader->exp68, sizeof(reader->exp68), "exp68: ");
BN_CTX_end(ctx6);
BN_CTX_free(ctx6);
}
static void dt05_20(struct s_reader *reader)
{
uint8_t data_20_00[72];
uint8_t sig_20_00[16];
uint8_t data_20_id[72];
uint8_t data_20_x[64];
uint8_t data_20_fin[72];
uint8_t data_20_flag58[16];
rdr_log_dump_dbg(reader, D_READER, reader->tmprsa, sizeof(reader->tmprsa), "DT05_20 after RSA: ");
// copy signature
memcpy(sig_20_00, reader->tmprsa + 24, 16);
// copy data
memcpy(data_20_00, reader->tmprsa + 40, 72);
// IDEA encrypt 0x48 data
int i;
int offs = 0;
for(i = 0; i < 9; i++)
{
IDEA_KEY_SCHEDULE ks;
idea_set_encrypt_key(reader->key3310, &ks);
idea_ecb_encrypt(data_20_00 + offs, data_20_id + offs, &ks);
offs += 8;
}
// xor
for(i = 0; i < 64; i++)
{
data_20_x[i] = data_20_00[i] ^ data_20_id[i + 8];
}
rdr_log_dump_dbg(reader, D_READER, data_20_x, sizeof(data_20_x), "data_20_x: ");
// create final data block
memcpy(data_20_fin, data_20_id, 8);
memcpy(data_20_fin + 8, data_20_x, 64);
rdr_log_dump_dbg(reader, D_READER, data_20_fin, sizeof(data_20_fin), "data_20_fin: ");
uint8_t mdc_hash4[MDC2_DIGEST_LENGTH];
uint8_t check4[112];
memset(check4, 0x00, 112);
memcpy(check4, reader->cardid, 4);
memcpy(check4 + 4, reader->idird, 4);
memcpy(check4 + 23, reader->tmprsa + 23, 1);
memcpy(check4 + 40, data_20_fin, 72);
MDC2_CTX c4;
MDC2_Init(&c4);
MDC2_Update(&c4, check4, 112);
MDC2_Final(&(mdc_hash4[0]), &c4);
if(memcmp(mdc_hash4, sig_20_00, 16) == 0)
{
rdr_log(reader, "DT05_20 is correct");
}
else
{
rdr_log(reader, "DT05_20 error - check MOD2");
}
// Store 3des software key Flag58 CW overencrypt
memcpy(data_20_flag58, data_20_x + 16, 16);
memcpy(reader->key3des, data_20_flag58, 16);
rdr_log_dump_dbg(reader, D_READER, reader->key3des, sizeof(reader->key3des), "Flag58 3DES Key: ");
// create rsa pair from final data
memcpy(reader->klucz68, data_20_fin, 0x18);
rdr_log_dump_dbg(reader, D_READER, reader->klucz68, sizeof(reader->klucz68), "klucz68: ");
}
static int32_t CAK7_cmd03_global(struct s_reader *reader)
{
def_resp;
if(reader->cak7_seq <= 15)
{
unsigned char klucz[24];
memset(klucz, 0x00, 24);
memcpy(klucz, reader->key3588, 24);
CreateRSAPair60(reader, klucz);
}
rsa_decrypt(reader->step1, 0x60, reader->data, reader->key60, 0x60, reader->exp60, 0x60);
memcpy(&reader->step2[0], d00ff, 4);
memcpy(&reader->step2[4], reader->cardid, 4);
memcpy(&reader->step2[8], reader->data, 0x60);
rdr_log_dump_dbg(reader, D_READER, reader->step2, sizeof(reader->step2), "STEP 2:");
rsa_decrypt(reader->step2, 0x68, reader->data, reader->kdt05_10, 0x68, public_exponent, 3);
memcpy(&reader->step3[0], d00ff, 4);
memcpy(&reader->step3[4], reader->data, 0x68);
rdr_log_dump_dbg(reader, D_READER, reader->step3, sizeof(reader->step3), "STEP 3:");
rsa_decrypt(reader->step3, 0x6C, reader->data, reader->kdt05_00, 0x6C, public_exponent, 3);
uint8_t cmd03[] = {0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x0A, 0x03, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
memcpy(&cmd03[9], reader->data, 0x6C);
do_cak7_cmd(reader, cta_res, &cta_lr, cmd03, sizeof(cmd03), 0x90);
if(cta_lr == 0)
{
rdr_log(reader, "card is not responding to CMD03 - check your data");
return ERROR;
}
rdr_log_dump_dbg(reader, D_READER, cta_res, 0x90, "CMD03 ANSWER:");
memcpy(reader->encrypted, &cta_res[10], 0x68);
rsa_decrypt(reader->encrypted, 0x68, reader->result, reader->kdt05_10, 0x68, public_exponent, 3);
//uint8_t stillencrypted[0x50];
memcpy(reader->stillencrypted, &reader->result[12], 0x50);
//uint8_t resultrsa[0x50];
rsa_decrypt(reader->stillencrypted, 0x50, reader->resultrsa, reader->mod50, reader->mod50_length, reader->cak7expo, 0x11);
uint8_t mdc_hash3[MDC2_DIGEST_LENGTH];
MDC2_CTX c3;
MDC2_Init(&c3);
MDC2_Update(&c3, reader->resultrsa, sizeof(reader->resultrsa));
MDC2_Final(&(mdc_hash3[0]), &c3);
memcpy(&reader->cak7_aes_key[16], mdc_hash3, 16);
memcpy(reader->cak7_aes_key, mdc_hash3, 16);
char tmp7[128];
rdr_log(reader, "New AES: %s", cs_hexdump(1, reader->cak7_aes_key, 16, tmp7, sizeof(tmp7)));
return OK;
}
static int32_t CAK7_cmd03_unique(struct s_reader *reader)
{
def_resp;
rsa_decrypt(reader->step1, 0x60, reader->data, reader->key3460, reader->key3460_length, public_exponent, 3);
memcpy(&reader->step2[0], d00ff, 4);
memcpy(&reader->step2[4], reader->cardid, 4);
memcpy(&reader->step2[8], reader->data, 0x60);
rdr_log_dump_dbg(reader, D_READER, reader->step2, sizeof(reader->step2), "STEP 2:");
if(reader->cak7_seq <= 15)
{
dt05_20(reader);
CreateRSAPair68(reader, reader->klucz68);
}
rsa_decrypt(reader->step2, 0x68, reader->data, reader->key68, 0x68, reader->exp68, 0x68);
memcpy(&reader->step3[0], d00ff, 4);
memcpy(&reader->step3[4], reader->data, 0x68);
rdr_log_dump_dbg(reader, D_READER, reader->step3, sizeof(reader->step3), "STEP 3:");
rsa_decrypt(reader->step3, 0x6C, reader->data, reader->kdt05_00, 0x6C, public_exponent, 3);
uint8_t cmd03[] = {0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x0A, 0x03, 0x6C, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
memcpy(&cmd03[9], reader->data, 0x6C);
do_cak7_cmd(reader, cta_res, &cta_lr, cmd03, sizeof(cmd03), 0x90);
if(cta_lr == 0)
{
rdr_log(reader, "card is not responding to CMD03 - check your data");
return ERROR;
}
rdr_log_dump_dbg(reader, D_READER, cta_res, 0x90, "CMD03 ANSWER:");
memcpy(reader->encrypted, &cta_res[18], 0x60);
rsa_decrypt(reader->encrypted, 0x60, reader->result, reader->key3460, reader->key3460_length, public_exponent, 3);
rdr_log_dump_dbg(reader, D_READER, reader->result, 0x60, "after RSA_3460: ");
//uint8_t stillencrypted[0x50];
memcpy(reader->stillencrypted, &reader->result[4], 0x50);
//uint8_t resultrsa[0x50];
rsa_decrypt(reader->stillencrypted, 0x50, reader->resultrsa, reader->mod50, reader->mod50_length, reader->cak7expo, 0x11);
uint8_t mdc_hash5[MDC2_DIGEST_LENGTH];
MDC2_CTX c5;
MDC2_Init(&c5);
MDC2_Update(&c5, reader->resultrsa, sizeof(reader->resultrsa));
MDC2_Final(&(mdc_hash5[0]), &c5);
memcpy(&reader->cak7_aes_key[16], mdc_hash5, 16);
memcpy(reader->cak7_aes_key, mdc_hash5, 16);
char tmp7[128];
rdr_log(reader, "New AES: %s", cs_hexdump(1, reader->cak7_aes_key, 16, tmp7, sizeof(tmp7)));
return OK;
}
static int32_t CAK7_GetCamKey(struct s_reader *reader)
{
def_resp;
uint8_t cmd0e[] = {0xCC, 0xCC, 0xCC, 0xCC, 0x00, 0x00, 0x00, 0x0E, 0x83, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC};
if(!reader->nuid_length)
{
uint8_t cmd02[] = {0x02, 0x7B};
memcpy(cmd0e + 7, cmd02, 2);
rdr_log(reader, "using CMD02");
}
else
{
int cwekeycount = 0, i;
memcpy(cmd0e + 132, reader->nuid, reader->nuid_length); // inject NUID
for (i = 0; i < 17; i++)
{
cwekeycount = reader->cwekey_length[i] ? i + 1 : cwekeycount;
}
if(cwekeycount == 0)
{
if(reader->otpcsc_length)
{
memcpy(cmd0e + 136, reader->otpcsc, reader->otpcsc_length);
}
else
{
cmd0e[136] = 0x00;
cmd0e[137] = !reader->cwpkota ? 0xFF : 0x00;
}
if(reader->otacsc_length)
{
memcpy(cmd0e + 138, reader->otacsc, reader->otacsc_length);
}
else
{
cmd0e[138] = 0x00;
cmd0e[139] = reader->cwpkota ? 0xFF : 0x00;
}
}
else
{
if(reader->otpcsc_length)
{
memcpy(cmd0e + 136, reader->otpcsc, reader->otpcsc_length);
}
else
{
cmd0e[136] = 0x00;
cmd0e[137] = !reader->cwpkota ? cwekeycount : 0x00;
}
if(reader->otacsc_length)
{
memcpy(cmd0e + 138, reader->otacsc, reader->otacsc_length);
}
else
{
cmd0e[138] = 0x00;
cmd0e[139] = reader->cwpkota ? cwekeycount : 0x00;
}
}
char tmp[16];
rdr_log(reader, "OTP CSC No. of keys: %s", cs_hexdump(1, cmd0e + 136, 2, tmp, sizeof(tmp)));
rdr_log(reader, "OTA CSC No. of keys: %s", cs_hexdump(1, cmd0e + 138, 2, tmp, sizeof(tmp)));
}
if(reader->forcepair_length)
{
rdr_log(reader, "Forcing Pairing Type");
memcpy(cmd0e + 13, reader->forcepair, 1);
}
else
{
if(reader->hasunique == 1)
{
cmd0e[13] = 0x40;
}
}
memcpy(cmd0e + 14, reader->idird, 4);
memcpy(reader->irdId, reader->idird, 4);
if(reader->cmd0eprov_length)
{
memcpy(cmd0e + 18, reader->cmd0eprov, 2);
}
else
{
memcpy(cmd0e + 18, reader->prid[0] + 2, 2);
}
memcpy(cmd0e + 20, reader->key3588 + 24, 0x70);
if(reader->cak7_seq <= 15)
{
srand(time(NULL));
}
uint32_t data1r = rand() % 4294967294u;
reader->timestmp1[0] = (data1r >> 24) & 0xFF;
reader->timestmp1[1] = (data1r >> 16) & 0xFF;
reader->timestmp1[2] = (data1r >> 8) & 0xFF;
reader->timestmp1[3] = (data1r ) & 0xFF;
memcpy(cmd0e + 9, reader->timestmp1, 0x04);
rdr_log_dump_dbg(reader, D_READER, reader->timestmp1, 4, "DATA1 CMD0E:");
rdr_log_dump_dbg(reader, D_READER, reader->prid[0], 4, "SysID:");
do_cak7_cmd(reader,cta_res, &cta_lr, cmd0e, sizeof(cmd0e), 0x20);
if(cta_lr == 0)
{
rdr_log(reader, "card is not responding to CMD02/E - check your data");
return ERROR;
}
rdr_log_dump_dbg(reader, D_READER, cta_res, 0x20, "Decrypted answer to CMD02/0E:");
reader->needrestart = (cta_res[22] << 16);
reader->needrestart += (cta_res[23] << 8);
reader->needrestart += (cta_res[24] );
reader->needrestart--;
if(reader->cak7_seq <= 15)
{
rdr_log(reader, "card needs FASTreinit after %d CMDs", reader->needrestart);
}
else
{
uint32_t cmdleft = reader->needrestart - reader->cak7_seq;
rdr_log(reader, "%d CMDs left to FASTreinit", cmdleft);
}
reader->dword_83DBC = (cta_res[18] << 24);
reader->dword_83DBC += (cta_res[19] << 16);
reader->dword_83DBC += (cta_res[20] << 8);
reader->dword_83DBC += (cta_res[21] );
calc_cak7_exponent(&reader->dword_83DBC, reader->cak7expo, 0x11);
rdr_log_dump_dbg(reader, D_READER, reader->cak7expo, 0x11, "CAK7 Exponent:");
memcpy(reader->cardid, cta_res + 14, 4);
rdr_log_dump_dbg(reader, D_READER, reader->cardid, 0x04, "CardSerial: ");
memcpy(reader->hexserial + 2, reader->cardid, 4);
unsigned long datal = (cta_res[9] << 24) + (cta_res[10] << 16) + (cta_res[11] << 8) + (cta_res[12]);
datal++;
reader->data2[0] = (datal >> 24) & 0xFF;
reader->data2[1] = (datal >> 16) & 0xFF;
reader->data2[2] = (datal >> 8) & 0xFF;
reader->data2[3] = (datal ) & 0xFF;
data1r++;
reader->timestmp2[0] = (data1r >> 24) & 0xFF;
reader->timestmp2[1] = (data1r >> 16) & 0xFF;
reader->timestmp2[2] = (data1r >> 8) & 0xFF;
reader->timestmp2[3] = (data1r ) & 0xFF;
memcpy(reader->ecmheader, cta_res + 18, 4);
if(reader->cak7_seq <= 15)
{
uint8_t mdc_hash2[MDC2_DIGEST_LENGTH];
uint8_t check2[0x78];
memset(check2, 0x00, 0x78);
memcpy(check2, reader->cardid, 4);
memcpy(check2 + 16, reader->kdt05_10, 0x68);
MDC2_CTX c2;
MDC2_Init(&c2);
MDC2_Update(&c2, check2, 0x78);
MDC2_Final(&(mdc_hash2[0]), &c2);
rdr_log_dump_dbg(reader, D_READER, reader->ideakey1, 16, "IDEAKEY1: ");
rdr_log_dump_dbg(reader, D_READER, mdc_hash2, 16, "MDC_HASH: ");
if(memcmp(mdc_hash2 + 1, reader->ideakey1 + 1, 14) == 0)
{
rdr_log(reader, "DT05_10 is correct");
}
else
{
rdr_log(reader, "DT05_10 error - check MOD1");
}
}
rsa_decrypt(reader->data50, reader->data50_length, reader->data, reader->mod50, reader->mod50_length, reader->cak7expo, 0x11);
rdr_log_dump_dbg(reader, D_READER, reader->timestmp2, 4, "DATA1 CMD03:");
memcpy(&reader->step1[0], d00ff, 4);
memcpy(&reader->step1[4], reader->data, 0x50);
memcpy(&reader->step1[4 + 0x50], reader->idird, 0x04);
memcpy(&reader->step1[4 + 4 + 0x50], reader->timestmp2, 0x04);
memcpy(&reader->step1[4 + 4 + 4 + 0x50], reader->data2, 0x04);
rdr_log_dump_dbg(reader, D_READER, reader->step1, sizeof(reader->step1), "STEP 1:");
reader->pairtype = cta_res[13];
if((reader->pairtype > 0x00) && (reader->pairtype < 0xC0))
{
rdr_log(reader,"Card is starting in GLOBAL mode");
if(!CAK7_cmd03_global(reader))
{
return ERROR;
}
}
else if(reader->pairtype == 0xC0)
{
rdr_log(reader,"Card is starting in UNIQUE mode");
if(!reader->mod2_length)
{
rdr_log(reader, "no mod2 defined");
return ERROR;
}
if(!reader->key3460_length)
{
rdr_log(reader, "no key3460 defined");
return ERROR;
}
if(!reader->key3310_length)
{
rdr_log(reader, "no key3310 defined");
return ERROR;
}
if(!CAK7_cmd03_unique(reader))
{
return ERROR;
}
}
else
{
rdr_log(reader, "Unknown Pairing Type");
return ERROR;
}
return OK;
}
static int32_t nagra3_card_init(struct s_reader *reader, ATR *newatr)
{
get_atr;
memset(reader->hexserial, 0, 8);
reader->cak7_seq = 0;
reader->hasunique = 0;
memset(reader->ecmheader, 0, 4);
cs_clear_entitlement(reader);
if(memcmp(atr + 8, "DNASP4", 6) == 0)
{
if((memcmp(atr + 8, "DNASP400", 8) == 0) && !reader->cak7_mode)
{
return ERROR;
}
else
{
memcpy(reader->rom, atr + 8, 15);
rdr_log(reader, "Rom revision: %.15s", reader->rom);
}
}
else if(memcmp(atr + 11, "DNASP4", 6) == 0)
{
memcpy(reader->rom, atr + 11, 15);
rdr_log(reader, "Rom revision: %.15s", reader->rom);
}
else
{
return ERROR;
}
reader->nprov = 1;
/*reader->nsa = 0;
reader->nemm82u = 0;
reader->nemm84 = 0;
reader->nemm84s = 0;
reader->nemm83u = 0;
reader->nemm83s = 0;
reader->nemm87 = 0;*/
if(!reader->mod1_length)
{
rdr_log(reader, "no MOD1 defined");
return ERROR;
}
if(!reader->key3588_length)
{
rdr_log(reader, "no key3588 defined");
return ERROR;
}
if(!reader->data50_length)
{
rdr_log(reader, "no data50 defined");
return ERROR;
}
if(!reader->mod50_length)
{
rdr_log(reader, "no mod50 defined");
return ERROR;
}
if(!reader->idird_length)
{
rdr_log(reader, "no idird defined");
return ERROR;
}
CAK7GetDataType(reader, SYSID_CAID);
CAK7GetDataType(reader, DT05);
if(!CAK7_GetCamKey(reader))
{
return ERROR;
}
CAK7GetDataType(reader, 0x09);
char tmp[4 * 3 + 1];
reader->nsa = 0;
reader->nemm82u = 0;
reader->nemm84 = 0;
reader->nemm84s = 0;
reader->nemm83u = 0;
reader->nemm83s = 0;
reader->nemm87 = 0;
CAK7GetDataType(reader, 0x04);
if(reader->forceemmg)
{
reader->emm82 = 1;
}
int i;
for(i = 1; i < reader->nprov; i++)
{
rdr_log(reader, "Prv.ID: %s", cs_hexdump(1, reader->prid[i], 4, tmp, sizeof(tmp)));
}
if(reader->cak7type != 3)
{
rdr_log(reader, "-----------------------------------------");
rdr_log(reader, "| EMM Filters (PRIVATE!!) |");
rdr_log(reader, "+---------------------------------------+");
if(reader->emm82 == 1)
{
rdr_log(reader, "|emm82 |");
}
char tmp7[48];
for(i = 0; i < reader->nemm84; i++)
{
rdr_log(reader, "|emm84 : %s |", cs_hexdump(1, reader->emm84[i], 3, tmp7, sizeof(tmp7)));
}
for(i = 0; i < reader->nemm83u; i++)
{
rdr_log(reader, "|emm83U: %s |", cs_hexdump(1, reader->emm83u[i], 6, tmp7, sizeof(tmp7)));
}
for(i = 0; i < reader->nemm83s; i++)
{
rdr_log(reader, "|emm83S: %s |", cs_hexdump(1, reader->emm83s[i], 6, tmp7, sizeof(tmp7)));
}
for(i = 0; i < reader->nemm87; i++)
{
rdr_log(reader, "|emm87 : %s |", cs_hexdump(1, reader->emm87[i], 6, tmp7, sizeof(tmp7)));
}
rdr_log(reader, "-----------------------------------------");
}
if(reader->cak7type != 1)
{
rdr_log(reader, "-----------------------------------------");
rdr_log(reader, "| EMM Filters (PRIVATE!!) |");
rdr_log(reader, "+---------------------------------------+");
if(reader->emm83 == 1)
{
rdr_log(reader, "|emm83 |");
}
char tmp7[48];
for(i = 0; i < reader->nemm82u; i++)
{
rdr_log(reader, "|emm82U: %s |", cs_hexdump(1, reader->emm82u[i], 7, tmp7, sizeof(tmp7)));
}
for(i = 0; i < reader->nemm84s; i++)
{
rdr_log(reader, "|emm84S: %s |", cs_hexdump(1, reader->emm84s[i], 6, tmp7, sizeof(tmp7)));
}
rdr_log(reader, "-----------------------------------------");
}
rdr_log(reader, "ready for requests");
return OK;
}
static int32_t nagra3_card_info(struct s_reader *reader)
{
char tmp[4 * 3 + 1];
rdr_log(reader, "ROM: %c %c %c %c %c %c %c %c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3], reader->rom[4], reader->rom[5], reader->rom[6], reader->rom[7]);
rdr_log(reader, "REV: %c %c %c %c %c %c", reader->rom[9], reader->rom[10], reader->rom[11], reader->rom[12], reader->rom[13], reader->rom[14]);
rdr_log_sensitive(reader, "SER: {%s}", cs_hexdump(1, reader->hexserial + 2, 4, tmp, sizeof(tmp)));
rdr_log(reader, "ECM CAID: %04X", reader->caid);
rdr_log(reader, "EMM CAID: %04X", reader->cak7_emm_caid);
rdr_log(reader, "Prv.ID: %s(sysid)", cs_hexdump(1, reader->prid[0], 4, tmp, sizeof(tmp)));
cs_clear_entitlement(reader); // reset the entitlements
rdr_log(reader, "-----------------------------------------");
rdr_log(reader, "|id |tier |valid from |valid to |");
rdr_log(reader, "+----+--------+------------+------------+");
CAK7GetDataType(reader, IRDINFO);
CAK7GetDataType(reader, TIERS);
rdr_log(reader, "-----------------------------------------");
struct timeb now;
cs_ftime(&now);
reader->last_refresh = now;
return OK;
}
static int32_t fastreinit(struct s_reader *reader)
{
ATR newatr[ATR_MAX_SIZE];
memset(newatr, 0, 1);
if(ICC_Async_Activate(reader, newatr, 0))
{
return ERROR;
}
reader->cak7_seq = 0;
if(!CAK7_GetCamKey(reader))
{
return ERROR;
}
return OK;
}
static void nagra3_post_process(struct s_reader *reader)
{
if(reader->cak7_seq >= reader->needrestart)
{
rdr_log(reader, "card needs FASTreinit to prevent crash");
if(!fastreinit(reader))
{
rdr_log(reader, "FASTreinit failed - need to restart reader");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
}
else if((reader->cak7_camstate & 64) == 64)
{
rdr_log(reader, "negotiating new Session Key");
if(!CAK7_GetCamKey(reader))
{
rdr_log(reader, "negotiations failed - trying FASTreinit");
if(!fastreinit(reader))
{
rdr_log(reader, "FASTreinit failed - need to restart reader");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
}
}
}
static int32_t nagra3_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
def_resp;
if(reader->cak7type == 3)
{
if(er->ecm[2] > 0x61 && er->ecm[7] == 0x5C && er->ecm[100] == 0x0B)
{
if(er->ecm[101] == 0x03 || er->ecm[101] == 0x04)
{
if(er->ecm[104] > reader->pairtype)
{
rdr_log(reader, "reinit card in Unique Pairing Mode");
return ERROR;
}
if(er->ecm[104] == 0x80 && reader->pairtype == 0x80)
{
rdr_log(reader, "reinit card in Unique Pairing Mode");
return ERROR;
}
}
if(er->ecm[101] == 0x04 && !reader->nuid_length)
{
rdr_log(reader, "reinit card with NUID");
return ERROR;
}
}
}
else
{
if(er->ecm[2] > 0x86 && er->ecm[4] == 0x84 && er->ecm[137] == 0x0B)
{
if(er->ecm[138] == 0x03 || er->ecm[138] == 0x04)
{
if(er->ecm[141] > reader->pairtype)
{
rdr_log(reader, "reinit card in Unique Pairing Mode");
return ERROR;
}
if(er->ecm[141] == 0x80 && reader->pairtype == 0x80)
{
rdr_log(reader, "reinit card in Unique Pairing Mode");
return ERROR;
}
}
if(er->ecm[138] == 0x04 && !reader->nuid_length)
{
rdr_log(reader, "reinit card with NUID");
return ERROR;
}
}
}
uint8_t ecmreq[0xC0];
memset(ecmreq, 0xCC, 0xC0);
ecmreq[7] = 0x05;
if(reader->headermode == 0)
{
ecmreq[ 9] = 0x00;
ecmreq[10] = 0x00;
ecmreq[11] = 0x00;
ecmreq[12] = 0x00;
ecmreq[13] = 0x00;
}
else if(reader->headermode == 1)
{
ecmreq[ 9] = 0x04;
ecmreq[10] = reader->ecmheader[0];
ecmreq[11] = reader->ecmheader[1];
ecmreq[12] = reader->ecmheader[2];
ecmreq[13] = reader->ecmheader[3];
}
if(reader->cak7type == 3)
{
ecmreq[8] = er->ecm[7] + 6;
memcpy(&ecmreq[14], er->ecm + 7, er->ecm[7] + 1);
}
else
{
ecmreq[8] = er->ecm[4] + 6;
memcpy(&ecmreq[14], er->ecm + 4, er->ecm[4] + 1);
}
if((er->ecm[2] == 0xAC) && (er->ecm[3] == 0x05))
{
ecmreq[15] = 0x0A;
}
do_cak7_cmd(reader, cta_res, &cta_lr, ecmreq, sizeof(ecmreq), 0xB0);
rdr_log_dump_dbg(reader, D_READER, cta_res, 0xB0, "Decrypted ECM Answer:");
if((cta_res[cta_lr - 2] != 0x90 && cta_res[cta_lr - 1] != 0x00) || cta_lr == 0)
{
rdr_log(reader, "(ECM) Reader will be restart now cause: %02X %02X card answer!!!", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
else if(cta_res[27] != 0x00 && cta_res[27] != 0xCC)
{
memcpy(reader->ecmheader, cta_res + 9, 4);
reader->cak7_camstate = cta_res[4];
uint8_t _cwe0[8];
uint8_t _cwe1[8];
if(cta_res[78] == 0x01 || reader->forcecwswap)
{
memcpy(_cwe0, &cta_res[52], 0x08);
memcpy(_cwe1, &cta_res[28], 0x08);
}
else
{
memcpy(_cwe0, &cta_res[28], 0x08);
memcpy(_cwe1, &cta_res[52], 0x08);
}
if(cta_res[27] == 0x5C)
{
uint8_t cta_res144 = cta_res[144];
if(cta_res144 < 0x11)
{
if(!reader->cwekey_length[cta_res144])
{
rdr_log(reader, "ERROR: CWPK%d is not set, can not decrypt CW", cta_res[144]);
return ERROR;
}
des_ecb3_decrypt(_cwe0, reader->cwekey[cta_res144]);
des_ecb3_decrypt(_cwe1, reader->cwekey[cta_res144]);
rdr_log_dbg(reader, D_READER, "CW Decrypt ok");
}
}
else if(cta_res[27] == 0x58)
{
des_ecb3_decrypt(_cwe0, reader->key3des);
des_ecb3_decrypt(_cwe1, reader->key3des);
rdr_log_dbg(reader, D_READER, "CW Decrypt ok");
}
memcpy(ea->cw, _cwe0, 0x08);
memcpy(ea->cw + 8, _cwe1, 0x08);
return OK;
}
else if(cta_res[23] == 0x00)
{
memcpy(reader->ecmheader, cta_res + 9, 4);
reader->cak7_camstate = cta_res[4];
if(reader->hasunique && reader->pairtype < 0xC0)
{
rdr_log(reader, "reinit card in Unique Pairing Mode");
}
else
{
rdr_log(reader, "card has no right to decode this channel");
}
}
else if(cta_res[23] == 0x04)
{
if(!reader->nuid_length)
{
rdr_log(reader, "reinit card with NUID");
}
else
{
rdr_log(reader, "wrong OTP/OTA CSC values");
}
}
else
{
rdr_log(reader, "card got wrong ECM");
}
return ERROR;
}
static int32_t nagra3_do_emm(struct s_reader *reader, EMM_PACKET *ep)
{
def_resp;
if(ep->emm[0] == 0x90)
{
rdr_log(reader, "OSCam got your BoxEMM");
char tmp[128];
rdr_log(reader, "NUID: %s", cs_hexdump(1, reader->nuid, 4, tmp, sizeof(tmp)));
rdr_log(reader, "Index: %s", cs_hexdump(1, ep->emm + 10, 1, tmp, sizeof(tmp)));
rdr_log(reader, "eCWPK: %s", cs_hexdump(1, ep->emm + 11, 16, tmp, sizeof(tmp)));
}
else
{
uint8_t emmreq[0xC0];
memset(emmreq, 0xCC, 0xC0);
emmreq[7] = 0x05;
if(reader->headermode == 0)
{
emmreq[ 9] = 0x00;
emmreq[10] = 0x00;
emmreq[11] = 0x00;
emmreq[12] = 0x00;
emmreq[13] = 0x00;
}
else if(reader->headermode == 1)
{
emmreq[ 9] = 0x04;
emmreq[10] = reader->ecmheader[0];
emmreq[11] = reader->ecmheader[1];
emmreq[12] = reader->ecmheader[2];
emmreq[13] = reader->ecmheader[3];
}
if(reader->cak7type == 3)
{
int32_t i;
uint8_t *prov_id_ptr;
switch(ep->type)
{
case SHARED:
emmreq[8] = ep->emm[9] + 6;
prov_id_ptr = ep->emm + 3;
memcpy(&emmreq[14], ep->emm + 9, ep->emm[9] + 1);
break;
case UNIQUE:
emmreq[8] = ep->emm[12] + 6;
prov_id_ptr = ep->emm + 9;
memcpy(&emmreq[14], ep->emm + 12, ep->emm[12] + 1);
break;
case GLOBAL:
emmreq[8] = ep->emm[6] + 6;
prov_id_ptr = ep->emm + 3;
memcpy(&emmreq[14], ep->emm + 6, ep->emm[6] + 1);
break;
default:
rdr_log(reader, "EMM: Congratulations, you have discovered a new EMM on Merlin.");
rdr_log(reader, "This has not been decoded yet.");
return ERROR;
}
i = get_prov_index(reader, prov_id_ptr);
if(i == -1)
{
rdr_log(reader, "EMM: skipped since provider id doesnt match");
return SKIPPED;
}
}
else
{
emmreq[8] = ep->emm[9] + 6;
memcpy(&emmreq[14], ep->emm + 9, ep->emm[9] + 1);
}
do_cak7_cmd(reader, cta_res, &cta_lr, emmreq, sizeof(emmreq), 0xB0);
rdr_log_dump_dbg(reader, D_READER, cta_res, 0xB0, "Decrypted EMM Answer:");
if((cta_res[cta_lr - 2] != 0x90 && cta_res[cta_lr - 1] != 0x00) || cta_lr == 0)
{
rdr_log(reader, "(EMM) Reader will be restart now cause: %02X %02X card answer!!!", cta_res[cta_lr - 2], cta_res[cta_lr - 1]);
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
else
{
memcpy(reader->ecmheader, cta_res + 9, 4);
if(reader->cak7_seq >= reader->needrestart)
{
rdr_log(reader, "card needs FASTreinit to prevent crash");
if(!fastreinit(reader))
{
rdr_log(reader, "FASTreinit failed - need to restart reader");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
}
else if(cta_res[4] == 0x80)
{
rdr_log_dbg(reader, D_READER, "EMM forced card to reinit");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
else if(cta_res[13] == 0x02)
{
rdr_log_dbg(reader, D_READER, "Revision update - card reinit necessary");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
else if((cta_res[4] & 64) == 64)
{
rdr_log(reader, "negotiating new Session Key");
if(!CAK7_GetCamKey(reader))
{
rdr_log(reader, "negotiations failed - trying FASTreinit");
if(!fastreinit(reader))
{
rdr_log(reader, "FASTreinit failed - need to restart reader");
reader->card_status = CARD_NEED_INIT;
add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
}
}
}
else if(cta_res[8] == 0x0E)
{
rdr_log_dbg(reader, D_READER, "card got wrong EMM");
return OK;
}
struct timeb now;
cs_ftime(&now);
int64_t gone_now = comp_timeb(&now, &reader->emm_last);
int64_t gone_refresh = comp_timeb(&reader->emm_last, &reader->last_refresh);
if(((gone_now > (int64_t)3600*1000) && (gone_now < (int64_t)365*24*3600*1000)) || ((gone_refresh > (int64_t)12*3600*1000) && (gone_refresh < (int64_t)365*24*3600*1000)))
{
reader->last_refresh = now;
add_job(reader->client, ACTION_READER_CARDINFO, NULL, 0); // refresh entitlement since it might have been changed!
}
}
}
return OK;
}
const struct s_cardsystem reader_nagracak7 =
{
.desc = "nagra merlin",
.caids = (uint16_t[]){ 0x18, 0 },
.do_emm = nagra3_do_emm,
.do_ecm = nagra3_do_ecm,
.post_process = nagra3_post_process,
.card_info = nagra3_card_info,
.card_init = nagra3_card_init,
.get_emm_type = nagra_get_emm_type,
.get_emm_filter = nagra_get_emm_filter,
};
#endif