Merge pull request #44 from RfidResearchGroup/master

Rebase
This commit is contained in:
mwalker33
2020-09-09 09:20:51 +10:00
committed by GitHub
98 changed files with 3284 additions and 1341 deletions
@@ -0,0 +1,47 @@
---
name: Checklist for release
about: A template when making a release (usage reserved to repo maintainers)
title: "[RELEASE 4.x] Checklist"
labels: Release
assignees: doegox, iceman1001
---
# Checklist
- [ ] CHANGELOG.md
- [ ] `make style`
- [ ] `make clean; make client CC=clang CXX=clang++ LD=clang++` on recent Debian or Ubuntu
- [ ] `mymanualchecks.sh`
- [ ] `mycppcheck.sh` no alarming warning?
- [ ] `mymakeclang.sh` no alarming error/warning ?
- [ ] `mystandalone_makes.sh` compile all standalone modes (linux only)
- [ ] [Travis](https://travis-ci.org/github/RfidResearchGroup/proxmark3/builds) green (linux noqt / osx+qt ; with makefile (w/wo bt) / with cmake)
- [ ] [Appveyor](https://ci.appveyor.com/project/RfidResearchGroup/proxmark3/history) green (PS)
# OS compilation and tests
```bash
make clean && make -j PLATFORM=PM3OTHER && tools/pm3test.sh
make clean && make -j PLATFORM=PM3RDV4 && tools/pm3test.sh
make clean && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && tools/pm3test.sh
make install; pushd /tmp; proxmark3 -c 'data load em4x05.pm3;lf search 1'; popd; make uninstall
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3OTHER && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
( cd client; rm -rf build; mkdir build;cd build;cmake .. && make -j PLATFORM=PM3RDV4 PLATFORM_EXTRAS=BTADDON && PM3BIN=./proxmark3 ../../tools/pm3test.sh client )
```
- [ ] RPI Zero
- [ ] WSL
- [ ] PSv3.3
- [ ] Kali
- [ ] Debian
- [ ] Ubuntu20
- [ ] ParrotOS
- [ ] Fedora
- [ ] OpenSuse
- [ ] OSX
- [ ] Android
- [ ] Termux
+5
View File
@@ -3,6 +3,11 @@ 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]
- Add `hf 14a config` to deal with badly configured cards: invalid ATQA/BCC/SAK (@doegox)"
- Mikron JSC Russia Ultralight EV1 41 pages tag type support (@McEloff)
- Add test for Ultralight gen2 magic 'hf search' (@McEloff)
- Add test for Ultralight EV1 gen2 magic 'hf search' (@McEloff)
- Added `hf mf gen3*`magic gen 3 card operations (@McEloff)
- Readded verichip command which seems missing (@iceman1001)
- Fix missing t55x7 config block detection (@iceman1001)
- Fix missing define on proxspace (@mwalker33)
+4 -1
View File
@@ -38,6 +38,9 @@ define KNOWN_STANDALONE_DEFINITIONS
| HF_14ASNIFF | 14a sniff to flashmem |
| (RDV4 only) | |
+----------------------------------------------------------+
| HF_AVEFUL | Mifare ultralight read/simulation |
| | - Ave Ozkal |
+----------------------------------------------------------+
| HF_BOG | 14a sniff with ULC/ULEV1/NTAG auth |
| (RDV4 only) | storing in flashmem - Bogito |
+----------------------------------------------------------+
@@ -62,7 +65,7 @@ define KNOWN_STANDALONE_DEFINITIONS
endef
STANDALONE_MODES := LF_SKELETON LF_EM4100EMUL LF_EM4100RSWB LF_EM4100RWC LF_HIDBRUTE LF_ICEHID LF_PROXBRUTE LF_SAMYRUN
STANDALONE_MODES += HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
STANDALONE_MODES += HF_14ASNIFF HF_AVEFUL HF_BOG HF_COLIN HF_ICECLASS HF_LEGIC HF_MATTYRUN HF_MSDSAL HF_YOUNG
STANDALONE_MODES_REQ_SMARTCARD :=
STANDALONE_MODES_REQ_FLASH := LF_ICEHID HF_14ASNIFF HF_BOG HF_COLIN HF_ICECLASS
ifneq ($(filter $(STANDALONE),$(STANDALONE_MODES)),)
+4
View File
@@ -37,6 +37,10 @@ endif
ifneq (,$(findstring WITH_STANDALONE_HF_14ASNIFF,$(APP_CFLAGS)))
SRC_STANDALONE = hf_14asniff.c
endif
# WITH_STANDALONE_HF_AVEFUL
ifneq (,$(findstring WITH_STANDALONE_HF_AVEFUL,$(APP_CFLAGS)))
SRC_STANDALONE = hf_aveful.c
endif
# WITH_STANDALONE_LF_ICEHID
ifneq (,$(findstring WITH_STANDALONE_LF_ICEHID,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icehid.c
+127
View File
@@ -0,0 +1,127 @@
//-----------------------------------------------------------------------------
// A. Ozkal, 2020
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
//-----------------------------------------------------------------------------
// main code for HF Mifare Ultralight read/simulation by Ave Ozkal
//-----------------------------------------------------------------------------
// Several parts of this code is based on code by Craig Young from HF_YOUNG
// This code does not:
// - Account for cards with authentication (MFU EV1 etc)
// - Determine if cards have block count that's not the same as the BLOCKS def
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "appmain.h"
#include "fpgaloader.h"
#include "util.h"
#include "dbprint.h"
#include "ticks.h" // SpinDelay
#include "mifareutil.h"
#include "iso14443a.h"
#define BLOCKS 16
#define SAK 0x00
#define ATQA0 0x44
#define ATQA1 0x00
#define STATE_SEARCH 0
#define STATE_READ 1
#define STATE_EMUL 2
typedef struct {
uint8_t uid[10];
uint8_t uidlen;
uint8_t atqa[2];
uint8_t sak;
} PACKED card_clone_t;
void ModInfo(void) {
DbpString(" HF Mifare Ultralight read/simulation by Ave Ozkal");
}
void RunMod(void) {
StandAloneMode();
Dbprintf("AveFUL (MF Ultralight read/emul) started");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// the main loop for your standalone mode
for (;;) {
WDT_HIT();
// exit from RunMod, send a usbcommand.
if (data_available()) break;
iso14a_card_select_t card;
SpinDelay(500);
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// 0 = search, 1 = read, 2 = emul
int state = STATE_SEARCH;
DbpString("Scanning...");
for (;;) {
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
if (button_pressed != BUTTON_NO_CLICK || data_available())
break;
else if (state == STATE_SEARCH) {
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, true)) {
continue;
} else {
if (card.sak == SAK && card.atqa[0] == ATQA0 && card.atqa[1] == ATQA1 && card.uidlen == 7) {
DbpString("Found ultralight with UID: ");
Dbhexdump(card.uidlen, card.uid, 0);
state = STATE_READ;
} else {
DbpString("Found non-ultralight card, ignoring.");
}
}
} else if (state == STATE_READ) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
iso14443a_select_card(NULL, NULL, NULL, true, 0, true);
bool read_successful = true;
Dbprintf("Contents:");
for (int i = 0; i < BLOCKS; i++) {
uint8_t dataout[4] = {0x00};
if (mifare_ultra_readblock(i, dataout)) {
// If there's an error reading, go back to search state
read_successful = false;
break;
}
// We're skipping 14 blocks (56 bytes) here, as that "[...] has version/signature/counter data here" according to comments on dumptoemul-mfu
// When converting a bin, it's almost all 0 other than one 0x0F byte, and functionality seems to be unaffected if that byte is set to 0x00.
emlSetMem_xt(dataout, 14 + i, 1, 4);
Dbhexdump(4, dataout, 0);
}
if (read_successful) {
Dbprintf("Successfully loaded into emulator memory...");
state = STATE_EMUL;
} else {
Dbprintf("Read failure, going back to search state.");
state = STATE_SEARCH;
}
} else if (state == 2) {
uint8_t flags = FLAG_7B_UID_IN_DATA;
Dbprintf("Starting simulation, press pm3-button to stop and go back to search state.");
SimulateIso14443aTag(2, flags, card.uid);
// Go back to search state if user presses pm3-button
state = STATE_SEARCH;
}
}
}
DbpString("exiting");
LEDsoff();
}
+9
View File
@@ -7,6 +7,15 @@
//-----------------------------------------------------------------------------
// main code for hf_iceclass by Iceman
//-----------------------------------------------------------------------------
//
// Created for the live streamed talk 'DEFCON 28 Wireless Village-Omikron and Iceman - Ghosting the PACS-man: New Tools and Techniques'
// https://www.youtube.com/watch?v=ghiHXK4GEzE
//
// I created a youtube video demostrating the HF_ICECLASS standalone mode
// https://youtu.be/w_1GnAscNIU
//
//
#include "standalone.h" // standalone definitions
#include "proxmark3_arm.h"
#include "appmain.h"
+2 -2
View File
@@ -22,7 +22,6 @@
#include "legic.h" // legic_card_select_t struct
#include "spiffs.h" // flashmem
/*
* To list all dump files from flash:
*
@@ -106,6 +105,7 @@ void RunMod(void) {
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
Dbprintf("[=] >> HF Legic Prime Read/Simulate Started <<");
DbpString("[=] press and HOLD button to exit standalone mode");
for (;;) {
WDT_HIT();
@@ -163,7 +163,7 @@ void RunMod(void) {
}
// The read data is migrated to a MIM1024 card
LegicRfSimulate(ct);
LegicRfSimulate(ct, false);
}
}
+58 -23
View File
@@ -355,8 +355,11 @@ static void SendStatus(void) {
I2C_print_status();
#endif
#ifdef WITH_LF
printConfig(); // LF Sampling config
printLFConfig(); // LF Sampling config
printT55xxConfig(); // LF T55XX Config
#endif
#ifdef WITH_ISO14443a
printHf14aConfig(); // HF 14a config
#endif
printConnSpeed();
DbpString(_CYAN_("Various"));
@@ -739,7 +742,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_LF_SAMPLING_PRINT_CONFIG: {
printConfig();
printLFConfig();
break;
}
case CMD_LF_SAMPLING_GET_CONFIG: {
@@ -756,7 +759,7 @@ static void PacketReceived(PacketCommandNG *packet) {
}
case CMD_LF_ACQ_RAW_ADC: {
struct p {
uint8_t verbose;
bool verbose;
uint32_t samples;
} PACKED;
struct p *payload = (struct p *)packet->data.asBytes;
@@ -1058,14 +1061,19 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t uid[8];
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
SetTag15693Uid(payload->uid);
break;
SetTag15693Uid(payload->uid);
break;
}
#endif
#ifdef WITH_LEGICRF
case CMD_HF_LEGIC_SIMULATE: {
LegicRfSimulate(packet->oldarg[0]);
struct p {
uint8_t tagtype;
bool send_reply;
} PACKED;
struct p *payload = (struct p *) packet->data.asBytes;
LegicRfSimulate(payload->tagtype, payload->send_reply);
break;
}
case CMD_HF_LEGIC_WRITER: {
@@ -1140,6 +1148,21 @@ static void PacketReceived(PacketCommandNG *packet) {
#endif
#ifdef WITH_ISO14443a
case CMD_HF_ISO14443A_PRINT_CONFIG: {
printHf14aConfig();
break;
}
case CMD_HF_ISO14443A_GET_CONFIG: {
hf14a_config *hf14aconfig = getHf14aConfig();
reply_ng(CMD_HF_ISO14443A_GET_CONFIG, PM3_SUCCESS, (uint8_t *)hf14aconfig, sizeof(hf14a_config));
break;
}
case CMD_HF_ISO14443A_SET_CONFIG: {
hf14a_config c;
memcpy(&c, packet->data.asBytes, sizeof(hf14a_config));
setHf14aConfig(&c);
break;
}
case CMD_HF_ISO14443A_SNIFF: {
SniffIso14443a(packet->data.asBytes[0]);
reply_ng(CMD_HF_ISO14443A_SNIFF, PM3_SUCCESS, NULL, 0);
@@ -1214,6 +1237,10 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareUWriteBlock(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break;
}
case CMD_HF_MIFAREU_WRITEBL_COMPAT: {
MifareUWriteBlockCompat(packet->oldarg[0], packet->oldarg[1], packet->data.asBytes);
break;
}
case CMD_HF_MIFARE_ACQ_ENCRYPTED_NONCES: {
MifareAcquireEncryptedNonces(packet->oldarg[0], packet->oldarg[1], packet->oldarg[2], packet->data.asBytes);
break;
@@ -1248,7 +1275,7 @@ static void PacketReceived(PacketCommandNG *packet) {
break;
}
case CMD_HF_MIFARE_CHKKEYS: {
MifareChkKeys(packet->data.asBytes);
MifareChkKeys(packet->data.asBytes, false);
break;
}
case CMD_HF_MIFARE_CHKKEYS_FAST: {
@@ -1318,6 +1345,19 @@ static void PacketReceived(PacketCommandNG *packet) {
MifareCIdent();
break;
}
// Gen 3 magic cards
case CMD_HF_MIFARE_GEN3UID: {
MifareGen3UID(packet->oldarg[0], packet->data.asBytes);
break;
}
case CMD_HF_MIFARE_GEN3BLK: {
MifareGen3Blk(packet->oldarg[0], packet->data.asBytes);
break;
}
case CMD_HF_MIFARE_GEN3FREEZ: {
MifareGen3Freez();
break;
}
// mifare sniffer
// case CMD_HF_MIFARE_SNIFF: {
// SniffMifare(packet->oldarg[0]);
@@ -1806,12 +1846,9 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs dump : %s", filename);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs dump : %s", filename);
//uint32_t size = 0;
//rdv40_spiffs_stat((char *)filename, (uint32_t *)size,RDV40_SPIFFS_SAFETY_SAFE);
uint32_t size = packet->oldarg[1];
//uint8_t buff[size];
uint8_t *buff = BigBuf_malloc(size);
rdv40_spiffs_read_as_filetype((char *)filename, (uint8_t *)buff, size, RDV40_SPIFFS_SAFETY_SAFE);
@@ -1836,7 +1873,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs STAT : %s", filename);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs STAT : %s", filename);
int changed = rdv40_spiffs_lazy_mount();
uint32_t size = size_in_spiffs((char *)filename);
if (changed) rdv40_spiffs_lazy_unmount();
@@ -1849,7 +1886,7 @@ static void PacketReceived(PacketCommandNG *packet) {
uint8_t filename[32];
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs REMOVE : %s", filename);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("Filename received for spiffs REMOVE : %s", filename);
rdv40_spiffs_remove((char *) filename, RDV40_SPIFFS_SAFETY_SAFE);
LED_B_OFF();
break;
@@ -1864,9 +1901,9 @@ static void PacketReceived(PacketCommandNG *packet) {
strncpy((char *)src, token, sizeof(src) - 1);
token = strtok(NULL, ",");
strncpy((char *)dest, token, sizeof(dest) - 1);
if (DBGLEVEL > 1) {
Dbprintf("> Filename received as source for spiffs RENAME : %s", src);
Dbprintf("> Filename received as destination for spiffs RENAME : %s", dest);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs RENAME : %s", src);
Dbprintf("Filename received as destination for spiffs RENAME : %s", dest);
}
rdv40_spiffs_rename((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
LED_B_OFF();
@@ -1882,9 +1919,9 @@ static void PacketReceived(PacketCommandNG *packet) {
strncpy((char *)src, token, sizeof(src) - 1);
token = strtok(NULL, ",");
strncpy((char *)dest, token, sizeof(dest) - 1);
if (DBGLEVEL > 1) {
Dbprintf("> Filename received as source for spiffs COPY : %s", src);
Dbprintf("> Filename received as destination for spiffs COPY : %s", dest);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("Filename received as source for spiffs COPY : %s", src);
Dbprintf("Filename received as destination for spiffs COPY : %s", dest);
}
rdv40_spiffs_copy((char *) src, (char *)dest, RDV40_SPIFFS_SAFETY_SAFE);
LED_B_OFF();
@@ -1896,14 +1933,12 @@ static void PacketReceived(PacketCommandNG *packet) {
uint32_t append = packet->oldarg[0];
uint32_t size = packet->oldarg[1];
uint8_t *data = packet->data.asBytes;
//rdv40_spiffs_lazy_mount();
uint8_t *pfilename = packet->data.asBytes;
memcpy(filename, pfilename, SPIFFS_OBJ_NAME_LEN);
data += SPIFFS_OBJ_NAME_LEN;
if (DBGLEVEL > 1) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
if (DBGLEVEL >= DBG_DEBUG) Dbprintf("> Filename received for spiffs WRITE : %s with APPEND SET TO : %d", filename, append);
if (!append) {
rdv40_spiffs_write((char *) filename, (uint8_t *)data, size, RDV40_SPIFFS_SAFETY_SAFE);
} else {
+31 -28
View File
@@ -90,6 +90,7 @@ static em4x50_tag_t tag = {
#define EM4X50_COMMAND_WRITE_PASSWORD 0x11
#define EM4X50_COMMAND_SELECTIVE_READ 0x0A
#define EM4X50_COMMAND_TIMEOUT 5000
#define FPGA_TIMER_0 0
int gHigh = 0;
@@ -99,6 +100,8 @@ int gLow = 0;
static void init_tag(void) {
// iceman: memset(tag.sectors, 0x00, sizeof));
// initialize global tag structure
for (int i = 0; i < 34; i++)
for (int j = 0; j < 7; j++)
@@ -185,10 +188,9 @@ static void em4x50_setup_read(void) {
// 50ms for the resonant antenna to settle.
SpinDelay(50);
// Now set up the SSC to get the ADC samples that are now streaming at us.
FpgaSetupSsc(FPGA_MAJOR_MODE_LF_READER);
// start a 1.5ticks is 1us
StartTicks();
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_DIVISOR_125);
@@ -255,10 +257,9 @@ static bool get_signalproperties(void) {
signal_found = true;
break;
}
}
if (!signal_found)
if (signal_found == false)
return false;
// calculate mean maximum value of 32 periods, each period has a length of
@@ -312,35 +313,46 @@ static int get_next_bit(void) {
static uint32_t get_pulse_length(void) {
// Dbprintf( _CYAN_("4x50 get_pulse_length A") );
int32_t timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
// iterates pulse length (low -> high -> low)
uint8_t sample = 0;
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
while (sample > gLow)
while (sample > gLow && (timeout--)) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
}
if (timeout == 0)
return 0;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG;
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
while (sample < gHigh)
while (sample < gHigh && (timeout--)) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
}
while (sample > gLow)
if (timeout == 0)
return 0;
timeout = (T0 * 3 * EM4X50_T_TAG_FULL_PERIOD);
while (sample > gLow && (timeout--)) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
}
if (timeout == 0)
return 0;
return (uint32_t)AT91C_BASE_TC1->TC_CV;
}
static bool check_pulse_length(uint32_t pl, int length) {
// check if pulse length <pl> corresponds to given length <length>
if ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) &
(pl <= T0 * (length + EM4X50_TAG_TOLERANCE)))
return true;
else
return false;
return ((pl >= T0 * (length - EM4X50_TAG_TOLERANCE)) & (pl <= T0 * (length + EM4X50_TAG_TOLERANCE)));
}
static void em4x50_send_bit(int bit) {
@@ -428,13 +440,9 @@ static bool find_single_listen_window(void) {
// listen window found
return true;
}
} else {
cnt_pulses++;
}
cnt_pulses++;
}
return false;
@@ -494,7 +502,6 @@ static bool find_double_listen_window(bool bcommand) {
return true;
}
}
} else {
cnt_pulses++;
}
}
@@ -506,9 +513,7 @@ static bool find_em4x50_tag(void) {
// function is used to check wether a tag on the proxmark is an
// EM4x50 tag or not -> speed up "lf search" process
return (find_single_listen_window());
return find_single_listen_window();
}
static bool request_receive_mode(void) {
@@ -516,9 +521,7 @@ static bool request_receive_mode(void) {
// To issue a command we have to find a listen window first.
// Because identification and sychronization at the same time is not
// possible when using pulse lengths a double listen window is used.
bool bcommand = true;
return find_double_listen_window(bcommand);
}
+8 -8
View File
@@ -229,7 +229,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
sizeof(apdu_select_binary_cardaccess),
response_apdu,
sizeof(response_apdu)
);
);
if (rapdu_length < 6
|| response_apdu[rapdu_length - 4] != 0x90
@@ -243,7 +243,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
sizeof(apdu_read_binary),
response_apdu,
sizeof(response_apdu)
);
);
if (rapdu_length <= 6
|| response_apdu[rapdu_length - 4] != 0x90
@@ -325,11 +325,11 @@ void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
// now get the nonce
uint8_t nonce[256] = {0};
struct p {
uint32_t m;
} PACKED;
struct p *packet = (struct p*)c->data.asBytes;
struct p *packet = (struct p *)c->data.asBytes;
func_return = EPA_PACE_Get_Nonce(packet->m, nonce);
// check if the command succeeded
@@ -359,7 +359,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
// copy the constant part
memcpy(apdu, apdu_general_authenticate_pace_get_nonce, sizeof(apdu_general_authenticate_pace_get_nonce));
// append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU
apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4;
@@ -444,8 +444,8 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
// check if the command succeeded
if (send_return != 6)
// && response_apdu[send_return - 4] != 0x90
// || response_apdu[send_return - 3] != 0x00)
{
// || response_apdu[send_return - 3] != 0x00)
{
return 1;
}
return 0;
@@ -500,7 +500,7 @@ void EPA_PACE_Replay(PacketCommandNG *c) {
apdu_lengths_replay[i],
response_apdu,
sizeof(response_apdu)
);
);
timings[i] = GetCountUS();
// every step but the last one should succeed
if (i < ARRAYLEN(apdu_lengths_replay) - 1
+108 -20
View File
@@ -122,6 +122,51 @@ static uint32_t LastProxToAirDuration;
#define SEC_Y 0x00
#define SEC_Z 0xc0
/*
Default HF 14a config is set to:
forceanticol = 0 (auto)
forcebcc = 0 (expect valid BCC)
forcecl2 = 0 (auto)
forcecl3 = 0 (auto)
forcerats = 0 (auto)
*/
static hf14a_config hf14aconfig = { 0, 0, 0, 0, 0 } ;
void printHf14aConfig(void) {
DbpString(_CYAN_("HF 14a config"));
Dbprintf("[a] Anticol override......%s%s%s", (hf14aconfig.forceanticol == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forceanticol == 1) ? _RED_("Yes: Always do anticol") : "", (hf14aconfig.forceanticol == 2) ? _RED_("Yes: Always skip anticol") : "");
Dbprintf("[b] BCC override..........%s%s%s", (hf14aconfig.forcebcc == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcebcc == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcebcc == 2) ? _RED_("Yes: Always use card BCC") : "");
Dbprintf("[2] CL2 override..........%s%s%s", (hf14aconfig.forcecl2 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl2 == 1) ? _RED_("Yes: Always do CL2") : "", (hf14aconfig.forcecl2 == 2) ? _RED_("Yes: Always skip CL2") : "");
Dbprintf("[3] CL3 override..........%s%s%s", (hf14aconfig.forcecl3 == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcecl3 == 1) ? _RED_("Yes: Always do CL3") : "", (hf14aconfig.forcecl3 == 2) ? _RED_("Yes: Always skip CL3") : "");
Dbprintf("[r] RATS override.........%s%s%s", (hf14aconfig.forcerats == 0) ? _GREEN_("No") " (follow standard)" : "", (hf14aconfig.forcerats == 1) ? _RED_("Yes: Always do RATS") : "", (hf14aconfig.forcerats == 2) ? _RED_("Yes: Always skip RATS") : "");
}
/**
* Called from the USB-handler to set the 14a configuration
* The 14a config is used for card selection sequence.
*
* Values set to '-1' implies no change
* @brief setSamplingConfig
* @param sc
*/
void setHf14aConfig(hf14a_config *hc) {
if ((hc->forceanticol >= 0) && (hc->forceanticol <= 2))
hf14aconfig.forceanticol = hc->forceanticol;
if ((hc->forcebcc >= 0) && (hc->forcebcc <= 2))
hf14aconfig.forcebcc = hc->forcebcc;
if ((hc->forcecl2 >= 0) && (hc->forcecl2 <= 2))
hf14aconfig.forcecl2 = hc->forcecl2;
if ((hc->forcecl3 >= 0) && (hc->forcecl3 <= 2))
hf14aconfig.forcecl3 = hc->forcecl3;
if ((hc->forcerats >= 0) && (hc->forcerats <= 2))
hf14aconfig.forcerats = hc->forcerats;
}
hf14a_config *getHf14aConfig(void) {
return &hf14aconfig;
}
void iso14a_set_trigger(bool enable) {
g_trigger = enable;
}
@@ -1832,8 +1877,8 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par) {
for (;;) {
WDT_HIT();
if (check == 1000) {
if (BUTTON_PRESS() || data_available())
if (check == 2000) {
if (BUTTON_PRESS())
return 1;
check = 0;
}
@@ -1959,7 +2004,6 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) {
b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
(void)b;
}
if (BUTTON_PRESS()) break;
}
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
@@ -2336,7 +2380,8 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller
uint8_t resp_par[MAX_PARITY_SIZE] = {0};
uint8_t sak = 0x04; // cascade uid
uint8_t sak; // cascade uid
bool do_cascade = 1;
int cascade_level = 0;
if (p_card) {
@@ -2360,26 +2405,32 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
memset(uid_ptr, 0, 10);
}
// check for proprietary anticollision:
if ((resp[0] & 0x1F) == 0) return 3;
if (hf14aconfig.forceanticol == 0) {
// check for proprietary anticollision:
if ((resp[0] & 0x1F) == 0) return 3;
} else if (hf14aconfig.forceanticol == 2) {
return 3; // force skipping anticol
} // else force executing
// OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in
// which case we need to make a cascade 2 request and select - this is a long UID
// While the UID is not complete, the 3nd bit (from the right) is set in the SAK.
for (; sak & 0x04; cascade_level++) {
for (; do_cascade; cascade_level++) {
// SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97)
uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x20 };
uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
uint8_t uid_resp[4] = {0};
uint8_t uid_resp[5] = {0}; // UID + original BCC
sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2;
if (anticollision) {
// SELECT_ALL
ReaderTransmit(sel_all, sizeof(sel_all), NULL);
if (!ReaderReceive(resp, resp_par)) return 0;
if (!ReaderReceive(resp, resp_par)) {
Dbprintf("Card didn't answer to CL%i select all", cascade_level + 1);
return 0;
}
if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit
memset(uid_resp, 0, 4);
memset(uid_resp, 0, 5);
uint16_t uid_resp_bits = 0;
uint16_t collision_answer_offset = 0;
// anti-collision-loop:
@@ -2391,7 +2442,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
}
uid_resp[uid_resp_bits / 8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position
uid_resp_bits++;
// construct anticollosion command:
// construct anticollision command:
sel_uid[1] = ((2 + uid_resp_bits / 8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits
for (uint16_t i = 0; i <= uid_resp_bits / 8; i++) {
sel_uid[2 + i] = uid_resp[i];
@@ -2407,7 +2458,7 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
}
} else { // no collision, use the response to SELECT_ALL as current uid
memcpy(uid_resp, resp, 4);
memcpy(uid_resp, resp, 5); // UID + original BCC
}
} else {
@@ -2426,18 +2477,51 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
// Construct SELECT UID command
sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC)
memcpy(sel_uid + 2, uid_resp, 4); // the UID received during anticollision, or the provided UID
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
if (anticollision) {
memcpy(sel_uid + 2, uid_resp, 5); // the UID received during anticollision with original BCC
uint8_t bcc = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate BCC
if (sel_uid[6] != bcc) {
Dbprintf("BCC%d incorrect, got 0x%02x, expected 0x%02x", cascade_level, sel_uid[6], bcc);
if (hf14aconfig.forcebcc == 0) {
Dbprintf("Aborting");
return 0;
} else if (hf14aconfig.forcebcc == 1) {
sel_uid[6] = bcc;
} // else use card BCC
Dbprintf("Using BCC=" _YELLOW_("0x%02x") " to perform anticollision", sel_uid[6]);
}
} else {
memcpy(sel_uid + 2, uid_resp, 4); // the provided UID
sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC
}
AddCrc14A(sel_uid, 7); // calculate and add CRC
ReaderTransmit(sel_uid, sizeof(sel_uid), NULL);
// Receive the SAK
if (!ReaderReceive(resp, resp_par)) return 0;
if (!ReaderReceive(resp, resp_par)) {
Dbprintf("Card didn't answer to select");
return 0;
}
sak = resp[0];
// Test if more parts of the uid are coming
if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) {
do_cascade = (((sak & 0x04) /* && uid_resp[0] == 0x88 */) > 0);
if (cascade_level == 0) {
if (hf14aconfig.forcecl2 == 2) {
do_cascade = false;
} else if (hf14aconfig.forcecl2 == 1) {
do_cascade = true;
} // else 0==auto
} else if (cascade_level == 1) {
if (hf14aconfig.forcecl3 == 2) {
do_cascade = false;
} else if (hf14aconfig.forcecl3 == 1) {
do_cascade = true;
} // else 0==auto
}
if (do_cascade) {
// Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of:
// http://www.nxp.com/documents/application_note/AN10927.pdf
uid_resp[0] = uid_resp[1];
@@ -2459,8 +2543,12 @@ int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32
p_card->sak = sak;
}
// PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0)
if ((sak & 0x20) == 0) return 2;
if (hf14aconfig.forcerats == 0) {
// PICC compliant with iso14443a-4 ---> (SAK & 0x20 != 0)
if ((sak & 0x20) == 0) return 2;
} else if (hf14aconfig.forcerats == 2) {
return 2;
} // else force RATS
// RATS, Request for answer to select
if (!no_rats) {
+3
View File
@@ -96,6 +96,9 @@ typedef struct {
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
void printHf14aConfig(void);
void setHf14aConfig(hf14a_config *hc);
hf14a_config *getHf14aConfig(void);
void iso14a_set_timeout(uint32_t timeout);
uint32_t iso14a_get_timeout(void);
+158 -158
View File
File diff suppressed because it is too large Load Diff
+9 -10
View File
@@ -84,7 +84,7 @@
#define ISO15693_READER_TIMEOUT 330 // 330/212kHz = 1558us
#define ISO15693_READER_TIMEOUT_WRITE 4700 // 4700/212kHz = 22ms, nominal 20ms
// iceman: This defines below exists in the header file, just here for my easy reading
// iceman: This defines below exists in the header file, just here for my easy reading
// Delays in SSP_CLK ticks.
// SSP_CLK runs at 13,56MHz / 32 = 423.75kHz when simulating a tag
//#define DELAY_ISO15693_VCD_TO_VICC_SIM 132 // 132/423.75kHz = 311.5us from end of command EOF to start of tag response
@@ -700,7 +700,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dma->buf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
WDT_HIT();
if (BUTTON_PRESS()) {
DbpString("stopped");
@@ -725,7 +725,7 @@ int GetIso15693AnswerFromTag(uint8_t *response, uint16_t max_len, uint16_t timeo
// timeout
if (samples > timeout && dt->state < STATE_TAG_RECEIVING_DATA) {
ret = -3;
ret = -3;
break;
}
@@ -1715,7 +1715,6 @@ void SimTagIso15693(uint8_t *uid) {
uint32_t reader_eof_time = 0;
int cmd_len = GetIso15693CommandFromReader(cmd, sizeof(cmd), &reader_eof_time);
if (cmd_len < 0) {
Dbprintf("button pressed, exiting");
button_pressed = true;
exit_loop = true;
break;
@@ -1736,7 +1735,7 @@ void SimTagIso15693(uint8_t *uid) {
if (button_pressed)
DbpString("button pressed");
reply_ng(CMD_HF_ISO15693_SIMULATE, PM3_SUCCESS, NULL, 0);
}
@@ -1881,7 +1880,7 @@ SLIx functions from official master forks.
void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
LED_A_ON();
uint8_t cmd_inventory[] = {ISO15693_REQ_DATARATE_HIGH | ISO15693_REQ_INVENTORY | ISO15693_REQINV_SLOT1, 0x01, 0x00, 0x00, 0x00 };
uint8_t cmd_get_rnd[] = {ISO15693_REQ_DATARATE_HIGH, 0xB2, 0x04, 0x00, 0x00 };
uint8_t cmd_set_pass[] = {ISO15693_REQ_DATARATE_HIGH, 0xB3, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
@@ -1893,7 +1892,7 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
uint32_t start_time = 0;
bool done = false;
// setup 'get random number' command
// setup 'get random number' command
crc = Iso15693Crc(cmd_get_rnd, 3);
cmd_get_rnd[3] = crc & 0xff;
cmd_get_rnd[4] = crc >> 8;
@@ -1901,7 +1900,7 @@ void LockPassSlixIso15693(uint32_t pass_id, uint32_t password) {
Dbprintf("LockPass: Press button lock password, long-press to terminate.");
while (!done) {
LED_D_ON();
switch(BUTTON_HELD(1000)) {
case BUTTON_SINGLE_CLICK:
@@ -2033,7 +2032,7 @@ void SetTag15693Uid(uint8_t *uid) {
SendDataTag(cmd[i], sizeof(cmd[i]), i == 0 ? true : false, true, recvbuf, sizeof(recvbuf), start_time, ISO15693_READER_TIMEOUT_WRITE, &eof_time);
start_time = eof_time + DELAY_ISO15693_VICC_TO_VCD_READER;
}
reply_ng(CMD_HF_ISO15693_CSETUID, PM3_SUCCESS, NULL, 0);
switch_off();
}
}
+51 -46
View File
@@ -64,11 +64,11 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
//-----------------------------------------------------------------------------
// I/O interface abstraction (FPGA -> ARM)
//-----------------------------------------------------------------------------
static uint8_t rx_byte_from_fpga(void) {
static uint16_t rx_frame_from_fpga(void) {
for (;;) {
WDT_HIT();
// wait for byte be become available in rx holding register
// wait for frame be become available in rx holding register
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
return AT91C_BASE_SSC->SSC_RHR;
}
@@ -76,48 +76,53 @@ static uint8_t rx_byte_from_fpga(void) {
}
//-----------------------------------------------------------------------------
// Demodulation
// Demodulation (Reader)
//-----------------------------------------------------------------------------
// Returns am aproximated power measurement
// Returns a demedulated bit
//
// The FPGA running on the xcorrelation kernel samples the subcarrier at ~3 MHz.
// The kernel was initialy designed to receive BSPK/2-PSK. Hance, it reports an
// I/Q pair every 18.9us (8 bits i and 8 bits q).
// The FPGA running xcorrelation samples the subcarrier at ~13.56 MHz. The mode
// was initialy designed to receive BSPK/2-PSK. Hance, it reports an I/Q pair
// every 4.7us (8 bits i and 8 bits q).
//
// The subcarrier amplitude can be calculated using Pythagoras sqrt(i^2 + q^2).
// To reduce CPU time the amplitude is approximated by using linear functions:
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
//
// Note: The SSC receiver is never synchronized the calculation may be performed
// on a i/q pair from two subsequent correlations, but does not matter.
// Note: inlining this function would fail with -Os
static int32_t sample_power(void) {
int32_t q = (int8_t)rx_byte_from_fpga();
q = ABS(q);
int32_t i = (int8_t)rx_byte_from_fpga();
i = ABS(i);
return MAX(i, q) + (MIN(i, q) >> 1);
}
// Returns a demedulated bit
// The bit time is 99.1us (21 I/Q pairs). The receiver skips the first 5 samples
// and averages the next (most stable) 8 samples. The final 8 samples are dropped
// also.
//
// An aproximated power measurement is available every 18.9us. The bit time
// is 100us. The code samples 5 times and uses the last (most stable) sample.
// The demodulated should be alligned to the bit period by the caller. This is
// done in rx_bit and rx_ack.
//
// Note: The demodulator would be drifting (18.9us * 5 != 100us), rx_frame
// has a delay loop that aligns rx_bit calls to the TAG tx timeslots.
//
// Note: inlining this function would fail with -Os
static bool rx_bit(void) {
int32_t power;
int32_t sum_cq = 0;
int32_t sum_ci = 0;
// skip first 5 I/Q pairs
for (size_t i = 0; i < 5; ++i) {
power = sample_power();
(void)rx_frame_from_fpga();
}
return (power > INPUT_THRESHOLD);
// sample next 8 I/Q pairs
for (uint8_t i = 0; i < 8; ++i) {
uint16_t iq = rx_frame_from_fpga();
int8_t ci = (int8_t)(iq >> 8);
int8_t cq = (int8_t)(iq & 0xff);
sum_ci += ci;
sum_cq += cq;
}
// calculate power
int32_t power = (MAX(ABS(sum_ci), ABS(sum_cq)) + (MIN(ABS(sum_ci), ABS(sum_cq)) >> 1));
// compare average (power / 8) to threshold
return ((power >> 3) > INPUT_THRESHOLD);
}
//-----------------------------------------------------------------------------
@@ -131,18 +136,18 @@ static bool rx_bit(void) {
static void tx_bit(bool bit) {
// insert pause
LOW(GPIO_SSC_DOUT);
HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
// return to high, wait for bit periode to end
// return to carrier on, wait for bit periode to end
LOW(GPIO_SSC_DOUT);
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
}
//-----------------------------------------------------------------------------
// Frame Handling
// Frame Handling (Reader)
//
// The LEGIC RF protocol from card to reader does not include explicit frame
// start/stop information or length information. The reader must know beforehand
@@ -169,10 +174,10 @@ static void tx_frame(uint32_t frame, uint8_t len) {
};
// add pause to mark end of the frame
LOW(GPIO_SSC_DOUT);
HIGH(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE;
while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT);
LOW(GPIO_SSC_DOUT);
// log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
@@ -267,12 +272,12 @@ static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
p_card->cmdsize = 0;
p_card->addrsize = 0;
p_card->cardsize = 0;
return 2;
return PM3_ESOFT;
}
return 0;
return PM3_SUCCESS;
}
static void init_reader(bool clear_mem) {
static void init_reader(void) {
// configure FPGA
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER | FPGA_HF_READER_SUBCARRIER_212_KHZ | FPGA_HF_READER_MODE_RECEIVE_IQ);
@@ -285,7 +290,7 @@ static void init_reader(bool clear_mem) {
// re-claim GPIO_SSC_DOUT as GPIO and enable output
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
HIGH(GPIO_SSC_DOUT);
LOW(GPIO_SSC_DOUT);
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
legic_mem = BigBuf_get_EM_addr();
@@ -406,11 +411,11 @@ legic_card_select_t *getLegicCardInfo(void) {
void LegicRfInfo(void) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
uint8_t card_type = setup_phase(0x01);
if (init_card(card_type, &card) != 0) {
if (init_card(card_type, &card) != PM3_SUCCESS) {
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
@@ -446,11 +451,11 @@ int LegicRfReaderEx(uint16_t offset, uint16_t len, uint8_t iv) {
int res = PM3_SUCCESS;
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) {
if (init_card(card_type, &card) != PM3_SUCCESS) {
res = PM3_ESOFT;
goto OUT;
}
@@ -481,11 +486,11 @@ OUT:
void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// establish shared secret and detect card type
uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) {
if (init_card(card_type, &card) != PM3_SUCCESS) {
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
@@ -518,7 +523,7 @@ OUT:
void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
// configure ARM and FPGA
init_reader(false);
init_reader();
// uid is not writeable
if (offset <= WRITE_LOWERLIMIT) {
@@ -528,7 +533,7 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
// establish shared secret and detect card type
uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) {
if (init_card(card_type, &card) != PM3_SUCCESS) {
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
}
@@ -539,8 +544,8 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
}
// write in reverse order, only then is DCF (decremental field) writable
while (len-- > 0 && !BUTTON_PRESS()) {
if (!write_byte(len + offset, data[len], card.addrsize)) {
while (len-- > 0 && BUTTON_PRESS() == false) {
if (write_byte(len + offset, data[len], card.addrsize) == false) {
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT;
+37 -11
View File
@@ -15,7 +15,7 @@
#include "crc.h" /* legic crc-4 */
#include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */
#include "cmd.h"
#include "proxmark3_arm.h"
#include "BigBuf.h"
#include "fpgaloader.h"
@@ -295,9 +295,9 @@ static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
p_card->cmdsize = 0;
p_card->addrsize = 0;
p_card->cardsize = 0;
return 2;
return PM3_ESOFT;
}
return 0;
return PM3_SUCCESS;
}
static void init_tag(void) {
@@ -455,23 +455,37 @@ static int32_t connected_phase(legic_card_select_t *p_card) {
// Only this function is public / called from appmain.c
//-----------------------------------------------------------------------------
void LegicRfSimulate(uint8_t cardtype) {
void LegicRfSimulate(uint8_t tagtype, bool send_reply) {
// configure ARM and FPGA
init_tag();
int res = PM3_SUCCESS;
// verify command line input
if (init_card(cardtype, &card) != 0) {
DbpString("[!] Unknown tagtype.");
if (init_card(tagtype, &card) != PM3_SUCCESS) {
DbpString("Unknown tagtype to simulate");
res = PM3_ESOFT;
goto OUT;
}
uint16_t counter = 0;
LED_A_ON();
DbpString("[=] Starting Legic emulator, press " _YELLOW_("button") " to end");
while (!BUTTON_PRESS() && !data_available()) {
Dbprintf("Legic Prime, simulating uid: %02X%02X%02X%02X", legic_mem[0], legic_mem[1], legic_mem[2], legic_mem[3]);
while (BUTTON_PRESS() == false) {
WDT_HIT();
if (counter >= 2000) {
if (data_available()) {
res = PM3_EOPABORTED;
break;
}
counter = 0;
}
counter++;
// wait for carrier, restart after timeout
if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
if (wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD) == false) {
continue;
}
@@ -481,13 +495,25 @@ void LegicRfSimulate(uint8_t cardtype) {
}
// conection is established, process commands until one fails
while (!connected_phase(&card)) {
while (connected_phase(&card) == false) {
WDT_HIT();
}
}
OUT:
DbpString("[=] Sim stopped");
if (DBGLEVEL >= DBG_ERROR) {
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", get_tracing(), BigBuf_get_traceLen());
}
if (res == PM3_EOPABORTED)
DbpString("aborted by user");
switch_off();
StopTicks();
if (send_reply)
reply_ng(CMD_HF_LEGIC_SIMULATE, res, NULL, 0);
BigBuf_free_keep_EM();
}
+3 -2
View File
@@ -1,7 +1,8 @@
//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2018 AntiCat
//
// 2019 Piwi
// 2020 Iceman
// This code is licensed to you under the terms of the GNU GPL, version 2 or,
// at your option, any later version. See the LICENSE.txt file for the text of
// the license.
@@ -14,6 +15,6 @@
#include "common.h"
void LegicRfSimulate(uint8_t cardtype);
void LegicRfSimulate(uint8_t tagtype, bool send_reply);
#endif /* __LEGICRFSIM_H */
+41 -34
View File
@@ -2041,7 +2041,7 @@ void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block,
// Acquisition
// Now do the acquisition
DoPartialAcquisition(0, false, samples, 0);
DoPartialAcquisition(0, false, samples, 1000);
// Turn the field off
if (brute_mem == false) {
@@ -2084,7 +2084,7 @@ void T55xx_ChkPwds(uint8_t flags) {
baseline_faulty >>= 5;
if (DBGLEVEL >= DBG_DEBUG)
Dbprintf("Baseline " _YELLOW_("%llu"), baseline_faulty);
Dbprintf("Baseline " _YELLOW_("%llu"), baseline_faulty);
uint8_t *pwds = BigBuf_get_EM_addr();
uint16_t pwd_count = 0;
@@ -2147,7 +2147,7 @@ void T55xx_ChkPwds(uint8_t flags) {
if (DBGLEVEL >= DBG_DEBUG)
Dbprintf("%08x has distance " _YELLOW_("%llu"), pwd, curr);
if (curr > prev) {
idx = i;
prev = curr;
@@ -2165,7 +2165,7 @@ OUT:
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
reply_ng(CMD_LF_T55XX_CHK_PWDS, PM3_SUCCESS, (uint8_t*)&payload, sizeof(payload));
reply_ng(CMD_LF_T55XX_CHK_PWDS, PM3_SUCCESS, (uint8_t *)&payload, sizeof(payload));
BigBuf_free();
}
@@ -2492,36 +2492,37 @@ static void SendForward(uint8_t fwd_bit_count) {
}
static void EM4xLogin(uint32_t pwd) {
uint8_t len;
forward_ptr = forwardLink_data;
len = Prepare_Cmd(FWD_CMD_LOGIN);
uint8_t len = Prepare_Cmd(FWD_CMD_LOGIN);
len += Prepare_Data(pwd & 0xFFFF, pwd >> 16);
SendForward(len);
//WaitUS(20); // no wait for login command.
// should receive
// 0000 1010 ok.
// 0000 1010 ok
// 0000 0001 fail
}
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
LED_A_ON();
uint8_t len;
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(20);
//clear buffer now so it does not interfere with timing later
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
StartTicks();
/* should we read answer from Logincommand?
*
* should receive
* 0000 1010 ok.
* 0000 1010 ok
* 0000 0001 fail
**/
if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
len = Prepare_Cmd(FWD_CMD_READ);
uint8_t len = Prepare_Cmd(FWD_CMD_READ);
len += Prepare_Addr(addr);
SendForward(len);
@@ -2530,19 +2531,23 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) {
DoPartialAcquisition(20, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_READWORD, PM3_SUCCESS, NULL, 0);
LED_A_OFF();
LEDsoff();
}
void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
LED_A_ON();
uint8_t len;
//clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
StartTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
WaitMS(50);
LED_A_ON();
// clear buffer now so it does not interfere with timing later
BigBuf_Clear_ext(false);
/* should we read answer from Logincommand?
*
* should receive
@@ -2552,20 +2557,21 @@ void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd) {
if (usepwd) EM4xLogin(pwd);
forward_ptr = forwardLink_data;
len = Prepare_Cmd(FWD_CMD_WRITE);
uint8_t len = Prepare_Cmd(FWD_CMD_WRITE);
len += Prepare_Addr(addr);
len += Prepare_Data(data & 0xFFFF, data >> 16);
SendForward(len);
//Wait 20ms for write to complete?
// Wait 20ms for write to complete?
WaitMS(7);
DoPartialAcquisition(20, false, 6000, 1000);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
reply_ng(CMD_LF_EM4X_WRITEWORD, PM3_SUCCESS, NULL, 0);
LED_A_OFF();
LEDsoff();
}
/*
@@ -2612,25 +2618,27 @@ void Cotag(uint32_t arg0) {
LED_A_ON();
LFSetupFPGAForADC(LF_DIVISOR_125, true);
LFSetupFPGAForADC(LF_FREQ2DIV(132), true); //132
//clear buffer now so it does not interfere with timing later
BigBuf_free();
BigBuf_Clear_ext(false);
//send COTAG start pulse
ON(740) OFF(2035)
ON(3330) OFF(2035)
ON(740) OFF(2035)
ON(1000)
/*
// send COTAG start pulse
// http://www.proxmark.org/forum/viewtopic.php?id=4455
/*
ON(740) OFF(2035)
ON(3330) OFF(2035)
ON(740) OFF(2035)
ON(2000)
*/
ON(800) OFF(2200)
ON(3600) OFF(2200)
ON(800) OFF(2200)
ON(3400)
*/
ON(2000) // ON(3400)
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, LF_FREQ2DIV(66)); // 66kHz
switch (rawsignal) {
case 0: {
doCotagAcquisition();
@@ -2658,7 +2666,6 @@ void Cotag(uint32_t arg0) {
// Turn the field off
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff();
}
/*
+40 -30
View File
@@ -36,7 +36,7 @@ static BitstreamOut data = {0, 0, 0};
// internal struct to keep track of samples gathered
static sampling_t samples = {0, 0, 0, 0};
void printConfig(void) {
void printLFConfig(void) {
uint32_t d = config.divisor;
DbpString(_CYAN_("LF Sampling config"));
Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d.%02d kHz")" )", d, 12000 / (d + 1), ((1200000 + (d + 1) / 2) / (d + 1)) - ((12000 / (d + 1)) * 100));
@@ -97,7 +97,7 @@ void setSamplingConfig(sample_config *sc) {
config.samples_to_skip = sc->samples_to_skip;
if (sc->verbose)
printConfig();
printLFConfig();
}
sample_config *getSamplingConfig(void) {
@@ -268,10 +268,10 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
initSampleBuffer(&sample_size);
if (DBGLEVEL >= DBG_DEBUG) {
Dbprintf("lf sampling - after init");
printSamples();
}
bool trigger_hit = false;
uint32_t cancel_counter = 0;
int16_t checked = 0;
@@ -279,7 +279,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
// only every 4000th times, in order to save time when collecting samples.
// interruptible only when logging not yet triggered
if ((checked >= 4000) && (trigger_threshold > 0)) {
if ((checked >= 4000) && trigger_hit == false) {
if (data_available()) {
checked = -1;
break;
@@ -298,20 +298,22 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
volatile uint8_t sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
// Testpoint 8 (TP8) can be used to trigger oscilliscope
// Test point 8 (TP8) can be used to trigger oscilloscope
LED_D_OFF();
// threshold either high or low values 128 = center 0. if trigger = 178
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
if (cancel_after > 0) {
cancel_counter++;
if (cancel_after == cancel_counter)
break;
if (trigger_hit == false) {
if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
if (cancel_after > 0) {
cancel_counter++;
if (cancel_after == cancel_counter)
break;
}
continue;
}
continue;
}
trigger_threshold = 0;
trigger_hit = true;
if (samples_to_skip > 0) {
samples_to_skip--;
@@ -324,18 +326,19 @@ uint32_t DoAcquisition(uint8_t decimation, uint8_t bits_per_sample, bool avg, in
}
}
if (checked == -1 && verbose) {
Dbprintf("lf sampling aborted");
}
if (verbose) {
if (checked == -1) {
Dbprintf("lf sampling aborted");
} else if (cancel_counter == cancel_after) {
Dbprintf("lf sampling cancelled after %u", cancel_counter);
}
Dbprintf("Done, saved " _YELLOW_("%d")" out of " _YELLOW_("%d")" seen samples at " _YELLOW_("%d")" bits/sample", samples.total_saved, samples.counter, bits_per_sample);
}
// Ensure that DC offset removal and noise check is performed for any device-side processing
removeSignalOffset(data.buffer, samples.total_saved);
computeSignalProperties(data.buffer, samples.total_saved);
return data.numbits;
}
/**
@@ -356,20 +359,28 @@ uint32_t DoAcquisition_config(bool verbose, uint32_t sample_size) {
, config.trigger_threshold
, verbose
, sample_size
, 0
, 0 // cancel_after
, config.samples_to_skip);
}
uint32_t DoPartialAcquisition(int trigger_threshold, bool verbose, uint32_t sample_size, uint32_t cancel_after) {
return DoAcquisition(1, 8, 0, trigger_threshold, verbose, sample_size, cancel_after, 0);
return DoAcquisition(config.decimation
, config.bits_per_sample
, config.averaging
, trigger_threshold
, verbose
, sample_size
, cancel_after
, 0); // samples to skip
}
static uint32_t ReadLF(bool reader_field, bool verbose, uint32_t sample_size) {
if (verbose)
printConfig();
printLFConfig();
LFSetupFPGAForADC(config.divisor, reader_field);
uint32_t ret = DoAcquisition_config(verbose, sample_size);
StopTicks();
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
}
@@ -495,7 +506,7 @@ void doCotagAcquisition(void) {
bool firsthigh = false, firstlow = false;
uint16_t i = 0, noise_counter = 0;
while ((i < bufsize) && (noise_counter < COTAG_T1 << 1)) {
while ((i < bufsize - 1) && (noise_counter < COTAG_T1 << 1)) {
if (BUTTON_PRESS())
break;
@@ -527,14 +538,13 @@ void doCotagAcquisition(void) {
firstlow = true;
}
if (++i < bufsize) {
if (sample > COTAG_ONE_THRESHOLD) {
dest[i] = 255;
} else if (sample < COTAG_ZERO_THRESHOLD) {
dest[i] = 0;
} else {
dest[i] = dest[i - 1];
}
++i;
if (sample > COTAG_ONE_THRESHOLD) {
dest[i] = 255;
} else if (sample < COTAG_ZERO_THRESHOLD) {
dest[i] = 0;
} else {
dest[i] = dest[i - 1];
}
}
}
@@ -548,7 +558,7 @@ uint16_t doCotagAcquisitionManchester(uint8_t *dest, uint16_t destlen) {
if (dest == NULL)
return 0;
dest[0] = 0;
bool firsthigh = false, firstlow = false;
+1 -1
View File
@@ -99,7 +99,7 @@ void setSamplingConfig(sample_config *sc);
sample_config *getSamplingConfig(void);
void printConfig(void);
void printLFConfig(void);
void printSamples(void);
#endif // __LFSAMPLING_H

Some files were not shown because too many files have changed in this diff Show More