Esempio n. 1
0
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) {
		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) {
		rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]);
		rdr_log(rdr, "ERROR: response[-1] != 0x00 its 0x%02X", response[*response_length - 1]);
		return ERROR; // The reader responded with "command not OK"
	}
	return OK;
}
Esempio n. 2
0
static int32_t griffin_exec_cmd(struct s_reader *rdr, uint8_t cmd_op, const uint8_t *data, uint8_t data_len, uint8_t *response, uint16_t *response_length)
{
	struct griffin_data *csystem_data = rdr->csystem_data;
	uint8_t buf[cmd_buf_len];

	int32_t ret = reader_cmd2icc(rdr, buf,
		griffin_init_cmd(rdr, buf, csystem_data->cmd_base + cmd_op, data, data_len),
		response, response_length);
	if (DEBUG) {
		char tmp[1024];
		rdr_log(rdr, "RECV[1] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length);
	}
	if (ret || *response_length < 2) return ERROR; // Response is two short
	if (response[0] != 0x90)         return ERROR; // Invalid response
	if (response[1] == 0)            return OK;    // Nothing to retrieve, command OK

	// Retrieve response
	uint8_t cmd_read_response = 0x02;
	if (csystem_data->cmd_base > 0x10)
		cmd_read_response += csystem_data->cmd_base - 0x10;

	ret = reader_cmd2icc(rdr, buf,
		griffin_init_cmd(rdr, buf, cmd_read_response, NULL, response[1]),
		response, response_length);

	if (DEBUG) {
		char tmp[1024];
		rdr_log(rdr, "RECV[2] <- %s (ret=%d resp_len=%d)", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), ret, *response_length);
	}
	if (ret || *response_length < 2)            return ERROR; // Response is two short
	if (response[*response_length - 2] != 0x90) return ERROR; // Invalid response
	if (response[*response_length - 1] != 0x00) return ERROR; // We don't expect command_op 0x12 to return more data
	return OK;
}
Esempio n. 3
0
static int32_t conax_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
{
	int32_t i, ok = 0;
	char tmp_dbg[17];

	rdr_debug_mask(rdr, D_EMM, "Entered conax_get_emm_type ep->emm[2]=%02x", ep->emm[2]);

	for (i = 0; i < rdr->nprov; i++) {
		ok = (!memcmp(&ep->emm[6], rdr->sa[i], 4));
		if (ok) break;
	}

	if (ok) {
		ep->type = SHARED;
		memset(ep->hexserial, 0, 8);
		memcpy(ep->hexserial, &ep->emm[6], 4);
		rdr_debug_mask_sensitive(rdr, D_EMM, "SHARED, ep->hexserial = {%s}", cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg)));
		return 1;
	}
	else {
		if (!memcmp(&ep->emm[6], rdr->hexserial + 2, 4)) {
			ep->type = UNIQUE;
			memset(ep->hexserial, 0, 8);
			memcpy(ep->hexserial+2, &ep->emm[6], 4);
			rdr_debug_mask_sensitive(rdr, D_EMM, "UNIQUE, ep->hexserial = {%s}", cs_hexdump(1, ep->hexserial, 8, tmp_dbg, sizeof(tmp_dbg)));
			return 1;
		}
		else {
			ep->type = GLOBAL;
			rdr_debug_mask(rdr, D_EMM, "GLOBAL");
			memset(ep->hexserial, 0, 8);
			return 1;
		}
	}
}
Esempio n. 4
0
static int32_t bulcrypt_get_emm_type(EMM_PACKET *ep, struct s_reader *reader)
{
	char dump_emm_sn[64];
	int32_t emm_len = check_sct_len(ep->emm, 3);

	memset(ep->hexserial, 0, 8);

	if (emm_len < 176)
	{
		rdr_debug_mask(reader, D_TRACE | D_EMM, "emm_len < 176 (%u): %s",
			emm_len, cs_hexdump(1, ep->emm, 12, dump_emm_sn, sizeof(dump_emm_sn)));
		ep->type = UNKNOWN;
		return 0;
	}

	uint8_t mask_last = 0x00;
	ep->type = UNKNOWN;
	switch (ep->emm[0]) {
	case BULCRYPT_EMM_UNIQUE_82: ep->type = UNIQUE; mask_last = 0xF0; break; // Bulsatcom
	case BULCRYPT_EMM_UNIQUE_8a: ep->type = UNIQUE; mask_last = 0xF0; break; // Polaris
	case BULCRYPT_EMM_UNIQUE_85: ep->type = UNIQUE; mask_last = 0x00; break; // Bulsatcom
	case BULCRYPT_EMM_UNIQUE_8b: ep->type = UNIQUE; mask_last = 0x00; break; // Polaris
	case BULCRYPT_EMM_SHARED_84: ep->type = SHARED; break;
	}

	bool ret = false;
	if (ep->type == UNIQUE) {
		// The serial numbers looks like this:
		//   aa bb cc dd
		// To match EMM_82 and EMM_8a serial we compare (mask_last == 0xf0):
		//   aa bb cc d-
		// To match EMM_85 and EMM_8b serial we compare (mask_last == 0x00):
		//   aa bb cc --
		memcpy(ep->hexserial, ep->emm + 3, 4);
		ret = reader->hexserial[0] == ep->hexserial[0] &&
			  reader->hexserial[1] == ep->hexserial[1] &&
			  reader->hexserial[2] == ep->hexserial[2] &&
			  ((reader->hexserial[3] & mask_last) == (ep->hexserial[3] & mask_last));
	} else if (ep->type == SHARED) {
		// To match EMM_84
		//   aa bb -- --
		memcpy(ep->hexserial, ep->emm + 3, 2);
		ret = reader->hexserial[0] == ep->hexserial[0] &&
			  reader->hexserial[1] == ep->hexserial[1];
	}

	if (ret) {
		char dump_card_sn[64];
		cs_hexdump(1, reader->hexserial, 4, dump_card_sn, sizeof(dump_card_sn));
		cs_hexdump(1, ep->hexserial, 4, dump_emm_sn, sizeof(dump_emm_sn));
		rdr_log_sensitive(reader, "EMM_%s-%02x, emm_sn = {%s}, card_sn = {%s}",
			ep->type == UNIQUE ? "UNIQUE" :
			ep->type == SHARED ? "SHARED" : "??????",
			ep->emm[0],
			dump_emm_sn,
			dump_card_sn);
	}

	return ret;
}
Esempio n. 5
0
static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
	def_resp;
	char tmp_dbg[256];
	struct dre_data *csystem_data = reader->csystem_data;
	if(reader->caid == 0x4ae0)
	{
		uchar ecmcmd41[] = { 0x41,
							 0x58, 0x1f, 0x00,     //fixed part, dont change
							 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
							 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
							 0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
						   };
		ecmcmd41[22] = csystem_data->provider;
		memcpy(ecmcmd41 + 4, er->ecm + 8, 16);
		ecmcmd41[20] = er->ecm[6];  //keynumber
		ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
		rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg)));
		rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg)));
		if((dre_cmd(ecmcmd41)))     //ecm request
		{
			if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
				{ return ERROR; }       //exit if response is not 90 00
			memcpy(ea->cw, cta_res + 11, 8);
			memcpy(ea->cw + 8, cta_res + 3, 8);

			return OK;
		}
	}
	else
	{

		uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,  //fixed header?
							 0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
							 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
							 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
							 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
							 0x14          //provider
						   };
		memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21);
		rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
		rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
		ecmcmd51[33] = csystem_data->provider;  //no part of sig
		if((dre_cmd(ecmcmd51)))     //ecm request
		{
			if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
				{ return ERROR; }       //exit if response is not 90 00
			DREover(er->ecm, cta_res + 3);
			memcpy(ea->cw, cta_res + 11, 8);
			memcpy(ea->cw + 8, cta_res + 3, 8);
			return OK;
		}
	}
	return ERROR;
}
Esempio n. 6
0
static void rsakey_fn(const char *token, char *value, void *setting, FILE *f)
{
	struct s_reader *rdr = setting;
	if(value)
	{
		int32_t len = strlen(value);
		if(len != 128 && len != 240)
		{
			rdr->rsa_mod_length = 0;
			memset(rdr->rsa_mod, 0, 120);
		}
		else
		{
			if(key_atob_l(value, rdr->rsa_mod, len))
			{
				fprintf(stderr, "reader rsakey parse error, %s=%s\n", token, value);
				rdr->rsa_mod_length = 0;
				memset(rdr->rsa_mod, 0, sizeof(rdr->rsa_mod));
			}
			else
			{
				rdr->rsa_mod_length = len/2;	
			}
		}
		return;
	}
	int32_t len = rdr->rsa_mod_length;
	if(len > 0)
	{
		char tmp[len * 2 + 1];
		fprintf_conf(f, "rsakey", "%s\n", cs_hexdump(0, rdr->rsa_mod, len, tmp, sizeof(tmp)));
	}
	else if(cfg.http_full_cfg)
		{ fprintf_conf(f, "rsakey", "\n"); }
}
static void boxkey_fn(const char *token, char *value, void *setting, FILE *f)
{
	struct s_reader *rdr = setting;
	if(value)
	{
		int32_t len = strlen(value);
		if(len != 16 && len != 32)
		{
			memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
		}
		else
		{
			if(key_atob_l(value, rdr->boxkey, len))
			{
				fprintf(stderr, "reader boxkey parse error, %s=%s\n", token, value);
				memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
			}
		}
		return;
	}
	int32_t len = check_filled(rdr->boxkey, sizeof(rdr->boxkey));
	if(len > 0)
	{
		if(len > 8) { len = 16; }
		else { len = 8; }
		char tmp[len * 2 + 1];
		fprintf_conf(f, "boxkey", "%s\n", cs_hexdump(0, rdr->boxkey, len, tmp, sizeof(tmp)));
	}
	else if(cfg.http_full_cfg)
		{ fprintf_conf(f, "boxkey", "\n"); }
}
Esempio n. 8
0
static void boxkey_fn(const char *token, char *value, void *setting, FILE *f)
{
	struct s_reader *rdr = setting;
	if(value)
	{
		int32_t len = strlen(value);
		if(((len % 8) != 0) || len == 0 || len > 32)
		{
			rdr->boxkey_length = 0;
			memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
		}
		else
		{
			if(key_atob_l(value, rdr->boxkey, len))
			{
				fprintf(stderr, "reader boxkey parse error, %s=%s\n", token, value);
				rdr->boxkey_length = 0;
				memset(rdr->boxkey, 0, sizeof(rdr->boxkey));
			}
			else
			{
				rdr->boxkey_length = len/2;	
			}
		}
		return;
	}
	int32_t len = rdr->boxkey_length;
	if(len > 0)
	{
		char tmp[len * 2 + 1];
		fprintf_conf(f, "boxkey", "%s\n", cs_hexdump(0, rdr->boxkey, len, tmp, sizeof(tmp)));
	}
	else if(cfg.http_full_cfg)
		{ fprintf_conf(f, "boxkey", "\n"); }
}
static void ins7E_fn(const char *token, char *value, void *setting, long var_size, FILE *f)
{
	uint8_t *var = setting;
	var_size -= 1; // var_size contains sizeof(var) which is [X + 1]
	if(value)
	{
		int32_t len = strlen(value);
		if(len != var_size * 2 || key_atob_l(value, var, len))
		{
			if(len > 0)
				{ fprintf(stderr, "reader %s parse error, %s=%s\n", token, token, value); }
			memset(var, 0, var_size + 1);
		}
		else
		{
			var[var_size] = 1; // found and correct
		}
		return;
	}
	if(var[var_size])
	{
		char tmp[var_size * 2 + 1];
		fprintf_conf(f, token, "%s\n", cs_hexdump(0, var, var_size, tmp, sizeof(tmp)));
	}
	else if(cfg.http_full_cfg)
		{ fprintf_conf(f, token, "\n"); }
}
Esempio n. 10
0
int32_t constcw_analyse_file(uint16_t c_caid, uint32_t UNUSED(c_prid), uint16_t c_sid, uchar *dcw)
{
	//CAID:PROVIDER:SID:PMT:PID::XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX

	FILE *fp;
	char token[512];
	uint32_t caid, provid, sid, pmt, pid;
	int32_t cw[16];

	fp=fopen(cur_client()->reader->device, "r");
	if (!fp) return (0);

	while (fgets(token, sizeof(token), fp)){
		if (token[0]=='#') continue;

		sscanf(token, "%4x:%6x:%4x:%4x:%4x::%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmt, &pid,
			&cw[0], &cw[1], &cw[2],	&cw[3],	&cw[4], &cw[5], &cw[6], &cw[7],
			&cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]);

		//cs_log("Line found: %s", token);
		if (c_caid == caid && c_sid == sid){
			fclose(fp);
			int8_t i;
			for(i = 0; i < 16; ++i)
				dcw[i] = (uchar) cw[i];
			cs_log("Entry found: %04X:%06X:%04X:%04X:%04X::%s", caid, provid, sid, pmt, pid, cs_hexdump(1, dcw, 16, token, sizeof(token)));
			return 1;
		}
	}

	fclose(fp);
	return 0;
}
Esempio n. 11
0
static void saveemm(struct s_reader *aureader, EMM_PACKET *ep)
{
	FILE *fp;
	char tmp[17];
	char buf[80];
	char token[256];
	char *tmp2;
	time_t rawtime;
	uint32_t emmtype;
	struct tm timeinfo;
	if (ep->type == UNKNOWN)
		emmtype = EMM_UNKNOWN;
	else
		emmtype = 1 << (ep->type - 1);
	// should this nano be saved?
	if (((1 << (ep->emm[0] % 0x80)) & aureader->s_nano) || (aureader->saveemm & emmtype))
	{
		time(&rawtime);
		localtime_r(&rawtime, &timeinfo); // to access LOCAL date/time info
		int32_t emm_length = ((ep->emm[1] & 0x0f) << 8) | ep->emm[2];
		strftime(buf, sizeof(buf), "%Y/%m/%d %H:%M:%S", &timeinfo);
		fp = fopen(get_emmlog_filename(token, sizeof(token), aureader->label, "log"), "a");
		if (!fp) {
			rdr_log(aureader, "ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
		} else {
			if (cs_malloc(&tmp2, (emm_length + 3) * 2 + 1)) {
				fprintf(fp, "%s   %s   ", buf, cs_hexdump(0, ep->hexserial, 8, tmp, sizeof(tmp)));
				fprintf(fp, "%s\n", cs_hexdump(0, ep->emm, emm_length + 3, tmp2, (emm_length + 3) * 2 + 1));
				free(tmp2);
				rdr_log(aureader, "Successfully added EMM to %s", token);
			}
			fclose(fp);
		}
		fp = fopen(get_emmlog_filename(token, sizeof(token), aureader->label, "bin"), "ab");
		if (!fp) {
			rdr_log(aureader, "ERROR: Cannot open file '%s' (errno=%d: %s)\n", token, errno, strerror(errno));
		} else {
			if ((int)fwrite(ep->emm, 1, emm_length + 3, fp) == emm_length + 3) {
				rdr_log(aureader, "Successfully added binary EMM to %s", token);
			} else {
				rdr_log(aureader, "ERROR: Cannot write binary EMM to %s (errno=%d: %s)\n", token, errno, strerror(errno));
			}
			fclose(fp);
		}
	}
}
Esempio n. 12
0
static int32_t oscam_ser_send_ecm(struct s_client *client, ECM_REQUEST *er, uchar *buf)
{
	char *tmp;
	switch(client->serialdata->oscam_ser_proto)
	{
	case P_HSIC:
		memset(buf, 0, 12);
		buf[0] = 2;
		i2b_buf(2, er->caid, buf + 1);
		i2b_buf(3, er->prid, buf + 3);
		i2b_buf(2, er->pid, buf + 6);
		i2b_buf(2, er->srvid, buf + 10);
		memcpy(buf + 12, er->ecm, er->ecmlen);
		oscam_ser_send(client, buf, 12 + er->ecmlen);
		break;
	case P_BOMBA:
		oscam_ser_send(client, er->ecm, er->ecmlen);
		break;
	case P_DSR95:
		if(cs_malloc(&tmp, er->ecmlen * 2 + 1))
		{
			if(client->serialdata->dsr9500type == P_DSR_WITHSID)
			{
				snprintf((char *)buf, 512, "%c%08X%04X%s%04X\n\r",
						 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1), er->srvid);
				oscam_ser_send(client, buf, (er->ecmlen << 1) + 19); // 1 + 8 + 4 + l*2 + 4 + 2
			}
			else
			{
				snprintf((char *)buf, 512, "%c%08X%04X%s\n\r",
						 3, er->prid, er->caid, cs_hexdump(0, er->ecm, er->ecmlen, tmp, er->ecmlen * 2 + 1));
				oscam_ser_send(client, buf, (er->ecmlen << 1) + 15); // 1 + 8 + 4 + l*2 + 2
			}
			free(tmp);
		}
		break;
	case P_ALPHA:
		buf[0] = 0x80;
		i2b_buf(2, 2 + er->ecmlen, buf + 1);
		i2b_buf(2, er->caid, buf + 3);
		memcpy(buf + 5, er->ecm, er->ecmlen);
		oscam_ser_send(client, buf, oscam_ser_alpha_convert(buf, 5 + er->ecmlen));
		break;
	}
	return (0);
}
Esempio n. 13
0
static int32_t radegast_recv_chk(struct s_client *client, uchar *dcw, int32_t *rc, uchar *buf, int32_t UNUSED(n))
{
  if ((buf[0] == 2) && (buf[1] == 0x12)) {
    char tmp_dbg[33];
    memcpy(dcw, buf+4, 16);
    cs_debug_mask(D_CLIENT, "radegast: recv chk - %s", cs_hexdump(0, dcw, 16, tmp_dbg, sizeof(tmp_dbg)));
    *rc = 1;
    return(client->reader->msg_idx);
  }

  return (-1);
}
Esempio n. 14
0
int32_t ICC_Async_Activate(struct s_reader *reader, ATR *atr, uint16_t deprecated)
{
	rdr_debug_mask(reader, D_IFD, "Activating card");

	reader->current_baudrate = DEFAULT_BAUDRATE;
	if(reader->atr[0] != 0 && !reader->ins7e11_fast_reset)
	{
		rdr_log(reader, "Using ATR from reader config");
		ATR_InitFromArray(atr, reader->atr, ATR_MAX_SIZE);
	}
	else
	{
		call(reader->crdr.activate(reader, atr));
		if(reader->crdr.skip_extra_atr_parsing)
			{ return OK; }
	}

	unsigned char atrarr[ATR_MAX_SIZE];
	uint32_t atr_size;
	ATR_GetRaw(atr, atrarr, &atr_size);
	char tmp[atr_size * 3 + 1];
	rdr_log(reader, "ATR: %s", cs_hexdump(1, atrarr, atr_size, tmp, sizeof(tmp)));
	memcpy(reader->card_atr, atrarr, atr_size);
	reader->card_atr_length = atr_size;

	/* Get ICC reader->convention */
	if(ATR_GetConvention(atr, &(reader->convention)) != ATR_OK)
	{
		rdr_log(reader, "ERROR: Could not read reader->convention");
		reader->convention = 0;
		reader->protocol_type = 0;
		return ERROR;
	}

	reader->protocol_type = ATR_PROTOCOL_TYPE_T0;

	// Parse_ATR and InitCard need to be included in lock because they change parity of serial port
	if(reader->crdr.lock)
		{ reader->crdr.lock(reader); }

	int32_t ret = Parse_ATR(reader, atr, deprecated);

	if(reader->crdr.unlock)
		{ reader->crdr.unlock(reader); }

	if(ret)
		{ rdr_log(reader, "ERROR: Parse_ATR returned error"); }
	if(ret)
		{ return ERROR; }
	rdr_debug_mask(reader, D_IFD, "Card succesfully activated");

	return OK;
}
Esempio n. 15
0
static int32_t bulcrypt_do_emm(struct s_reader *reader, EMM_PACKET *ep)
{
	char tmp[512];
	uchar emm_cmd[1024];

	def_resp

	// DE 04 xx yy B0
	//  xx == EMM type   (emm[0])
	//  yy == EMM type2  (emm[5])
	//  B0 == EMM len    (176)
	memcpy(emm_cmd, cmd_emm1, sizeof(cmd_emm1));
	memcpy(emm_cmd + sizeof(cmd_emm1), ep->emm + 7, 176);

	switch (ep->emm[0]) {
	case BULCRYPT_EMM_UNIQUE_82:
		emm_cmd[2] = ep->emm[0]; // 0x82
		break;
	case BULCRYPT_EMM_UNIQUE_8a: // Polaris equivallent of 0x82
		emm_cmd[2] = 0x82;
		emm_cmd[3] = 0x0b;
		break;
	case BULCRYPT_EMM_SHARED_84:
		emm_cmd[2] = ep->emm[0]; // 0x84
		emm_cmd[3] = ep->emm[5]; // 0x0b
		break;
	case BULCRYPT_EMM_UNIQUE_85:
	case BULCRYPT_EMM_UNIQUE_8b: // Polaris 0x85 equivallent of 0x85
		memcpy(emm_cmd, cmd_emm2, sizeof(cmd_emm2));
		emm_cmd[2] = ep->emm[5]; // 0xXX (Last bytes of the serial)
		emm_cmd[3] = ep->emm[6]; // 0x0b
		break;
	}

	// Write emm
	write_cmd(emm_cmd, emm_cmd + 5);
	if (cta_lr != 2 || cta_res[0] != 0x90 || (cta_res[1] != 0x00 && cta_res[1] != 0x0a))
	{
		rdr_log(reader, "(emm_cmd) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	if (ep->emm[0] == BULCRYPT_EMM_UNIQUE_82 && cta_res[0] == 0x90 && cta_res[1] == 0x0a) {
		rdr_log(reader, "Your subscription data was updated.");
		add_job(reader->client, ACTION_READER_CARDINFO, NULL, 0);
	}

	return OK;
}
Esempio n. 16
0
static int32_t dre_set_provider_info(struct s_reader *reader)
{
	def_resp;
	int32_t i;
	uchar cmd59[] = { 0x59, 0x14 };   // subscriptions
	uchar cmd5b[] = { 0x5b, 0x00, 0x14 }; //validity dates
	struct dre_data *csystem_data = reader->csystem_data;

	cs_clear_entitlement(reader);

	cmd59[1] = csystem_data->provider;
	if((dre_cmd(cmd59)))      //ask subscription packages, returns error on 0x11 card
	{
		uchar pbm[32];
		char tmp_dbg[65];
		memcpy(pbm, cta_res + 3, cta_lr - 6);
		rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, 32, tmp_dbg, sizeof(tmp_dbg)));

		if(pbm[0] == 0xff)
			{ rdr_log(reader, "no active packages"); }
		else
			for(i = 0; i < 32; i++)
				if(pbm[i] != 0xff)
				{
					cmd5b[1] = i;
					cmd5b[2] = csystem_data->provider;
					dre_cmd(cmd5b);   //ask for validity dates

					time_t start;
					time_t end;
					start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
					end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];

					struct tm temp;

					localtime_r(&start, &temp);
					int32_t startyear = temp.tm_year + 1900;
					int32_t startmonth = temp.tm_mon + 1;
					int32_t startday = temp.tm_mday;
					localtime_r(&end, &temp);
					int32_t endyear = temp.tm_year + 1900;
					int32_t endmonth = temp.tm_mon + 1;
					int32_t endday = temp.tm_mday;
					rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i, startyear, startmonth, startday,
							endyear, endmonth, endday);
					cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, 0, start, end, 1, 1);
				}
	}
	return OK;
}
Esempio n. 17
0
void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er) {
	if (ecm_ratelimit_check(reader, er, 1) != OK) {
		rdr_debug_mask(reader, D_READER, "%s: ratelimit check failed.", __func__);
		return; // reader_mode = 1: checkout ratelimiter in reader mode so srvid can be replaced
	}
	cs_ddump_mask(D_ATR, er->ecm, er->ecmlen, "ecm:");

	struct timeb tps, tpe;
	cs_ftime(&tps);

	struct s_ecm_answer ea;
	memset(&ea, 0, sizeof(struct s_ecm_answer));

	int32_t rc = cardreader_do_ecm(reader, er, &ea);
	rdr_debug_mask(reader, D_READER, "%s: cardreader_do_ecm returned rc=%d (ERROR=%d)", __func__, rc, ERROR);

	ea.rc = E_FOUND; //default assume found
	ea.rcEx = 0; //no special flag

	if (rc == ERROR) {
		char buf[32];
		rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
			er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
		ea.rc = E_NOTFOUND;
		ea.rcEx = 0;
		ICC_Async_DisplayMsg(reader, "Eer");
	}

	if (rc == E_CORRUPT) {
		char buf[32];
		rdr_debug_mask(reader, D_READER, "Error processing ecm for caid %04X, srvid %04X, servicename: %s",
			er->caid, er->srvid, get_servicename(cl, er->srvid, er->caid, buf));
		ea.rc = E_NOTFOUND;
		ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum
		memcpy (ea.msglog,"Invalid ecm type for card",25);
	}
	cs_ftime(&tpe);
	cl->lastecm=time((time_t*)0);
	char ecmd5[17*3];                
    cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));

	rdr_debug_mask(reader, D_READER, "ecm hash: %s real time: %ld ms",
		ecmd5, 1000 * (tpe.time - tps.time) + tpe.millitm - tps.millitm);

	write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog);

	reader_post_process(reader);
}
Esempio n. 18
0
void cardreader_process_ecm(struct s_reader *reader, struct s_client *cl, ECM_REQUEST *er)
{

	cs_log_dump_dbg(D_ATR, er->ecm, er->ecmlen, "ecm:");

	struct timeb tps, tpe;
	struct s_ecm_answer ea;
	memset(&ea, 0, sizeof(struct s_ecm_answer));
	
	cs_ftime(&tps);
	int32_t rc = cardreader_do_ecm(reader, er, &ea);
	cs_ftime(&tpe);
	
	rdr_log_dbg(reader, D_READER, "%s: cardreader_do_ecm returned rc=%d (ERROR=%d)", __func__, rc, ERROR);

	ea.rc = E_FOUND; //default assume found
	ea.rcEx = 0; //no special flag

	if(rc == ERROR)
	{
		char buf[CS_SERVICENAME_SIZE];
		rdr_log_dbg(reader, D_READER, "Error processing ecm for caid %04X, provid %06X, srvid %04X, servicename: %s",
					   er->caid, er->prid, er->srvid, get_servicename(cl, er->srvid, er->prid, er->caid, buf, sizeof(buf)));
		ea.rc = E_NOTFOUND;
		ea.rcEx = 0;
		ICC_Async_DisplayMsg(reader, "Eer");
	}

	if(rc == E_CORRUPT)
	{
		char buf[CS_SERVICENAME_SIZE];
		rdr_log_dbg(reader, D_READER, "Error processing ecm for caid %04X, provid %06X, srvid %04X, servicename: %s",
					   er->caid, er->prid, er->srvid, get_servicename(cl, er->srvid, er->prid, er->caid, buf, sizeof(buf)));
		ea.rc = E_NOTFOUND;
		ea.rcEx = E2_WRONG_CHKSUM; //flag it as wrong checksum
		memcpy(ea.msglog, "Invalid ecm type for card", 25);
	}

	write_ecm_answer(reader, er, ea.rc, ea.rcEx, ea.cw, ea.msglog, ea.tier, &ea.cw_ex);
	
	cl->lastecm = time((time_t *)0);
	char ecmd5[17 * 3];
	cs_hexdump(0, er->ecmd5, 16, ecmd5, sizeof(ecmd5));

	rdr_log_dbg(reader, D_READER, "ecm hash: %s real time: %"PRId64" ms", ecmd5, comp_timeb(&tpe, &tps));
	
	reader_post_process(reader);
}
Esempio n. 19
0
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...)
{
	va_list params;

	char log_txt[LOG_BUF_SIZE];
	int32_t i, len = 0;
	pthread_mutex_lock(&log_mutex);
	if (((mask & cs_dblevel) || !mask) && (fmt))
	{
		va_start(params, fmt);
		len = get_log_header(1, log_txt);
		vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params);
		va_end(params);
		int repeated_line = strcmp(last_log_txt, log_txt + len) == 0;
		if (last_log_duplicates > 0) {
			if (!last_log_ts) // Must be initialized once
				last_log_ts = log_ts;
			// Report duplicated lines when the new log line is different
			// than the old or 60 seconds have passed.
			if (!repeated_line || log_ts - last_log_ts >= 60) {
				char dupl[len + 32];
				len = get_log_header(2, dupl);
				snprintf(dupl + len - 1, len + 32, "--- Skipped %d duplicated log lines ---", last_log_duplicates);
				write_to_log_int(dupl, 0);
				last_log_duplicates = 0;
				last_log_ts = log_ts;
			}
		}
		if (!repeated_line) {
			memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE);
			write_to_log_int(log_txt, len);
		} else {
			last_log_duplicates++;
		}
	}
	if (buf && ((mask & cs_dblevel) || !mask))
	{
		for (i=0; i<n; i+=16)
		{
			len = get_log_header(0, log_txt);
			cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i, log_txt + len, sizeof(log_txt) - len);
			write_to_log_int(log_txt, len);
		}
	}
	pthread_mutex_unlock(&log_mutex);
}
Esempio n. 20
0
// Sets cmd_buf and returns buf_len
static uint32_t griffin_init_cmd(struct s_reader *rdr, uint8_t *cmd_buf, uint8_t cmd_op, const uint8_t *data, uint8_t data_len)
{
	#define cmd_len 5
	memset(cmd_buf, 0, cmd_buf_len);
	cmd_buf[0] = 0xDC; // Command start
	cmd_buf[1] = cmd_op;
	cmd_buf[2] = 0x00;
	cmd_buf[3] = 0x00;
	cmd_buf[4] = data_len; // Set payload length
	if (data && data_len)
		memcpy(cmd_buf + cmd_len, data, data_len);
	uint32_t len = cmd_len + (data ? data_len : 0);
	if (DEBUG) {
		char tmp[1024];
		rdr_log(rdr, "SEND[-] -> %s", cs_hexdump(1, cmd_buf, len, tmp, sizeof(tmp)));
	}
	return len;
}
Esempio n. 21
0
static int32_t pcsc_activate_card(struct s_reader *pcsc_reader, uchar *atr, uint16_t *atr_size)
{
	struct pcsc_data *crdr_data = pcsc_reader->crdr_data;
	LONG rv;
	DWORD dwState, dwAtrLen, dwReaderLen;
	unsigned char pbAtr[ATR_MAX_SIZE];
	char tmp[sizeof(pbAtr) * 3 + 1];

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC initializing card in (%s)", crdr_data->pcsc_name);
	dwAtrLen = sizeof(pbAtr);
	dwReaderLen = 0;

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting card in (%s) with handle %ld", crdr_data->pcsc_name, (long)(crdr_data->hCard));
	rv = SCardReconnect(crdr_data->hCard, SCARD_SHARE_EXCLUSIVE, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,  SCARD_RESET_CARD, &crdr_data->dwActiveProtocol);

	if(rv != SCARD_S_SUCCESS)
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to reset card (%lx)", (unsigned long)rv);
		return ERROR;
	}

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC resetting done on card in (%s)", crdr_data->pcsc_name);
	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 :  1));

	rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC getting ATR for card in (%s)", crdr_data->pcsc_name);
	rv = SCardStatus(crdr_data->hCard, NULL, &dwReaderLen, &dwState, &crdr_data->dwActiveProtocol, pbAtr, &dwAtrLen);
	if(rv == SCARD_S_SUCCESS)
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "PCSC Protocol (T=%d)", (crdr_data->dwActiveProtocol == SCARD_PROTOCOL_T0 ? 0 :  1));
		memcpy(atr, pbAtr, dwAtrLen);
		*atr_size = dwAtrLen;

		rdr_log(pcsc_reader, "ATR: %s", cs_hexdump(1, (uchar *)pbAtr, dwAtrLen, tmp, sizeof(tmp)));
		memcpy(pcsc_reader->card_atr, pbAtr, dwAtrLen);
		pcsc_reader->card_atr_length = dwAtrLen;
		return OK;
	}
	else
	{
		rdr_log_dbg(pcsc_reader, D_DEVICE, "ERROR: PCSC failed to get ATR for card (%lx)", (unsigned long)rv);
	}

	return ERROR;
}
Esempio n. 22
0
void cs_log_hex(const char *log_prefix, const uint8_t *buf, int32_t n, const char *fmt, ...)
{
	if(logStarted == 0)
		{ return; }
	
	SAFE_MUTEX_LOCK_NOLOG(&log_mutex);
	__do_log();
	if(buf)
	{
		int32_t i;
		__init_log_prefix("%10s   ");
		for(i = 0; i < n; i += 16)
		{
			cs_hexdump(1, buf + i, (n - i > 16) ? 16 : n - i, log_txt + hdr_len + log_prefix_len, sizeof(log_txt) - (hdr_len + log_prefix_len));
			write_to_log_int(log_txt, hdr_len, hdr_logcount_offset, hdr_date_offset, hdr_time_offset, hdr_info_offset);
		}
	}
	SAFE_MUTEX_UNLOCK_NOLOG(&log_mutex);
}
Esempio n. 23
0
static int32_t bulcrypt_do_emm(struct s_reader *reader, EMM_PACKET *ep)
{
	char tmp[512];
	uchar emm_cmd[1024];

	def_resp

	switch (ep->emm[0]) {
	case BULCRYPT_EMM_UNIQUE_82:
		// DE 02 82 00 B0
		memcpy(emm_cmd, cmd_emm_uniq, sizeof(cmd_emm));
		memcpy(emm_cmd + sizeof(cmd_emm), ep->emm + 7, 176);
		break;
	case BULCRYPT_EMM_UNIQUE_85:
	case BULCRYPT_EMM_SHARED_84:
	case BULCRYPT_EMM_8b:
	case BULCRYPT_EMM_8a:
		// DE 04 00 00 B0
		memcpy(emm_cmd, cmd_emm, sizeof(cmd_emm));
		memcpy(emm_cmd + sizeof(cmd_emm), ep->emm + 7, 176);
		emm_cmd[2] = ep->emm[5]; // Emm cmd 1
		emm_cmd[3] = ep->emm[6]; // Emm cmd 2
		break;
	}

	// Write emm
	write_cmd(emm_cmd, emm_cmd + 5);
	if (cta_lr != 2 || cta_res[0] != 0x90 || (cta_res[1] != 0x00 && cta_res[1] != 0x0a))
	{
		rdr_log(reader, "(emm_cmd) Unexpected card answer: %s",
			cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
		return ERROR;
	}

	if (ep->emm[0] == BULCRYPT_EMM_UNIQUE_82 && cta_res[0] == 0x90 && cta_res[1] == 0x0a)
		rdr_log(reader, "Your subscription data was updated.");

	return OK;
}
Esempio n. 24
0
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...)
{
	va_list params;

	char log_txt[LOG_BUF_SIZE];
	int32_t i, len = 0;
	if (((mask & cs_dblevel) || !mask) && (fmt))
	{
		va_start(params, fmt);
		len = get_log_header(1, log_txt);
		vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params);
		write_to_log_int(log_txt, len);
		va_end(params);
	}
	if (buf && (mask & cs_dblevel || !mask))
	{
		for (i=0; i<n; i+=16)
		{
			len = get_log_header(0, log_txt);
			cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i, log_txt + len, sizeof(log_txt) - len);
			write_to_log_int(log_txt, len);
		}
	}
}
Esempio n. 25
0
static int32_t dre_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
{
	def_resp;
	uint16_t overcryptId;
	uint8_t tmp[16];
	char tmp_dbg[256];
	struct dre_data *csystem_data = reader->csystem_data;
	if(reader->caid == 0x4ae0)
	{
		uchar ecmcmd41[] = { 0x41,
							 0x58, 0x1f, 0x00,     //fixed part, dont change
							 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,   //0x01 - 0x08: next key
							 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18,   //0x11 - 0x18: current key
							 0x3b, 0x59, 0x11      //0x3b = keynumber, can be a value 56 ;; 0x59 number of package = 58+1 - Pay Package ;; 0x11 = provider
						   };
		ecmcmd41[22] = csystem_data->provider;
		memcpy(ecmcmd41 + 4, er->ecm + 8, 16);
		ecmcmd41[20] = er->ecm[6];  //keynumber
		ecmcmd41[21] = 0x58 + er->ecm[25];  //package number
		rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 8, tmp_dbg, sizeof(tmp_dbg)));
		rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 24, er->ecm[2] + 2 - 24, tmp_dbg, sizeof(tmp_dbg)));
		if((dre_cmd(ecmcmd41)))     //ecm request
		{
			if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
				{ return ERROR; }       //exit if response is not 90 00
			memcpy(ea->cw, cta_res + 11, 8);
			memcpy(ea->cw + 8, cta_res + 3, 8);

			return OK;
		}
	}

    else if(reader->caid == 0x4ae1)
    {
        if(csystem_data->provider == 0x11 || csystem_data->provider == 0x14)
        {
            uchar ecmcmd51[] = { 0x51, 0x02, 0x56, 0x05, 0x00, 0x4A, 0xE3,  //fixed header?
                                 0x9C, 0xDA,       //first three nibbles count up, fourth nibble counts down; all ECMs sent twice
                                 0xC1, 0x71, 0x21, 0x06, 0xF0, 0x14, 0xA7, 0x0E,   //next key?
                                 0x89, 0xDA, 0xC9, 0xD7, 0xFD, 0xB9, 0x06, 0xFD,   //current key?
                                 0xD5, 0x1E, 0x2A, 0xA3, 0xB5, 0xA0, 0x82, 0x11,   //key or signature?
                                 0x14          //provider
                               };
            memcpy(ecmcmd51 + 1, er->ecm + 5, 0x21);
            rdr_log_dbg(reader, D_READER, "unused ECM info front:%s", cs_hexdump(0, er->ecm, 5, tmp_dbg, sizeof(tmp_dbg)));
            rdr_log_dbg(reader, D_READER, "unused ECM info back:%s", cs_hexdump(0, er->ecm + 37, 4, tmp_dbg, sizeof(tmp_dbg)));
            ecmcmd51[33] = csystem_data->provider;  //no part of sig

            if((dre_cmd(ecmcmd51)))     //ecm request
            {
                if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
                    { return ERROR; }       //exit if response is not 90 00

                if(er->ecm[2] >= 46 && er->ecm[43] == 1 && csystem_data->provider == 0x11)
                {
                    memcpy(tmp, cta_res + 11, 8);
                    memcpy(tmp + 8, cta_res + 3, 8);
                    overcryptId = b2i(2, &er->ecm[44]);
                    rdr_log_dbg(reader, D_READER, "ICG ID: %04X", overcryptId);
                    Drecrypt2OverCW(overcryptId,tmp);
                    if(isValidDCW(tmp))
                    {
                        memcpy(ea->cw, tmp, 16);
                        return OK;
                    }
                    return ERROR;
                }

                DREover(reader, er->ecm, cta_res + 3);

                if(isValidDCW(cta_res + 3))
                {
                    memcpy(ea->cw, cta_res + 11, 8);
                    memcpy(ea->cw + 8, cta_res + 3, 8);
                    return OK;
                }
            }
        }
        else if((csystem_data->provider == 0x02 || csystem_data->provider == 0x03) && er->ecm[3] == 3)
        {
            // DRE 3

            if (er->ecm[4] == 2)
            {
                memcpy( ea->cw   , &er->ecm[42], 8);
                memcpy(&ea->cw[8], &er->ecm[34], 8);
                return OK;
            }

            uchar cmdlen;
            uchar crypted = er->ecm[8] & 1;
            uchar cryptkey = (er->ecm[8] & 6) >> 1;

            if (crypted == 0)
            {
                cmdlen = 50;
            }
            else
            {
                cmdlen = 57;
            }

            uchar ecmcmd[cmdlen];

            memcpy(ecmcmd, &er->ecm[17], cmdlen-1);
            ecmcmd[cmdlen-1] = csystem_data->provider;

            dre_cmd_c(ecmcmd, crypted, cryptkey);

            if(cta_res[2] == 0xD2 && isValidDCW(cta_res + 3))
            {
                memcpy(ea->cw, cta_res+11, 8);
                memcpy(ea->cw+8, cta_res+3, 8);
                return OK;
            }
        }
    }
    else if(reader->caid == 0x2710 && er->ecm[3] == 4)
