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; }
int32_t card_write(struct s_reader * reader, const uchar *cmd, const uchar *data, uchar *response, uint16_t * response_length) { uchar buf[260]; // always copy to be able to be able to use const buffer without changing all code memcpy(buf, cmd, CMD_LEN); if (data) { if (cmd[4]) memcpy(buf+CMD_LEN, data, cmd[4]); return(reader_cmd2icc(reader, buf, CMD_LEN+cmd[4], response, response_length)); } else return(reader_cmd2icc(reader, buf, CMD_LEN, response, response_length)); }
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; }
int32_t card_write(struct s_reader *reader, const uchar *cmd, const uchar *data, uchar *response, uint16_t *response_length) { int32_t datalen = MAX_ECM_SIZE; // default datalen is max ecm size defined uchar buf[MAX_ECM_SIZE + CMD_LEN]; // always copy to be able to be able to use const buffer without changing all code memcpy(buf, cmd, CMD_LEN); // copy command if(data) { if(cmd[4]) { datalen = cmd[4]; } memcpy(buf + CMD_LEN, data, datalen); return (reader_cmd2icc(reader, buf, CMD_LEN + datalen, response, response_length)); } else { return (reader_cmd2icc(reader, buf, CMD_LEN, response, response_length)); } }
static void dre_read_ee(struct s_reader *reader, const char *path, uchar provid) { def_resp; int i, n; uchar *ee = malloc(2048); if(ee == NULL) return; uchar drecmd43[] = { 0x80, 0x00, 0x00, 0x00, 0x05, 0x59, 0x03, 0x43, 0x11, 0xAD }; uchar drecmd45[] = { 0x45, 0x11 }; drecmd43[8] = drecmd45[1] = provid; drecmd43[9] = ~xor(&drecmd43[7], 2); for(i = 0; i < 8; i++) { for(n = 0; n < 8; n++) { reader_cmd2icc(reader, drecmd43, 10, cta_res, &cta_lr); dre_cmd_c(drecmd45, n, i*32); if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00)) { free(ee); rdr_log(reader, "ERROR read ee.bin from card"); return; } memcpy(&ee[((n*8)+i)*32] ,&cta_res[2] ,32); } } FILE *pFile = fopen(path, "wb"); if(pFile == NULL) { free(ee); return ; } fwrite(ee, 2048, 1, pFile); fclose(pFile); free(ee); rdr_log(reader, "ee.bin saved to %s", path); }
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; }
static int32_t dre_command (struct s_reader * reader, const uchar * cmd, int32_t cmdlen, unsigned char * cta_res, uint16_t * p_cta_lr) //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]; char tmp[256]; int32_t headerlen = sizeof (startcmd); startcmd[4] = cmdlen + 3; //commandlength + type + len + checksum bytes memcpy (command, startcmd, headerlen); command[headerlen++] = CMD_BYTE; //type command[headerlen++] = cmdlen + 1; //len = command + 1 checksum byte memcpy (command + headerlen, cmd, cmdlen); uchar checksum = ~xor (cmd, cmdlen); //cs_debug_mask(D_READER, "[dre-reader] Checksum: %02x", checksum); cmdlen += headerlen; command[cmdlen++] = checksum; reader_cmd2icc (reader, command, cmdlen, cta_res, p_cta_lr); if ((*p_cta_lr != 2) || (cta_res[0] != OK_RESPONSE)) { cs_log ("[dre-reader] command sent to card: %s", cs_hexdump(0, command, cmdlen, tmp, sizeof(tmp))); cs_log ("[dre-reader] unexpected answer from card: %s", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); return ERROR; //error } reqans[4] = cta_res[1]; //adapt length byte reader_cmd2icc (reader, reqans, 5, cta_res, p_cta_lr); if (cta_res[0] != CMD_BYTE) { cs_log ("[dre-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]) { case 0xe1: cs_log ("[dre-reader] checksum error: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe2: cs_log ("[dre-reader] wrong provider: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xe3: cs_log ("[dre-reader] illegal command: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; case 0xec: cs_log ("[dre-reader] wrong signature: %s.", cs_hexdump(0, cta_res, *p_cta_lr, tmp, sizeof(tmp))); break; default: cs_debug_mask(D_READER, "[dre-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) { cs_log ("[dre-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; }