style
[RRG-proxmark3.git] / client / src / cmdhftesla.c
blobe1687a170a83eb81fafdfd31442b2479583bea72
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 // High frequency ISO14443A / TESLA commands
17 //-----------------------------------------------------------------------------
19 #include "cmdhftesla.h"
20 #include <ctype.h>
21 #include <string.h>
22 #include "cmdparser.h" // command_t
23 #include "comms.h" // clearCommandBuffer
24 #include "cmdtrace.h"
25 #include "cliparser.h"
26 #include "cmdhf14a.h"
27 #include "protocols.h" // definitions of ISO14A/7816 protocol
28 #include "iso7816/apduinfo.h" // GetAPDUCodeDescription
29 #include "commonutil.h" // get_sw
30 #include "protocols.h" // ISO7816 APDU return co-des
31 #include "ui.h"
32 #include "cmdhf14a.h" // apdu chaining
34 #define TIMEOUT 2000
36 static int CmdHelp(const char *Cmd);
38 /**
39 * 0x80 0x00 0x00 0x00 - get interface object
40 0x80 0x01 0x00 0x00 - load data from storage
41 0x80 0x02 KEY_INDEX 0x00 - initialize key pair
42 0x80 0x03 KEY_INDEX 0x00 - generate key pair
43 0x80 0x04 KEY_INDEX 0x00 - get public key
44 0x80 0x05 CRT_INDEX 0x00 - load certificate
45 0x80 0x06 CRT_INDEX 0x00 - get certificate
46 0x80 0x07 0x00 0x00 - get version
47 0x80 0x08 0x00 0x00 - confirm prepersonalization
48 0x80 0x10 KEY_INDEX 0x00 - sign challenge
49 0x80 0x11 KEY_INDEX 0x00 - dh key exchange
53 // TESLA
54 static int info_hf_tesla(void) {
56 bool activate_field = true;
57 bool keep_field_on = true;
58 uint8_t response[PM3_CMD_DATA_SIZE];
59 int resplen = 0;
61 // --------------- Select TESLA application ----------------
62 uint8_t aSELECT_AID[80];
63 int aSELECT_AID_n = 0;
64 param_gethex_to_eol("00a404000a7465736c614c6f676963", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
65 int res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
66 if (res != PM3_SUCCESS) {
67 DropField();
68 return PM3_ESOFT;
71 activate_field = false;
72 uint16_t sw = get_sw(response, resplen);
74 if ((resplen < 2) || (sw != ISO7816_OK)) {
76 param_gethex_to_eol("00a404000af465736c614c6f676963", 0, aSELECT_AID, sizeof(aSELECT_AID), &aSELECT_AID_n);
77 res = ExchangeAPDU14a(aSELECT_AID, aSELECT_AID_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
78 if (res != PM3_SUCCESS) {
79 DropField();
80 return res;
84 if ((resplen < 2) || (sw != ISO7816_OK)) {
85 PrintAndLogEx(ERR, "Selecting TESLA aid failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
86 // DropField();
87 // return PM3_ESOFT;
91 keep_field_on = true;
94 // --------------- ECDH public key file reading ----------------
95 uint8_t pk[3][65] = {{0}};
97 for (uint8_t i = 0; i < 3; i++) {
99 uint8_t aSELECT_PK[5] = {0x80, 0x04, i, 0x00, 0x00};
100 res = ExchangeAPDU14a(aSELECT_PK, sizeof(aSELECT_PK), activate_field, keep_field_on, response, sizeof(response), &resplen);
101 if (res != PM3_SUCCESS) {
102 continue;
105 sw = get_sw(response, resplen);
106 if (sw == ISO7816_OK) {
107 memcpy(pk[i], response, resplen - 2);
111 uint8_t aREAD_FORM_FACTOR[30];
112 int aREAD_FORM_FACTOR_n = 0;
113 param_gethex_to_eol("80140000", 0, aREAD_FORM_FACTOR, sizeof(aREAD_FORM_FACTOR), &aREAD_FORM_FACTOR_n);
114 res = ExchangeAPDU14a(aREAD_FORM_FACTOR, aREAD_FORM_FACTOR_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
115 if (res != PM3_SUCCESS) {
116 DropField();
117 return res;
120 sw = get_sw(response, resplen);
121 if (sw != ISO7816_OK) {
122 PrintAndLogEx(ERR, "reading FORM FACTOR file failed (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff));
123 DropField();
124 return PM3_ESOFT;
127 // store form factor for later
128 uint8_t form_factor[resplen - 2];
129 memcpy(form_factor, response, sizeof(form_factor));
131 uint8_t aREAD_VERSION[30];
132 int aREAD_VERSION_n = 0;
133 param_gethex_to_eol("80170000", 0, aREAD_VERSION, sizeof(aREAD_VERSION), &aREAD_VERSION_n);
134 res = ExchangeAPDU14a(aREAD_VERSION, aREAD_VERSION_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
135 if (res != PM3_SUCCESS) {
136 DropField();
137 return res;
140 uint8_t version[resplen - 2];
142 sw = get_sw(response, resplen);
143 if (sw == ISO7816_OK) {
144 // store version for later
145 memcpy(version, response, sizeof(version));
148 // --------------- CERT reading ----------------
149 Set_apdu_in_framing(true);
150 for (uint8_t i = 0; i < 5; i++) {
152 uint8_t aSELECT_CERT[PM3_CMD_DATA_SIZE] = {0x80, 0x06, i, 0x00, 0x00, 0x00, 0xFF};
153 int aSELECT_CERT_n = 7;
155 res = ExchangeAPDU14a(aSELECT_CERT, aSELECT_CERT_n, activate_field, keep_field_on, response, PM3_CMD_DATA_SIZE, &resplen);
156 if (res != PM3_SUCCESS) {
157 continue;
160 sw = get_sw(response, resplen);
162 if (sw == ISO7816_OK) {
163 // save CERT for later
164 uint8_t cert[515] = {0};
165 memcpy(cert, response, resplen - 2);
167 PrintAndLogEx(INFO, "CERT # %i", i);
168 PrintAndLogEx(INFO, "%s", sprint_hex_inrow(cert, resplen - 2));
171 Set_apdu_in_framing(false);
173 uint8_t aAUTH[90];
174 int aAUTH_n = 0;
175 // vehicle public key , 16 byte CHALLENGE
176 // 00112233445566778899AABBCCDDEEFF
177 // 0x51 = 81 dec
178 // param_gethex_to_eol("8011000051 046F08AE62526ABB5690643458152AC963CF5D7C113949F3C2453D1DDC6E4385B430523524045A22F5747BF236F1B5F60F0EA32DC2B8276D75ACDE9813EF77C330 00112233445566778899AABBCCDDEEFF", 0, aAUTH, sizeof(aAUTH), &aAUTH_n);
179 param_gethex_to_eol("8011000051046F08AE62526ABB5690643458152AC963CF5D7C113949F3C2453D1DDC6E4385B430523524045A22F5747BF236F1B5F60F0EA32DC2B8276D75ACDE9813EF77C33000112233445566778899AABBCCDDEEFF", 0, aAUTH, sizeof(aAUTH), &aAUTH_n);
180 res = ExchangeAPDU14a(aAUTH, aAUTH_n, activate_field, keep_field_on, response, sizeof(response), &resplen);
181 if (res != PM3_SUCCESS) {
182 DropField();
183 return res;
186 uint8_t auth[resplen - 2];
188 sw = get_sw(response, resplen);
189 if (sw == ISO7816_OK) {
190 // store CHALLENGE for later
191 memcpy(auth, response, sizeof(auth));
194 keep_field_on = false;
195 DropField();
197 PrintAndLogEx(NORMAL, "");
198 PrintAndLogEx(INFO, "--- " _CYAN_("Tag Information") " ---------------------------");
199 PrintAndLogEx(NORMAL, "");
200 PrintAndLogEx(INFO, "PUBLIC KEY");
201 for (int i = 0; i < 3; i++) {
202 PrintAndLogEx(INFO, "%d - %s", i, sprint_hex_inrow(pk[i], 65));
204 PrintAndLogEx(INFO, "Form factor... %s " NOLF, sprint_hex_inrow(form_factor, sizeof(form_factor)));
206 uint16_t form_factor_value = MemBeToUint2byte(form_factor);
208 switch (form_factor_value) {
209 case 0x0001:
210 PrintAndLogEx(NORMAL, "( card )");
211 break;
212 case 0x0022:
213 PrintAndLogEx(NORMAL, "( fob )");
214 break;
215 case 0x0031:
216 PrintAndLogEx(NORMAL, "( phone app )");
217 break;
218 default:
219 PrintAndLogEx(NORMAL, "( unknown )");
220 break;
223 if (sizeof(version) > 0) {
224 PrintAndLogEx(INFO, "Version....... %s", sprint_hex_inrow(version, sizeof(version)));
227 PrintAndLogEx(INFO, "CHALL......... %s", sprint_hex_inrow(auth, sizeof(auth)));
229 PrintAndLogEx(INFO, "Fingerprint");
230 if ((memcmp(pk[0], pk[1], 65) == 0)) {
231 PrintAndLogEx(INFO, " GaussKey detected");
234 return PM3_SUCCESS;
237 // menu command to get and print all info known about any known ST25TA tag
238 static int CmdHFTeslaInfo(const char *Cmd) {
239 CLIParserContext *ctx;
240 CLIParserInit(&ctx, "hf telsa info",
241 "Get info about TESLA Key tag",
242 "hf tesla info"
245 void *argtable[] = {
246 arg_param_begin,
247 arg_param_end
249 CLIExecWithReturn(ctx, Cmd, argtable, true);
250 CLIParserFree(ctx);
251 return info_hf_tesla();
254 static int CmdHFTeslaList(const char *Cmd) {
255 return CmdTraceListAlias(Cmd, "hf tesla", "7816");
258 static command_t CommandTable[] = {
259 {"help", CmdHelp, AlwaysAvailable, "This help"},
260 {"info", CmdHFTeslaInfo, IfPm3Iso14443a, "Tag information"},
261 {"list", CmdHFTeslaList, AlwaysAvailable, "List ISO 14443A/7816 history"},
262 {NULL, NULL, NULL, NULL}
265 static int CmdHelp(const char *Cmd) {
266 (void)Cmd; // Cmd is not used so far
267 CmdsHelp(CommandTable);
268 return PM3_SUCCESS;
271 int CmdHFTESLA(const char *Cmd) {
272 clearCommandBuffer();
273 return CmdsParse(CommandTable, Cmd);