fix for client crash in lf hitag eload. Hitag simulation still now working (wip)
[RRG-proxmark3.git] / common / cardhelper.c
blobdb62c49f6dd7dfaccfbb4453b58e7cbec9fa79bf
1 //-----------------------------------------------------------------------------
2 // Iceman, February 2020
3 //
4 // This code is licensed to you under the terms of the GNU GPL, version 2 or,
5 // at your option, any later version. See the LICENSE.txt file for the text of
6 // the license.
7 //-----------------------------------------------------------------------------
8 // Support functions for smart card
9 //-----------------------------------------------------------------------------
10 #include "cardhelper.h"
11 #include <string.h>
12 #include <stdio.h>
13 #include "cmdparser.h"
14 #include "cmdsmartcard.h"
15 #include "ui.h"
16 #include "util.h"
18 #define CARD_INS_DECRYPT 0x01
19 #define CARD_INS_ENCRYPT 0x02
20 #define CARD_INS_VEIRFY_RRG 0x05
21 #define CARD_INS_DECODE 0x06
22 #define CARD_INS_NUMBLOCKS 0x07
23 #define CARD_INS_PINSIZE 0x08
24 #define CARD_INS_CC 0x81
25 #define CARD_INS_CC_DESC 0x82
27 // look for CardHelper
28 bool IsCardHelperPresent(bool verbose) {
30 if (IfPm3Smartcard()) {
31 int resp_len = 0;
32 uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
33 uint8_t resp[30] = {0};
34 ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
36 if (resp_len < 8) {
37 return false;
40 if (strstr("CryptoHelper", (char *)resp) == 0) {
41 if (verbose) {
42 PrintAndLogEx(INFO, "Found smart card helper");
44 return true;
47 return false;
50 static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
51 uint8_t cmd[] = {0x96, ins, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
52 memcpy(cmd + 5, src, 8);
54 int resp_len = 0;
55 uint8_t dec[11] = {0};
56 ExchangeAPDUSC(false, cmd, sizeof(cmd), false, true, dec, sizeof(dec), &resp_len);
57 if (resp_len == 10) {
58 memcpy(dest, dec, 8);
59 return true;
61 return false;
64 bool Decrypt(uint8_t *src, uint8_t *dest) {
65 return executeCrypto(CARD_INS_DECRYPT, src, dest);
68 bool Encrypt(uint8_t *src, uint8_t *dest) {
69 return executeCrypto(CARD_INS_ENCRYPT, src, dest);
72 // Call with block6
73 void DecodeBlock6(uint8_t *src) {
74 int resp_len = 0;
75 uint8_t resp[254] = {0};
77 uint8_t c[] = {0x96, CARD_INS_DECODE, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
78 memcpy(c + 6, src, 8);
80 // first part
81 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
84 if (resp_len < 11) {
85 return;
88 PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
90 // second part
91 c[5] = 0x02;
92 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
95 if (resp_len < 11) {
96 return;
98 PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
101 // Call with block6
102 uint8_t GetNumberBlocksForUserId(uint8_t *src) {
103 int resp_len = 0;
104 uint8_t resp[254] = {0};
105 uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
106 memcpy(c + 5, src, 8);
107 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
110 if (resp_len < 8) {
111 return 0;
114 return resp[8];
117 // Call with block6
118 uint8_t GetPinSize(uint8_t *src) {
119 int resp_len = 0;
120 uint8_t resp[254] = {0};
121 uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
122 memcpy(c + 5, src, 8);
123 ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
124 if (resp_len < 2) {
125 return 0;
128 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
129 return resp[8];
131 return 0;
134 int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) {
135 if (blocks == NULL)
136 return PM3_EINVARG;
138 int resp_len = 0;
139 uint8_t resp[254] = {0};
140 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};
141 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
143 if (resp_len < 2) {
144 return PM3_ESOFT;
147 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
148 memcpy(blocks, resp + 1, 16);
149 return PM3_SUCCESS;
151 return PM3_ESOFT;
154 int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out) {
155 if (out == NULL)
156 return PM3_EINVARG;
158 int resp_len = 0;
159 uint8_t resp[254] = {0};
160 uint8_t c[] = {0x96, CARD_INS_CC_DESC, 0x00, 0x00, 1, typ};
161 ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
163 if (resp_len < 2) {
164 return PM3_ESOFT;
167 if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
168 memcpy(out, resp + 1, resp_len - 2 - 1);
169 return PM3_SUCCESS;
171 return PM3_ESOFT;
174 int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature) {
175 if (memid == NULL || signature == NULL)
176 return PM3_EINVARG;
178 int resp_len = 0;
179 uint8_t resp[254] = {0};
180 uint8_t c[5 + 8 + 128] = {0x96, CARD_INS_VEIRFY_RRG, 0x00, 0x00, 8 + 128};
182 memcpy(c + 5, memid, 8);
183 memcpy(c + 5 + 8, signature, 128);
185 ExchangeAPDUSC(false, c, sizeof(c), true, false, resp, sizeof(resp), &resp_len);
186 if (resp_len < 2) {
187 return PM3_ESOFT;
190 if (memcmp(resp + resp_len - 4, "\x6f\x6b\x90\x00", 4) == 0) {
191 return PM3_SUCCESS;
193 return PM3_ESOFT;