2020-02-27 23:35:17 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
2022-01-07 08:58:03 +08:00
|
|
|
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
2020-02-27 23:35:17 +08:00
|
|
|
//
|
2022-01-07 08:58:03 +08:00
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
// GNU General Public License for more details.
|
|
|
|
//
|
|
|
|
// See LICENSE.txt for the text of the license.
|
2020-02-27 23:35:17 +08:00
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Support functions for smart card
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
#include "cardhelper.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include "cmdparser.h"
|
|
|
|
#include "cmdsmartcard.h"
|
|
|
|
#include "ui.h"
|
|
|
|
#include "util.h"
|
|
|
|
|
2020-03-12 04:00:19 +08:00
|
|
|
#define CARD_INS_DECRYPT 0x01
|
|
|
|
#define CARD_INS_ENCRYPT 0x02
|
2022-01-07 03:14:58 +08:00
|
|
|
#define CARD_INS_VERIFY_RRG 0x05
|
2020-03-12 04:00:19 +08:00
|
|
|
#define CARD_INS_DECODE 0x06
|
|
|
|
#define CARD_INS_NUMBLOCKS 0x07
|
2020-07-20 02:45:47 +08:00
|
|
|
#define CARD_INS_PINSIZE 0x08
|
2021-04-04 23:01:43 +08:00
|
|
|
#define CARD_INS_CC 0x81
|
|
|
|
#define CARD_INS_CC_DESC 0x82
|
2020-02-27 23:35:17 +08:00
|
|
|
|
2021-04-04 23:01:43 +08:00
|
|
|
// look for CardHelper
|
|
|
|
bool IsCardHelperPresent(bool verbose) {
|
2020-02-27 23:35:17 +08:00
|
|
|
|
|
|
|
if (IfPm3Smartcard()) {
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t version[] = {0x96, 0x69, 0x00, 0x00, 0x00};
|
2021-04-08 15:34:11 +08:00
|
|
|
uint8_t resp[30] = {0};
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(verbose, version, sizeof(version), true, true, resp, sizeof(resp), &resp_len);
|
|
|
|
|
|
|
|
if (resp_len < 8) {
|
|
|
|
return false;
|
|
|
|
}
|
2020-02-27 23:35:17 +08:00
|
|
|
|
2020-03-10 00:09:41 +08:00
|
|
|
if (strstr("CryptoHelper", (char *)resp) == 0) {
|
2020-07-14 02:58:24 +08:00
|
|
|
if (verbose) {
|
|
|
|
PrintAndLogEx(INFO, "Found smart card helper");
|
|
|
|
}
|
2020-02-27 23:35:17 +08:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2020-07-14 02:58:24 +08:00
|
|
|
return false;
|
2020-02-27 23:35:17 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool executeCrypto(uint8_t ins, uint8_t *src, uint8_t *dest) {
|
2021-04-08 15:34:11 +08:00
|
|
|
uint8_t cmd[] = {0x96, ins, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
2020-02-27 23:35:17 +08:00
|
|
|
memcpy(cmd + 5, src, 8);
|
|
|
|
|
2021-04-08 15:34:11 +08:00
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t dec[11] = {0};
|
2022-01-04 05:09:42 +08:00
|
|
|
ExchangeAPDUSC(false, cmd, sizeof(cmd), true, true, dec, sizeof(dec), &resp_len);
|
2020-02-27 23:35:17 +08:00
|
|
|
if (resp_len == 10) {
|
|
|
|
memcpy(dest, dec, 8);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:09:41 +08:00
|
|
|
bool Decrypt(uint8_t *src, uint8_t *dest) {
|
2020-02-27 23:35:17 +08:00
|
|
|
return executeCrypto(CARD_INS_DECRYPT, src, dest);
|
|
|
|
}
|
|
|
|
|
2020-03-10 00:09:41 +08:00
|
|
|
bool Encrypt(uint8_t *src, uint8_t *dest) {
|
2020-02-27 23:35:17 +08:00
|
|
|
return executeCrypto(CARD_INS_ENCRYPT, src, dest);
|
|
|
|
}
|
|
|
|
|
2020-03-12 04:00:19 +08:00
|
|
|
// Call with block6
|
2020-02-27 23:35:17 +08:00
|
|
|
void DecodeBlock6(uint8_t *src) {
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
|
|
|
|
|
|
|
uint8_t c[] = {0x96, CARD_INS_DECODE, 0x00, 0x00, 0x09, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
memcpy(c + 6, src, 8);
|
|
|
|
|
|
|
|
// first part
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
|
|
|
|
|
|
|
|
|
|
|
if (resp_len < 11) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2020-03-01 23:46:31 +08:00
|
|
|
PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
|
2020-02-27 23:35:17 +08:00
|
|
|
|
|
|
|
// second part
|
|
|
|
c[5] = 0x02;
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
|
|
|
|
|
2021-04-08 16:44:31 +08:00
|
|
|
|
2021-04-04 23:01:43 +08:00
|
|
|
if (resp_len < 11) {
|
|
|
|
return;
|
|
|
|
}
|
2020-03-01 23:46:31 +08:00
|
|
|
PrintAndLogEx(SUCCESS, "%.*s", resp_len - 11, resp + 9);
|
2020-02-27 23:35:17 +08:00
|
|
|
}
|
|
|
|
|
2020-03-12 04:00:19 +08:00
|
|
|
// Call with block6
|
|
|
|
uint8_t GetNumberBlocksForUserId(uint8_t *src) {
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
|
|
|
uint8_t c[] = {0x96, CARD_INS_NUMBLOCKS, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
memcpy(c + 5, src, 8);
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
|
|
|
|
|
|
|
|
|
|
|
|
if (resp_len < 8) {
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-03-12 04:00:19 +08:00
|
|
|
return resp[8];
|
2020-04-16 15:01:14 +08:00
|
|
|
}
|
2020-07-20 02:45:47 +08:00
|
|
|
|
|
|
|
// Call with block6
|
|
|
|
uint8_t GetPinSize(uint8_t *src) {
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
|
|
|
uint8_t c[] = {0x96, CARD_INS_PINSIZE, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
|
|
|
|
memcpy(c + 5, src, 8);
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, false, resp, sizeof(resp), &resp_len);
|
|
|
|
if (resp_len < 2) {
|
|
|
|
return 0;
|
|
|
|
}
|
2020-08-13 18:25:04 +08:00
|
|
|
|
|
|
|
if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
|
2020-07-20 05:08:53 +08:00
|
|
|
return resp[8];
|
|
|
|
}
|
|
|
|
return 0;
|
2020-07-20 02:45:47 +08:00
|
|
|
}
|
2021-04-04 23:01:43 +08:00
|
|
|
|
|
|
|
int GetConfigCardByIdx(uint8_t typ, uint8_t *blocks) {
|
|
|
|
if (blocks == NULL)
|
|
|
|
return PM3_EINVARG;
|
|
|
|
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
2021-04-08 16:44:31 +08:00
|
|
|
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};
|
2021-04-04 23:01:43 +08:00
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
|
|
|
|
|
|
|
if (resp_len < 2) {
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
|
|
|
|
memcpy(blocks, resp + 1, 16);
|
|
|
|
return PM3_SUCCESS;
|
|
|
|
}
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
int GetConfigCardStrByIdx(uint8_t typ, uint8_t *out) {
|
|
|
|
if (out == NULL)
|
|
|
|
return PM3_EINVARG;
|
|
|
|
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
|
|
|
uint8_t c[] = {0x96, CARD_INS_CC_DESC, 0x00, 0x00, 1, typ};
|
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), false, true, resp, sizeof(resp), &resp_len);
|
|
|
|
|
|
|
|
if (resp_len < 2) {
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (resp[resp_len - 2] == 0x90 && resp[resp_len - 1] == 0x00) {
|
|
|
|
memcpy(out, resp + 1, resp_len - 2 - 1);
|
|
|
|
return PM3_SUCCESS;
|
|
|
|
}
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
int VerifyRdv4Signature(uint8_t *memid, uint8_t *signature) {
|
|
|
|
if (memid == NULL || signature == NULL)
|
|
|
|
return PM3_EINVARG;
|
|
|
|
|
|
|
|
int resp_len = 0;
|
|
|
|
uint8_t resp[254] = {0};
|
2022-01-07 03:14:58 +08:00
|
|
|
uint8_t c[5 + 8 + 128] = {0x96, CARD_INS_VERIFY_RRG, 0x00, 0x00, 8 + 128};
|
2021-04-04 23:01:43 +08:00
|
|
|
|
|
|
|
memcpy(c + 5, memid, 8);
|
|
|
|
memcpy(c + 5 + 8, signature, 128);
|
|
|
|
|
|
|
|
ExchangeAPDUSC(false, c, sizeof(c), true, false, resp, sizeof(resp), &resp_len);
|
|
|
|
if (resp_len < 2) {
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(resp + resp_len - 4, "\x6f\x6b\x90\x00", 4) == 0) {
|
|
|
|
return PM3_SUCCESS;
|
|
|
|
}
|
|
|
|
return PM3_ESOFT;
|
|
|
|
}
|