Esempio n. 26
0
static int32_t dre_command(struct s_reader *reader, const uchar *cmd, int32_t cmdlen, unsigned char *cta_res, uint16_t *p_cta_lr, 
                                                            uint8_t crypted, uint8_t keynum, uint8_t dre_v, uint8_t cmd_type)
                                                            //attention: inputcommand will be changed!!!! answer will be in cta_res, length cta_lr ; returning 1 = no error, return ERROR = err
{
	uchar startcmd[] = { 0x80, 0xFF, 0x10, 0x01, 0x05 };  //any command starts with this,
	//last byte is nr of bytes of the command that will be sent
	//after the startcmd
	//response on startcmd+cmd:     = { 0x61, 0x05 }  //0x61 = "OK", last byte is nr. of bytes card will send
	uchar reqans[] = { 0x00, 0xC0, 0x00, 0x00, 0x08 };    //after command answer has to be requested,
	//last byte must be nr. of bytes that card has reported to send
	uchar command[256];
	uchar checksum;
	char tmp[256];
	int32_t headerlen = sizeof(startcmd);

    if(dre_v > 0)
    {
        startcmd[1] = 0;
        startcmd[2] = crypted;
        startcmd[3] = keynum;
    }

    startcmd[4] = cmdlen + 3 - cmd_type; //commandlength + type + len + checksum bytes
	memcpy(command, startcmd, headerlen);
    command[headerlen++] = cmd_type ? 0x86 : CMD_BYTE;  //type
    command[headerlen++] = cmdlen + (cmd_type == 1 ? 0 : 1);    //len = command + 1 checksum byte
	memcpy(command + headerlen, cmd, cmdlen);

    if(!cmd_type)
    {
        checksum = ~xor(cmd, cmdlen);
        //rdr_log_dbg(reader, D_READER, "Checksum: %02x", checksum);
        cmdlen += headerlen;
        command[cmdlen++] = checksum;
    }
    else cmdlen += headerlen;

	reader_cmd2icc(reader, command, cmdlen, cta_res, p_cta_lr);

	if((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE))
	{
		rdr_log(reader, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
		rdr_log(reader, "unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
		return ERROR;           //error
	}

    rdr_log_dbg(reader, D_READER, "command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp)));
    rdr_log_dbg(reader, D_READER, "answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));

	reqans[4] = cta_res[1];   //adapt length byte
	reader_cmd2icc(reader, reqans, 5, cta_res, p_cta_lr);

	if(cta_res[0] != CMD_BYTE)
	{
		rdr_log(reader, "unknown response: cta_res[0] expected to be %02x, is %02x", CMD_BYTE, cta_res[0]);
		return ERROR;
	}

	if((cta_res[1] == 0x03) && (cta_res[2] == 0xe2))
	{
		switch(cta_res[3+dre_v])
		{
		case 0xe1:
			rdr_log(reader, "checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		case 0xe2:
			rdr_log(reader, "wrong cmd len: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		case 0xe3:
			rdr_log(reader, "illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
        case 0xe4:
            rdr_log(reader, "wrong adress type: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe5:
            rdr_log(reader, "wrong CMD param: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe6:
            rdr_log(reader, "wrong UA: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe7:
            rdr_log(reader, "wrong group: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xe8:
            rdr_log(reader, "wrong key num: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xeb:
            rdr_log(reader, "No key or subscribe : %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
		case 0xec:
			rdr_log(reader, "wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
        case 0xed:
            rdr_log(reader, "wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
        case 0xef:
            rdr_log(reader, "wrong GEO code: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
            break;
		default:
			rdr_log_dbg(reader, D_READER, "unknown error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
			break;
		}
		return ERROR;           //error
	}

	int32_t length_excl_leader = *p_cta_lr;

	if((cta_res[*p_cta_lr - 2] == 0x90) && (cta_res[*p_cta_lr - 1] == 0x00))
		{ length_excl_leader -= 2; }

	checksum = ~xor(cta_res + 2, length_excl_leader - 3);

	if(cta_res[length_excl_leader - 1] != checksum)
	{
		rdr_log(reader, "checksum does not match, expected %02x received %02x:%s", checksum,
				cta_res[length_excl_leader - 1], cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp)));
		return ERROR;           //error
	}
	return OK;
}
Esempio n. 27
0
/*
static void cmd_test(struct s_reader *reader)
{
    def_resp;
    int i;
    uchar drecmd[] = { 0x00, 0x02 };
    char tmp[64];

    for(i = 0; i <= 0xFF; i++)
    {
        if(i == 0x45) continue;
        drecmd[0] = i;
        dre_cmd(drecmd);
        if(cta_res[2] == 0xE2)
        {
            if(cta_res[3] != 0xE3) rdr_log(reader, "cmd %02X error %02X",i ,cta_res[3]);
        }
        else
        {
            rdr_log(reader, "cmd %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
    }

    uchar drecmd[64];

    //memset(drecmd, 0, 64);
    //drecmd[0] = 0x71;
    for(i = 2; i <= 64; i++)
    {
        memset(drecmd, 0, 64);
        drecmd[i-1] = 0x02;
        drecmd[0] = 0x71;

        dre_script(drecmd, i, 0, 0, 0);

        if(cta_res[2] == 0xE2)
        {
            if((cta_res[3] != 0xE2) & (cta_res[3] != 0xED)) rdr_log(reader, "Len %02X error %02X",i ,cta_res[3]);
            if((cta_res[3] & 0xF0) != 0xE0) rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
        else
        {
            rdr_log(reader, "Len %02X answer %s",i ,cs_hexdump(0, cta_res, cta_res[1]+2, tmp, sizeof(tmp)));
        }
    }
}
*/
static int32_t dre_card_init(struct s_reader *reader, ATR *newatr)
{
	get_atr;
	def_resp;
	uchar ua[] = { 0x43, 0x15 };  // get serial number (UA)
	uchar providers[] = { 0x49, 0x15 };   // get providers
	uchar cmd56[] = { 0x56, 0x00 };
	int32_t i;
	char *card;
	char tmp[9];

	if((atr[0] != 0x3b) || (atr[1] != 0x15) || (atr[2] != 0x11) || (atr[3] != 0x12) || (
				((atr[4] != 0x01) || (atr[5] != 0x01)) &&
				((atr[4] != 0xca) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcb) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcc) || (atr[5] != 0x07)) &&
                ((atr[4] != 0xcd) || (atr[5] != 0x07))
			))
		{ return ERROR; }

	if(!cs_malloc(&reader->csystem_data, sizeof(struct dre_data)))
		{ return ERROR; }
	struct dre_data *csystem_data = reader->csystem_data;

	csystem_data->provider = atr[6];
	uchar checksum = xor(atr + 1, 6);

	if(checksum != atr[7])
		{ rdr_log(reader, "warning: expected ATR checksum %02x, smartcard reports %02x", checksum, atr[7]); }

	switch(atr[6])
	{
        case 0:

            if(!(dre_cmd(cmd56))) { return ERROR; }
            if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { return ERROR; }

            switch(cta_res[4])
            {
                case 0x02:
                    card = "Tricolor Centr DRE3";
                    reader->caid = 0x4ae1;
                    break;
                case 0x03:
                    card = "Tricolor Syberia DRE3";
                    reader->caid = 0x4ae1;  
                    break;
                case 0x18:
                case 0x19:
                    card = "Tricolor Centr DRE4";
                    reader->caid = 0x2710;
                    break;
                case 0x1A:
                    card = "Tricolor Syberia DRE4";
                    reader->caid = 0x2710;
                    break;
                default:
                    return ERROR;
            }
            csystem_data->provider = cta_res[4];
            providers[0] = 0x83;
            break;
        case 0x11:
            card = "Tricolor Centr DRE2";
            reader->caid = 0x4ae1;
            break;          //59 type card = MSP (74 type = ATMEL)
        case 0x12:
            card = "Cable TV";
            reader->caid = 0x4ae1;  //TODO not sure about this one
            break;
        case 0x14:
            card = "Tricolor Syberia DRE2";
            reader->caid = 0x4ae1;
            break;          //59 type card
        case 0x15:
            card = "Platforma HD / DW old";
            reader->caid = 0x4ae1;
            break;          //59 type card
        default:
            return ERROR;
	}

	memset(reader->prid, 0x00, 8);

    if(atr[6] > 0)
    {
        reader->prid[0][3] = atr[6];
    }
    else
    {
        reader->prid[0][3] = csystem_data->provider;
    }

	uchar cmd54[] = { 0x54, 0x14 };   // geocode
	cmd54[1] = csystem_data->provider;
	uchar geocode = 0;
	if((dre_cmd(cmd54)))      //error would not be fatal, like on 0x11 cards
		{ geocode = cta_res[3]; }

	providers[1] = csystem_data->provider;
	if(!(dre_cmd(providers)))
		{ return ERROR; }           //fatal error
	if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
		{ return ERROR; }

	uchar provname[128];
	for(i = 0; ((i < cta_res[2] - 6) && (i < 128)); i++)
	{
		provname[i] = cta_res[6 + i];
		if(provname[i] == 0x00)
			{ break; }
	}

	int32_t major_version = cta_res[3];
	int32_t minor_version = cta_res[4];

	ua[1] = csystem_data->provider;
	dre_cmd(ua);          //error would not be fatal

	int32_t hexlength = cta_res[1] - 2;   //discard first and last byte, last byte is always checksum, first is answer code

    if(reader->force_ua)
    {
        rdr_log(reader, "WARNING!!!! used UA from force_ua %08X", reader->force_ua);
        memcpy(cta_res + 3, &reader->force_ua, 4);
    }

	reader->hexserial[0] = 0;
	reader->hexserial[1] = 0;
	memcpy(reader->hexserial + 2, cta_res + 3, hexlength);

	int32_t low_dre_id, dre_chksum;
	uchar buf[32];

    if(major_version < 0x3)
    {
        low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]) - 48608;
        dre_chksum = 0;
        snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider - 16, major_version + 1, low_dre_id);

        for(i = 0; i < 32; i++)
        {
            if(buf[i] == 0x00)
                { break; }
            dre_chksum += buf[i] - 48;
        }

        if(major_version < 2)
        {
            reader->caid = 0x4ae0;
            card = csystem_data->provider == 0x11 ? "Tricolor Centr DRE1" : "Tricolor Syberia DRE1";
        }

        rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%i%i%08i, geocode %i, card: %s v%i.%i",
                reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider - 16,
                major_version + 1, low_dre_id, geocode, card, major_version, minor_version);
    }
    else
    {
        low_dre_id = ((cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6]);
        dre_chksum = 0;
        snprintf((char *)buf, sizeof(buf), "%i%i%08i", csystem_data->provider, major_version, low_dre_id);

        for(i = 0; i < 32; i++)
        {
            if(buf[i] == 0x00)
                { break; }
            dre_chksum += buf[i] - 48;
        }
        rdr_log(reader, "type: DRE Crypt, caid: %04X, serial: {%s}, dre id: %i%03i%i%08i, geocode %i, card: %s v%i.%i",
                reader->caid, cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)), dre_chksum, csystem_data->provider,
                major_version, low_dre_id, geocode, card, major_version, minor_version);
    }

	rdr_log(reader, "Provider name:%s.", provname);

	memset(reader->sa, 0, sizeof(reader->sa));
	memcpy(reader->sa[0], reader->hexserial + 2, 1);  //copy first byte of unique address also in shared address, because we dont know what it is...

	rdr_log_sensitive(reader, "SA = %02X%02X%02X%02X, UA = {%s}", reader->sa[0][0], reader->sa[0][1], reader->sa[0][2],
					  reader->sa[0][3], cs_hexdump(0, reader->hexserial + 2, 4, tmp, sizeof(tmp)));

	reader->nprov = 1;

//  cmd_test(reader);

    // exec user script, wicardd format
    if(reader->userscript != NULL)
    {
        uint8_t *usercmd = NULL;
        int cmd_len;
        int n;
        char *tempbuf = malloc(2048);
        trim2(reader->userscript);
        FILE *pFile = fopen(reader->userscript, "rt");

        if(pFile != NULL)
        {
            uchar ignoreProvid = 0;
            uchar crypted = 0;
            uchar cryptkey = 0;
            do
            {
                tempbuf[0] = '\0';
                if(usercmd != NULL) free(usercmd);

                if(fgets(tempbuf, 2048, pFile) == NULL) continue;

                if(strlen(tempbuf) < 10) continue;

                trim2(tempbuf);

                ignoreProvid = 0;
                crypted = 0;
                cryptkey = 0;

                if(tempbuf[0] == '8' && tempbuf[1] == '6' && csystem_data->provider == 0x11) ignoreProvid = 1;
                else if(strncmp(tempbuf ,"REG2" ,4) == 0)
                {
                    dre_read_ee(reader, &tempbuf[4] ,csystem_data->provider);
                    continue;
                }
                else if(strncmp(tempbuf ,"CR" ,2) == 0)
                {
                    crypted = 1;
                    cryptkey = ((tempbuf[2] - (tempbuf[2] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[3] - (tempbuf[3] > 0x39 ? 0x37:0x30)) & 0xF);
                }
                else if(tempbuf[0] != '5' && tempbuf[1] != '9') continue;

                strtoupper(tempbuf);

                cmd_len = strlen(tempbuf) / 2 - 3 + ignoreProvid - (crypted * 2);
                usercmd = malloc(cmd_len);

                for(i=0,n= 4+(crypted * 4);i<cmd_len;i++,n+=2)
                {
                    usercmd[i] = ((tempbuf[n] - (tempbuf[n] > 0x39 ? 0x37:0x30)) << 4) + ((tempbuf[n+1] - (tempbuf[n+1] > 0x39 ? 0x37:0x30)) & 0xF);
                }

                /*if(usercmd[cmd_len-1] != csystem_data->provider && !ignoreProvid)
                {
                    rdr_log(reader, "Skip script: current provid %02X , script provid %02X", csystem_data->provider, usercmd[cmd_len-1]);
                    continue;
                }
                */
                rdr_log(reader, "User script: %s", tempbuf);

                /*ret =*/ 

                rdr_log(reader, "Script %s", (dre_script(usercmd, cmd_len, ignoreProvid, crypted, cryptkey)) ? "done" : "error");
            }
            while(!feof(pFile));
        }
        else
        {
            rdr_log(reader, "Can't open script file (%s)", reader->userscript);
        }

        //if(usercmd != NULL) free(usercmd);
        if(tempbuf != NULL) free(tempbuf);
    }

    if(csystem_data->provider == 0x11)
    {
        memset(reader->prid[1], 0x00, 8);
        reader->prid[1][3] = 0xFE;
        reader->nprov = 2;
    }

	if(!dre_set_provider_info(reader))
		{ return ERROR; }           //fatal error

	rdr_log(reader, "ready for requests");
	return OK;
}
Esempio n. 28
0
static int32_t dre_set_provider_info(struct s_reader *reader)
{
	def_resp;
	int32_t i;
    int subscr_cmd_len = 4;
    uchar subscr[4];// = { 0x59, 0x14 };   // subscriptions
    uchar dates[] = { 0x5b, 0x00, 0x14 }; //validity dates
    uchar subscr_len = 0, n = 0;
	struct dre_data *csystem_data = reader->csystem_data;

	cs_clear_entitlement(reader);

    switch(csystem_data->provider)
    {
        case 0x02:
        case 0x03:
            subscr[0] = 0x84;
            subscr[1] = 0;
            subscr[2] = 0x5F;
            subscr[3] = csystem_data->provider;
            dates[0] = 0x85;
            subscr_len = 0x5F;
            break;
        case 0x18:
        case 0x19:
        case 0x1A:
            subscr[0] = 0x94;
            subscr[1] = 0;
            subscr[2] = 0x5F;
            subscr[3] = csystem_data->provider;
            dates[0] = 0x95;
            subscr_len = 0x5F;
            break;
        default:
            subscr[0] = 0x59;
            subscr[1] = csystem_data->provider;
            subscr_len = 0x20;
            subscr_cmd_len = 2;
    }

chk_subscr:
    
    if((dre_script(subscr, subscr_cmd_len, 0, 0, 0)))      //ask subscription packages, returns error on 0x11 card
    {
        uchar pbm[subscr_len];
        char tmp_dbg[subscr_len*2+1];
		memcpy(pbm, cta_res + 3, cta_lr - 6);
        rdr_log_dbg(reader, D_READER, "pbm: %s", cs_hexdump(0, pbm, subscr_len, tmp_dbg, sizeof(tmp_dbg)));

        for(i = 0; i < subscr_len; i++)
            if(pbm[i] != 0xff)
            {
                dates[1] = i;
                dates[2] = csystem_data->provider;
                dre_cmd(dates);   //ask for validity dates

                time_t start;
                time_t end;
                start = (cta_res[3] << 24) | (cta_res[4] << 16) | (cta_res[5] << 8) | cta_res[6];
                end = (cta_res[7] << 24) | (cta_res[8] << 16) | (cta_res[9] << 8) | cta_res[10];

                struct tm temp;

                localtime_r(&start, &temp);
                int32_t startyear = temp.tm_year + 1900;
                int32_t startmonth = temp.tm_mon + 1;
                int32_t startday = temp.tm_mday;
                localtime_r(&end, &temp);
                int32_t endyear = temp.tm_year + 1900;
                int32_t endmonth = temp.tm_mon + 1;
                int32_t endday = temp.tm_mday;
                rdr_log(reader, "active package %i valid from %04i/%02i/%02i to %04i/%02i/%02i", i+n, startyear, startmonth, startday,
                        endyear, endmonth, endday);
                cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), 0, i+n, start, end, 5, 1);
            }
    }
    
    if(subscr_len == 0x5F) // read second part subscription packages, for DRE3 and DRE4
    {
        subscr[1] = 0x5F;
        subscr[2] = 0x21;
        subscr_len = 0x21;
        n = 0x5F;
        goto chk_subscr;
    }

	return OK;
}
Esempio n. 29
0
int32_t constcw_analyse_file(uint16_t c_caid, uint32_t c_prid, uint16_t c_sid, uint16_t c_pmtpid, uint32_t c_vpid, uint16_t c_ecmpid, uchar *dcw)
{
	//CAID:PROVIDER:SID:PMTPID:ECMPID:VPID:XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
	FILE *fp;
	char token[512];
	uint32_t caid, provid, sid, vpid, pmtpid, ecmpid;
	int32_t cw[16];

	fp = fopen(cur_client()->reader->device, "r");
	if(!fp)
	{
		cs_log("ERROR: Can't open %s (errno=%d %s)", cur_client()->reader->device, errno, strerror(errno));
		return (0);
	}

	cs_log("Searching CW for CAID %04X PROVID %06X SRVID %04X ECMPID %04X PMTPID %04X VPID %04X", c_caid, c_prid, c_sid, c_ecmpid, c_pmtpid, c_vpid);

	while(fgets(token, sizeof(token), fp))
	{
		if(token[0] == '#') { continue; }
		vpid = 0;
		int ret = sscanf(token, "%4x:%6x:%4x:%4x:%4x::%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmtpid, &ecmpid,
			   &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7],
			   &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]);
		
		if(ret != 21){   
			ret = sscanf(token, "%4x:%6x:%4x:%4x:%4x:%4x:%2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x %2x", &caid, &provid, &sid, &pmtpid, &ecmpid, &vpid,
				   &cw[0], &cw[1], &cw[2], &cw[3], &cw[4], &cw[5], &cw[6], &cw[7],
				   &cw[8], &cw[9], &cw[10], &cw[11], &cw[12], &cw[13], &cw[14], &cw[15]);
			if(ret != 22) continue;
		}		

		//cs_log("Line found: %s", token);
		if(c_caid == caid && c_sid == sid && (!provid || provid == c_prid) && (!pmtpid || !c_pmtpid || pmtpid == c_pmtpid) && (!vpid || !c_vpid || vpid == c_vpid) 
				&& (!ecmpid || !c_ecmpid || ecmpid == c_ecmpid))
		{
			fclose(fp);
			int8_t i;
			for(i = 0; i < 16; ++i)
				{ dcw[i] = (uchar) cw[i]; }
			cs_log("Entry found: %04X@%06X:%04X:%04X:%04X:%04X:%s", caid, provid, sid, pmtpid, ecmpid, vpid, cs_hexdump(1, dcw, 16, token, sizeof(token)));
			return 1;
		}
	}

	fclose(fp);
	return 0;
}
Esempio n. 30
0
void cs_log_int(uint16_t mask, int8_t lock __attribute__((unused)), const uchar *buf, int32_t n, const char *fmt, ...)
{
	if((mask & cs_dblevel) || !mask)
	{
		va_list params;

		int32_t dupl_header_len, repeated_line, i, len = 0;
		pthread_mutex_lock(&log_mutex);
		if(fmt)
		{
			va_start(params, fmt);
			len = get_log_header(1, log_txt);
			vsnprintf(log_txt + len, sizeof(log_txt) - len, fmt, params);
			va_end(params);
			if(cfg.logduplicatelines)
			{
				memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE);
				write_to_log_int(log_txt, len);
			}
			else
			{
				repeated_line = strcmp(last_log_txt, log_txt + len) == 0;
				if(last_log_duplicates > 0)
				{
					if(!cs_valid_time(&last_log_ts))  // Must be initialized once
						{ last_log_ts = log_ts; }
					// Report duplicated lines when the new log line is different
					// than the old or 60 seconds have passed.
					int32_t gone = comp_timeb(&log_ts, &last_log_ts);
					if(!repeated_line || gone >= 60*1000)
					{
						dupl_header_len = get_log_header(2, dupl);
						snprintf(dupl + dupl_header_len - 1, sizeof(dupl) - dupl_header_len, "--- Skipped %u duplicated log lines ---", last_log_duplicates);
						write_to_log_int(dupl, 0);
						last_log_duplicates = 0;
						last_log_ts = log_ts;
					}
				}
				if(!repeated_line)
				{
					memcpy(last_log_txt, log_txt + len, LOG_BUF_SIZE);
					write_to_log_int(log_txt, len);
				}
				else
				{
					last_log_duplicates++;
				}
			}
		}
		if(buf)
		{
			for(i = 0; i < n; i += 16)
			{
				len = get_log_header(0, log_txt);
				cs_hexdump(1, buf + i, (n - i > 16) ? 16 : n - i, log_txt + len, sizeof(log_txt) - len);
				write_to_log_int(log_txt, len);
			}
		}
		pthread_mutex_unlock(&log_mutex);
	}
}