1 | //
|
---|
2 | // Common videoguard functions.
|
---|
3 | //
|
---|
4 | #include "globals.h"
|
---|
5 | #ifdef READER_VIDEOGUARD
|
---|
6 | #include "reader-common.h"
|
---|
7 | #include "reader-videoguard-common.h"
|
---|
8 |
|
---|
9 | #define VG_EMMTYPE_MASK 0xC0
|
---|
10 | #define VG_EMMTYPE_G 0
|
---|
11 | #define VG_EMMTYPE_U 1
|
---|
12 | #define VG_EMMTYPE_S 2
|
---|
13 |
|
---|
14 | typedef struct mailmsg_s
|
---|
15 | {
|
---|
16 | uint16_t caid;
|
---|
17 | uint32_t serial;
|
---|
18 | uint16_t date;
|
---|
19 | uint16_t id;
|
---|
20 | uint8_t nsubs;
|
---|
21 | uint16_t len;
|
---|
22 | uint8_t mask;
|
---|
23 | uint8_t written;
|
---|
24 | char *message;
|
---|
25 | char *subject;
|
---|
26 | } MAILMSG;
|
---|
27 |
|
---|
28 | LLIST *vg_msgs = 0;
|
---|
29 |
|
---|
30 | void set_known_card_info(struct s_reader * reader, const unsigned char * atr, const uint32_t *atr_size)
|
---|
31 | {
|
---|
32 | /* Set to sensible default values */
|
---|
33 | reader->card_baseyear = 1997;
|
---|
34 | reader->card_tierstart = 0;
|
---|
35 | reader->card_system_version = NDSUNKNOWN;
|
---|
36 | reader->card_desc = "VideoGuard Unknown Card";
|
---|
37 |
|
---|
38 | NDS_ATR_ENTRY nds_atr_table[]={ // {atr}, atr len, base year, tier start, nds version, description
|
---|
39 | /* known NDS1 atrs */
|
---|
40 | {{ 0x3F, 0x78, 0x13, 0x25, 0x04, 0x40, 0xB0, 0x09, 0x4A, 0x50, 0x01, 0x4E, 0x5A },
|
---|
41 | 13, 1992, 0, NDS1, "VideoGuard Sky New Zealand (0969)"}, //160E
|
---|
42 | {{ 0x3F, 0x78, 0x12, 0x25, 0x01, 0x40, 0xB0, 0x14, 0x4A, 0x50, 0x01, 0x53, 0x44 },
|
---|
43 | 13, 1997, 0, NDS1, "VideoGuard StarTV India (caid unknown)"}, //105.5E
|
---|
44 | /* known NDS1+ atrs */
|
---|
45 | {{ 0x3F, 0x7F, 0x13, 0x25, 0x04, 0x33, 0xB0, 0x02, 0x69, 0xFF, 0x4A, 0x50, 0xE0, 0x00, 0x00, 0x54,
|
---|
46 | 0x42, 0x00, 0x00, 0x00 },
|
---|
47 | 20, 1997, 0, NDS12, "VideoGuard China (0988)"},
|
---|
48 | {{ 0x3F, 0x78, 0x13, 0x25, 0x03, 0x40, 0xB0, 0x20, 0xFF, 0xFF, 0x4A, 0x50, 0x00 },
|
---|
49 | 13, 1997, 0, NDS12, "VideoGuard DirecTV"},
|
---|
50 | /* known NDS2 atrs */
|
---|
51 | {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x33, 0xB0, 0x08, 0xFF, 0xFF, 0x4A, 0x50, 0x90,
|
---|
52 | 0x00, 0x00, 0x47, 0x4C, 0x01 },
|
---|
53 | 21, 2004, 0, NDS2, "VideoGuard Sky Brasil GL39 (0907)"},
|
---|
54 | {{ 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x46,
|
---|
55 | 0x44, 0x01, 0x00, 0x00 },
|
---|
56 | 20, 2000, 0, NDS2, "VideoGuard Foxtel Australia (090B)"}, //156E
|
---|
57 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x0E, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
58 | 0x00, 0x49, 0x54, 0x02, 0x00, 0x00 },
|
---|
59 | 22, 1997, 0, NDS2, "VideoGuard Sky Italia (0919)"},
|
---|
60 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
61 | 0x00, 0x5A, 0x4A, 0x01, 0x00, 0x00 },
|
---|
62 | 22, 2004, 0, NDS2, "VideoGuard Dolce Romania (092F)"},
|
---|
63 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x54, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
64 | 0x00, 0x41, 0x55, 0x01, 0x00, 0x00 },
|
---|
65 | 22, 1997, 0, NDS2, "VideoGuard OnoCable Espana (093A)"},
|
---|
66 | {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x33, 0xB0, 0x13, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
|
---|
67 | 0x80, 0x00, 0x49, 0x54, 0x03 },
|
---|
68 | 21, 1997, 0, NDS2, "VideoGuard Sky Italia (093B)"},
|
---|
69 | {{ 0x3F, 0x7D, 0x11, 0x25, 0x02, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0, 0x80, 0x00, 0x56,
|
---|
70 | 0x54, 0x03 },
|
---|
71 | 18, 2000, 0, NDS2, "VideoGuard Viasat (093E)"},
|
---|
72 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x54, 0xB0, 0x03, 0xFF, 0xFF, 0x4A, 0x50, 0x80,
|
---|
73 | 0x00, 0x00, 0x00, 0x00, 0x47, 0x4C, 0x05 },
|
---|
74 | 23, 2009, 0, NDS2, "VideoGuard Sky Brasil GL54 (0943)"},
|
---|
75 | {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x00, 0x0F, 0x33, 0xB0, 0x0F, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
|
---|
76 | 0x00, 0x00, 0x53, 0x59, 0x02 },
|
---|
77 | 21, 1997, 0, NDS2, "VideoGuard BSkyB (0963)"},
|
---|
78 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
79 | 0x00, 0x4E, 0x5A, 0x01, 0x00, 0x00 },
|
---|
80 | 22, 1992, 0, NDS2, "VideoGuard Sky New Zealand (096A)"}, //160E
|
---|
81 | {{ 0x3F, 0xFD, 0x11, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
82 | 0x80, 0x00, 0x46, 0x44, 0x03 },
|
---|
83 | 21, 2000, 0, NDS2, "VideoGuard Foxtel Australia (096C)"}, //156E
|
---|
84 | {{ 0x3F, 0xFF, 0x11, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
85 | 0x00, 0x41, 0x5A, 0x01, 0x00, 0x11 },
|
---|
86 | 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC)"},
|
---|
87 | {{ 0x3F, 0xFF, 0x12, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
88 | 0x00, 0x41, 0x5A, 0x01, 0x00, 0x12 },
|
---|
89 | 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC) FastMode"},
|
---|
90 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
91 | 0x00, 0x41, 0x5A, 0x01, 0x00, 0x13 },
|
---|
92 | 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC) FastMode"},
|
---|
93 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
94 | 0x00, 0x41, 0x5A, 0x01, 0x00, 0x14 },
|
---|
95 | 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC) FastMode"},
|
---|
96 | {{ 0x3F, 0xFF, 0x15, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x06, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
97 | 0x00, 0x41, 0x5A, 0x01, 0x00, 0x15 },
|
---|
98 | 22, 2004, 50, NDS2, "VideoGuard Astro Malaysia (09AC) FastMode"},
|
---|
99 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
|
---|
100 | 0x00, 0x58, 0x34, 0x01, 0x00, 0x14 },
|
---|
101 | 22, 1997, 0, NDS2, "VideoGuard Cingal Philippines (09B4)"},
|
---|
102 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x02, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
|
---|
103 | 0x00, 0x58, 0x38, 0x01, 0x00, 0x14 },
|
---|
104 | 22, 1997, 0, NDS2, "VideoGuard TopTV (09B8)"},
|
---|
105 | {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x54, 0xB0, 0x04, 0x69, 0xFF, 0x4A, 0x50, 0xD0,
|
---|
106 | 0x80, 0x00, 0x49, 0x54, 0x03 },
|
---|
107 | 21, 1997, 0, NDS2, "VideoGuard Sky Italia (09CD)"},
|
---|
108 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x50, 0x00,
|
---|
109 | 0x00, 0x47, 0x54, 0x01, 0x00, 0x00 },
|
---|
110 | 22, 1997, 0, NDS2, "VideoGuard YES DBS Israel"},
|
---|
111 | {{ 0x3F, 0x7F, 0x11, 0x25, 0x03, 0x33, 0xB0, 0x09, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00, 0x00, 0x56,
|
---|
112 | 0x54, 0x01, 0x00, 0x00 },
|
---|
113 | 20, 2000, 0, NDS2, "VideoGuard Viasat Scandinavia"},
|
---|
114 | {{ 0x3F, 0xFF, 0x11, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
115 | 0x00, 0x50, 0x31, 0x01, 0x00, 0x11 },
|
---|
116 | 22, 2004, 0, NDS2, "VideoGuard Sky Germany (09C4)"},
|
---|
117 | {{ 0x3F, 0xFF, 0x12, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
118 | 0x00, 0x50, 0x31, 0x01, 0x00, 0x12 },
|
---|
119 | 22, 2004, 0, NDS2, "VideoGuard Sky Germany (09C4) FastMode"},
|
---|
120 | {{ 0x3F, 0xFF, 0x13, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
121 | 0x00, 0x50, 0x31, 0x01, 0x00, 0x13 },
|
---|
122 | 22, 2004, 0, NDS2, "VideoGuard Sky Germany (09C4) FastMode"},
|
---|
123 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
124 | 0x00, 0x50, 0x31, 0x01, 0x00, 0x14 },
|
---|
125 | 22, 2004, 0, NDS2, "VideoGuard Sky Germany (09C4) FastMode"},
|
---|
126 | {{ 0x3F, 0xFF, 0x15, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
127 | 0x00, 0x50, 0x31, 0x01, 0x00, 0x15 },
|
---|
128 | 22, 2004, 0, NDS2, "VideoGuard Sky Germany (09C4) FastMode"},
|
---|
129 | {{ 0x3F, 0xFD, 0x13, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x41, 0xB0, 0x0A, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
130 | 0x00, 0x00, 0x50, 0x31, 0x03 },
|
---|
131 | 21, 2004, 0, NDS2, "VideoGuard Sky Germany (098C)"},
|
---|
132 | {{ 0x3F, 0xFD, 0x14, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x41, 0xB0, 0x0A, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
133 | 0x00, 0x00, 0x50, 0x31, 0x03 },
|
---|
134 | 21, 2004, 0, NDS2, "VideoGuard Sky Germany (098C) FastMode"},
|
---|
135 | {{ 0x3F, 0xFD, 0x15, 0x25, 0x02, 0x50, 0x80, 0x0F, 0x41, 0xB0, 0x0A, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
136 | 0x00, 0x00, 0x50, 0x31, 0x03 },
|
---|
137 | 21, 2004, 0, NDS2, "VideoGuard Sky Germany (098C) FastMode"},
|
---|
138 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
139 | 0x00, 0x5A, 0x48, 0x01, 0x00, 0x00 },
|
---|
140 | 22, 2004, 0, NDS2, "VideoGuard DSMART Turkey"},
|
---|
141 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x54, 0xB0, 0x01, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
142 | 0x00, 0x4B, 0x57, 0x01, 0x00, 0x00 },
|
---|
143 | 22, 2004, 0, NDS2, "VideoGuard Kabel BW (098E)"},
|
---|
144 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
145 | 0x00, 0x5A, 0x43, 0x01, 0x00, 0x00 },
|
---|
146 | 22, 2004, 0, NDS2, "VideoGuard totalTV Serbia (091F)"},
|
---|
147 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
148 | 0x00, 0x5A, 0x45, 0x01, 0x00, 0x00 },
|
---|
149 | 22, 2004, 0, NDS2, "VideoGuard Get Kabel Norway"},
|
---|
150 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
|
---|
151 | 0x00, 0x58, 0x36, 0x01, 0x00, 0x14 },
|
---|
152 | 22, 2004, 0, NDS2, "VideoGuard Teleclub (09B6)"},
|
---|
153 | {{ 0x3F, 0xFD, 0x11, 0x25, 0x02, 0x50, 0x00, 0x03, 0x33, 0xB0, 0x15, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
154 | 0x80, 0x03, 0x4B, 0x4C, 0x03 },
|
---|
155 | 21, 2004, 0, NDS2, "VideoGuard Kabel Deutschland G02/G09 (09C7)"},
|
---|
156 | {{ 0x3F, 0xFD, 0x15, 0x25, 0x02, 0x50, 0x00, 0x03, 0x33, 0xB0, 0x15, 0x69, 0xFF, 0x4A, 0x50, 0xF0,
|
---|
157 | 0x80, 0x03, 0x4B, 0x4C, 0x03 },
|
---|
158 | 21, 2004, 0, NDS2, "VideoGuard Kabel Deutschland G02/G09 (09C7) FastMode"},
|
---|
159 | {{ 0x3F, 0x7D, 0x13, 0x25, 0x02, 0x41, 0xB0, 0x03, 0x69, 0xFF, 0x4A, 0x50, 0xF0, 0x80, 0x00, 0x54,
|
---|
160 | 0x37, 0x03 },
|
---|
161 | 18, 2004, 0, NDS2, "VideoGuard Telecolumbus (09AF)"},
|
---|
162 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x33, 0xB0, 0x10, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x00,
|
---|
163 | 0x00, 0x5A, 0x49, 0x01, 0x00, 0x00 },
|
---|
164 | 22, 2004, 0, NDS2, "VideoGuard Cyprus (092E)"},
|
---|
165 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
|
---|
166 | 0x00, 0x58, 0x45, 0x01, 0x00, 0x14 },
|
---|
167 | 22, 2004, 0, NDS2, "VideoGuard OTE TV Sat (09BE)"},
|
---|
168 | // NDS Version Unknown as Yet
|
---|
169 | {{ 0x3F, 0x7F, 0x13, 0x25, 0x02, 0x40, 0xB0, 0x12, 0x69, 0xFF, 0x4A, 0x50, 0x90, 0x41, 0x55, 0x00,
|
---|
170 | 0x00, 0x00, 0x00, 0x00 },
|
---|
171 | 20, 1997, 0, NDSUNKNOWN, "VideoGuard OnoCable Espana (0915)"},
|
---|
172 | {{ 0x3F, 0xFF, 0x14, 0x25, 0x03, 0x10, 0x80, 0x41, 0xB0, 0x07, 0x69, 0xFF, 0x4A, 0x50, 0x70, 0x80,
|
---|
173 | 0x00, 0x58, 0x44, 0x01, 0x00, 0x14 },
|
---|
174 | 22, 1997, 0, NDSUNKNOWN, "VideoGuard Sky Vivacom (09BD)"}, //45E
|
---|
175 | {{ 0x3F, 0x7F, 0x13, 0x25, 0x05, 0x40, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x00, 0x00, 0x00, 0x48,
|
---|
176 | 0x4B, 0x00, 0x01, 0x00 },
|
---|
177 | 20, 1997, 0, NDSUNKNOWN, "VideoGuard StarTV India (caid unknown)"}, //105.5E
|
---|
178 | {{ 0x3F, 0x7F, 0x13, 0x25, 0x03, 0x33, 0xB0, 0x11, 0x69, 0xFF, 0x4A, 0x50, 0x50, 0x00, 0x00, 0x49,
|
---|
179 | 0x56, 0x01, 0x00, 0x00 },
|
---|
180 | 22, 2004, 50, NDS2, "VideoGuard Indovision (09C1)" },
|
---|
181 | {{ 0 }, 0, 0, 0, 0, NULL}
|
---|
182 | };
|
---|
183 |
|
---|
184 | int32_t i=0;
|
---|
185 | ATR atrdata;
|
---|
186 | ATR *newatr = &atrdata;
|
---|
187 | ATR_InitFromArray(newatr, atr, *atr_size);
|
---|
188 | get_hist;
|
---|
189 |
|
---|
190 | ATR tableatr;
|
---|
191 | unsigned char table_hist[ATR_MAX_HISTORICAL];
|
---|
192 | uint32_t table_hist_size;
|
---|
193 |
|
---|
194 | while(nds_atr_table[i].desc) {
|
---|
195 | ATR_InitFromArray(&tableatr, nds_atr_table[i].atr, nds_atr_table[i].atr_len);
|
---|
196 | ATR_GetHistoricalBytes(&tableatr, table_hist, &table_hist_size);
|
---|
197 |
|
---|
198 | if ((hist_size == table_hist_size)
|
---|
199 | && (memcmp (hist, table_hist, hist_size) == 0)) {
|
---|
200 | reader->card_baseyear=nds_atr_table[i].base_year;
|
---|
201 | reader->card_tierstart=nds_atr_table[i].tier_start;
|
---|
202 | reader->card_system_version = nds_atr_table[i].nds_version;
|
---|
203 | reader->card_desc = nds_atr_table[i].desc;
|
---|
204 | break;
|
---|
205 | }
|
---|
206 | i++;
|
---|
207 | }
|
---|
208 | }
|
---|
209 |
|
---|
210 | static void cCamCryptVG_LongMult(uint16_t *pData, uint16_t *pLen, uint32_t mult, uint32_t carry);
|
---|
211 | static void cCamCryptVG_PartialMod(uint16_t val, uint32_t count, uint16_t *outkey, const uint16_t *inkey);
|
---|
212 | static void cCamCryptVG_RotateRightAndHash(unsigned char *p);
|
---|
213 | static void cCamCryptVG_Reorder16A(unsigned char *dest, const unsigned char *src);
|
---|
214 | static void cCamCryptVG_ReorderAndEncrypt(struct s_reader * reader, unsigned char *p);
|
---|
215 | static void cCamCryptVG_Process_D0(struct s_reader * reader, const unsigned char *ins, unsigned char *data);
|
---|
216 | static void cCamCryptVG_Process_D1(struct s_reader * reader, const unsigned char *ins, unsigned char *data, const unsigned char *status);
|
---|
217 | static void cCamCryptVG_Decrypt_D3(struct s_reader * reader, unsigned char *ins, unsigned char *data, const unsigned char *status);
|
---|
218 | static void cCamCryptVG_PostProcess_Decrypt(struct s_reader * reader, unsigned char *rxbuff);
|
---|
219 | static int32_t cAES_Encrypt(struct s_reader * reader, const unsigned char *data, int32_t len, unsigned char *crypted);
|
---|
220 | static void swap_lb (const unsigned char *buff, int32_t len);
|
---|
221 |
|
---|
222 | int32_t cw_is_valid(unsigned char *cw) // returns 1 if cw_is_valid, returns 0 if cw is all zeros
|
---|
223 | {
|
---|
224 | int32_t i;
|
---|
225 | for (i = 0; i < 8; i++)
|
---|
226 | if (cw[i] != 0) { //test if cw = 00
|
---|
227 | return OK;
|
---|
228 | }
|
---|
229 | return ERROR;
|
---|
230 | }
|
---|
231 |
|
---|
232 | void cAES_SetKey(struct s_reader * reader, const unsigned char *key)
|
---|
233 | {
|
---|
234 | AES_set_encrypt_key(key,128,&(reader->ekey));
|
---|
235 | }
|
---|
236 |
|
---|
237 | int32_t cAES_Encrypt(struct s_reader * reader, const unsigned char *data, int32_t len, unsigned char *crypted)
|
---|
238 | {
|
---|
239 | len=(len+15)&(~15); // pad up to a multiple of 16
|
---|
240 | int32_t i;
|
---|
241 | for(i=0; i<len; i+=16) AES_encrypt(data+i,crypted+i,&(reader->ekey));
|
---|
242 | return len;
|
---|
243 | }
|
---|
244 |
|
---|
245 | static void swap_lb (const unsigned char *buff, int32_t len)
|
---|
246 | {
|
---|
247 |
|
---|
248 | #if __BYTE_ORDER != __BIG_ENDIAN
|
---|
249 | return;
|
---|
250 |
|
---|
251 | #endif /* */
|
---|
252 | int32_t i;
|
---|
253 | uint16_t *tmp;
|
---|
254 | for (i = 0; i < len / 2; i++) {
|
---|
255 | tmp = (uint16_t *) buff + i;
|
---|
256 | *tmp = ((*tmp << 8) & 0xff00) | ((*tmp >> 8) & 0x00ff);
|
---|
257 | }
|
---|
258 | }
|
---|
259 |
|
---|
260 | inline void __xxor(unsigned char *data, int32_t len, const unsigned char *v1, const unsigned char *v2)
|
---|
261 | {
|
---|
262 | uint32_t i;
|
---|
263 | switch(len) { // looks ugly but the cpu don't crash!
|
---|
264 | case 16:
|
---|
265 | for(i = 8; i < 16; ++i ) {
|
---|
266 | data[i] = v1[i] ^ v2[i];
|
---|
267 | }
|
---|
268 | case 8:
|
---|
269 | for(i = 4; i < 8; ++i) {
|
---|
270 | data[i] = v1[i] ^ v2[i];
|
---|
271 | }
|
---|
272 | case 4:
|
---|
273 | for(i = 0; i < 4; ++i ) {
|
---|
274 | data[i] = v1[i] ^ v2[i];
|
---|
275 | }
|
---|
276 | break;
|
---|
277 | default:
|
---|
278 | while(len--) *data++ = *v1++ ^ *v2++;
|
---|
279 | break;
|
---|
280 | }
|
---|
281 | }
|
---|
282 |
|
---|
283 |
|
---|
284 | void cCamCryptVG_SetSeed(struct s_reader * reader)
|
---|
285 | {
|
---|
286 | #if __BYTE_ORDER != __BIG_ENDIAN
|
---|
287 | static const unsigned char key1[] = {
|
---|
288 | 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd5, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61, 0xd6,
|
---|
289 | 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd6, 0x09, 0xd7, 0x15, 0xd7, 0x21, 0xd7,
|
---|
290 | 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd7, 0x11, 0xd8, 0x23, 0xd8,
|
---|
291 | 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7, 0xd8
|
---|
292 | };
|
---|
293 | static const unsigned char key2[] = {
|
---|
294 | 0x01, 0x00, 0xcf, 0x13, 0xe0, 0x60, 0x54, 0xac, 0xab, 0x99, 0xe6, 0x0c, 0x9f, 0x5b, 0x91, 0xb9,
|
---|
295 | 0x72, 0x72, 0x4d, 0x5b, 0x5f, 0xd3, 0xb7, 0x5b, 0x01, 0x4d, 0xef, 0x9e, 0x6b, 0x8a, 0xb9, 0xd1,
|
---|
296 | 0xc9, 0x9f, 0xa1, 0x2a, 0x8d, 0x86, 0xb6, 0xd6, 0x39, 0xb4, 0x64, 0x65, 0x13, 0x77, 0xa1, 0x0a,
|
---|
297 | 0x0c, 0xcf, 0xb4, 0x2b, 0x3a, 0x2f, 0xd2, 0x09, 0x92, 0x15, 0x40, 0x47, 0x66, 0x5c, 0xda, 0xc9
|
---|
298 | };
|
---|
299 | #else
|
---|
300 | static const unsigned char key1[] = {
|
---|
301 | 0xd5, 0xb9, 0xd5, 0xef, 0xd5, 0xf5, 0xd5, 0xfb, 0xd6, 0x31, 0xd6, 0x43, 0xd6, 0x55, 0xd6, 0x61,
|
---|
302 | 0xd6, 0x85, 0xd6, 0x9d, 0xd6, 0xaf, 0xd6, 0xc7, 0xd6, 0xd9, 0xd7, 0x09, 0xd7, 0x15, 0xd7, 0x21,
|
---|
303 | 0xd7, 0x27, 0xd7, 0x3f, 0xd7, 0x45, 0xd7, 0xb1, 0xd7, 0xbd, 0xd7, 0xdb, 0xd8, 0x11, 0xd8, 0x23,
|
---|
304 | 0xd8, 0x29, 0xd8, 0x2f, 0xd8, 0x4d, 0xd8, 0x8f, 0xd8, 0xa1, 0xd8, 0xad, 0xd8, 0xbf, 0xd8, 0xd7
|
---|
305 | };
|
---|
306 | static const unsigned char key2[] = {
|
---|
307 | 0x00, 0x01, 0x13, 0xcf, 0x60, 0xe0, 0xac, 0x54, 0x99, 0xab, 0x0c, 0xe6, 0x5b, 0x9f, 0xb9, 0x91,
|
---|
308 | 0x72, 0x72, 0x5b, 0x4d, 0xd3, 0x5f, 0x5b, 0xb7, 0x4d, 0x01, 0x9e, 0xef, 0x8a, 0x6b, 0xd1, 0xb9,
|
---|
309 | 0x9f, 0xc9, 0x2a, 0xa1, 0x86, 0x8d, 0xd6, 0xb6, 0xb4, 0x39, 0x65, 0x64, 0x77, 0x13, 0x0a, 0xa1,
|
---|
310 | 0xcf, 0x0c, 0x2b, 0xb4, 0x2f, 0x3a, 0x09, 0xd2, 0x15, 0x92, 0x47, 0x40, 0x5c, 0x66, 0xc9, 0xda
|
---|
311 | };
|
---|
312 | #endif
|
---|
313 | memcpy(reader->cardkeys[1],key1,sizeof(reader->cardkeys[1]));
|
---|
314 | memcpy(reader->cardkeys[2],key2,sizeof(reader->cardkeys[2]));
|
---|
315 | }
|
---|
316 |
|
---|
317 | void cCamCryptVG_GetCamKey(struct s_reader * reader, unsigned char *buff)
|
---|
318 | {
|
---|
319 | uint16_t *tb2=(uint16_t *)buff, c=1;
|
---|
320 | memset(tb2,0,64);
|
---|
321 | tb2[0]=1;
|
---|
322 | int32_t i;
|
---|
323 | for(i=0; i<32; i++) cCamCryptVG_LongMult(tb2,&c,reader->cardkeys[1][i],0);
|
---|
324 | swap_lb (buff, 64);
|
---|
325 | }
|
---|
326 |
|
---|
327 | static void cCamCryptVG_PostProcess_Decrypt(struct s_reader * reader, unsigned char *rxbuff)
|
---|
328 | {
|
---|
329 | switch(rxbuff[0]) {
|
---|
330 | case 0xD0:
|
---|
331 | cCamCryptVG_Process_D0(reader,rxbuff,rxbuff+5);
|
---|
332 | break;
|
---|
333 | case 0xD1:
|
---|
334 | cCamCryptVG_Process_D1(reader,rxbuff,rxbuff+5,rxbuff+rxbuff[4]+5);
|
---|
335 | break;
|
---|
336 | case 0xD3:
|
---|
337 | cCamCryptVG_Decrypt_D3(reader,rxbuff,rxbuff+5,rxbuff+rxbuff[4]+5);
|
---|
338 | break;
|
---|
339 | }
|
---|
340 | }
|
---|
341 |
|
---|
342 | static void cCamCryptVG_Process_D0(struct s_reader * reader, const unsigned char *ins, unsigned char *data)
|
---|
343 | {
|
---|
344 | switch(ins[1]) {
|
---|
345 | case 0xb4:
|
---|
346 | swap_lb (data, 64);
|
---|
347 | memcpy(reader->cardkeys[0],data,sizeof(reader->cardkeys[0]));
|
---|
348 | break;
|
---|
349 | case 0xbc:
|
---|
350 | {
|
---|
351 | swap_lb (data, 64);
|
---|
352 | const uint16_t *key1=(const uint16_t *)reader->cardkeys[1];
|
---|
353 | uint16_t key2[32];
|
---|
354 | memcpy(key2,reader->cardkeys[2],sizeof(key2));
|
---|
355 | int32_t count2;
|
---|
356 | uint16_t iidata[32];
|
---|
357 | memcpy( (unsigned char*)&iidata, data, 64 );
|
---|
358 | for(count2=0; count2<32; count2++) {
|
---|
359 | uint32_t rem=0, divisor=key1[count2];
|
---|
360 | int8_t i;
|
---|
361 | for(i=31; i>=0; i--) {
|
---|
362 | uint32_t x=iidata[i] | (rem<<16);
|
---|
363 | rem=(x%divisor)&0xffff;
|
---|
364 | }
|
---|
365 | uint32_t carry=1, t=val_by2on3(divisor) | 1;
|
---|
366 | while(t) {
|
---|
367 | if(t&1) carry=((carry*rem)%divisor)&0xffff;
|
---|
368 | rem=((rem*rem)%divisor)&0xffff;
|
---|
369 | t>>=1;
|
---|
370 | }
|
---|
371 | cCamCryptVG_PartialMod(carry,count2,key2,key1);
|
---|
372 | }
|
---|
373 | uint16_t idatacount=0;
|
---|
374 | int32_t i;
|
---|
375 | for(i=31; i>=0; i--) cCamCryptVG_LongMult(iidata,&idatacount,key1[i],key2[i]);
|
---|
376 | memcpy( data, iidata, 64 );
|
---|
377 | swap_lb (data, 64);
|
---|
378 | unsigned char stateD1[16];
|
---|
379 | cCamCryptVG_Reorder16A(stateD1,data);
|
---|
380 | cAES_SetKey(reader,stateD1);
|
---|
381 | break;
|
---|
382 | }
|
---|
383 | }
|
---|
384 | }
|
---|
385 |
|
---|
386 | static void cCamCryptVG_Process_D1(struct s_reader * reader, const unsigned char *ins, unsigned char *data, const unsigned char *status)
|
---|
387 | {
|
---|
388 | unsigned char iter[16], tmp[16];
|
---|
389 | memset(iter,0,sizeof(iter));
|
---|
390 | memcpy(iter,ins,5);
|
---|
391 | xor16(iter,reader->stateD3A,iter);
|
---|
392 | memcpy(reader->stateD3A,iter,sizeof(iter));
|
---|
393 |
|
---|
394 | int32_t datalen=status-data;
|
---|
395 | int32_t datalen1=datalen;
|
---|
396 | if(datalen<0) datalen1+=15;
|
---|
397 | int32_t blocklen=datalen1>>4;
|
---|
398 | int32_t i;
|
---|
399 | int32_t iblock;
|
---|
400 | for(i=0,iblock=0; i<blocklen+2; i++,iblock+=16) {
|
---|
401 | unsigned char in[16];
|
---|
402 | int32_t docalc=1;
|
---|
403 | if(blocklen==i && (docalc=datalen&0xf)) {
|
---|
404 | memset(in,0,sizeof(in));
|
---|
405 | memcpy(in,&data[iblock],datalen-(datalen1&~0xf));
|
---|
406 | }
|
---|
407 | else if(blocklen+1==i) {
|
---|
408 | memset(in,0,sizeof(in));
|
---|
409 | memcpy(&in[5],status,2);
|
---|
410 | }
|
---|
411 | else
|
---|
412 | memcpy(in,&data[iblock],sizeof(in));
|
---|
413 |
|
---|
414 | if(docalc) {
|
---|
415 | xor16(iter,in,tmp);
|
---|
416 | cCamCryptVG_ReorderAndEncrypt(reader,tmp);
|
---|
417 | xor16(tmp,reader->stateD3A,iter);
|
---|
418 | }
|
---|
419 | }
|
---|
420 | memcpy(reader->stateD3A,tmp,16);
|
---|
421 | }
|
---|
422 |
|
---|
423 | static void cCamCryptVG_Decrypt_D3(struct s_reader * reader, unsigned char *ins, unsigned char *data, const unsigned char *status)
|
---|
424 | {
|
---|
425 | if(ins[4]>16) ins[4]-=16;
|
---|
426 | if(ins[1]==0xbe) memset(reader->stateD3A,0,sizeof(reader->stateD3A));
|
---|
427 |
|
---|
428 | unsigned char tmp[16];
|
---|
429 | memset(tmp,0,sizeof(tmp));
|
---|
430 | memcpy(tmp,ins,5);
|
---|
431 | xor16(tmp,reader->stateD3A,reader->stateD3A);
|
---|
432 |
|
---|
433 | int32_t len1=ins[4];
|
---|
434 | int32_t blocklen=len1>>4;
|
---|
435 | if(ins[1]!=0xbe) blocklen++;
|
---|
436 |
|
---|
437 | unsigned char iter[16], states[16][16];
|
---|
438 | memset(iter,0,sizeof(iter));
|
---|
439 | int32_t blockindex;
|
---|
440 | for(blockindex=0; blockindex<blocklen; blockindex++) {
|
---|
441 | iter[0]+=blockindex;
|
---|
442 | xor16(iter,reader->stateD3A,iter);
|
---|
443 | cCamCryptVG_ReorderAndEncrypt(reader,iter);
|
---|
444 | xor16(iter,&data[blockindex*16],states[blockindex]);
|
---|
445 | if(blockindex==(len1>>4)) {
|
---|
446 | int32_t c=len1-(blockindex*16);
|
---|
447 | if(c<16) memset(&states[blockindex][c],0,16-c);
|
---|
448 | }
|
---|
449 | xor16(states[blockindex],reader->stateD3A,reader->stateD3A);
|
---|
450 | cCamCryptVG_RotateRightAndHash(reader->stateD3A);
|
---|
451 | }
|
---|
452 | memset(tmp,0,sizeof(tmp));
|
---|
453 | memcpy(tmp+5,status,2);
|
---|
454 | xor16(tmp,reader->stateD3A,reader->stateD3A);
|
---|
455 | cCamCryptVG_ReorderAndEncrypt(reader,reader->stateD3A);
|
---|
456 |
|
---|
457 | memcpy(reader->stateD3A,status-16,sizeof(reader->stateD3A));
|
---|
458 | cCamCryptVG_ReorderAndEncrypt(reader,reader->stateD3A);
|
---|
459 |
|
---|
460 | memcpy(data,states[0],len1);
|
---|
461 | if(ins[1]==0xbe) {
|
---|
462 | cCamCryptVG_Reorder16A(tmp,states[0]);
|
---|
463 | cAES_SetKey(reader,tmp);
|
---|
464 | }
|
---|
465 | }
|
---|
466 |
|
---|
467 | static void cCamCryptVG_ReorderAndEncrypt(struct s_reader * reader, unsigned char *p)
|
---|
468 | {
|
---|
469 | unsigned char tmp[16];
|
---|
470 | cCamCryptVG_Reorder16A(tmp,p);
|
---|
471 | cAES_Encrypt(reader,tmp,16,tmp);
|
---|
472 | cCamCryptVG_Reorder16A(p,tmp);
|
---|
473 | }
|
---|
474 |
|
---|
475 | // reorder AAAABBBBCCCCDDDD to ABCDABCDABCDABCD
|
---|
476 | static void cCamCryptVG_Reorder16A(unsigned char *dest, const unsigned char *src)
|
---|
477 | {
|
---|
478 | int32_t i;
|
---|
479 | int32_t j;
|
---|
480 | int32_t k;
|
---|
481 | for(i=0,k=0; i<4; i++)
|
---|
482 | for(j=i; j<16; j+=4,k++)
|
---|
483 | dest[k]=src[j];
|
---|
484 | }
|
---|
485 |
|
---|
486 | static void cCamCryptVG_LongMult(uint16_t *pData, uint16_t *pLen, uint32_t mult, uint32_t carry)
|
---|
487 | {
|
---|
488 | int32_t i;
|
---|
489 | for(i=0; i<*pLen; i++) {
|
---|
490 | carry+=pData[i]*mult;
|
---|
491 | pData[i]=(uint16_t)carry;
|
---|
492 | carry>>=16;
|
---|
493 | }
|
---|
494 | if(carry) pData[(*pLen)++]=carry;
|
---|
495 | }
|
---|
496 |
|
---|
497 | static void cCamCryptVG_PartialMod(uint16_t val, uint32_t count, uint16_t *outkey, const uint16_t *inkey)
|
---|
498 | {
|
---|
499 | if(count) {
|
---|
500 | uint32_t mod=inkey[count];
|
---|
501 | uint16_t mult=(inkey[count]-outkey[count-1])&0xffff;
|
---|
502 | uint32_t i;
|
---|
503 | uint32_t ib1;
|
---|
504 | for(i=0,ib1=count-2; i<count-1; i++,ib1--) {
|
---|
505 | uint32_t t=(inkey[ib1]*mult)%mod;
|
---|
506 | mult=t-outkey[ib1];
|
---|
507 | if(mult>t) mult+=mod;
|
---|
508 | }
|
---|
509 | mult+=val;
|
---|
510 | if((val>mult) || (mod<mult)) mult-=mod;
|
---|
511 | outkey[count]=(outkey[count]*mult)%mod;
|
---|
512 | }
|
---|
513 | else
|
---|
514 | outkey[0]=val;
|
---|
515 | }
|
---|
516 |
|
---|
517 | static void cCamCryptVG_RotateRightAndHash(unsigned char *p)
|
---|
518 | {
|
---|
519 | static const unsigned char table1[256] = {
|
---|
520 | 0x63,0x7c,0x77,0x7b,0xf2,0x6b,0x6f,0xc5, 0x30,0x01,0x67,0x2b,0xfe,0xd7,0xab,0x76,
|
---|
521 | 0xca,0x82,0xc9,0x7d,0xfa,0x59,0x47,0xf0, 0xad,0xd4,0xa2,0xaf,0x9c,0xa4,0x72,0xc0,
|
---|
522 | 0xb7,0xfd,0x93,0x26,0x36,0x3f,0xf7,0xcc, 0x34,0xa5,0xe5,0xf1,0x71,0xd8,0x31,0x15,
|
---|
523 | 0x04,0xc7,0x23,0xc3,0x18,0x96,0x05,0x9a, 0x07,0x12,0x80,0xe2,0xeb,0x27,0xb2,0x75,
|
---|
524 | 0x09,0x83,0x2c,0x1a,0x1b,0x6e,0x5a,0xa0, 0x52,0x3b,0xd6,0xb3,0x29,0xe3,0x2f,0x84,
|
---|
525 | 0x53,0xd1,0x00,0xed,0x20,0xfc,0xb1,0x5b, 0x6a,0xcb,0xbe,0x39,0x4a,0x4c,0x58,0xcf,
|
---|
526 | 0xd0,0xef,0xaa,0xfb,0x43,0x4d,0x33,0x85, 0x45,0xf9,0x02,0x7f,0x50,0x3c,0x9f,0xa8,
|
---|
527 | 0x51,0xa3,0x40,0x8f,0x92,0x9d,0x38,0xf5, 0xbc,0xb6,0xda,0x21,0x10,0xff,0xf3,0xd2,
|
---|
528 | 0xcd,0x0c,0x13,0xec,0x5f,0x97,0x44,0x17, 0xc4,0xa7,0x7e,0x3d,0x64,0x5d,0x19,0x73,
|
---|
529 | 0x60,0x81,0x4f,0xdc,0x22,0x2a,0x90,0x88, 0x46,0xee,0xb8,0x14,0xde,0x5e,0x0b,0xdb,
|
---|
530 | 0xe0,0x32,0x3a,0x0a,0x49,0x06,0x24,0x5c, 0xc2,0xd3,0xac,0x62,0x91,0x95,0xe4,0x79,
|
---|
531 | 0xe7,0xc8,0x37,0x6d,0x8d,0xd5,0x4e,0xa9, 0x6c,0x56,0xf4,0xea,0x65,0x7a,0xae,0x08,
|
---|
532 | 0xba,0x78,0x25,0x2e,0x1c,0xa6,0xb4,0xc6, 0xe8,0xdd,0x74,0x1f,0x4b,0xbd,0x8b,0x8a,
|
---|
533 | 0x70,0x3e,0xb5,0x66,0x48,0x03,0xf6,0x0e, 0x61,0x35,0x57,0xb9,0x86,0xc1,0x1d,0x9e,
|
---|
534 | 0xe1,0xf8,0x98,0x11,0x69,0xd9,0x8e,0x94, 0x9b,0x1e,0x87,0xe9,0xce,0x55,0x28,0xdf,
|
---|
535 | 0x8c,0xa1,0x89,0x0d,0xbf,0xe6,0x42,0x68, 0x41,0x99,0x2d,0x0f,0xb0,0x54,0xbb,0x16,
|
---|
536 | };
|
---|
537 | unsigned char t1=p[15];
|
---|
538 | int32_t i;
|
---|
539 | for(i=0; i<16; i++) {
|
---|
540 | unsigned char t2=t1;
|
---|
541 | t1=p[i]; p[i]=table1[(t1>>1)|((t2&1)<<7)];
|
---|
542 | }
|
---|
543 | }
|
---|
544 |
|
---|
545 | int32_t status_ok(const unsigned char *status)
|
---|
546 | {
|
---|
547 | //rdr_log(reader, "check status %02x%02x", status[0],status[1]);
|
---|
548 | return (status[0] == 0x90 || status[0] == 0x91)
|
---|
549 | && (status[1] == 0x00 || status[1] == 0x01
|
---|
550 | || status[1] == 0x20 || status[1] == 0x21
|
---|
551 | || status[1] == 0x80 || status[1] == 0x81
|
---|
552 | || status[1] == 0xa0 || status[1] == 0xa1);
|
---|
553 | }
|
---|
554 |
|
---|
555 | void memorize_cmd_table (struct s_reader * reader, const unsigned char *mem, int32_t size){
|
---|
556 | if (cs_malloc(&reader->cmd_table, size))
|
---|
557 | memcpy(reader->cmd_table,mem,size);
|
---|
558 | }
|
---|
559 |
|
---|
560 | int32_t cmd_table_get_info(struct s_reader * reader, const unsigned char *cmd, unsigned char *rlen, unsigned char *rmode)
|
---|
561 | {
|
---|
562 | struct s_CmdTabEntry *pcte=reader->cmd_table->e;
|
---|
563 | int32_t i;
|
---|
564 | for(i=0; i< reader->cmd_table->Nentries; i++,pcte++)
|
---|
565 | if(cmd[1]==pcte->cmd) {
|
---|
566 | *rlen=pcte->len;
|
---|
567 | *rmode=pcte->mode;
|
---|
568 | return 1;
|
---|
569 | }
|
---|
570 | return 0;
|
---|
571 | }
|
---|
572 |
|
---|
573 | int32_t cmd_exists(struct s_reader * reader, const unsigned char *cmd)
|
---|
574 | {
|
---|
575 | struct s_CmdTabEntry *pcte=reader->cmd_table->e;
|
---|
576 | int32_t i;
|
---|
577 | for(i=0; i< reader->cmd_table->Nentries; i++,pcte++)
|
---|
578 | if(cmd[1]==pcte->cmd) {
|
---|
579 | return 1;
|
---|
580 | }
|
---|
581 | return 0;
|
---|
582 | }
|
---|
583 |
|
---|
584 | int32_t read_cmd_len(struct s_reader * reader, const unsigned char *cmd)
|
---|
585 | {
|
---|
586 | def_resp;
|
---|
587 | unsigned char cmd2[5];
|
---|
588 | memcpy(cmd2,cmd,5);
|
---|
589 | if (cmd2[0] == 0xD3){
|
---|
590 | cmd2[0] = 0xD0;
|
---|
591 | }
|
---|
592 | cmd2[3]=0x80;
|
---|
593 | cmd2[4]=1;
|
---|
594 | // some card reply with L 91 00 (L being the command length).
|
---|
595 | if(!write_cmd_vg(cmd2,NULL) || !status_ok(cta_res+1)|| cta_res[0]==0) {
|
---|
596 | if (cta_res[0]==0) { //some cards reply len=0x00 for not supported ins
|
---|
597 | rdr_debug_mask(reader, D_READER, "failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[1],cta_res[2]);
|
---|
598 | } else { //others reply only status byte
|
---|
599 | rdr_debug_mask(reader, D_READER, "failed to read %02x%02x cmd length (%02x %02x)",cmd[1],cmd[2],cta_res[0],cta_res[1]);
|
---|
600 | }
|
---|
601 | return -1;
|
---|
602 | }
|
---|
603 | return cta_res[0];
|
---|
604 | }
|
---|
605 |
|
---|
606 | int32_t do_cmd(struct s_reader * reader, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff,
|
---|
607 | unsigned char * cta_res)
|
---|
608 | {
|
---|
609 | uint16_t cta_lr;
|
---|
610 | unsigned char ins2[5];
|
---|
611 | memcpy(ins2,ins,5);
|
---|
612 | unsigned char len=0, mode=0;
|
---|
613 | if(cmd_table_get_info(reader,ins2,&len,&mode)) {
|
---|
614 | if(len==0xFF && mode==2) {
|
---|
615 | if(ins2[4]==0) ins2[4]=len=read_cmd_len(reader,ins2);
|
---|
616 | }
|
---|
617 | else if(mode!=0) ins2[4]=len;
|
---|
618 | }
|
---|
619 | if(ins2[0]==0xd3) {
|
---|
620 | if (ins2[4] == 0) return 0;
|
---|
621 | ins2[4]+=16;
|
---|
622 | }
|
---|
623 | len=ins2[4];
|
---|
624 | unsigned char tmp[264];
|
---|
625 | if(rxbuff == NULL) rxbuff=tmp;
|
---|
626 | if(mode>1) {
|
---|
627 | if(!write_cmd_vg(ins2,NULL) || !status_ok(cta_res+len)) return -1;
|
---|
628 | memcpy(rxbuff,ins2,5);
|
---|
629 | memcpy(rxbuff+5,cta_res,len);
|
---|
630 | memcpy(rxbuff+5+len,cta_res+len,2);
|
---|
631 | }
|
---|
632 | else {
|
---|
633 | if(!write_cmd_vg(ins2,txbuff) || !status_ok(cta_res)) return -2;
|
---|
634 | memcpy(rxbuff,ins2,5);
|
---|
635 | memcpy(rxbuff+5,txbuff,len);
|
---|
636 | memcpy(rxbuff+5+len,cta_res,2);
|
---|
637 | }
|
---|
638 | cCamCryptVG_PostProcess_Decrypt(reader,rxbuff);
|
---|
639 |
|
---|
640 | return len;
|
---|
641 | }
|
---|
642 |
|
---|
643 | void rev_date_calc_tm(const unsigned char *Date, struct tm *timeinfo , int32_t base_year)
|
---|
644 | {
|
---|
645 | timeinfo->tm_year = Date[0] / 12 + base_year - 1900; //tm year starts at 1900
|
---|
646 | timeinfo->tm_mon = Date[0] % 12; //tm month starts with 0
|
---|
647 | timeinfo->tm_mday = Date[1] & 0x1f;
|
---|
648 | timeinfo->tm_hour = Date[2] / 8;
|
---|
649 | timeinfo->tm_min = (0x100 * (Date[2] - timeinfo->tm_hour * 8) + Date[3]) / 32;
|
---|
650 | timeinfo->tm_sec = (Date[3] - timeinfo->tm_min * 32) * 2;
|
---|
651 | }
|
---|
652 |
|
---|
653 | int32_t videoguard_get_emm_type(EMM_PACKET *ep, struct s_reader * rdr)
|
---|
654 | {
|
---|
655 |
|
---|
656 | /*
|
---|
657 | Unique:
|
---|
658 | 82 30 ad 70 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 XX XX XX 00 00
|
---|
659 | d3 02 00 22 90 20 44 02 4a 50 1d 88 ab 02 ac 79 16 6c df a1 b1 b7 77 00 ba eb 63 b5 c9 a9 30 2b 43 e9 16 a9 d5 14 00
|
---|
660 | d3 02 00 22 90 20 44 02 13 e3 40 bd 29 e4 90 97 c3 aa 93 db 8d f5 6b e4 92 dd 00 9b 51 03 c9 3d d0 e2 37 44 d3 bf 00
|
---|
661 | d3 02 00 22 90 20 44 02 97 79 5d 18 96 5f 3a 67 70 55 bb b9 d2 49 31 bd 18 17 2a e9 6f eb d8 76 ec c3 c9 cc 53 39 00
|
---|
662 | d2 02 00 21 90 1f 44 02 99 6d df 36 54 9c 7c 78 1b 21 54 d9 d4 9f c1 80 3c 46 10 76 aa 75 ef d6 82 27 2e 44 7b 00
|
---|
663 |
|
---|
664 | Unknown:
|
---|
665 | 82 00 1C 81 02 00 18 90 16 42 01 xx xx xx xx xx
|
---|
666 | xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx
|
---|
667 | */
|
---|
668 |
|
---|
669 | int32_t i;
|
---|
670 | int32_t serial_count = ((ep->emm[3] >> 4) & 3) + 1;
|
---|
671 | int32_t serial_len = (ep->emm[3] & 0x80) ? 3 : 4;
|
---|
672 | uchar emmtype = (ep->emm[3] & VG_EMMTYPE_MASK) >> 6;
|
---|
673 |
|
---|
674 | switch(emmtype) {
|
---|
675 | case VG_EMMTYPE_G:
|
---|
676 | rdr_debug_mask(rdr, D_EMM, "GLOBAL");
|
---|
677 | ep->type=GLOBAL;
|
---|
678 | return 1;
|
---|
679 |
|
---|
680 | case VG_EMMTYPE_U:
|
---|
681 | case VG_EMMTYPE_S:
|
---|
682 | rdr_debug_mask(rdr, D_EMM, "%s", (emmtype == VG_EMMTYPE_U) ? "UNIQUE" : "SHARED");
|
---|
683 | ep->type=emmtype;
|
---|
684 | if (ep->emm[1] == 0) // detected UNIQUE EMM from cccam (there is no serial)
|
---|
685 | return 1;
|
---|
686 |
|
---|
687 | for (i = 0; i < serial_count; i++) {
|
---|
688 | if (!memcmp(&ep->emm[i * 4 + 4], rdr->hexserial + 2, serial_len)) {
|
---|
689 | memcpy(ep->hexserial, &ep->emm[i * 4 + 4], serial_len);
|
---|
690 | return 1;
|
---|
691 | }
|
---|
692 | }
|
---|
693 | return 0; // if UNIQUE or SHARED but no serial match return FALSE
|
---|
694 |
|
---|
695 | default:
|
---|
696 | //remote emm without serial
|
---|
697 | rdr_debug_mask(rdr, D_EMM, "UNKNOWN");
|
---|
698 | ep->type=UNKNOWN;
|
---|
699 | return 1;
|
---|
700 | }
|
---|
701 | }
|
---|
702 |
|
---|
703 | int32_t videoguard_do_emm(struct s_reader * reader, EMM_PACKET *ep, unsigned char CLA,
|
---|
704 | void (*read_tiers)(struct s_reader *),
|
---|
705 | int32_t (*docmd)(struct s_reader *, const unsigned char *ins, const unsigned char *txbuff, unsigned char *rxbuff, unsigned char *cta_res))
|
---|
706 | {
|
---|
707 | unsigned char cta_res[CTA_RES_LEN];
|
---|
708 | unsigned char ins42[5] = { CLA, 0x42, 0x00, 0x00, 0xFF };
|
---|
709 | int32_t rc = SKIPPED;
|
---|
710 | int32_t nsubs = ((ep->emm[3] & 0x30) >> 4) + 1;
|
---|
711 | int32_t offs = 4;
|
---|
712 | int32_t emmv2 = 0;
|
---|
713 | int32_t position, ua_position = -1;
|
---|
714 | int32_t serial_len = (ep->type == SHARED) ? 3: 4;
|
---|
715 | int32_t vdrsc_fix = 0;
|
---|
716 |
|
---|
717 | if (ep->type == UNIQUE || ep->type == SHARED)
|
---|
718 | {
|
---|
719 | if (ep->emm[1] == 0x00) // cccam sends emm-u without UA
|
---|
720 | {
|
---|
721 | nsubs = 1;
|
---|
722 | ua_position = 0;
|
---|
723 | }
|
---|
724 | else
|
---|
725 | {
|
---|
726 | int32_t i;
|
---|
727 | for (i = 0; i < nsubs; ++i)
|
---|
728 | {
|
---|
729 | if (memcmp(&ep->emm[4+i*4], &reader->hexserial[2], serial_len) == 0)
|
---|
730 | {
|
---|
731 | ua_position = i;
|
---|
732 | break;
|
---|
733 | }
|
---|
734 | }
|
---|
735 | offs += nsubs * 4;
|
---|
736 | }
|
---|
737 | if (ua_position == -1)
|
---|
738 | return ERROR;
|
---|
739 | }
|
---|
740 | // if (ep->type == GLOBAL && memcmp(&ep->emm[4], &reader->hexserial[2], 4) == 0) // workaround for vdr-sc client
|
---|
741 | // {
|
---|
742 | // ep->type = UNIQUE;
|
---|
743 | // vdrsc_fix = 1;
|
---|
744 | // offs += 4;
|
---|
745 | // }
|
---|
746 | if (ep->emm[offs] == 0x00 && (ep->emm[offs+1] == 0x00 || ep->emm[offs+1] == 0x01)) // unmodified emm from dvbapi
|
---|
747 | {
|
---|
748 | emmv2 = ep->emm[offs+1];
|
---|
749 | offs += 2 + 1 + emmv2; // skip sub-emm len (2 bytes sub-emm len if 0x01);
|
---|
750 | }
|
---|
751 | for (position = 0; position < nsubs && offs+2 < ep->emmlen; ++position)
|
---|
752 | {
|
---|
753 | if (ep->emm[offs] > 0x07) // workaround for mgcamd and emmv2
|
---|
754 | ++offs;
|
---|
755 | if (ep->emm[offs] == 0x02 || ep->emm[offs] == 0x03 || ep->emm[offs] == 0x07)
|
---|
756 | {
|
---|
757 | if (ep->emm[offs] == 0x03)
|
---|
758 | {
|
---|
759 | if (position == ua_position || vdrsc_fix)
|
---|
760 | {
|
---|
761 | videoguard_mail_msg(reader, &ep->emm[offs+2]);
|
---|
762 | return rc;
|
---|
763 | }
|
---|
764 | else
|
---|
765 | {
|
---|
766 | offs += ep->emm[offs+1] + 2;
|
---|
767 | if (!(offs+1 < ep->emmlen)) return rc;
|
---|
768 | if (ep->emm[offs] == 0x00 && (ep->emm[offs+1] == 0x00 || ep->emm[offs+1] == 0x01))
|
---|
769 | offs += 2 + 1 + emmv2;
|
---|
770 | continue;
|
---|
771 | }
|
---|
772 | }
|
---|
773 | offs += ep->emm[offs+1] + 2;
|
---|
774 | if (!(offs+1 < ep->emmlen)) return rc;
|
---|
775 | if (ep->emm[offs] != 0)
|
---|
776 | {
|
---|
777 | if (ep->type == GLOBAL || vdrsc_fix || position == ua_position)
|
---|
778 | {
|
---|
779 | ins42[4] = ep->emm[offs];
|
---|
780 | int32_t l = (*docmd)(reader, ins42, &ep->emm[offs+1], NULL, cta_res);
|
---|
781 | rc = (l > 0 && status_ok(cta_res)) ? OK : ERROR;
|
---|
782 | rdr_debug_mask(reader, D_EMM, "request return code : %02X%02X", cta_res[0], cta_res[1]);
|
---|
783 | if (status_ok(cta_res) && (cta_res[1] & 0x01))
|
---|
784 | (*read_tiers)(reader);
|
---|
785 | }
|
---|
786 | offs += ep->emm[offs] + 1;
|
---|
787 | if (offs < ep->emmlen && ep->emm[offs] == 0x00) ++offs;
|
---|
788 | }
|
---|
789 | offs += 1 + emmv2;
|
---|
790 | if (vdrsc_fix) --position;
|
---|
791 | }
|
---|
792 | else
|
---|
793 | return rc;
|
---|
794 | }
|
---|
795 | return rc;
|
---|
796 | }
|
---|
797 |
|
---|
798 | void videoguard_get_emm_filter(struct s_reader * rdr, uchar *filter)
|
---|
799 | {
|
---|
800 | int32_t idx = 2;
|
---|
801 | int32_t n;
|
---|
802 |
|
---|
803 | filter[0]=0xFF;
|
---|
804 | filter[1]=0;
|
---|
805 |
|
---|
806 | for (n = 0; n < 3; ++n)
|
---|
807 | {
|
---|
808 | filter[idx++]=EMM_UNIQUE;
|
---|
809 | filter[idx++]=0;
|
---|
810 | filter[idx+0] = 0x82;
|
---|
811 | filter[idx+0+16] = 0xFF;
|
---|
812 | filter[idx+1] = 0x40;
|
---|
813 | filter[idx+1+16] = 0xC0;
|
---|
814 | memcpy(filter+idx+2+4*n, rdr->hexserial+2, 4);
|
---|
815 | memset(filter+idx+2+4*n+16, 0xFF, 4);
|
---|
816 | idx +=32;
|
---|
817 | filter[1]++;
|
---|
818 | }
|
---|
819 | // fourth serial position does not fit within the 16bytes demux filter
|
---|
820 |
|
---|
821 | for (n = 0; n < 3; ++n)
|
---|
822 | {
|
---|
823 | filter[idx++]=EMM_SHARED;
|
---|
824 | filter[idx++]=0;
|
---|
825 | filter[idx+0] = 0x82;
|
---|
826 | filter[idx+0+16] = 0xFF;
|
---|
827 | filter[idx+1] = 0x80;
|
---|
828 | filter[idx+1+16] = 0xC0;
|
---|
829 | memcpy(filter+idx+2+4*n, rdr->hexserial+2, 3);
|
---|
830 | memset(filter+idx+2+4*n+16, 0xFF, 3);
|
---|
831 | idx +=32;
|
---|
832 | filter[1]++;
|
---|
833 | }
|
---|
834 | // fourth serial position does not fit within the 16bytes demux filter
|
---|
835 |
|
---|
836 | filter[idx++]=EMM_GLOBAL;
|
---|
837 | filter[idx++]=0;
|
---|
838 | filter[idx+0] = 0x82;
|
---|
839 | filter[idx+0+16] = 0xFF;
|
---|
840 | filter[idx+1] = 0x00;
|
---|
841 | filter[idx+1+16] = 0xC0;
|
---|
842 | filter[1]++;
|
---|
843 |
|
---|
844 | return;
|
---|
845 | }
|
---|
846 |
|
---|
847 | static MAILMSG *find_msg(uint16_t caid, uint32_t serial, uint16_t date, uint16_t msg_id)
|
---|
848 | {
|
---|
849 | MAILMSG *msg;
|
---|
850 | LL_ITER it = ll_iter_create(vg_msgs);
|
---|
851 | while ((msg = (MAILMSG *)ll_iter_next(&it)))
|
---|
852 | {
|
---|
853 | if (msg->caid == caid && msg->serial == serial && msg->date == date && msg->id == msg_id)
|
---|
854 | return msg;
|
---|
855 | }
|
---|
856 | return 0;
|
---|
857 | }
|
---|
858 |
|
---|
859 | static void write_msg(struct s_reader *reader, MAILMSG *msg, uint32_t baseyear)
|
---|
860 | {
|
---|
861 | FILE *fp = fopen(cfg.mailfile, "a");
|
---|
862 | if (fp == 0)
|
---|
863 | {
|
---|
864 | rdr_log(reader, "Cannot open mailfile %s", cfg.mailfile);
|
---|
865 | return;
|
---|
866 | }
|
---|
867 |
|
---|
868 | uint16_t i;
|
---|
869 | for (i = 0; i < msg->len - 1; ++i)
|
---|
870 | {
|
---|
871 | if (msg->message[i] == 0x00 && msg->message[i+1] == 0x32)
|
---|
872 | {
|
---|
873 | msg->subject = &msg->message[i+3];
|
---|
874 | break;
|
---|
875 | }
|
---|
876 | }
|
---|
877 | int32_t year = (msg->date >> 8) / 12 + baseyear;
|
---|
878 | int32_t mon = (msg->date >> 8) % 12 + 1;
|
---|
879 | int32_t day = msg->date & 0x1f;
|
---|
880 |
|
---|
881 | fprintf(fp, "%04X:%08X:%02d/%02d/%04d:%04X:\"%s\":\"%s\"\n", msg->caid, msg->serial, day, mon, year,
|
---|
882 | msg->id, msg->subject, msg->message);
|
---|
883 | fclose(fp);
|
---|
884 | free(msg->message);
|
---|
885 | msg->message = msg->subject = 0;
|
---|
886 | msg->written = 1;
|
---|
887 | }
|
---|
888 |
|
---|
889 | static void msgs_init(uint32_t baseyear)
|
---|
890 | {
|
---|
891 | vg_msgs = ll_create("vg_msgs");
|
---|
892 | FILE *fp = fopen(cfg.mailfile, "r");
|
---|
893 | if (fp == 0)
|
---|
894 | return;
|
---|
895 | int32_t year, mon, day;
|
---|
896 | char buffer[2048];
|
---|
897 | while (fgets(buffer, sizeof(buffer), fp))
|
---|
898 | {
|
---|
899 | MAILMSG *msg;
|
---|
900 | if (!cs_malloc(&msg, sizeof(MAILMSG)))
|
---|
901 | {
|
---|
902 | fclose(fp);
|
---|
903 | return;
|
---|
904 | }
|
---|
905 | sscanf(buffer, "%04hX:%08X:%02d/%02d/%04d:%04hX", &msg->caid, &msg->serial, &day, &mon, &year, &msg->id);
|
---|
906 | year -= baseyear;
|
---|
907 | msg->date = ((year * 12) + mon - 1) << 8 | day;
|
---|
908 | msg->message = msg->subject = 0;
|
---|
909 | msg->written = 1;
|
---|
910 | ll_append(vg_msgs, msg);
|
---|
911 | }
|
---|
912 | fclose(fp);
|
---|
913 | }
|
---|
914 |
|
---|
915 | void videoguard_mail_msg(struct s_reader *rdr, uint8_t *data)
|
---|
916 | {
|
---|
917 | if (cfg.disablemail)
|
---|
918 | return;
|
---|
919 |
|
---|
920 | if (vg_msgs == 0)
|
---|
921 | msgs_init(rdr->card_baseyear);
|
---|
922 |
|
---|
923 | if (data[0] != 0xFF || data[1] != 0xFF)
|
---|
924 | return;
|
---|
925 |
|
---|
926 | uint16_t msg_id = (data[2] << 8) | data[3];
|
---|
927 | uint8_t idx = data[4] & 0x0F;
|
---|
928 | int32_t msg_size = data[5] * 10 + 2;
|
---|
929 | uint16_t date = (data[9] << 8) | data[10];
|
---|
930 | int32_t submsg_len = data[12] - 2;
|
---|
931 | uint16_t submsg_idx = (data[13] << 8) | data[14];
|
---|
932 | uint32_t serial = (rdr->hexserial[2]<<24) | (rdr->hexserial[3]<<16) | (rdr->hexserial[4]<<8) | rdr->hexserial[5];
|
---|
933 |
|
---|
934 | MAILMSG *msg = find_msg(rdr->caid, serial, date, msg_id);
|
---|
935 |
|
---|
936 | if (msg == 0)
|
---|
937 | {
|
---|
938 | if (!cs_malloc(&msg, sizeof(MAILMSG)))
|
---|
939 | return;
|
---|
940 | msg->caid = rdr->caid;
|
---|
941 | msg->serial = serial;
|
---|
942 | msg->date = date;
|
---|
943 | msg->id = msg_id;
|
---|
944 | msg->nsubs = (data[4] & 0xF0) >> 4;
|
---|
945 | msg->mask = 1 << idx;
|
---|
946 | msg->written = 0;
|
---|
947 | msg->len = submsg_len;
|
---|
948 | if (!cs_malloc(&msg->message, msg_size))
|
---|
949 | {
|
---|
950 | free(msg);
|
---|
951 | return;
|
---|
952 | }
|
---|
953 | memset(msg->message, 0, msg_size);
|
---|
954 | memcpy(&msg->message[submsg_idx], &data[15], submsg_len);
|
---|
955 | msg->subject = 0;
|
---|
956 | ll_append(vg_msgs, msg);
|
---|
957 | }
|
---|
958 | else
|
---|
959 | {
|
---|
960 | if (msg->written == 1 || msg->mask & (1 << idx))
|
---|
961 | return;
|
---|
962 | msg->mask |= 1 << idx;
|
---|
963 | msg->len += submsg_len;
|
---|
964 | memcpy(&msg->message[submsg_idx], &data[15], submsg_len);
|
---|
965 | }
|
---|
966 | if (msg->mask == (1 << msg->nsubs) - 1)
|
---|
967 | write_msg(rdr, msg, rdr->card_baseyear);
|
---|
968 | }
|
---|
969 | #endif
|
---|