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"
|
---|
7 |
|
---|
8 | static void dimeno_PostProcess_Decrypt(struct s_reader *reader, unsigned char *rxbuff, unsigned char *cw)
|
---|
9 | {
|
---|
10 | struct videoguard_data *csystem_data = reader->csystem_data;
|
---|
11 | unsigned char tag, len, len2;
|
---|
12 | bool valid_0x55 = 0;
|
---|
13 | unsigned char *body;
|
---|
14 | unsigned char buffer[0x10];
|
---|
15 | int32_t a = 0x13;
|
---|
16 | len2 = rxbuff[4];
|
---|
17 | while(a < len2 + 5 - 9) // +5 for 5 ins bytes, -9 (body=8 len=1) to prevent memcpy(buffer+8,body,8) from reading past rxbuff
|
---|
18 | {
|
---|
19 | tag = rxbuff[a];
|
---|
20 | len = rxbuff[a + 1];
|
---|
21 | body = rxbuff + a + 2;
|
---|
22 | switch(tag)
|
---|
23 | {
|
---|
24 | case 0x55:
|
---|
25 | {
|
---|
26 | if(body[0] == 0x84) //Tag 0x56 has valid data...
|
---|
27 | {
|
---|
28 | valid_0x55 = 1;
|
---|
29 | }
|
---|
30 | }
|
---|
31 | break;
|
---|
32 | case 0x56:
|
---|
33 | {
|
---|
34 | memcpy(buffer + 8, body, 8);
|
---|
35 | }
|
---|
36 | break;
|
---|
37 | }
|
---|
38 | a += len + 2;
|
---|
39 | }
|
---|
40 | if(valid_0x55)
|
---|
41 | {
|
---|
42 | memcpy(buffer, rxbuff + 5, 8);
|
---|
43 | AES_decrypt(buffer, buffer, &(csystem_data->astrokey));
|
---|
44 | memcpy(cw + 0, buffer, 8); // copy calculated CW in right place
|
---|
45 | }
|
---|
46 | }
|
---|
47 |
|
---|
48 | static void do_post_dw_hash(struct s_reader *reader, unsigned char *cw, const unsigned char *ecm_header_data)
|
---|
49 | {
|
---|
50 | int32_t i, ecmi, ecm_header_count;
|
---|
51 | unsigned char buffer[0x85]; //original 0x80 but with 0x7D mask applied +8 bytes cw it was still to small
|
---|
52 | unsigned char md5tmp[MD5_DIGEST_LENGTH];
|
---|
53 | static const uint16_t Hash3[] = {0x0123, 0x4567, 0x89AB, 0xCDEF, 0xF861, 0xCB52};
|
---|
54 | static const unsigned char Hash4[] = {0x0B, 0x04, 0x07, 0x08, 0x05, 0x09, 0x0B, 0x0A, 0x07, 0x02, 0x0A, 0x05, 0x04, 0x08, 0x0D, 0x0F};
|
---|
55 | static const uint16_t NdTabB001[0x15][0x20] =
|
---|
56 | {
|
---|
57 | {
|
---|
58 | 0xEAF1, 0x0237, 0x29D0, 0xBAD2, 0xE9D3, 0x8BAE, 0x2D6D, 0xCD1B,
|
---|
59 | 0x538D, 0xDE6B, 0xA634, 0xF81A, 0x18B5, 0x5087, 0x14EA, 0x672E,
|
---|
60 | 0xF0FC, 0x055E, 0x62E5, 0xB78F, 0x5D09, 0x0003, 0xE4E8, 0x2DCE,
|
---|
61 | 0x6BE0, 0xAC4E, 0xF485, 0x6967, 0xF28C, 0x97A0, 0x01EF, 0x0100
|
---|
62 | },
|
---|
63 | {
|
---|
64 | 0xC539, 0xF5B9, 0x9099, 0x013A, 0xD4B9, 0x6AB5, 0xEA67, 0x7EB4,
|
---|
65 | 0x6C30, 0x4BF0, 0xB810, 0xB0B5, 0xB76D, 0xA751, 0x1AE7, 0x14CA,
|
---|
66 | 0x4F4F, 0x1586, 0x2608, 0x10B1, 0xE7E1, 0x48BE, 0x7DDD, 0x5ECB,
|
---|
67 | 0xCFBF, 0x323B, 0x8B31, 0xB131, 0x0F1A, 0x664B, 0x0140, 0x0100
|
---|
68 | },
|
---|
69 | {
|
---|
70 | 0x3C7D, 0xBDC4, 0xFEC7, 0x26A6, 0xB0A0, 0x6E55, 0xF710, 0xF9BF,
|
---|
71 | 0x0023, 0xE81F, 0x41CA, 0xBE32, 0xB461, 0xE92D, 0xF1AF, 0x409F,
|
---|
72 | 0xFC85, 0xFE5B, 0x7FCE, 0x17F5, 0x01AB, 0x4A46, 0xEB05, 0xA251,
|
---|
73 | 0xDC6F, 0xF0C0, 0x10F0, 0x1D51, 0xEFAA, 0xE9BF, 0x0100, 0x0100
|
---|
74 | },
|
---|
75 | {
|
---|
76 | 0x1819, 0x0CAA, 0x9067, 0x607A, 0x7576, 0x1CBC, 0xE51D, 0xBF77,
|
---|
77 | 0x7EC6, 0x839E, 0xB695, 0xF096, 0xDC10, 0xCB69, 0x4654, 0x8E68,
|
---|
78 | 0xD62D, 0x4F1A, 0x4227, 0x92AC, 0x9064, 0x6BD1, 0x1E75, 0x2747,
|
---|
79 | 0x00DA, 0xA6A6, 0x6CF1, 0xD151, 0xBE56, 0x3E33, 0x0128, 0x0100
|
---|
80 | },
|
---|
81 | {
|
---|
82 | 0x4091, 0x09ED, 0xD494, 0x6054, 0x1869, 0x71D5, 0xB572, 0x7BF1,
|
---|
83 | 0xE925, 0xEE2D, 0xEEDE, 0xA13C, 0x6613, 0x9BAB, 0x122D, 0x7AE4,
|
---|
84 | 0x5268, 0xE6C9, 0x50CB, 0x79A1, 0xF212, 0xA062, 0x6B48, 0x70B3,
|
---|
85 | 0xF6B0, 0x06D5, 0xF8AB, 0xECF5, 0x6255, 0xEDD8, 0x79D2, 0x290A
|
---|
86 | },
|
---|
87 | {
|
---|
88 | 0xD3CF, 0x014E, 0xACB3, 0x8F6B, 0x0F2C, 0xA5D8, 0xE8E0, 0x863D,
|
---|
89 | 0x80D5, 0x5705, 0x658A, 0x8BC2, 0xEE46, 0xD3AE, 0x0199, 0x0100,
|
---|
90 | 0x4A35, 0xABE4, 0xF976, 0x935A, 0xA8A5, 0xBAE9, 0x24D0, 0x71AA,
|
---|
91 | 0xB3FE, 0x095E, 0xAB06, 0x4CD5, 0x2F0D, 0x1ACB, 0x59F3, 0x4C50
|
---|
92 | },
|
---|
93 | {
|
---|
94 | 0xFD27, 0x0F8E, 0x191A, 0xEEE7, 0x2F49, 0x3A05, 0x3267, 0x4F88,
|
---|
95 | 0x38AE, 0xFCE9, 0x9476, 0x18C6, 0xF961, 0x4EF0, 0x39D0, 0x42E6,
|
---|
96 | 0xB747, 0xE625, 0xB68E, 0x5100, 0xF92A, 0x86FE, 0xE79B, 0xEE91,
|
---|
97 | 0x21D5, 0x4C3C, 0x683D, 0x5AD1, 0x1B49, 0xF407, 0x0194, 0x0100
|
---|
98 | },
|
---|
99 | {
|
---|
100 | 0x4BF9, 0xDC0D, 0x9478, 0x5174, 0xCB4A, 0x8A89, 0x4D6A, 0xFED8,
|
---|
101 | 0xF123, 0xA8CD, 0xEEE7, 0xA6D1, 0xB763, 0xF5E2, 0xE085, 0x01EF,
|
---|
102 | 0xE466, 0x9FA3, 0x2F68, 0x2190, 0x423F, 0x287F, 0x7F3F, 0x09F6,
|
---|
103 | 0x2111, 0xA963, 0xD0BB, 0x674A, 0xBA72, 0x45F9, 0xF186, 0xB8F5
|
---|
104 | },
|
---|
105 | {
|
---|
106 | 0x0010, 0xD1B9, 0xB164, 0x9E87, 0x1F49, 0x6950, 0x2DBF, 0x38D3,
|
---|
107 | 0x2EB0, 0x3E8E, 0x91E6, 0xF688, 0x7E41, 0x566E, 0x01B0, 0x0100,
|
---|
108 | 0x24A1, 0x73D8, 0xA0C3, 0xF71B, 0xA0A5, 0x2A06, 0xBA46, 0xFEC3,
|
---|
109 | 0xDD4C, 0x52CC, 0xF9BC, 0x3B7E, 0x3812, 0x0666, 0xB74B, 0x40F8
|
---|
110 | },
|
---|
111 | {
|
---|
112 | 0x28F2, 0x7C81, 0xFC92, 0x6FBD, 0x53D6, 0x72A3, 0xBBDF, 0xB6FC,
|
---|
113 | 0x9CE5, 0x2331, 0xD4F6, 0xC5BB, 0xE8BB, 0x6676, 0x02D9, 0x2F0E,
|
---|
114 | 0xD009, 0xD136, 0xCD09, 0x7551, 0x1826, 0x9D9B, 0x63EA, 0xFC63,
|
---|
115 | 0x68CD, 0x3672, 0xCB95, 0xD28E, 0xF1CD, 0x20CA, 0x014C, 0x0100
|
---|
116 | },
|
---|
117 | {
|
---|
118 | 0xE539, 0x55B7, 0x989D, 0x21C4, 0x463A, 0xE68F, 0xF8B5, 0xE5C5,
|
---|
119 | 0x662B, 0x35BF, 0x3C50, 0x0131, 0xF4BF, 0x38B2, 0x41BC, 0xB829,
|
---|
120 | 0x02B7, 0x6B8F, 0xA25C, 0xAFD2, 0xD84A, 0x2243, 0x53EB, 0xC6C9,
|
---|
121 | 0x2E14, 0x181F, 0x8F96, 0xDF0E, 0x0D4C, 0x30F6, 0xFFE1, 0x9DDA
|
---|
122 | },
|
---|
123 | {
|
---|
124 | 0x30B6, 0x777E, 0xDA3D, 0xAF77, 0x205E, 0xC90B, 0x856B, 0xB451,
|
---|
125 | 0x3BCC, 0x76C2, 0x8ACF, 0xDCB1, 0xA5E5, 0xDD64, 0x0197, 0x0100,
|
---|
126 | 0xE751, 0xB661, 0x0404, 0xDB4A, 0xE9DD, 0xA400, 0xAF26, 0x3F5E,
|
---|
127 | 0x904B, 0xA924, 0x09E0, 0xE72B, 0x825B, 0x2C50, 0x6FD0, 0x0D52
|
---|
128 | },
|
---|
129 | {
|
---|
130 | 0x2730, 0xC2BA, 0x9E44, 0x5815, 0xFC47, 0xB21D, 0x67B8, 0xF8B9,
|
---|
131 | 0x047D, 0xB0AF, 0x9F14, 0x741B, 0x4668, 0xBE54, 0xDE16, 0xDB14,
|
---|
132 | 0x7CB7, 0xF2B8, 0x0683, 0x762C, 0x09A0, 0x9507, 0x7F92, 0x022C,
|
---|
133 | 0xBA6A, 0x7D52, 0x0AF4, 0x1BC3, 0xB46A, 0xC4FD, 0x01C2, 0x0100
|
---|
134 | },
|
---|
135 | {
|
---|
136 | 0x7611, 0x66F3, 0xEE87, 0xEDD3, 0xC559, 0xEFD4, 0xDC59, 0xF86B,
|
---|
137 | 0x6D1C, 0x1C85, 0x9BB1, 0x3373, 0x763F, 0x4EBE, 0x1BF3, 0x99B5,
|
---|
138 | 0xD721, 0x978F, 0xCF5C, 0xAC51, 0x0984, 0x7462, 0x8F0C, 0x2817,
|
---|
139 | 0x4AD9, 0xFD41, 0x6678, 0x7C85, 0xD330, 0xC9F8, 0x1D9A, 0xC622
|
---|
140 | },
|
---|
141 | {
|
---|
142 | 0x5AE4, 0xE16A, 0x60F6, 0xFD45, 0x668C, 0x29D6, 0x0285, 0x6B92,
|
---|
143 | 0x92C2, 0x21DE, 0x45E0, 0xEF3D, 0x8B0D, 0x02CD, 0x0198, 0x0100,
|
---|
144 | 0x9E6D, 0x4D38, 0xDEF9, 0xE6F2, 0xF72E, 0xB313, 0x14F2, 0x390A,
|
---|
145 | 0x2D67, 0xC71E, 0xCB69, 0x7F66, 0xD3CF, 0x7F8A, 0x81D9, 0x9DDE
|
---|
146 | },
|
---|
147 | {
|
---|
148 | 0x85E3, 0x8F29, 0x36EB, 0xC968, 0x3696, 0x59F6, 0x7832, 0xA78B,
|
---|
149 | 0xA1D8, 0xF5CF, 0xAB64, 0x646D, 0x7A2A, 0xBAF8, 0xAA87, 0x41C7,
|
---|
150 | 0x5120, 0xDE78, 0x738D, 0xDC1A, 0x268D, 0x5DF8, 0xED69, 0x1C8A,
|
---|
151 | 0xBC85, 0x3DCD, 0xAE30, 0x0F8D, 0xEC89, 0x3ABD, 0x0166, 0x0100
|
---|
152 | },
|
---|
153 | {
|
---|
154 | 0xB8BD, 0x643B, 0x748E, 0xBD63, 0xEC6F, 0xE23A, 0x9493, 0xDD76,
|
---|
155 | 0x0A62, 0x774F, 0xCD68, 0xA67A, 0x9A23, 0xC8A8, 0xBDE5, 0x9D1B,
|
---|
156 | 0x2B86, 0x8B36, 0x5428, 0x1DFB, 0xCD1D, 0x0713, 0x29C2, 0x8E8E,
|
---|
157 | 0x5207, 0xA13F, 0x6005, 0x4F5E, 0x52E0, 0xE7C8, 0x6D1C, 0x3E34
|
---|
158 | },
|
---|
159 | {
|
---|
160 | 0x581D, 0x2BFA, 0x5E1D, 0xA891, 0x1069, 0x1DA4, 0x39A0, 0xBE45,
|
---|
161 | 0x5B9A, 0x7333, 0x6F3E, 0x8637, 0xA550, 0xC9E9, 0x5C6C, 0x42BA,
|
---|
162 | 0xA712, 0xC3EA, 0x3808, 0x0910, 0xAA4D, 0x5B25, 0xABCD, 0xE680,
|
---|
163 | 0x96AD, 0x2CEC, 0x8EBB, 0xA47D, 0x1690, 0xE8FB, 0x01C8, 0x0100
|
---|
164 | },
|
---|
165 | {
|
---|
166 | 0x73B9, 0x82BC, 0x9EBC, 0xB130, 0x0DA5, 0x8617, 0x9F7B, 0x9766,
|
---|
167 | 0x205D, 0x752D, 0xB05C, 0x2A17, 0xA75C, 0x18EF, 0x8339, 0xFD34,
|
---|
168 | 0x8DA2, 0x7970, 0xD0B4, 0x70F1, 0x3765, 0x7380, 0x7CAF, 0x570E,
|
---|
169 | 0x6440, 0xBC44, 0x0743, 0x2D02, 0x0419, 0xA240, 0x2113, 0x1AD4
|
---|
170 | },
|
---|
171 | {
|
---|
172 | 0x1EB5, 0xBBFF, 0x39B1, 0x3209, 0x705F, 0x15F4, 0xD7AD, 0x340B,
|
---|
173 | 0xC2A6, 0x25CA, 0xF412, 0x9570, 0x0F4F, 0xE4D5, 0x1614, 0xE464,
|
---|
174 | 0x911A, 0x0F0E, 0x07DA, 0xA929, 0x2379, 0xD988, 0x0AA6, 0x3B57,
|
---|
175 | 0xBF63, 0x71FB, 0x72D5, 0x26CE, 0xB0AF, 0xCF45, 0x011B, 0x0100
|
---|
176 | },
|
---|
177 | {
|
---|
178 | 0x9999, 0x98FE, 0xA108, 0x6588, 0xF90B, 0x4554, 0xFF38, 0x4642,
|
---|
179 | 0x8F5F, 0x6CC3, 0x4E8E, 0xFF7E, 0x64C2, 0x50CA, 0x0E7F, 0xAD7D,
|
---|
180 | 0x6AAB, 0x33C1, 0xE1F4, 0x6165, 0x7894, 0x83B9, 0x0A0C, 0x38AF,
|
---|
181 | 0x5803, 0x18C0, 0xFA36, 0x592C, 0x4548, 0xABB8, 0x1527, 0xAEE9
|
---|
182 | }
|
---|
183 | };
|
---|
184 |
|
---|
185 |
|
---|
186 | //ecm_header_data = 01 03 b0 01 01
|
---|
187 | if(!cw_is_valid(cw)) //if cw is all zero, keep it that way
|
---|
188 | {
|
---|
189 | return;
|
---|
190 | }
|
---|
191 | ecm_header_count = ecm_header_data[0];
|
---|
192 | for(i = 0, ecmi = 1; i < ecm_header_count; i++)
|
---|
193 | {
|
---|
194 | if(ecm_header_data[ecmi + 1] != 0xb0)
|
---|
195 | {
|
---|
196 | ecmi += ecm_header_data[ecmi] + 1;
|
---|
197 | }
|
---|
198 | else
|
---|
199 | {
|
---|
200 | switch(ecm_header_data[ecmi + 2])
|
---|
201 | {
|
---|
202 | //b0 01
|
---|
203 | case 1:
|
---|
204 | {
|
---|
205 | uint16_t hk[8], r, j, m = 0;
|
---|
206 | for(r = 0; r < 6; r++)
|
---|
207 | { hk[2 + r] = Hash3[r]; }
|
---|
208 | for(r = 0; r < 2; r++)
|
---|
209 | {
|
---|
210 | for(j = 0; j < 0x48; j += 2)
|
---|
211 | {
|
---|
212 | if(r)
|
---|
213 | {
|
---|
214 | hk[0] = ((hk[3] & hk[5]) | ((~hk[5]) & hk[4]));
|
---|
215 | }
|
---|
216 | else
|
---|
217 | {
|
---|
218 | hk[0] = ((hk[3] & hk[4]) | ((~hk[3]) & hk[5]));
|
---|
219 | }
|
---|
220 | if(j < 8)
|
---|
221 | {
|
---|
222 | hk[0] = (hk[0] + ((cw[j + 1] << 8) | cw[j]));
|
---|
223 | }
|
---|
224 | if(j == 8)
|
---|
225 | {
|
---|
226 | hk[0] = (hk[0] + 0x80);
|
---|
227 | }
|
---|
228 | hk[0] = (hk[0] + hk[2] + (0xFF & NdTabB001[ecm_header_data[ecmi + 3]][m >> 1] >> ((m & 1) << 3)));
|
---|
229 | hk[1] = hk[2];
|
---|
230 | hk[2] = hk[3];
|
---|
231 | hk[3] = hk[4];
|
---|
232 | hk[4] = hk[5];
|
---|
233 | hk[5] = hk[6];
|
---|
234 | hk[6] = hk[7];
|
---|
235 | hk[7] = hk[2] + (((hk[0] << Hash4[m & 0xF]) | (hk[0] >> (0x10 - Hash4[m & 0xF]))));
|
---|
236 | m = (m + 1) & 0x3F;
|
---|
237 | }
|
---|
238 | }
|
---|
239 | for(r = 0; r < 6; r++)
|
---|
240 | {
|
---|
241 | hk[2 + r] += Hash3[r];
|
---|
242 | }
|
---|
243 | for(r = 0; r < 7; r++)
|
---|
244 | {
|
---|
245 | cw[r] = hk[2 + (r >> 1)] >> ((r & 1) << 3);
|
---|
246 | }
|
---|
247 | cw[3] = (cw[0] + cw[1] + cw[2]) & 0xFF;
|
---|
248 | cw[7] = (cw[4] + cw[5] + cw[6]) & 0xFF;
|
---|
249 | rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 1 DW:");
|
---|
250 | break;
|
---|
251 | }
|
---|
252 | case 3:
|
---|
253 | {
|
---|
254 | memset(buffer, 0, sizeof(buffer));
|
---|
255 | memcpy(buffer, cw, 8);
|
---|
256 | memcpy(buffer + 8, &ecm_header_data[ecmi + 3], ecm_header_data[ecmi] & 0x7D);
|
---|
257 | MD5(buffer, 8 + (ecm_header_data[ecmi] & 0x7D), md5tmp);
|
---|
258 | memcpy(cw, md5tmp, 8);
|
---|
259 | rdr_ddump_mask(reader, D_READER, cw, 8, "Postprocessed Case 3 DW:");
|
---|
260 | break;
|
---|
261 | }
|
---|
262 | case 2:
|
---|
263 | {
|
---|
264 | /* Method 2 left out */
|
---|
265 | //memcpy(DW_OUTPUT, DW_INPUT, 8);
|
---|
266 | break;
|
---|
267 | }
|
---|
268 | }
|
---|
269 | }
|
---|
270 | }
|
---|
271 | }
|
---|
272 |
|
---|
273 |
|
---|
274 | static void vg2_read_tiers(struct s_reader *reader)
|
---|
275 | {
|
---|
276 | def_resp;
|
---|
277 | int32_t l;
|
---|
278 |
|
---|
279 | /* ins2a is not needed and causes an error on some cards eg Sky Italy 09CD
|
---|
280 | check if ins2a is in command table before running it
|
---|
281 | */
|
---|
282 | static const unsigned char ins2a[5] = { 0xD0, 0x2a, 0x00, 0x00, 0x00 };
|
---|
283 | if(cmd_exists(reader, ins2a))
|
---|
284 | {
|
---|
285 | l = do_cmd(reader, ins2a, NULL, NULL, cta_res);
|
---|
286 | if(l < 0 || !status_ok(cta_res + l))
|
---|
287 | {
|
---|
288 | rdr_log(reader, "classD0 ins2a: failed");
|
---|
289 | return;
|
---|
290 | }
|
---|
291 | }
|
---|
292 |
|
---|
293 | static const unsigned char ins76007f[5] = { 0xD0, 0x76, 0x00, 0x7f, 0x02 };
|
---|
294 | if(!write_cmd_vg(ins76007f, NULL) || !status_ok(cta_res + 2))
|
---|
295 | {
|
---|
296 | rdr_log(reader, "classD0 ins76007f: failed");
|
---|
297 | return;
|
---|
298 | }
|
---|
299 | int32_t num = cta_res[1];
|
---|
300 |
|
---|
301 | int32_t i;
|
---|
302 | unsigned char ins76[5] = { 0xD0, 0x76, 0x00, 0x00, 0x00 };
|
---|
303 | struct videoguard_data *csystem_data = reader->csystem_data;
|
---|
304 |
|
---|
305 | // some cards start real tiers info in middle of tier info
|
---|
306 | // and have blank tiers between old tiers and real tiers eg 09AC
|
---|
307 | int32_t starttier = csystem_data->card_tierstart;
|
---|
308 | bool stopemptytier = 1;
|
---|
309 | if(!starttier)
|
---|
310 | { stopemptytier = 0; }
|
---|
311 |
|
---|
312 | // check to see if specified start tier is blank and if blank, start at 0 and ignore blank tiers
|
---|
313 | ins76[2] = starttier;
|
---|
314 | l = do_cmd(reader, ins76, NULL, NULL, cta_res);
|
---|
315 | if(l < 0 || !status_ok(cta_res + l)) { return; }
|
---|
316 | if(cta_res[2] == 0 && cta_res[3] == 0)
|
---|
317 | {
|
---|
318 | stopemptytier = 0;
|
---|
319 | starttier = 0;
|
---|
320 | }
|
---|
321 |
|
---|
322 | cs_clear_entitlement(reader); // reset the entitlements
|
---|
323 |
|
---|
324 | for(i = starttier; i < num; i++)
|
---|
325 | {
|
---|
326 | ins76[2] = i;
|
---|
327 | l = do_cmd(reader, ins76, NULL, NULL, cta_res);
|
---|
328 | if(l < 0 || !status_ok(cta_res + l)) { return; }
|
---|
329 | if(cta_res[2] == 0 && cta_res[3] == 0 && stopemptytier) { return; }
|
---|
330 | if(cta_res[2] != 0 || cta_res[3] != 0)
|
---|
331 | {
|
---|
332 | char tiername[83];
|
---|
333 | uint16_t tier_id = (cta_res[2] << 8) | cta_res[3];
|
---|
334 | // add entitlements to list
|
---|
335 | struct tm timeinfo;
|
---|
336 | memset(&timeinfo, 0, sizeof(struct tm));
|
---|
337 | rev_date_calc_tm(&cta_res[4], &timeinfo, csystem_data->card_baseyear);
|
---|
338 | cs_add_entitlement(reader, reader->caid, b2ll(4, reader->prid[0]), tier_id, 0, 0, mktime(&timeinfo), 4);
|
---|
339 |
|
---|
340 | if(!stopemptytier)
|
---|
341 | {
|
---|
342 | rdr_debug_mask(reader, D_READER, "tier: %04x, tier-number: 0x%02x", tier_id, i);
|
---|
343 | }
|
---|
344 | rdr_log(reader, "tier: %04x, expiry date: %04d/%02d/%02d-%02d:%02d:%02d %s", 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));
|
---|
345 | }
|
---|
346 | }
|
---|
347 | }
|
---|
348 |
|
---|
349 | static int32_t videoguard2_card_init(struct s_reader *reader, ATR *newatr)
|
---|
350 | {
|
---|
351 | get_hist;
|
---|
352 | if((hist_size < 7) || (hist[1] != 0xB0) || (hist[4] != 0xFF) || (hist[5] != 0x4A) || (hist[6] != 0x50))
|
---|
353 | {
|
---|
354 | rdr_debug_mask(reader, D_READER, "failed history check");
|
---|
355 | return ERROR;
|
---|
356 | }
|
---|
357 | rdr_debug_mask(reader, D_READER, "passed history check");
|
---|
358 |
|
---|
359 | get_atr;
|
---|
360 | def_resp;
|
---|
361 |
|
---|
362 | if(!cs_malloc(&reader->csystem_data, sizeof(struct videoguard_data)))
|
---|
363 | { return ERROR; }
|
---|
364 | struct videoguard_data *csystem_data = reader->csystem_data;
|
---|
365 |
|
---|
366 | /* set information on the card stored in reader-videoguard-common.c */
|
---|
367 | set_known_card_info(reader, atr, &atr_size);
|
---|
368 |
|
---|
369 | if((reader->ndsversion != NDS2) &&
|
---|
370 | (((csystem_data->card_system_version != NDS2) && (csystem_data->card_system_version != NDSUNKNOWN)) ||
|
---|
371 | (reader->ndsversion != NDSAUTO)))
|
---|
372 | {
|
---|
373 | /* known ATR and not NDS2
|
---|
374 | or known NDS2 ATR and forced to another NDS version */
|
---|
375 | return ERROR;
|
---|
376 | }
|
---|
377 |
|
---|
378 | rdr_debug_mask(reader, D_READER, "type: %s, baseyear: %i", csystem_data->card_desc, csystem_data->card_baseyear);
|
---|
379 | if(reader->ndsversion == NDS2)
|
---|
380 | {
|
---|
381 | rdr_debug_mask(reader, D_READER, "forced to NDS2");
|
---|
382 | }
|
---|
383 |
|
---|
384 | //a non videoguard2/NDS2 card will fail on read_cmd_len(ins7401)
|
---|
385 | //this way unknown videoguard2/NDS2 cards will also pass this check
|
---|
386 |
|
---|
387 | unsigned char ins7401[5] = { 0xD0, 0x74, 0x01, 0x00, 0x00 };
|
---|
388 | int32_t l;
|
---|
389 | if((l = read_cmd_len(reader, ins7401)) < 0) //not a videoguard2/NDS card or communication error
|
---|
390 | {
|
---|
391 | return ERROR;
|
---|
392 | }
|
---|
393 | ins7401[4] = l;
|
---|
394 | if(!write_cmd_vg(ins7401, NULL) || !status_ok(cta_res + l))
|
---|
395 | {
|
---|
396 | rdr_log(reader, "classD0 ins7401: failed - cmd list not read");
|
---|
397 | return ERROR;
|
---|
398 | }
|
---|
399 |
|
---|
400 | memorize_cmd_table(reader, cta_res, l);
|
---|
401 |
|
---|
402 | unsigned char buff[256];
|
---|
403 |
|
---|
404 | static const unsigned char ins02[5] = { 0xD0, 0x02, 0x00, 0x00, 0x08 };
|
---|
405 | // D0 02 command is not always present in command table but should be supported
|
---|
406 | // on most cards so do not use do_cmd()
|
---|
407 | if(!write_cmd_vg(ins02, NULL) || !status_ok(cta_res + 8))
|
---|
408 | {
|
---|
409 | rdr_log(reader, "Unable to get NDS ROM version.");
|
---|
410 | }
|
---|
411 | else
|
---|
412 | {
|
---|
413 | int i;
|
---|
414 | for(i = 0; i < 8; i++)
|
---|
415 | {
|
---|
416 | if(cta_res[i] <= 0x09)
|
---|
417 | {
|
---|
418 | cta_res[i] = cta_res[i] + 0x30;
|
---|
419 | }
|
---|
420 | else if(!isalnum(cta_res[i]))
|
---|
421 | {
|
---|
422 | cta_res[i] = '*';
|
---|
423 | }
|
---|
424 | }
|
---|
425 | memset(reader->rom, 0, sizeof(reader->rom));
|
---|
426 | memcpy(reader->rom, cta_res, 4);
|
---|
427 | reader->rom[4] = '-';
|
---|
428 | memcpy(reader->rom + 5, cta_res + 4, 4);
|
---|
429 |
|
---|
430 | rdr_log(reader, "Card type: %c%c%c%c", reader->rom[0], reader->rom[1], reader->rom[2], reader->rom[3]);
|
---|
431 | rdr_log(reader, "Rom version: %c%c%c%c", reader->rom[5], reader->rom[6], reader->rom[7], reader->rom[8]);
|
---|
432 | }
|
---|
433 |
|
---|
434 | /* get Vg credit on card */
|
---|
435 | unsigned char ins7404[5] = { 0xD0, 0x74, 0x04, 0x00, 0x00 };
|
---|
436 | l = read_cmd_len(reader, ins7404); //get command len for ins7404
|
---|
437 | ins7404[4] = l;
|
---|
438 | if(!write_cmd_vg(ins7404, NULL) || !status_ok(cta_res + l))
|
---|
439 | {
|
---|
440 | rdr_log(reader, "Unable to get smartcard credit");
|
---|
441 | }
|
---|
442 | else
|
---|
443 | {
|
---|
444 | if (cta_res[0] == 0x15)
|
---|
445 | {
|
---|
446 | reader->VgCredit = ((cta_res[8] << 8) + cta_res[9]) / 100;
|
---|
447 | rdr_log(reader, "Credit available on card: %i ", reader->VgCredit);
|
---|
448 | }
|
---|
449 | }
|
---|
450 |
|
---|
451 | if(reader->ins7E11[0x01])
|
---|
452 | {
|
---|
453 | unsigned char ins742b[5] = { 0xD0, 0x74, 0x2b, 0x00, 0x00 };
|
---|
454 |
|
---|
455 | l = read_cmd_len(reader, ins742b); //get command len for ins742b
|
---|
456 |
|
---|
457 | if(l < 2)
|
---|
458 | {
|
---|
459 | rdr_log(reader, "No TA1 change for this card is possible by ins7E11");
|
---|
460 | }
|
---|
461 | else
|
---|
462 | {
|
---|
463 | ins742b[4] = l;
|
---|
464 | bool ta1ok = 0;
|
---|
465 |
|
---|
466 | if(!write_cmd_vg(ins742b, NULL) || !status_ok(cta_res + ins742b[4])) //get supported TA1 bytes
|
---|
467 | {
|
---|
468 | rdr_log(reader, "classD0 ins742b: failed");
|
---|
469 | return ERROR;
|
---|
470 | }
|
---|
471 | else
|
---|
472 | {
|
---|
473 | int32_t i;
|
---|
474 |
|
---|
475 | for(i = 2; i < l; i++)
|
---|
476 | {
|
---|
477 | if(cta_res[i] == reader->ins7E11[0x00])
|
---|
478 | {
|
---|
479 | ta1ok = 1;
|
---|
480 | break;
|
---|
481 | }
|
---|
482 | }
|
---|
483 | }
|
---|
484 | if(ta1ok == 0)
|
---|
485 | {
|
---|
486 | 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]);
|
---|
487 | }
|
---|
488 | else
|
---|
489 | {
|
---|
490 | static const uint8_t ins7E11[5] = { 0xD0, 0x7E, 0x11, 0x00, 0x01 };
|
---|
491 |
|
---|
492 | reader->ins7e11_fast_reset = 0;
|
---|
493 |
|
---|
494 | l = do_cmd(reader, ins7E11, reader->ins7E11, NULL, cta_res);
|
---|
495 |
|
---|
496 | if(l < 0 || !status_ok(cta_res))
|
---|
497 | {
|
---|
498 | rdr_log(reader, "classD0 ins7E11: failed");
|
---|
499 | return ERROR;
|
---|
500 | }
|
---|
501 | else
|
---|
502 | {
|
---|
503 | unsigned char TA1;
|
---|
504 |
|
---|
505 | if(ATR_GetInterfaceByte(newatr, 1, ATR_INTERFACE_BYTE_TA, &TA1) == ATR_OK)
|
---|
506 | {
|
---|
507 | if(TA1 != reader->ins7E11[0x00])
|
---|
508 | {
|
---|
509 | rdr_log(reader, "classD0 ins7E11: Scheduling card reset for TA1 change from %02X to %02X", TA1, reader->ins7E11[0x00]);
|
---|
510 | reader->ins7e11_fast_reset = 1;
|
---|
511 | #ifdef WITH_COOLAPI
|
---|
512 | if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART || reader->typ == R_INTERNAL)
|
---|
513 | {
|
---|
514 | #else
|
---|
515 | if(reader->typ == R_MOUSE || reader->typ == R_SC8in1 || reader->typ == R_SMART)
|
---|
516 | {
|
---|
517 | #endif
|
---|
518 | add_job(reader->client, ACTION_READER_RESET_FAST, NULL, 0);
|
---|
519 | }
|
---|
520 | else
|
---|
521 | {
|
---|
522 | add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
|
---|
523 | }
|
---|
524 | return OK; // Skip the rest of the init since the card will be reset anyway
|
---|
525 | }
|
---|
526 | }
|
---|
527 | }
|
---|
528 | }
|
---|
529 | }
|
---|
530 | }
|
---|
531 | static const unsigned char ins7416[5] = { 0xD0, 0x74, 0x16, 0x00, 0x00 };
|
---|
532 |
|
---|
533 | if(do_cmd(reader, ins7416, NULL, NULL, cta_res) < 0)
|
---|
534 | {
|
---|
535 | rdr_log(reader, "classD0 ins7416: failed");
|
---|
536 | return ERROR;
|
---|
537 | }
|
---|
538 | unsigned char boxID [4];
|
---|
539 |
|
---|
540 | if(reader->boxid > 0)
|
---|
541 | {
|
---|
542 | /* the boxid is specified in the config */
|
---|
543 | int32_t i;
|
---|
544 | for(i = 0; i < 4; i++)
|
---|
545 | {
|
---|
546 | boxID[i] = (reader->boxid >> (8 * (3 - i))) % 0x100;
|
---|
547 | }
|
---|
548 | }
|
---|
549 | else
|
---|
550 | {
|
---|
551 | unsigned char ins36[5] = { 0xD0, 0x36, 0x00, 0x00, 0x00 };
|
---|
552 | static const unsigned char ins5e[5] = { 0xD0, 0x5E, 0x00, 0x0C, 0x02 };
|
---|
553 |
|
---|
554 | /* we can try to get the boxid from the card */
|
---|
555 | int32_t boxidOK = 0;
|
---|
556 | l = read_cmd_len(reader, ins36);
|
---|
557 | if(l > 0)
|
---|
558 | {
|
---|
559 | ins36[4] = l;
|
---|
560 | }
|
---|
561 | else if(cmd_exists(reader, ins5e))
|
---|
562 | {
|
---|
563 | if(!write_cmd_vg(ins5e, NULL) || !status_ok(cta_res + 2))
|
---|
564 | {
|
---|
565 | rdr_log(reader, "classD0 ins5e: failed");
|
---|
566 | }
|
---|
567 | else
|
---|
568 | {
|
---|
569 | ins36[3] = cta_res[0];
|
---|
570 | ins36[4] = cta_res[1];
|
---|
571 | }
|
---|
572 | }
|
---|
573 | l = ins36[4];
|
---|
574 | if(!write_cmd_vg(ins36, NULL) || !status_ok(cta_res + l))
|
---|
575 | {
|
---|
576 | rdr_log(reader, "classD0 ins36: failed");
|
---|
577 | return ERROR;
|
---|
578 | }
|
---|
579 | memcpy(buff, ins36, 5);
|
---|
580 | memcpy(buff + 5, cta_res, l);
|
---|
581 | memcpy(buff + 5 + l, cta_res + l, 2);
|
---|
582 | if(l < 13)
|
---|
583 | { rdr_log(reader, "classD0 ins36: answer too int16"); }
|
---|
584 | else if(buff[7] > 0x0F)
|
---|
585 | { rdr_log(reader, "classD0 ins36: encrypted - can't parse"); }
|
---|
586 | else
|
---|
587 | {
|
---|
588 | /* skipping the initial fixed fields: cmdecho (4) + length (1) + encr/rev++ (4) */
|
---|
589 | int32_t i = 9;
|
---|
590 | int32_t gotUA = 0;
|
---|
591 | while(i < l)
|
---|
592 | {
|
---|
593 | if(!gotUA && buff[i] < 0xF0) /* then we guess that the next 4 bytes is the UA */
|
---|
594 | {
|
---|
595 | gotUA = 1;
|
---|
596 | i += 4;
|
---|
597 | }
|
---|
598 | else switch(buff[i]) /* object length vary depending on type */
|
---|
599 | {
|
---|
600 | case 0x00: /* padding */
|
---|
601 | i += 1;
|
---|
602 | break;
|
---|
603 | case 0xEF: /* card status */
|
---|
604 | i += 3;
|
---|
605 | break;
|
---|
606 | case 0xD1:
|
---|
607 | i += 4;
|
---|
608 | break;
|
---|
609 | case 0xDF: /* next server contact */
|
---|
610 | i += 5;
|
---|
611 | break;
|
---|
612 | case 0xF3: /* boxID */
|
---|
613 | memcpy(boxID, buff + i + 1, sizeof(boxID));
|
---|
614 | boxidOK = 1;
|
---|
615 | i += 5;
|
---|
616 | break;
|
---|
617 | case 0xF6:
|
---|
618 | i += 6;
|
---|
619 | break;
|
---|
620 | case 0x01: /* date & time */
|
---|
621 | i += 7;
|
---|
622 | break;
|
---|
623 | case 0xFA:
|
---|
624 | i += 9;
|
---|
625 | break;
|
---|
626 | case 0x5E:
|
---|
627 | case 0x67: /* signature */
|
---|
628 | case 0xDE:
|
---|
629 | case 0xE2:
|
---|
630 | case 0xE9: /* tier dates */
|
---|
631 | case 0xF8: /* Old PPV Event Record */
|
---|
632 | case 0xFD:
|
---|
633 | i += buff[i + 1] + 2; /* skip length + 2 bytes (type and length) */
|
---|
634 | break;
|
---|
635 | default: /* default to assume a length byte */
|
---|
636 | rdr_log(reader, "classD0 ins36: returned unknown type=0x%02X - parsing may fail", buff[i]);
|
---|
637 | i += buff[i + 1] + 2;
|
---|
638 | }
|
---|
639 | }
|
---|
640 | }
|
---|
641 |
|
---|
642 | if(!boxidOK)
|
---|
643 | {
|
---|
644 | rdr_log(reader, "no boxID available");
|
---|
645 | return ERROR;
|
---|
646 | }
|
---|
647 | }
|
---|
648 |
|
---|
649 | unsigned char ins4C[5] = { 0xD0, 0x4C, 0x00, 0x00, 0x09 };
|
---|
650 | unsigned char len4c = 0, mode = 0;
|
---|
651 | unsigned char payload4C[0xF] = { 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
---|
652 | if(cmd_table_get_info(reader, ins4C, &len4c, &mode))
|
---|
653 | {
|
---|
654 | ins4C[4] = len4c; //don't mind if payload is > of ins len, it will be cutted after write_cmd_vg()
|
---|
655 | if(len4c > 9)
|
---|
656 | {
|
---|
657 | payload4C[8] = 0x44; //value taken from v14 boot log
|
---|
658 | rdr_log(reader, "Extended 4C detected");
|
---|
659 | }
|
---|
660 | }
|
---|
661 |
|
---|
662 | memcpy(payload4C, boxID, 4);
|
---|
663 | if(!write_cmd_vg(ins4C, payload4C) || !status_ok(cta_res ))
|
---|
664 | {
|
---|
665 | rdr_log(reader, "classD0 ins4C: failed - sending boxid failed");
|
---|
666 | return ERROR;
|
---|
667 | }
|
---|
668 |
|
---|
669 | //int16_t int32_t SWIRDstatus = cta_res[1];
|
---|
670 | static const unsigned char ins58[5] = { 0xD0, 0x58, 0x00, 0x00, 0x00 };
|
---|
671 | l = do_cmd(reader, ins58, NULL, NULL, cta_res);
|
---|
672 | if(l < 0)
|
---|
673 | {
|
---|
674 | rdr_log(reader, "classD0 ins58: failed");
|
---|
675 | return ERROR;
|
---|
676 | }
|
---|
677 | memset(reader->hexserial, 0, 8);
|
---|
678 | memcpy(reader->hexserial + 2, cta_res + 3, 4);
|
---|
679 | memcpy(reader->sa, cta_res + 3, 3);
|
---|
680 | reader->caid = cta_res[24] * 0x100 + cta_res[25];
|
---|
681 | memset(reader->VgRegionC, 0, 8);
|
---|
682 | memcpy(reader->VgRegionC, cta_res + 60, 8);
|
---|
683 | 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]);
|
---|
684 |
|
---|
685 | /* we have one provider, 0x0000 */
|
---|
686 | reader->nprov = 1;
|
---|
687 | memset(reader->prid, 0x00, sizeof(reader->prid));
|
---|
688 |
|
---|
689 | /*
|
---|
690 | rdr_log(reader, "INS58 : Fuse byte=0x%02X, IRDStatus=0x%02X", cta_res[2],SWIRDstatus);
|
---|
691 | if (SWIRDstatus==4) {
|
---|
692 | // If swMarriage=4, not married then exchange for BC Key
|
---|
693 | rdr_log(reader, "Card not married, exchange for BC Keys");
|
---|
694 | */
|
---|
695 |
|
---|
696 | cCamCryptVG_SetSeed(reader);
|
---|
697 |
|
---|
698 | static const unsigned char insB4[5] = { 0xD0, 0xB4, 0x00, 0x00, 0x40 };
|
---|
699 | unsigned char tbuff[64];
|
---|
700 | cCamCryptVG_GetCamKey(reader, tbuff);
|
---|
701 | l = do_cmd(reader, insB4, tbuff, NULL, cta_res);
|
---|
702 | if(l < 0 || !status_ok(cta_res))
|
---|
703 | {
|
---|
704 | rdr_log(reader, "classD0 insB4: failed");
|
---|
705 | return ERROR;
|
---|
706 | }
|
---|
707 |
|
---|
708 | static const unsigned char insBC[5] = { 0xD0, 0xBC, 0x00, 0x00, 0x00 };
|
---|
709 | l = do_cmd(reader, insBC, NULL, NULL, cta_res);
|
---|
710 | if(l < 0)
|
---|
711 | {
|
---|
712 | rdr_log(reader, "classD0 insBC: failed");
|
---|
713 | return ERROR;
|
---|
714 | }
|
---|
715 |
|
---|
716 | // Class D1/D3 instructions only work after this point
|
---|
717 |
|
---|
718 | static const unsigned char insBE[5] = { 0xD3, 0xBE, 0x00, 0x00, 0x00 };
|
---|
719 | l = do_cmd(reader, insBE, NULL, NULL, cta_res);
|
---|
720 | if(l < 0)
|
---|
721 | {
|
---|
722 | rdr_log(reader, "classD3 insBE: failed");
|
---|
723 | return ERROR;
|
---|
724 | }
|
---|
725 |
|
---|
726 | static const unsigned char ins58a[5] = { 0xD1, 0x58, 0x00, 0x00, 0x00 };
|
---|
727 | l = do_cmd(reader, ins58a, NULL, NULL, cta_res);
|
---|
728 | if(l < 0)
|
---|
729 | {
|
---|
730 | rdr_log(reader, "classD1 ins58: failed");
|
---|
731 | return ERROR;
|
---|
732 | }
|
---|
733 | /*new ins74 present at boot*/
|
---|
734 |
|
---|
735 | static const unsigned char ins7423[5] = { 0xD1, 0x74, 0x23, 0x00, 0x00 };
|
---|
736 | if(do_cmd(reader, ins7423, NULL, NULL, cta_res) < 0)
|
---|
737 | {
|
---|
738 | rdr_log(reader, "classD1 ins7423: failed");
|
---|
739 | }
|
---|
740 |
|
---|
741 | static const unsigned char ins742A[5] = { 0xD1, 0x74, 0x2A, 0x00, 0x00 };
|
---|
742 | if(do_cmd(reader, ins742A, NULL, NULL, cta_res) < 0)
|
---|
743 | {
|
---|
744 | rdr_log(reader, "classD1 ins742A: failed");
|
---|
745 | }
|
---|
746 |
|
---|
747 | static const unsigned char ins741B[5] = { 0xD1, 0x74, 0x1B, 0x00, 0x00 };
|
---|
748 | if(do_cmd(reader, ins741B, NULL, NULL, cta_res) < 0)
|
---|
749 | {
|
---|
750 | rdr_log(reader, "classD1 ins741B: failed");
|
---|
751 | }
|
---|
752 |
|
---|
753 | static const unsigned char ins4Ca[5] = { 0xD1, 0x4C, 0x00, 0x00, 0x00 };
|
---|
754 | unsigned char ins741C[5] = { 0xD1, 0x74, 0x1C, 0x00, 0x00 };
|
---|
755 | if(len4c > 9)
|
---|
756 | {
|
---|
757 | if((l = read_cmd_len(reader, ins741C)) < 0) // We need to know the exact len
|
---|
758 | {
|
---|
759 | return ERROR;
|
---|
760 | }
|
---|
761 | ins741C[4] = l;
|
---|
762 | if(do_cmd(reader, ins741C, NULL, NULL, cta_res) < 0) //from log this payload is copied on 4c
|
---|
763 | {
|
---|
764 | rdr_log(reader, "classD1 ins741C: failed");
|
---|
765 | }
|
---|
766 | else
|
---|
767 | {
|
---|
768 | if(l > 8) //if payload4c is length 0xF, we can't copy over more than 8 bytes in the next memcopy
|
---|
769 | {
|
---|
770 | l = 8;
|
---|
771 | }
|
---|
772 | memcpy(payload4C + 8, cta_res, l);
|
---|
773 | }
|
---|
774 | }
|
---|
775 | l = do_cmd(reader, ins4Ca, payload4C, NULL, cta_res);
|
---|
776 | if(l < 0 || !status_ok(cta_res))
|
---|
777 | {
|
---|
778 | rdr_log(reader, "classD1 ins4Ca: failed");
|
---|
779 | return ERROR;
|
---|
780 | }
|
---|
781 |
|
---|
782 | if(reader->ins7E[0x1A])
|
---|
783 | {
|
---|
784 | static const uint8_t ins7E[5] = { 0xD1, 0x7E, 0x10, 0x00, 0x1A };
|
---|
785 | l = do_cmd(reader, ins7E, reader->ins7E, NULL, cta_res);
|
---|
786 | if(l < 0 || !status_ok(cta_res))
|
---|
787 | {
|
---|
788 | rdr_log(reader, "classD1 ins7E: failed");
|
---|
789 | return ERROR;
|
---|
790 | }
|
---|
791 | }
|
---|
792 | /* get PIN settings */
|
---|
793 | static const unsigned char ins7411[5] = { 0xD1, 0x74, 0x11, 0x00, 0x00 };
|
---|
794 | unsigned char payload2e4[4];
|
---|
795 | if(do_cmd(reader, ins7411, NULL, NULL, cta_res) < 0)
|
---|
796 | {
|
---|
797 | rdr_log(reader, "classD1 ins7411: unable to get PIN");
|
---|
798 | return ERROR;
|
---|
799 | }
|
---|
800 | else
|
---|
801 | {
|
---|
802 | memset(payload2e4, 0, 4);
|
---|
803 | memcpy(payload2e4, cta_res + 2, 4);
|
---|
804 | reader->VgPin = (cta_res[4] << 8) + cta_res[5];
|
---|
805 | rdr_log(reader, "Pincode read: %i", reader->VgPin);
|
---|
806 | }
|
---|
807 |
|
---|
808 | /* get PCB(content rating) settings */
|
---|
809 | static const unsigned char ins74e[5] = {0xD1, 0x74, 0x0E, 0x00, 0x00};
|
---|
810 | if(do_cmd(reader, ins74e, NULL, NULL, cta_res) < 0)
|
---|
811 | {
|
---|
812 | rdr_log(reader, "classD1 ins74e: failed to get PCB settings");
|
---|
813 | }
|
---|
814 | else
|
---|
815 | {
|
---|
816 | rdr_log(reader, "PCB settings: %X %X %X %X", cta_res[2], cta_res[3], cta_res[4], cta_res[5]);
|
---|
817 | }
|
---|
818 |
|
---|
819 | /* send PIN */
|
---|
820 | static const unsigned char ins2epin[5] = {0xD1, 0x2E, 0x04, 0x00, 0x04};
|
---|
821 | if(cfg.ulparent)
|
---|
822 | {
|
---|
823 | l = do_cmd(reader, ins2epin, payload2e4, NULL, cta_res);
|
---|
824 | if(l < 0 || !status_ok(cta_res))
|
---|
825 | {
|
---|
826 | rdr_log(reader, "classD1 ins2E: failed");
|
---|
827 | rdr_log(reader, "Cannot disable parental control");
|
---|
828 | return ERROR;
|
---|
829 | }
|
---|
830 | else
|
---|
831 | {
|
---|
832 | rdr_log(reader, "Parental control disabled");
|
---|
833 | }
|
---|
834 | }
|
---|
835 | /* send check control for pin, needed on some cards */
|
---|
836 | /* the presence and the value of payloads is provider's dependent*/
|
---|
837 | if(reader->ins2e06[4])
|
---|
838 | {
|
---|
839 | static const unsigned char ins2e06[5] = { 0xD1, 0x2E, 0x06, 0x00, 0x04 };
|
---|
840 | l = do_cmd(reader, ins2e06, reader->ins2e06, NULL, cta_res);
|
---|
841 | if(l < 0 || !status_ok(cta_res))
|
---|
842 | {
|
---|
843 | rdr_log(reader, "classD1 ins2E: failed");
|
---|
844 | return ERROR;
|
---|
845 | }
|
---|
846 | }
|
---|
847 |
|
---|
848 | // fix for 09ac cards
|
---|
849 | unsigned char dimeno_magic[0x10] = {0xF9, 0xFB, 0xCD, 0x5A, 0x76, 0xB5, 0xC4, 0x5C, 0xC8, 0x2E, 0x1D, 0xE1, 0xCC, 0x5B, 0x6B, 0x02};
|
---|
850 | int32_t a;
|
---|
851 | for(a = 0; a < 4; a++)
|
---|
852 | { dimeno_magic[a] = dimeno_magic[a] ^ boxID[a]; }
|
---|
853 | AES_set_decrypt_key(dimeno_magic, 128, &(csystem_data->astrokey));
|
---|
854 |
|
---|
855 | rdr_log(reader, "type: %s, caid: %04X",
|
---|
856 | csystem_data->card_desc,
|
---|
857 | reader->caid);
|
---|
858 | rdr_log_sensitive(reader, "serial: {%02X%02X%02X%02X}, BoxID: {%02X%02X%02X%02X}, baseyear: %i",
|
---|
859 | reader->hexserial[2], reader->hexserial[3], reader->hexserial[4], reader->hexserial[5],
|
---|
860 | boxID[0], boxID[1], boxID[2], boxID[3],
|
---|
861 | csystem_data->card_baseyear);
|
---|
862 | rdr_log(reader, "ready for requests");
|
---|
863 |
|
---|
864 | return OK;
|
---|
865 | }
|
---|
866 |
|
---|
867 | static int32_t videoguard2_do_ecm(struct s_reader *reader, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
868 | {
|
---|
869 | unsigned char cta_res[CTA_RES_LEN];
|
---|
870 | static const char valid_ecm[] = { 0x00, 0x00, 0x01 };
|
---|
871 | unsigned char ins40[5] = { 0xD1, 0x40, 0x00, 0x80, 0xFF };
|
---|
872 | static const unsigned char ins54[5] = { 0xD3, 0x54, 0x00, 0x00, 0x00};
|
---|
873 | int32_t posECMpart2 = er->ecm[6] + 7;
|
---|
874 | int32_t lenECMpart2 = er->ecm[posECMpart2] + 1;
|
---|
875 | unsigned char tbuff[264], rbuff[264];
|
---|
876 | tbuff[0] = 0;
|
---|
877 |
|
---|
878 | 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
|
---|
879 |
|
---|
880 | if(memcmp(&(er->ecm[3]), valid_ecm, sizeof(valid_ecm) != 0))
|
---|
881 | {
|
---|
882 | rdr_log(reader, "Not a valid ecm");
|
---|
883 | return ERROR;
|
---|
884 | }
|
---|
885 |
|
---|
886 | memcpy(tbuff + 1, er->ecm + posECMpart2 + 1, lenECMpart2 - 1);
|
---|
887 |
|
---|
888 | /*
|
---|
889 | //log parental lock byte
|
---|
890 | int32_t j;
|
---|
891 | for (j = posECMpart2+1; j < lenECMpart2+posECMpart2+1-4; j++){
|
---|
892 | if (er->ecm[j] == 0x02 && er->ecm[j+3] == 0x02) {
|
---|
893 | 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]);
|
---|
894 | break;
|
---|
895 | }
|
---|
896 | }
|
---|
897 |
|
---|
898 | //log tiers
|
---|
899 | int32_t k;
|
---|
900 | char tiername[83];
|
---|
901 | for (k = posECMpart2+1; k < lenECMpart2+posECMpart2+1-4; k++){
|
---|
902 | if (er->ecm[k] == 0x03 && er->ecm[k+3] == 0x80) {
|
---|
903 | uint16_t vtier_id = (er->ecm[k+1] << 8) | er->ecm[k+2];
|
---|
904 | get_tiername(vtier_id, reader->caid, tiername);
|
---|
905 | rdr_log(reader, "valid tier: %04x %s",vtier_id, tiername);
|
---|
906 | }
|
---|
907 | }
|
---|
908 | */
|
---|
909 |
|
---|
910 | int32_t new_len = lenECMpart2;
|
---|
911 | if(reader->fix_9993 && reader->caid == 0x919 && tbuff[1] == 0x7F)
|
---|
912 | {
|
---|
913 | tbuff[1] = 0x47;
|
---|
914 | tbuff[2] = 0x08;
|
---|
915 | memmove(tbuff + 11, tbuff + 13, new_len - 11);
|
---|
916 | new_len -= 2;
|
---|
917 | }
|
---|
918 | ins40[4] = new_len;
|
---|
919 | int32_t l;
|
---|
920 |
|
---|
921 | l = do_cmd(reader, ins40, tbuff, NULL, cta_res);
|
---|
922 | if(l < 0 || !status_ok(cta_res))
|
---|
923 | {
|
---|
924 | rdr_log(reader, "classD1 ins40: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
|
---|
925 | rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
|
---|
926 | add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
|
---|
927 | return ERROR;
|
---|
928 | }
|
---|
929 | else
|
---|
930 | {
|
---|
931 | l = do_cmd(reader, ins54, NULL, rbuff, cta_res);
|
---|
932 | if(l < 0 || !status_ok(cta_res + l))
|
---|
933 | {
|
---|
934 | rdr_log(reader, "classD3 ins54: (%d) status not ok %02x %02x", l, cta_res[0], cta_res[1]);
|
---|
935 | rdr_log(reader, "The card is not answering correctly! Restarting reader for safety");
|
---|
936 | add_job(reader->client, ACTION_READER_RESTART, NULL, 0);
|
---|
937 | return ERROR;
|
---|
938 | }
|
---|
939 | else
|
---|
940 | {
|
---|
941 |
|
---|
942 | // Log decrypted INS54
|
---|
943 | rdr_ddump_mask(reader, D_READER, rbuff, 5, "INS54:");
|
---|
944 | rdr_ddump_mask(reader, D_READER, rbuff + 5, rbuff[4], "Decrypted payload");
|
---|
945 |
|
---|
946 | if(!cw_is_valid(rbuff + 5)) //sky cards report 90 00 = ok but send cw = 00 when channel not subscribed
|
---|
947 | {
|
---|
948 | rdr_log(reader, "classD3 ins54: status 90 00 = ok but cw=00 -> channel not subscribed ");
|
---|
949 | return ERROR;
|
---|
950 | }
|
---|
951 |
|
---|
952 | // copy cw1 in place
|
---|
953 | memcpy(ea->cw + 0, rbuff + 5, 8);
|
---|
954 |
|
---|
955 | // process cw2
|
---|
956 | unsigned char *payload = rbuff + 5;
|
---|
957 | int32_t payloadLen = rbuff[4];
|
---|
958 | int32_t ind = 8 + 6; // +8 for CW1, +6 for counter(?)
|
---|
959 |
|
---|
960 | while(ind < payloadLen)
|
---|
961 | {
|
---|
962 | switch(payload[ind])
|
---|
963 | {
|
---|
964 | case 0x25: // CW2
|
---|
965 | //cs_dump (payload + ind, payload[ind+1]+2, "INS54 - CW2");
|
---|
966 | memcpy(ea->cw + 8, &payload[ind + 3], 8);
|
---|
967 | ind += payload[ind + 1] + 2;
|
---|
968 | break;
|
---|
969 |
|
---|
970 | default:
|
---|
971 | //cs_dump (payload + ind, payload[ind+1]+2, "INS54");
|
---|
972 | ind += payload[ind + 1] + 2;
|
---|
973 | break;
|
---|
974 | }
|
---|
975 | }
|
---|
976 |
|
---|
977 | if(new_len != lenECMpart2)
|
---|
978 | {
|
---|
979 | memcpy(ea->cw, ea->cw + 8, 8);
|
---|
980 | memset(ea->cw + 8, 0, 8);
|
---|
981 | }
|
---|
982 | // fix for 09ac cards
|
---|
983 | dimeno_PostProcess_Decrypt(reader, rbuff, ea->cw);
|
---|
984 |
|
---|
985 | //test for postprocessing marker
|
---|
986 | int32_t posB0 = -1;
|
---|
987 | int32_t i;
|
---|
988 | for(i = 6; i < posECMpart2; i++)
|
---|
989 | {
|
---|
990 | 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)))
|
---|
991 | {
|
---|
992 | posB0 = i;
|
---|
993 | break;
|
---|
994 | }
|
---|
995 | }
|
---|
996 | if(posB0 != -1)
|
---|
997 | {
|
---|
998 | do_post_dw_hash(reader, ea->cw + 0, &er->ecm[posB0 - 2]);
|
---|
999 | do_post_dw_hash(reader, ea->cw + 8, &er->ecm[posB0 - 2]);
|
---|
1000 | }
|
---|
1001 |
|
---|
1002 | if(reader->caid == 0x0907) //quickfix: cw2 is not a valid cw, something went wrong before
|
---|
1003 | {
|
---|
1004 | memset(ea->cw + 8, 0, 8);
|
---|
1005 | if(er->ecm[0] & 1)
|
---|
1006 | {
|
---|
1007 | memcpy(ea->cw + 8, ea->cw, 8);
|
---|
1008 | memset(ea->cw, 0, 8);
|
---|
1009 | }
|
---|
1010 | }
|
---|
1011 | else
|
---|
1012 | {
|
---|
1013 | if(er->ecm[0] & 1)
|
---|
1014 | {
|
---|
1015 | unsigned char tmpcw[8];
|
---|
1016 | memcpy(tmpcw, ea->cw + 8, 8);
|
---|
1017 | memcpy(ea->cw + 8, ea->cw + 0, 8);
|
---|
1018 | memcpy(ea->cw + 0, tmpcw, 8);
|
---|
1019 | }
|
---|
1020 | }
|
---|
1021 |
|
---|
1022 | return OK;
|
---|
1023 | }
|
---|
1024 | }
|
---|
1025 | }
|
---|
1026 |
|
---|
1027 | static int32_t videoguard2_do_emm(struct s_reader *reader, EMM_PACKET *ep)
|
---|
1028 | {
|
---|
1029 | return videoguard_do_emm(reader, ep, 0xD1, vg2_read_tiers, do_cmd);
|
---|
1030 | }
|
---|
1031 |
|
---|
1032 | static int32_t videoguard2_card_info(struct s_reader *reader)
|
---|
1033 | {
|
---|
1034 | /* info is displayed in init, or when processing info */
|
---|
1035 | struct videoguard_data *csystem_data = reader->csystem_data;
|
---|
1036 | rdr_log(reader, "card detected");
|
---|
1037 | rdr_log(reader, "type: %s", csystem_data->card_desc);
|
---|
1038 | if(reader->ins7e11_fast_reset != 1)
|
---|
1039 | {
|
---|
1040 | vg2_read_tiers(reader);
|
---|
1041 | }
|
---|
1042 | return OK;
|
---|
1043 | }
|
---|
1044 |
|
---|
1045 | void reader_videoguard2(struct s_cardsystem *ph)
|
---|
1046 | {
|
---|
1047 | ph->do_emm = videoguard2_do_emm;
|
---|
1048 | ph->do_ecm = videoguard2_do_ecm;
|
---|
1049 | ph->card_info = videoguard2_card_info;
|
---|
1050 | ph->card_init = videoguard2_card_init;
|
---|
1051 | ph->get_emm_type = videoguard_get_emm_type;
|
---|
1052 | ph->get_emm_filter = videoguard_get_emm_filter;
|
---|
1053 | ph->caids[0] = 0x09;
|
---|
1054 | ph->desc = "videoguard2";
|
---|
1055 | }
|
---|
1056 | #endif
|
---|
1057 |
|
---|