mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-05-12 11:18:11 -07:00
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)),)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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) {
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+9
-10
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
Reference in New Issue
Block a user