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