1 //-----------------------------------------------------------------------------
2 // Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
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.
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"
22 #include "cmdparser.h" // command_t
23 #include "comms.h" // clearCommandBuffer
25 #include "cliparser.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
32 #include "cmdhf14a.h" // apdu chaining
36 static int CmdHelp(const char *Cmd
);
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
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
];
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
) {
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
) {
84 if ((resplen
< 2) || (sw
!= ISO7816_OK
)) {
85 PrintAndLogEx(ERR
, "Selecting TESLA aid failed (%04x - %s).", sw
, GetAPDUCodeDescription(sw
>> 8, sw
& 0xff));
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
) {
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
) {
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));
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
) {
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
) {
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);
175 // vehicle public key , 16 byte CHALLENGE
176 // 00112233445566778899AABBCCDDEEFF
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
) {
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;
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
) {
210 PrintAndLogEx(NORMAL
, "( card )");
213 PrintAndLogEx(NORMAL
, "( fob )");
216 PrintAndLogEx(NORMAL
, "( phone app )");
219 PrintAndLogEx(NORMAL
, "( unknown )");
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");
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",
249 CLIExecWithReturn(ctx
, Cmd
, argtable
, true);
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
);
271 int CmdHFTESLA(const char *Cmd
) {
272 clearCommandBuffer();
273 return CmdsParse(CommandTable
, Cmd
);