mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 13:53:55 -07:00
hf felica liteauth: add external authentication
This commit is contained in:
parent
a0df90af18
commit
30689f7d3c
1 changed files with 274 additions and 97 deletions
|
@ -33,9 +33,16 @@
|
||||||
#include "cliparser.h" // cliparser
|
#include "cliparser.h" // cliparser
|
||||||
#include "util_posix.h" // msleep
|
#include "util_posix.h" // msleep
|
||||||
|
|
||||||
|
|
||||||
#define FELICA_BLK_SIZE 16
|
#define FELICA_BLK_SIZE 16
|
||||||
#define FELICA_BLK_HALF (FELICA_BLK_SIZE/2)
|
#define FELICA_BLK_HALF (FELICA_BLK_SIZE/2)
|
||||||
|
|
||||||
|
#define FELICA_BLK_NUMBER_RC 0x80
|
||||||
|
#define FELICA_BLK_NUMBER_ID 0x82
|
||||||
|
#define FELICA_BLK_NUMBER_WCNT 0x90
|
||||||
|
#define FELICA_BLK_NUMBER_MACA 0x91
|
||||||
|
#define FELICA_BLK_NUMBER_STATE 0x92
|
||||||
|
|
||||||
#define FELICA_SERVICE_ATTRIBUTE_UNAUTH_READ (0b000001)
|
#define FELICA_SERVICE_ATTRIBUTE_UNAUTH_READ (0b000001)
|
||||||
#define FELICA_SERVICE_ATTRIBUTE_READ_ONLY (0b000010)
|
#define FELICA_SERVICE_ATTRIBUTE_READ_ONLY (0b000010)
|
||||||
#define FELICA_SERVICE_ATTRIBUTE_RANDOM_ACCESS (0b001000)
|
#define FELICA_SERVICE_ATTRIBUTE_RANDOM_ACCESS (0b001000)
|
||||||
|
@ -2289,7 +2296,7 @@ static uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t trac
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x90: {
|
case 0x90: {
|
||||||
PrintAndLogEx(NORMAL, "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]);
|
PrintAndLogEx(NORMAL, "Write counter, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 0x91: {
|
case 0x91: {
|
||||||
|
@ -2545,7 +2552,32 @@ static int parse_multiple_block_data(const uint8_t *data, const size_t datalen,
|
||||||
|
|
||||||
memcpy(out, data + res_size, num * FELICA_BLK_SIZE);
|
memcpy(out, data + res_size, num * FELICA_BLK_SIZE);
|
||||||
|
|
||||||
|
if (outlen) {
|
||||||
*outlen = num * FELICA_BLK_SIZE;
|
*outlen = num * FELICA_BLK_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_rd_multiple_plain(uint8_t flags, uint16_t datalen, uint8_t *data, uint8_t *out) {
|
||||||
|
clear_and_send_command(flags, datalen, data, false);
|
||||||
|
PacketResponseNG res;
|
||||||
|
if (waitCmdFelica(false, &res, false) == false) {
|
||||||
|
PrintAndLogEx(ERR, "\nGot no response from card");
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t block_data[FELICA_BLK_SIZE*4];
|
||||||
|
memset(block_data, 0, sizeof(block_data));
|
||||||
|
|
||||||
|
uint8_t outlen = 0;
|
||||||
|
|
||||||
|
int ret = parse_multiple_block_data(res.data.asBytes, sizeof(res.data.asBytes), block_data, &outlen);
|
||||||
|
if (ret) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(out, block_data, outlen);
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -2598,12 +2630,22 @@ cleanup:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void felica_auth_context_free(felica_auth_context_t *auth_ctx) {
|
||||||
|
if (!auth_ctx) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mbedtls_platform_zeroize(auth_ctx->session_key, sizeof(auth_ctx->session_key));
|
||||||
|
mbedtls_platform_zeroize(auth_ctx->random_challenge, sizeof(auth_ctx->random_challenge));
|
||||||
|
}
|
||||||
|
|
||||||
static int felica_generate_mac(
|
static int felica_generate_mac(
|
||||||
mbedtls_des3_context *ctx,
|
mbedtls_des3_context *ctx,
|
||||||
const felica_auth_context_t *auth_ctx,
|
const felica_auth_context_t *auth_ctx,
|
||||||
const uint8_t *initialize_block,
|
const uint8_t *initialize_block,
|
||||||
const uint8_t *block_data,
|
const uint8_t *block_data,
|
||||||
const size_t length,
|
const size_t length,
|
||||||
|
bool use_read_key,
|
||||||
uint8_t *mac) {
|
uint8_t *mac) {
|
||||||
|
|
||||||
int ret = PM3_SUCCESS;
|
int ret = PM3_SUCCESS;
|
||||||
|
@ -2619,7 +2661,16 @@ static int felica_generate_mac(
|
||||||
return PM3_EINVARG;
|
return PM3_EINVARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
SwapEndian64ex(auth_ctx->session_key, sizeof(auth_ctx->session_key), 8, rev_sk);
|
uint8_t sk[FELICA_BLK_SIZE];
|
||||||
|
|
||||||
|
if (use_read_key == false) {
|
||||||
|
memcpy(sk, auth_ctx->session_key + 8, 8);
|
||||||
|
memcpy(sk + 8, auth_ctx->session_key, 8);
|
||||||
|
} else {
|
||||||
|
memcpy(sk, auth_ctx->session_key, sizeof(auth_ctx->session_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
SwapEndian64ex(sk, sizeof(sk), 8, rev_sk);
|
||||||
|
|
||||||
memcpy(iv, auth_ctx->random_challenge, sizeof(iv));
|
memcpy(iv, auth_ctx->random_challenge, sizeof(iv));
|
||||||
|
|
||||||
|
@ -2642,6 +2693,7 @@ static int felica_generate_mac(
|
||||||
SwapEndian64ex(out, FELICA_BLK_HALF, 8, mac);
|
SwapEndian64ex(out, FELICA_BLK_HALF, 8, mac);
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
|
mbedtls_platform_zeroize(sk, sizeof(sk));
|
||||||
mbedtls_platform_zeroize(rev_sk, sizeof(rev_sk));
|
mbedtls_platform_zeroize(rev_sk, sizeof(rev_sk));
|
||||||
mbedtls_platform_zeroize(iv, sizeof(iv));
|
mbedtls_platform_zeroize(iv, sizeof(iv));
|
||||||
mbedtls_platform_zeroize(out, sizeof(out));
|
mbedtls_platform_zeroize(out, sizeof(out));
|
||||||
|
@ -2650,79 +2702,58 @@ cleanup:
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
static int write_with_mac(
|
||||||
* Command parser for liteauth.
|
mbedtls_des3_context *ctx,
|
||||||
* @param Cmd input data of the user.
|
const felica_auth_context_t *auth_ctx,
|
||||||
* @return client result code.
|
const uint8_t *counter,
|
||||||
*/
|
const uint8_t blk_number,
|
||||||
static int CmdHFFelicaAuthenticationLite(const char *Cmd) {
|
const uint8_t *block_data,
|
||||||
CLIParserContext *ctx;
|
uint8_t *out) {
|
||||||
CLIParserInit(&ctx, "hf felica liteauth",
|
|
||||||
"Authenticate",
|
|
||||||
"hf felica liteauth -i 11100910C11BC407\n"
|
|
||||||
"hf felica liteauth -k 46656c69436130313233343536616263\n"
|
|
||||||
"hf felica liteauth -c 701185c59f8d30afeab8e4b3a61f5cc4 -k 46656c69436130313233343536616263"
|
|
||||||
);
|
|
||||||
void *argtable[] = {
|
|
||||||
arg_param_begin,
|
|
||||||
arg_str0("k", "key", "<hex>", "set card key, 16 bytes"),
|
|
||||||
arg_str0("c", "", "<hex>", "set random challenge, 16 bytes"),
|
|
||||||
arg_str0("i", "", "<hex>", "set custom IDm"),
|
|
||||||
arg_param_end
|
|
||||||
};
|
|
||||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
|
||||||
|
|
||||||
uint8_t key[FELICA_BLK_SIZE];
|
uint8_t initialize_blk[FELICA_BLK_HALF];
|
||||||
memset(key, 0, sizeof(key));
|
memset(initialize_blk, 0, sizeof(initialize_blk));
|
||||||
int keylen = 0;
|
|
||||||
int ret = CLIParamHexToBuf(arg_get_str(ctx, 1), key, sizeof(key), &keylen);
|
uint8_t wcnt[3];
|
||||||
if (ret) {
|
memcpy(wcnt, counter, 3);
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
memcpy(initialize_blk, wcnt, sizeof(wcnt));
|
||||||
|
initialize_blk[4] = blk_number;
|
||||||
|
initialize_blk[6] = 0x91;
|
||||||
|
|
||||||
|
uint8_t mac[FELICA_BLK_HALF];
|
||||||
|
|
||||||
|
int ret = felica_generate_mac(ctx, auth_ctx, initialize_blk, block_data, FELICA_BLK_SIZE, false, mac);
|
||||||
|
if (ret != PM3_SUCCESS) {
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t rc[FELICA_BLK_SIZE];
|
uint8_t payload[FELICA_BLK_SIZE*2];
|
||||||
memset(rc, 0, sizeof(rc));
|
memset(payload, 0, sizeof(payload));
|
||||||
int rclen = 0;
|
|
||||||
ret = CLIParamHexToBuf(arg_get_str(ctx, 2), rc, sizeof(rc), &rclen);
|
|
||||||
if (ret) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t idm[8];
|
memcpy(payload, block_data, FELICA_BLK_SIZE);
|
||||||
memset(idm, 0, sizeof(idm));
|
memcpy(payload + FELICA_BLK_SIZE, mac, sizeof(mac));
|
||||||
int ilen = 0;
|
memcpy(payload + FELICA_BLK_SIZE + sizeof(mac), wcnt, sizeof(wcnt));
|
||||||
ret = CLIParamHexToBuf(arg_get_str(ctx, 3), idm, sizeof(idm), &ilen);
|
|
||||||
if (ret) {
|
|
||||||
CLIParserFree(ctx);
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
|
|
||||||
CLIParserFree(ctx);
|
memcpy(out, payload, sizeof(payload));
|
||||||
|
|
||||||
if (!ilen) {
|
return PM3_SUCCESS;
|
||||||
if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) {
|
}
|
||||||
memcpy(idm, last_known_card.IDm, sizeof(idm));
|
|
||||||
} else {
|
|
||||||
PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm");
|
|
||||||
return PM3_EINVARG;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Card Key: %s", sprint_hex(key, sizeof(key)));
|
static int felica_internal_authentication(
|
||||||
PrintAndLogEx(INFO, "Random Challenge(RC): %s", sprint_hex(rc, sizeof(rc)));
|
const uint8_t *idm,
|
||||||
|
const uint8_t* rc,
|
||||||
PrintAndLogEx(SUCCESS, "FeliCa lite - auth started");
|
const size_t rclen,
|
||||||
|
mbedtls_des3_context *ctx,
|
||||||
|
const felica_auth_context_t *auth_ctx) {
|
||||||
|
|
||||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
|
|
||||||
uint8_t blk_numbers[1] = {0x80}; // RC
|
uint8_t blk_numbers[1] = {FELICA_BLK_NUMBER_RC};
|
||||||
|
|
||||||
uint16_t datalen = 0;
|
uint16_t datalen = 0;
|
||||||
|
|
||||||
ret = write_without_encryption(idm, (uint8_t)sizeof(blk_numbers), blk_numbers, rc, sizeof(rc), data, &datalen);
|
int ret = write_without_encryption(idm, (uint8_t)sizeof(blk_numbers), blk_numbers, rc, rclen, data, &datalen);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
@ -2732,28 +2763,16 @@ static int CmdHFFelicaAuthenticationLite(const char *Cmd) {
|
||||||
|
|
||||||
uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW | FELICA_NO_DISCONNECT);
|
uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW | FELICA_NO_DISCONNECT);
|
||||||
|
|
||||||
felica_status_response_t sres;
|
felica_status_response_t res;
|
||||||
if (send_wr_plain(flags, datalen, data, false, &sres) != PM3_SUCCESS) {
|
if (send_wr_plain(flags, datalen, data, false, &res) != PM3_SUCCESS) {
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sres.status_flags.status_flag1[0] != 0x00 && sres.status_flags.status_flag2[0] != 0x00) {
|
if (res.status_flags.status_flag1[0] != 0x00 && res.status_flags.status_flag2[0] != 0x00) {
|
||||||
PrintAndLogEx(ERR, "\nError RC Write");
|
PrintAndLogEx(ERR, "\nError RC Write");
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
|
||||||
mbedtls_des3_context des3_ctx;
|
|
||||||
mbedtls_des3_init(&des3_ctx);
|
|
||||||
|
|
||||||
felica_auth_context_t auth_ctx;
|
|
||||||
|
|
||||||
ret = felica_auth_context_init(&des3_ctx, rc, sizeof(rc), key, sizeof(key), &auth_ctx);
|
|
||||||
if (ret) {
|
|
||||||
return PM3_ERFTRANS;
|
|
||||||
}
|
|
||||||
|
|
||||||
PrintAndLogEx(INFO, "Session Key(SK): %s", sprint_hex(auth_ctx.session_key, sizeof(auth_ctx.session_key)));
|
|
||||||
|
|
||||||
memset(data, 0, sizeof(data));
|
memset(data, 0, sizeof(data));
|
||||||
|
|
||||||
uint8_t blk_numbers2[2] = {0x82, 0x91};
|
uint8_t blk_numbers2[2] = {0x82, 0x91};
|
||||||
|
@ -2766,20 +2785,10 @@ static int CmdHFFelicaAuthenticationLite(const char *Cmd) {
|
||||||
AddCrc(data, datalen);
|
AddCrc(data, datalen);
|
||||||
datalen += 2;
|
datalen += 2;
|
||||||
|
|
||||||
flags &= ~FELICA_NO_DISCONNECT;
|
uint8_t pd[FELICA_BLK_SIZE*sizeof(blk_numbers2)];
|
||||||
|
|
||||||
clear_and_send_command(flags, datalen, data, false);
|
|
||||||
PacketResponseNG pres;
|
|
||||||
if (waitCmdFelica(false, &pres, false) == false) {
|
|
||||||
PrintAndLogEx(ERR, "\nGot no response from card");
|
|
||||||
return PM3_ERFTRANS;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t pd[64];
|
|
||||||
memset(pd, 0, sizeof(pd));
|
memset(pd, 0, sizeof(pd));
|
||||||
|
|
||||||
uint8_t pd_size = 0;
|
ret = send_rd_multiple_plain(flags, datalen, data, pd);
|
||||||
ret = parse_multiple_block_data(pres.data.asBytes, sizeof(pres.data.asBytes), pd, &pd_size);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
@ -2793,32 +2802,200 @@ static int CmdHFFelicaAuthenticationLite(const char *Cmd) {
|
||||||
uint8_t initialize_blk[8];
|
uint8_t initialize_blk[8];
|
||||||
memset(initialize_blk, 0xFF, sizeof(initialize_blk));
|
memset(initialize_blk, 0xFF, sizeof(initialize_blk));
|
||||||
|
|
||||||
initialize_blk[0] = 0x82; // ID
|
initialize_blk[0] = FELICA_BLK_NUMBER_ID;
|
||||||
initialize_blk[1] = 0x00;
|
initialize_blk[1] = 0x00;
|
||||||
initialize_blk[2] = 0x91; // MAC_A
|
initialize_blk[2] = FELICA_BLK_NUMBER_MACA;
|
||||||
initialize_blk[3] = 0x00;
|
initialize_blk[3] = 0x00;
|
||||||
|
|
||||||
uint8_t mac[FELICA_BLK_HALF];
|
uint8_t mac[FELICA_BLK_HALF];
|
||||||
|
|
||||||
ret = felica_generate_mac(&des3_ctx, &auth_ctx, initialize_blk, id_blk, sizeof(id_blk), mac);
|
ret = felica_generate_mac(ctx, auth_ctx, initialize_blk, id_blk, sizeof(id_blk), true, mac);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "MAC_A: %s", sprint_hex(mac, sizeof(mac)));
|
PrintAndLogEx(SUCCESS, "MAC_A: %s", sprint_hex(mac, sizeof(mac)));
|
||||||
|
|
||||||
mbedtls_des3_free(&des3_ctx);
|
|
||||||
|
|
||||||
if (memcmp(mac_blk, mac, FELICA_BLK_HALF) != 0) {
|
if (memcmp(mac_blk, mac, FELICA_BLK_HALF) != 0) {
|
||||||
PrintAndLogEx(ERR, "\nAuthenticate Failed");
|
PrintAndLogEx(ERR, "\nInternal Authenticate: " _RED_("Failed"));
|
||||||
return PM3_ERFTRANS;
|
return PM3_ERFTRANS;
|
||||||
}
|
}
|
||||||
|
|
||||||
PrintAndLogEx(SUCCESS, "Authenticate Success");
|
PrintAndLogEx(SUCCESS, "Internal Authenticate: " _GREEN_("OK"));
|
||||||
|
|
||||||
return PM3_SUCCESS;
|
return PM3_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int felica_external_authentication(
|
||||||
|
const uint8_t *idm,
|
||||||
|
mbedtls_des3_context *ctx,
|
||||||
|
const felica_auth_context_t *auth_ctx,
|
||||||
|
bool keep) {
|
||||||
|
|
||||||
|
uint8_t data[PM3_CMD_DATA_SIZE_MIX];
|
||||||
|
memset(data, 0, sizeof(data));
|
||||||
|
|
||||||
|
uint8_t flags = (FELICA_APPEND_CRC | FELICA_RAW | FELICA_NO_DISCONNECT);
|
||||||
|
|
||||||
|
uint16_t datalen = 0;
|
||||||
|
|
||||||
|
uint8_t blk_numbers[1] = {FELICA_BLK_NUMBER_WCNT};
|
||||||
|
|
||||||
|
int ret = read_without_encryption(idm, (uint8_t)sizeof(blk_numbers), blk_numbers, data, &datalen);
|
||||||
|
if (ret) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
|
||||||
|
uint8_t wcnt_blk[FELICA_BLK_SIZE];
|
||||||
|
ret = send_rd_multiple_plain(flags, datalen, data, wcnt_blk);
|
||||||
|
if (ret) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t ext_auth[FELICA_BLK_SIZE];
|
||||||
|
memset(ext_auth, 0, sizeof(ext_auth));
|
||||||
|
|
||||||
|
ext_auth[0] = 1; // After Authenticate
|
||||||
|
|
||||||
|
uint8_t mac_w[FELICA_BLK_SIZE*2];
|
||||||
|
|
||||||
|
ret = write_with_mac(ctx, auth_ctx, wcnt_blk, FELICA_BLK_NUMBER_STATE, ext_auth, mac_w);
|
||||||
|
if (ret) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t blk_numbers2[2] = {FELICA_BLK_NUMBER_STATE, FELICA_BLK_NUMBER_MACA};
|
||||||
|
|
||||||
|
ret = write_without_encryption(idm, (uint8_t)sizeof(blk_numbers2), blk_numbers2, mac_w, sizeof(mac_w), data, &datalen);
|
||||||
|
if (ret) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
AddCrc(data, datalen);
|
||||||
|
datalen += 2;
|
||||||
|
|
||||||
|
if (keep == false) {
|
||||||
|
flags &= ~FELICA_NO_DISCONNECT;
|
||||||
|
}
|
||||||
|
|
||||||
|
felica_status_response_t res;
|
||||||
|
if (send_wr_plain(flags, datalen, data, false, &res) != PM3_SUCCESS) {
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (res.status_flags.status_flag1[0] != 0x00 && res.status_flags.status_flag2[0] != 0x00) {
|
||||||
|
PrintAndLogEx(ERR, "\nExternal Authenticate: " _RED_("Failed"));
|
||||||
|
return PM3_ERFTRANS;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "External Authenticate: " _GREEN_("OK"));
|
||||||
|
|
||||||
|
return PM3_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Command parser for liteauth.
|
||||||
|
* @param Cmd input data of the user.
|
||||||
|
* @return client result code.
|
||||||
|
*/
|
||||||
|
static int CmdHFFelicaAuthenticationLite(const char *Cmd) {
|
||||||
|
CLIParserContext *ctx;
|
||||||
|
CLIParserInit(&ctx, "hf felica liteauth",
|
||||||
|
"Authenticate",
|
||||||
|
"hf felica liteauth -i 11100910C11BC407\n"
|
||||||
|
"hf felica liteauth -k 46656c69436130313233343536616263\n"
|
||||||
|
"hf felica liteauth -k 46656c69436130313233343536616263 -@\n"
|
||||||
|
"hf felica liteauth -c 701185c59f8d30afeab8e4b3a61f5cc4 -k 46656c69436130313233343536616263"
|
||||||
|
);
|
||||||
|
void *argtable[] = {
|
||||||
|
arg_param_begin,
|
||||||
|
arg_str0("k", "key", "<hex>", "set card key, 16 bytes"),
|
||||||
|
arg_str0("c", "", "<hex>", "set random challenge, 16 bytes"),
|
||||||
|
arg_str0("i", "", "<hex>", "set custom IDm"),
|
||||||
|
arg_lit0("@", "", "keep signal field ON after receive"),
|
||||||
|
arg_param_end
|
||||||
|
};
|
||||||
|
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||||
|
|
||||||
|
uint8_t key[FELICA_BLK_SIZE];
|
||||||
|
memset(key, 0, sizeof(key));
|
||||||
|
int keylen = 0;
|
||||||
|
int res = CLIParamHexToBuf(arg_get_str(ctx, 1), key, sizeof(key), &keylen);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t rc[FELICA_BLK_SIZE];
|
||||||
|
memset(rc, 0, sizeof(rc));
|
||||||
|
int rclen = 0;
|
||||||
|
res = CLIParamHexToBuf(arg_get_str(ctx, 2), rc, sizeof(rc), &rclen);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t idm[8];
|
||||||
|
memset(idm, 0, sizeof(idm));
|
||||||
|
int ilen = 0;
|
||||||
|
res = CLIParamHexToBuf(arg_get_str(ctx, 3), idm, sizeof(idm), &ilen);
|
||||||
|
if (res) {
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keep_field_on = arg_get_lit(ctx, 4);
|
||||||
|
|
||||||
|
CLIParserFree(ctx);
|
||||||
|
|
||||||
|
if (!ilen) {
|
||||||
|
if (last_known_card.IDm[0] != 0 && last_known_card.IDm[1] != 0) {
|
||||||
|
memcpy(idm, last_known_card.IDm, sizeof(idm));
|
||||||
|
} else {
|
||||||
|
PrintAndLogEx(WARNING, "No last known card! Use `" _YELLOW_("hf felica reader") "` first or set a custom IDm");
|
||||||
|
return PM3_EINVARG;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret = PM3_SUCCESS;
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Card Key: %s", sprint_hex(key, sizeof(key)));
|
||||||
|
PrintAndLogEx(INFO, "Random Challenge(RC): %s", sprint_hex(rc, sizeof(rc)));
|
||||||
|
|
||||||
|
PrintAndLogEx(SUCCESS, "FeliCa lite - auth started");
|
||||||
|
|
||||||
|
mbedtls_des3_context des3_ctx;
|
||||||
|
mbedtls_des3_init(&des3_ctx);
|
||||||
|
|
||||||
|
felica_auth_context_t auth_ctx;
|
||||||
|
|
||||||
|
ret = felica_auth_context_init(&des3_ctx, rc, sizeof(rc), key, sizeof(key), &auth_ctx);
|
||||||
|
if (ret) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
PrintAndLogEx(INFO, "Session Key(SK): %s", sprint_hex(auth_ctx.session_key, sizeof(auth_ctx.session_key)));
|
||||||
|
|
||||||
|
ret = felica_internal_authentication(idm, rc, sizeof(rc), &des3_ctx, &auth_ctx);
|
||||||
|
if (ret) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = felica_external_authentication(idm, &des3_ctx, &auth_ctx, keep_field_on);
|
||||||
|
if (ret) {
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
mbedtls_des3_free(&des3_ctx);
|
||||||
|
felica_auth_context_free(&auth_ctx);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
static int CmdHFFelicaCmdRaw(const char *Cmd) {
|
||||||
|
|
||||||
CLIParserContext *ctx;
|
CLIParserContext *ctx;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue