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