1 | #include "globals.h"
|
---|
2 | #ifdef READER_TONGFANG
|
---|
3 | #include "reader-common.h"
|
---|
4 |
|
---|
5 | // returns 1 if cw_is_valid, returns 0 if cw is all zeros
|
---|
6 | static int32_t cw_is_valid(uint8_t *cw)
|
---|
7 | {
|
---|
8 | int32_t i;
|
---|
9 |
|
---|
10 | for(i = 0; i < 8; i++)
|
---|
11 | {
|
---|
12 | if(cw[i] != 0) // test if cw = 00
|
---|
13 | {
|
---|
14 | return OK;
|
---|
15 | }
|
---|
16 | }
|
---|
17 | return ERROR;
|
---|
18 | }
|
---|
19 |
|
---|
20 | static int32_t tongfang_read_data(struct s_reader *reader, uint8_t size, uint8_t *cta_res, uint16_t *status)
|
---|
21 | {
|
---|
22 | uint8_t read_data_cmd[] = { 0x00, 0xc0, 0x00, 0x00, 0xff };
|
---|
23 | uint16_t cta_lr;
|
---|
24 |
|
---|
25 | read_data_cmd[4] = size;
|
---|
26 | write_cmd(read_data_cmd, NULL);
|
---|
27 |
|
---|
28 | *status = (cta_res[cta_lr - 2] << 8) | cta_res[cta_lr - 1];
|
---|
29 |
|
---|
30 | return (cta_lr - 2);
|
---|
31 | }
|
---|
32 |
|
---|
33 | static int32_t tongfang_card_init(struct s_reader *reader, ATR *newatr)
|
---|
34 | {
|
---|
35 | static const uint8_t begin_cmd[] = { 0x00, 0xa4, 0x04, 0x00, 0x05, 0xf9, 0x5a, 0x54, 0x00, 0x06 };
|
---|
36 | static const uint8_t get_serial_cmd[] = { 0x80, 0x46, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x04 };
|
---|
37 | uint8_t pairing_cmd[] = { 0x80, 0x4c, 0x00, 0x00, 0x04, 0xFF, 0xFF, 0xFF, 0xFF };
|
---|
38 |
|
---|
39 | uint8_t data[257];
|
---|
40 | int32_t data_len = 0;
|
---|
41 | uint16_t status = 0;
|
---|
42 | uint8_t boxID[] = { 0xFF, 0xFF, 0xFF, 0xFF };
|
---|
43 | int32_t i;
|
---|
44 |
|
---|
45 | def_resp;
|
---|
46 | get_hist;
|
---|
47 |
|
---|
48 | if((hist_size < 4) || (memcmp(hist, "NTIC", 4)))
|
---|
49 | {
|
---|
50 | return ERROR;
|
---|
51 | }
|
---|
52 |
|
---|
53 | reader->caid = 0x4A02;
|
---|
54 | // For now, only one provider, 0000
|
---|
55 | reader->nprov = 1;
|
---|
56 | memset(reader->prid, 0x00, sizeof(reader->prid));
|
---|
57 |
|
---|
58 | rdr_log(reader, "Tongfang card detected");
|
---|
59 |
|
---|
60 | write_cmd(begin_cmd, begin_cmd + 5);
|
---|
61 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
62 | {
|
---|
63 | return ERROR;
|
---|
64 | }
|
---|
65 |
|
---|
66 | write_cmd(get_serial_cmd, get_serial_cmd + 5);
|
---|
67 | if((cta_res[cta_lr - 2] & 0xf0) != 0x60)
|
---|
68 | {
|
---|
69 | return ERROR;
|
---|
70 | }
|
---|
71 |
|
---|
72 | data_len = tongfang_read_data(reader, cta_res[cta_lr - 1], data, &status);
|
---|
73 | if(data_len < 0)
|
---|
74 | {
|
---|
75 | return ERROR;
|
---|
76 | }
|
---|
77 |
|
---|
78 | if(status != 0x9000)
|
---|
79 | {
|
---|
80 | return ERROR;
|
---|
81 | }
|
---|
82 |
|
---|
83 | memset(reader->hexserial, 0, 8);
|
---|
84 | memcpy(reader->hexserial + 2, data, 4); // might be incorrect offset
|
---|
85 |
|
---|
86 | if(reader->boxid > 0)
|
---|
87 | {
|
---|
88 | /* the boxid is specified in the config */
|
---|
89 | for(i = 0; i < 4; i++)
|
---|
90 | {
|
---|
91 | boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
|
---|
92 | }
|
---|
93 | }
|
---|
94 | memcpy(pairing_cmd + 5, boxID, sizeof(boxID));
|
---|
95 | write_cmd(pairing_cmd, pairing_cmd + 5);
|
---|
96 |
|
---|
97 | rdr_log_sensitive(reader, "type: Tongfang, caid: %04X, serial: {%llu}, hex serial: {%02x%02x%02x%02x}, BoxID: {%02X%02X%02X%02X}",
|
---|
98 | reader->caid, (unsigned long long) b2ll(6, reader->hexserial), reader->hexserial[2],
|
---|
99 | reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
|
---|
100 | boxID[0], boxID[1], boxID[2], boxID[3]);
|
---|
101 |
|
---|
102 | return OK;
|
---|
103 | }
|
---|
104 |
|
---|
105 | /*
|
---|
106 | Example ecm:
|
---|
107 | 03 85 80 70 61 8E 2A 16 4F 00 12 0F 21 5A E5 6A
|
---|
108 | 8F 4D C1 57 4E 24 2A 38 3C 26 8A 4C C2 74 A1 23
|
---|
109 | 9F 12 43 80 3A 16 4F 3E 8E 2A C0 40 0F 22 94 E4
|
---|
110 | 6A 89 F1 09 38 8F DF 3D 08 A6 29 1A 61 98 31 82
|
---|
111 | 7F 34 55 74 0E A3 54 38 01 09 00 01 00 01 D9 31
|
---|
112 | A5 1B 8B CA A8 95 E0 D1 24 7D 36 8C F6 89 4A F7
|
---|
113 | B2 3A 74 3D D1 D4
|
---|
114 | */
|
---|
115 | static int32_t tongfang_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
116 | {
|
---|
117 | uint8_t ecm_cmd[200];
|
---|
118 | int32_t ecm_len;
|
---|
119 | const uint8_t *pbuf = er->ecm;
|
---|
120 | char *tmp;
|
---|
121 | int32_t i = 0;
|
---|
122 | int32_t write_len = 0;
|
---|
123 | def_resp;
|
---|
124 | int32_t read_size = 0;
|
---|
125 | uint8_t data[100];
|
---|
126 | int32_t data_len = 0;
|
---|
127 | uint16_t status = 0;
|
---|
128 |
|
---|
129 | if((ecm_len = check_sct_len(er->ecm, 3)) < 0)
|
---|
130 | {
|
---|
131 | return ERROR;
|
---|
132 | }
|
---|
133 |
|
---|
134 | if(cs_malloc(&tmp, ecm_len * 3 + 1))
|
---|
135 | {
|
---|
136 | rdr_log_dbg(reader, D_IFD, "ECM: %s", cs_hexdump(1, er->ecm, ecm_len, tmp, ecm_len * 3 + 1));
|
---|
137 | NULLFREE(tmp);
|
---|
138 | }
|
---|
139 |
|
---|
140 | for(i = 0; i < (ecm_len - 1); i++)
|
---|
141 | {
|
---|
142 | if((pbuf[0] == 0x80) && (pbuf[1] == 0x3a))
|
---|
143 | {
|
---|
144 | break;
|
---|
145 | }
|
---|
146 | pbuf++;
|
---|
147 | }
|
---|
148 | write_len = pbuf[4] + 5;
|
---|
149 |
|
---|
150 | memcpy(ecm_cmd, pbuf, write_len);
|
---|
151 | write_cmd(ecm_cmd, ecm_cmd + 5);
|
---|
152 |
|
---|
153 | if((cta_lr - 2) >= 2)
|
---|
154 | {
|
---|
155 | read_size = cta_res[1];
|
---|
156 | }
|
---|
157 | else
|
---|
158 | {
|
---|
159 | if((cta_res[cta_lr - 2] & 0xf0) == 0x60)
|
---|
160 | {
|
---|
161 | read_size = cta_res[cta_lr - 1];
|
---|
162 | }
|
---|
163 | else
|
---|
164 | {
|
---|
165 | return ERROR;
|
---|
166 | }
|
---|
167 | }
|
---|
168 |
|
---|
169 | data_len = tongfang_read_data(reader, read_size, data, &status);
|
---|
170 |
|
---|
171 | if(data_len < 23)
|
---|
172 | {
|
---|
173 | return ERROR;
|
---|
174 | }
|
---|
175 |
|
---|
176 | if(!(er->ecm[0] & 0x01))
|
---|
177 | {
|
---|
178 | memcpy(ea->cw, data + 8, 16);
|
---|
179 | }
|
---|
180 | else
|
---|
181 | {
|
---|
182 | memcpy(ea->cw, data + 16, 8);
|
---|
183 | memcpy(ea->cw + 8, data + 8, 8);
|
---|
184 | }
|
---|
185 |
|
---|
186 | // All zeroes is no valid CW, can be a result of wrong boxid
|
---|
187 | if(!cw_is_valid(ea->cw) || !cw_is_valid(ea->cw + 8))
|
---|
188 | {
|
---|
189 | return ERROR;
|
---|
190 | }
|
---|
191 |
|
---|
192 | return OK;
|
---|
193 | }
|
---|
194 |
|
---|
195 | static int32_t tongfang_get_emm_type(EMM_PACKET *ep, struct s_reader *UNUSED(reader))
|
---|
196 | {
|
---|
197 | ep->type = UNKNOWN;
|
---|
198 | return 1;
|
---|
199 | }
|
---|
200 |
|
---|
201 | static int32_t tongfang_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
202 | {
|
---|
203 | uint8_t emm_cmd[200];
|
---|
204 | def_resp;
|
---|
205 | int32_t write_len;
|
---|
206 |
|
---|
207 | if(SCT_LEN(ep->emm) < 8)
|
---|
208 | {
|
---|
209 | return ERROR;
|
---|
210 | }
|
---|
211 |
|
---|
212 | write_len = ep->emm[15] + 5;
|
---|
213 | memcpy(emm_cmd, ep->emm + 11, write_len);
|
---|
214 |
|
---|
215 | write_cmd(emm_cmd, emm_cmd + 5);
|
---|
216 |
|
---|
217 | return OK;
|
---|
218 | }
|
---|
219 |
|
---|
220 | static int32_t tongfang_card_info(struct s_reader *reader)
|
---|
221 | {
|
---|
222 | static const uint8_t get_provider_cmd[] = {0x80, 0x44, 0x00, 0x00, 0x08};
|
---|
223 | def_resp;
|
---|
224 | int32_t i;
|
---|
225 |
|
---|
226 | write_cmd(get_provider_cmd, NULL);
|
---|
227 | if((cta_res[cta_lr - 2] != 0x90) || (cta_res[cta_lr - 1] != 0x00))
|
---|
228 | {
|
---|
229 | return ERROR;
|
---|
230 | }
|
---|
231 |
|
---|
232 | for(i = 0; i < 4; i++)
|
---|
233 | {
|
---|
234 | rdr_log(reader, "Provider:%02x%02x", cta_res[i * 2], cta_res[i * 2 + 1]);
|
---|
235 | }
|
---|
236 | return OK;
|
---|
237 | }
|
---|
238 |
|
---|
239 | const struct s_cardsystem reader_tongfang =
|
---|
240 | {
|
---|
241 | .desc = "tongfang",
|
---|
242 | .caids = (uint16_t[]){ 0x4B, 0 },
|
---|
243 | .do_emm = tongfang_do_emm,
|
---|
244 | .do_ecm = tongfang_do_ecm,
|
---|
245 | .card_info = tongfang_card_info,
|
---|
246 | .card_init = tongfang_card_init,
|
---|
247 | .get_emm_type = tongfang_get_emm_type,
|
---|
248 | };
|
---|
249 |
|
---|
250 | #endif
|
---|