- fix for ticker #4787
[oscam.git] / reader-dgcrypt.c
blob63ec7372edb4e2dcff77dc3ef494b688e017461b
1 #include "globals.h"
2 #ifdef READER_DGCRYPT
3 #include "reader-common.h"
5 #define DEBUG 0
7 static const uint8_t dgcrypt_atr[8] = { 0x3B, 0xE9, 0x00, 0x00, 0x81, 0x31, 0xC3, 0x45 };
8 static const uint8_t cmd_CWKEY[5] = { 0x81, 0xD0, 0x00, 0x01, 0x08 };
9 //static const uint8_t cmd_CAID[5] = { 0x81, 0xC0, 0x00, 0x01, 0x0A };
10 static const uint8_t cmd_SERIAL[5] = { 0x81, 0xD1, 0x00, 0x01, 0x10 };
11 static const uint8_t cmd_LABEL[5] = { 0x81, 0xD2, 0x00, 0x01, 0x10 };
12 //static const uint8_t cmd_SUBSYS[5] = { 0x81, 0xDD, 0x00, 0x10, 0x04 };
13 static const uint8_t cmd_ECM[3] = { 0x80, 0xEA, 0x80 };
15 struct dgcrypt_data
17 uint8_t session_key[16];
20 static int32_t dgcrypt_cmd(struct s_reader *rdr, const uint8_t *buf, const int32_t buflen, uint8_t *response, uint16_t *response_length, uint16_t min_response_len)
22 rdr->ifsc = 195;
23 rdr->ns = 1;
25 if(DEBUG)
27 char tmp[512];
28 rdr_log(rdr, "SEND -> %s(%d)", cs_hexdump(1, buf, buflen, tmp, sizeof(tmp)), buflen);
30 int32_t ret = reader_cmd2icc(rdr, buf, buflen, response, response_length);
32 if(DEBUG)
34 char tmp[512];
35 rdr_log(rdr, "RECV <- %s(%d) ret=%d", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), *response_length, ret);
37 // reader_cmd2icc retuns ERROR=1, OK=0 - the opposite of OK and ERROR defines in reader-common.h
39 if(ret)
41 rdr_log(rdr, "ERROR: reader_cmd2icc() ret=%d", ret);
42 return ERROR;
45 if(*response_length < 2 || *response_length < min_response_len)
47 rdr_log(rdr, "ERROR: response_length=%d < min_response_length=%d", *response_length, min_response_len);
48 return ERROR; // Response is two short
51 if(response[*response_length - 2] != 0x90 || response[*response_length - 1] != 0x00)
53 rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]);
54 rdr_log(rdr, "ERROR: response[-1] != 0x00 its 0x%02X", response[*response_length - 1]);
55 return ERROR; // The reader responded with "command not OK"
57 return OK;
60 static int32_t dgcrypt_card_init(struct s_reader *rdr, ATR *newatr)
62 def_resp
64 get_atr
65 if(atr_size < sizeof(dgcrypt_atr))
66 { return ERROR; }
68 // Full ATR: 3B E9 00 00 81 31 C3 45 99 63 74 69 19 99 12 56 10 EC
69 if(memcmp(atr, dgcrypt_atr, sizeof(dgcrypt_atr)) != 0)
70 { return ERROR; }
72 if(!cs_malloc(&rdr->csystem_data, sizeof(struct dgcrypt_data)))
73 { return ERROR; }
75 struct dgcrypt_data *csystem_data = rdr->csystem_data;
77 rdr_log(rdr, "[dgcrypt-reader] card detected.");
79 memset(rdr->sa, 0, sizeof(rdr->sa));
80 memset(rdr->prid, 0, sizeof(rdr->prid));
81 memset(rdr->hexserial, 0, sizeof(rdr->hexserial));
83 rdr->nprov = 1;
84 rdr->caid = 0x4ABF;
86 // Get session key
87 // Send: 81 D0 00 01 08
88 // Recv: 32 86 17 D5 2C 66 61 14 90 00
89 if(!dgcrypt_cmd(rdr, cmd_CWKEY, sizeof(cmd_CWKEY), cta_res, &cta_lr, 8))
90 { return ERROR; }
91 memcpy(csystem_data->session_key + 0, cta_res, 8);
92 memcpy(csystem_data->session_key + 8, cta_res, 8);
94 // Get CAID
95 // Send: 81 C0 00 01 0A
96 // Recv: 4A BF 90 00
97 // if (!dgcrypt_cmd(rdr, cmd_CAID, sizeof(cmd_CAID), cta_res, &cta_lr, 2))
98 // return ERROR;
99 // rdr->caid = (cta_res[0] << 8) | cta_res[1];
101 // Get serial number
102 // Send: 81 D1 00 01 10
103 // Recv: 00 0D DB 08 71 0D D5 0C 30 30 30 30 30 30 30 30 90 00
104 if(!dgcrypt_cmd(rdr, cmd_SERIAL, sizeof(cmd_SERIAL), cta_res, &cta_lr, 8))
105 { return ERROR; }
106 memcpy(rdr->hexserial, cta_res + 1, 7);
108 // Get LABEL
109 // Send: 81 D2 00 01 10
110 // Recv: 50 61 79 5F 54 56 5F 43 61 72 64 00 00 00 00 00 90 00
111 // Txt: P a y _ T V _ C a r d
112 if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 16))
113 { return ERROR; }
114 char label[17];
115 memset(label, 0, sizeof(label));
116 memcpy(label, cta_res, 16);
118 // Get subsystem - !FIXME! We are not using the answer of this command!
119 // Send: 81 DD 00 10 04
120 // Recv: 00 55 00 55 90 00
121 if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 4))
122 { return ERROR; }
124 rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%"PRIu64"} HexSerial: {%02X %02X %02X %02X %02X %02X %02X} Label: {%s}",
125 rdr->caid,
126 b2ll(7, rdr->hexserial),
127 rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2],
128 rdr->hexserial[3], rdr->hexserial[4], rdr->hexserial[5], rdr->hexserial[6],
129 label);
131 return OK;
134 static int32_t dgcrypt_do_ecm(struct s_reader *rdr, const ECM_REQUEST *er, struct s_ecm_answer *ea)
136 def_resp
137 uint8_t cmd_buffer[256];
138 struct dgcrypt_data *csystem_data = rdr->csystem_data;
140 memcpy(cmd_buffer, er->ecm, er->ecm[2] + 3);
141 // Replace The first 3 bytes of the ECM with the command
142 memcpy(cmd_buffer, cmd_ECM, sizeof(cmd_ECM));
144 // Write ECM
145 // Send: 80 EA 80 00 55 00 00 3F 90 03 00 00 18 5D 82 4E 01 C4 2D 60 12 ED 34 37 ED 72 .. .. ..
146 // Recv: 72 25 8D A1 0D 0D D2 44 EE ED 51 2F 3B 5D 19 63 E6 90 00
147 if(!dgcrypt_cmd(rdr, cmd_buffer, er->ecm[2] + 3, cta_res, &cta_lr, 17))
148 { return ERROR; }
150 if(cta_res[0] != 0x72) // CW response MUST start with 0x72
151 { return ERROR; }
153 int i;
154 for(i = 0; i < 16; i++)
156 ea->cw[i] = cta_res[1 + i] ^ csystem_data->session_key[i];
158 return OK;
161 static int32_t dgcrypt_get_emm_filter(struct s_reader *rdr __attribute__((unused)), struct s_csystem_emm_filter **emm_filters __attribute__((unused)), unsigned int *filter_count)
163 *filter_count = 0;
164 return OK;
167 const struct s_cardsystem reader_dgcrypt =
169 .desc = "dgcrypt",
170 .caids = (uint16_t[]){ 0x4ABF, 0 },
171 // DGCrypt system does not send EMMs
172 .card_init = dgcrypt_card_init,
173 .do_ecm = dgcrypt_do_ecm,
174 .get_emm_filter = dgcrypt_get_emm_filter,
177 #endif