1 | #include "globals.h"
|
---|
2 | #ifdef READER_DGCRYPT
|
---|
3 | #include "reader-common.h"
|
---|
4 |
|
---|
5 | #define DEBUG 0
|
---|
6 |
|
---|
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 };
|
---|
14 |
|
---|
15 | struct dgcrypt_data
|
---|
16 | {
|
---|
17 | uint8_t session_key[16];
|
---|
18 | };
|
---|
19 |
|
---|
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)
|
---|
21 | {
|
---|
22 | rdr->ifsc = 195;
|
---|
23 | rdr->ns = 1;
|
---|
24 | if(DEBUG)
|
---|
25 | {
|
---|
26 | char tmp[512];
|
---|
27 | rdr_log(rdr, "SEND -> %s(%d)", cs_hexdump(1, buf, buflen, tmp, sizeof(tmp)), buflen);
|
---|
28 | }
|
---|
29 | int32_t ret = reader_cmd2icc(rdr, buf, buflen, response, response_length);
|
---|
30 | if(DEBUG)
|
---|
31 | {
|
---|
32 | char tmp[512];
|
---|
33 | rdr_log(rdr, "RECV <- %s(%d) ret=%d", cs_hexdump(1, response, *response_length, tmp, sizeof(tmp)), *response_length, ret);
|
---|
34 | }
|
---|
35 | // reader_cmd2icc retuns ERROR=1, OK=0 - the opposite of OK and ERROR defines in reader-common.h
|
---|
36 | if(ret)
|
---|
37 | {
|
---|
38 | rdr_log(rdr, "ERROR: reader_cmd2icc() ret=%d", ret);
|
---|
39 | return ERROR;
|
---|
40 | }
|
---|
41 | if(*response_length < 2 || *response_length < min_response_len)
|
---|
42 | {
|
---|
43 | rdr_log(rdr, "ERROR: response_length=%d < min_response_length=%d", *response_length, min_response_len);
|
---|
44 | return ERROR; // Response is two short
|
---|
45 | }
|
---|
46 | if(response[*response_length - 2] != 0x90 || response[*response_length - 1] != 0x00)
|
---|
47 | {
|
---|
48 | rdr_log(rdr, "ERROR: response[-2] != 0x90 its 0x%02X", response[*response_length - 2]);
|
---|
49 | rdr_log(rdr, "ERROR: response[-1] != 0x00 its 0x%02X", response[*response_length - 1]);
|
---|
50 | return ERROR; // The reader responded with "command not OK"
|
---|
51 | }
|
---|
52 | return OK;
|
---|
53 | }
|
---|
54 |
|
---|
55 | static int32_t dgcrypt_card_init(struct s_reader *rdr, ATR *newatr)
|
---|
56 | {
|
---|
57 | def_resp
|
---|
58 |
|
---|
59 | get_atr
|
---|
60 | if(atr_size < sizeof(dgcrypt_atr))
|
---|
61 | { return ERROR; }
|
---|
62 |
|
---|
63 | // Full ATR: 3B E9 00 00 81 31 C3 45 99 63 74 69 19 99 12 56 10 EC
|
---|
64 | if(memcmp(atr, dgcrypt_atr, sizeof(dgcrypt_atr)) != 0)
|
---|
65 | { return ERROR; }
|
---|
66 |
|
---|
67 | if(!cs_malloc(&rdr->csystem_data, sizeof(struct dgcrypt_data)))
|
---|
68 | { return ERROR; }
|
---|
69 | struct dgcrypt_data *csystem_data = rdr->csystem_data;
|
---|
70 |
|
---|
71 | rdr_log(rdr, "[dgcrypt-reader] card detected.");
|
---|
72 |
|
---|
73 | memset(rdr->sa, 0, sizeof(rdr->sa));
|
---|
74 | memset(rdr->prid, 0, sizeof(rdr->prid));
|
---|
75 | memset(rdr->hexserial, 0, sizeof(rdr->hexserial));
|
---|
76 |
|
---|
77 | rdr->nprov = 1;
|
---|
78 | rdr->caid = 0x4ABF;
|
---|
79 |
|
---|
80 | // Get session key
|
---|
81 | // Send: 81 D0 00 01 08
|
---|
82 | // Recv: 32 86 17 D5 2C 66 61 14 90 00
|
---|
83 | if(!dgcrypt_cmd(rdr, cmd_CWKEY, sizeof(cmd_CWKEY), cta_res, &cta_lr, 8))
|
---|
84 | { return ERROR; }
|
---|
85 | memcpy(csystem_data->session_key + 0, cta_res, 8);
|
---|
86 | memcpy(csystem_data->session_key + 8, cta_res, 8);
|
---|
87 |
|
---|
88 | // Get CAID
|
---|
89 | // Send: 81 C0 00 01 0A
|
---|
90 | // Recv: 4A BF 90 00
|
---|
91 | // if (!dgcrypt_cmd(rdr, cmd_CAID, sizeof(cmd_CAID), cta_res, &cta_lr, 2))
|
---|
92 | // return ERROR;
|
---|
93 | // rdr->caid = (cta_res[0] << 8) | cta_res[1];
|
---|
94 |
|
---|
95 | // Get serial number
|
---|
96 | // Send: 81 D1 00 01 10
|
---|
97 | // Recv: 00 0D DB 08 71 0D D5 0C 30 30 30 30 30 30 30 30 90 00
|
---|
98 | if(!dgcrypt_cmd(rdr, cmd_SERIAL, sizeof(cmd_SERIAL), cta_res, &cta_lr, 8))
|
---|
99 | { return ERROR; }
|
---|
100 | memcpy(rdr->hexserial, cta_res + 1, 7);
|
---|
101 |
|
---|
102 | // Get LABEL
|
---|
103 | // Send: 81 D2 00 01 10
|
---|
104 | // Recv: 50 61 79 5F 54 56 5F 43 61 72 64 00 00 00 00 00 90 00
|
---|
105 | // Txt: P a y _ T V _ C a r d
|
---|
106 | if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 16))
|
---|
107 | { return ERROR; }
|
---|
108 | char label[17];
|
---|
109 | memset(label, 0, sizeof(label));
|
---|
110 | memcpy(label, cta_res, 16);
|
---|
111 |
|
---|
112 | // Get subsystem - !FIXME! We are not using the answer of this command!
|
---|
113 | // Send: 81 DD 00 10 04
|
---|
114 | // Recv: 00 55 00 55 90 00
|
---|
115 | if(!dgcrypt_cmd(rdr, cmd_LABEL, sizeof(cmd_LABEL), cta_res, &cta_lr, 4))
|
---|
116 | { return ERROR; }
|
---|
117 |
|
---|
118 | rdr_log_sensitive(rdr, "CAID: 0x%04X, Serial: {%"PRIu64"} HexSerial: {%02X %02X %02X %02X %02X %02X %02X} Label: {%s}",
|
---|
119 | rdr->caid,
|
---|
120 | b2ll(7, rdr->hexserial),
|
---|
121 | rdr->hexserial[0], rdr->hexserial[1], rdr->hexserial[2],
|
---|
122 | rdr->hexserial[3], rdr->hexserial[4], rdr->hexserial[5], rdr->hexserial[6],
|
---|
123 | label);
|
---|
124 |
|
---|
125 | return OK;
|
---|
126 | }
|
---|
127 |
|
---|
128 | static int32_t dgcrypt_do_ecm(struct s_reader *rdr, const ECM_REQUEST *er, struct s_ecm_answer *ea)
|
---|
129 | {
|
---|
130 | def_resp
|
---|
131 | uint8_t cmd_buffer[256];
|
---|
132 | struct dgcrypt_data *csystem_data = rdr->csystem_data;
|
---|
133 |
|
---|
134 | memcpy(cmd_buffer, er->ecm, er->ecm[2] + 3);
|
---|
135 | // Replace The first 3 bytes of the ECM with the command
|
---|
136 | memcpy(cmd_buffer, cmd_ECM, sizeof(cmd_ECM));
|
---|
137 |
|
---|
138 | // Write ECM
|
---|
139 | // 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 .. .. ..
|
---|
140 | // Recv: 72 25 8D A1 0D 0D D2 44 EE ED 51 2F 3B 5D 19 63 E6 90 00
|
---|
141 | if(!dgcrypt_cmd(rdr, cmd_buffer, er->ecm[2] + 3, cta_res, &cta_lr, 17))
|
---|
142 | { return ERROR; }
|
---|
143 | if(cta_res[0] != 0x72) // CW response MUST start with 0x72
|
---|
144 | { return ERROR; }
|
---|
145 |
|
---|
146 | int i;
|
---|
147 | for(i = 0; i < 16; i++)
|
---|
148 | {
|
---|
149 | ea->cw[i] = cta_res[1 + i] ^ csystem_data->session_key[i];
|
---|
150 | }
|
---|
151 | return OK;
|
---|
152 | }
|
---|
153 |
|
---|
154 | void reader_dgcrypt(struct s_cardsystem *ph)
|
---|
155 | {
|
---|
156 | // DGCrypt system does not send EMMs
|
---|
157 | ph->card_init = dgcrypt_card_init;
|
---|
158 | ph->do_ecm = dgcrypt_do_ecm;
|
---|
159 | ph->caids[0] = 0x4ABF;
|
---|
160 | ph->desc = "dgcrypt";
|
---|
161 | }
|
---|
162 | #endif
|
---|