revert breaks some stupid old compilers
[oscam.git] / reader-dgcrypt.c
blobe46163ab8e69e163e6de2bfb4aae9dcf79eaa6ac
1 #include "globals.h"
2 #ifdef READER_DGCRYPT
3 #include "reader-common.h"
5 #define DEBUG 0
7 static const uint8_t dgcrypt_atr[8] = { 0x3B, 0xE9, 0x00, 0x00, 0x81, 0x31, 0xC3, 0x45 };
8 static const uint8_t cmd_CWKEY[5] = { 0x81, 0xD0, 0x00, 0x01, 0x08 };
9 //static const uint8_t cmd_CAID[5] = { 0x81, 0xC0, 0x00, 0x01, 0x0A };
10 static const uint8_t cmd_SERIAL[5] = { 0x81, 0xD1, 0x00, 0x01, 0x10 };
11 static const uint8_t cmd_LABEL[5] = { 0x81, 0xD2, 0x00, 0x01, 0x10 };
12 //static const uint8_t cmd_SUBSYS[5] = { 0x81, 0xDD, 0x00, 0x10, 0x04 };
13 static const uint8_t cmd_ECM[3] = { 0x80, 0xEA, 0x80 };
15 struct dgcrypt_data
17 uint8_t session_key[16];
20 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)
22 rdr->ifsc = 195;
23 rdr->ns = 1;
24 if(DEBUG)
26 char tmp[512];
27 rdr_log(rdr, "SEND -> %s(%d)", cs_hexdump(1, buf, buflen, tmp, sizeof(tmp)), buflen);
29 int32_t ret = reader_cmd2icc(rdr, buf, buflen, response, response_length);
30 if(DEBUG)
32 char tmp[512];
33 rdr_log(rdr, "RECV <- %s(%d) ret=%d", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), *response_length, ret);
35 // reader_cmd2icc retuns ERROR=1, OK=0 - the opposite of OK and ERROR defines in reader-common.h
36 if(ret)
38 rdr_log(rdr, "ERROR: reader_cmd2icc() ret=%d", ret);
39 return ERROR;
41 if(*response_length < 2 || *response_length < min_response_len)
43 rdr_log(rdr, "ERROR: response_length=%d < min_response_length=%d", *response_length, min_response_len);
44 return ERROR; // Response is two short
46 if(response[*response_length - 2] != 0x90 || response[*response_length - 1] != 0x00)
48 rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]);
49 rdr_log(rdr, "ERROR: response[-1] != 0x00 its 0x%02X", response[*response_length - 1]);
50 return ERROR; // The reader responded with "command not OK"
52 return OK;
55 static int32_t dgcrypt_card_init(struct s_reader *rdr, ATR *newatr)
57 def_resp
59 get_atr
60 if(atr_size < sizeof(dgcrypt_atr))
61 { return ERROR; }
63 // Full ATR: 3B E9 00 00 81 31 C3 45 99 63 74 69 19 99 12 56 10 EC
64 if(memcmp(atr, dgcrypt_atr, sizeof(dgcrypt_atr)) != 0)
65 { return ERROR; }
67 if(!cs_malloc(&rdr->csystem_data, sizeof(struct dgcrypt_data)))
68 { return ERROR; }
69 struct dgcrypt_data *csystem_data = rdr->csystem_data;
71 rdr_log(rdr, "[dgcrypt-reader] card detected.");
73 memset(rdr->sa, 0, sizeof(rdr->sa));
74 memset(rdr->prid, 0, sizeof(rdr->prid));
75 memset(rdr->hexserial, 0, sizeof(rdr->hexserial));
77 rdr->nprov = 1;
78 rdr->caid = 0x4ABF;
80 // Get session key
81 // Send: 81 D0 00 01 08
82 // Recv: 32 86 17 D5 2C 66 61 14 90 00
83 if(!dgcrypt_cmd(rdr, cmd_CWKEY, sizeof(cmd_CWKEY), cta_res, &cta_lr, 8))
84 { return ERROR; }
85 memcpy(csystem_data->session_key + 0, cta_res, 8);
86 memcpy(csystem_data->session_key + 8, cta_res, 8);
88 // Get CAID
89 // Send: 81 C0 00 01 0A
90 // Recv: 4A BF 90 00
91 // if (!dgcrypt_cmd(rdr, cmd_CAID, sizeof(cmd_CAID), cta_res, &cta_lr, 2))
92 // return ERROR;
93 // rdr->caid = (cta_res[0] << 8) | cta_res[1];
95 // Get serial number
96 // Send: 81 D1 00 01 10
97 // Recv: 00 0D DB 08 71 0D D5 0C 30 30 30 30 30 30 30 30 90 00
98 if(!dgcrypt_cmd(rdr, cmd_SERIAL, sizeof(cmd_SERIAL), cta_res, &cta_lr, 8))
99 { return ERROR; }
100 memcpy(rdr->hexserial, cta_res + 1, 7);
102 // Get LABEL
103 // Send: 81 D2 00 01 10
104 // Recv: 50 61 79 5F 54 56 5F 43 61 72 64 00 00 00 00 00 90 00
105 // Txt: P a y _ T V _ C a r d
106 if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 16))
107 { return ERROR; }
108 char label[17];
109 memset(label, 0, sizeof(label));
110 memcpy(label, cta_res, 16);
112 // Get subsystem - !FIXME! We are not using the answer of this command!
113 // Send: 81 DD 00 10 04
114 // Recv: 00 55 00 55 90 00
115 if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 4))
116 { return ERROR; }
118 rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%"PRIu64"} HexSerial: {%02X %02X %02X %02X %02X %02X %02X} Label: {%s}",
119 rdr->caid,
120 b2ll(7, rdr->hexserial),
121 rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2],
122 rdr->hexserial[3], rdr->hexserial[4], rdr->hexserial[5], rdr->hexserial[6],
123 label);
125 return OK;
128 static int32_t dgcrypt_do_ecm(struct s_reader *rdr, const ECM_REQUEST *er, struct s_ecm_answer *ea)
130 def_resp
131 uint8_t cmd_buffer[256];
132 struct dgcrypt_data *csystem_data = rdr->csystem_data;
134 memcpy(cmd_buffer, er->ecm, er->ecm[2] + 3);
135 // Replace The first 3 bytes of the ECM with the command
136 memcpy(cmd_buffer, cmd_ECM, sizeof(cmd_ECM));
138 // Write ECM
139 // Send: 80 EA 80 00 55 00 00 3F 90 03 00 00 18 5D 82 4E 01 C4 2D 60 12 ED 34 37 ED 72 .. .. ..
140 // Recv: 72 25 8D A1 0D 0D D2 44 EE ED 51 2F 3B 5D 19 63 E6 90 00
141 if(!dgcrypt_cmd(rdr, cmd_buffer, er->ecm[2] + 3, cta_res, &cta_lr, 17))
142 { return ERROR; }
143 if(cta_res[0] != 0x72) // CW response MUST start with 0x72
144 { return ERROR; }
146 int i;
147 for(i = 0; i < 16; i++)
149 ea->cw[i] = cta_res[1 + i] ^ csystem_data->session_key[i];
151 return OK;
154 static int32_t dgcrypt_get_emm_filter(struct s_reader *rdr __attribute__((unused)), struct s_csystem_emm_filter **emm_filters __attribute__((unused)), unsigned int *filter_count)
156 *filter_count = 0;
157 return OK;
160 const struct s_cardsystem reader_dgcrypt =
162 .desc = "dgcrypt",
163 .caids = (uint16_t[]){ 0x4ABF, 0 },
164 // DGCrypt system does not send EMMs
165 .card_init = dgcrypt_card_init,
166 .do_ecm = dgcrypt_do_ecm,
167 .get_emm_filter = dgcrypt_get_emm_filter,
170 #endif