1 /*
2 Minisatip does not assume any responsability related to functionality of this
3 code. It also does not include any certificates, please procure them from
4 alternative source
5
6 */
7
8 #include <arpa/inet.h>
9 #include <ctype.h>
10 #include <errno.h>
11 #include <fcntl.h>
12 #include <math.h>
13 #include <net/if.h>
14 #include <netdb.h>
15 #include <netinet/in.h>
16 #include <stdint.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 #include <sys/ioctl.h>
21 #include <sys/socket.h>
22 #include <sys/stat.h>
23 #include <sys/types.h>
24 #include <time.h>
25 #include <unistd.h>
26
27 #include <libdvbapi/dvbca.h>
28 #include <libdvben50221/en50221_app_ai.h>
29 #include <libdvben50221/en50221_app_auth.h>
30 #include <libdvben50221/en50221_app_ca.h>
31 #include <libdvben50221/en50221_app_datetime.h>
32 #include <libdvben50221/en50221_app_dvb.h>
33 #include <libdvben50221/en50221_app_epg.h>
34 #include <libdvben50221/en50221_app_lowspeed.h>
35 #include <libdvben50221/en50221_app_mmi.h>
36 #include <libdvben50221/en50221_app_rm.h>
37 #include <libdvben50221/en50221_app_smartcard.h>
38 #include <libdvben50221/en50221_app_tags.h>
39 #include <libdvben50221/en50221_app_teletext.h>
40 #include <libdvben50221/en50221_app_utils.h>
41 #include <libdvben50221/en50221_session.h>
42
43 #include <openssl/aes.h>
44 #include <openssl/conf.h>
45 #include <openssl/err.h>
46 #include <openssl/evp.h>
47 #include <openssl/pem.h>
48 #include <openssl/sha.h>
49 #include <openssl/x509.h>
50 #include <openssl/x509v3.h>
51
52 #include "adapter.h"
53 #include "ca.h"
54 #include "dvb.h"
55 #include "dvbapi.h"
56 #include "minisatip.h"
57 #include "pmt.h"
58 #include "search.h"
59 #include "socketworks.h"
60 #include <linux/dvb/ca.h>
61
62 #include "utils.h"
63
64 #define MAX_ELEMENTS 33
65 #define MAX_PAIRS 10
66 #define DEFAULT_LOG LOG_DVBCA
67
68 #define TS101699_APP_RM_RESOURCEID MKRID(1, 1, 2)
69 #define TS101699_APP_AI_RESOURCEID MKRID(2, 1, 2)
70 #define CIPLUS_APP_AI_RESOURCEID MKRID(2, 1, 3)
71 #define CIPLUS_APP_AI_RESOURCEID_MULTI MKRID(2, 1, 4)
72 #define CIPLUS_APP_DVB_RESOURCEID MKRID(32, 1, 2) // host control
73 #define CIPLUS_APP_DVB_RESOURCEID_TWO MKRID(32, 1, 3) // host control
74 #define CIPLUS_APP_DVB_RESOURCEID_MULTI \
75 MKRID(32, 2, 1) // host control multistream
76 #define CIPLUS_APP_CA_RESOURCEID MKRID(3, 1, 1)
77 #define CIPLUS_APP_CA_RESOURCEID_MULTI MKRID(3, 2, 1)
78 //#define CIPLUS_APP_LOWSPEED_RESOURCEID (DEVICE_TYPE, DEVICE_NUMBER)
79 // MKRID(96,((DEVICE_TYPE)<<2)|((DEVICE_NUMBER) & 0x03),2) #define
80 // CIPLUS_APP_LOWSPEED_RESOURCEID_TWO (DEVICE_TYPE, DEVICE_NUMBER)
81 // MKRID(96,((DEVICE_TYPE)<<2)|((DEVICE_NUMBER) & 0x03),3) //CI+ v1.3
82 #define CIPLUS_APP_CC_RESOURCEID MKRID(140, 64, 1)
83 #define CIPLUS_APP_CC_RESOURCEID_TWO MKRID(140, 64, 2) // CI+ v1.3
84 #define CIPLUS_APP_CC_RESOURCEID_THREE MKRID(140, 64, 3) // CI+ v1.3
85 #define CIPLUS_APP_CC_RESOURCEID_MULTI MKRID(140, 65, 1) // CI+ v1.3 multistream
86 #define CIPLUS_APP_LANG_RESOURCEID MKRID(141, 64, 1)
87 #define CIPLUS_APP_UPGR_RESOURCEID MKRID(142, 64, 1)
88 #define CIPLUS_APP_OPRF_RESOURCEID MKRID(143, 64, 1)
89 #define CIPLUS_APP_MULTISTREAM_RESOURCEID MKRID(144, 1, 1)
90 #define CIPLUS_APP_SAS_RESOURCEID MKRID(150, 64, 1)
91 #define TS101699_APP_AMMI_RESOURCEID MKRID(65, 1, 1)
92 #define CIPLUS_APP_AMMI_RESOURCEID MKRID(65, 1, 2)
93
94 #define CIPLUS_TAG_CC_OPEN_REQ 0x9f9001
95 #define CIPLUS_TAG_CC_OPEN_CNF 0x9f9002
96 #define CIPLUS_TAG_CC_DATA_REQ 0x9f9003
97 #define CIPLUS_TAG_CC_DATA_CNF 0x9f9004
98 #define CIPLUS_TAG_CC_SYNC_REQ 0x9f9005
99 #define CIPLUS_TAG_CC_SAC_DATA_REQ 0x9f9007
100 #define CIPLUS_TAG_CC_SAC_SYNC_REQ 0x9f9009
101 #define CIPLUS_TAG_APP_INFO 0x9f8021
102 #define CIPLUS_TAG_CICAM_RESET 0x9f8023
103 #define CIPLUS_TAG_COUNTRY_ENQ 0x9f8100
104 #define CIPLUS_TAG_LANG_ENQ 0x9f8110
105 #define CIPLUS_TAG_SAS_CONNECT_CNF 0x9f9a01
106 #define CIPLUS_TAG_FIRMWARE_UPGR 0x9f9d01
107 #define CIPLUS_TAG_FIRMWARE_UPGR_PRGRS 0x9f9d03
108 #define CIPLUS_TAG_FIRMWARE_UPGR_COMPLT 0x9f9d04
109 #define CIPLUS_TAG_OPERATOR_STATUS 0x9f9c01
110 #define CIPLUS_TAG_OPERATOR_INFO 0x9f9c05
111 #define CIPLUS_TAG_OPERATOR_SEARCH_STATUS 0x9f9c07
112 #define CIPLUS_TAG_OPERATOR_TUNE 0x9f9c09
113
114 #if OPENSSL_VERSION_NUMBER < 0x10100000L
DH_set0_pqg(DH * dh,BIGNUM * p,BIGNUM * q,BIGNUM * g)115 int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) {
116 /* If the fields p and g in d are NULL, the corresponding input
117 * parameters MUST be non-NULL. q may remain NULL.
118 */
119 if ((dh->p == NULL && p == NULL) || (dh->g == NULL && g == NULL))
120 return 0;
121
122 if (p != NULL) {
123 BN_free(dh->p);
124 dh->p = p;
125 }
126 if (q != NULL) {
127 BN_free(dh->q);
128 dh->q = q;
129 }
130 if (g != NULL) {
131 BN_free(dh->g);
132 dh->g = g;
133 }
134
135 if (q != NULL) {
136 dh->length = BN_num_bits(q);
137 }
138
139 return 1;
140 }
141
DH_get0_key(const DH * dh,const BIGNUM ** pub_key,const BIGNUM ** priv_key)142 void DH_get0_key(const DH *dh, const BIGNUM **pub_key,
143 const BIGNUM **priv_key) {
144 if (pub_key != NULL)
145 *pub_key = dh->pub_key;
146 if (priv_key != NULL)
147 *priv_key = dh->priv_key;
148 }
149
DH_set_flags(DH * dh,int flags)150 void DH_set_flags(DH *dh, int flags) { dh->flags |= flags; }
151 #endif
152
153 char ci_name_underscore[128];
154 int ci_number;
155 int logging = 0;
156 char logfile[256];
157 int extract_ci_cert = 0;
158
159 extern char *listmgmt_str[];
160
161 uint32_t datatype_sizes[MAX_ELEMENTS] = {
162 0, 50, 0, 0, 0, 8, 8, 0, 0, 0, 0, 0, 32, 256, 256, 0, 0,
163 256, 256, 32, 8, 8, 32, 32, 0, 8, 2, 32, 1, 32, 1, 0, 32};
164
165 struct element {
166 uint8_t *data;
167 uint32_t size;
168 /* buffer valid */
169 int valid;
170 };
171
172 struct ci_buffer {
173 size_t size;
174 unsigned char data[];
175 };
176
177 struct ci_session {
178 /* parent */
179 struct ca_device *ca;
180
181 /* slot index */
182 uint32_t slot_index;
183 uint16_t index;
184 uint32_t resid;
185 int action;
186
187 /* resources */
188 const struct ci_resource *resource;
189
190 /* private data */
191 void *private_data;
192 };
193
194 typedef struct ca_device {
195 int enabled;
196 SCAPMT capmt[MAX_CA_PMT];
197 int max_ca_pmt, multiple_pmt;
198 int fd;
199 int slot_id;
200 int tc;
201 int id;
202 int ignore_close;
203 int init_ok;
204 uint16_t caid[MAX_CAID];
205 uint32_t caids;
206
207 pthread_t stackthread;
208
209 struct en50221_transport_layer *tl;
210 struct en50221_session_layer *sl;
211
212 struct en50221_app_send_functions sf;
213 struct en50221_app_rm *rm_resource;
214 struct en50221_app_ai *ai_resource;
215 struct en50221_app_dvb *dvb_resource;
216 struct en50221_app_ca *ca_resource;
217 struct en50221_app_datetime *dt_resource;
218 struct en50221_app_mmi *mmi_resource;
219
220 int ca_high_bitrate_mode;
221 int ca_ai_version;
222 int ca_session_number;
223 int uri_mask;
224
225 uint16_t ai_session_number;
226 uint16_t mmi_session_number;
227
228 struct list_head *txq;
229 struct list_head *mmiq;
230
231 struct ci_session session[64];
232 const struct ci_resource *resources[64];
233 /*
234 * CAM module info
235 */
236 char ci_name[128];
237
238 char cam_menu_string[64];
239 char pin_str[10];
240 char force_ci;
241 uint8_t key[2][16], iv[2][16];
242 int sp, is_ciplus, parity;
243
244 } ca_device_t;
245
246 int dvbca_id;
247 ca_device_t *ca_devices[MAX_ADAPTERS];
248
249 struct cc_ctrl_data {
250
251 /* parent */
252 struct ci_session *session;
253
254 /* ci+ credentials */
255 struct element elements[MAX_ELEMENTS];
256
257 /* DHSK */
258 uint8_t dhsk[256];
259
260 /* KS_host */
261 uint8_t ks_host[32];
262
263 /* derived keys */
264 uint8_t sek[16];
265 uint8_t sak[16];
266
267 /* AKH checks - module performs 5 tries to get correct AKH */
268 unsigned int akh_index;
269
270 /* authentication data */
271 uint8_t dh_exp[256];
272
273 /* certificates */
274 struct cert_ctx *cert_ctx;
275
276 /* private key of device-cert */
277 RSA *rsa_device_key;
278 };
279
280 struct cert_ctx {
281 X509_STORE *store;
282
283 /* Host */
284 X509 *cust_cert;
285 X509 *device_cert;
286
287 /* Module */
288 X509 *ci_cust_cert;
289 X509 *ci_device_cert;
290 };
291
292 struct aes_xcbc_mac_ctx {
293 uint8_t K[3][16];
294 uint8_t IV[16];
295 AES_KEY key;
296 int buflen;
297 };
298
299 // this contains all known resource ids so we can see if the cam asks for
300 // something exotic
301 uint32_t resource_ids[] =
302 {/* EN50221_APP_TELETEXT_RESOURCEID, EN50221_APP_SMARTCARD_RESOURCEID(1),EN50221_APP_AUTH_RESOURCEID,EN50221_APP_EPG_RESOURCEID(1) */ //not discribed in spec - so don't need
303 // EN50221_APP_RM_RESOURCEID,
304 TS101699_APP_RM_RESOURCEID,
305 // EN50221_APP_AI_RESOURCEID,
306 // TS101699_APP_AI_RESOURCEID,
307 CIPLUS_APP_AI_RESOURCEID,
308 // CIPLUS_APP_AI_RESOURCEID_MULTI,
309 EN50221_APP_CA_RESOURCEID,
310 // CIPLUS_APP_CA_RESOURCEID_MULTI,
311 // EN50221_APP_DVB_RESOURCEID,
312 CIPLUS_APP_DVB_RESOURCEID, //host control
313 // CIPLUS_APP_DVB_RESOURCEID_TWO, //host control
314 // CIPLUS_APP_DVB_RESOURCEID_MULTI, //host control
315 EN50221_APP_DATETIME_RESOURCEID,
316 EN50221_APP_MMI_RESOURCEID,
317 EN50221_APP_LOWSPEED_RESOURCEID(1, 1), /* CIPLUS_APP_LOWSPEED_RESOURCEID(1, 1), CIPLUS_APP_LOWSPEED_RESOURCEID_TWO(1, 1), */
318 // CIPLUS_APP_CC_RESOURCEID,
319 CIPLUS_APP_CC_RESOURCEID_TWO,
320 // CIPLUS_APP_CC_RESOURCEID_THREE,
321 // CIPLUS_APP_CC_RESOURCEID_MULTI,
322 CIPLUS_APP_LANG_RESOURCEID,
323 CIPLUS_APP_UPGR_RESOURCEID,
324 CIPLUS_APP_OPRF_RESOURCEID,
325 CIPLUS_APP_SAS_RESOURCEID,
326 CIPLUS_APP_MULTISTREAM_RESOURCEID,
327 // TS101699_APP_AMMI_RESOURCEID,
328 CIPLUS_APP_AMMI_RESOURCEID};
329
330 int resource_ids_count = sizeof(resource_ids) / 4;
331
332 uint32_t resource_ids_ci[] = {EN50221_APP_TELETEXT_RESOURCEID,
333 EN50221_APP_SMARTCARD_RESOURCEID(1),
334 EN50221_APP_RM_RESOURCEID,
335 EN50221_APP_MMI_RESOURCEID,
336 EN50221_APP_LOWSPEED_RESOURCEID(1, 1),
337 EN50221_APP_EPG_RESOURCEID(1),
338 EN50221_APP_DVB_RESOURCEID,
339 EN50221_APP_CA_RESOURCEID,
340 EN50221_APP_DATETIME_RESOURCEID,
341 EN50221_APP_AUTH_RESOURCEID,
342 EN50221_APP_AI_RESOURCEID,
343 TS101699_APP_AI_RESOURCEID,
344 CIPLUS_APP_AI_RESOURCEID};
345
346 int resource_ids_ci_count = sizeof(resource_ids_ci) / 4;
347
348 typedef enum {
349 CIPLUS_DATA_RATE_72_MBPS = 0,
350 CIPLUS_DATA_RATE_96_MBPS = 1,
351 } ciplus13_data_rate_t;
352
353 unsigned char dh_p[256] =
354 {/* prime */
355 0xd6, 0x27, 0x14, 0x7a, 0x7c, 0x0c, 0x26, 0x63, 0x9d, 0x82, 0xeb, 0x1f,
356 0x4a, 0x18, 0xff, 0x6c, 0x34, 0xad, 0xea, 0xa6, 0xc0, 0x23, 0xe6, 0x65,
357 0xfc, 0x8e, 0x32, 0xc3, 0x33, 0xf4, 0x91, 0xa7, 0xcc, 0x88, 0x58, 0xd7,
358 0xf3, 0xb3, 0x17, 0x5e, 0xb0, 0xa8, 0xeb, 0x5c, 0xd4, 0xd8, 0x3a, 0xae,
359 0x8e, 0x75, 0xa1, 0x50, 0x5f, 0x5d, 0x67, 0xc5, 0x40, 0xf4, 0xb3, 0x68,
360 0x35, 0xd1, 0x3a, 0x4c, 0x93, 0x7f, 0xca, 0xce, 0xdd, 0x83, 0x29, 0x01,
361 0xc8, 0x4b, 0x76, 0x81, 0x56, 0x34, 0x83, 0x31, 0x92, 0x72, 0x65, 0x7b,
362 0xac, 0xd9, 0xda, 0xa9, 0xd1, 0xd3, 0xe5, 0x77, 0x58, 0x6f, 0x5b, 0x44,
363 0x3e, 0xaf, 0x7f, 0x6d, 0xf5, 0xcf, 0x0a, 0x80, 0x0d, 0xa5, 0x56, 0x4f,
364 0x4b, 0x85, 0x41, 0x0f, 0x13, 0x41, 0x06, 0x1f, 0xf3, 0xd9, 0x65, 0x36,
365 0xae, 0x47, 0x41, 0x1f, 0x1f, 0xe0, 0xde, 0x69, 0xe5, 0x86, 0x2a, 0xa1,
366 0xf2, 0x48, 0x02, 0x92, 0x68, 0xa6, 0x37, 0x9f, 0x76, 0x4f, 0x7d, 0x94,
367 0x5d, 0x10, 0xe5, 0xab, 0x5d, 0xb2, 0xf3, 0x12, 0x8c, 0x79, 0x03, 0x92,
368 0xa6, 0x7f, 0x8a, 0x78, 0xb0, 0xba, 0xc5, 0xb5, 0x31, 0xc5, 0xc8, 0x22,
369 0x6e, 0x29, 0x02, 0x40, 0xab, 0xe7, 0x5c, 0x23, 0x33, 0x7f, 0xcb, 0x86,
370 0xc7, 0xb4, 0xfd, 0xaa, 0x44, 0xcd, 0x9c, 0x9f, 0xba, 0xac, 0x3a, 0xcf,
371 0x7e, 0x31, 0x5f, 0xa8, 0x47, 0xce, 0xca, 0x1c, 0xb4, 0x77, 0xa0, 0xec,
372 0x9a, 0x46, 0xd4, 0x79, 0x7b, 0x64, 0xbb, 0x6c, 0x91, 0xb2, 0x38, 0x01,
373 0x65, 0x11, 0x45, 0x9f, 0x62, 0x08, 0x6f, 0x31, 0xcf, 0xc4, 0xba, 0xdc,
374 0xd0, 0x03, 0x91, 0xf1, 0x18, 0x1f, 0xcb, 0x4d, 0xfc, 0x73, 0x5a, 0xa2,
375 0x15, 0xb8, 0x3c, 0x8d, 0x80, 0x92, 0x1c, 0xa1, 0x03, 0xd0, 0x83, 0x2f,
376 0x5f, 0xe3, 0x07, 0x69};
377
378 unsigned char dh_g[256] =
379 {/* generator */
380 0x95, 0x7d, 0xd1, 0x49, 0x68, 0xc1, 0xa5, 0xf1, 0x48, 0xe6, 0x50, 0x4f,
381 0xa1, 0x10, 0x72, 0xc4, 0xef, 0x12, 0xec, 0x2d, 0x94, 0xbe, 0xc7, 0x20,
382 0x2c, 0x94, 0xf9, 0x68, 0x67, 0x0e, 0x22, 0x17, 0xb5, 0x5c, 0x0b, 0xca,
383 0xac, 0x9f, 0x25, 0x9c, 0xd2, 0xa6, 0x1a, 0x20, 0x10, 0x16, 0x6a, 0x42,
384 0x27, 0x83, 0x47, 0x42, 0xa0, 0x07, 0x52, 0x09, 0x33, 0x97, 0x4e, 0x30,
385 0x57, 0xd8, 0xb7, 0x1e, 0x46, 0xa6, 0xba, 0x4e, 0x40, 0x6a, 0xe9, 0x1a,
386 0x5a, 0xa0, 0x74, 0x56, 0x92, 0x55, 0xc2, 0xbd, 0x44, 0xcd, 0xb3, 0x33,
387 0xf7, 0x35, 0x46, 0x25, 0xdf, 0x84, 0x19, 0xf3, 0xe2, 0x7a, 0xac, 0x4e,
388 0xee, 0x1a, 0x86, 0x3b, 0xb3, 0x87, 0xa6, 0x66, 0xc1, 0x70, 0x21, 0x41,
389 0xd3, 0x58, 0x36, 0xb5, 0x3b, 0x6e, 0xa1, 0x55, 0x60, 0x9a, 0x59, 0xd3,
390 0x85, 0xd8, 0xdc, 0x6a, 0xff, 0x41, 0xb6, 0xbf, 0x42, 0xde, 0x64, 0x00,
391 0xd0, 0xee, 0x3a, 0xa1, 0x8a, 0xed, 0x12, 0xf9, 0xba, 0x54, 0x5c, 0xdb,
392 0x06, 0x24, 0x49, 0xe8, 0x47, 0xcf, 0x5b, 0xe4, 0xbb, 0xc0, 0xaa, 0x8a,
393 0x8c, 0xbe, 0x73, 0xd9, 0x02, 0xea, 0xee, 0x8d, 0x87, 0x5b, 0xbf, 0x78,
394 0x04, 0x41, 0x9e, 0xa8, 0x5c, 0x3c, 0x49, 0xde, 0x88, 0x6d, 0x62, 0x21,
395 0x7f, 0xf0, 0x5e, 0x2d, 0x1d, 0xfc, 0x47, 0x0d, 0x1b, 0xaa, 0x4e, 0x0d,
396 0x78, 0x20, 0xfe, 0x57, 0x0f, 0xca, 0xdf, 0xeb, 0x3c, 0x84, 0xa7, 0xe1,
397 0x61, 0xb2, 0x95, 0x98, 0x07, 0x73, 0x8e, 0x51, 0xc6, 0x87, 0xe4, 0xcf,
398 0xf1, 0x5f, 0x86, 0x99, 0xec, 0x8d, 0x44, 0x92, 0x2c, 0x99, 0xf6, 0xc0,
399 0xf4, 0x39, 0xe8, 0x05, 0xbf, 0xc1, 0x56, 0xde, 0xfe, 0x93, 0x75, 0x06,
400 0x69, 0x87, 0x83, 0x06, 0x51, 0x80, 0xa5, 0x6e, 0xa6, 0x19, 0x7d, 0x3b,
401 0xef, 0xfb, 0xe0, 0x4a};
402
403 int dvbca_close_device(ca_device_t *c);
404
405 ////// MISC.C
406
get_random(unsigned char * dest,int len)407 int get_random(unsigned char *dest, int len) {
408 int fd;
409 char *urnd = "/dev/urandom";
410
411 fd = open(urnd, O_RDONLY);
412 if (fd < 0) {
413 LOG("cannot open %s", urnd);
414 return -1;
415 }
416
417 if (read(fd, dest, len) != len) {
418 LOG("cannot read from %s", urnd);
419 close(fd);
420 return -2;
421 }
422
423 close(fd);
424
425 return len;
426 }
427
parseLengthField(const unsigned char * pkt,int * len)428 int parseLengthField(const unsigned char *pkt, int *len) {
429 int i;
430
431 *len = 0;
432 if (!(*pkt & 0x80)) {
433 *len = *pkt;
434 return 1;
435 }
436 for (i = 0; i < (pkt[0] & 0x7F); ++i) {
437 *len <<= 8;
438 *len |= pkt[i + 1];
439 }
440 return (pkt[0] & 0x7F) + 1;
441 }
442
add_padding(uint8_t * dest,unsigned int len,unsigned int blocklen)443 int add_padding(uint8_t *dest, unsigned int len, unsigned int blocklen) {
444 uint8_t padding = 0x80;
445 int count = 0;
446
447 while (len & (blocklen - 1)) {
448 *dest++ = padding;
449 ++len;
450 ++count;
451 padding = 0;
452 }
453
454 return count;
455 }
456
get_bin_from_nibble(int in)457 static int get_bin_from_nibble(int in) {
458 if ((in >= '0') && (in <= '9'))
459 return in - 0x30;
460
461 if ((in >= 'A') && (in <= 'Z'))
462 return in - 0x41 + 10;
463
464 if ((in >= 'a') && (in <= 'z'))
465 return in - 0x61 + 10;
466
467 LOG("fixme: unsupported chars in hostid");
468
469 return 0;
470 }
471
str2bin(uint8_t * dst,char * data,int len)472 void str2bin(uint8_t *dst, char *data, int len) {
473 int i;
474
475 for (i = 0; i < len; i += 2)
476 *dst++ = (get_bin_from_nibble(data[i]) << 4) |
477 get_bin_from_nibble(data[i + 1]);
478 }
479
UINT32(const unsigned char * in,unsigned int len)480 uint32_t UINT32(const unsigned char *in, unsigned int len) {
481 uint32_t val = 0;
482 unsigned int i;
483
484 for (i = 0; i < len; i++) {
485 val <<= 8;
486 val |= *in++;
487 }
488
489 return val;
490 }
491
BYTE32(unsigned char * dest,uint32_t val)492 int BYTE32(unsigned char *dest, uint32_t val) {
493 *dest++ = val >> 24;
494 *dest++ = val >> 16;
495 *dest++ = val >> 8;
496 *dest++ = val;
497
498 return 4;
499 }
500
BYTE16(unsigned char * dest,uint16_t val)501 int BYTE16(unsigned char *dest, uint16_t val) {
502 *dest++ = val >> 8;
503 *dest++ = val;
504 return 2;
505 }
506
cert_strings(char * certfile)507 void cert_strings(char *certfile) {
508 int c;
509 unsigned count;
510 // off_t offset;
511 FILE *file;
512 char string[256];
513 int n = 2; /* too short string to be usefull */
514 int line = 0;
515
516 file = fopen(certfile, "r");
517 if (!file) {
518 LOG("Could not open certificate file %s", certfile);
519 return;
520 }
521 LOG("#########################################################\n");
522 // offset = 0;
523 count = 0;
524 do {
525 if (line > 14)
526 n = 8; /* after usefull info be stricter */
527 c = fgetc(file);
528 // if (isprint(c) || c == '\t')
529 if (isprint(c)) {
530 string[count] = c;
531 count++;
532 } else {
533 if (count > n) /* line feed */
534 {
535 string[count - 1] = 0;
536 LOG("%s\n", string);
537 line++;
538 }
539 count = 0;
540 }
541 // offset++;
542 } while ((c != EOF) && (line < 16)); /* only frst 15 lines */
543 fclose(file);
544 LOG("#########################################################\n");
545 return;
546 }
547
548 /// END MISC
549
550 ///// AES_XCBC_MAC
551
aes_xcbc_mac_init(struct aes_xcbc_mac_ctx * ctx,const uint8_t * key)552 int aes_xcbc_mac_init(struct aes_xcbc_mac_ctx *ctx, const uint8_t *key) {
553 AES_KEY aes_key;
554 int y, x;
555
556 memset(&aes_key, 0, sizeof(aes_key));
557
558 AES_set_encrypt_key(key, 128, &aes_key);
559
560 for (y = 0; y < 3; y++) {
561 for (x = 0; x < 16; x++)
562 ctx->K[y][x] = y + 1;
563 AES_ecb_encrypt(ctx->K[y], ctx->K[y], &aes_key, 1);
564 }
565
566 /* setup K1 */
567 AES_set_encrypt_key(ctx->K[0], 128, &ctx->key);
568
569 memset(ctx->IV, 0, 16);
570 ctx->buflen = 0;
571
572 return 0;
573 }
574
aes_xcbc_mac_process(struct aes_xcbc_mac_ctx * ctx,const uint8_t * in,unsigned int len)575 int aes_xcbc_mac_process(struct aes_xcbc_mac_ctx *ctx, const uint8_t *in,
576 unsigned int len) {
577 while (len) {
578 if (ctx->buflen == 16) {
579 AES_ecb_encrypt(ctx->IV, ctx->IV, &ctx->key, 1);
580 ctx->buflen = 0;
581 }
582 ctx->IV[ctx->buflen++] ^= *in++;
583 --len;
584 }
585
586 return 0;
587 }
588
aes_xcbc_mac_done(struct aes_xcbc_mac_ctx * ctx,uint8_t * out)589 int aes_xcbc_mac_done(struct aes_xcbc_mac_ctx *ctx, uint8_t *out) {
590 int i;
591
592 if (ctx->buflen == 16) {
593 /* K2 */
594 for (i = 0; i < 16; i++)
595 ctx->IV[i] ^= ctx->K[1][i];
596 } else {
597 ctx->IV[ctx->buflen] ^= 0x80;
598 /* K3 */
599 for (i = 0; i < 16; i++)
600 ctx->IV[i] ^= ctx->K[2][i];
601 }
602
603 AES_ecb_encrypt(ctx->IV, ctx->IV, &ctx->key, 1);
604 memcpy(out, ctx->IV, 16);
605
606 return 0;
607 }
608
609 ////// END_AES_XCBC_MAC
610 ////// DH_RSA_MISC
611
pkcs_1_mgf1(const uint8_t * seed,unsigned long seedlen,uint8_t * mask,unsigned long masklen)612 static int pkcs_1_mgf1(const uint8_t *seed, unsigned long seedlen,
613 uint8_t *mask, unsigned long masklen) {
614 unsigned long hLen, x;
615 uint32_t counter;
616 uint8_t *buf;
617
618 /* get hash output size */
619 hLen = 20; /* SHA1 */
620
621 /* allocate memory */
622 buf = malloc(hLen);
623 if (buf == NULL) {
624 LOG("error mem");
625 return -1;
626 }
627
628 /* start counter */
629 counter = 0;
630
631 while (masklen > 0) {
632 /* handle counter */
633 BYTE32(buf, counter);
634 ++counter;
635
636 /* get hash of seed || counter */
637 unsigned char buffer[0x18];
638 memcpy(buffer, seed, seedlen);
639 memcpy(buffer + 0x14, buf, 4);
640 SHA1(buffer, 0x18, buf);
641
642 /* store it */
643 for (x = 0; x < hLen && masklen > 0; x++, masklen--)
644 *mask++ = buf[x];
645 }
646
647 free(buf);
648 return 0;
649 }
650
pkcs_1_pss_encode(const uint8_t * msghash,unsigned int msghashlen,unsigned long saltlen,unsigned long modulus_bitlen,uint8_t * out,unsigned int outlen)651 static int pkcs_1_pss_encode(const uint8_t *msghash, unsigned int msghashlen,
652 unsigned long saltlen,
653 unsigned long modulus_bitlen, uint8_t *out,
654 unsigned int outlen) {
655 unsigned char *DB, *mask, *salt, *hash;
656 unsigned long x, y, hLen, modulus_len;
657 int err = -1;
658 unsigned char *hashbuf;
659 unsigned int hashbuflen;
660
661 hLen = 20; /* SHA1 */
662 modulus_len = (modulus_bitlen >> 3) + (modulus_bitlen & 7 ? 1 : 0);
663
664 /* allocate ram for DB/mask/salt/hash of size modulus_len */
665 DB = malloc(modulus_len);
666 mask = malloc(modulus_len);
667 salt = malloc(modulus_len);
668 hash = malloc(modulus_len);
669
670 hashbuflen = 8 + msghashlen + saltlen;
671 hashbuf = malloc(hashbuflen);
672
673 if (!(DB && mask && salt && hash && hashbuf)) {
674 LOG("out of memory");
675 goto LBL_ERR;
676 }
677
678 /* generate random salt */
679 if (saltlen > 0) {
680 if (get_random(salt, saltlen) != (long)saltlen) {
681 LOG("rnd failed");
682 goto LBL_ERR;
683 }
684 }
685
686 /* M = (eight) 0x00 || msghash || salt, hash = H(M) */
687 memset(hashbuf, 0, 8);
688 memcpy(hashbuf + 8, msghash, msghashlen);
689 memcpy(hashbuf + 8 + msghashlen, salt, saltlen);
690 SHA1(hashbuf, hashbuflen, hash);
691
692 /* generate DB = PS || 0x01 || salt, PS == modulus_len - saltlen - hLen - 2
693 * zero bytes */
694 x = 0;
695 memset(DB + x, 0, modulus_len - saltlen - hLen - 2);
696 x += modulus_len - saltlen - hLen - 2;
697 DB[x++] = 0x01;
698 memcpy(DB + x, salt, saltlen);
699 x += saltlen;
700
701 err = pkcs_1_mgf1(hash, hLen, mask, modulus_len - hLen - 1);
702 if (err)
703 goto LBL_ERR;
704
705 /* xor against DB */
706 for (y = 0; y < (modulus_len - hLen - 1); y++)
707 DB[y] ^= mask[y];
708
709 /* output is DB || hash || 0xBC */
710 if (outlen < modulus_len) {
711 err = -1;
712 LOG("error overflow");
713 goto LBL_ERR;
714 }
715
716 /* DB len = modulus_len - hLen - 1 */
717 y = 0;
718 memcpy(out + y, DB, modulus_len - hLen - 1);
719 y += modulus_len - hLen - 1;
720
721 /* hash */
722 memcpy(out + y, hash, hLen);
723 y += hLen;
724
725 /* 0xBC */
726 out[y] = 0xBC;
727
728 /* now clear the 8*modulus_len - modulus_bitlen most significant bits */
729 out[0] &= 0xFF >> ((modulus_len << 3) - (modulus_bitlen - 1));
730
731 err = 0;
732 LBL_ERR:
733 free(hashbuf);
734 free(hash);
735 free(salt);
736 free(mask);
737 free(DB);
738
739 return err;
740 }
741
742 /* DH */
743
dh_gen_exp(uint8_t * dest,int dest_len,uint8_t * dh_g,int dh_g_len,uint8_t * dh_p,int dh_p_len)744 int dh_gen_exp(uint8_t *dest, int dest_len, uint8_t *dh_g, int dh_g_len,
745 uint8_t *dh_p, int dh_p_len) {
746 DH *dh;
747 BIGNUM *p, *g;
748 const BIGNUM *priv_key;
749 int len;
750 unsigned int gap;
751
752 dh = DH_new();
753
754 p = BN_bin2bn(dh_p, dh_p_len, 0);
755 g = BN_bin2bn(dh_g, dh_g_len, 0);
756 DH_set0_pqg(dh, p, NULL, g);
757 DH_set_flags(dh, DH_FLAG_NO_EXP_CONSTTIME);
758
759 DH_generate_key(dh);
760
761 DH_get0_key(dh, NULL, &priv_key);
762 len = BN_num_bytes(priv_key);
763 if (len > dest_len) {
764 LOG("len > dest_len");
765 return -1;
766 }
767
768 gap = dest_len - len;
769 memset(dest, 0, gap);
770 BN_bn2bin(priv_key, &dest[gap]);
771
772 DH_free(dh);
773
774 return 0;
775 }
776
777 /* dest = base ^ exp % mod */
dh_mod_exp(uint8_t * dest,int dest_len,uint8_t * base,int base_len,uint8_t * mod,int mod_len,uint8_t * exp,int exp_len)778 int dh_mod_exp(uint8_t *dest, int dest_len, uint8_t *base, int base_len,
779 uint8_t *mod, int mod_len, uint8_t *exp, int exp_len) {
780 BIGNUM *bn_dest, *bn_base, *bn_exp, *bn_mod;
781 BN_CTX *ctx;
782 int len;
783 unsigned int gap;
784
785 bn_base = BN_bin2bn(base, base_len, NULL);
786 bn_exp = BN_bin2bn(exp, exp_len, NULL);
787 bn_mod = BN_bin2bn(mod, mod_len, NULL);
788 ctx = BN_CTX_new();
789
790 bn_dest = BN_new();
791 BN_mod_exp(bn_dest, bn_base, bn_exp, bn_mod, ctx);
792 BN_CTX_free(ctx);
793
794 len = BN_num_bytes(bn_dest);
795 if (len > dest_len) {
796 LOG("len > dest_len");
797 return -1;
798 }
799
800 gap = dest_len - len;
801 memset(dest, 0, gap);
802 BN_bn2bin(bn_dest, &dest[gap]);
803
804 BN_free(bn_dest);
805 BN_free(bn_mod);
806 BN_free(bn_exp);
807 BN_free(bn_base);
808
809 return 0;
810 }
811
dh_dhph_signature(uint8_t * out,uint8_t * nonce,uint8_t * dhph,RSA * r)812 int dh_dhph_signature(uint8_t *out, uint8_t *nonce, uint8_t *dhph, RSA *r) {
813 unsigned char dest[302];
814 uint8_t hash[20];
815 unsigned char dbuf[256];
816
817 dest[0x00] = 0x00; /* version */
818 dest[0x01] = 0x00;
819 dest[0x02] = 0x08; /* len (bits) */
820 dest[0x03] = 0x01; /* version data */
821
822 dest[0x04] = 0x01; /* msg_label */
823 dest[0x05] = 0x00;
824 dest[0x06] = 0x08; /* len (bits) */
825 dest[0x07] = 0x02; /* message data */
826
827 dest[0x08] = 0x02; /* auth_nonce */
828 dest[0x09] = 0x01;
829 dest[0x0a] = 0x00; /* len (bits) */
830 memcpy(&dest[0x0b], nonce, 32);
831
832 dest[0x2b] = 0x04; /* DHPH - DH public key host */
833 dest[0x2c] = 0x08;
834 dest[0x2d] = 0x00; /* len (bits) */
835 memcpy(&dest[0x2e], dhph, 256);
836
837 SHA1(dest, 0x12e, hash);
838
839 if (pkcs_1_pss_encode(hash, 20, 20, 0x800, dbuf, sizeof(dbuf))) {
840 LOG("pss encode failed");
841 return -1;
842 }
843
844 RSA_private_encrypt(sizeof(dbuf), dbuf, out, r, RSA_NO_PADDING);
845
846 return 0;
847 }
848
is_ca_initializing(int i)849 int is_ca_initializing(int i) {
850 if (i >= 0 && i < MAX_ADAPTERS && ca_devices[i] && ca_devices[i]->enabled &&
851 !ca_devices[i]->init_ok)
852 return 1;
853 return 0;
854 }
855
get_max_pmt_for_ca(int i)856 int get_max_pmt_for_ca(int i) {
857 if (i >= 0 && i < MAX_ADAPTERS && ca_devices[i] && ca_devices[i]->enabled)
858 return (ca_devices[i]->multiple_pmt + 1) * ca_devices[i]->max_ca_pmt;
859 return MAX_CA_PMT;
860 }
861
send_cw_to_all_pmts(ca_device_t * d,int parity)862 void send_cw_to_all_pmts(ca_device_t *d, int parity) {
863 int i;
864 for (i = 0; i < d->max_ca_pmt; i++) {
865 if (PMT_ID_IS_VALID(d->capmt[i].pmt_id)) {
866 send_cw(d->capmt[i].pmt_id, CA_ALGO_AES128_CBC, parity,
867 d->key[parity], d->iv[parity], 3720);
868 }
869 if (PMT_ID_IS_VALID(d->capmt[i].other_id)) {
870 send_cw(d->capmt[i].other_id, CA_ALGO_AES128_CBC, parity,
871 d->key[parity], d->iv[parity], 3720);
872 }
873 }
874 }
875
disable_cws_for_all_pmts(ca_device_t * d)876 void disable_cws_for_all_pmts(ca_device_t *d) {
877 int i;
878 for (i = 0; i < d->max_ca_pmt; i++) {
879 if (PMT_ID_IS_VALID(d->capmt[i].pmt_id)) {
880 disable_cw(d->capmt[i].pmt_id);
881 }
882 if (PMT_ID_IS_VALID(d->capmt[i].other_id)) {
883 disable_cw(d->capmt[i].other_id);
884 }
885 }
886 }
887
create_capmt(SCAPMT * ca,int listmgmt,uint8_t * capmt,int capmt_len,int cmd_id)888 int create_capmt(SCAPMT *ca, int listmgmt, uint8_t *capmt, int capmt_len,
889 int cmd_id) {
890 int pos = 0;
891 SPMT *pmt = get_pmt(ca->pmt_id);
892 SPMT *other = get_pmt(ca->other_id);
893 int version = ca->version;
894
895 if (!pmt)
896 LOG_AND_RETURN(1, "%s: PMT %d not found", __FUNCTION__, ca->pmt_id);
897
898 capmt[pos++] = listmgmt;
899 copy16(capmt, pos, ca->sid);
900 pos += 2;
901 capmt[pos++] = ((version & 0xF) << 1);
902 capmt[pos++] = 0; // PI LEN 2 bytes, set 0
903 capmt[pos++] = 0;
904
905 pos += CAPMT_add_PMT(capmt + pos, capmt_len - pos, pmt, cmd_id);
906 if (other) {
907 pos += CAPMT_add_PMT(capmt + pos, capmt_len - pos, other, cmd_id);
908 }
909
910 return pos;
911 }
912
913 // Creates and Sends 2 PMTs to bundle them into the same CAPMT
914 // Second PMT can be NULL
send_capmt(struct en50221_app_ca * ca_resource,int ca_session_number,SCAPMT * ca,int listmgmt,int reason)915 int send_capmt(struct en50221_app_ca *ca_resource, int ca_session_number,
916 SCAPMT *ca, int listmgmt, int reason) {
917 uint8_t capmt[8192];
918 int rc;
919 memset(capmt, 0, sizeof(capmt));
920
921 int size = create_capmt(ca, listmgmt, capmt, sizeof(capmt), reason);
922 hexdump("CAPMT: ", capmt, size);
923
924 if (size <= 0)
925 LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY, "create_capmt failed");
926
927 if ((rc =
928 en50221_app_ca_pmt(ca_resource, ca_session_number, capmt, size))) {
929 LOG("Failed to send CA PMT object, error %d", rc);
930 }
931 return rc;
932 }
933
get_enabled_pmts_for_ca(ca_device_t * d)934 int get_enabled_pmts_for_ca(ca_device_t *d) {
935 int i, enabled_pmts = 0;
936 for (i = 0; i < d->max_ca_pmt; i++) {
937 if (PMT_ID_IS_VALID(d->capmt[i].pmt_id))
938 enabled_pmts++;
939 if (PMT_ID_IS_VALID(d->capmt[i].other_id))
940 enabled_pmts++;
941 }
942 return enabled_pmts;
943 }
944
add_pmt_to_capmt(ca_device_t * d,SPMT * pmt,int multiple)945 SCAPMT *add_pmt_to_capmt(ca_device_t *d, SPMT *pmt, int multiple) {
946 int ca_pos;
947 SCAPMT *res = NULL;
948 for (ca_pos = 0; ca_pos < d->max_ca_pmt; ca_pos++) {
949 if (d->capmt[ca_pos].pmt_id == -1) {
950 d->capmt[ca_pos].pmt_id = pmt->id;
951 res = d->capmt + ca_pos;
952 break;
953 }
954 if (multiple && d->capmt[ca_pos].other_id == -1) {
955 d->capmt[ca_pos].other_id = pmt->id;
956 res = d->capmt + ca_pos;
957 break;
958 }
959 }
960
961 if (res) {
962 res->version = (res->version + 1) & 0xF;
963 } else {
964 LOG("CA %d all channels used %d, multiple allowed %d", d->id,
965 d->max_ca_pmt, multiple);
966 for (ca_pos = 0; ca_pos < d->max_ca_pmt; ca_pos++) {
967 LOG("CAPMT %d pmts %d %d", ca_pos, d->capmt[ca_pos].pmt_id,
968 d->capmt[ca_pos].other_id);
969 }
970 }
971
972 return res;
973 }
974
get_active_capmts(ca_device_t * d)975 int get_active_capmts(ca_device_t *d) {
976 int i, active = 0;
977 for (i = 0; i < d->max_ca_pmt; i++)
978 if (PMT_ID_IS_VALID(d->capmt[i].pmt_id) ||
979 PMT_ID_IS_VALID(d->capmt[i].other_id))
980 active++;
981 return active;
982 }
983
984 // Sending _LIST, _MORE and _LAST leads to decryption issues on some CAMs
985 // (existing channels are restarted) This method tries to send _ONLY for the
986 // first PMT or when the sid changes (when 2 PMTs are packed inside the same
987 // CAPMT) and uses just _UPDATE to update the existing and new CAPMT According
988 // to the docs _ADD should be used for new CAPMTs but _UPDATE with a new sid
989 // works To not leak sids, the first channel will have the original SID (some
990 // CAMs do not like this), the other ones a fixed SID
991
dvbca_process_pmt(adapter * ad,SPMT * spmt)992 int dvbca_process_pmt(adapter *ad, SPMT *spmt) {
993 ca_device_t *d = ca_devices[ad->id];
994 uint16_t pid, sid, ver;
995 int listmgmt;
996 SPMT *first = NULL;
997
998 if (!d)
999 return TABLES_RESULT_ERROR_NORETRY;
1000 if (!d->init_ok)
1001 LOG_AND_RETURN(TABLES_RESULT_ERROR_RETRY, "CAM not yet initialized");
1002
1003 SCAPMT *capmt = add_pmt_to_capmt(d, spmt, d->multiple_pmt);
1004 if (!capmt)
1005 LOG_AND_RETURN(TABLES_RESULT_ERROR_RETRY,
1006 "No free slots to add PMT %d to CA %d", spmt->id, d->id);
1007
1008 first = get_pmt(capmt->pmt_id);
1009 if (!first)
1010 LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY,
1011 "First PMT not found from capmt %d", capmt->pmt_id);
1012 pid = spmt->pid;
1013 ver = capmt->version;
1014 sid = spmt->sid;
1015
1016 listmgmt = get_active_capmts(d) == 1 ? CLM_ONLY : CLM_UPDATE;
1017 if (listmgmt == CLM_ONLY) {
1018 if (capmt->sid == first->sid)
1019 listmgmt = CLM_UPDATE;
1020 capmt->sid = first->sid;
1021 int i;
1022 for (i = 0; i < d->max_ca_pmt; i++) {
1023 int sid = MAKE_SID_FOR_CA(d->id, i);
1024 if (capmt != d->capmt + i) {
1025 if (capmt->sid == sid)
1026 d->capmt[i].sid = MAKE_SID_FOR_CA(d->id, MAX_CA_PMT);
1027 else
1028 d->capmt[i].sid = sid;
1029 }
1030 }
1031 }
1032
1033 LOG("PMT CA %d pmt %d pid %u (%s) ver %u sid %u (%d), "
1034 "enabled_pmts %d, "
1035 "%s, PMTS to be send %d %d, pos %ld",
1036 spmt->adapter, spmt->id, pid, spmt->name, ver, sid, capmt->sid,
1037 get_enabled_pmts_for_ca(d), listmgmt_str[listmgmt], capmt->pmt_id,
1038 capmt->other_id, capmt - d->capmt);
1039
1040 if (send_capmt(d->ca_resource, d->ca_session_number, capmt, listmgmt,
1041 CA_PMT_CMD_ID_OK_DESCRAMBLING))
1042 LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY, "send_capmt failed");
1043
1044 if (d->key[0][0])
1045 send_cw(spmt->id, CA_ALGO_AES128_CBC, 0, d->key[0], d->iv[0],
1046 3600); // 1 hour
1047 if (d->key[1][0])
1048 send_cw(spmt->id, CA_ALGO_AES128_CBC, 1, d->key[1], d->iv[1], 3600);
1049
1050 return 0;
1051 }
1052
1053 // Remove the PMT from the CAPMT associated with this device
1054 // if the pmt_id is not valid and other_id is valid,
1055 // exchange the IDs
remove_pmt_from_device(ca_device_t * d,SPMT * pmt)1056 void remove_pmt_from_device(ca_device_t *d, SPMT *pmt) {
1057 int i;
1058 for (i = 0; i < d->max_ca_pmt; i++) {
1059 if (d->capmt[i].pmt_id == pmt->id) {
1060 d->capmt[i].pmt_id = PMT_INVALID;
1061 if (PMT_ID_IS_VALID(d->capmt[i].other_id)) {
1062 d->capmt[i].pmt_id = d->capmt[i].other_id;
1063 d->capmt[i].other_id = PMT_INVALID;
1064 d->capmt[i].version++;
1065 }
1066 }
1067 if (d->capmt[i].other_id == pmt->id) {
1068 d->capmt[i].other_id = PMT_INVALID;
1069 d->capmt[i].version++;
1070 }
1071 }
1072 return;
1073 }
1074
get_capmt_for_pmt(ca_device_t * d,SPMT * pmt)1075 SCAPMT *get_capmt_for_pmt(ca_device_t *d, SPMT *pmt) {
1076 int i;
1077 for (i = 0; i < d->max_ca_pmt; i++)
1078 if (d->capmt[i].pmt_id == pmt->id || d->capmt[i].other_id == pmt->id)
1079 return d->capmt + i;
1080 return NULL;
1081 }
1082
dvbca_del_pmt(adapter * ad,SPMT * spmt)1083 int dvbca_del_pmt(adapter *ad, SPMT *spmt) {
1084 ca_device_t *d = ca_devices[ad->id];
1085 int listmgmt = -1;
1086
1087 SCAPMT *capmt = get_capmt_for_pmt(d, spmt);
1088 if (!capmt)
1089 LOG_AND_RETURN(0, "CAPMT not found for pmt %d", spmt->id);
1090
1091 remove_pmt_from_device(d, spmt);
1092 if (PMT_ID_IS_VALID(capmt->pmt_id)) {
1093 listmgmt = CLM_UPDATE;
1094 if (send_capmt(d->ca_resource, d->ca_session_number, capmt, listmgmt,
1095 CA_PMT_CMD_ID_OK_DESCRAMBLING))
1096 LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY,
1097 "%s: send_capmt failed for pmt ids %d", __FUNCTION__,
1098 capmt->pmt_id)
1099 }
1100 LOG("PMT CA %d DEL pmt %d pid %u, sid %u (%u), ver %d, %s name: %s",
1101 spmt->adapter, spmt->id, spmt->pid, spmt->sid, capmt->sid,
1102 capmt->version, listmgmt >= 0 ? listmgmt_str[listmgmt] : "NO UPDATE",
1103 spmt->name);
1104 return 0;
1105 }
1106
ciplus13_app_ai_data_rate_info(ca_device_t * d,ciplus13_data_rate_t rate)1107 static int ciplus13_app_ai_data_rate_info(ca_device_t *d,
1108 ciplus13_data_rate_t rate) {
1109 uint8_t data[] = {0x9f, 0x80, 0x24, 0x01, (uint8_t)rate};
1110
1111 /* only version 3 (CI+ 1.3) supports data_rate_info - no it isn't, 1.2
1112 * support too*/
1113 if (d->ca_ai_version < 2)
1114 return 0;
1115
1116 LOG("setting CI+ CAM data rate to %s Mbps", rate ? "96" : "72");
1117
1118 return en50221_sl_send_data(d->sl, d->ai_session_number, data,
1119 sizeof(data));
1120 }
1121
ca_ai_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t application_type,uint16_t application_manufacturer,uint16_t manufacturer_code,uint8_t menu_string_length,uint8_t * menu_string)1122 int ca_ai_callback(void *arg, uint8_t slot_id, uint16_t session_number,
1123 uint8_t application_type, uint16_t application_manufacturer,
1124 uint16_t manufacturer_code, uint8_t menu_string_length,
1125 uint8_t *menu_string) {
1126 ca_device_t *d = arg;
1127
1128 LOG("%02x:%s", slot_id, __func__);
1129 LOG(" Application type: %02x", application_type);
1130 LOG(" Application manufacturer: %04x", application_manufacturer);
1131 LOG(" Manufacturer code: %04x", manufacturer_code);
1132 LOG(" Menu string: %.*s", menu_string_length, menu_string);
1133
1134 d->ai_session_number = session_number;
1135 memcpy(d->ci_name, menu_string, menu_string_length);
1136 return 0;
1137 }
1138
element_get(struct cc_ctrl_data * cc_data,unsigned int id)1139 static struct element *element_get(struct cc_ctrl_data *cc_data,
1140 unsigned int id) {
1141 /* array index */
1142 if ((id < 1) || (id >= MAX_ELEMENTS)) {
1143 LOG("element_get: invalid id");
1144 return NULL;
1145 }
1146 return &cc_data->elements[id];
1147 }
1148
element_invalidate(struct cc_ctrl_data * cc_data,unsigned int id)1149 static void element_invalidate(struct cc_ctrl_data *cc_data, unsigned int id) {
1150 struct element *e;
1151
1152 e = element_get(cc_data, id);
1153 if (e) {
1154 free(e->data);
1155 memset(e, 0, sizeof(struct element));
1156 }
1157 }
1158
element_init(struct cc_ctrl_data * cc_data)1159 static void element_init(struct cc_ctrl_data *cc_data) {
1160 unsigned int i;
1161
1162 for (i = 1; i < MAX_ELEMENTS; i++)
1163 element_invalidate(cc_data, i);
1164 }
1165
element_set(struct cc_ctrl_data * cc_data,unsigned int id,const uint8_t * data,uint32_t size)1166 static int element_set(struct cc_ctrl_data *cc_data, unsigned int id,
1167 const uint8_t *data, uint32_t size) {
1168 struct element *e;
1169
1170 e = element_get(cc_data, id);
1171 if (e == NULL)
1172 return 0;
1173
1174 /* check size */
1175 if ((datatype_sizes[id] != 0) && (datatype_sizes[id] != size)) {
1176 LOG("size %d of datatype_id %d doesn't match", size, id);
1177 return 0;
1178 }
1179
1180 free(e->data);
1181 e->data = malloc(size);
1182 memcpy(e->data, data, size);
1183 e->size = size;
1184 e->valid = 1;
1185
1186 LOGM("_element_set_ stored %d with len %d", id, size);
1187 // hexdump("DATA: ", (void *)data, size);
1188 return 1;
1189 }
1190
element_set_certificate(struct cc_ctrl_data * cc_data,unsigned int id,X509 * cert)1191 static int element_set_certificate(struct cc_ctrl_data *cc_data,
1192 unsigned int id, X509 *cert) {
1193 unsigned char *cert_der = NULL;
1194 int cert_len;
1195
1196 cert_len = i2d_X509(cert, &cert_der);
1197 if (cert_len <= 0) {
1198 LOG("can not get data in DER format");
1199 return 0;
1200 }
1201
1202 if (!element_set(cc_data, id, cert_der, cert_len)) {
1203 LOG("can not store element (%d)", id);
1204 return 0;
1205 }
1206
1207 return 1;
1208 }
1209
element_set_hostid_from_certificate(struct cc_ctrl_data * cc_data,unsigned int id,X509 * cert)1210 static int element_set_hostid_from_certificate(struct cc_ctrl_data *cc_data,
1211 unsigned int id, X509 *cert) {
1212 X509_NAME *subject;
1213 int nid_cn = OBJ_txt2nid("CN");
1214 char hostid[20];
1215 uint8_t bin_hostid[8];
1216
1217 if ((id != 5) && (id != 6)) {
1218 LOG("wrong datatype_id for hostid");
1219 return 0;
1220 }
1221
1222 subject = X509_get_subject_name(cert);
1223 X509_NAME_get_text_by_NID(subject, nid_cn, hostid, sizeof(hostid));
1224
1225 if (strlen(hostid) != 16) {
1226 LOG("malformed hostid");
1227 return 0;
1228 }
1229 LOG("%sID: %s", id == 5 ? "HOST" : "CICAM", hostid);
1230
1231 str2bin(bin_hostid, hostid, 16);
1232
1233 if (!element_set(cc_data, id, bin_hostid, sizeof(bin_hostid))) {
1234 LOG("can not set hostid");
1235 return 0;
1236 }
1237
1238 return 1;
1239 }
1240
element_valid(struct cc_ctrl_data * cc_data,unsigned int id)1241 static int element_valid(struct cc_ctrl_data *cc_data, unsigned int id) {
1242 struct element *e;
1243
1244 e = element_get(cc_data, id);
1245
1246 return e && e->valid;
1247 }
1248
element_get_buf(struct cc_ctrl_data * cc_data,uint8_t * dest,unsigned int id)1249 static unsigned int element_get_buf(struct cc_ctrl_data *cc_data, uint8_t *dest,
1250 unsigned int id) {
1251 struct element *e;
1252
1253 e = element_get(cc_data, id);
1254 if (e == NULL)
1255 return 0;
1256
1257 if (!e->valid) {
1258 LOG("element_get_buf: datatype %d not valid", id);
1259 return 0;
1260 }
1261
1262 if (!e->data) {
1263 LOG("element_get_buf: datatype %d doesn't exist", id);
1264 return 0;
1265 }
1266
1267 if (dest)
1268 memcpy(dest, e->data, e->size);
1269
1270 return e->size;
1271 }
1272
element_get_req(struct cc_ctrl_data * cc_data,uint8_t * dest,unsigned int id)1273 static unsigned int element_get_req(struct cc_ctrl_data *cc_data, uint8_t *dest,
1274 unsigned int id) {
1275 unsigned int len = element_get_buf(cc_data, &dest[3], id);
1276
1277 if (len == 0) {
1278 LOG("can not get element %d", id);
1279 return 0;
1280 }
1281
1282 dest[0] = id;
1283 dest[1] = len >> 8;
1284 dest[2] = len;
1285
1286 return 3 + len;
1287 }
1288
element_get_ptr(struct cc_ctrl_data * cc_data,unsigned int id)1289 static uint8_t *element_get_ptr(struct cc_ctrl_data *cc_data, unsigned int id) {
1290 struct element *e;
1291
1292 e = element_get(cc_data, id);
1293 if (e == NULL)
1294 return NULL;
1295
1296 if (!e->valid) {
1297 LOG("element_get_ptr: datatype %u not valid", id);
1298 return NULL;
1299 }
1300
1301 if (!e->data) {
1302 LOG("element_get_ptr: datatype %u doesn't exist", id);
1303
1304 return NULL;
1305 }
1306
1307 return e->data;
1308 }
1309
get_authdata_filename(char * dest,size_t len,unsigned int slot,char * ci_name)1310 static void get_authdata_filename(char *dest, size_t len, unsigned int slot,
1311 char *ci_name) {
1312 char cin[128];
1313 char source[256];
1314 char target[256];
1315 /* add module name to slot authorization bin file */
1316 memset(cin, 0, sizeof(cin));
1317 strncpy(cin, ci_name, sizeof(cin) - 1);
1318 FILE *auth_bin;
1319 /* quickly replace blanks */
1320 int i = 0;
1321 while (cin[i] != 0) {
1322 if (cin[i] == 32)
1323 cin[i] = 95; /* underscore _ */
1324 i++;
1325 };
1326 snprintf(source, sizeof(source) - 1, "%s/ci_auth_%d.bin", getenv("HOME"),
1327 slot);
1328 snprintf(target, sizeof(target) - 1, "%s/ci_auth_%s_%d.bin", getenv("HOME"),
1329 cin, slot);
1330
1331 struct stat buf;
1332
1333 if (lstat(source, &buf) == 0) {
1334
1335 char linkname[4096];
1336 memset(linkname, 0, sizeof(linkname));
1337 ssize_t len = readlink(source, linkname, sizeof(linkname) - 1);
1338 if (len > 0) {
1339 if (strcmp(linkname, target) != 0) {
1340 /* link doesn't point to target */
1341 auth_bin = fopen(target, "r");
1342 if (auth_bin)
1343 fclose(auth_bin);
1344 /* correct symlink */
1345 int r = remove(source);
1346 LOG("CORRECTING %s to %s %s", target, source,
1347 r ? "" : "(remove failed)");
1348 symlink(target, source);
1349 }
1350 } else {
1351 auth_bin = fopen(target, "r");
1352 if (auth_bin) {
1353 /* if new file already exists and source is not symlink.
1354 remove and do symlink */
1355 fclose(auth_bin);
1356 int r = remove(source);
1357 LOG("LINKING %s to %s %s", target, source,
1358 r ? "" : "(remove failed)");
1359 symlink(target, source);
1360 } else {
1361 /* target doesn't exist needs migration...
1362 which means rename old bin file without module name
1363 to new file with module name and do symlink to old one */
1364 LOG("MIGRATING %s to %s", source, target);
1365 if (!rename(source, target))
1366 symlink(target, source);
1367 }
1368 }
1369 } else {
1370 auth_bin = fopen(target, "r");
1371 if (auth_bin) {
1372 /* if new file already exists and source is nit there
1373 simply do symlink */
1374 fclose(auth_bin);
1375 LOG("LINKING %s to %s", target, source);
1376 symlink(target, source);
1377 }
1378 /* else do nothing to prevent stranded symlinks */
1379 }
1380 snprintf(dest, len, "%s/ci_auth_%s_%d.bin", getenv("HOME"), cin, slot);
1381 }
1382
get_authdata(uint8_t * host_id,uint8_t * dhsk,uint8_t * akh,unsigned int slot,unsigned int index,char * ci_name)1383 static int get_authdata(uint8_t *host_id, uint8_t *dhsk, uint8_t *akh,
1384 unsigned int slot, unsigned int index, char *ci_name) {
1385 char filename[FILENAME_MAX];
1386 int fd;
1387 uint8_t chunk[8 + 256 + 32];
1388 unsigned int i;
1389 /* 5 pairs of data only */
1390 if (index > MAX_PAIRS)
1391 return 0;
1392
1393 get_authdata_filename(filename, sizeof(filename), slot, ci_name);
1394
1395 fd = open(filename, O_RDONLY);
1396 if (fd < 0) {
1397 LOG("cannot open %s", filename);
1398 return 0;
1399 }
1400
1401 for (i = 0; i < MAX_PAIRS; i++) {
1402 if (read(fd, chunk, sizeof(chunk)) != sizeof(chunk)) {
1403 LOG("cannot read auth_data");
1404 close(fd);
1405 return 0;
1406 }
1407 if (i == index) {
1408 memcpy(host_id, chunk, 8);
1409 memcpy(dhsk, &chunk[8], 256);
1410 memcpy(akh, &chunk[8 + 256], 32);
1411 close(fd);
1412 return 1;
1413 }
1414 }
1415
1416 close(fd);
1417 return 0;
1418 }
1419
write_authdata(unsigned int slot,const uint8_t * host_id,const uint8_t * dhsk,const uint8_t * akh,char * ci_name)1420 static int write_authdata(unsigned int slot, const uint8_t *host_id,
1421 const uint8_t *dhsk, const uint8_t *akh,
1422 char *ci_name) {
1423 char filename[FILENAME_MAX];
1424 int fd;
1425 uint8_t buf[(8 + 256 + 32) * MAX_PAIRS];
1426 unsigned int entries;
1427 unsigned int i;
1428
1429 int ret = 0;
1430
1431 for (entries = 0; entries < MAX_PAIRS; entries++) {
1432 int offset = (8 + 256 + 32) * entries;
1433 if (!get_authdata(&buf[offset], &buf[offset + 8],
1434 &buf[offset + 8 + 256], slot, entries, ci_name))
1435 break;
1436
1437 /* check if we got this pair already */
1438 if (!memcmp(&buf[offset + 8 + 256], akh, 32)) {
1439 LOG("data already stored");
1440 return 1;
1441 }
1442 }
1443
1444 LOG("got %d entries", entries);
1445
1446 get_authdata_filename(filename, sizeof(filename), slot, ci_name);
1447
1448 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
1449 if (fd < 0) {
1450 LOG("cannot open %s for writing - authdata not stored", filename);
1451 return 0;
1452 }
1453
1454 /* store new entry first */
1455 if (write(fd, host_id, 8) != 8) {
1456 LOG("error in write");
1457 goto end;
1458 }
1459
1460 if (write(fd, dhsk, 256) != 256) {
1461 LOG("error in write");
1462 goto end;
1463 }
1464
1465 if (write(fd, akh, 32) != 32) {
1466 LOG("error in write");
1467 goto end;
1468 }
1469
1470 /* skip the last one if exists */
1471 if (entries > 3)
1472 entries = 3;
1473
1474 for (i = 0; i < entries; i++) {
1475 int offset = (8 + 256 + 32) * i;
1476 if (write(fd, &buf[offset], (8 + 256 + 32)) != (8 + 256 + 32)) {
1477 LOG("error in write");
1478 goto end;
1479 }
1480 }
1481
1482 ret = 1;
1483 end:
1484 close(fd);
1485
1486 return ret;
1487 }
1488
data_initialize(struct ci_session * session)1489 static int data_initialize(struct ci_session *session) {
1490 struct cc_ctrl_data *data;
1491 uint8_t buf[32], host_id[8];
1492
1493 if (session->private_data) {
1494
1495 LOG("strange private_data not null!");
1496 session->private_data = 0;
1497 // return false;
1498 }
1499
1500 data = calloc(1, sizeof(struct cc_ctrl_data));
1501 if (!data) {
1502 LOG("out of memory");
1503 return 0;
1504 }
1505
1506 /* parent */
1507 data->session = session;
1508
1509 /* clear storage of credentials */
1510 element_init(data);
1511
1512 /* set status field - OK */
1513 memset(buf, 0, 1);
1514 if (!element_set(data, 30, buf, 1)) {
1515 LOG("can not set status in elements");
1516 }
1517
1518 /* set uri versions */
1519 memset(buf, 0, 32);
1520 buf[31] = session->ca->uri_mask; // uri version bitmask, e.g. 1-3
1521 LOG("uri version bitmask set to '%d'", buf[31]);
1522 if (!element_set(data, 29, buf, 32)) {
1523 LOG("can not set uri_versions in elements");
1524 }
1525 /* load first AKH */
1526 data->akh_index = 0;
1527 if (!get_authdata(host_id, data->dhsk, buf, session->ca->id,
1528 data->akh_index, session->ca->ci_name)) {
1529 // if (!get_authdata(host_id, data->dhsk, buf, 1,
1530 // data->akh_index)) {
1531 /* no AKH available */
1532 memset(buf, 0, sizeof(buf));
1533 data->akh_index = 5; /* last one */
1534 }
1535
1536 if (!element_set(data, 22, buf, 32)) {
1537 LOG("can not set AKH in elements");
1538 }
1539
1540 if (!element_set(data, 5, host_id, 8)) {
1541 LOG("can not set host_id elements");
1542 }
1543
1544 session->private_data = data;
1545
1546 return 1;
1547 }
1548 /* content_control commands */
1549
sac_check_auth(const uint8_t * data,unsigned int len,uint8_t * sak)1550 static int sac_check_auth(const uint8_t *data, unsigned int len, uint8_t *sak) {
1551 struct aes_xcbc_mac_ctx ctx;
1552 uint8_t calced_signature[16];
1553
1554 if (len < 16) {
1555 LOG("auth too short");
1556 return 0;
1557 }
1558
1559 aes_xcbc_mac_init(&ctx, sak);
1560 aes_xcbc_mac_process(&ctx, (uint8_t *)"\x04", 1); /* header len */
1561 aes_xcbc_mac_process(&ctx, data, len - 16);
1562 aes_xcbc_mac_done(&ctx, calced_signature);
1563
1564 if (memcmp(&data[len - 16], calced_signature, 16)) {
1565 LOG("signature wrong");
1566 return 0;
1567 }
1568
1569 LOG("auth ok!");
1570 return 1;
1571 }
1572
sac_gen_auth(uint8_t * out,uint8_t * in,unsigned int len,uint8_t * sak)1573 static int sac_gen_auth(uint8_t *out, uint8_t *in, unsigned int len,
1574 uint8_t *sak) {
1575 struct aes_xcbc_mac_ctx ctx;
1576
1577 aes_xcbc_mac_init(&ctx, sak);
1578 aes_xcbc_mac_process(&ctx, (uint8_t *)"\x04", 1); /* header len */
1579 aes_xcbc_mac_process(&ctx, in, len);
1580 aes_xcbc_mac_done(&ctx, out);
1581
1582 return 16;
1583 }
1584
generate_key_seed(struct cc_ctrl_data * cc_data)1585 static void generate_key_seed(struct cc_ctrl_data *cc_data) {
1586 /* this is triggered by new ns_module */
1587
1588 /* generate new key_seed -> SEK/SAK key derivation */
1589
1590 SHA256_CTX sha;
1591
1592 SHA256_Init(&sha);
1593 SHA256_Update(&sha, &cc_data->dhsk[240], 16);
1594 SHA256_Update(&sha, element_get_ptr(cc_data, 22),
1595 element_get_buf(cc_data, NULL, 22));
1596 SHA256_Update(&sha, element_get_ptr(cc_data, 20),
1597 element_get_buf(cc_data, NULL, 20));
1598 SHA256_Update(&sha, element_get_ptr(cc_data, 21),
1599 element_get_buf(cc_data, NULL, 21));
1600 SHA256_Final(cc_data->ks_host, &sha);
1601 }
1602
generate_ns_host(struct cc_ctrl_data * cc_data)1603 static void generate_ns_host(struct cc_ctrl_data *cc_data)
1604
1605 {
1606 uint8_t buf[8];
1607 get_random(buf, sizeof(buf));
1608 element_set(cc_data, 20, buf, sizeof(buf));
1609 }
1610
generate_SAK_SEK(uint8_t * sak,uint8_t * sek,const uint8_t * ks_host)1611 static int generate_SAK_SEK(uint8_t *sak, uint8_t *sek,
1612 const uint8_t *ks_host) {
1613 AES_KEY key;
1614 const uint8_t key_data[16] = {0xea, 0x74, 0xf4, 0x71, 0x99, 0xd7,
1615 0x6f, 0x35, 0x89, 0xf0, 0xd1, 0xdf,
1616 0x0f, 0xee, 0xe3, 0x00};
1617 uint8_t dec[32];
1618 int i;
1619
1620 /* key derivation of sak & sek */
1621 memset(&key, 0, sizeof(key));
1622
1623 AES_set_encrypt_key(key_data, 128, &key);
1624
1625 for (i = 0; i < 2; i++)
1626 AES_ecb_encrypt(&ks_host[16 * i], &dec[16 * i], &key, 1);
1627
1628 for (i = 0; i < 16; i++)
1629 sek[i] = ks_host[i] ^ dec[i];
1630
1631 for (i = 0; i < 16; i++)
1632 sak[i] = ks_host[16 + i] ^ dec[16 + i];
1633
1634 return 0;
1635 }
1636
sac_crypt(uint8_t * dst,const uint8_t * src,unsigned int len,const uint8_t * key_data,int encrypt)1637 static int sac_crypt(uint8_t *dst, const uint8_t *src, unsigned int len,
1638 const uint8_t *key_data, int encrypt) {
1639 uint8_t iv[16] = {0xf7, 0x70, 0xb0, 0x36, 0x03, 0x61, 0xf7, 0x96,
1640 0x65, 0x74, 0x8a, 0x26, 0xea, 0x4e, 0x85, 0x41};
1641 AES_KEY key;
1642
1643 /* AES_ENCRYPT is '1' */
1644 memset(&key, 0, sizeof(key));
1645
1646 if (encrypt)
1647 AES_set_encrypt_key(key_data, 128, &key);
1648 else
1649 AES_set_decrypt_key(key_data, 128, &key);
1650
1651 AES_cbc_encrypt(src, dst, len, &key, iv, encrypt);
1652
1653 return 0;
1654 }
1655
verify_cb(int ok,X509_STORE_CTX * ctx)1656 static int verify_cb(int ok, X509_STORE_CTX *ctx) {
1657 if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_NOT_YET_VALID) {
1658 time_t now = time(NULL);
1659 struct tm *t = localtime(&now);
1660 if (t->tm_year < 2015) {
1661 LOG("seems our rtc is wrong - ignore!");
1662 return 1;
1663 }
1664 }
1665
1666 if (X509_STORE_CTX_get_error(ctx) == X509_V_ERR_CERT_HAS_EXPIRED)
1667 return 1;
1668 return 0;
1669 }
1670
rsa_privatekey_open(const char * filename)1671 static RSA *rsa_privatekey_open(const char *filename) {
1672 FILE *fp;
1673 RSA *r = NULL;
1674
1675 fp = fopen(filename, "r");
1676 if (!fp) {
1677 LOG("can not open %s", filename);
1678 return NULL;
1679 }
1680
1681 PEM_read_RSAPrivateKey(fp, &r, NULL, NULL);
1682 if (!r) {
1683 LOG("read error");
1684 }
1685
1686 fclose(fp);
1687
1688 return r;
1689 }
1690
certificate_open(const char * filename)1691 static X509 *certificate_open(const char *filename) {
1692 FILE *fp;
1693 X509 *cert;
1694
1695 fp = fopen(filename, "r");
1696 if (!fp) {
1697 LOG("can not open %s", filename);
1698 return NULL;
1699 }
1700
1701 cert = PEM_read_X509(fp, NULL, NULL, NULL);
1702 if (!cert) {
1703 LOG("can not read cert");
1704 }
1705
1706 fclose(fp);
1707
1708 return cert;
1709 }
1710
certificate_validate(struct cert_ctx * ctx,X509 * cert)1711 static int certificate_validate(struct cert_ctx *ctx, X509 *cert) {
1712 X509_STORE_CTX *store_ctx;
1713 int ret;
1714
1715 store_ctx = X509_STORE_CTX_new();
1716
1717 X509_STORE_CTX_init(store_ctx, ctx->store, cert, NULL);
1718 X509_STORE_CTX_set_verify_cb(store_ctx, verify_cb);
1719 X509_STORE_CTX_set_flags(store_ctx, X509_V_FLAG_IGNORE_CRITICAL);
1720
1721 ret = X509_verify_cert(store_ctx);
1722
1723 if (ret != 1) {
1724 LOG("%s",
1725 X509_verify_cert_error_string(X509_STORE_CTX_get_error(store_ctx)));
1726 }
1727
1728 X509_STORE_CTX_free(store_ctx);
1729
1730 if (ret == 1)
1731 return 1;
1732 else
1733 return 0;
1734 }
1735
certificate_load_and_check(struct cert_ctx * ctx,const char * filename)1736 static X509 *certificate_load_and_check(struct cert_ctx *ctx,
1737 const char *filename) {
1738 X509 *cert;
1739
1740 if (!ctx->store) {
1741 /* we assume this is the first certificate added - so its root-ca */
1742 ctx->store = X509_STORE_new();
1743 if (!ctx->store) {
1744 LOG("can not create cert_store");
1745 exit(-1);
1746 }
1747
1748 if (X509_STORE_load_locations(ctx->store, filename, NULL) != 1) {
1749 LOG("load of first certificate (root_ca) failed");
1750 exit(-1);
1751 }
1752
1753 return NULL;
1754 }
1755
1756 cert = certificate_open(filename);
1757 if (!cert) {
1758 LOG("can not open certificate %s", filename);
1759 return NULL;
1760 }
1761
1762 if (!certificate_validate(ctx, cert)) {
1763 LOG("can not vaildate certificate");
1764 X509_free(cert);
1765 return NULL;
1766 }
1767
1768 /* push into store - create a chain */
1769 if (X509_STORE_load_locations(ctx->store, filename, NULL) != 1) {
1770 LOG("load of certificate failed");
1771 X509_free(cert);
1772 return NULL;
1773 }
1774
1775 return cert;
1776 }
1777
certificate_import_and_check(struct cert_ctx * ctx,const uint8_t * data,int len)1778 static X509 *certificate_import_and_check(struct cert_ctx *ctx,
1779 const uint8_t *data, int len) {
1780 X509 *cert;
1781
1782 cert = d2i_X509(NULL, &data, len);
1783 if (!cert) {
1784 LOG("can not read certificate");
1785 return NULL;
1786 }
1787
1788 if (!certificate_validate(ctx, cert)) {
1789 LOG("can not vaildate certificate");
1790 X509_free(cert);
1791 return NULL;
1792 }
1793
1794 X509_STORE_add_cert(ctx->store, cert);
1795
1796 return cert;
1797 }
1798
import_ci_certificates(struct cc_ctrl_data * cc_data,unsigned int id)1799 static X509 *import_ci_certificates(struct cc_ctrl_data *cc_data,
1800 unsigned int id) {
1801 struct cert_ctx *ctx = cc_data->cert_ctx;
1802 X509 *cert;
1803 uint8_t buf[2048];
1804 unsigned int len;
1805
1806 len = element_get_buf(cc_data, buf, id);
1807
1808 cert = certificate_import_and_check(ctx, buf, len);
1809 if (!cert) {
1810 LOG("cannot read/verify DER cert");
1811 return NULL;
1812 }
1813
1814 return cert;
1815 }
1816
check_ci_certificates(struct cc_ctrl_data * cc_data)1817 static int check_ci_certificates(struct cc_ctrl_data *cc_data) {
1818 struct cert_ctx *ctx = cc_data->cert_ctx;
1819
1820 /* check if both certificates are available before we push and verify them
1821 */
1822
1823 /* check for CICAM_BrandCert */
1824 if (!element_valid(cc_data, 8)) {
1825 LOG("CICAM brand cert invalid");
1826 return -1;
1827 }
1828
1829 /* check for CICAM_DevCert */
1830 if (!element_valid(cc_data, 16)) {
1831 LOG("CICAM device cert invalid");
1832 return -1;
1833 }
1834
1835 if (extract_ci_cert) {
1836 /* write ci device cert to disk */
1837 char ci_cert_file[256];
1838 memset(ci_cert_file, 0, sizeof(ci_cert_file));
1839 snprintf(ci_cert_file, sizeof(ci_cert_file) - 1,
1840 "/%s/ci_cert_%s_%d.der", getenv("HOME"), ci_name_underscore,
1841 ci_number);
1842 LOG("CI%d EXTRACTING %s", ci_number, ci_cert_file);
1843 int fd =
1844 open(ci_cert_file, O_CREAT | O_WRONLY | O_TRUNC, S_IRUSR | S_IWUSR);
1845 if (fd < 0)
1846 LOG_AND_RETURN(-1, "opening %s for writing failed", ci_cert_file);
1847 int ret = write(fd, element_get_ptr(cc_data, 16),
1848 element_get_buf(cc_data, NULL, 16));
1849 if (ret)
1850 LOG("write cert failed");
1851 close(fd);
1852 /* display strings in der cert file */
1853 cert_strings(ci_cert_file);
1854 }
1855
1856 /* import CICAM_BrandCert */
1857 if ((ctx->ci_cust_cert = import_ci_certificates(cc_data, 8)) == NULL) {
1858 LOG("can not import brand cert");
1859 return -1;
1860 }
1861
1862 /* import CICAM_DevCert */
1863 if ((ctx->ci_device_cert = import_ci_certificates(cc_data, 16)) == NULL) {
1864 LOG("can not import device cert");
1865 return -1;
1866 }
1867
1868 /* everything seems to be fine here - so extract the CICAM_id from cert */
1869 if (!element_set_hostid_from_certificate(cc_data, 6, ctx->ci_device_cert)) {
1870 LOG("can not set cicam_id in elements");
1871 return -1;
1872 }
1873
1874 return 0;
1875 }
1876
generate_akh(struct cc_ctrl_data * cc_data)1877 static int generate_akh(struct cc_ctrl_data *cc_data) {
1878 uint8_t akh[32];
1879 SHA256_CTX sha;
1880
1881 SHA256_Init(&sha);
1882 SHA256_Update(&sha, element_get_ptr(cc_data, 6),
1883 element_get_buf(cc_data, NULL, 6));
1884 SHA256_Update(&sha, element_get_ptr(cc_data, 5),
1885 element_get_buf(cc_data, NULL, 5));
1886 SHA256_Update(&sha, cc_data->dhsk, 256);
1887 SHA256_Final(akh, &sha);
1888
1889 element_set(cc_data, 22, akh, sizeof(akh));
1890
1891 return 0;
1892 }
1893
check_dh_challenge(struct cc_ctrl_data * cc_data)1894 static int check_dh_challenge(struct cc_ctrl_data *cc_data) {
1895 /* check if every element for calculation of DHSK & AKH is available */
1896 LOG("checking ...");
1897
1898 /* check for auth_nonce */
1899 if (!element_valid(cc_data, 19)) {
1900 LOG("auth nonce invalid");
1901 return 0;
1902 }
1903
1904 /* check for CICAM_id */
1905 if (!element_valid(cc_data, 6)) {
1906 LOG("cicam id invalid");
1907 return 0;
1908 }
1909
1910 /* check for DHPM */
1911 if (!element_valid(cc_data, 14)) {
1912 LOG("dphm invalid");
1913 return 0;
1914 }
1915
1916 /* check for Signature_B */
1917 if (!element_valid(cc_data, 18)) {
1918 LOG("signature B invalid");
1919 return 0;
1920 }
1921
1922 /* calculate DHSK - DHSK = DHPM ^ dh_exp % dh_p */
1923 dh_mod_exp(cc_data->dhsk, 256, element_get_ptr(cc_data, 14), 256, dh_p,
1924 sizeof(dh_p), cc_data->dh_exp, 256);
1925
1926 /* gen AKH */
1927 generate_akh(cc_data);
1928
1929 /* disable 5 tries of startup -> use new calculated one */
1930 cc_data->akh_index = 5;
1931
1932 LOG("writing authdata ...");
1933 /* write to disk */
1934 write_authdata(cc_data->session->ca->id, element_get_ptr(cc_data, 5),
1935 cc_data->dhsk, element_get_ptr(cc_data, 22),
1936 cc_data->session->ca->ci_name);
1937
1938 return 1;
1939 }
1940
restart_dh_challenge(struct cc_ctrl_data * cc_data)1941 static int restart_dh_challenge(struct cc_ctrl_data *cc_data) {
1942 uint8_t dhph[256], sign_A[256];
1943 struct cert_ctx *ctx;
1944 LOG(".... rechecking ...");
1945
1946 if (!cc_data->cert_ctx) {
1947 ctx = calloc(1, sizeof(struct cert_ctx));
1948 cc_data->cert_ctx = ctx;
1949 } else {
1950 ctx = cc_data->cert_ctx;
1951 }
1952
1953 /* load certificates and device key */
1954 certificate_load_and_check(ctx, "/etc/ssl/certs/root.pem");
1955 ctx->cust_cert =
1956 certificate_load_and_check(ctx, "/etc/ssl/certs/customer.pem");
1957 ctx->device_cert =
1958 certificate_load_and_check(ctx, "/etc/ssl/certs/device.pem");
1959
1960 if (!ctx->cust_cert || !ctx->device_cert) {
1961 LOG("can not check loader certificates");
1962 return -1;
1963 }
1964
1965 /* add data to element store */
1966 if (!element_set_certificate(cc_data, 7, ctx->cust_cert))
1967 LOG("can not store cert in elements");
1968
1969 if (!element_set_certificate(cc_data, 15, ctx->device_cert))
1970 LOG("can not store cert in elements");
1971
1972 if (!element_set_hostid_from_certificate(cc_data, 5, ctx->device_cert))
1973 LOG("can not set hostid in elements");
1974
1975 cc_data->rsa_device_key = rsa_privatekey_open("/etc/ssl/certs/device.pem");
1976 if (!cc_data->rsa_device_key) {
1977 LOG("can not read private key");
1978 return -1;
1979 }
1980
1981 /* invalidate elements */
1982 element_invalidate(cc_data, 6);
1983 element_invalidate(cc_data, 14);
1984 element_invalidate(cc_data, 18);
1985 element_invalidate(cc_data, 22); /* this will refuse a unknown cam */
1986
1987 /* new dh_exponent */
1988 dh_gen_exp(cc_data->dh_exp, 256, dh_g, sizeof(dh_g), dh_p, sizeof(dh_p));
1989
1990 /* new DHPH - DHPH = dh_g ^ dh_exp % dh_p */
1991 dh_mod_exp(dhph, sizeof(dhph), dh_g, sizeof(dh_g), dh_p, sizeof(dh_p),
1992 cc_data->dh_exp, 256);
1993
1994 /* store DHPH */
1995 element_set(cc_data, 13, dhph, sizeof(dhph));
1996
1997 /* create Signature_A */
1998 dh_dhph_signature(sign_A, element_get_ptr(cc_data, 19), dhph,
1999 cc_data->rsa_device_key);
2000
2001 /* store Signature_A */
2002 element_set(cc_data, 17, sign_A, sizeof(sign_A));
2003
2004 return 0;
2005 }
2006
generate_uri_confirm(struct cc_ctrl_data * cc_data,const uint8_t * sak)2007 static int generate_uri_confirm(struct cc_ctrl_data *cc_data,
2008 const uint8_t *sak) {
2009 SHA256_CTX sha;
2010 uint8_t uck[32];
2011 uint8_t uri_confirm[32];
2012
2013 /* calculate UCK (uri confirmation key) */
2014 SHA256_Init(&sha);
2015 SHA256_Update(&sha, sak, 16);
2016 SHA256_Final(uck, &sha);
2017
2018 /* calculate uri_confirm */
2019 SHA256_Init(&sha);
2020 SHA256_Update(&sha, element_get_ptr(cc_data, 25),
2021 element_get_buf(cc_data, NULL, 25));
2022 SHA256_Update(&sha, uck, 32);
2023 SHA256_Final(uri_confirm, &sha);
2024
2025 element_set(cc_data, 27, uri_confirm, 32);
2026
2027 return 0;
2028 }
2029
check_new_key(ca_device_t * d,struct cc_ctrl_data * cc_data)2030 static void check_new_key(ca_device_t *d, struct cc_ctrl_data *cc_data) {
2031 const uint8_t s_key[16] = {0x3e, 0x20, 0x15, 0x84, 0x2c, 0x37, 0xce, 0xe3,
2032 0xd6, 0x14, 0x57, 0x3e, 0x3a, 0xab, 0x91, 0xb6};
2033 AES_KEY aes_ctx;
2034 uint8_t dec[32];
2035 uint8_t *kp;
2036 uint8_t slot;
2037 unsigned int i;
2038 memset(&aes_ctx, 0, sizeof(aes_ctx));
2039
2040 /* check for keyprecursor */
2041 if (!element_valid(cc_data, 12)) {
2042 LOG("key precursor invalid");
2043 return;
2044 }
2045
2046 /* check for slot */
2047 if (!element_valid(cc_data, 28)) {
2048 LOG("slot(key register) invalid");
2049 return;
2050 }
2051 kp = element_get_ptr(cc_data, 12);
2052 element_get_buf(cc_data, &slot, 28);
2053
2054 AES_set_encrypt_key(s_key, 128, &aes_ctx);
2055 for (i = 0; i < 32; i += 16)
2056 AES_ecb_encrypt(&kp[i], &dec[i], &aes_ctx, 1);
2057
2058 for (i = 0; i < 32; i++)
2059 dec[i] ^= kp[i];
2060
2061 LOGM("=== descrambler_set_key === adapter = CA%i key regiser (0-even, "
2062 "1-odd) "
2063 "= %i",
2064 cc_data->session->ca->id, slot);
2065 char buf[400];
2066 int pos;
2067 pos = sprintf(buf, "KEY: ");
2068 for (i = 0; i < 16; i++)
2069 pos += sprintf(buf + pos, "%02X ", dec[i]);
2070 pos += sprintf(buf + pos, "\n\t\t\t\t\t\tIV: ");
2071 for (i = 16; i < 32; i++)
2072 pos += sprintf(buf + pos, "%02X ", dec[i]);
2073 LOG("received from CI+ CAM %d: %s", d->id, buf);
2074
2075 memcpy(d->key[slot], dec, 16);
2076 memcpy(d->iv[slot], dec + 16, 16);
2077 d->parity = slot;
2078
2079 send_cw_to_all_pmts(d, slot);
2080
2081 d->is_ciplus = 1;
2082
2083 /* reset */
2084 element_invalidate(cc_data, 12);
2085 element_invalidate(cc_data, 28);
2086 }
2087
data_get_handle_new(ca_device_t * d,struct cc_ctrl_data * cc_data,unsigned int id)2088 static int data_get_handle_new(ca_device_t *d, struct cc_ctrl_data *cc_data,
2089 unsigned int id) {
2090 /* handle trigger events */
2091
2092 /* depends on new received items */
2093 // LOG("!!!!!!!!!!!!!!!!!!!! data_get_handle_new ID =
2094 // %i!!!!!!!!!!!!!!!!!!!!!!!!!", id);
2095 switch (id) {
2096 case 8: /* CICAM_BrandCert */
2097 /* this results in CICAM_ID when cert-chain is verified and ok */
2098 if (check_ci_certificates(cc_data))
2099 break;
2100 /* generate DHSK & AKH */
2101 check_dh_challenge(cc_data);
2102 break;
2103
2104 case 19: /* auth_nonce - triggers new dh keychallenge - invalidates DHSK &
2105 * AKH
2106 */
2107 /* generate DHPH & Signature_A */
2108 restart_dh_challenge(cc_data);
2109 break;
2110
2111 case 21: /* Ns_module - triggers SAC key calculation */
2112 generate_ns_host(cc_data);
2113 generate_key_seed(cc_data);
2114 generate_SAK_SEK(cc_data->sak, cc_data->sek, cc_data->ks_host);
2115 break;
2116
2117 /* SAC data messages */
2118
2119 case 28: /* key register */
2120 check_new_key(d, cc_data);
2121 break;
2122 case 25: // uri_message
2123 // case 26: /* program_number */
2124 generate_uri_confirm(cc_data, cc_data->sak);
2125 break;
2126
2127 case 6: /* CICAM_id */
2128 case 12: /* keyprecursor */
2129 case 14: /* DHPM */
2130 case 16: /* CICAM_DevCert */
2131 case 18: /* Signature_B */
2132 case 26: /* program_number */
2133 LOGM("not need to be handled id %d", id);
2134 break;
2135
2136 default:
2137 LOG("unhandled id %d", id);
2138 break;
2139 }
2140
2141 return 0;
2142 }
2143
data_req_handle_new(struct cc_ctrl_data * cc_data,unsigned int id)2144 static int data_req_handle_new(struct cc_ctrl_data *cc_data, unsigned int id) {
2145 switch (id) {
2146 case 22: /* AKH */
2147 {
2148 uint8_t akh[32], host_id[8];
2149 memset(akh, 0, sizeof(akh));
2150 if (cc_data->akh_index != 5) {
2151 if (!get_authdata(host_id, cc_data->dhsk, akh,
2152 cc_data->session->ca->id, cc_data->akh_index++,
2153 cc_data->session->ca->ci_name))
2154 cc_data->akh_index = 5;
2155 if (!element_set(cc_data, 22, akh, 32))
2156 LOG("cannot set AKH in elements");
2157 if (!element_set(cc_data, 5, host_id, 8))
2158 LOG("cannot set host_id in elements");
2159 }
2160 }
2161 default:
2162 break;
2163 }
2164
2165 return 0;
2166 }
2167
data_get_loop(ca_device_t * d,struct cc_ctrl_data * cc_data,const unsigned char * data,unsigned int datalen,unsigned int items)2168 static int data_get_loop(ca_device_t *d, struct cc_ctrl_data *cc_data,
2169 const unsigned char *data, unsigned int datalen,
2170 unsigned int items) {
2171 unsigned int i;
2172 int dt_id, dt_len;
2173 unsigned int pos = 0;
2174
2175 for (i = 0; i < items; i++) {
2176 if (pos + 3 > datalen)
2177 return 0;
2178 dt_id = data[pos++];
2179 dt_len = data[pos++] << 8;
2180 dt_len |= data[pos++];
2181 if (pos + dt_len > datalen)
2182 return 0;
2183 LOGM("set element(dt_id) %d dt_len = %i", dt_id, dt_len);
2184 // hexdump("data_get_loop: ", (void *)&data[pos],
2185 // dt_len);
2186 element_set(cc_data, dt_id, &data[pos], dt_len);
2187 data_get_handle_new(d, cc_data, dt_id);
2188
2189 pos += dt_len;
2190 }
2191
2192 return pos;
2193 }
2194
data_req_loop(struct cc_ctrl_data * cc_data,unsigned char * dest,const unsigned char * data,unsigned int datalen,unsigned int items)2195 static int data_req_loop(struct cc_ctrl_data *cc_data, unsigned char *dest,
2196 const unsigned char *data, unsigned int datalen,
2197 unsigned int items) {
2198 int dt_id;
2199 unsigned int i;
2200 int pos = 0;
2201 int len;
2202
2203 if (items > datalen)
2204 return -1;
2205
2206 for (i = 0; i < items; i++) {
2207 dt_id = *data++;
2208 LOGM("req element %d", dt_id);
2209 data_req_handle_new(
2210 cc_data,
2211 dt_id); /* check if there is any action needed before we answer */
2212 len = element_get_req(cc_data, dest, dt_id);
2213 if (len == 0) {
2214 LOG("cannot get element %d", dt_id);
2215 return -1;
2216 }
2217 pos += len;
2218 dest += len;
2219 }
2220
2221 return pos;
2222 }
2223
2224 /////////////////////////////////////////////////////////////////////////////////////////
2225
buildLengthField(uint8_t * pkt,int len)2226 static int buildLengthField(uint8_t *pkt, int len) {
2227 if (len < 127) {
2228 *pkt++ = len;
2229 return 1;
2230 } else if (len < 256) {
2231 *pkt++ = 0x81;
2232 *pkt++ = len;
2233 return 2;
2234 } else if (len < 65536) {
2235 *pkt++ = 0x82;
2236 *pkt++ = len >> 8;
2237 *pkt++ = len;
2238 return 3;
2239 } else {
2240 LOG("too big for lengthField");
2241 exit(0);
2242 }
2243 }
2244
ci_session_sendSPDU_A(struct ca_device * ca,uint8_t tag,uint8_t * data,size_t len,uint16_t session_nb)2245 static void ci_session_sendSPDU_A(struct ca_device *ca, uint8_t tag,
2246 uint8_t *data, size_t len,
2247 uint16_t session_nb) {
2248 uint8_t pkt[4096];
2249 uint8_t *ptr = pkt;
2250
2251 *ptr++ = tag;
2252 ptr += buildLengthField(ptr, len + 2);
2253 *ptr++ = session_nb >> 8;
2254 *ptr++ = session_nb;
2255
2256 if (data)
2257 memcpy(ptr, data, len);
2258 ptr += len;
2259 // LOG("==============ci_session_sendSPDU_A================ sess = %i
2260 // sess_nb = %i len = %i ",ca->session,ca->session->index,len);
2261 // hexdump("ci_session_sendSPDU_A DATA ", data, (len < 50 ? len :
2262 // 16));
2263 en50221_sl_send_data(ca->sl, session_nb, data, len);
2264 }
2265
ci_session_sendAPDU(struct ci_session * session,const uint8_t * tag,const uint8_t * data,size_t len)2266 void ci_session_sendAPDU(struct ci_session *session, const uint8_t *tag,
2267 const uint8_t *data, size_t len) {
2268 uint8_t pkt[len + 3 + 4];
2269 int l;
2270
2271 memcpy(pkt, tag, 3);
2272 l = buildLengthField(pkt + 3, len);
2273 if (data)
2274 memcpy(pkt + 3 + l, data, len);
2275 ci_session_sendSPDU_A(session->ca, 0x90, pkt, len + 3 + l, session->index);
2276 }
2277
ci_ccmgr_cc_open_cnf(struct ci_session * session)2278 void ci_ccmgr_cc_open_cnf(struct ci_session *session) {
2279 const uint8_t tag[3] = {0x9f, 0x90, 0x02};
2280 const uint8_t bitmap = 0x01;
2281
2282 data_initialize(session);
2283 LOGM("SEND ------------ CC_OPEN_CNF----------- ");
2284 ci_session_sendAPDU(session, tag, &bitmap, 1);
2285 }
2286
ci_ccmgr_cc_sac_send(struct ci_session * session,const uint8_t * tag,uint8_t * data,unsigned int pos)2287 static int ci_ccmgr_cc_sac_send(struct ci_session *session, const uint8_t *tag,
2288 uint8_t *data, unsigned int pos) {
2289 struct cc_ctrl_data *cc_data = session->private_data;
2290 if (pos < 8)
2291 return 0;
2292 LOG("______________________ci_ccmgr_cc_sac_send______________________");
2293 // _hexdump("TAG: ", &tag, 3);
2294 // _hexdump("UNENCRYPTED: ", data, pos);
2295
2296 pos += add_padding(&data[pos], pos - 8, 16);
2297 BYTE16(&data[6], pos - 8); /* len in header */
2298
2299 pos += sac_gen_auth(&data[pos], data, pos, cc_data->sak);
2300 sac_crypt(&data[8], &data[8], pos - 8, cc_data->sek, AES_ENCRYPT);
2301
2302 // _hexdump("ENCRYPTED ",data, pos);
2303 ci_session_sendAPDU(session, tag, data, pos);
2304
2305 return 1;
2306 }
2307
ci_ccmgr_cc_sac_data_req(ca_device_t * d,struct ci_session * session,const uint8_t * data,unsigned int len)2308 static int ci_ccmgr_cc_sac_data_req(ca_device_t *d, struct ci_session *session,
2309 const uint8_t *data, unsigned int len) {
2310 struct cc_ctrl_data *cc_data = session->private_data;
2311 const uint8_t data_cnf_tag[3] = {0x9f, 0x90, 0x08};
2312 uint8_t dest[2048];
2313 uint8_t tmp[len];
2314 int id_bitmask, dt_nr;
2315 unsigned int serial;
2316 int answ_len;
2317 int pos = 0;
2318 unsigned int rp = 0;
2319
2320 if (len < 10)
2321 return 0;
2322 //_hexdump("ci_ccmgr_cc_sac_data_req:", data, len);
2323
2324 memcpy(tmp, data, 8);
2325 sac_crypt(&tmp[8], &data[8], len - 8, cc_data->sek, AES_DECRYPT);
2326 data = tmp;
2327
2328 if (!sac_check_auth(data, len, cc_data->sak)) {
2329 LOG("check_auth of message failed");
2330 return 0;
2331 }
2332
2333 disable_cws_for_all_pmts(d);
2334
2335 serial = UINT32(&data[rp], 4);
2336 LOGM("serial sac data req: %d", serial);
2337
2338 /* skip serial & header */
2339 rp += 8;
2340
2341 id_bitmask = data[rp++];
2342
2343 /* handle data loop */
2344 dt_nr = data[rp++];
2345 rp += data_get_loop(d, cc_data, &data[rp], len - rp, dt_nr);
2346
2347 if (len < rp + 1)
2348 return 0;
2349
2350 dt_nr = data[rp++];
2351
2352 /* create answer */
2353 pos += BYTE32(&dest[pos], serial);
2354 pos += BYTE32(&dest[pos], 0x01000000);
2355
2356 dest[pos++] = id_bitmask;
2357 dest[pos++] = dt_nr; /* dt_nbr */
2358
2359 answ_len = data_req_loop(cc_data, &dest[pos], &data[rp], len - rp, dt_nr);
2360 if (answ_len <= 0) {
2361 LOG("cannot req data");
2362 return 0;
2363 }
2364 pos += answ_len;
2365
2366 LOGM("SEND ------------ CC_SAC_DATA_CNF----------- ");
2367 // _hexdump("sac_data_send", &dest[8], pos-8); //skip serial and
2368 // header
2369 return ci_ccmgr_cc_sac_send(session, data_cnf_tag, dest, pos);
2370 }
2371
ci_ccmgr_cc_sac_sync_req(struct ci_session * session,const uint8_t * data,unsigned int len)2372 static void ci_ccmgr_cc_sac_sync_req(struct ci_session *session,
2373 const uint8_t *data, unsigned int len) {
2374 const uint8_t sync_cnf_tag[3] = {0x9f, 0x90, 0x10};
2375 uint8_t dest[64];
2376 unsigned int serial;
2377 int pos = 0;
2378
2379 // hexdump("cc_sac_sync_req: ", (void *)data, len);
2380
2381 serial = UINT32(data, 4);
2382
2383 pos += BYTE32(&dest[pos], serial);
2384 pos += BYTE32(&dest[pos], 0x01000000);
2385
2386 /* status OK */
2387 dest[pos++] = 0;
2388
2389 LOG("SEND ------------ CC_SAC_SYNC_CNF----------- ");
2390 ci_ccmgr_cc_sac_send(session, sync_cnf_tag, dest, pos);
2391 }
2392
ci_ccmgr_cc_sync_req(struct ci_session * session,const uint8_t * data,unsigned int len)2393 static void ci_ccmgr_cc_sync_req(struct ci_session *session,
2394 const uint8_t *data, unsigned int len) {
2395 const uint8_t tag[3] = {0x9f, 0x90, 0x06};
2396 const uint8_t status = 0x00; /* OK */
2397 LOGM("SEND ------------ CC_SYNC_CNF----------- ");
2398 ci_session_sendAPDU(session, tag, &status, 1);
2399 }
2400
ci_ccmgr_cc_data_req(ca_device_t * d,struct ci_session * session,const uint8_t * data,unsigned int len)2401 static int ci_ccmgr_cc_data_req(ca_device_t *d, struct ci_session *session,
2402 const uint8_t *data, unsigned int len) {
2403 struct cc_ctrl_data *cc_data = session->private_data;
2404 uint8_t cc_data_cnf_tag[3] = {0x9f, 0x90, 0x04};
2405 uint8_t dest[2048 * 2];
2406 int dt_nr;
2407 int id_bitmask;
2408 int answ_len;
2409 unsigned int rp = 0;
2410
2411 if (len < 2)
2412 return 0;
2413
2414 id_bitmask = data[rp++];
2415
2416 /* handle data loop */
2417 dt_nr = data[rp++];
2418
2419 // printf("CC_DATA: ");
2420 // hexdump(cc_data, sizeof(cc_data));
2421 rp += data_get_loop(d, cc_data, &data[rp], len - rp, dt_nr);
2422
2423 if (len < rp + 1)
2424 return 0;
2425
2426 /* handle req_data loop */
2427 dt_nr = data[rp++];
2428
2429 dest[0] = id_bitmask;
2430 dest[1] = dt_nr;
2431
2432 answ_len = data_req_loop(cc_data, &dest[2], &data[rp], len - rp, dt_nr);
2433 if (answ_len <= 0) {
2434 LOG("cannot req data");
2435 return 0;
2436 }
2437
2438 answ_len += 2;
2439
2440 LOGM("SEND ------------ CC_DATA_CNF----------- ");
2441 ci_session_sendAPDU(session, cc_data_cnf_tag, dest, answ_len);
2442
2443 return 1;
2444 }
2445
stackthread_func(void * arg)2446 void *stackthread_func(void *arg) {
2447 ca_device_t *d = arg;
2448 int lasterror = 0;
2449 adapter *ad;
2450 sprintf(thread_name, "CA%d", d->id);
2451
2452 LOG("%s: start", __func__);
2453
2454 while (d->enabled) {
2455 usleep(100 * 1000);
2456 int error;
2457 if ((error = en50221_tl_poll(d->tl)) != 0) {
2458 if (error != lasterror && en50221_tl_get_error(d->tl) != -7) {
2459 LOG("Error reported by stack slot:%i error:%i",
2460 en50221_tl_get_error_slot(d->tl),
2461 en50221_tl_get_error(d->tl));
2462 ad = get_adapter(d->id);
2463 if (ad)
2464 ad->adapter_timeout = opts.adapter_timeout;
2465 d->ignore_close = 0; // force device close..
2466 // ca_init(d);
2467 // break;
2468 }
2469 lasterror = error;
2470 }
2471 }
2472
2473 return 0;
2474 }
2475
ciplus_app_cc_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2476 static int ciplus_app_cc_message(void *arg, uint8_t slot_id,
2477 uint16_t session_number, uint32_t resource_id,
2478 uint8_t *data, uint32_t data_length) {
2479 ca_device_t *d = arg;
2480 d->session->index = session_number;
2481 d->session->resid = resource_id;
2482 d->session->ca = d;
2483 d->slot_id = slot_id;
2484
2485 uint32_t tag;
2486 uint32_t len;
2487
2488 // printf(" RECV DATA WITH TAG: ");
2489 // hexdump(" RECV DATA WITH TAG: ", data,data_length<33?data_length:32);
2490
2491 tag = data[0] << 16 | data[1] << 8 | data[2];
2492 if (data[3] == 0x82) {
2493 len = (data[4] << 8 | data[5]);
2494 data = &data[6];
2495 } else if (data[3] == 0x81) {
2496 len = (data[4] << 8);
2497 data = &data[5];
2498 } else {
2499 len = data[3];
2500 data = &data[4];
2501 }
2502 LOG("RECV ciplus cc msg CAM%i slot_id %u, session_num %u, resource_id %x "
2503 "tag "
2504 "%x len %i dt_id %i",
2505 d->id, slot_id, session_number, resource_id, tag, len, data[2]);
2506 // printf(" RECV DATA: ");
2507 // hexdump(data,len<33?len:32);
2508
2509 switch (tag) {
2510
2511 case CIPLUS_TAG_CC_OPEN_REQ: // 01
2512 ci_ccmgr_cc_open_cnf(d->session);
2513 break;
2514 case CIPLUS_TAG_CC_DATA_REQ: // 03
2515 ci_ccmgr_cc_data_req(d, d->session, data, len);
2516 break;
2517 case CIPLUS_TAG_CC_SYNC_REQ: // 05
2518 ci_ccmgr_cc_sync_req(d->session, data, len);
2519 break;
2520 case CIPLUS_TAG_CC_SAC_DATA_REQ: // 07
2521 ci_ccmgr_cc_sac_data_req(d, d->session, data, len);
2522 break;
2523 case CIPLUS_TAG_CC_SAC_SYNC_REQ: // 09
2524 ci_ccmgr_cc_sac_sync_req(d->session, data, len);
2525 break;
2526 default:
2527 LOG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! unknown cc tag "
2528 "%x "
2529 "len %u",
2530 tag, len);
2531 }
2532 return 0;
2533 }
2534
ciplus_app_lang_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2535 static int ciplus_app_lang_message(void *arg, uint8_t slot_id,
2536 uint16_t session_number,
2537 uint32_t resource_id, uint8_t *data,
2538 uint32_t data_length) {
2539 ca_device_t *d = arg;
2540 uint32_t tag;
2541
2542 LOG("host_lang&country_receive");
2543 // if (data_length)
2544 // hexdump(data, data_length);
2545
2546 tag = data[0] << 16 | data[1] << 8 | data[2];
2547
2548 uint8_t data_reply_lang[3]; // ISO 639 Part 2
2549 data_reply_lang[0] = 0x65; /* e */
2550 data_reply_lang[1] = 0x6e; /* n */
2551 data_reply_lang[2] = 0x67; /* g */
2552
2553 uint8_t data_reply_country[3]; // ISO 3166-1 alpha 3
2554 data_reply_country[0] = 0x55; /* U */
2555 data_reply_country[1] = 0x53; /* S */
2556 data_reply_country[2] = 0x41; /* A */
2557
2558 switch (tag) {
2559 case CIPLUS_TAG_COUNTRY_ENQ: /* country enquiry */
2560 {
2561 LOG("country answered with '%c%c%c'", data_reply_country[0],
2562 data_reply_country[1], data_reply_country[2]);
2563 uint8_t tag[3] = {0x9f, 0x81, 0x01}; /* host country reply */
2564 ci_session_sendAPDU(d->session, tag, data_reply_country, 3);
2565 break;
2566 }
2567 case CIPLUS_TAG_LANG_ENQ: /* language enquiry */
2568 {
2569 LOG("language answered with '%c%c%c'", data_reply_lang[0],
2570 data_reply_lang[1], data_reply_lang[2]);
2571 uint8_t tag[3] = {0x9f, 0x81, 0x11}; /* host language reply */
2572 ci_session_sendAPDU(d->session, tag, data_reply_lang, 3);
2573 break;
2574 }
2575 default:
2576 LOG("unknown host lac apdu tag %02x", tag);
2577 }
2578 return 0;
2579 }
2580
ciplus_app_sas_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2581 static int ciplus_app_sas_message(void *arg, uint8_t slot_id,
2582 uint16_t session_number, uint32_t resource_id,
2583 uint8_t *data, uint32_t data_length) {
2584 ca_device_t *d = arg;
2585 uint32_t tag;
2586 LOG("CAM_SAS_connect_cnf_receive");
2587
2588 tag = data[0] << 16 | data[1] << 8 | data[2];
2589
2590 switch (tag) {
2591 case CIPLUS_TAG_SAS_CONNECT_CNF: /* */
2592 {
2593 LOG("CI+ CA%i 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x "
2594 "0x%02x 0x%02x",
2595 d->id, data[3], data[4], data[5], data[6], data[7], data[8],
2596 data[9], data[10], data[11], data[12]);
2597 if (data[12] == 0) {
2598 uint8_t tag[3] = {0x9f, 0x9a, 0x07}; /* cam sas async msg */
2599 ci_session_sendAPDU(d->session, tag, 0x00, 0);
2600 }
2601 break;
2602 }
2603 default:
2604 LOG("unknown SAS apdu tag %03x", tag);
2605 }
2606
2607 return 0;
2608 } /* not working, just for fun */
2609
ciplus_app_oprf_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2610 static int ciplus_app_oprf_message(void *arg, uint8_t slot_id,
2611 uint16_t session_number,
2612 uint32_t resource_id, uint8_t *data,
2613 uint32_t data_length) {
2614 ca_device_t *d = arg;
2615 uint32_t tag;
2616 char buf[400];
2617 int pos, i;
2618 pos = sprintf(buf, " ");
2619
2620 uint8_t data_oprf_search[9];
2621 data_oprf_search[0] =
2622 0x03; /* unattended mode bit=0 + length in bytes of the service types */
2623 data_oprf_search[1] = 0x01; /* service MPEG-2 television (0x01) */
2624 data_oprf_search[2] = 0x16; /* service h264 SD (0x16) */
2625 data_oprf_search[3] = 0x19; /* service h264 HD (0x19) */
2626 data_oprf_search[4] = 0x02; /* length in bytes of the delivery_capability */
2627 data_oprf_search[5] = 0x43; /* DVB-S */
2628 data_oprf_search[6] = 0x79; /* DVB-S2 */
2629 data_oprf_search[7] =
2630 0x01; /* length in bytes of the application_capability */
2631 data_oprf_search[8] = 0x00; /* System Software Update service */
2632
2633 uint8_t data_oprf_tune_status[64];
2634 data_oprf_tune_status[0] = 0x01; // unprocessed descriptor_number
2635 data_oprf_tune_status[1] = 0x50; // signal strength
2636 data_oprf_tune_status[2] = 0x50; // signal quality
2637 data_oprf_tune_status[3] = 0x00; // status 0 - OK
2638 data_oprf_tune_status[4] = 0x0d; // lenght next part (13 bytes)
2639
2640 tag = data[0] << 16 | data[1] << 8 | data[2];
2641
2642 switch (tag) {
2643 case CIPLUS_TAG_OPERATOR_STATUS: /* operator_status 01 */
2644 {
2645 LOG("CAM_OPRF_operator_status_receive");
2646 pos = sprintf(buf, " ");
2647 for (i = 4; i < data[3] + 4; i++)
2648 pos += sprintf(buf + pos, "%02X ", data[i]);
2649 uint8_t tag_part = 0x04; /* operator_info_req */
2650 if (data[5] & 0x20) // initialised_flag - profile initialised
2651 tag_part = 0x08; /* operator_exit */
2652 if (data[5] & 0x40) {
2653 LOG("CI+ CA%d: %s operator profile %sinitialised", d->id, buf,
2654 data[5] & 0x60 ? "" : "NOT ");
2655 } else
2656 LOG("CI+ CA%d: %s operator profile disabled", d->id, buf);
2657 uint8_t tag[3] = {0x9f, 0x9c, tag_part};
2658 ci_session_sendAPDU(d->session, tag, 0x00, 0);
2659 break;
2660 }
2661 case CIPLUS_TAG_OPERATOR_INFO: /* operator_info */
2662 {
2663 LOG("CAM_OPRF_operator_info_receive");
2664 for (i = 4; i < data[3] + 4; i++)
2665 pos += sprintf(buf + pos, "%02X ", data[i]);
2666 LOG("CI+ CA%d: %s", d->id, buf);
2667 uint8_t tag[3] = {0x9f, 0x9c, 0x06}; /* operator_search_start */
2668 ci_session_sendAPDU(d->session, tag, data_oprf_search, 9);
2669 break;
2670 }
2671 case 0x9f9c03: /* operator_nit */
2672 {
2673 LOG("CAM_OPRF_operator_nit_receive");
2674 for (i = 4; i < data[3] + 4; i++)
2675 pos += sprintf(buf + pos, "%02X ", data[i]);
2676 LOG("CI+ CA%d: %s", d->id, buf);
2677 uint8_t tag[3] = {0x9f, 0x9c, 0x08}; /* operator_exit */
2678 ci_session_sendAPDU(d->session, tag, 0x00, 0);
2679 break;
2680 }
2681 case CIPLUS_TAG_OPERATOR_SEARCH_STATUS: /* operator_search_status */
2682 {
2683 LOG("CAM_OPRF_operator_search_status_receive");
2684 for (i = 4; i < data[3] + 4; i++)
2685 pos += sprintf(buf + pos, "%02X ", data[i]);
2686 LOG("CI+ CA%d: %s", d->id, buf);
2687
2688 uint8_t tag[3] = {0x9f, 0x9c, 0x02}; /* operator_nit */
2689 if (data[5] & 0x02) // refresh_request_flag == 2 (urgent request)
2690 {
2691 uint8_t tag[3] = {0x9f, 0x9c, 0x06}; /* operator_search_start */
2692 ci_session_sendAPDU(d->session, tag, data_oprf_search, 9);
2693 } else
2694 ci_session_sendAPDU(d->session, tag, 0x00, 0);
2695 break;
2696 }
2697 case CIPLUS_TAG_OPERATOR_TUNE: /* operator_tune */
2698 {
2699 char *pol = "H";
2700 if (data[9] & 0x20)
2701 pol = "V";
2702 else if (data[9] & 0x40)
2703 pol = "L";
2704 else if (data[9] & 0x60)
2705 pol = "R";
2706 LOG("CAM_OPRF_operator_tune_receive");
2707 for (i = 4; i < data[3] + 4; i++) {
2708 pos += sprintf(buf + pos, "%02X ", data[i]);
2709 data_oprf_tune_status[i + 1] = data[i + 2];
2710 }
2711 LOG("CI+ CA%d: %s", d->id, buf);
2712 LOG("Please TUNE to transponder %x%x%x %c", data[6], data[7], data[8],
2713 *pol);
2714 // data_oprf_tune_status[13]=0xC6; //psk8 dvb-s2
2715 usleep(3 * 1000 * 1000); // wait 3 secs
2716 uint8_t tag[3] = {0x9f, 0x9c, 0x0a}; /* operator_tune_status */
2717 ci_session_sendAPDU(d->session, tag, data_oprf_tune_status, 18);
2718 break;
2719 }
2720 default:
2721 LOG("unknown OPRF apdu tag %03x", tag);
2722 }
2723 return 0;
2724 }
2725
ciplus_app_upgr_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2726 static int ciplus_app_upgr_message(void *arg, uint8_t slot_id,
2727 uint16_t session_number,
2728 uint32_t resource_id, uint8_t *data,
2729 uint32_t data_length) {
2730 ca_device_t *d = arg;
2731 int fd = d->fd;
2732 ca_slot_info_t info;
2733
2734 uint32_t tag;
2735 const uint8_t answer =
2736 0x00; // 0x00 - mean no upgrade, 0x01 - upgrade, 0x02 - ask user by mmi
2737
2738 LOG("CAM_fw_upgrade_receive");
2739
2740 tag = data[0] << 16 | data[1] << 8 | data[2];
2741
2742 switch (tag) {
2743 case CIPLUS_TAG_FIRMWARE_UPGR: /* */
2744 {
2745 LOG("CI+ CA%i Firmware Upgrade Command detected... ", d->id);
2746 uint8_t tag[3] = {0x9f, 0x9d, 0x02}; /* cam firmware update reply */
2747 ci_session_sendAPDU(d->session, tag, &answer, 1);
2748 break;
2749 }
2750 case CIPLUS_TAG_FIRMWARE_UPGR_PRGRS: /* */
2751 {
2752 LOG("CI+ CA%i Firmware Upgrade Progress %i percents", d->id, data[4]);
2753 break;
2754 }
2755 case CIPLUS_TAG_FIRMWARE_UPGR_COMPLT: /* */
2756 {
2757 LOG("CI+ CA%i Firmware Upgrade Complete (reset status %i)", d->id,
2758 data[4]);
2759 if (data[4] < 2) { // reset requred
2760 if (ioctl(fd, CA_RESET, &info))
2761 LOG_AND_RETURN(0, "%s: Could not reset ca %d", __FUNCTION__,
2762 d->id);
2763 return 1;
2764 }
2765 break;
2766 }
2767 default:
2768 LOG("unknown fw upgrade apdu tag %03x", tag);
2769 }
2770 return 0;
2771 } /* works now, be careful!!! just in case upgrade disabled */
2772
ciplus_app_ai_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2773 static int ciplus_app_ai_message(void *arg, uint8_t slot_id,
2774 uint16_t session_number, uint32_t resource_id,
2775 uint8_t *data, uint32_t data_length) {
2776 ca_device_t *d = arg;
2777 ca_slot_info_t info;
2778 int fd = d->fd;
2779
2780 if (data_length < 3) {
2781 LOG("Received short data");
2782 return -1;
2783 }
2784 uint32_t tag = (data[0] << 16) | (data[1] << 8) | data[2];
2785
2786 LOG("RECV ciplus AI msg slot_id %u, session_num %u, resource_id %x tag %x",
2787 slot_id, session_number, resource_id, tag);
2788
2789 switch (tag) {
2790 case CIPLUS_TAG_APP_INFO:
2791 // hexdump(data,data_length);
2792 return en50221_app_ai_message(d->ai_resource, slot_id, session_number,
2793 resource_id, data, data_length);
2794 break;
2795 case CIPLUS_TAG_CICAM_RESET:
2796 // hexdump(data,data_length);
2797 if (ioctl(fd, CA_RESET, &info))
2798 LOG_AND_RETURN(0, "%s: Could not reset ca %d", __FUNCTION__, d->id);
2799 return 1;
2800 break;
2801 default:
2802 LOG("Received unexpected tag %x", tag);
2803 }
2804 return -1;
2805 }
2806
en50221_app_unknown_message(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id,uint8_t * data,uint32_t data_length)2807 static int en50221_app_unknown_message(void *arg, uint8_t slot_id,
2808 uint16_t session_number,
2809 uint32_t resource_id, uint8_t *data,
2810 uint32_t data_length) {
2811 ca_device_t *d = arg;
2812 d->session->index = session_number;
2813 d->session->resid = resource_id;
2814 d->slot_id = slot_id;
2815 uint32_t tag = data[0] << 16 | data[1] << 8 | data[2];
2816 LOG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! unknown message "
2817 "slot_id %u, session_num %u, resource_id %x tag %u",
2818 slot_id, session_number, resource_id, tag);
2819 return -1;
2820 }
2821
ca_session_callback(void * arg,int reason,uint8_t slot_id,uint16_t session_number,uint32_t resource_id)2822 static int ca_session_callback(void *arg, int reason, uint8_t slot_id,
2823 uint16_t session_number, uint32_t resource_id) {
2824 ca_device_t *d = arg;
2825 d->session->ca = d;
2826
2827 LOGM("%s: reason %d slot_id %u session_number %u resource_id %x", __func__,
2828 reason, slot_id, session_number, resource_id);
2829
2830 switch (reason) {
2831 case S_SCALLBACK_REASON_CAMCONNECTING: // 0
2832 LOGM("%02x:CAM connecting to resource %08x, session_number %i", slot_id,
2833 resource_id, session_number);
2834 break;
2835 case S_SCALLBACK_REASON_CLOSE: // 5
2836 LOGM("%02x:Connection to resource %08x, session_number %i closed",
2837 slot_id, resource_id, session_number);
2838
2839 if (resource_id == EN50221_APP_CA_RESOURCEID) {
2840 LOG("_________S_SCALLBACK_REASON_CLOSE___________EN50221_APP_CA_"
2841 "RESOURCEID__________________________");
2842 d->ignore_close = 1;
2843 d->init_ok = 0;
2844 } else if (resource_id == CIPLUS_APP_CC_RESOURCEID ||
2845 resource_id == CIPLUS_APP_CC_RESOURCEID_TWO ||
2846 resource_id == CIPLUS_APP_CC_RESOURCEID_THREE ||
2847 resource_id == CIPLUS_APP_CC_RESOURCEID_MULTI) {
2848 LOG("__________S_SCALLBACK_REASON_CLOSE____________CIPLUS_APP_CC_"
2849 "RESOURCEID________________________");
2850 } else if (resource_id == EN50221_APP_MMI_RESOURCEID) {
2851 LOG("_________S_SCALLBACK_REASON_CLOSE____________EN50221_APP_MMI_"
2852 "RESOURCEID_________________________");
2853 }
2854 break;
2855
2856 case S_SCALLBACK_REASON_TC_CONNECT: // 6
2857 LOGM("%02x:Host originated transport connection %i resource 0x%08x "
2858 "connected",
2859 slot_id, resource_id, session_number);
2860 break;
2861 case S_SCALLBACK_REASON_TC_CAMCONNECT: // 7
2862 LOGM("%02x:CAM originated transport connection %i connected", slot_id,
2863 session_number);
2864 break;
2865 case S_SCALLBACK_REASON_CAMCONNECTED: // 1
2866 LOGM("%02x:CAM successfully connected to resource %08x, session_number "
2867 "%i",
2868 slot_id, resource_id, session_number);
2869
2870 if (resource_id == EN50221_APP_RM_RESOURCEID) {
2871 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2872 "EN50221_"
2873 "APP_RM_RESOURCEID-------------------------");
2874 en50221_app_rm_enq(d->rm_resource, session_number);
2875 } else if (resource_id == EN50221_APP_AI_RESOURCEID ||
2876 resource_id == TS101699_APP_AI_RESOURCEID) {
2877 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2878 "EN50221_"
2879 "APP_AI_RESOURCEID-------------------------");
2880 d->ai_session_number = session_number;
2881 en50221_app_ai_enquiry(d->ai_resource, session_number);
2882 } else if (resource_id == CIPLUS_APP_AI_RESOURCEID) {
2883 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2884 "CIPLUS_"
2885 "APP_AI_RESOURCEID-------------------------");
2886 d->ca_ai_version = resource_id & 0x3f;
2887 d->ai_session_number = session_number;
2888 d->ca_high_bitrate_mode =
2889 1; // 96 MBPS now (should get from command line)
2890 en50221_app_ai_enquiry(d->ai_resource, session_number);
2891 ciplus13_app_ai_data_rate_info(d, d->ca_high_bitrate_mode
2892 ? CIPLUS_DATA_RATE_96_MBPS
2893 : CIPLUS_DATA_RATE_72_MBPS);
2894 } else if (resource_id == EN50221_APP_CA_RESOURCEID ||
2895 resource_id == CIPLUS_APP_CA_RESOURCEID) {
2896 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2897 "EN50221_"
2898 "APP_CA_RESOURCEID-------------------------");
2899 en50221_app_ca_info_enq(d->ca_resource, session_number);
2900 d->ca_session_number = session_number;
2901 } else if (resource_id == EN50221_APP_MMI_RESOURCEID) {
2902 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2903 "EN50221_"
2904 "APP_MMI_RESOURCEID-------------------------");
2905 } else if (resource_id == CIPLUS_APP_SAS_RESOURCEID) {
2906 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2907 "CIPLUS_"
2908 "APP_SAS_RESOURCEID-------------------------");
2909 uint8_t data[] = {
2910 0x9f, 0x9a, 0x00, 0x08, 0x69, 0x74,
2911 0x64, 0x74, 0x74, 0x63, 0x61, 0x00}; // blank
2912 // private_Host_application_ID
2913 en50221_sl_send_data(d->sl, session_number, data, sizeof(data));
2914 } else if (resource_id == CIPLUS_APP_OPRF_RESOURCEID) {
2915 LOG("--------------------S_SCALLBACK_REASON_CAMCONNECTED---------"
2916 "CIPLUS_"
2917 "APP_OPRF_RESOURCEID-------------------------");
2918 }
2919 d->ignore_close = 1;
2920 break;
2921 case S_SCALLBACK_REASON_CAMCONNECTFAIL: // 2
2922 LOG("%02x:CAM on failed to connect to resource %08x", slot_id,
2923 resource_id);
2924 break;
2925 case S_SCALLBACK_REASON_CONNECTED: // 3
2926 LOG("%02x:Host connection to resource %08x connected successfully, "
2927 "session_number %i",
2928 slot_id, resource_id, session_number);
2929 break;
2930 case S_SCALLBACK_REASON_CONNECTFAIL: // 4
2931 LOG("%02x:Host connection to resource %08x failed, session_number %i",
2932 slot_id, resource_id, session_number);
2933 break;
2934 }
2935 return 0;
2936 }
2937
ca_lookup_callback(void * arg,uint8_t slot_id,uint32_t requested_resource_id,en50221_sl_resource_callback * callback_out,void ** arg_out,uint32_t * connected_resource_id)2938 static int ca_lookup_callback(void *arg, uint8_t slot_id,
2939 uint32_t requested_resource_id,
2940 en50221_sl_resource_callback *callback_out,
2941 void **arg_out, uint32_t *connected_resource_id) {
2942 ca_device_t *d = arg;
2943 d->session->ca = d;
2944
2945 LOGM("===================> %s: slot_id %u requested_resource_id %x",
2946 __func__, slot_id, requested_resource_id);
2947
2948 switch (requested_resource_id) {
2949 case EN50221_APP_RM_RESOURCEID:
2950 case TS101699_APP_RM_RESOURCEID:
2951 *callback_out = (en50221_sl_resource_callback)en50221_app_rm_message;
2952 *arg_out = d->rm_resource;
2953 *connected_resource_id = EN50221_APP_RM_RESOURCEID;
2954 break;
2955 case CIPLUS_APP_AI_RESOURCEID:
2956 *callback_out = (en50221_sl_resource_callback)ciplus_app_ai_message;
2957 *arg_out = d;
2958 *connected_resource_id = CIPLUS_APP_AI_RESOURCEID;
2959 break;
2960 case EN50221_APP_AI_RESOURCEID:
2961 case TS101699_APP_AI_RESOURCEID:
2962 *callback_out = (en50221_sl_resource_callback)en50221_app_ai_message;
2963 *arg_out = d->ai_resource;
2964 *connected_resource_id = requested_resource_id;
2965 break;
2966 case EN50221_APP_CA_RESOURCEID:
2967 *callback_out = (en50221_sl_resource_callback)en50221_app_ca_message;
2968 *arg_out = d->ca_resource;
2969 *connected_resource_id = EN50221_APP_CA_RESOURCEID;
2970 break;
2971 case EN50221_APP_DATETIME_RESOURCEID:
2972 *callback_out =
2973 (en50221_sl_resource_callback)en50221_app_datetime_message;
2974 *arg_out = d->dt_resource;
2975 *connected_resource_id = EN50221_APP_DATETIME_RESOURCEID;
2976 break;
2977 case EN50221_APP_MMI_RESOURCEID:
2978 *callback_out = (en50221_sl_resource_callback)en50221_app_mmi_message;
2979 *arg_out = d->mmi_resource;
2980 *connected_resource_id = EN50221_APP_MMI_RESOURCEID;
2981 break;
2982 case CIPLUS_APP_CC_RESOURCEID:
2983 /* CI Plus Implementation Guidelines V1.0.6 (2013-10)
2984 5.3.1 URI version advertisement
2985 A Host should advertise URI v1 only when Content Control v1 is selected by
2986 the CICAM */
2987 d->uri_mask = 0x1;
2988 *callback_out = (en50221_sl_resource_callback)ciplus_app_cc_message;
2989 *arg_out = d;
2990 *connected_resource_id = requested_resource_id;
2991 break;
2992 case CIPLUS_APP_CC_RESOURCEID_TWO:
2993 case CIPLUS_APP_CC_RESOURCEID_THREE:
2994 case CIPLUS_APP_CC_RESOURCEID_MULTI:
2995 d->uri_mask = 0x3;
2996 *callback_out = (en50221_sl_resource_callback)ciplus_app_cc_message;
2997 *arg_out = d;
2998 *connected_resource_id = requested_resource_id;
2999 break;
3000 case CIPLUS_APP_LANG_RESOURCEID:
3001 *callback_out = (en50221_sl_resource_callback)ciplus_app_lang_message;
3002 *arg_out = d;
3003 *connected_resource_id = requested_resource_id;
3004 break;
3005 case CIPLUS_APP_UPGR_RESOURCEID:
3006 *callback_out = (en50221_sl_resource_callback)ciplus_app_upgr_message;
3007 *arg_out = d;
3008 *connected_resource_id = requested_resource_id;
3009 break;
3010 case CIPLUS_APP_SAS_RESOURCEID:
3011 *callback_out = (en50221_sl_resource_callback)ciplus_app_sas_message;
3012 *arg_out = d;
3013 *connected_resource_id = requested_resource_id;
3014 break;
3015 case CIPLUS_APP_OPRF_RESOURCEID:
3016 *callback_out = (en50221_sl_resource_callback)ciplus_app_oprf_message;
3017 *arg_out = d;
3018 *connected_resource_id = requested_resource_id;
3019 break;
3020 default:
3021 *callback_out =
3022 (en50221_sl_resource_callback)en50221_app_unknown_message;
3023 *arg_out = d;
3024 *connected_resource_id = requested_resource_id;
3025 LOG("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! lookup callback for "
3026 "unknown resource id %x on slot %u",
3027 requested_resource_id, slot_id);
3028 break;
3029 }
3030 return 0;
3031 }
3032
ca_rm_enq_callback(void * arg,uint8_t slot_id,uint16_t session_number)3033 static int ca_rm_enq_callback(void *arg, uint8_t slot_id,
3034 uint16_t session_number) {
3035 ca_device_t *d = arg;
3036 uint32_t *resource = resource_ids;
3037 uint32_t resource_count = resource_ids_count;
3038 int fd;
3039 fd = open("/etc/ssl/certs/root.pem", O_RDONLY);
3040 if (fd < 0)
3041 d->force_ci = 1;
3042 else
3043 close(fd);
3044 if (d->force_ci) {
3045 resource = resource_ids_ci;
3046 resource_count = resource_ids_ci_count;
3047 }
3048
3049 LOG("%02x:%s resource_count %i %s", slot_id, __func__, resource_count,
3050 d->force_ci ? "CI MODE" : "CI+ MODE");
3051
3052 if (en50221_app_rm_reply(d->rm_resource, session_number, resource_count,
3053 resource)) {
3054 LOG("%02x:Failed to send reply to ENQ", slot_id);
3055 }
3056
3057 return 0;
3058 }
3059
ca_rm_reply_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t resource_id_count,uint32_t * _resource_ids)3060 static int ca_rm_reply_callback(void *arg, uint8_t slot_id,
3061 uint16_t session_number,
3062 uint32_t resource_id_count,
3063 uint32_t *_resource_ids) {
3064 ca_device_t *d = arg;
3065 LOG("%02x:%s resource_count %i", slot_id, __func__, resource_id_count);
3066
3067 uint32_t i;
3068 for (i = 0; i < resource_id_count; i++) {
3069 LOG(" CAM provided resource id: %08x", _resource_ids[i]);
3070 }
3071
3072 if (en50221_app_rm_changed(d->rm_resource, session_number)) {
3073 LOG("%02x:Failed to send REPLY", slot_id);
3074 }
3075
3076 return 0;
3077 }
3078
ca_rm_changed_callback(void * arg,uint8_t slot_id,uint16_t session_number)3079 static int ca_rm_changed_callback(void *arg, uint8_t slot_id,
3080 uint16_t session_number) {
3081 ca_device_t *d = arg;
3082 LOG("%02x:%s", slot_id, __func__);
3083
3084 if (en50221_app_rm_enq(d->rm_resource, session_number)) {
3085 LOG("%02x:Failed to send ENQ", slot_id);
3086 }
3087
3088 return 0;
3089 }
3090
ca_ca_info_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint32_t ca_id_count,uint16_t * ca_ids)3091 static int ca_ca_info_callback(void *arg, uint8_t slot_id,
3092 uint16_t session_number, uint32_t ca_id_count,
3093 uint16_t *ca_ids) {
3094 (void)session_number;
3095 ca_device_t *d = arg;
3096 uint32_t i;
3097 int overwritten = 0;
3098
3099 d->init_ok = 1;
3100 if (d->caids) {
3101 ca_ids = d->caid;
3102 ca_id_count = d->caids;
3103 overwritten = 1;
3104 }
3105 for (i = 0; i < ca_id_count; i++) {
3106 uint8_t *b = (uint8_t *)&ca_ids[i];
3107 int caid = b[1] * 256 + b[0];
3108 LOG(" %s CA ID: %04x for CA%d", overwritten ? "Forced" : "Supported",
3109 caid, d->id);
3110 add_caid_mask(dvbca_id, d->id, caid, 0xFFFF);
3111 }
3112
3113 return 0;
3114 }
3115
ca_ca_pmt_reply_callback(void * arg,uint8_t slot_id,uint16_t session_number,struct en50221_app_pmt_reply * reply,uint32_t reply_size)3116 static int ca_ca_pmt_reply_callback(void *arg, uint8_t slot_id,
3117 uint16_t session_number,
3118 struct en50221_app_pmt_reply *reply,
3119 uint32_t reply_size) {
3120 (void)arg;
3121 (void)session_number;
3122 (void)reply;
3123 (void)reply_size;
3124
3125 LOG("ca_ca_pmt_reply_callback %02x:%s", slot_id, __func__);
3126
3127 if (!reply->CA_enable_flag || reply->CA_enable != 1) {
3128 LOG("Unable to descramble. ca_enable_flag: %d, ca_enable: 0x%02x",
3129 reply->CA_enable_flag, reply->CA_enable);
3130 return 0;
3131 }
3132
3133 LOG("OK descrambling");
3134
3135 return 0;
3136 }
3137
ca_dt_enquiry_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t response_interval)3138 static int ca_dt_enquiry_callback(void *arg, uint8_t slot_id,
3139 uint16_t session_number,
3140 uint8_t response_interval) {
3141 ca_device_t *d = arg;
3142
3143 LOGM("%02x:%s", slot_id, __func__);
3144 LOGM(" response_interval:%i", response_interval);
3145
3146 if (en50221_app_datetime_send(d->dt_resource, session_number, time(NULL),
3147 -1)) {
3148 LOG("%02x:Failed to send datetime", slot_id);
3149 }
3150
3151 return 0;
3152 }
3153
ca_mmi_close_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t cmd_id,uint8_t delay)3154 static int ca_mmi_close_callback(void *arg, uint8_t slot_id,
3155 uint16_t session_number, uint8_t cmd_id,
3156 uint8_t delay) {
3157 LOG("mmi close cb received for slot %u session_num %u "
3158 "cmd_id 0x%02x delay %u",
3159 slot_id, session_number, cmd_id, delay);
3160
3161 return 0;
3162 }
3163
ca_mmi_display_ctl_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t cmd_id,uint8_t mmi_mode)3164 static int ca_mmi_display_ctl_callback(void *arg, uint8_t slot_id,
3165 uint16_t session_number, uint8_t cmd_id,
3166 uint8_t mmi_mode) {
3167 ca_device_t *d = arg;
3168
3169 LOG("mmi display ctl cb received for slot %u session_num %u "
3170 "cmd_id 0x%02x mmi_mode %u",
3171 slot_id, session_number, cmd_id, mmi_mode);
3172
3173 if (cmd_id == MMI_DISPLAY_CONTROL_CMD_ID_SET_MMI_MODE) {
3174 struct en50221_app_mmi_display_reply_details det;
3175
3176 det.u.mode_ack.mmi_mode = mmi_mode;
3177 if (en50221_app_mmi_display_reply(d->mmi_resource, session_number,
3178 MMI_DISPLAY_REPLY_ID_MMI_MODE_ACK,
3179 &det)) {
3180 LOG("Slot %u: Failed to send MMI mode ack reply", slot_id);
3181 }
3182 }
3183
3184 return 0;
3185 }
3186
ca_mmi_enq_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t blind_answ,uint8_t exp_answ_len,uint8_t * text,uint32_t text_size)3187 static int ca_mmi_enq_callback(void *arg, uint8_t slot_id,
3188 uint16_t session_number, uint8_t blind_answ,
3189 uint8_t exp_answ_len, uint8_t *text,
3190 uint32_t text_size) {
3191 ca_device_t *d = arg;
3192 char buffer[256];
3193
3194 snprintf(buffer, sizeof(buffer), "%.*s", text_size, text);
3195
3196 LOG("MMI enquiry from CAM in slot %u: %s (%s%u digits)", slot_id, buffer,
3197 blind_answ ? "blind " : "", exp_answ_len);
3198
3199 if (strlen((char *)d->pin_str) == exp_answ_len) {
3200 LOG("answering to PIN enquiry");
3201 en50221_app_mmi_answ(d->mmi_resource, session_number,
3202 MMI_ANSW_ID_ANSWER, (uint8_t *)d->pin_str,
3203 exp_answ_len);
3204 }
3205
3206 en50221_app_mmi_close(d->mmi_resource, session_number,
3207 MMI_CLOSE_MMI_CMD_ID_IMMEDIATE, 0);
3208
3209 return 0;
3210 }
3211
ca_mmi_menu_callback(void * arg,uint8_t slot_id,uint16_t session_number,struct en50221_app_mmi_text * title,struct en50221_app_mmi_text * sub_title,struct en50221_app_mmi_text * bottom,uint32_t item_count,struct en50221_app_mmi_text * items,uint32_t item_raw_length,uint8_t * items_raw)3212 static int ca_mmi_menu_callback(void *arg, uint8_t slot_id,
3213 uint16_t session_number,
3214 struct en50221_app_mmi_text *title,
3215 struct en50221_app_mmi_text *sub_title,
3216 struct en50221_app_mmi_text *bottom,
3217 uint32_t item_count,
3218 struct en50221_app_mmi_text *items,
3219 uint32_t item_raw_length, uint8_t *items_raw) {
3220 ca_device_t *d = arg;
3221
3222 LOG("MMI menu from CAM in the slot %u:", slot_id);
3223 LOG(" title: %.*s", title->text_length, title->text);
3224 LOG(" subtitle: %.*s", sub_title->text_length, sub_title->text);
3225
3226 uint32_t i;
3227 for (i = 0; i < item_count; i++) {
3228 LOG(" item %i: %.*s", i + 1, items[i].text_length, items[i].text);
3229 }
3230 LOG(" bottom: %.*s", bottom->text_length, bottom->text);
3231
3232 /* menu answer OK */
3233 en50221_app_mmi_menu_answ(d->mmi_resource, session_number, 0x01);
3234 /* enter "OK" */
3235 // en50221_app_mmi_keypress(d->mmi_resource, session_number,
3236 // 0x11);
3237 /* cancel menu */
3238 en50221_app_mmi_close(d->mmi_resource, session_number,
3239 MMI_CLOSE_MMI_CMD_ID_IMMEDIATE, 0);
3240
3241 return 0;
3242 }
3243
ca_app_mmi_list_callback(void * arg,uint8_t slot_id,uint16_t session_num,struct en50221_app_mmi_text * title,struct en50221_app_mmi_text * sub_title,struct en50221_app_mmi_text * bottom,uint32_t item_count,struct en50221_app_mmi_text * items,uint32_t item_raw_length,uint8_t * items_raw)3244 static int ca_app_mmi_list_callback(
3245 void *arg, uint8_t slot_id, uint16_t session_num,
3246 struct en50221_app_mmi_text *title, struct en50221_app_mmi_text *sub_title,
3247 struct en50221_app_mmi_text *bottom, uint32_t item_count,
3248 struct en50221_app_mmi_text *items, uint32_t item_raw_length,
3249 uint8_t *items_raw) {
3250 ca_device_t *d = arg;
3251
3252 LOG("MMI list from CAM in the slot %u:", slot_id);
3253 LOG(" title: %.*s", title->text_length, title->text);
3254 LOG(" subtitle: %.*s", sub_title->text_length, sub_title->text);
3255
3256 uint32_t i;
3257 for (i = 0; i < item_count; i++) {
3258 LOG(" item %i: %.*s", i + 1, items[i].text_length, items[i].text);
3259 }
3260 LOG(" bottom: %.*s", bottom->text_length, bottom->text);
3261
3262 /* cancel menu */
3263 en50221_app_mmi_close(d->mmi_resource, session_num,
3264 MMI_CLOSE_MMI_CMD_ID_IMMEDIATE, 0);
3265 return 0;
3266 }
3267
ca_mmi_keypad_control_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t cmd_id,uint8_t * key_codes,uint32_t key_codes_count)3268 static int ca_mmi_keypad_control_callback(void *arg, uint8_t slot_id,
3269 uint16_t session_number,
3270 uint8_t cmd_id, uint8_t *key_codes,
3271 uint32_t key_codes_count) {
3272 (void)arg;
3273 (void)session_number;
3274 (void)cmd_id;
3275 (void)key_codes;
3276 (void)key_codes_count;
3277
3278 LOG("================================ %02x:%s", slot_id, __func__);
3279
3280 return 0;
3281 }
3282
ca_mmi_subtitle_segment_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t * segment,uint32_t segment_size)3283 static int ca_mmi_subtitle_segment_callback(void *arg, uint8_t slot_id,
3284 uint16_t session_number,
3285 uint8_t *segment,
3286 uint32_t segment_size) {
3287 (void)arg;
3288 (void)session_number;
3289 (void)segment;
3290 (void)segment_size;
3291
3292 LOG("%02x:%s", slot_id, __func__);
3293
3294 return 0;
3295 }
3296
ca_mmi_scene_end_mark_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t decoder_continue_flag,uint8_t scene_reveal_flag,uint8_t send_scene_done,uint8_t scene_tag)3297 static int ca_mmi_scene_end_mark_callback(void *arg, uint8_t slot_id,
3298 uint16_t session_number,
3299 uint8_t decoder_continue_flag,
3300 uint8_t scene_reveal_flag,
3301 uint8_t send_scene_done,
3302 uint8_t scene_tag) {
3303 (void)arg;
3304 (void)session_number;
3305 (void)decoder_continue_flag;
3306 (void)scene_reveal_flag;
3307 (void)send_scene_done;
3308 (void)scene_tag;
3309
3310 LOG("%02x:%s", slot_id, __func__);
3311
3312 return 0;
3313 }
3314
ca_mmi_scene_control_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t decoder_continue_flag,uint8_t scene_reveal_flag,uint8_t scene_tag)3315 static int ca_mmi_scene_control_callback(void *arg, uint8_t slot_id,
3316 uint16_t session_number,
3317 uint8_t decoder_continue_flag,
3318 uint8_t scene_reveal_flag,
3319 uint8_t scene_tag) {
3320 (void)arg;
3321 (void)session_number;
3322 (void)decoder_continue_flag;
3323 (void)scene_reveal_flag;
3324 (void)scene_tag;
3325
3326 LOG("%02x:%s", slot_id, __func__);
3327
3328 return 0;
3329 }
3330
ca_mmi_subtitle_download_callback(void * arg,uint8_t slot_id,uint16_t session_number,uint8_t * segment,uint32_t segment_size)3331 static int ca_mmi_subtitle_download_callback(void *arg, uint8_t slot_id,
3332 uint16_t session_number,
3333 uint8_t *segment,
3334 uint32_t segment_size) {
3335 (void)arg;
3336 (void)session_number;
3337 (void)segment;
3338 (void)segment_size;
3339
3340 LOG("%02x:%s", slot_id, __func__);
3341
3342 return 0;
3343 }
3344
ca_mmi_flush_download_callback(void * arg,uint8_t slot_id,uint16_t session_number)3345 static int ca_mmi_flush_download_callback(void *arg, uint8_t slot_id,
3346 uint16_t session_number) {
3347 (void)arg;
3348 (void)session_number;
3349
3350 LOG("%02x:%s", slot_id, __func__);
3351
3352 return 0;
3353 }
3354
ca_init(ca_device_t * d)3355 int ca_init(ca_device_t *d) {
3356 ca_slot_info_t info;
3357 int64_t st = getTick();
3358 __attribute__((unused)) int tries = 800; // wait up to 8s for the CAM
3359 int fd = d->fd;
3360 d->tl = NULL;
3361 d->sl = NULL;
3362 d->slot_id = -1;
3363 memset(&info, 0, sizeof(info));
3364
3365 if (ioctl(fd, CA_RESET, &info))
3366 LOG_AND_RETURN(0, "%s: Could not reset ca %d", __FUNCTION__, d->id);
3367 d->sp = 0;
3368 d->is_ciplus = 0;
3369 do {
3370 if (ioctl(fd, CA_GET_SLOT_INFO, &info))
3371 LOG_AND_RETURN(0, "%s: Could not get info1 for ca %d", __FUNCTION__,
3372 d->id);
3373 usleep(10000);
3374 } while ((tries-- > 0) && !(info.flags & CA_CI_MODULE_READY));
3375
3376 if (ioctl(fd, CA_GET_SLOT_INFO, &info))
3377 LOG_AND_RETURN(0, "%s: Could not get info2 for ca %d, tries %d",
3378 __FUNCTION__, d->id, tries);
3379
3380 LOG("initializing CA, fd %d type %d flags 0x%x, after %jd ms", fd,
3381 info.type, info.flags, (getTick() - st));
3382
3383 if (info.type != CA_CI_LINK) {
3384 LOG("incompatible CA interface");
3385 goto fail;
3386 }
3387
3388 if (!(info.flags & CA_CI_MODULE_READY)) {
3389 LOG("CA module not present or not ready");
3390 goto fail;
3391 }
3392
3393 if ((d->tl = en50221_tl_create(8, 32)) == NULL) {
3394 LOG("failed to create transport layer");
3395 goto fail;
3396 }
3397
3398 if ((d->slot_id = en50221_tl_register_slot(d->tl, fd, 0, 10000, 1000)) <
3399 0) {
3400 LOG("slot registration failed");
3401 goto fail;
3402 }
3403 LOG("slotid: %i", d->slot_id);
3404
3405 // create session layer
3406 d->sl = en50221_sl_create(d->tl, 256);
3407 if (d->sl == NULL) {
3408 LOG("failed to create session layer");
3409 goto fail;
3410 }
3411
3412 // create the sendfuncs
3413 d->sf.arg = d->sl;
3414 d->sf.send_data = (en50221_send_data)en50221_sl_send_data;
3415 d->sf.send_datav = (en50221_send_datav)en50221_sl_send_datav;
3416
3417 /* create app resources and assign callbacks */
3418 d->rm_resource = en50221_app_rm_create(&d->sf);
3419 en50221_app_rm_register_enq_callback(d->rm_resource, ca_rm_enq_callback, d);
3420 en50221_app_rm_register_reply_callback(d->rm_resource, ca_rm_reply_callback,
3421 d);
3422 en50221_app_rm_register_changed_callback(d->rm_resource,
3423 ca_rm_changed_callback, d);
3424
3425 d->dt_resource = en50221_app_datetime_create(&d->sf);
3426 en50221_app_datetime_register_enquiry_callback(d->dt_resource,
3427 ca_dt_enquiry_callback, d);
3428
3429 d->ai_resource = en50221_app_ai_create(&d->sf);
3430 en50221_app_ai_register_callback(d->ai_resource, ca_ai_callback, d);
3431
3432 d->ca_resource = en50221_app_ca_create(&d->sf);
3433 en50221_app_ca_register_info_callback(d->ca_resource, ca_ca_info_callback,
3434 d);
3435 en50221_app_ca_register_pmt_reply_callback(d->ca_resource,
3436 ca_ca_pmt_reply_callback, d);
3437
3438 d->mmi_resource = en50221_app_mmi_create(&d->sf);
3439 en50221_app_mmi_register_close_callback(d->mmi_resource,
3440 ca_mmi_close_callback, d);
3441 en50221_app_mmi_register_display_control_callback(
3442 d->mmi_resource, ca_mmi_display_ctl_callback, d);
3443 en50221_app_mmi_register_keypad_control_callback(
3444 d->mmi_resource, ca_mmi_keypad_control_callback, d);
3445
3446 en50221_app_mmi_register_subtitle_segment_callback(
3447 d->mmi_resource, ca_mmi_subtitle_segment_callback, d);
3448 en50221_app_mmi_register_scene_end_mark_callback(
3449 d->mmi_resource, ca_mmi_scene_end_mark_callback, d);
3450 en50221_app_mmi_register_scene_control_callback(
3451 d->mmi_resource, ca_mmi_scene_control_callback, d);
3452 en50221_app_mmi_register_subtitle_download_callback(
3453 d->mmi_resource, ca_mmi_subtitle_download_callback, d);
3454 en50221_app_mmi_register_flush_download_callback(
3455 d->mmi_resource, ca_mmi_flush_download_callback, d);
3456
3457 en50221_app_mmi_register_enq_callback(d->mmi_resource, ca_mmi_enq_callback,
3458 d);
3459 en50221_app_mmi_register_menu_callback(d->mmi_resource,
3460 ca_mmi_menu_callback, d);
3461 en50221_app_mmi_register_list_callback(d->mmi_resource,
3462 ca_app_mmi_list_callback, d);
3463
3464 pthread_create(&d->stackthread, NULL, stackthread_func, d);
3465
3466 en50221_sl_register_lookup_callback(d->sl, ca_lookup_callback, d);
3467 en50221_sl_register_session_callback(d->sl, ca_session_callback, d);
3468
3469 d->tc = en50221_tl_new_tc(d->tl, d->slot_id);
3470 LOG("tcid: %i", d->tc);
3471
3472 return 0;
3473 fail:
3474 close(fd);
3475 d->fd = -1;
3476 d->enabled = 0;
3477 return 1;
3478 }
3479
alloc_ca_device()3480 ca_device_t *alloc_ca_device() {
3481 ca_device_t *d = malloc1(sizeof(ca_device_t));
3482 if (!d) {
3483 LOG_AND_RETURN(NULL, "Could not allocate memory for CA device");
3484 }
3485 memset(d, 0, sizeof(ca_device_t));
3486 d->max_ca_pmt = MAX_CA_PMT;
3487 return d;
3488 }
3489
dvbca_init_dev(adapter * ad)3490 int dvbca_init_dev(adapter *ad) {
3491 ca_device_t *c = ca_devices[ad->id];
3492 int fd;
3493 char ca_dev_path[100];
3494
3495 if (c && c->enabled)
3496 return TABLES_RESULT_OK;
3497
3498 if (ad->type != ADAPTER_DVB && ad->type != ADAPTER_CI)
3499 return TABLES_RESULT_ERROR_NORETRY;
3500 #ifdef ENIGMA
3501 sprintf(ca_dev_path, "/dev/ci%d", ad->pa);
3502 #else
3503 sprintf(ca_dev_path, "/dev/dvb/adapter%d/ca%d", ad->pa, ad->fn);
3504 #endif
3505 fd = open(ca_dev_path, O_RDWR);
3506 if (fd < 0)
3507 LOG_AND_RETURN(TABLES_RESULT_ERROR_NORETRY,
3508 "No CA device detected on adapter %d: file %s", ad->id,
3509 ca_dev_path);
3510 if (!c) {
3511 c = ca_devices[ad->id] = alloc_ca_device();
3512 if (!c) {
3513 close(fd);
3514 LOG_AND_RETURN(0, "Could not allocate memory for CA device %d",
3515 ad->id);
3516 }
3517 }
3518 c->enabled = 1;
3519 c->ignore_close = 0;
3520 c->fd = fd;
3521 c->id = ad->id;
3522 c->ca_high_bitrate_mode = 0;
3523 c->stackthread = 0;
3524 c->init_ok = 0;
3525 memset(c->capmt, -1, sizeof(c->capmt));
3526 memset(c->key[0], 0, sizeof(c->key[0]));
3527 memset(c->key[1], 0, sizeof(c->key[1]));
3528 memset(c->iv[0], 0, sizeof(c->iv[0]));
3529 memset(c->iv[1], 0, sizeof(c->iv[1]));
3530 if (ca_init(c)) {
3531 dvbca_close_device(c);
3532 return TABLES_RESULT_ERROR_NORETRY;
3533 }
3534 return TABLES_RESULT_OK;
3535 }
3536
dvbca_close_device(ca_device_t * c)3537 int dvbca_close_device(ca_device_t *c) {
3538 LOG("closing CA device %d, fd %d", c->id, c->fd);
3539 c->enabled = 0;
3540 if (c->stackthread)
3541 pthread_join(c->stackthread, NULL);
3542 if (c->tl && (c->slot_id >= 0))
3543 en50221_tl_destroy_slot(c->tl, c->slot_id);
3544 if (c->sl)
3545 en50221_sl_destroy(c->sl);
3546 if (c->tl)
3547 en50221_tl_destroy(c->tl);
3548 if (c->fd >= 0)
3549 close(c->fd);
3550 EVP_cleanup();
3551 ERR_free_strings();
3552 return 0;
3553 }
dvbca_close_dev(adapter * ad)3554 int dvbca_close_dev(adapter *ad) {
3555 ca_device_t *c = ca_devices[ad->id];
3556 if (c && c->enabled &&
3557 !c->ignore_close) // do not close the CA unless in a bad state
3558 {
3559 dvbca_close_device(c);
3560 }
3561 return 1;
3562 }
3563
dvbca_close()3564 int dvbca_close() {
3565 int i;
3566 for (i = 0; i < MAX_ADAPTERS; i++)
3567 if (ca_devices[i] && ca_devices[i]->enabled) {
3568 dvbca_close_device(ca_devices[i]);
3569 }
3570 return 0;
3571 }
3572
3573 SCA_op dvbca;
3574
dvbca_init()3575 void dvbca_init() // you can search the devices here and fill the ca_devices,
3576 // then open them here (for example independent CA devices),
3577 // or use dvbca_init_dev to open them (like in this module)
3578 {
3579 memset(&dvbca, 0, sizeof(dvbca));
3580 dvbca.ca_init_dev = dvbca_init_dev;
3581 dvbca.ca_close_dev = dvbca_close_dev;
3582 dvbca.ca_add_pmt = dvbca_process_pmt;
3583 dvbca.ca_del_pmt = dvbca_del_pmt;
3584 dvbca.ca_close_ca = dvbca_close;
3585 dvbca.ca_ts = NULL; // dvbca_ts;
3586 dvbca_id = add_ca(&dvbca, 0xFFFFFFFF);
3587 }
3588
get_ca_pin(int i)3589 char *get_ca_pin(int i) {
3590 if (ca_devices[i])
3591 return ca_devices[i]->pin_str;
3592 return NULL;
3593 }
3594
set_ca_pin(int i,char * pin)3595 void set_ca_pin(int i, char *pin) {
3596 if (!ca_devices[i])
3597 ca_devices[i] = alloc_ca_device();
3598 if (!ca_devices[i])
3599 return;
3600 memset(ca_devices[i]->pin_str, 0, sizeof(ca_devices[i]->pin_str));
3601 strncpy(ca_devices[i]->pin_str, pin, sizeof(ca_devices[i]->pin_str) - 1);
3602 }
3603
force_ci_adapter(int i)3604 void force_ci_adapter(int i) {
3605 if (!ca_devices[i])
3606 ca_devices[i] = alloc_ca_device();
3607 if (!ca_devices[i])
3608 return;
3609 ca_devices[i]->force_ci = 1;
3610 }
3611
set_ca_adapter_force_ci(char * o)3612 void set_ca_adapter_force_ci(char *o) {
3613 int i, j, la, st, end;
3614 char buf[1000], *arg[40], *sep;
3615 SAFE_STRCPY(buf, o);
3616 la = split(arg, buf, ARRAY_SIZE(arg), ',');
3617 for (i = 0; i < la; i++) {
3618 sep = strchr(arg[i], '-');
3619
3620 if (sep == NULL) {
3621 st = end = map_int(arg[i], NULL);
3622 } else {
3623 st = map_int(arg[i], NULL);
3624 end = map_int(sep + 1, NULL);
3625 }
3626 for (j = st; j <= end; j++) {
3627
3628 force_ci_adapter(j);
3629 LOG("Forcing CA %d to CI", j);
3630 }
3631 }
3632 }
3633
set_ca_adapter_pin(char * o)3634 void set_ca_adapter_pin(char *o) {
3635 int i, j, la, st, end;
3636 char buf[1000], *arg[40], *sep, *seps;
3637 SAFE_STRCPY(buf, o);
3638 la = split(arg, buf, ARRAY_SIZE(arg), ',');
3639 for (i = 0; i < la; i++) {
3640 sep = strchr(arg[i], '-');
3641 seps = strchr(arg[i], ':');
3642
3643 if (!seps)
3644 continue;
3645
3646 if (sep == NULL) {
3647 st = end = map_int(arg[i], NULL);
3648 } else {
3649 st = map_int(arg[i], NULL);
3650 end = map_int(sep + 1, NULL);
3651 }
3652 for (j = st; j <= end; j++) {
3653 set_ca_pin(j, seps + 1);
3654 LOG("Setting CA %d pin to %s", j, seps + 1);
3655 }
3656 }
3657 }
3658
set_ca_multiple_pmt(char * o)3659 void set_ca_multiple_pmt(char *o) {
3660 int i, la, ddci;
3661 char buf[1000], *arg[40], *sep, *seps;
3662 SAFE_STRCPY(buf, o);
3663 la = split(arg, buf, ARRAY_SIZE(arg), ',');
3664 for (i = 0; i < la; i++) {
3665 sep = strchr(arg[i], ':');
3666
3667 if (!sep)
3668 continue;
3669
3670 int max_ca_pmt = atoi(sep + 1);
3671
3672 ddci = map_intd(arg[i], NULL, -1);
3673 if (!ca_devices[ddci])
3674 ca_devices[ddci] = alloc_ca_device();
3675 if (!ca_devices[ddci])
3676 return;
3677 ca_devices[ddci]->multiple_pmt = 1;
3678 ca_devices[ddci]->max_ca_pmt = max_ca_pmt;
3679 LOG("Forcing CA %d to use multiple PMTs with maximum channels %d", ddci,
3680 max_ca_pmt);
3681 seps = sep;
3682 while ((seps = strchr(seps + 1, '-'))) {
3683 int caid = strtoul(seps + 1, NULL, 16);
3684 if (caid > 0)
3685 ca_devices[ddci]->caid[ca_devices[ddci]->caids++] = caid;
3686 LOG("Forcing CA %d to use CAID %04X", ddci, caid);
3687 }
3688 }
3689 }
3690