mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-14 10:37:23 -07:00
Add auth1 output - experimental.
Add auth2 command - experimental.
This commit is contained in:
parent
a65cfc5f4b
commit
bb53a40adb
2 changed files with 176 additions and 5 deletions
|
@ -292,7 +292,7 @@ static int usage_hf_felica_authentication1() {
|
|||
PrintAndLogEx(NORMAL, " - Number of Services m: 1-byte (1 <= n <= 8)");
|
||||
PrintAndLogEx(NORMAL, " - Service Code List: 2n byte");
|
||||
PrintAndLogEx(NORMAL, " - 3DES-Key: 128-bit master secret used for the encryption");
|
||||
PrintAndLogEx(NORMAL, " - M1c: Encrypted random number (challenge for tag authentication) 8-byte");
|
||||
PrintAndLogEx(NORMAL, " - M1c: Encrypted random number - challenge for tag authentication (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - Response:");
|
||||
PrintAndLogEx(NORMAL, " - Response Code: 11h 1-byte");
|
||||
PrintAndLogEx(NORMAL, " - Manufacture ID(IDm): 8-byte");
|
||||
|
@ -301,7 +301,7 @@ static int usage_hf_felica_authentication1() {
|
|||
PrintAndLogEx(NORMAL, " - Success: Card Mode switches to Mode1. You can check this with the request response command.");
|
||||
PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all.");
|
||||
|
||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809 3DES-key hex (128bit)>");
|
||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica auth1 [-h][-i] <01 Number of Areas hex> <0A0B... Area Code List hex> <01 Number of Services hex> <0A0B... Service Code List hex> <0x0102030405060809... 3DES-key hex (16-byte)>");
|
||||
PrintAndLogEx(NORMAL, " -h this help");
|
||||
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||
|
@ -311,6 +311,30 @@ static int usage_hf_felica_authentication1() {
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int usage_hf_felica_authentication2() {
|
||||
PrintAndLogEx(NORMAL, "\nInfo: Complete mutual authentication. This command can only be executed subsquent to Authentication1"
|
||||
" command.");
|
||||
PrintAndLogEx(NORMAL, " - Auth2 Parameters:");
|
||||
PrintAndLogEx(NORMAL, " - Manufacturer IDm: (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - M3c: card challenge (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - 3DES Key: key used for decryption of M3c (16-byte)");
|
||||
PrintAndLogEx(NORMAL, " - Response (encrypted):");
|
||||
PrintAndLogEx(NORMAL, " - Response Code: 13h (1-byte)");
|
||||
PrintAndLogEx(NORMAL, " - IDtc: (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - IDi (encrypted): (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - PMi (encrypted): (8-byte)");
|
||||
PrintAndLogEx(NORMAL, " - Success: Card switches to mode2 and sends response frame.");
|
||||
PrintAndLogEx(NORMAL, " - Unsuccessful: Card should not respond at all.");
|
||||
PrintAndLogEx(NORMAL, "\nUsage: hf felica auth2 [-h][-i] <0102030405060708 M3c hex> <0x0102030405060809... 3DES-key hex (16-byte)>");
|
||||
PrintAndLogEx(NORMAL, " -h this help");
|
||||
PrintAndLogEx(NORMAL, " -i <0A0B0C ... hex> set custom IDm to use");
|
||||
PrintAndLogEx(NORMAL, "\nExamples: ");
|
||||
PrintAndLogEx(NORMAL, " hf felica auth2 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB");
|
||||
PrintAndLogEx(NORMAL, " hf felica auth2 -i 11100910C11BC407 0102030405060708 AAAAAAAAAAAAAAAABBBBBBBBBBBBBBBB\n\n");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for response from pm3 or timeout.
|
||||
* Checks if receveid bytes have a valid CRC.
|
||||
|
@ -530,6 +554,12 @@ int send_wr_unencrypted(uint8_t flags, uint16_t datalen, uint8_t *data, bool ver
|
|||
}
|
||||
}
|
||||
|
||||
static void reverse_3des_key(uint8_t *master_key, int length, uint8_t *reverse_master_key){
|
||||
for(int i=0; i<length; i++){
|
||||
reverse_master_key[i] = master_key[(length+1)-i];
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Command parser for auth1
|
||||
* @param Cmd input data of the user.
|
||||
|
@ -539,6 +569,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
|
|||
if (strlen(Cmd) < 4) {
|
||||
return usage_hf_felica_authentication1();
|
||||
}
|
||||
PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND");
|
||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||
bool custom_IDm = false;
|
||||
strip_cmds(Cmd);
|
||||
|
@ -582,7 +613,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
|
|||
}
|
||||
}
|
||||
|
||||
// READER CHALLENGE - (RANDOM To Encrypt)
|
||||
// READER CHALLENGE - (RANDOM To Encrypt = Rac)
|
||||
unsigned char input[8];
|
||||
input[0] = 0x1;
|
||||
input[1] = 0x2;
|
||||
|
@ -592,6 +623,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
|
|||
input[5] = 0x6;
|
||||
input[6] = 0x7;
|
||||
input[7] = 0x8;
|
||||
PrintAndLogEx(INFO, "Reader challenge (unencrypted): %s", sprint_hex(input, 8));
|
||||
unsigned char output[8];
|
||||
// Create M1c Challenge with 3DES (3 Keys = 24, 2 Keys = 16)
|
||||
uint8_t master_key[PM3_CMD_DATA_SIZE];
|
||||
|
@ -603,6 +635,7 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
|
|||
PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 24));
|
||||
} else if (param_getlength(Cmd, paramCount) == 32) {
|
||||
param_gethex(Cmd, paramCount, master_key, 32);
|
||||
// Assumption: Master secret split in half for Kac, Kbc
|
||||
mbedtls_des3_set2key_enc(&des3_ctx, master_key);
|
||||
PrintAndLogEx(INFO, "3DES Master Secret: %s", sprint_hex(master_key, 16));
|
||||
} else {
|
||||
|
@ -638,11 +671,141 @@ static int CmdHFFelicaAuthentication1(const char *Cmd) {
|
|||
PrintAndLogEx(SUCCESS, "IDm: %s", sprint_hex(auth1_response.frame_response.IDm, sizeof(auth1_response.frame_response.IDm)));
|
||||
PrintAndLogEx(SUCCESS, "M2C: %s", sprint_hex(auth1_response.m2c, sizeof(auth1_response.m2c)));
|
||||
PrintAndLogEx(SUCCESS, "M3C: %s", sprint_hex(auth1_response.m3c, sizeof(auth1_response.m3c)));
|
||||
// Assumption: Key swap method used
|
||||
uint8_t reverse_master_key[PM3_CMD_DATA_SIZE];
|
||||
reverse_3des_key(master_key, 16, reverse_master_key);
|
||||
mbedtls_des3_set2key_dec(&des3_ctx, reverse_master_key);
|
||||
bool isKeyCorrect = false;
|
||||
unsigned char p2c[8];
|
||||
mbedtls_des3_crypt_ecb(&des3_ctx, auth1_response.m2c, p2c);
|
||||
for(int i=0; i < 8; i++){
|
||||
if(p2c[i] != input[i]){
|
||||
isKeyCorrect = false;
|
||||
break;
|
||||
}else{
|
||||
isKeyCorrect = true;
|
||||
}
|
||||
}
|
||||
if(isKeyCorrect){
|
||||
PrintAndLogEx(SUCCESS, "\nAuth1 done with correct key material! Use Auth2 now with M3C and same key");
|
||||
}else{
|
||||
PrintAndLogEx(INFO, "\n\nP2c: %s", sprint_hex(p2c, 8));
|
||||
PrintAndLogEx(ERR, "Can't decrypt M2C with master secret (P1c != P2c)! Probably wrong keys or wrong decryption method");
|
||||
}
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Command parser for auth2
|
||||
* @param Cmd input data of the user.
|
||||
* @return client result code.
|
||||
*/
|
||||
static int CmdHFFelicaAuthentication2(const char *Cmd) {
|
||||
if (strlen(Cmd) < 2) {
|
||||
return usage_hf_felica_authentication2();
|
||||
}
|
||||
PrintAndLogEx(INFO, "EXPERIMENTAL COMMAND - M2c/P2c will be not checked");
|
||||
uint8_t data[PM3_CMD_DATA_SIZE];
|
||||
bool custom_IDm = false;
|
||||
strip_cmds(Cmd);
|
||||
uint16_t datalen = 18; // Length (1), Command ID (1), IDm (8), M4c (8)
|
||||
uint8_t paramCount = 0;
|
||||
uint8_t flags = 0;
|
||||
int i = 0;
|
||||
while (Cmd[i] != '\0') {
|
||||
if (Cmd[i] == '-') {
|
||||
switch (tolower(Cmd[i + 1])) {
|
||||
case 'h':
|
||||
return usage_hf_felica_authentication2();
|
||||
case 'i':
|
||||
paramCount++;
|
||||
custom_IDm = true;
|
||||
if (!add_param(Cmd, paramCount, data, 2, 16)) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
paramCount++;
|
||||
i += 16;
|
||||
break;
|
||||
default:
|
||||
return usage_hf_felica_authentication1();
|
||||
}
|
||||
}
|
||||
i++;
|
||||
}
|
||||
data[0] = int_to_hex(&datalen);
|
||||
data[1] = 0x12; // Command ID
|
||||
if (!custom_IDm && !check_last_idm(data, datalen)) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
// M3c (8)
|
||||
unsigned char m3c[8];
|
||||
if (add_param(Cmd, paramCount, m3c, 0, 16)) {
|
||||
paramCount++;
|
||||
} else {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
// Create M4c challenge response with 3DES
|
||||
uint8_t master_key[PM3_CMD_DATA_SIZE];
|
||||
uint8_t reverse_master_key[PM3_CMD_DATA_SIZE];
|
||||
mbedtls_des3_context des3_ctx;
|
||||
mbedtls_des3_init(&des3_ctx);
|
||||
unsigned char p3c[8];
|
||||
if (param_getlength(Cmd, paramCount) == 32) {
|
||||
param_gethex(Cmd, paramCount, master_key, 32);
|
||||
reverse_3des_key(master_key, 16, reverse_master_key);
|
||||
mbedtls_des3_set2key_dec(&des3_ctx, reverse_master_key);
|
||||
mbedtls_des3_set2key_enc(&des3_ctx, master_key);
|
||||
// Assumption: Key swap method used for E2
|
||||
PrintAndLogEx(INFO, "3DES Master Secret (encryption): %s", sprint_hex(master_key, 16));
|
||||
PrintAndLogEx(INFO, "3DES Master Secret (decryption): %s", sprint_hex(reverse_master_key, 16));
|
||||
} else {
|
||||
PrintAndLogEx(ERR, "Invalid key length");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
// Decrypt m3c with reverse_master_key
|
||||
mbedtls_des3_crypt_ecb(&des3_ctx, m3c, p3c);
|
||||
PrintAndLogEx(INFO, "3DES decrypted M3c = P3c: %s", sprint_hex(p3c, 8));
|
||||
// Encrypt p3c with master_key
|
||||
unsigned char m4c[8];
|
||||
mbedtls_des3_crypt_ecb(&des3_ctx, p3c, m4c);
|
||||
PrintAndLogEx(INFO, "3DES encrypted M4c: %s", sprint_hex(m4c, 8));
|
||||
|
||||
// Add M4c Challenge to frame
|
||||
int frame_position = 10;
|
||||
for (int i = 0; i < 8; i++) {
|
||||
data[frame_position++] = m4c[i];
|
||||
}
|
||||
|
||||
AddCrc(data, datalen);
|
||||
datalen += 2;
|
||||
flags |= FELICA_APPEND_CRC;
|
||||
flags |= FELICA_RAW;
|
||||
|
||||
PrintAndLogEx(INFO, "Client Send AUTH2 Frame: %s", sprint_hex(data, datalen));
|
||||
clear_and_send_command(flags, datalen, data, 0);
|
||||
|
||||
PacketResponseNG resp;
|
||||
if (!waitCmdFelica(0, &resp, 1)) {
|
||||
PrintAndLogEx(ERR, "\nGot no Response from card");
|
||||
return PM3_ERFTRANS;
|
||||
} else {
|
||||
felica_auth2_response_t auth2_response;
|
||||
memcpy(&auth2_response, (felica_auth2_response_t *)resp.data.asBytes, sizeof(felica_auth2_response_t));
|
||||
if (auth2_response.code[0] != 0x12) {
|
||||
PrintAndLogEx(SUCCESS, "\nGot auth2 response:");
|
||||
PrintAndLogEx(SUCCESS, "IDtc: %s", sprint_hex(auth2_response.IDtc, sizeof(auth2_response.IDtc)));
|
||||
PrintAndLogEx(SUCCESS, "IDi (encrypted): %s", sprint_hex(auth2_response.IDi, sizeof(auth2_response.IDi)));
|
||||
PrintAndLogEx(SUCCESS, "PMi (encrypted): %s", sprint_hex(auth2_response.PMi, sizeof(auth2_response.PMi)));
|
||||
}else{
|
||||
PrintAndLogEx(ERR, "\nGot wrong frame format.");
|
||||
}
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Command parser for wrunencrypted.
|
||||
* @param Cmd input data of the user.
|
||||
|
@ -1650,8 +1813,8 @@ static command_t CommandTable[] = {
|
|||
{"wrunencrypted", CmdHFFelicaWriteWithoutEncryption, IfPm3Felica, "write Block Data to an authentication-not-required Service."},
|
||||
{"scsvcode", CmdHFFelicaNotImplementedYet, IfPm3Felica, "acquire Area Code and Service Code."},
|
||||
{"rqsyscode", CmdHFFelicaRequestSystemCode, IfPm3Felica, "acquire System Code registered to the card."},
|
||||
{"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1 (v1)"},
|
||||
{"auth2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Auth2 (v1)"},
|
||||
{"auth1", CmdHFFelicaAuthentication1, IfPm3Felica, "authenticate a card. Start mutual authentication with Auth1"},
|
||||
{"auth2", CmdHFFelicaAuthentication2, IfPm3Felica, "allow a card to authenticate a Reader/Writer. Complete mutual authentication"},
|
||||
{"read", CmdHFFelicaNotImplementedYet, IfPm3Felica, "read Block Data from authentication-required Service."},
|
||||
//{"write", CmdHFFelicaNotImplementedYet, IfPm3Felica, "write Block Data to an authentication-required Service."},
|
||||
//{"scsvcodev2", CmdHFFelicaNotImplementedYet, IfPm3Felica, "verify the existence of Area or Service, and to acquire Key Version."},
|
||||
|
|
|
@ -226,6 +226,14 @@ typedef struct {
|
|||
uint8_t m3c[8];
|
||||
} PACKED felica_auth1_response_t;
|
||||
|
||||
typedef struct {
|
||||
uint8_t code[1];
|
||||
uint8_t IDtc[8];
|
||||
uint8_t IDi[8];
|
||||
uint8_t PMi[8];
|
||||
} PACKED felica_auth2_response_t;
|
||||
|
||||
|
||||
typedef enum FELICA_COMMAND {
|
||||
FELICA_CONNECT = (1 << 0),
|
||||
FELICA_NO_DISCONNECT = (1 << 1),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue