R&Y: Added DAY RTA Tapp Card and Additional BKK BEM Stored Value Card AIDs to `aid_de...
[RRG-proxmark3.git] / common / cardhelper.c
blob388cb955d486fea7422968e9f9d76fbde10865c4
1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
14 // See LICENSE.txt for the text of the license.
15 //-----------------------------------------------------------------------------
16 // Support functions for smart card
17 //-----------------------------------------------------------------------------
18 #include "cardhelper.h"
19 #include <string.h>
20 #include <stdio.h>
21 #include "cmdparser.h"
22 #include "cmdsmartcard.h"
23 #include "ui.h"
24 #include "util.h"
25 #include "commonutil.h"
27 #define CARD_INS_DECRYPT 0x01
28 #define CARD_INS_ENCRYPT 0x02
29 #define CARD_INS_VERIFY_RRG 0x05
30 #define CARD_INS_DECODE 0x06
31 #define CARD_INS_NUMBLOCKS 0x07
32 #define CARD_INS_PINSIZE 0x08
33 #define CARD_INS_CC 0x81
34 #define CARD_INS_CC_DESC 0x82
36 // look for CardHelper
37 bool IsCardHelperPresent(bool verbose) {
39 if (IfPm3Smartcard() == false) {
40 return false;
43 int resp_len = 0;
44 uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
45 uint8_t resp[30] = {0};
46 ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
48 if (resp_len < 8) {
49 return false;
52 if (strstr("CryptoHelper", (char *)resp) == 0) {
53 if (verbose) {
54 PrintAndLogEx(INFO, "Found smart card helper");
56 return true;
58 return false;
61 bool IsHIDSamPresent(bool verbose) {
63 if (IfPm3Smartcard() == false) {
64 PrintAndLogEx(WARNING, "Proxmark3 does not have SMARTCARD support enabled, exiting");
65 return false;
68 // detect SAM
69 smart_card_atr_t card;
70 smart_select(verbose, &card);
71 if (card.atr_len == 0) {
72 PrintAndLogEx(ERR, "Can't get ATR from a smart card");
73 return false;
76 // SAM identification
77 smart_card_atr_t supported[] = {
78 {15, {0x3B, 0x95, 0x96, 0x80, 0xB1, 0xFE, 0x55, 0x1F, 0xC7, 0x47, 0x72, 0x61, 0x63, 0x65, 0x13}},
79 {11, {0x3b, 0x90, 0x96, 0x91, 0x81, 0xb1, 0xfe, 0x55, 0x1f, 0xc7, 0xd4}},
81 bool found = false;
82 for (int i = 0; i < ARRAYLEN(supported); i++) {
83 if ((card.atr_len == supported[i].atr_len) &&
84 (memcmp(card.atr, supported[i].atr, supported[i].atr_len) == 0)) {
85 found = true;
86 break;
89 if (found == false) {
90 if (verbose) {
91 PrintAndLogEx(SUCCESS, "Not detecting a SAM");
93 return false;
96 // Suspect some SAMs has version name in the historical bytes
97 uint8_t T0 = card.atr[1];
98 uint8_t K = T0 & 0x0F; // Number of historical bytes
99 if (K > 0 && (K < (card.atr_len - 3)) && verbose) {
100 // Last byte of ATR is CRC and before that we have K bytes of
101 // "historical bytes".
102 // By construction K can't go above 15
103 char sam_name[16] = {0};
104 memcpy(sam_name, &card.atr[card.atr_len - 1 - K], K);
105 PrintAndLogEx(SUCCESS, "SAM (%s) detected", sam_name);
107 return true;
110 static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
111 uint8_t cmd[] = {0x96, ins, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
112 memcpy(cmd + 5, src, 8);
114 int resp_len = 0;
115 uint8_t dec[11] = {0};
116 ExchangeAPDUSC(false, cmd, sizeof(cmd), true, true, dec, sizeof(dec), &resp_len);
117 if (resp_len == 10) {
118 memcpy(dest, dec, 8);
119 return true;
121 return false;
124 bool Decrypt(uint8_t *src, uint8_t *dest) {
125 return executeCrypto(CARD_INS_DECRYPT, src, dest);
128 bool Encrypt(uint8_t *src, uint8_t *dest) {
129 return executeCrypto(CARD_INS_ENCRYPT, src, dest);
132 // Call with block6
133 void DecodeBlock6(uint8_t *src) {
135 uint8_t c[] = {0x96, CARD_INS_DECODE, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
136 memcpy(c + 6, src, 8);
138 int resp_len = 0;
139 uint8_t resp[254] = {0};
141 // first part
142 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
144 if (resp_len < 11) {
145 PrintAndLogEx(DEBUG, "decodeblock6, wrong response len, expected 11 got ( " _RED_("%d") " )", resp_len);
146 return;
149 PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
151 // second part
152 c[5] = 0x02;
153 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
155 if (resp_len < 11) {
156 PrintAndLogEx(DEBUG, "decodeblock6, wrong response len, expected 11 got ( " _RED_("%d") " )", resp_len);
157 return;
160 PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
163 // Call with block6
164 uint8_t GetNumberBlocksForUserId(uint8_t *src) {
165 int resp_len = 0;
166 uint8_t resp[254] = {0};
167 uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
168 memcpy(c + 5, src, 8);
169 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
171 if (resp_len < 8) {
172 return 0;
175 return resp[8];
178 // Call with block6
179 uint8_t GetPinSize(uint8_t *src) {
180 int resp_len = 0;
181 uint8_t resp[254] = {0};
182 uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
183 memcpy(c + 5, src, 8);
184 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
185 if (resp_len < 2) {
186 return 0;
189 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
190 return resp[8];
192 return 0;
195 int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) {
196 if (blocks == NULL) {
197 return PM3_EINVARG;
200 int resp_len = 0;
201 uint8_t resp[254] = {0};
202 uint8_t c[] = {0x96, CARD_INS_CC, 0x00, 0x00, 17, typ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
203 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
205 if (resp_len < 2) {
206 return PM3_ESOFT;
209 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
210 memcpy(blocks, resp + 1, 16);
211 return PM3_SUCCESS;
213 return PM3_ESOFT;
216 int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out) {
217 if (out == NULL) {
218 return PM3_EINVARG;
221 int resp_len = 0;
222 uint8_t resp[254] = {0};
223 uint8_t c[] = {0x96, CARD_INS_CC_DESC, 0x00, 0x00, 1, typ};
224 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
226 if (resp_len < 2) {
227 return PM3_ESOFT;
230 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
231 memcpy(out, resp + 1, resp_len - 2 - 1);
232 return PM3_SUCCESS;
234 return PM3_ESOFT;
237 int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature) {
238 if (memid == NULL || signature == NULL) {
239 return PM3_EINVARG;
242 int resp_len = 0;
243 uint8_t resp[254] = {0};
244 uint8_t c[5 + 8 + 128] = {0x96, CARD_INS_VERIFY_RRG, 0x00, 0x00, 8 + 128};
246 memcpy(c + 5, memid, 8);
247 memcpy(c + 5 + 8, signature, 128);
249 ExchangeAPDUSC(false, c, sizeof(c), true, false, resp, sizeof(resp), &resp_len);
250 if (resp_len < 2) {
251 return PM3_ESOFT;
254 if (memcmp(resp + resp_len - 4, "\x6f\x6b\x90\x00", 4) == 0) {
255 return PM3_SUCCESS;
257 return PM3_ESOFT;