2 * Bulcrypt card reader for OSCAM
3 * Copyright (C) 2012 Unix Solutions Ltd.
5 * Authors: Anton Tinchev (atl@unixsol.org)
6 * Georgi Chorbadzhiyski (gf@unixsol.org)
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 * =========================================================================
23 * For more information read the code and the comments. We have tried to
24 * write clear code with lots of comments so it is easy for others to
25 * understand what is going on. There are some things marked *FIXME*,
26 * that are mostly unknown or not fully understand.
28 * WHAT WAS TESTED AND WAS WORKING:
29 * - Cards with bulcrypt v1 ("cherga"/carpet) are working (we have cards
30 * that report CardType: 0x4c and 0x75.
31 * - Cards return valid code words for subscribed channels.
32 * - Tested with channels encrypted with CAID 0x5581 and 0x4aee on
33 * Hellas 39E. Both MPEG2 (SD) and H.264 (SD and HD) channels were
35 * - Brand new cards were inited without ever being put into providers STBs.
36 * as long the protocol you are using is sending EMMs to the card.
37 * - AU was working (subscription dates and packages were updated)
38 * as long the protocol you are using is sending EMMs to the card.
40 * WHAT WE DON'T KNOW (YET!):
41 * - How to deobfuscate v2 codewords.
44 * - Many thanks to ilian_71 @ satfriends forum for the protocol info.
45 * - Shouts to yuriks for oscam-ymod, pity it is violating the GPL.
50 #ifdef READER_BULCRYPT
51 #include "oscam-work.h"
52 #include "reader-common.h"
54 static const uint8_t atr_carpet
[] = { 0x3b, 0x20, 0x00 };
56 // *FIXME* We do not know how every 4th byte of the sess_key is calculated.
57 // Currently they are correct thou and code words checksums are correct are
59 static const uint8_t sess_key
[] = { 0xF2, 0x21, 0xC5, 0x69, 0x28, 0x86, 0xFB, 0x9E,
60 0xC0, 0x20, 0x28, 0x06, 0xD2, 0x23, 0x72, 0x31 };
62 static const uint8_t cmd_set_key
[] = { 0xDE, 0x1C, 0x00, 0x00, 0x0A, 0x12, 0x08, 0x56,
63 0x47, 0x38, 0x29, 0x10, 0xAF, 0xBE, 0xCD };
65 static const uint8_t cmd_set_key_v2
[] = { 0xDE, 0x1C, 0x00, 0x00, 0x0A, 0x12, 0x08, 0x00,
66 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
70 static const uint8_t cmd_card_v2_key1
[] = { 0xDE, 0x12, 0x00, 0x00, 0x00, 0x00 };
71 static const uint8_t cmd_card_v2_key2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x12, 0x00 };
73 static const uint8_t cmd_cardtype1
[] = { 0xDE, 0x16, 0x00, 0x00, 0x00, 0x00 };
74 static const uint8_t cmd_cardtype2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x03, 0x00 };
76 // Response2: 01 01 4C 90 00 or 01 01 xx 90 00
77 // xx - 4C or 75 (Card type)
79 static const uint8_t cmd_unkn_0a1
[] = { 0xDE, 0x0A, 0x00, 0x00, 0x00, 0x00 };
80 static const uint8_t cmd_unkn_0a2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x03, 0x00 };
82 // Response2: 08 01 00 90 00
84 static const uint8_t cmd_cardsn1
[] = { 0xDE, 0x18, 0x00, 0x00, 0x00, 0x00 };
85 static const uint8_t cmd_cardsn2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x06, 0x00 };
87 // Response2: 02 04 xx xx xx xy 90 00
88 // xx - Card HEX serial
89 // y - Unknown *FIXME*
91 static const uint8_t cmd_ascsn1
[] = { 0xDE, 0x1A, 0x00, 0x00, 0x00, 0x00 };
92 static const uint8_t cmd_ascsn2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x0F, 0x00 };
94 // Response2: 05 0D xx xx 20 xx xx xx xx xx xx 20 xx xx xx 90 00
95 // xx - Card ASCII serial
97 static const uint8_t cmd_ecm_empty
[] = { 0xDE, 0x20, 0x00, 0x00, 0x00, 0x00 };
100 static const uint8_t cmd_ecm
[] = { 0xDE, 0x20, 0x00, 0x00, 0x4c };
101 // The last byte is ECM length
103 static const uint8_t cmd_ecm_get_cw
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x13, 0x00 };
104 // Response: 0A 11 80 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx 90 00
105 // 80 - Returned codeword type? *FIXME*
106 // xx - Obfuscated CW
108 static const uint8_t cmd_emm1
[] = { 0xDE, 0x02, 0x82, 0x00, 0xb0 };
109 // Response: 90 00 (EMM written OK) or
110 // Response: 90 0A (Subscription data was updated)
111 // The last byte is EMM length (0xb0)
113 static const uint8_t cmd_emm2
[] = { 0xDE, 0x04, 0x00, 0x00, 0xb0 };
114 // Response: 90 00 (EMM written OK)
115 // cmd_emm[2] = emm_cmd1
116 // cmd_emm[3] = emm_cmd2
117 // The last byte is EMM length (0xb0)
119 static const uint8_t cmd_sub_info1
[] = { 0xDE, 0x06, 0x00, 0x00, 0x00, 0x00 };
120 static const uint8_t cmd_sub_info2
[] = { 0xDE, 0x1E, 0x00, 0x00, 0x2B, 0x00 };
121 // See bulcrypt_card_info() for reponse description
125 uint8_t bulcrypt_version
;
128 static int32_t bulcrypt_card_init(struct s_reader
*reader
, ATR
*newatr
)
132 char card_serial
[16];
133 const uint8_t *set_key_command
;
139 if(memcmp(atr
, atr_carpet
, MIN(sizeof(atr_carpet
), atr_size
)) != 0)
143 rdr_log(reader
, "ATR_len=3 but ATR is unknown: %s",
144 cs_hexdump(1, atr
, atr_size
, tmp
, sizeof(tmp
)));
149 if(!cs_malloc(&reader
->csystem_data
, sizeof(struct bulcrypt_data
)))
152 struct bulcrypt_data
*csystem_data
= reader
->csystem_data
;
155 memset(reader
->prid
, 0, sizeof(reader
->prid
));
156 memset(reader
->hexserial
, 0, sizeof(reader
->hexserial
));
157 memset(card_serial
, 0, sizeof(card_serial
));
159 rdr_log(reader
, "Bulcrypt card detected, checking card version.");
161 // Do we have Bulcrypt V2 card?
162 write_cmd(cmd_card_v2_key1
, NULL
);
163 write_cmd(cmd_card_v2_key2
, NULL
);
164 if(cta_lr
< 18 || (cta_res
[0] != 0x11 && cta_res
[1] != 0x10))
167 csystem_data
->bulcrypt_version
= 1;
168 set_key_command
= cmd_set_key
;
173 csystem_data
->bulcrypt_version
= 2;
174 set_key_command
= cmd_set_key_v2
;
177 // Set CW obfuscation key
178 write_cmd(set_key_command
, set_key_command
+ 5);
179 if(cta_lr
< 2 || (cta_res
[0] != 0x90 && cta_res
[1] != 0x00))
181 rdr_log(reader
, "(cmd_set_key) Unexpected card answer: %s",
182 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
186 rdr_log(reader
, "Bulcrypt v%d card detected.%s", csystem_data
->bulcrypt_version
,
187 csystem_data
->bulcrypt_version
!= 1 ? " *UNSUPPORTED CARD VERSION*" : "");
190 write_cmd(cmd_cardtype1
, NULL
);
191 write_cmd(cmd_cardtype2
, NULL
);
192 if(cta_lr
< 5 || (cta_res
[0] != 0x01 && cta_res
[1] != 0x01))
194 rdr_log(reader
, "(cmd_cardtype) Unexpected card answer: %s",
195 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
198 card_type
= cta_res
[2]; // We have seen 0x4c and 0x75
200 // *FIXME* Unknown command
201 write_cmd(cmd_unkn_0a1
, NULL
);
202 write_cmd(cmd_unkn_0a2
, NULL
);
204 // Read card HEX serial
205 write_cmd(cmd_cardsn1
, NULL
);
206 write_cmd(cmd_cardsn2
, NULL
);
207 if(cta_lr
< 6 || (cta_res
[0] != 0x02 && cta_res
[1] != 0x04))
209 rdr_log(reader
, "(card_sn) Unexpected card answer: %s",
210 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
213 memcpy(reader
->hexserial
, cta_res
+ 2, 4);
214 // Skip bottom four bits (they are 0x0b on our cards)
215 reader
->hexserial
[3] = reader
->hexserial
[3] & 0xF0;
217 // Read card ASCII serial
218 write_cmd(cmd_ascsn1
, NULL
);
219 write_cmd(cmd_ascsn2
, NULL
);
221 if(cta_lr
< 15 || (cta_res
[0] != 0x05 && cta_res
[1] != 0x0d))
223 rdr_log(reader
, "(asc_sn) Unexpected card answer: %s",
224 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
227 memcpy(card_serial
, cta_res
+ 2, 13);
228 cta_lr
= cs_strlen(card_serial
);
230 for(i
= 0; i
< cta_lr
; i
++)
232 if(card_serial
[i
] == ' ')
236 if(!isdigit((uint8_t)card_serial
[i
]))
237 { card_serial
[i
] = '*'; }
240 // Write empty ECM, *FIXME* why are we doing this? To prepare the card somehow?
241 write_cmd(cmd_ecm_empty
, NULL
);
243 // The HEX serial have nothing to do with Serial (they do not match)
244 rdr_log_sensitive(reader
, "CAID: 0x4AEE|0x5581, CardType: 0x%02x, Serial: {%s}, HexSerial: {%02X %02X %02X %02X}",
247 reader
->hexserial
[0], reader
->hexserial
[1], reader
->hexserial
[2], reader
->hexserial
[3]);
249 rdr_log(reader
, "Ready for requests.");
254 static int cw_is_valid(struct s_reader
*reader
, uint8_t *cw
)
256 unsigned int i
= 0, cnt
= 0;
266 rdr_log(reader
, "Invalid CW (all zeroes)");
270 uint8_t cksum1
= cw
[0] + cw
[1] + cw
[2];
271 uint8_t cksum2
= cw
[4] + cw
[5] + cw
[6];
272 if(cksum1
!= cw
[3] || cksum2
!= cw
[7])
275 { rdr_log(reader
, "Invalid CW (cksum1 mismatch expected 0x%02x got 0x%02x)", cksum1
, cw
[3]); }
277 { rdr_log(reader
, "Invalid CW (cksum2 mismatch expected 0x%02x got 0x%02x)", cksum2
, cw
[7]); }
285 Bulcrypt ECM structure:
287 80 70 - ECM header (80 | 81)
288 4c - ECM length after this field (0x4c == 76 bytes)
289 4f 8d 87 0b - unixts == 1334675211 == Tue Apr 17 18:06:51 EEST 2012
290 00 66 - *FIXME* Program number?
294 xx yy zz .. - Encrypted ECM payload (64 bytes)
297 static int32_t bulcrypt_do_ecm(struct s_reader
*reader
, const ECM_REQUEST
*er
, struct s_ecm_answer
*ea
)
300 uint8_t ecm_cmd
[256];
301 struct bulcrypt_data
*csystem_data
= reader
->csystem_data
;
305 int32_t ecm_len
= check_sct_len(er
->ecm
, 3);
306 if(ecm_len
< 64 || ecm_len
> 188)
308 rdr_log(reader
, "Wrong ECM length: %d", ecm_len
);
312 // CMD: DE 20 00 00 4C
313 memcpy(ecm_cmd
, cmd_ecm
, sizeof(cmd_ecm
));
314 ecm_cmd
[4] = er
->ecm
[2]; // Set ECM length
315 memcpy(ecm_cmd
+ sizeof(cmd_ecm
), er
->ecm
+ 3, ecm_cmd
[4]);
318 write_cmd(ecm_cmd
, ecm_cmd
+ 5);
321 rdr_log(reader
, "(ecm_cmd) Unexpected card answer: %s",
322 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
326 if(cta_res
[0] == 0x90 && cta_res
[1] == 0x03)
328 rdr_log(reader
, "No active subscription.");
332 if(!(cta_res
[0] == 0x90 && cta_res
[1] == 0x13))
334 rdr_log(reader
, "(ecm_cmd) Unexpected card answer: %s",
335 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
340 write_cmd(cmd_ecm_get_cw
, NULL
);
342 // rdr_log(reader, "CW_LOG: %s", cs_hexdump(1, cta_res, cta_lr, tmp, sizeof(tmp)));
343 if(cta_lr
< 20 || (cta_res
[0] != 0x0a && cta_res
[1] != 0x11))
345 rdr_log(reader
, "(get_cw) Unexpected card answer: %s",
346 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
350 // *FIXME* is the bellow info true?
351 // 0x80 (ver 1) is supported
352 // 0xc0 (ver 2) is *NOT* supported currently
353 if(cta_res
[2] == 0xc0)
355 rdr_log(reader
, "Possibly unsupported codeword (bulcrypt v2): %s",
356 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
357 // *FIXME* commented for testing, this really should be an error
361 // Remove code word obfuscation
362 uint8_t *cw
= cta_res
+ 3;
363 if(csystem_data
->bulcrypt_version
== 1)
366 for(i
= 0 ; i
< 16; i
++)
368 cw
[i
] = cw
[i
] ^ sess_key
[i
];
372 if(er
->ecm
[0] == 0x81)
374 // Even/Odd CWs should be exchanged
375 memcpy(ea
->cw
, cw
+ 8, 8);
376 memcpy(ea
->cw
+ 8, cw
, 8);
380 memcpy(ea
->cw
, cw
, 8);
381 memcpy(ea
->cw
+ 8, cw
+ 8, 8);
384 // Check if DCW is valid
385 if(!cw_is_valid(reader
, ea
->cw
) || !cw_is_valid(reader
, ea
->cw
+ 8))
392 Bulcrypt EMMs structure
394 All EMMs are with section length 183 (0xb7)
395 3 bytes section header
399 82 70 - UNUQUE_EMM_82|8a
400 b4 - Payload length (0xb4 == 180)
401 xx xx xx xy - Card HEX SN (the last 4 bits (y) must be masked)
404 85 70 - GLOBAL_EMM_85|8b
405 b4 - Payload length (0xb4 == 180)
406 xx xx yy yy - Card HEX SN (the last 16 bits (y) must be masked)
409 84 70 - SHARED_EMM_84
410 b4 - Payload length (0xb4 == 180)
411 xx xx - Card HEX SN Prefix
417 8f 70 b4 ff ff ff ff ff ff ff ff ff .. .. (ff to the end)
419 Stats for EMMs collected for a period of 1 hours and 24 minutes
421 2279742 - 82 70 b4 - unique_82
422 19051 - 8a 70 b4 - unique_8a (polaris equivallent of 0x82)
423 199949 - 84 70 b4 - shared_84
424 595309 - 85 70 b4 - global_85
425 6417 - 8b 70 b4 - global_8b (polaris equivallent of 0x85)
426 74850 - 8f 70 b4 - filler
428 Total EMMs for the period: 3175317
431 #define BULCRYPT_EMM_UNIQUE_82 0x82 // Addressed at single card (updates subscription info)
432 #define BULCRYPT_EMM_UNIQUE_8a 0x8a // Addressed at single card (like 0x82) used for Polaris
433 #define BULCRYPT_EMM_SHARED_84 0x84 // Addressed to 4096 cards (updates keys)
434 #define BULCRYPT_EMM_GLOBAL_85 0x85 // Addressed at 4096 cards (updates packages)
435 #define BULCRYPT_EMM_GLOBAL_8b 0x8b // Addressed at 4096 cards (like 0x85) used for Polaris
436 #define BULCRYPT_EMM_FILLER 0x8f // Filler to pad the EMM stream
438 static int32_t bulcrypt_get_emm_type(EMM_PACKET
*ep
, struct s_reader
*reader
)
440 char dump_emm_sn
[64];
441 int32_t emm_len
= check_sct_len(ep
->emm
, 3);
443 memset(ep
->hexserial
, 0, 8);
447 rdr_log_dbg(reader
, D_TRACE
| D_EMM
, "emm_len < 176 (%u): %s",
448 emm_len
, cs_hexdump(1, ep
->emm
, 12, dump_emm_sn
, sizeof(dump_emm_sn
)));
456 case BULCRYPT_EMM_UNIQUE_82
:
460 case BULCRYPT_EMM_UNIQUE_8a
:
464 case BULCRYPT_EMM_SHARED_84
:
468 case BULCRYPT_EMM_GLOBAL_85
:
472 case BULCRYPT_EMM_GLOBAL_8b
:
478 if(ep
->type
== UNIQUE
)
480 // The serial numbers looks like this:
482 memcpy(ep
->hexserial
, ep
->emm
+ 3, 4);
483 ret
= reader
->hexserial
[0] == ep
->hexserial
[0] &&
484 reader
->hexserial
[1] == ep
->hexserial
[1] &&
485 reader
->hexserial
[2] == ep
->hexserial
[2] &&
486 ((reader
->hexserial
[3] & 0xF0) == (ep
->hexserial
[3] & 0xF0));
490 // To match EMM_84, EMM_85, EMM_8b
492 memcpy(ep
->hexserial
, ep
->emm
+ 3, 2);
493 ret
= reader
->hexserial
[0] == ep
->hexserial
[0] &&
494 reader
->hexserial
[1] == ep
->hexserial
[1];
499 char dump_card_sn
[64];
500 cs_hexdump(1, reader
->hexserial
, 4, dump_card_sn
, sizeof(dump_card_sn
));
501 cs_hexdump(1, ep
->hexserial
, 4, dump_emm_sn
, sizeof(dump_emm_sn
));
502 rdr_log_sensitive(reader
, "EMM_%s-%02x, emm_sn = {%s}, card_sn = {%s}",
503 ep
->type
== UNIQUE
? "UNIQUE" :
504 ep
->type
== SHARED
? "SHARED" :
505 ep
->type
== GLOBAL
? "GLOBAL" : "??????",
514 static int32_t bulcrypt_get_emm_filter(struct s_reader
*rdr
, struct s_csystem_emm_filter
**emm_filters
, unsigned int *filter_count
)
516 if(*emm_filters
== NULL
)
518 const unsigned int max_filter_count
= 5;
519 if(!cs_malloc(emm_filters
, max_filter_count
* sizeof(struct s_csystem_emm_filter
)))
522 struct s_csystem_emm_filter
*filters
= *emm_filters
;
527 filters
[idx
].type
= EMM_UNIQUE
;
528 filters
[idx
].enabled
= 1;
529 filters
[idx
].filter
[0] = 0x82;
530 filters
[idx
].filter
[1] = rdr
->hexserial
[0];
531 filters
[idx
].filter
[2] = rdr
->hexserial
[1];
532 filters
[idx
].filter
[3] = rdr
->hexserial
[2];
533 filters
[idx
].filter
[4] = rdr
->hexserial
[3];
534 filters
[idx
].mask
[0] = 0xFF;
535 filters
[idx
].mask
[1] = 0xFF;
536 filters
[idx
].mask
[2] = 0xFF;
537 filters
[idx
].mask
[3] = 0xFF;
538 filters
[idx
].mask
[4] = 0xF0;
541 filters
[idx
].type
= EMM_UNIQUE
;
542 filters
[idx
].enabled
= 1;
543 filters
[idx
].filter
[0] = 0x8a;
544 filters
[idx
].filter
[1] = rdr
->hexserial
[0];
545 filters
[idx
].filter
[2] = rdr
->hexserial
[1];
546 filters
[idx
].filter
[3] = rdr
->hexserial
[2];
547 filters
[idx
].filter
[4] = rdr
->hexserial
[3];
548 filters
[idx
].mask
[0] = 0xFF;
549 filters
[idx
].mask
[1] = 0xFF;
550 filters
[idx
].mask
[2] = 0xFF;
551 filters
[idx
].mask
[3] = 0xFF;
552 filters
[idx
].mask
[4] = 0xF0;
555 filters
[idx
].type
= EMM_SHARED
;
556 filters
[idx
].enabled
= 1;
557 filters
[idx
].filter
[0] = 0x84;
558 filters
[idx
].filter
[1] = rdr
->hexserial
[0];
559 filters
[idx
].filter
[2] = rdr
->hexserial
[1];
560 filters
[idx
].mask
[0] = 0xFF;
561 filters
[idx
].mask
[1] = 0xFF;
562 filters
[idx
].mask
[2] = 0xFF;
565 filters
[idx
].type
= EMM_GLOBAL
;
566 filters
[idx
].enabled
= 1;
567 filters
[idx
].filter
[0] = 0x85;
568 filters
[idx
].filter
[1] = rdr
->hexserial
[0];
569 filters
[idx
].filter
[2] = rdr
->hexserial
[1];
570 filters
[idx
].mask
[0] = 0xFF;
571 filters
[idx
].mask
[1] = 0xFF;
572 filters
[idx
].mask
[2] = 0xFF;
575 filters
[idx
].type
= EMM_GLOBAL
;
576 filters
[idx
].enabled
= 1;
577 filters
[idx
].filter
[0] = 0x8b;
578 filters
[idx
].filter
[1] = rdr
->hexserial
[0];
579 filters
[idx
].filter
[2] = rdr
->hexserial
[1];
580 filters
[idx
].mask
[0] = 0xFF;
581 filters
[idx
].mask
[1] = 0xFF;
582 filters
[idx
].mask
[2] = 0xFF;
591 static int32_t bulcrypt_do_emm(struct s_reader
*reader
, EMM_PACKET
*ep
)
594 uint8_t emm_cmd
[1024];
599 // xx == EMM type (emm[0])
600 // yy == EMM type2 (emm[5])
601 // B0 == EMM len (176)
602 memcpy(emm_cmd
, cmd_emm1
, sizeof(cmd_emm1
));
603 memcpy(emm_cmd
+ sizeof(cmd_emm1
), ep
->emm
+ 7, 176);
607 case BULCRYPT_EMM_UNIQUE_82
:
608 emm_cmd
[2] = ep
->emm
[0]; // 0x82
611 case BULCRYPT_EMM_UNIQUE_8a
: // Polaris equivallent of 0x82
616 case BULCRYPT_EMM_SHARED_84
:
617 emm_cmd
[2] = ep
->emm
[0]; // 0x84
618 emm_cmd
[3] = ep
->emm
[5]; // 0x0b
621 case BULCRYPT_EMM_GLOBAL_85
:
622 case BULCRYPT_EMM_GLOBAL_8b
: // Polaris 0x85 equivallent of 0x85
623 memcpy(emm_cmd
, cmd_emm2
, sizeof(cmd_emm2
));
624 emm_cmd
[2] = ep
->emm
[5]; // 0xXX (Last bytes of the serial)
625 emm_cmd
[3] = ep
->emm
[6]; // 0x0b
630 write_cmd(emm_cmd
, emm_cmd
+ 5);
631 if(cta_lr
!= 2 || cta_res
[0] != 0x90 || (cta_res
[1] != 0x00 && cta_res
[1] != 0x0a && cta_res
[1] != 0x12))
633 rdr_log(reader
, "(emm_cmd) Unexpected card answer: %s",
634 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
638 // V2 answers of 82 EMM
639 if(cta_res
[0] == 0x90 && cta_res
[1] == 0x12)
641 write_cmd(cmd_card_v2_key2
, NULL
);
642 if(cta_res
[18] == 0x90 && cta_res
[19] == 0x12)
644 write_cmd(cmd_card_v2_key2
, NULL
);
648 if(ep
->emm
[0] == BULCRYPT_EMM_UNIQUE_82
&& cta_res
[0] == 0x90 && (cta_res
[1] == 0x0a || cta_res
[1] == 0x00))
650 rdr_log(reader
, "Your subscription data was updated.");
651 add_job(reader
->client
, ACTION_READER_CARDINFO
, NULL
, 0);
657 static char *dec2bin_str(unsigned int d
, char *s
)
659 unsigned int i
, r
= 8;
661 for(i
= 1; i
< 256; i
<<= 1)
662 { s
[--r
] = (d
& i
) == i
? '+' : '-'; }
666 static int32_t bulcrypt_card_info(struct s_reader
*reader
)
669 time_t last_upd_ts
, subs_end_ts
;
673 rdr_log(reader
, "Reading subscription info.");
675 cs_clear_entitlement(reader
);
677 write_cmd(cmd_sub_info1
, NULL
);
678 write_cmd(cmd_sub_info2
, NULL
);
682 rdr_log(reader
, "(info_cmd) Unexpected card answer: %s",
683 cs_hexdump(1, cta_res
, cta_lr
, tmp
, sizeof(tmp
)));
687 // Response contains:
689 // 4F 8F 00 E9 - Unix ts set by UNIQUE_EMM_82
690 // 3C 65 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF
691 // 3C 84 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 BF
694 last_upd_ts
= b2i(4, cta_res
+ 3);
695 subs_end_ts
= last_upd_ts
+ (31 * 86400); // *FIXME* this is just a guess
697 reader
->card_valid_to
= subs_end_ts
;
699 gmtime_r(&last_upd_ts
, &tm
);
700 memset(tmp
, 0, sizeof(tmp
));
701 strftime(tmp
, sizeof(tmp
), "%Y-%m-%d %H:%M:%S %Z", &tm
);
702 rdr_log(reader
, "Subscription data last update : %s", tmp
);
704 gmtime_r(&subs_end_ts
, &tm
);
705 memset(tmp
, 0, sizeof(tmp
));
706 strftime(tmp
, sizeof(tmp
), "%Y-%m-%d %H:%M:%S %Z", &tm
);
707 rdr_log(reader
, "Subscription should be active to : %s", tmp
);
709 unsigned int subs1
= b2i(2, cta_res
+ 3 + 4 + 16);
710 unsigned int subs2
= b2i(2, cta_res
+ 3 + 4 + 16 + 18);
714 rdr_log(reader
, "No active subscriptions (0x%04x, 0x%04x)", subs1
, subs2
);
719 rdr_log(reader
, "Subscription data 1 (0x%04x): %s",
720 subs1
, dec2bin_str(subs1
, tmp
));
721 rdr_log(reader
, "Subscription data 2 (0x%04x): %s",
722 subs2
, dec2bin_str(subs2
, tmp
));
724 // Configure your tiers to get subscription packets name resolution
725 // # Example oscam.tiers file
726 // 5581:0001|Economic
727 // 5581:0002|Standard
731 // 5581:0020|Unknown Package 20
732 // 5581:0040|Film Plus - Sport Plus HD & Hobby TV HD
733 // 5581:0080|Unknown Package 80
734 for(i
= 1; i
< 256; i
<<= 1)
738 cs_add_entitlement(reader
, 0x4AEE,
742 last_upd_ts
, /* start_ts */
743 subs_end_ts
, /* end_ts */
747 cs_add_entitlement(reader
, 0x5581,
751 last_upd_ts
, /* start_ts */
752 subs_end_ts
, /* end_ts */
756 get_tiername(i
, 0x4aee, tmp
);
758 { get_tiername(i
, 0x5581, tmp
); }
759 rdr_log(reader
, "Package %02x is active: %s", i
, tmp
);
764 rdr_log(reader
, "End subscription info.");
768 const struct s_cardsystem reader_bulcrypt
=
771 .caids
= (uint16_t[]){ 0x5581, 0x4AEE, 0 },
772 .do_emm
= bulcrypt_do_emm
,
773 .do_ecm
= bulcrypt_do_ecm
,
774 .card_info
= bulcrypt_card_info
,
775 .card_init
= bulcrypt_card_init
,
776 .get_emm_type
= bulcrypt_get_emm_type
,
777 .get_emm_filter
= bulcrypt_get_emm_filter
,