revert breaks some stupid old compilers
[oscam.git] / reader-videoguard2.c
blob28f4a3ffcba5e4ff57202f89fca8b1f8b7657bb5
1 #include "globals.h"
2 #ifdef READER_VIDEOGUARD
3 #include "cscrypt/md5.h"
4 #include "oscam-work.h"
5 #include "reader-common.h"
6 #include "reader-videoguard-common.h"
9 static void do_post_dw_hash(struct s_reader *reader, unsigned char *cw, const unsigned char *ecm_header_data)
11 int32_t i, ecmi, ecm_header_count;
12 unsigned char buffer[0x85]; //original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
13 unsigned char md5tmp[MD5_DIGEST_LENGTH];
14 static const uint16_t Hash3[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52};
15 static const unsigned char Hash4[] = {0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A, 0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F};
16 static const uint16_t NdTabB001[0x15][0x20] =
19 0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
20 0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
21 0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
22 0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
25 0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
26 0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
27 0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
28 0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
31 0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
32 0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
33 0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
34 0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
37 0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
38 0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
39 0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
40 0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
43 0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
44 0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
45 0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
46 0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
49 0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
50 0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
51 0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
52 0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
55 0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
56 0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
57 0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
58 0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
61 0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
62 0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
63 0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
64 0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
67 0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
68 0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
69 0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
70 0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
73 0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
74 0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
75 0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
76 0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
79 0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
80 0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
81 0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
82 0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
85 0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
86 0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
87 0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
88 0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
91 0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
92 0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
93 0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
94 0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
97 0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
98 0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
99 0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
100 0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
103 0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
104 0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
105 0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
106 0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
109 0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
110 0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
111 0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
112 0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
115 0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
116 0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
117 0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
118 0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
121 0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
122 0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
123 0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
124 0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
127 0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
128 0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
129 0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
130 0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
133 0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
134 0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
135 0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
136 0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
139 0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
140 0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
141 0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
142 0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
147 //ecm_header_data = 01 03 b0 01 01
148 if(!cw_is_valid(cw)) //if cw is all zero, keep it that way
150 return;
152 ecm_header_count = ecm_header_data[0];
153 for(i = 0, ecmi = 1; i < ecm_header_count; i++)
155 if(ecm_header_data[ecmi + 1] != 0xb0)
157 ecmi += ecm_header_data[ecmi] + 1;
159 else
161 switch(ecm_header_data[ecmi + 2])
163 //b0 01
164 case 1:
166 uint16_t hk[8], r, j, m = 0;
167 for(r = 0; r < 6; r++)
168 { hk[2 + r] = Hash3[r]; }
169 for(r = 0; r < 2; r++)
171 for(j = 0; j < 0x48; j += 2)
173 if(r)
175 hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
177 else
179 hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
181 if(j < 8)
183 hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
185 if(j == 8)
187 hk[0] = (hk[0] + 0x80);
189 hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
190 hk[1] = hk[2];
191 hk[2] = hk[3];
192 hk[3] = hk[4];
193 hk[4] = hk[5];
194 hk[5] = hk[6];
195 hk[6] = hk[7];
196 hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
197 m = (m + 1) & 0x3F;
200 for(r = 0; r < 6; r++)
202 hk[2 + r] += Hash3[r];
204 for(r = 0; r < 7; r++)
206 cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
208 cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
209 cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
210 rdr_log_dump_dbg(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
211 break;
213 case 3:
215 memset(buffer, 0, sizeof(buffer));
216 memcpy(buffer, cw, 8);
217 memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
218 MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
219 memcpy(cw, md5tmp, 8);
220 rdr_log_dump_dbg(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
221 break;
223 case 2:
225 /* Method 2 left out */
226 //memcpy(DW_OUTPUT, DW_INPUT, 8);
227 break;
235 static void vg2_read_tiers(struct s_reader *reader)
237 def_resp;
238 struct videoguard_data *csystem_data = reader->csystem_data;
239 if (reader->readtiers == 1)
241 uint8_t ins707f[5] = { 0xD1, 0x70, 0x00, 0x7f, 0x02 };
242 if(do_cmd(reader, ins707f, NULL, NULL, cta_res) < 0)
244 rdr_log(reader, "classD1 ins707f: failed to get number of classes supported");
246 else
248 cs_clear_entitlement(reader);
249 rdr_log(reader, "------------------------------------------------------------------");
250 rdr_log(reader, "|- class -|-- tier --|----- valid to ------|--- package name ----|");
251 rdr_log(reader, "+---------+----------+---------------------+---------------------+");
252 if ((reader->VgFuse&5) == 0)
254 rdr_log(reader, "|------- This card is not active, so no package available! ------|");
256 uint32_t TierClass, ClassSupported;
257 ClassSupported = cta_res[1];
258 uint8_t ins70[5] = { 0xD1, 0x70, 0x00, 0x00, 0x00 };
259 for( TierClass=0; TierClass<ClassSupported; TierClass++)
261 ins70[2] = TierClass;
262 if(do_cmd(reader, ins70, NULL, NULL, cta_res) < 0)
264 rdr_log(reader, "classD1 ins70: failed to get tiers for class %02X",TierClass);
266 else
268 char tiername[83];
269 uint32_t word;
270 uint32_t bitnum;
271 uint32_t tier_id;
272 struct tm timeinfo;
273 memset(&timeinfo, 0, sizeof(struct tm));
274 time_t start_t = 0, end_t;
275 if (cta_res[1] > 0x23)
277 rev_date_calc_tm(&cta_res[38], &timeinfo, csystem_data->card_baseyear);
278 start_t = mktime(&timeinfo);
280 rev_date_calc_tm(&cta_res[34], &timeinfo, csystem_data->card_baseyear);
281 end_t = mktime(&timeinfo);
282 for( word=0; word<32; word+=2)
284 for (bitnum=0; bitnum<8; bitnum++)
286 if((cta_res[word+2] >> bitnum) & 1)
288 tier_id = 0;
289 tier_id = ((TierClass<<8) + (word<<3) + bitnum);
290 cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, TierClass, start_t, end_t, 4, 1);
291 rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s", TierClass, tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
293 if((cta_res[word+1+2] >> bitnum) & 1)
295 tier_id = 0;
296 tier_id = ((TierClass<<8) + (word<<3) + bitnum + 8);
297 cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, TierClass, start_t, end_t, 4, 1);
298 rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s", TierClass, tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
305 rdr_log(reader, "------------------------------------------------------from-ins70--");
307 else if (reader->readtiers == 2)
309 int32_t l;
310 //ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
311 //check if ins2a is in command table before running it
313 static const unsigned char ins2a[5] = { 0xD0, 0x2a, 0x00, 0x00, 0x00 };
314 if(cmd_exists(reader, ins2a))
316 l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
317 if(l < 0 || !status_ok(cta_res + l))
319 rdr_log(reader, "classD0 ins2a: failed");
320 return;
324 static const unsigned char ins76007f[5] = { 0xD0, 0x76, 0x00, 0x7f, 0x02 };
325 if(!write_cmd_vg(ins76007f, NULL) || !status_ok(cta_res + 2))
327 rdr_log(reader, "classD0 ins76007f: failed");
328 return;
330 int32_t num = cta_res[1];
332 int32_t i;
333 unsigned char ins76[5] = { 0xD0, 0x76, 0x00, 0x00, 0x00 };
335 // some cards start real tiers info in middle of tier info
336 // and have blank tiers between old tiers and real tiers eg 09AC
337 int32_t starttier = csystem_data->card_tierstart;
338 bool stopemptytier = 1;
339 if(!starttier)
340 { stopemptytier = 0; }
342 // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
343 ins76[2] = starttier;
344 l = do_cmd(reader, ins76, NULL, NULL, cta_res);
345 if(l < 0 || !status_ok(cta_res + l)) { return; }
346 if(cta_res[2] == 0 && cta_res[3] == 0)
348 stopemptytier = 0;
349 starttier = 0;
352 cs_clear_entitlement(reader); // reset the entitlements
353 rdr_log(reader, "------------------------------------------------------------------");
354 rdr_log(reader, "|- class -|-- tier --|----- valid to ------|--- package name ----|");
355 rdr_log(reader, "+---------+----------+---------------------+---------------------+");
356 if ((reader->VgFuse&5) == 0)
358 rdr_log(reader, "|------- This card is not active, so no package available! ------|");
360 for(i = starttier; i < num; i++)
362 ins76[2] = i;
363 l = do_cmd(reader, ins76, NULL, NULL, cta_res);
364 if(l < 0 || !status_ok(cta_res + l)) { return; }
365 if(cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier) { return; }
366 if(cta_res[2] != 0 || cta_res[3] != 0)
368 char tiername[83];
369 uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
370 // add entitlements to list
371 struct tm timeinfo;
372 memset(&timeinfo, 0, sizeof(struct tm));
373 rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
374 cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4, 1);
376 if(!stopemptytier)
378 rdr_log_dbg(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
380 rdr_log(reader, "|-- %02x ---|-- %04x --| %04d/%02d/%02d-%02d:%02d:%02d | %s", cta_res[2], tier_id, timeinfo.tm_year + 1900, timeinfo.tm_mon + 1, timeinfo.tm_mday, timeinfo.tm_hour, timeinfo.tm_min, timeinfo.tm_sec, get_tiername(tier_id, reader->caid, tiername));
383 rdr_log(reader, "------------------------------------------------------from-ins76--");
385 else if (reader->readtiers == 0)
387 rdr_log(reader, "------------------------------------------------------------------");
388 rdr_log(reader, "|--- The reading of the tiers is disabled by the configuration --|");
389 rdr_log(reader, "------------------------------------------------------------------");
393 void videoguard2_poll_status(struct s_reader *reader)
395 const time_t poll_interval = 12; // less is better
396 time_t now = time(0);
397 int32_t i;
398 if (now >= reader->last_poll + poll_interval)
400 static const unsigned char ins5C[5] = { 0xD1, 0x5C, 0x00, 0x00, 0x04 };
401 unsigned char cta_res[CTA_RES_LEN];
402 int32_t l;
403 l = do_cmd(reader, ins5C, NULL, NULL, cta_res);
404 if (l < 0 || !status_ok(cta_res + l))
406 rdr_log(reader, "classD1 ins5C: failed");
407 } else switch (cta_res[1]) {
408 case 0x14: //loc_43C250
410 static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
411 l = do_cmd(reader, ins4Ca, reader->payload4C, NULL, cta_res);
412 if (l < 0 || !status_ok(cta_res))
414 rdr_log(reader, "classD1 ins4Ca: failed");
416 if (reader->ins7E[0x1A])
418 static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
419 l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
420 if (l < 0 || !status_ok(cta_res))
422 rdr_log(reader, "classD1 ins7E: failed");
425 if (reader->ins2e06[4])
427 static const unsigned char ins2e06[5] = { 0xD1, 0x2E, 0x06, 0x00, 0x04 };
428 l = do_cmd(reader, ins2e06, reader->ins2e06, NULL, cta_res);
429 if(l < 0 || !status_ok(cta_res))
431 rdr_log(reader, "classD1 ins2E: failed");
434 static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
435 if ((do_cmd(reader, ins58a, NULL, NULL, cta_res) < 0))
437 rdr_log(reader, "classD1 ins58: failed");
439 reader->VgFuse = cta_res[2];
440 static const unsigned char ins7403[5] = { 0xD0, 0x74, 0x03, 0x00, 0x00 };
441 if ((do_cmd(reader, ins7403, NULL, NULL, cta_res) < 0))
443 rdr_log(reader, "classD0 ins7403: failed");
445 else
447 if (((cta_res[2]>>5) & 1))
449 static const unsigned char ins7423[5] = { 0xD3, 0x74, 0x23, 0x00, 0x00 };
450 if (do_cmd(reader, ins7423, NULL, NULL, cta_res) < 0)
452 rdr_log(reader, "classD1 ins7423: failed");
456 break;
458 case 0xB: //.text:000000000043C050
460 unsigned char ins5E[5] = { 0xD1,0x5E,0x00,0x00,0x00 };
461 ins5E[2] = cta_res[2];
462 ins5E[3] = cta_res[1];
463 ins5E[4] = cta_res[3];
464 l = do_cmd(reader, ins5E, NULL, NULL, cta_res);
465 if (l < 0 || !status_ok(cta_res + l))
467 rdr_log(reader, "Ins5E: failed");
469 unsigned char ins78[5] = { 0xD1, 0x78, 0x00, 0x00, 0x18 };
470 ins78[2] = cta_res[0];
471 l = do_cmd(reader, ins78, NULL, NULL, cta_res);
472 if (l < 0 || !status_ok(cta_res + l))
474 rdr_log(reader, "classD1 ins78: failed");
476 unsigned char ins32[5] = { 0xD1, 0x32, 0x00, 0x00, 0x01 };
477 const unsigned char payload32[1] = { 0x25 };
478 l = do_cmd(reader, ins32, payload32, NULL, cta_res);
479 if (l < 0 || !status_ok(cta_res + l))
481 rdr_log(reader, "classD1 ins32: failed");
483 break;
485 case 0x0C: //loc_43C13F
487 unsigned char ins5E[5] = { 0xD1,0x5E,0x00,0x00,0x00 };
488 ins5E[2] = cta_res[2];
489 ins5E[3] = cta_res[1];
490 ins5E[4] = cta_res[3];
491 l = do_cmd(reader, ins5E, NULL, NULL, cta_res);
492 if (l < 0 || !status_ok(cta_res + l))
494 rdr_log(reader, "Ins5E: failed");
495 } else {
496 unsigned char ins36[5] = { 0xD1, 0x36, 0x00, 0x00, 0x00 };
497 ins36[4] = cta_res[1];
498 for (i = 0; i <= cta_res[0]; i++)
500 ins36[3] = i;
501 l = do_cmd(reader, ins36, NULL, NULL, cta_res);
502 if (l < 0 || !status_ok(cta_res + l))
504 rdr_log(reader, "Ins36: failed");
509 break;
511 case 0x10: //loc_43C203
513 unsigned char ins7411[5] = { 0xD3,0x74,0x11,0x00,0x00 };
514 l = read_cmd_len(reader, ins7411);
515 ins7411[4] = l + 0x10;
516 l = do_cmd(reader, ins7411, NULL, NULL, cta_res);
517 if (l < 0 || !status_ok(cta_res))
519 rdr_log(reader, "classD3 ins7411: failed");
521 break;
523 case 0x00: // normal state
525 break;
527 default:
529 rdr_log(reader, "unknown ins5C state: %02X %02X %02X %02X", cta_res[0], cta_res[1], cta_res[2], cta_res[3]);
530 break;
533 reader->last_poll = now;
537 static int32_t videoguard2_card_init(struct s_reader *reader, ATR *newatr)
539 get_hist;
540 if((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
542 rdr_log_dbg(reader, D_READER, "failed history check");
543 return ERROR;
545 rdr_log_dbg(reader, D_READER, "passed history check");
547 get_atr;
548 def_resp;
550 if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
551 { return ERROR; }
552 struct videoguard_data *csystem_data = reader->csystem_data;
554 /* set information on the card stored in reader-videoguard-common.c */
555 set_known_card_info(reader, atr, &atr_size);
557 if((reader->ndsversion != NDS2) &&
558 (((csystem_data->card_system_version != NDS2) && (csystem_data->card_system_version != NDSUNKNOWN)) ||
559 (reader->ndsversion != NDSAUTO)))
561 /* known ATR and not NDS2
562 or known NDS2 ATR and forced to another NDS version */
563 return ERROR;
566 rdr_log_dbg(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
567 if(reader->ndsversion == NDS2)
569 rdr_log_dbg(reader, D_READER, "forced to NDS2");
572 //a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
573 //this way unknown videoguard2/NDS2 cards will also pass this check
575 unsigned char ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
576 int32_t l;
577 if((l = read_cmd_len(reader, ins7401)) < 0) //not a videoguard2/NDS card or communication error
579 return ERROR;
581 ins7401[4] = l;
582 if(!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
584 rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
585 return ERROR;
588 memorize_cmd_table(reader, cta_res, l);
590 unsigned char buff[256];
592 static const unsigned char ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
593 // D0 02 command is not always present in command table but should be supported
594 // on most cards so do not use do_cmd()
595 if(!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
597 rdr_log(reader, "Unable to get NDS ROM version.");
599 else
601 int i;
602 for(i = 0; i < 8; i++)
604 if(cta_res[i] <= 0x09)
606 cta_res[i] = cta_res[i] + 0x30;
608 else if(!isalnum(cta_res[i]))
610 cta_res[i] = '*';
613 memset(reader->rom, 0, sizeof(reader->rom));
614 memcpy(reader->rom, cta_res, 4);
615 reader->rom[4] = '-';
616 memcpy(reader->rom + 5, cta_res + 4, 4);
618 rdr_log(reader, "Card type: %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
619 rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
623 /* get Vg credit on card */
624 unsigned char ins7404[5] = { 0xD0, 0x74, 0x04, 0x00, 0x00 };
625 if ((l = read_cmd_len(reader, ins7404)) > 0) //get command len for ins7404
627 ins7404[4] = l;
628 if(!write_cmd_vg(ins7404, NULL) || !status_ok(cta_res + l))
630 rdr_log(reader, "classD0 ins7404: failed");
632 else
634 if (cta_res[0] == 0x15)
636 reader->VgCredit = ((cta_res[8] << 8) + cta_res[9]) / 100;
637 rdr_log(reader, "Credit available on card: %i euro", reader->VgCredit);
641 else
642 { //case V13
643 rdr_log(reader, "Unable to get smartcard credit");
646 static const unsigned char ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
648 if(do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
650 rdr_log(reader, "classD0 ins7416: failed");
651 return ERROR;
653 unsigned char boxID [4];
655 if(reader->boxid > 0)
657 /* the boxid is specified in the config */
658 int32_t i;
659 for(i = 0; i < 4; i++)
661 boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
664 else
666 unsigned char ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
667 static const unsigned char ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
669 /* we can try to get the boxid from the card */
670 int32_t boxidOK = 0;
671 l = read_cmd_len(reader, ins36);
672 if(l > 0)
674 ins36[4] = l;
676 else if(cmd_exists(reader, ins5e))
678 if(!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
680 rdr_log(reader, "classD0 ins5e: failed");
682 else
684 ins36[3] = cta_res[0];
685 ins36[4] = cta_res[1];
688 l = ins36[4];
689 if(!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
691 rdr_log(reader, "classD0 ins36: failed");
692 return ERROR;
694 memcpy(buff, ins36, 5);
695 memcpy(buff + 5, cta_res, l);
696 memcpy(buff + 5 + l, cta_res + l, 2);
697 if(l < 13)
698 { rdr_log(reader, "classD0 ins36: answer too int16"); }
699 else if(buff[7] > 0x0F)
700 { rdr_log(reader, "classD0 ins36: encrypted - can't parse"); }
701 else
703 /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
704 int32_t i = 9;
705 int32_t gotUA = 0;
706 while(i < l)
708 if(!gotUA && buff[i] < 0xF0) /* then we guess that the next 4 bytes is the UA */
710 gotUA = 1;
711 i += 4;
713 else switch(buff[i]) /* object length vary depending on type */
715 case 0x00: /* padding */
716 i += 1;
717 break;
718 case 0xEF: /* card status */
719 i += 3;
720 break;
721 case 0xD1:
722 i += 4;
723 break;
724 case 0xDF: /* next server contact */
725 i += 5;
726 break;
727 case 0xF3: /* boxID */
728 memcpy(boxID, buff + i + 1, sizeof(boxID));
729 boxidOK = 1;
730 i += 5;
731 break;
732 case 0xF6:
733 i += 6;
734 break;
735 case 0x01: /* date & time */
736 i += 7;
737 break;
738 case 0xFA:
739 i += 9;
740 break;
741 case 0x5E:
742 case 0x67: /* signature */
743 case 0xDE:
744 case 0xE2:
745 case 0xE9: /* tier dates */
746 case 0xF8: /* Old PPV Event Record */
747 case 0xFD:
748 i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
749 break;
750 default: /* default to assume a length byte */
751 rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
752 i += buff[i + 1] + 2;
757 if(!boxidOK)
759 rdr_log(reader, "no boxID available");
760 return ERROR;
764 unsigned char ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
765 unsigned char len4c = 0, mode = 0;
766 unsigned char payload4C[0xF] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
767 if(cmd_table_get_info(reader, ins4C, &len4c, &mode))
769 ins4C[4] = len4c; //don't mind if payload is > of ins len, it will be cutted after write_cmd_vg()
770 if(len4c > 9)
772 payload4C[8] = 0x44; //value taken from v14 boot log
773 rdr_log(reader, "Extended 4C detected");
777 memcpy(payload4C, boxID, 4);
778 if(!write_cmd_vg(ins4C, payload4C))
780 rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
781 return ERROR;
784 int d37423_ok = 0;
785 static const unsigned char ins7403[5] = { 0xD0, 0x74, 0x03, 0x00, 0x00 }; //taken from v13 boot log
786 if(do_cmd(reader, ins7403, NULL, NULL, cta_res) < 0)
788 rdr_log(reader, "classD0 ins7403: failed");
790 else
792 d37423_ok = (cta_res[2] >> 5) & 1;
795 if(reader->ins7E11[0x01]) //the position of the ins7E is taken from v13 log
797 unsigned char ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
799 l = read_cmd_len(reader, ins742b); //get command len for ins742b
801 if(l < 2)
803 rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
805 else
807 ins742b[4] = l;
808 bool ta1ok = 0;
810 if(!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4])) //get supported TA1 bytes
812 rdr_log(reader, "classD0 ins742b: failed");
813 return ERROR;
815 else
817 int32_t i;
819 for(i = 2; i < l; i++)
821 if(cta_res[i] == reader->ins7E11[0x00])
823 ta1ok = 1;
824 break;
828 if(ta1ok == 0)
830 rdr_log(reader, "The value %02X of ins7E11 is not supported,try one between %02X and %02X", reader->ins7E11[0x00], cta_res[2], cta_res[ins742b[4] - 1]);
832 else
834 static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
836 reader->ins7e11_fast_reset = 0;
838 l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
840 if(l < 0 || !status_ok(cta_res))
842 rdr_log(reader, "classD0 ins7E11: failed");
843 return ERROR;
845 else
847 unsigned char TA1;
849 if(ATR_GetInterfaceByte(newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
851 if(TA1 != reader->ins7E11[0x00])
853 rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
854 reader->ins7e11_fast_reset = 1;
855 #if defined(WITH_COOLAPI) || defined(WITH_COOLAPI2)
856 if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
858 #else
859 if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
861 #endif
862 add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
864 else
866 add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
868 return OK; // Skip the rest of the init since the card will be reset anyway
876 //int16_t int32_t SWIRDstatus = cta_res[1];
877 static const unsigned char ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
878 l = do_cmd(reader, ins58, NULL, NULL, cta_res);
879 if(l < 0)
881 rdr_log(reader, "classD0 ins58: failed");
882 return ERROR;
884 memset(reader->hexserial, 0, 8);
885 memcpy(reader->hexserial + 2, cta_res + 3, 4);
886 memcpy(reader->sa, cta_res + 3, 3);
887 reader->caid = cta_res[24] * 0x100 + cta_res[25];
888 reader->VgFuse = cta_res[2];
889 rdr_log(reader, "FuseByte: %02X", reader->VgFuse);
890 memset(reader->VgRegionC, 0, 8);
891 memcpy(reader->VgRegionC, cta_res + 60, 8);
892 rdr_log(reader, "Region Code: %c%c%c%c%c%c%c%c", reader->VgRegionC[0], reader->VgRegionC[1], reader->VgRegionC[2], reader->VgRegionC[3], reader->VgRegionC[4], reader->VgRegionC[5], reader->VgRegionC[6], reader->VgRegionC[7]);
893 memset(reader->VgCountryC, 0, 3);
894 memcpy(reader->VgCountryC, cta_res + 55, 3);
895 rdr_log(reader, "Country Code: %c%c%c", reader->VgCountryC[0], reader->VgCountryC[1], reader->VgCountryC[2]);
897 /* we have one provider, 0x0000 */
898 reader->nprov = 1;
899 memset(reader->prid, 0x00, sizeof(reader->prid));
902 rdr_log(reader, "INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
903 if (SWIRDstatus==4) {
904 // If swMarriage=4, not married then exchange for BC Key
905 rdr_log(reader, "Card not married, exchange for BC Keys");
908 cCamCryptVG_SetSeed(reader);
910 static const unsigned char insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
911 uint16_t tbuff[32];
912 cCamCryptVG_GetCamKey(reader, tbuff);
913 l = do_cmd(reader, insB4, (unsigned char*)tbuff, NULL, cta_res);
914 if(l < 0 || !status_ok(cta_res))
916 rdr_log(reader, "classD0 insB4: failed");
917 return ERROR;
920 static const unsigned char insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
921 l = do_cmd(reader, insBC, NULL, NULL, cta_res);
922 if(l < 0)
924 rdr_log(reader, "classD0 insBC: failed");
925 return ERROR;
928 // Class D1/D3 instructions only work after this point
930 static const unsigned char insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
931 l = do_cmd(reader, insBE, NULL, NULL, cta_res);
932 if(l < 0)
934 rdr_log(reader, "classD3 insBE: failed");
935 return ERROR;
938 static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
939 l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
940 if(l < 0)
942 rdr_log(reader, "classD1 ins58: failed");
943 return ERROR;
945 /*new ins74 present at boot*/
947 if (d37423_ok) // from ins7403 answer
949 static const unsigned char ins7423[5] = { 0xD3, 0x74, 0x23, 0x00, 0x00 };
950 if(do_cmd(reader, ins7423, NULL, NULL, cta_res) < 0)
952 rdr_log(reader, "classD1 ins7423: failed");
956 static const unsigned char ins742A[5] = { 0xD1, 0x74, 0x2A, 0x00, 0x00 };
957 if(do_cmd(reader, ins742A, NULL, NULL, cta_res) < 0)
959 rdr_log(reader, "classD1 ins742A: failed");
962 static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
963 unsigned char ins741C[5] = { 0xD1, 0x74, 0x1C, 0x00, 0x00 };
964 if(len4c > 9)
966 if((l = read_cmd_len(reader, ins741C)) < 0) // We need to know the exact len
968 return ERROR;
970 ins741C[4] = l;
971 if(do_cmd(reader, ins741C, NULL, NULL, cta_res) < 0) //from log this payload is copied on 4c
973 rdr_log(reader, "classD1 ins741C: failed");
975 else
977 if(l > 8) //if payload4c is length 0xF, we can't copy over more than 8 bytes in the next memcopy
979 l = 8;
981 memcpy(payload4C + 8, cta_res, l);
984 l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
985 if(l < 0 || !status_ok(cta_res))
987 rdr_log(reader, "classD1 ins4Ca: failed");
988 return ERROR;
990 memcpy(reader->payload4C, payload4C, 0xF);
992 if(reader->ins7E[0x1A])
994 static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
995 l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
996 if(l < 0 || !status_ok(cta_res))
998 rdr_log(reader, "classD1 ins7E: failed");
999 return ERROR;
1002 /* get PIN settings */
1003 static const unsigned char ins7411[5] = { 0xD1, 0x74, 0x11, 0x00, 0x00 };
1004 unsigned char payload2e4[4];
1005 if(do_cmd(reader, ins7411, NULL, NULL, cta_res) < 0)
1007 rdr_log(reader, "classD1 ins7411: unable to get PIN");
1008 return ERROR;
1010 else
1012 memset(payload2e4, 0, 4);
1013 memcpy(payload2e4, cta_res + 2, 4);
1014 reader->VgPin = (cta_res[4] << 8) + cta_res[5];
1015 rdr_log(reader, "Pincode read: %04hu", reader->VgPin);
1018 /* get PCB(content rating) settings */
1019 static const unsigned char ins74e[5] = {0xD1, 0x74, 0x0E, 0x00, 0x00};
1020 if(do_cmd(reader, ins74e, NULL, NULL, cta_res) < 0)
1022 rdr_log(reader, "classD1 ins74e: failed to get PCB settings");
1024 else
1026 rdr_log(reader, "PCB settings: %X %X %X %X", cta_res[2], cta_res[3], cta_res[4], cta_res[5]);
1029 /* send PIN */
1030 static const unsigned char ins2epin[5] = {0xD1, 0x2E, 0x04, 0x00, 0x04};
1031 if(cfg.ulparent)
1033 l = do_cmd(reader, ins2epin, payload2e4, NULL, cta_res);
1034 if(l < 0 || !status_ok(cta_res))
1036 rdr_log(reader, "classD1 ins2E: failed");
1037 rdr_log(reader, "Cannot disable parental control");
1038 return ERROR;
1040 else
1042 rdr_log(reader, "Parental control disabled");
1045 /* send check control for pin, needed on some cards */
1046 /* the presence and the value of payloads is provider's dependent*/
1047 if(reader->ins2e06[4])
1049 static const unsigned char ins2e06[5] = { 0xD1, 0x2E, 0x06, 0x00, 0x04 };
1050 l = do_cmd(reader, ins2e06, reader->ins2e06, NULL, cta_res);
1051 if(l < 0 || !status_ok(cta_res))
1053 rdr_log(reader, "classD1 ins2E: failed");
1054 return ERROR;
1058 // fix for 09ac cards
1059 unsigned char dimeno_magic[0x10] = {0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C, 0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02};
1060 int32_t a;
1061 for(a = 0; a < 4; a++)
1062 { dimeno_magic[a] = dimeno_magic[a] ^ boxID[a]; }
1063 AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
1065 rdr_log(reader, "type: %s, caid: %04X",
1066 csystem_data->card_desc,
1067 reader->caid);
1068 rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
1069 reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
1070 boxID[0], boxID[1], boxID[2], boxID[3],
1071 csystem_data->card_baseyear);
1072 rdr_log(reader, "ready for requests");
1074 return OK;
1077 static int32_t videoguard2_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
1079 unsigned char cta_res[CTA_RES_LEN];
1080 static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
1081 unsigned char ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
1082 static const unsigned char ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
1083 int32_t posECMpart2 = er->ecm[6] + 7;
1084 int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
1085 unsigned char tbuff[264], rbuff[264];
1086 const unsigned char *EcmIrdHeader = er->ecm + 5;
1087 tbuff[0] = 0;
1089 memset(ea->cw + 0, 0, 16); //set cw to 0 so client will know it is invalid unless it is overwritten with a valid cw
1090 int32_t chk;
1091 chk = checksum_ok(EcmIrdHeader);
1092 if((memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm)) != 0) || (chk == 0))
1094 rdr_log(reader, "Not a valid ecm");
1095 return E_CORRUPT;
1097 memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
1100 //log parental lock byte
1101 int32_t j;
1102 for (j = posECMpart2+1; j < lenECMpart2+posECMpart2+1-4; j++){
1103 if (er->ecm[j] == 0x02 && er->ecm[j+3] == 0x02) {
1104 rdr_log(reader, "channel parental lock mask: %02X%02X, channel parental lock byte: %02X",er->ecm[j+1],er->ecm[j+2],er->ecm[j+4]);
1105 break;
1109 //log tiers
1110 int32_t k;
1111 char tiername[83];
1112 for (k = posECMpart2+1; k < lenECMpart2+posECMpart2+1-4; k++){
1113 if (er->ecm[k] == 0x03 && er->ecm[k+3] == 0x80) {
1114 uint16_t vtier_id = (er->ecm[k+1] << 8) | er->ecm[k+2];
1115 get_tiername(vtier_id, reader->caid, tiername);
1116 rdr_log(reader, "valid tier: %04x %s",vtier_id, tiername);
1121 int32_t new_len = lenECMpart2;
1122 if(reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
1124 tbuff[1] = 0x47;
1125 tbuff[2] = 0x08;
1126 memmove(tbuff + 11, tbuff + 13, new_len - 11);
1127 new_len -= 2;
1129 ins40[4] = new_len;
1130 int32_t l;
1132 l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
1133 if(l < 0 || !status_ok(cta_res))
1135 rdr_log(reader, "classD1 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
1136 rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
1137 add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
1138 return ERROR;
1140 else
1142 l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
1143 if(l < 0 || !status_ok(cta_res + l))
1145 rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
1146 rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
1147 add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
1148 return ERROR;
1150 else
1153 struct videoguard_data *csystem_data = reader->csystem_data;
1154 unsigned char *payload = rbuff + 5;
1155 unsigned char buff_0F[6]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1156 unsigned char buff_56[8]={ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
1157 unsigned char buff_55[1]={ 0x00 };
1158 unsigned char tag, t_len;
1159 unsigned char *t_body;
1160 int32_t payloadLen = rbuff[4];
1161 int32_t ind = 8 + 6; // +8 (CW1), +2 (cw checksum) + 2 (tier used) +2 (result byte)
1162 while(ind < payloadLen)
1164 tag = payload[ind];
1165 t_len = payload[ind + 1]; //len of the tag
1166 t_body = payload + ind + 2; //body of the tag
1167 switch(tag)
1169 case 0x0F: // Debug ecm info
1170 if(t_len > 6)
1172 t_len = 6;
1175 memcpy(buff_0F, t_body, t_len);
1176 break;
1177 case 0x25: // CW2 tag
1178 memcpy(ea->cw + 8, t_body +1, 8);
1179 break;
1180 case 0x55: // cw crypt info tag
1181 memcpy(buff_55, t_body, 1 );
1182 break;
1183 case 0x56: // tag data for astro
1184 memcpy(buff_56, t_body, 8);
1185 break;
1186 default:
1187 break;
1189 ind += t_len + 2;
1192 if(12 < payloadLen)
1194 ea->tier = b2i(2, &payload[10]);
1197 memcpy(reader->VgLastPayload, buff_0F, 6);
1199 int32_t test_0F = 1;
1200 if(!cw_is_valid(rbuff + 5)) //sky cards report 90 00 = ok but send cw = 00 when something goes wrong :(
1202 if (buff_0F[0]&1){ //case 0f_0x 01 xx xx xx xx xx
1203 rdr_log(reader, "classD3 ins54: no cw --> Bad/wrong ECM");
1204 test_0F = 0;
1206 if (buff_0F[1]&1){ //case 0f_0x xx 01 xx xx xx xx
1207 rdr_log(reader, "classD3 ins54: no cw --> Card appears in error");
1208 test_0F = 0;
1210 if ((buff_0F[0]>>1)&1){ //case 0f_0x 02 xx xx xx xx xx
1211 rdr_log(reader, "classD3 ins54: no cw --> Card isn't active");
1212 test_0F = 0;
1214 else{ //These Messages are only nessensary if the Card is active
1215 if ((buff_0F[1]>>4)&1){ //case 0f_0x xx 10 xx xx xx xx
1216 rdr_log(reader, "classD3 ins54: no cw --> Card needs pairing/extra data");
1217 test_0F = 0;
1219 if ((buff_0F[1]>>5)&1){ //case 0f_0x xx 20 xx xx xx xx
1220 rdr_log(reader, "classD3 ins54: no cw --> No tier found"); //check this
1221 test_0F = 0;
1223 if ((buff_0F[2]>>5)&1){ //case 0f_0x xx xx 20 xx xx xx
1224 rdr_log(reader, "classD3 ins54: no cw --> Tier expired");
1225 test_0F = 0;
1227 if ((buff_0F[1]>>6)&1){ //case 0f_0x xx 40 xx xx xx xx
1228 rdr_log(reader, "classD3 ins54: no cw --> Card needs pin");
1229 test_0F = 0;
1233 if (reader->caid == 0x98C || reader->caid == 0x98D){ //Only for Sky Germany 'V14/V15' Card
1234 if ((~buff_0F[5]&1) && ((buff_0F[5]>>3)&1)){ //case 0f_0x xx xx xx xx xx 08 > 0x08 = binary xxxx1xx0
1235 rdr_log(reader, "classD3 ins54: no cw --> Card is paired! (Debug-ECM-Info: 0F_06 %02X %02X %02X %02X %02X %02X)",buff_0F[0],buff_0F[1],buff_0F[2],buff_0F[3],buff_0F[4],buff_0F[5]);
1237 if ((~buff_0F[5]&1) && (~(buff_0F[5]>>3)&1)){ //case 0f_0x xx xx xx xx xx 00 > 0x00 = binary xxxx0xx0
1238 rdr_log(reader, "classD3 ins54: no cw --> Card is prepaired / Card is paired, but the pairing is deactivated (Debug-ECM-Info: 0F_06 %02X %02X %02X %02X %02X %02X)",buff_0F[0],buff_0F[1],buff_0F[2],buff_0F[3],buff_0F[4],buff_0F[5]);
1240 if (buff_0F[5]&1){ //case 0f_0x xx xx xx xx xx 01 > 0x01 = binary xxxxxxx1
1241 rdr_log(reader, "classD3 ins54: no cw --> Card is not paired (Debug-ECM-Info: 0F_06 %02X %02X %02X %02X %02X %02X)",buff_0F[0],buff_0F[1],buff_0F[2],buff_0F[3],buff_0F[4],buff_0F[5]);
1245 if (test_0F){ //case unknown error
1246 rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 tag 0F: %02X %02X %02X %02X %02X %02X, please report to the developers with decrypted ins54",buff_0F[0],buff_0F[1],buff_0F[2],buff_0F[3],buff_0F[4],buff_0F[5]);
1249 return ERROR;
1252 // copy cw1 in place
1253 memcpy(ea->cw + 0, rbuff + 5, 8);
1255 if (buff_55[0]&1){ //case 55_01 xx where bit0==1
1256 rdr_log(reader, "classD3 ins54: CW is crypted, pairing active, bad cw");
1257 return ERROR;
1259 if ((buff_55[0]>>2)&1){ //case 55_01 xx where bit2==1, old dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
1260 unsigned char buffer[0x10];
1261 memcpy(buffer, rbuff + 5, 8);
1262 memcpy(buffer + 8, buff_56, 8);
1263 AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
1264 memcpy(ea->cw + 0, buffer, 8); // copy calculated CW in right place
1267 if(new_len != lenECMpart2)
1269 memcpy(ea->cw, ea->cw + 8, 8);
1270 memset(ea->cw + 8, 0, 8);
1273 //test for postprocessing marker
1274 int32_t posB0 = -1;
1275 int32_t i;
1276 for(i = 6; i < posECMpart2; i++)
1278 if(er->ecm[i - 3] == 0x80 && er->ecm[i] == 0xB0 && ((er->ecm[i + 1] == 0x01) || (er->ecm[i + 1] == 0x02) || (er->ecm[i + 1] == 0x03)))
1280 posB0 = i;
1281 break;
1284 if(posB0 != -1 && (reader->caid == 0x919 || reader->caid == 0x93B || reader->caid == 0x9CD || reader->caid == 0x9C1))
1286 do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
1287 do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
1290 if(reader->caid == 0x0907) //quickfix: cw2 is not a valid cw, something went wrong before
1292 memset(ea->cw + 8, 0, 8);
1293 if(er->ecm[0] & 1)
1295 memcpy(ea->cw + 8, ea->cw, 8);
1296 memset(ea->cw, 0, 8);
1299 else
1301 if(er->ecm[0] & 1)
1303 unsigned char tmpcw[8];
1304 memcpy(tmpcw, ea->cw + 8, 8);
1305 memcpy(ea->cw + 8, ea->cw + 0, 8);
1306 memcpy(ea->cw + 0, tmpcw, 8);
1310 return OK;
1315 static int32_t videoguard2_do_emm(struct s_reader *reader, EMM_PACKET *ep)
1317 return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
1320 static int32_t videoguard2_card_info(struct s_reader *reader)
1322 /* info is displayed in init, or when processing info */
1323 struct videoguard_data *csystem_data = reader->csystem_data;
1324 rdr_log(reader, "card detected");
1325 rdr_log(reader, "type: %s", csystem_data->card_desc);
1326 if(reader->ins7e11_fast_reset != 1)
1328 vg2_read_tiers(reader);
1330 return OK;
1333 static void videoguard2_card_done(struct s_reader *reader)
1335 struct videoguard_data *csystem_data = reader->csystem_data;
1336 if (csystem_data)
1338 NULLFREE(csystem_data->cmd_table);
1342 const struct s_cardsystem reader_videoguard2 =
1344 .desc = "videoguard2",
1345 .caids = (uint16_t[]){ 0x09, 0 },
1346 .do_emm = videoguard2_do_emm,
1347 .do_ecm = videoguard2_do_ecm,
1348 .card_info = videoguard2_card_info,
1349 .card_init = videoguard2_card_init,
1350 .poll_status = videoguard2_poll_status,
1351 .card_done = videoguard2_card_done,
1352 .get_emm_type = videoguard_get_emm_type,
1353 .get_emm_filter = videoguard_get_emm_filter,
1356 #endif