mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
Merge branch 'master' into purring-basilisk
Signed-off-by: Iceman <iceman@iuse.se>
This commit is contained in:
+4
-1
@@ -3,9 +3,12 @@ All notable changes to this project will be documented in this file.
|
||||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
|
||||
- Removed `save_restoreDB` - replaced by `buffer_savestate_t` implementation (@HACKhalo2)
|
||||
- Removed `save_restoreGB` - replaced by `buffer_savestate_t` implementation (@HACKhalo2)
|
||||
- Changed `lf hitag dump --nrar` - now supports attack 1 from "gone in 360 seconds" paper. Thanks @kevsecurity! (@iceman1001)
|
||||
- Added `lf hitag selftest` - converted from RFIDLers selftest (@iceman1001)
|
||||
- Added `lf hitag chk` - dictionary attack against card (@iceman1001)
|
||||
- Added `lf hitag lookup` - verify collected challenges aginst dictionary (@iceman1001)
|
||||
- Updated windows workflow to use latest setup-wsl script (@iceman1001)
|
||||
- Added a micro second clock in the client (@iceman1001)
|
||||
- Fix `hf mfdes read` - buffer overflow when reading large files (@iceman1001)
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ else
|
||||
endif
|
||||
|
||||
ifneq (,$(findstring WITH_HITAG,$(APP_CFLAGS)))
|
||||
SRC_HITAG = hitag2_crypto.c hitag2.c hitagS.c
|
||||
SRC_HITAG = hitag2_crypto.c hitag2.c hitagS.c hitag2_crack.c
|
||||
APP_CFLAGS += -I../common/hitag2
|
||||
else
|
||||
SRC_HITAG =
|
||||
|
||||
+33
-13
@@ -40,6 +40,7 @@
|
||||
#include "thinfilm.h"
|
||||
#include "felica.h"
|
||||
#include "hitag2.h"
|
||||
#include "hitag2_crack.h"
|
||||
#include "hitagS.h"
|
||||
#include "em4x50.h"
|
||||
#include "em4x70.h"
|
||||
@@ -1131,7 +1132,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
#ifdef WITH_HITAG
|
||||
case CMD_LF_HITAG_SNIFF: { // Eavesdrop Hitag tag, args = type
|
||||
SniffHitag2(true);
|
||||
// SniffHitag2(packet->oldarg[0]);
|
||||
//hitag_sniff();
|
||||
reply_ng(CMD_LF_HITAG_SNIFF, PM3_SUCCESS, NULL, 0);
|
||||
break;
|
||||
}
|
||||
@@ -1139,8 +1140,24 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
SimulateHitag2(true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG2_CRACK: {
|
||||
lf_hitag_data_t *payload = (lf_hitag_data_t *) packet->data.asBytes;
|
||||
ht2_crack(payload->NrAr);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_READER: { // Reader for Hitag tags, args = type and function
|
||||
ReaderHitag((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, true);
|
||||
lf_hitag_data_t *payload = (lf_hitag_data_t *) packet->data.asBytes;
|
||||
|
||||
switch (payload->cmd) {
|
||||
case RHT2F_UID_ONLY: {
|
||||
ht2_read_uid(NULL, true, true, false);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
ReaderHitag(payload, true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAGS_SIMULATE: { // Simulate Hitag s tag, args = memory content
|
||||
@@ -1148,25 +1165,28 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAGS_TEST_TRACES: { // Tests every challenge within the given file
|
||||
Hitag_check_challenges(packet->data.asBytes, packet->oldarg[0], true);
|
||||
Hitag_check_challenges(packet->data.asBytes, packet->length, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAGS_READ: { //Reader for only Hitag S tags, args = key or challenge
|
||||
ReadHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, true);
|
||||
case CMD_LF_HITAGS_READ: { // Reader for only Hitag S tags, args = key or challenge
|
||||
lf_hitag_data_t *payload = (lf_hitag_data_t *) packet->data.asBytes;
|
||||
ReadHitagS(payload, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAGS_WRITE: { //writer for Hitag tags args=data to write,page and key or challenge
|
||||
if ((hitag_function)packet->oldarg[0] < 10) {
|
||||
WritePageHitagS((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, packet->oldarg[2], true);
|
||||
} else {
|
||||
WriterHitag((hitag_function)packet->oldarg[0], (hitag_data *)packet->data.asBytes, packet->oldarg[2], true);
|
||||
}
|
||||
case CMD_LF_HITAGS_WRITE: {
|
||||
lf_hitag_data_t *payload = (lf_hitag_data_t *) packet->data.asBytes;
|
||||
WritePageHitagS(payload, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG2_WRITE: {
|
||||
lf_hitag_data_t *payload = (lf_hitag_data_t *) packet->data.asBytes;
|
||||
WriterHitag(payload, true);
|
||||
break;
|
||||
}
|
||||
case CMD_LF_HITAG_ELOAD: {
|
||||
lf_hitag_t *payload = (lf_hitag_t *) packet->data.asBytes;
|
||||
uint8_t *mem = BigBuf_get_EM_addr();
|
||||
memcpy((uint8_t *)mem, payload->data, payload->len);
|
||||
memcpy(mem, payload->data, payload->len);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@@ -1371,7 +1391,7 @@ static void PacketReceived(PacketCommandNG *packet) {
|
||||
struct p *payload = (struct p *) packet->data.asBytes;
|
||||
SetTag15693Uid_v2(payload->uid);
|
||||
break;
|
||||
}
|
||||
}
|
||||
case CMD_HF_ISO15693_SLIX_DISABLE_EAS: {
|
||||
struct p {
|
||||
uint8_t pwd[4];
|
||||
|
||||
+641
-220
File diff suppressed because it is too large
Load Diff
+7
-3
@@ -23,8 +23,12 @@
|
||||
#include "hitag.h"
|
||||
|
||||
void SniffHitag2(bool ledcontrol);
|
||||
void hitag_sniff(void);
|
||||
void SimulateHitag2(bool ledcontrol);
|
||||
void ReaderHitag(hitag_function htf, const hitag_data *htd, bool ledcontrol);
|
||||
void WriterHitag(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
|
||||
void EloadHitag(const uint8_t *data, uint16_t len);
|
||||
void ReaderHitag(const lf_hitag_data_t *payload, bool ledcontrol);
|
||||
void WriterHitag(const lf_hitag_data_t *payload, bool ledcontrol);
|
||||
|
||||
bool ht2_packbits(uint8_t *nrz_samples, size_t nrzs, uint8_t *rx, size_t *rxlen);
|
||||
int ht2_read_uid(uint8_t *uid, bool ledcontrol, bool send_answer, bool keep_field_up);
|
||||
int ht2_tx_rx(uint8_t *tx, size_t txlen, uint8_t *rx, size_t *rxlen, bool ledcontrol, bool keep_field_up);
|
||||
#endif
|
||||
|
||||
+11
-11
@@ -14,7 +14,7 @@
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// This coode has been converted from RFIDler source code to work with Proxmark3.
|
||||
// This coode has been converted from RFIDler source code to work with Proxmark3.
|
||||
// https://github.com/AdamLaurie/RFIDler/blob/master/firmware/Pic32/RFIDler.X/src/hitag2crack.c
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
const static uint8_t ERROR_RESPONSE[] = { 0xF4, 0x02, 0x88, 0x9C };
|
||||
|
||||
// #define READP0CMD "1100000111"
|
||||
const static uint8_t read_p0_cmd[] = {1,1,0,0,0,0,0,1,1,1};
|
||||
const static uint8_t read_p0_cmd[] = {1, 1, 0, 0, 0, 0, 0, 1, 1, 1};
|
||||
|
||||
// hitag2crack_xor XORs the source with the pad to produce the target.
|
||||
// source, target and pad are binarrays of length len.
|
||||
@@ -121,7 +121,7 @@ static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar,
|
||||
uint8_t response[32];
|
||||
|
||||
// convert to binarray
|
||||
hex2binarray((char*)e_response, (char*)e_resp);
|
||||
hex2binarray((char *)e_response, (char *)e_resp);
|
||||
// decrypt response
|
||||
hitag2crack_xor(response, e_response, keybits + 10, 32);
|
||||
|
||||
@@ -129,7 +129,7 @@ static bool hitag2crack_read_page(uint8_t *resp, uint8_t pagenum, uint8_t *nrar,
|
||||
binarray2hex(response, 32, resp);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -200,7 +200,7 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
|
||||
// representing the inverted bit and the 3 page bits
|
||||
// in both the non-inverted and inverted parts of the
|
||||
// encrypted command.
|
||||
uint8_t guess[10];
|
||||
uint8_t guess[10];
|
||||
memcpy(guess, e_firstcmd, 10);
|
||||
if (a) {
|
||||
guess[5] = !guess[5];
|
||||
@@ -231,7 +231,7 @@ static bool hitag2crack_find_e_page0_cmd(uint8_t *keybits, uint8_t *e_firstcmd,
|
||||
|
||||
// convert response to binarray
|
||||
uint8_t e_uid[32];
|
||||
hex2binarray((char*)e_uid, (char*)resp);
|
||||
hex2binarray((char *)e_uid, (char *)resp);
|
||||
|
||||
// test if the guess was 'read page 0' command
|
||||
if (hitag2crack_test_e_p0cmd(keybits, nrar, guess, uid, e_uid)) {
|
||||
@@ -299,13 +299,13 @@ static bool hitag2crack_find_valid_e_cmd(uint8_t *e_cmd, uint8_t *nrar) {
|
||||
// hitag2_crack implements the first crack algorithm described in the paper,
|
||||
// Gone In 360 Seconds by Verdult, Garcia and Balasch.
|
||||
// response is a multi-line text response containing the 8 pages of the cracked tag
|
||||
// nrarhex is a string containing hex representations of the 32 bit nR and aR values
|
||||
// nrarhex is a string containing hex representations of the 32 bit nR and aR values
|
||||
void ht2_crack(uint8_t *nrar_hex) {
|
||||
|
||||
clear_trace();
|
||||
|
||||
lf_hitag_crack_response_t packet;
|
||||
memset((uint8_t*)&packet, 0x00, sizeof(lf_hitag_crack_response_t));
|
||||
memset((uint8_t *)&packet, 0x00, sizeof(lf_hitag_crack_response_t));
|
||||
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
@@ -319,7 +319,7 @@ void ht2_crack(uint8_t *nrar_hex) {
|
||||
|
||||
// convert to binarray
|
||||
uint8_t nrar[64] = {0};
|
||||
hex2binarray_n((char*)nrar, (char*)nrar_hex, 8);
|
||||
hex2binarray_n((char *)nrar, (char *)nrar_hex, 8);
|
||||
|
||||
// find a valid encrypted command
|
||||
uint8_t e_firstcmd[10];
|
||||
@@ -331,7 +331,7 @@ void ht2_crack(uint8_t *nrar_hex) {
|
||||
|
||||
// now we got a first encrypted command inside e_firstcmd
|
||||
uint8_t uid[32];
|
||||
hex2binarray_n((char*)uid, (char*)uid_hex, 4);
|
||||
hex2binarray_n((char *)uid, (char *)uid_hex, 4);
|
||||
|
||||
// find the 'read page 0' command and recover key stream
|
||||
uint8_t keybits[42];
|
||||
@@ -352,5 +352,5 @@ void ht2_crack(uint8_t *nrar_hex) {
|
||||
packet.status = 1;
|
||||
|
||||
out:
|
||||
reply_ng(CMD_LF_HITAG2_CRACK, res, (uint8_t*)&packet, sizeof(lf_hitag_crack_response_t));
|
||||
reply_ng(CMD_LF_HITAG2_CRACK, res, (uint8_t *)&packet, sizeof(lf_hitag_crack_response_t));
|
||||
}
|
||||
|
||||
+309
-159
File diff suppressed because it is too large
Load Diff
+2
-3
@@ -22,11 +22,10 @@
|
||||
#define _HITAGS_H_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "hitag.h"
|
||||
|
||||
void SimulateHitagSTag(bool tag_mem_supplied, const uint8_t *data, bool ledcontrol);
|
||||
void ReadHitagS(hitag_function htf, const hitag_data *htd, bool ledcontrol);
|
||||
void WritePageHitagS(hitag_function htf, const hitag_data *htd, int page, bool ledcontrol);
|
||||
void ReadHitagS(const lf_hitag_data_t *payload, bool ledcontrol);
|
||||
void WritePageHitagS(const lf_hitag_data_t *payload, bool ledcontrol);
|
||||
void Hitag_check_challenges(const uint8_t *data, uint32_t datalen, bool ledcontrol);
|
||||
#endif
|
||||
|
||||
+4
-5
@@ -2941,14 +2941,11 @@ void SetTag15693Uid_v2(const uint8_t *uid) {
|
||||
{ ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x47, 0x3f, 0x03, 0x8b, 0x00, 0x00, 0x00 },
|
||||
{ ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
|
||||
// hf 15 raw -wac -d 02 e0 09 41 + uid first four bytes
|
||||
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x41, uid[7], uid[6], uid[5], uid[4], 0x00, 0x00},
|
||||
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x40, uid[7], uid[6], uid[5], uid[4], 0x00, 0x00},
|
||||
// hf 15 raw -wac -d 02 e0 09 40 + uid last four bytes
|
||||
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x40, uid[3], uid[2], uid[1], uid[0], 0x00, 0x00}
|
||||
{ISO15_REQ_DATARATE_HIGH, ISO15693_MAGIC_WRITE, 0x09, 0x41, uid[3], uid[2], uid[1], uid[0], 0x00, 0x00}
|
||||
};
|
||||
|
||||
AddCrc15(cmd[0], 8);
|
||||
AddCrc15(cmd[1], 8);
|
||||
|
||||
uint8_t buf[ISO15693_MAX_RESPONSE_LENGTH] = {0x00};
|
||||
|
||||
uint32_t start_time = 0;
|
||||
@@ -2958,6 +2955,8 @@ void SetTag15693Uid_v2(const uint8_t *uid) {
|
||||
int res = PM3_SUCCESS;
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
|
||||
AddCrc15(cmd[i], 8);
|
||||
res = SendDataTag(
|
||||
cmd[i],
|
||||
sizeof(cmd[i]),
|
||||
|
||||
+4
-4
@@ -91,7 +91,7 @@ int hex2binarray_n(char *target, char *source, int sourcelen) {
|
||||
|
||||
// process 4 bits (1 hex digit) at a time
|
||||
while (sourcelen--) {
|
||||
|
||||
|
||||
char x = *(source++);
|
||||
|
||||
*(target++) = (x >> 7) & 1;
|
||||
@@ -102,7 +102,7 @@ int hex2binarray_n(char *target, char *source, int sourcelen) {
|
||||
*(target++) = (x >> 2) & 1;
|
||||
*(target++) = (x >> 1) & 1;
|
||||
*(target++) = (x & 1);
|
||||
|
||||
|
||||
count += 8;
|
||||
}
|
||||
return count;
|
||||
@@ -122,9 +122,9 @@ int binarray2hex(const uint8_t *bs, int bs_len, uint8_t *hex) {
|
||||
if (bs[i] == 1) {
|
||||
hex[byte_index] |= (1 << (7 - (count % 8)));
|
||||
}
|
||||
|
||||
|
||||
count++;
|
||||
|
||||
|
||||
// Move to the next byte if 8 bits have been filled
|
||||
if (count % 8 == 0) {
|
||||
byte_index++;
|
||||
|
||||
@@ -263,6 +263,7 @@ set (TARGET_SOURCES
|
||||
${PM3_ROOT}/common/cardhelper.c
|
||||
${PM3_ROOT}/common/generator.c
|
||||
${PM3_ROOT}/common/bruteforce.c
|
||||
${PM3_ROOT}/common/hitag2/hitag2_crypto.c
|
||||
${PM3_ROOT}/client/src/crypto/asn1dump.c
|
||||
${PM3_ROOT}/client/src/crypto/asn1utils.c
|
||||
${PM3_ROOT}/client/src/crypto/libpcrypto.c
|
||||
|
||||
@@ -1,13 +1,25 @@
|
||||
#
|
||||
# Mifare Default Keys
|
||||
# -- Iceman version --
|
||||
# -- contribute to this list, sharing is caring --
|
||||
#
|
||||
# Lets see how long it takes before other project takes this file
|
||||
# and claim they created it.
|
||||
#
|
||||
# factory HT2 pwd
|
||||
4D494B52
|
||||
# factory HT2 crypto key
|
||||
4F4E4D494B52
|
||||
#
|
||||
# GE HT2 reader
|
||||
#
|
||||
# TSPL
|
||||
5453504C
|
||||
05040202
|
||||
25293C2F
|
||||
# Gone in 360 seconds
|
||||
FFFF814632FF
|
||||
#
|
||||
# Paxton HT2
|
||||
BDF5E846
|
||||
#
|
||||
#
|
||||
# GE HT2 reader
|
||||
# TSPL
|
||||
5453504C
|
||||
05040202
|
||||
25293C2F
|
||||
@@ -125,4 +125,4 @@ local function main(args)
|
||||
end
|
||||
end
|
||||
|
||||
main(args)
|
||||
main(args)
|
||||
|
||||
@@ -1719,12 +1719,12 @@ static int CmdSetGraphMarkers(const char *Cmd) {
|
||||
g_MarkerC.pos = arg_get_u32_def(ctx, 4, (keep ? g_MarkerC.pos : 0));
|
||||
g_MarkerD.pos = arg_get_u32_def(ctx, 5, (keep ? g_MarkerD.pos : 0));
|
||||
CLIParserFree(ctx);
|
||||
PrintAndLogEx(INFO, "Setting markers " _BRIGHT_YELLOW_("A") "=%u, "_BRIGHT_MAGENTA_("B") "=%u, "_RED_("C") "=%u, "_BLUE_("D") "=%u",
|
||||
g_MarkerA.pos,
|
||||
g_MarkerB.pos,
|
||||
g_MarkerC.pos,
|
||||
g_MarkerD.pos
|
||||
);
|
||||
PrintAndLogEx(INFO, "Setting markers " _BRIGHT_YELLOW_("A") "=%u, "_BRIGHT_MAGENTA_("B") "=%u, "_RED_("C") "=%u, "_BLUE_("D") "=%u",
|
||||
g_MarkerA.pos,
|
||||
g_MarkerB.pos,
|
||||
g_MarkerC.pos,
|
||||
g_MarkerD.pos
|
||||
);
|
||||
RepaintGraphWindow();
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
@@ -3847,7 +3847,7 @@ static command_t CommandTable[] = {
|
||||
{"save", CmdSave, AlwaysAvailable, "Save signal trace data"},
|
||||
{"setdebugmode", CmdSetDebugMode, AlwaysAvailable, "Set Debugging Level on client side"},
|
||||
{"xor", CmdXor, AlwaysAvailable, "Xor a input string"},
|
||||
|
||||
|
||||
{"-----------", CmdHelp, AlwaysAvailable, "------------------------- " _CYAN_("Modulation") "-------------------------"},
|
||||
{"biphaserawdecode", CmdBiphaseDecodeRaw, AlwaysAvailable, "Biphase decode bin stream in DemodBuffer"},
|
||||
{"detectclock", CmdDetectClockRate, AlwaysAvailable, "Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"},
|
||||
|
||||
@@ -2737,7 +2737,7 @@ static int CmdHF15CSetUID(const char *Cmd) {
|
||||
"Set UID for magic Chinese card (only works with such cards)\n",
|
||||
"hf 15 csetuid -u E011223344556677 -> use gen1 command\n"
|
||||
"hf 15 csetuid -u E011223344556677 --v2 -> use gen2 command"
|
||||
);
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
|
||||
@@ -355,7 +355,7 @@ static int CmdHFMFPInfo(const char *Cmd) {
|
||||
if (supportVersion) {
|
||||
|
||||
int cardtype = getCardType(version[1], version[3], version[4]);
|
||||
switch(cardtype) {
|
||||
switch (cardtype) {
|
||||
case PLUS_EV1: {
|
||||
if (supportSignature) {
|
||||
PrintAndLogEx(INFO, "Tech..... " _GREEN_("MIFARE Plus EV1"));
|
||||
|
||||
+1111
-172
File diff suppressed because it is too large
Load Diff
@@ -22,6 +22,7 @@
|
||||
#include "common.h"
|
||||
|
||||
|
||||
#define HITAG_NRAR_SIZE 8
|
||||
#define HITAG_CRYPTOKEY_SIZE 6
|
||||
#define HITAG_PASSWORD_SIZE 4
|
||||
#define HITAG_UID_SIZE 4
|
||||
@@ -37,16 +38,18 @@
|
||||
|
||||
#define HITAG2_CONFIG_BLOCK 3
|
||||
#define HITAG2_CONFIG_OFFSET (HITAG_BLOCK_SIZE * HITAG2_CONFIG_BLOCK)
|
||||
#define HITAG_DICTIONARY "ht2_default"
|
||||
|
||||
int CmdLFHitag(const char *Cmd);
|
||||
|
||||
int readHitagUid(void);
|
||||
void annotateHitag1(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response);
|
||||
void annotateHitag2(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits, bool is_response);
|
||||
void annotateHitag2(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits, bool is_response, const uint64_t *keys, uint32_t keycount, bool isdecrypted);
|
||||
void annotateHitagS(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, bool is_response);
|
||||
|
||||
void annotateHitag2_init(void);
|
||||
|
||||
bool hitag2_get_plain(uint8_t *plain, uint8_t *plen);
|
||||
void hitag2_annotate_plain(char *exp, size_t size, const uint8_t *cmd, uint8_t cmdsize, uint8_t bits);
|
||||
|
||||
uint8_t hitag1_CRC_check(uint8_t *d, uint32_t nbit);
|
||||
#endif
|
||||
|
||||
+99
-8
@@ -501,7 +501,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
|
||||
uint32_t end_of_transmission_timestamp = 0;
|
||||
uint8_t topaz_reader_command[9];
|
||||
char explanation[40] = {0};
|
||||
char explanation[60] = {0};
|
||||
tracelog_hdr_t *first_hdr = (tracelog_hdr_t *)(trace);
|
||||
tracelog_hdr_t *hdr = (tracelog_hdr_t *)(trace + tracepos);
|
||||
|
||||
@@ -774,10 +774,9 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
|
||||
end_of_transmission_timestamp = hdr->timestamp + duration;
|
||||
|
||||
if (prev_eot)
|
||||
if (prev_eot) {
|
||||
*prev_eot = end_of_transmission_timestamp;
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Always annotate these protocols both reader/tag messages
|
||||
switch (protocol) {
|
||||
@@ -793,7 +792,7 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
annotateHitag1(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
break;
|
||||
case PROTO_HITAG2:
|
||||
annotateHitag2(explanation, sizeof(explanation), frame, data_len, parityBytes[0], hdr->isResponse);
|
||||
annotateHitag2(explanation, sizeof(explanation), frame, data_len, parityBytes[0], hdr->isResponse, mfDicKeys, mfDicKeysCount, false);
|
||||
break;
|
||||
case PROTO_HITAGS:
|
||||
annotateHitagS(explanation, sizeof(explanation), frame, data_len, hdr->isResponse);
|
||||
@@ -979,6 +978,71 @@ static uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *tr
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == PROTO_HITAG2) {
|
||||
|
||||
uint8_t ht2plain[9] = {0};
|
||||
uint8_t n = 0;
|
||||
if (hitag2_get_plain(ht2plain, &n)) {
|
||||
|
||||
memset(explanation, 0x00, sizeof(explanation));
|
||||
|
||||
// handle partial bytes. The parity array[0] is used to store number of left over bits from NBYTES
|
||||
// This part prints the number of bits in the trace entry for hitag.
|
||||
uint8_t nbits = parityBytes[0];
|
||||
|
||||
annotateHitag2(explanation, sizeof(explanation), ht2plain, n, nbits, hdr->isResponse, NULL, 0, true);
|
||||
|
||||
// iceman: colorise crc bytes here will need a refactor of code from above.
|
||||
for (int j = 0; j < n && (j / TRACE_MAX_HEX_BYTES) < TRACE_MAX_HEX_BYTES; j++) {
|
||||
|
||||
|
||||
if (j == 0) {
|
||||
|
||||
// only apply this to lesser than one byte
|
||||
if (n == 1) {
|
||||
|
||||
if (nbits == 5) {
|
||||
snprintf(line[0], 120, "%2u: %02X ", nbits, ht2plain[0] >> (8 - nbits));
|
||||
} else {
|
||||
snprintf(line[0], 120, "%2u: %02X ", nbits, ht2plain[0] >> (8 - nbits));
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (nbits == 0) {
|
||||
snprintf(line[0], 120, "%2u: %02X ", (n * 8), ht2plain[0]);
|
||||
} else {
|
||||
snprintf(line[0], 120, "%2u: %02X ", ((n - 1) * 8) + nbits, ht2plain[0]);
|
||||
}
|
||||
}
|
||||
offset = 4;
|
||||
|
||||
} else {
|
||||
snprintf(line[j / 18] + ((j % 18) * 4) + offset, 120, "%02X ", ht2plain[j]);
|
||||
}
|
||||
}
|
||||
|
||||
num_lines = MIN((n - 1) / TRACE_MAX_HEX_BYTES + 1, TRACE_MAX_HEX_BYTES);
|
||||
|
||||
for (int j = 0; j < num_lines ; j++) {
|
||||
if (hdr->isResponse) {
|
||||
PrintAndLogEx(NORMAL, " | | * |%-*s | %-4s| %s",
|
||||
str_padder,
|
||||
line[j],
|
||||
" ",
|
||||
explanation);
|
||||
} else {
|
||||
PrintAndLogEx(NORMAL, " | | * |" _YELLOW_("%-*s")" | " _YELLOW_("%s") "| " _YELLOW_("%s"),
|
||||
str_padder,
|
||||
line[j],
|
||||
" ",
|
||||
explanation);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (is_last_record(tracepos, traceLen)) {
|
||||
return traceLen;
|
||||
}
|
||||
@@ -1436,6 +1500,30 @@ int CmdTraceList(const char *Cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
if (protocol == PROTO_HITAG2) {
|
||||
|
||||
if (strlen(dictionary) == 0) {
|
||||
snprintf(dictionary, sizeof(dictionary), HITAG_DICTIONARY);
|
||||
}
|
||||
|
||||
// load keys
|
||||
uint8_t *keyBlock = NULL;
|
||||
int res = loadFileDICTIONARY_safe(dictionary, (void **) &keyBlock, HITAG_CRYPTOKEY_SIZE, &dicKeysCount);
|
||||
if (res != PM3_SUCCESS || dicKeysCount == 0 || keyBlock == NULL) {
|
||||
PrintAndLogEx(FAILED, "An error occurred while loading the dictionary!");
|
||||
} else {
|
||||
dicKeys = calloc(dicKeysCount, sizeof(uint64_t));
|
||||
for (int i = 0; i < dicKeysCount; i++) {
|
||||
uint64_t key = bytes_to_num(keyBlock + i * HITAG_CRYPTOKEY_SIZE, HITAG_CRYPTOKEY_SIZE);
|
||||
memcpy((uint8_t *) &dicKeys[i], &key, sizeof(uint64_t));
|
||||
}
|
||||
dictionaryLoad = true;
|
||||
}
|
||||
if (keyBlock != NULL) {
|
||||
free(keyBlock);
|
||||
}
|
||||
}
|
||||
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
if (use_relative) {
|
||||
PrintAndLogEx(NORMAL, " Gap | Duration | Src | Data (! denotes parity error, ' denotes short bytes) | CRC | Annotation");
|
||||
@@ -1463,16 +1551,19 @@ int CmdTraceList(const char *Cmd) {
|
||||
while (tracepos < gs_traceLen) {
|
||||
tracepos = printTraceLine(tracepos, gs_traceLen, gs_trace, protocol, show_wait_cycles, mark_crc, prev_EOT, use_us, dicKeys, dicKeysCount);
|
||||
|
||||
if (kbd_enter_pressed())
|
||||
if (kbd_enter_pressed()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (dictionaryLoad)
|
||||
if (dictionaryLoad) {
|
||||
free((void *) dicKeys);
|
||||
}
|
||||
}
|
||||
|
||||
if (show_hex)
|
||||
if (show_hex) {
|
||||
PrintAndLogEx(HINT, "syntax to use: " _YELLOW_("`text2pcap -t \"%%S.\" -l 264 -n <input-text-file> <output-pcapng-file>`"));
|
||||
}
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -127,34 +127,38 @@ void des3_decrypt(void *out, const void *in, const void *key, uint8_t keycount)
|
||||
// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001.
|
||||
int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) {
|
||||
uint8_t iiv[16] = {0};
|
||||
if (iv)
|
||||
if (iv) {
|
||||
memcpy(iiv, iv, 16);
|
||||
}
|
||||
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
if (mbedtls_aes_setkey_enc(&aes, key, 128))
|
||||
if (mbedtls_aes_setkey_enc(&aes, key, 128)) {
|
||||
return 1;
|
||||
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output))
|
||||
}
|
||||
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output)) {
|
||||
return 2;
|
||||
}
|
||||
mbedtls_aes_free(&aes);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length) {
|
||||
uint8_t iiv[16] = {0};
|
||||
if (iv)
|
||||
if (iv) {
|
||||
memcpy(iiv, iv, 16);
|
||||
}
|
||||
|
||||
mbedtls_aes_context aes;
|
||||
mbedtls_aes_init(&aes);
|
||||
if (mbedtls_aes_setkey_dec(&aes, key, 128))
|
||||
if (mbedtls_aes_setkey_dec(&aes, key, 128)) {
|
||||
return 1;
|
||||
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output))
|
||||
}
|
||||
if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output)) {
|
||||
return 2;
|
||||
}
|
||||
mbedtls_aes_free(&aes);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
// NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication.
|
||||
@@ -171,13 +175,14 @@ int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int lengt
|
||||
memset(mac, 0x00, 8);
|
||||
|
||||
int res = aes_cmac(iv, key, input, cmac_tmp, length);
|
||||
if (res)
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
for (int i = 0; i < 8; i++)
|
||||
for (int i = 0; i < 8; i++) {
|
||||
mac[i] = cmac_tmp[i * 2 + 1];
|
||||
|
||||
return 0;
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static uint8_t fixed_rand_value[250] = {0};
|
||||
@@ -188,21 +193,23 @@ static int fixed_rand(void *rng_state, unsigned char *output, size_t len) {
|
||||
memset(output, 0x00, len);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int sha1hash(uint8_t *input, int length, uint8_t *hash) {
|
||||
if (!hash || !input)
|
||||
if (!hash || !input) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbedtls_sha1(input, length, hash);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int sha256hash(uint8_t *input, int length, uint8_t *hash) {
|
||||
if (!hash || !input)
|
||||
if (!hash || !input) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbedtls_sha256_context sctx;
|
||||
mbedtls_sha256_init(&sctx);
|
||||
@@ -211,12 +218,13 @@ int sha256hash(uint8_t *input, int length, uint8_t *hash) {
|
||||
mbedtls_sha256_finish(&sctx, hash);
|
||||
mbedtls_sha256_free(&sctx);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int sha512hash(uint8_t *input, int length, uint8_t *hash) {
|
||||
if (!hash || !input)
|
||||
if (!hash || !input) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
mbedtls_sha512_context sctx;
|
||||
mbedtls_sha512_init(&sctx);
|
||||
@@ -225,33 +233,35 @@ int sha512hash(uint8_t *input, int length, uint8_t *hash) {
|
||||
mbedtls_sha512_finish(&sctx, hash);
|
||||
mbedtls_sha512_free(&sctx);
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ecdsa_init_str(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveid, const char *key_d, const char *key_x, const char *key_y) {
|
||||
if (!ctx)
|
||||
if (!ctx) {
|
||||
return 1;
|
||||
|
||||
int res;
|
||||
}
|
||||
|
||||
mbedtls_ecdsa_init(ctx);
|
||||
res = mbedtls_ecp_group_load(&ctx->grp, curveid);
|
||||
if (res)
|
||||
int res = mbedtls_ecp_group_load(&ctx->grp, curveid);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
|
||||
if (key_d) {
|
||||
res = mbedtls_mpi_read_string(&ctx->d, 16, key_d);
|
||||
if (res)
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
if (key_x && key_y) {
|
||||
res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y);
|
||||
if (res)
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int ecdsa_init(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy) {
|
||||
@@ -278,7 +288,7 @@ static int ecdsa_init(mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id curveid,
|
||||
return res;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int ecdsa_key_create(mbedtls_ecp_group_id curveid, uint8_t *key_d, uint8_t *key_xy) {
|
||||
@@ -519,8 +529,9 @@ int ecdsa_nist_test(bool verbose) {
|
||||
size_t siglen = 0;
|
||||
|
||||
// NIST ecdsa test
|
||||
if (verbose)
|
||||
PrintAndLogEx(INFO, " ECDSA NIST test: " NOLF);
|
||||
if (verbose) {
|
||||
PrintAndLogEx(INFO, "ECDSA NIST test " NOLF);
|
||||
}
|
||||
// make signature
|
||||
res = ecdsa_signature_create_test(curveid, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen);
|
||||
// PrintAndLogEx(INFO, "res: %x signature[%x]: %s", (res < 0)? -res : res, siglen, sprint_hex(signature, siglen));
|
||||
@@ -540,15 +551,16 @@ int ecdsa_nist_test(bool verbose) {
|
||||
uint8_t sval_s[33] = {0};
|
||||
param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen);
|
||||
if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) {
|
||||
PrintAndLogEx(INFO, "R or S check error");
|
||||
PrintAndLogEx(NORMAL, "( " _RED_("R or S check error") " )");
|
||||
res = 100;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// verify signature
|
||||
res = ecdsa_signature_verify_keystr(curveid, T_Q_X, T_Q_Y, input, length, signature, siglen, true);
|
||||
if (res)
|
||||
if (res) {
|
||||
goto exit;
|
||||
}
|
||||
|
||||
// verify wrong signature
|
||||
input[0] ^= 0xFF;
|
||||
@@ -559,8 +571,8 @@ int ecdsa_nist_test(bool verbose) {
|
||||
}
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(NORMAL, _GREEN_("passed"));
|
||||
PrintAndLogEx(INFO, " ECDSA binary signature create/check test: " NOLF);
|
||||
PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
|
||||
PrintAndLogEx(INFO, "ECDSA binary signature create/check test " NOLF);
|
||||
}
|
||||
|
||||
// random ecdsa test
|
||||
@@ -587,12 +599,12 @@ int ecdsa_nist_test(bool verbose) {
|
||||
goto exit;
|
||||
|
||||
if (verbose)
|
||||
PrintAndLogEx(NORMAL, _GREEN_("passed\n"));
|
||||
PrintAndLogEx(NORMAL, "( " _GREEN_("ok") " )");
|
||||
|
||||
return PM3_SUCCESS;
|
||||
exit:
|
||||
if (verbose)
|
||||
PrintAndLogEx(NORMAL, _RED_("failed\n"));
|
||||
PrintAndLogEx(NORMAL, "( " _RED_("fail") " )");
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user