Merge pull request #1 from RfidResearchGroup/master

Update
This commit is contained in:
Bjoern Kerler 2019-06-25 19:37:59 +02:00 committed by GitHub
commit f68dd76155
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
824 changed files with 203739 additions and 120203 deletions

10
.gitattributes vendored
View file

@ -1,6 +1,16 @@
# .gitattributes # .gitattributes
# prevent binary files from CRLF handling, diff and merge: # prevent binary files from CRLF handling, diff and merge:
fpga/fpga.bit -crlf -diff fpga/fpga.bit -crlf -diff
*.bin -crlf -diff *.bin -crlf -diff
*.z -crlf -diff *.z -crlf -diff
# Force LF
*.c text=auto eol=lf
*.cpp text=auto eol=lf
*.h text=auto eol=lf
*.lua text=auto eol=lf
*.py text=auto eol=lf
*.pl text=auto eol=lf
*.dic text=auto eol=lf
Makefile text=auto eol=lf

View file

@ -1,6 +1,9 @@
--- ---
name: Bug report name: Bug report
about: Create a report to help us improve about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
--- ---

View file

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: "[idea]"
labels: Request, enhancement
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.gitignore vendored
View file

@ -2,6 +2,7 @@
# don't push these files to the repository # don't push these files to the repository
.history .history
.bash_history
*.log *.log
*.eml *.eml
*.o *.o
@ -19,6 +20,12 @@
*.exe *.exe
*.dsym *.dsym
version.c version.c
*.json
# new build file for add-ons.
Makefile.platform
# Cache for detecting platform def changes
.Makefile.options.cache
!client/hardnested/*.bin !client/hardnested/*.bin
!client/hardnested/tables/*.z !client/hardnested/tables/*.z
@ -32,6 +39,7 @@ luac
fpga_compress fpga_compress
mfkey32 mfkey32
mfkey64 mfkey64
tools/nonce2key/nonce2key
fpga/* fpga/*
!fpga/tests !fpga/tests
@ -57,6 +65,6 @@ ppls patches/*
*- Copy.* *- Copy.*
client/lualibs/mf_default_keys.lua client/lualibs/mf_default_keys.lua
client/lualibs/usb_cmd.lua client/lualibs/pm3_cmd.lua
# recompiled # recompiled
fpga_version_info.c fpga_version_info.c

View file

@ -3,7 +3,199 @@ 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... 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] ## [unreleased][unreleased]
- Change: updates to README (@iceman)
- Change: hf mf/mfu dbg => hw dbg (@doegox)
- Change: replace usb_poll_validate_length() by data_available() that supports USART too (@doegox)
- Make sure standalone modes can be launched when connected on USB without client (@doegox)
- Change: cleaner makefile execution, use 'make V=1' if you want to see full lines (@doegox)
- Change: automate make clean when platform definitions are changed (@doegox)
- Add STANDALONE option to Makefile.hal (@Fl0-0)
- Change: mem info - production public key to verify rdv4.0 flash signature (@iceman)
- Fix specify that we need TCP and not UDP connection (@phcoder)
- Change: lf cotag demod - adjusted error trigger (@iceman)
- Add documentation on BT add-on (@iceman/@doegox)
- Change: new button behaviour in bootloader mode, no need to keep it pressed, press again to interrupt (@doegox)
- Change: new keys in dicts, new mem layout to accomodate them (@iceman/various)
- Fix lf sim - if called with empty graphbuffer all strange things happend, like turning on HF field (@iceman)
- Change: hf 14a sim / hf mf sim - check buttonpress/usb frame fewer times in order not to disrupt simulation (@McEloff)
- Change: data convertbitstream - converts bit to max/min in order to facilitate demodulation of simulation data (@iceman)
- Change: lf em 410x_demod - now can demod the simulation data (@iceman)
- Add HC-06 scripts for BT add-on (@doegox)
- Fix lf nedap sim - error when adding parity (@iceman)
- Add documentation on UART and baudrates (@doegox/@iceman)
- Change: prompt now shows which channel is used (@iceman)
- Change: USART baudrates computation, up to 6Mbps (@iceman/@doegox)
- Change: hf mf nack - keep sync if started without card over antenna
- Add usart btfactory - to reset a misconfigured BT add-on (@doegox)
- Change: hw status - now prints number of dictionary keys loaded (@iceman)
- Add home, end, pageup, and pagedown keybinds to the plot GUI. Also fix paged movement in GUI. (@mcd1992)
- Change legic.lua saves data in EML and BIN formats (@iceman)
- Change hf tune - is now synchronous (for BT add-on) and can be interrupted by kbd (@doegox)
- Change: update macOS install instruction (@ Uli Heilmeier)
- Add trace ouput in hexdump format for Wireshark import (@ Uli Heilmeier)
- Add usart btpin - to change BT add-on PIN (@doegox)
- Add reconnection support (@iceman/@doegox)
- Add usart tx/rx/... - USART developer commands (@doegox)
- Add PLATFORM_EXTRAS, WITH_FPC_USART_HOST, BTADDON Makefile configuration (@doegox)
- Fix slow reconfigure on mingw of serial port (@iceman)
- Fix cross thread communictions of timeout variable (@iceman)
- Change: client is now "universal", adapting to Proxmark3 capabilities (@doegox)
- Add disconnect support to Lua (@iceman)
- Change: handles FPC/FLASH FW more gracefully on non-RDV4 pm3 (@doegox)
- Add JTAG support for Shikra (@NinjaStyle82)
- Change: smart color handling: only if linux and on real term (@doegox)
- Change: reconfigure uart timeouts when compiled for FPC and connecting over USB (@iceman)
- Change: fast push for many commands (@iceman/@doegox)
- Add: fast push for Lua (@iceman)
- Add NDEF parser in Lua (@iceman)
- Change: improve NDEF parser (@iceman)
- Change: all commands got migrated to MIX/NG packet format (@iceman/@doegox)
- Fix: Mifare Ultralight read block missing bytes (@doegox)
- Add support new frame format in all Lua scripts (@iceman)
- Add CMD_CAPABILITIES for pm3 to inform dynamically the client (@doegox)
- Change baudrate handling, make it clear it's only indicative for USB-CDC & BT (@doegox)
- Change: new progressive light scheme for 'hw detectreader' (@doegox)
- Add common error definitions system for retvals (@doegox)
- Change USART RX & TX code and fix delays handling to make it more robust, especially over BT (@doegox)
- Add support for new frames format, speedup & huge changes, see doc/new_frame_format.txt (@doegox)
- Change: loadFile* & saveFile* accept filenames with (or still without) extension (@doegox)
- Fix LoadEML to accept final "\n", e.g. from pm3_mfd2eml.py (@doegox)
- Change: rework shell scripts for easy client or flasher (@doegox)
- Fix: stop poking Internet when compiling (@doegox)
- Add support for multiple commands to "-c", e.g. proxmark3 -c "hw ping;hw version" (@doegox)
- Fix external flash writing bitflips issues at 24MHz (@doegox)
- Add color support to Dbprintf & alike and rework Dbprintf flags (@doegox)
- Change: archive (and fix) hid-flasher (@doegox)
- Add standalone placeholder to simplify new standalone integration (@doegox)
- Change: refactor standalone mode info string (@iceman)
- Add iceman skeleton standalone mode for ppl to use as base for their new modes (@iceman)
- Change: move compilation options to Makefile.hal (@doegox)
- Fix compilation under OSX (@iceman)
- Add openocd config files for JLink (@doegox)
- Fix compilation dependencies for recovery (@doegox)
- Fix segfault when loading a file (@doegox)
- Change/Add new dump format for Ultralight/NTAG, counters support, simulation (@mceloff)
- Add 'hf mf sim' full-byte split anticollision support (@mceloff)
- Fix/Add 'hf mf sim' bugs fix, RATS support, etc (@mceloff)
- Fix serial of FPC. (@ryan)
- Fix 'data shiftgraphzero' corrupting end of GraphBuffer (@doegox)
- Fix 'hf legic info' - unsegmented card now uses card size to calc remaining length (@iceman)
- Add 36bit HID format, extend calcWiegand() to include oem bits ((@davidbeauchamp)
- Fix 'hf mf hardnested' - not verify key when reading nonce file (@iceman)
- Change optimizations for ask/bi (@iceman)
- Fix 'hf mf sim' - bugs fix, refactoring (@mceloff)
- Add WRITE and COMPATIBLE_WRITE support to Mifare Ultralight/NTAG simulation (@mceloff)
- Change installation instructions and add video links (@5w0rdfish)
- Change 'hf mf sim' to support more types (@vratiskol)
- Change better strong wave detection for biphase (@iceman)
- Add 'script run test_t55x7' (@iceman)
- Add new lua scripting support for some t55xx commands (@iceman)
- Add FPC USART for BT add-on with pm3 client. (@doegox)
- Add '-b baudrate' option to the pm3 client. (@doegox)
- Change 'lf t55xx info': tell if known configuration block0. (@iceman)
- Fix/Add FPC usart: fix TX, bring RX, full speed. (@doegox)
- Change 'lf t55xx config' options: allow to toggle on/off i/q5/st
- Change 'lf t55xx info': support offline block0, Q5, fix extended, add warns. (@doegox)
- Avoid race condition when flasher finds the not yet closed pm3 port. (@doegox)
- Fix 'lf t55xx trace': read the proper block. (@doegox)
- Fix Indala 64 on T55xx: use PSK1. (@doegox)
- Force proper Linefeed (LF) handling in ProxSpace. (@vratiskol)
- Fix Makefiles race conditions to allow parallel compilation, e.g. 'make -j8'. (@doegox)
- Add - dictionary key file for MFU. (not in use at the moment) (@mazodude)
- Change 'lf fdx demod - better biphase maxerrors. (@MalteHillmann)
- Change 'hf mf sim' - now works better against android (@mceloff)
- Fix 'lf t55xx brute' - now works after aquiredata adaptations (@iceman)
- Fix 'lf t55xx chk' - now works after aquiredata adaptations (@iceman)
- Fix 'lf t55xx recoverpwd' - now works after aquiredata adaptations (@iceman)
- Fix 'data detect p' - reverted bad clock detection (@iceman)
- Change 'data detect a' - better clock detection (@iceman)
- Add 'hf 14a info' - now detects some magic card Gen2 (@iceman)
- Removed 'LCD' code in armsrc compilation (@iceman)
- Change - Generic fixes of codestyle (@doegox) (@iceman)
- Change 'lf indala demod' - refactoring (@iceman)
- Change - handling fault bit markers (7) and partial nibbles in hex printing (@doegox)
- Change - printing of fault bit markers (7) using a dot (@doegox)
- Change 'sc upgrade' - firmware file integrity check (@piwi)
- Fix 'data rawdemod am' - last bit was missing (@doegox)
- Fix 'hf 15 dump f' - also selects tag first (@iceman)
- Fix 'hf iclass clone' - missing fileclose (@iceman)
- Add 'trace list hitag' - old hitag annotations now use the new trace (@iceman)
- Change 'lf hitag sim' - loads bin/eml/json (@iceman)
- Change 'lf hitag reader 21' - saves in bin/eml/json (@iceman)
- Change 'lf hitag' - refactoring (@iceman)
- Change 'lf hitag' - refactoring (@piwi)
- Fix 'lf hitag' - generic fix for missing clock init (@piwi)
- Fix fsk sim operations on deviceside - avoid division by zero (@doegox)
- Fix 'hf mf fchk' - condition always false (@doegox)
- Fix 'lf t55xx recoverpw' - shift as u32 (@doegox)
- Fix 'lf ti demod' - shift as u32 (@doegox)
- Fix 'lf ti read' - shift as u32 (@doegox)
- Fix 'lf t55xx chk' - condition always false (@doegox)
- Change 'lf sim' - ledcontrol refactoring (@doegox)
- Fix 'hf mf nack' - signedness bug (@doegox)
- Fix 'hf epa cnonce' - check return value (@doegox)
- Fix 'lf hitag write' - condition always true (@doegox)
- Fix 'mem write' - added extra check (@doegox)
- Fix 'iso15693' - bad string cpy (@doegox)
- Fix 'make style' - EOF LF support (@doegox)
- Add 'hf 14b raw' - added -t for timeout (@iceman)
- Rename 'lf hitag snoop' - renamed to 'lf hitag sniff' (@iceman)
- Rename 'lf snoop' - renamed to 'lf sniff' (@iceman)
- Rename 'hf snoop' - renamed to 'hf sniff' (@iceman)
- Fix 'hf mfp wrbl' - more blocks available (@merlokk)
- Add 'make platform' - compile for non-rdv4 devices made simpler (@doegox)
- Change Makefiles optimizations when recompiling (@doegox)
- Fix 'data load' - loads TITEST.txt again (@iceman)
- Change 'lf search' - now detects TI (@iceman)
- Change fixing signal cleaning for LF (@doegox)
- Fix 'lf paradox demod' - wrong check (@iceman)
- Change 'lf t55xx' - aquiredata uses getsamples (@iceman)
- Fix 'lf search' - chipset detection restore demod buffer again (@iceman)
- Add 'make style' (@doegox)
- Fix mixed tabs vs spaces. Now only use 4 space as tab. (@doegox)
- Fix 'lf visa2000 read' - too few samples (@iceman)
- Fix 'lf t55xx bruteforce' - infinity loop (@doegox)
- Fix 'analyse nuid' - correct crc (@doegox)
- Add command history not repeating logged commands (@doegox)
- Fix path for aidjson (@doegox)
- Fix missing init i2x (@doegox)
- Fix '14b select card' - (@doegox)
- Add 'hf mf ndef' - parsing of NDEF messages (@merlokk)
- Add 'hf mf mad' - parsing of Mifare Application Directory (@merlokk)
- Rename 'lf snoop' -> 'lf sniff' (@iceman)
- Rename 'hf snoop' -> 'hf sniff' (@iceman)
- Change generally added more colors (@iceman)
- Change 'sc upgrade' updated firmware v3.11 (RDV40) (@sentiprox)
- Change 'data autocorrelate' - better visual representation and added extra peak detection (@iceman)
- Fix 'lf search' - false positive indala identification fixed (@iceman)
- Add 'lf keri' - basic support for Keri tags (@iceman)
- Add 'hf mf list' - re-added it again (@iceman)
- Fix - A lot of bugfixes, like memory leaks (@iceman)
- Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit
- Fix 'hf mf fchk' (@iceman)
- Fix 'usb slow on posix based systems' (@fl0-0)
- Change 'lf pcf7931' - improved read code (@sguerrini97)
- Change 'hf felica list' - started with some FeliCa annotations (@iceman)
- Fix 'hf tune' - now works as expected (@iceman)
- Add 'option to use flash memory to upload dictionary files' (RDV40) (@iceman)
- Fix 'printing percentage now standard compliant' (@fabled)
- Add 'emv roca' - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman)
- Added TCP ports support (on linux) (@phcoder)
- Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton)
- Fix 'Lining up plot and control window' (@anticat)
- Fix 'annoying focus behaviour' on OSX (@Anticat)
- Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat)
- Added 'sc brute' - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman)
- Change 'lf t55xx detectconfig' - now optional to persist settings to flashmem (RDV40) (@iceman)
- Change 'hf mf csave' - now saves both EML/BIN formats (@iceman)
- Change 'hf mf esave' - now saves both EML/BIN formats (@iceman)
- Fix 'compiler warning on macos and gcc7.1 or higher' (@TomHarkness)
- Fix 'crash on Bionic libc if CloseProxmark is called twice' (@micolous)
- Change 'lf hid' - got an updated to Kastle format (@xilni)
- Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman)
- Chg adaptations for FPC communications (work in progress) (@iceman)
- Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato)
- Fix 'LEGIC SIM' - remake of legic sim (@drandreas)
- Changed 'proxmark3 client threading' - remake from official repo (@micolous) - Changed 'proxmark3 client threading' - remake from official repo (@micolous)
- Add 'rem' - new command that adds a line to the log file (@didierStevens) - Add 'rem' - new command that adds a line to the log file (@didierStevens)
- Fix 'EM410xdemod empty tag id in lfops.c' (@Defensor7) - Fix 'EM410xdemod empty tag id in lfops.c' (@Defensor7)
@ -65,6 +257,16 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac
- Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk) - Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk)
- Added 'hf emv' commands (@merlokk) - Added 'hf emv' commands (@merlokk)
- lots of bug fixes (many many) - lots of bug fixes (many many)
- Changed hf mfp security. Now it works in all the modes. (drHatson)
- Added `hf fido` commands that work with FIDO U2F authenticators (@merlokk)
- Added mbedtls instead of old polarssl (@merlokk)
- Added jansson (@merlokk)
- Added `hf emv scan` - save card's data to json file (@merlokk)
- Added `hf emv` `gpo`, `readrec`, `genac`, `challenge`, `intauth` - separate commands from `hf emc exec` (@merlokk)
- Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk)
- Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk)
- Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk)
### Fixed ### Fixed
- Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi)
- Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok)

273
HACKING.md Normal file
View file

@ -0,0 +1,273 @@
_"Coding styles are like assholes, everyone has one and no one likes anyone elses."_
--Eric Warmenhoven
# Overview
The Proxmark3 codebase is pretty messy and in the process of being cleaned up,
so we don't have clear guidelines on how to place new code just yet. However,
please don't make things worse.
However, we have established a set of coding style guidelines in order to
clean up the code consistently and keep it consistent in the future.
Look around and respect the same style.
Helper script to get some uniformity in the style:
`$ make style`
It makes use of `astyle` so be sure to install it first.
# Indentation
Don't use tabs, editors are messing them up too easily.
Increment unit is four spaces.
If you use `make style`, this will be done for you.
# Width
Try to keep lines to a reasonable length. 80 characters is a good mark; using an
editor that shows a vertical line is a great idea. However, don't break a line
just because you're slightly over, it's not worth it. No 200-character lines,
though.
# Macros
`#define`, function-like or not, are all UPPERCASE unless you're emulating a
well-known function name.
# Identifiers
Functions, local variables, and arguments are all named using
`underscores_as_spaces`. Global variables are Evil and are prepended with `g_` to
distinguish them. Avoid them.
Single-character variables are a bad idea. Exceptions: loop iterators and maybe
simple byte pointers (`*p`) in very obvious places. If you have more than one
such pointer, use a real name. If you have more than a couple nested loops,
complex logic, or indices that differ in interpretation or purpose, use real
names instead of i,j,k.
# Data types
Use `stdint.h` types (`uint32_t` and friends) unless you have a reason not to. Don't
use microsoft-style `DWORD` and the like, we're getting rid of those. Avoid char
for buffers, `uint8_t` is more obvious when you're not working with strings. Use
`const` where things are const. Try to use `size_t` for sizes.
Pointers and reference operators are attached to the variable name:
```
void *ptr;
```
not:
```
void* ptr;
```
otherwise you're tempted to write:
```
void* in, out;
```
and you'll fail.
`make style` will take care of pointers & reference operators.
# Expressions
In general, use whitespace around binary operators - no unspaced blobs of an
expression. `make style` will take care of whitespaces around operators.
For example,
```
if (5 * a < b && some_bool_var)
```
but not
```
if (5*a<b&&some_bool_var)
```
For equality with constants, use `i == 0xF00`, not `0xF00 == i`. The compiler warns
you about `=` vs `==` anyway, and you shouldn't be screwing that one up by now
anyway.
# If / for / while etc
Put the opening brace on the same line, with a space before it.
There should be a space between the construct name (if/for/whatever) and the
opening parenthesis, and there should be a space between the closing parenthesis
and the opening brace, and no space between parenthesis and expression.
`make style` will take care of all that.
If you do split the condition, put the binary operators that join the lines at
the beginning of the following lines, not at the end of the prior lines.
For generic `for()` iterator variables, declare them in-line:
```
for (int i = 0; i < 10; i++) {
...
}
```
Note the spaces after the semicolons.
if/else should be laid out as follows:
```
if (foo) {
...
} else if (bar) {
...
} else {
...
}
```
You can skip braces around 1-line statements but don't mix braces vs. no braces.
# Functions
Put the return type on the same line.
Put a space after a comma in argument lists.
Open the brace after the declaration (after a space).
`make style` will take care of all that.
```
void foo(int a_thing, int something_else) {
...
}
```
Functions with no arguments are declared as `f(void)`, not `f()`.
Use static for functions that aren't exported, and put exported functions
in a header file (one header file per source file with exported functions
usually, no huge headers with all functions).
```
void baz(void) {
foo(bluh, blah);
}
```
Function names should be `separated_with_underscores()`, except for standard
functions (`memcpy`, etc.). It may make sense to break this rule for very common,
generic functions that look like library functions (e.g. `dprintf()`).
Don't use single-character arguments.
Exception: very short functions with one argument that's really obvious:
```
static int ascii(char c) {
if (c < 0x20 || c >= 0x7f)
return '.';
else
return c;
}
```
vs.
```
static void hexdump(void *buf, size_t len) {
...
}
```
As a general guideline, functions shouldn't usually be much more than 30-50
lines. Above, the general algorithm won't be easily apparent, and you're
probably missing some factoring/restructuring opportunity.
# Structs / unions / enums
Use typedefs when defining structs. The type should be named something_t.
```
typedef struct {
blah blah;
} prox_cmd_t;
```
You can use anonymous enums to replace lots of sequential or mostly-sequential
#defines.
# Switch
Indent once for the `case:` labels, then again for the body. Like this:
```
switch(bar) {
case OPTION_A:
do_stuff();
break;
case OPTION_B:
do_other_stuff();
break;
}
```
`make style` will take care of the indentation.
If you fall through into another case, add an explicit comment;
otherwise, it can look confusing.
If your `switch()` is too long or has too many cases, it should be cleaned up.
Split off the cases into functions, break the switch() into parent and children
switches (e.g. command and subcommand), or use an array of function pointers or
the like. In other words, use common sense and your brain.
If you need local scope variables for a case, you can add braces:
```
switch(bar) {
case OPTION_A: {
int baz = 5 * bar;
do_stuff(baz);
break;
}
...
```
But at that point you should probably consider using a separate function.
# Comments
Use //, it's shorter:
```
// this does foo
...
// baz:
// This does blah blah blah .....
// blah blah...
```
`/* */` can be used to comment blocks of code, but you should probably remove
them anyway - we have version control, it's easy to fetch old code if needed,
so avoid committing commented out chunks of code. The same goes for `#if 0`.
# File
Please use common sense and restrain yourself from having a thousands line
file. Functions in a file should have something *specific* in common. Over time
sub-categories can arise and should therefore yield to file splitting.
For these reasons, vague and general filenames (e.g. `util.*`, `global.*`, `misc.*`,
`main.*`, and the like) should be very limited, if not prohibited.
# File headers
License/description header first:
```
//-----------------------------------------------------------------------------
// YOUR COPYRIGHT LINE GOES HERE
//
// 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.
//-----------------------------------------------------------------------------
// FILE DESCRIPTION GOES HERE
//-----------------------------------------------------------------------------
```
If you modify a file in any non-trivial way (add code, etc.), add your copyright
to the top with the current year.
# Header files
Use the following include guard format:
```
#ifndef FOOBAR_H__
#define FOOBAR_H__
...
#endif // FOOBAR_H__
```
Keep in mind that `__FOOBAR_H` would be reserved by the implementation and thus
you shouldn't use it (same for `_FOOBAR_H`).
# Whitespace
Avoid trailing whitespace (no line should end in tab or space).
Keep a newline (blank line) at the end of each file.
`make style` will take care of both.

View file

@ -1,291 +0,0 @@
"Coding styles are like assholes, everyone has one and no one likes anyone elses."
--Eric Warmenhoven
The Proxmark3 codebase is pretty messy and in the process of being cleaned up,
so we don't have clear guidelines on how to place new code just yet. However,
please don't make things worse.
However, we have established a set of coding style guidelines in order to
clean up the code consistently and keep it consistent in the future. Use common
sense and good taste. If breaking a rule leads to cleaner code, you can do so,
but laziness is not an excuse.
=== INDENTATION ===
Use tabs for indentation, but use spaces for alignment:
if (foo(this, that, there)
&& bar == baz)
{
dostuff();
}
Notice it's like this (T___ for tab, S for space, for a 4-char tab setting):
T___if (foo(this, that, there)
T___SSSS&& bar == baz)
Another example:
#define THIS 0x10
#define THAT_THING 0x20
#define SOMETHING_ELSE 0x80
These should look good no matter what your editor's tab setting is, so go nuts
and pick whatever you like best.
=== WIDTH ===
Try to keep lines to a reasonable length. 80 characters is a good mark; using an
editor that shows a vertical line is a great idea. However, don't break a line
just because you're slightly over, it's not worth it. No 200-character lines,
though.
=== MACROS ===
#defines, function-like or not, are all UPPERCASE unless you're emulating a
well-known function name.
=== IDENTIFIERS ===
Functions, local variables, and arguments are all named using
underscores_as_spaces. Global variables are Evil and are prepended with g_ to
distinguish them. Avoid them.
Single-character variables are a bad idea. Exceptions: loop iterators and maybe
simple byte pointers (*p) in very obvious places. If you have more than one
such pointer, use a real name. If you have more than a couple nested loops,
complex logic, or indices that differ in interpretation or purpose, use real
names instead of i,j,k.
=== DATA TYPES ===
Use stdint.h types (uint32_t and friends) unless you have a reason not to. Don't
use microsoft-style DWORD and the like, we're getting rid of those. Avoid char
for buffers, uint8_t is more obvious when you're not working with strings. Use
'const' where things are const. Try to use size_t for sizes.
Pointers are:
void *ptr;
not:
void* ptr;
otherwise you're tempted to write:
void* in, out;
and you'll fail.
=== EXPRESSIONS ===
In general, use whitespace around binary operators - no unspaced blobs of an
expression. This rule may be broken if it makes things clearer. For example,
if (5*a < b && some_bool_var)
but not
if (5*a<b&&some_bool_var)
For equality with constants, use i == 0xF00, not 0xF00 == i. The compiler warns
you about = vs == anyway, and you shouldn't be screwing that one up by now
anyway.
=== IF / FOR / WHILE / etc. ===
Put the opening brace on the same line, with a space before it. Exception: if
the if/for/while condition/whatever are split over several lines, it might be
more appealing to put the opening brace on its own line, so use your own
judgement there:
if (foo(this, that, there)
&& bar == baz)
{
dostuff();
}
If you do split the condition, put the binary operators that join the lines at
the beginning of the following lines (as above), not at the end of the prior
lines.
There should be a space between the construct name (if/for/whatever) and the
opening parenthesis, and there should be a space between the closing parenthesis
and the opening brace.
For generic for() iterator variables, declare them in-line:
for (int i = 0; i < 10; i++) {
...
}
Note the spaces after the semicolons.
if/else should be laid out as follows:
if (foo) {
...
} else if (bar) {
...
} else {
...
}
or
if (foo)
...
else if (bar)
...
else
...
Don't mix braces vs. no braces. If any of your bodies are > 1 line, put braces
around them all.
=== FUNCTIONS ===
Functions with no arguments are declared as f(void), not f(). Put the return
type on the same line. Use static for functions that aren't exported, and put
exported functions in a header file (one header file per source file with
exported functions usually, no huge headers with all functions). Put a space
after a comma in argument lists.
void foo(int a_thing, int something_else)
{
...
}
void baz(void)
{
foo(bluh, blah);
}
Function names should be separated_with_underscores(), except for standard
functions (memcpy, etc.). It may make sense to break this rule for very common,
generic functions that look like library functions (e.g. dprintf()).
Don't use single-character arguments. Exception: very short functions with one
argument that's really obvious:
static int ascii(char c)
{
if (c < 0x20 || c >= 0x7f)
return '.';
else
return c;
}
vs.
static void hexdump(void *buf, size_t len)
{
...
}
As a general guideline, functions shouldn't usually be much more than 30-50
lines. Above, the general algorithm won't be easily apparent, and you're
probably missing some factoring/restructuring opportunity.
=== STRUCTS / UNIONS / ENUMS ===
Use typedefs when defining structs. The type should be named something_t.
typedef struct {
blah blah;
} prox_cmd_t;
You can use anonymous enums to replace lots of sequential or mostly-sequential
#defines.
=== SWITCH ===
Indent once for the case: labels, then again for the body. Like this:
switch(bar) {
case OPTION_A:
do_stuff();
break;
case OPTION_B:
do_other_stuff();
break;
}
If you fall through into another case, add an explicit comment; otherwise, it
can look confusing.
If your switch() is too long or has too many cases, it should be cleaned up.
Split off the cases into functions, break the switch() into parent and children
switches (e.g. command and subcommand), or use an array of function pointers or
the like. In other words, use common sense and your brain.
If you need local scope variables for a case, you can add braces:
switch(bar) {
case OPTION_A: {
int baz = 5*bar;
do_stuff(baz);
break;
}
...
But at that point you should probably consider using a separate function.
=== COMMENTS ===
Use //, it's shorter:
// this does foo
...
// baz:
// This does blah blah blah .....
// blah blah...
/* */ can be used to comment blocks of code, but you should probably remove
them anyway - we have version control, it's easy to fetch old code if needed,
so avoid committing commented out chunks of code. The same goes for #if 0.
=== FILE ===
Please use common sense and restrain yourself from having a thousands+++ line
file. Functions in a file should have something *specific* in common. Over time
sub-categories can arise and should therefore yield to file splitting.
For these reasons, vague and general filenames (e.g. util.*, global.*, misc.*,
main.*, and the like) should be very limited, if not prohibited.
=== FILE HEADERS ===
License/description header first:
//-----------------------------------------------------------------------------
// YOUR COPYRIGHT LINE GOES HERE
//
// 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.
//-----------------------------------------------------------------------------
// FILE DESCRIPTION GOES HERE
//-----------------------------------------------------------------------------
If you modify a file in any non-trivial way (add code, etc.), add your copyright
to the top.
=== HEADER FILES ===
Use the following include guard format:
#ifndef FOOBAR_H__
#define FOOBAR_H__
...
#endif // FOOBAR_H__
Keep in mind that __FOOBAR_H would be reserved by the implementation and thus
you shouldn't use it (same for _FOOBAR_H).
=== WHITESPACE ===
Avoid trailing whitespace (no line should end in tab or space). People forget
this all the time if their editor doesn't handle it, but don't be surprised if
you see someone fixing it from time to time.
Keep a newline (blank line) at the end of each file.

125
Makefile
View file

@ -1,3 +1,9 @@
# Hide full compilation line:
ifneq ($(V),1)
Q?=@
endif
# To see full command lines, use make V=1
GZIP=gzip GZIP=gzip
# Windows' echo echos its input verbatim, on Posix there is some # Windows' echo echos its input verbatim, on Posix there is some
# amount of shell command line parsing going on. echo "" on # amount of shell command line parsing going on. echo "" on
@ -23,38 +29,70 @@ FLASH_PORT=com3
PATHSEP=\\# PATHSEP=\\#
endif endif
-include Makefile.platform
-include .Makefile.options.cache
include common/Makefile.hal
all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/% all clean: %: client/% bootrom/% armsrc/% recovery/% mfkey/% nonce2key/%
mfkey/%: FORCE mfkey/%: FORCE
$(MAKE) -C tools/mfkey $(patsubst mfkey/%,%,$@) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C tools/mfkey $(patsubst mfkey/%,%,$@)
nonce2key/%: FORCE nonce2key/%: FORCE
$(MAKE) -C tools/nonce2key $(patsubst nonce2key/%,%,$@) $(info [*] MAKE $@)
bootrom/%: FORCE $(Q)$(MAKE) --no-print-directory -C tools/nonce2key $(patsubst nonce2key/%,%,$@)
$(MAKE) -C bootrom $(patsubst bootrom/%,%,$@) bootrom/%: FORCE cleanifplatformchanged
armsrc/%: FORCE $(info [*] MAKE $@)
$(MAKE) -C armsrc $(patsubst armsrc/%,%,$@) $(Q)$(MAKE) --no-print-directory -C bootrom $(patsubst bootrom/%,%,$@)
armsrc/%: FORCE cleanifplatformchanged
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C armsrc $(patsubst armsrc/%,%,$@)
client/%: FORCE client/%: FORCE
$(MAKE) -C client $(patsubst client/%,%,$@) $(info [*] MAKE $@)
recovery/%: FORCE $(Q)$(MAKE) --no-print-directory -C client $(patsubst client/%,%,$@)
$(MAKE) -C recovery $(patsubst recovery/%,%,$@) recovery/%: FORCE cleanifplatformchanged bootrom/% armsrc/%
$(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C recovery $(patsubst recovery/%,%,$@)
FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites)
.PHONY: all clean help _test flash-bootrom flash-os flash-all FORCE .PHONY: all clean help _test bootrom flash-bootrom os flash-os flash-all recovery client mfkey nounce2key style checks FORCE udev accessrights cleanifplatformchanged
help: help:
@echo Multi-OS Makefile, you are running on $(DETECTED_OS) @echo "Multi-OS Makefile"
@echo Possible targets: @echo
@echo + all - Make bootrom, armsrc and the OS-specific host directory @echo "Possible targets:"
@echo + client - Make only the OS-specific host directory @echo "+ all - Make all targets: bootrom, armsrc and OS-specific host tools"
@echo + flash-bootrom - Make bootrom and flash it @echo "+ clean - Clean in all targets"
@echo + flash-os - Make armsrc and flash os \(includes fpga\) @echo
@echo + flash-all - Make bootrom and armsrc and flash bootrom and os image @echo "+ bootrom - Make bootrom"
@echo + mfkey - Make tools/mfkey @echo "+ os - Make armsrc (includes fpga)"
@echo + nounce2key - Make tools/nounce2key @echo "+ flash-bootrom - Make bootrom and flash it"
@echo + clean - Clean in bootrom, armsrc and the OS-specific host directory @echo "+ flash-os - Make armsrc and flash os image (includes fpga)"
@echo "+ flash-all - Make bootrom and armsrc and flash bootrom and os image"
@echo "+ recovery - Make bootrom and armsrc images for JTAG flashing"
@echo
@echo "+ client - Make only the OS-specific host client"
@echo "+ mfkey - Make tools/mfkey"
@echo "+ nounce2key - Make tools/nounce2key"
@echo
@echo "+ style - Apply some automated source code formatting rules"
@echo "+ checks - Detect various encoding issues in source code"
@echo
@echo "Possible platforms: try \"make PLATFORM=\" for more info, default is PM3RDV4"
@echo "To activate verbose mode, use make V=1"
client: client/all client: client/all
bootrom: bootrom/all
os: armsrc/all
recovery: recovery/all
mfkey: mfkey/all
nonce2key: nonce2key/all
flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL) flash-bootrom: bootrom/obj/bootrom.elf $(FLASH_TOOL)
$(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<) $(FLASH_TOOL) $(FLASH_PORT) -b $(subst /,$(PATHSEP),$<)
@ -69,16 +107,31 @@ newtarbin:
@touch proxmark3-$(platform)-bin.tar @touch proxmark3-$(platform)-bin.tar
tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin tarbin: newtarbin client/tarbin armsrc/tarbin bootrom/tarbin
$(GZIP) proxmark3-$(platform)-bin.tar $(info GEN proxmark3-$(platform)-bin.tar)
$(Q)$(GZIP) proxmark3-$(platform)-bin.tar
# configure system # detect if there were changes in the platform definitions, requiring a clean
# - to ignore PM3 device as a modem (blacklist) cleanifplatformchanged:
# - add user to the dialout group ifeq ($(PLATFORM_CHANGED), true)
# you may need to logout, relogin to get this access right correct. $(info [!] Platform definitions changed, cleaning bootrom/armsrc/recovery first...)
# Finally, you might need to run the proxmark3 client under SUDO on some systems $(Q)$(MAKE) --no-print-directory -C bootrom clean
$(Q)$(MAKE) --no-print-directory -C armsrc clean
$(Q)$(MAKE) --no-print-directory -C recovery clean
$(Q)echo CACHED_PLATFORM=$(PLATFORM) > .Makefile.options.cache
$(Q)echo CACHED_PLATFORM_EXTRAS=$(PLATFORM_EXTRAS) >> .Makefile.options.cache
$(Q)echo CACHED_PLATFORM_DEFS=$(PLATFORM_DEFS) >> .Makefile.options.cache
endif
# configure system to ignore PM3 device as a modem (ModemManager blacklist, effective *only* if ModemManager is not using _strict_ policy)
# Read doc/md/ModemManager-Must-Be-Discarded.md for more info
udev: udev:
sudo cp -rf driver/77-pm3-usb-device-blacklist.rules /etc/udev/rules.d/77-pm3-usb-device-blacklist.rules sudo cp -rf driver/77-pm3-usb-device-blacklist.rules /etc/udev/rules.d/77-pm3-usb-device-blacklist.rules
sudo udevadm control --reload-rules sudo udevadm control --reload-rules
# configure system to add user to the dialout group
# you need to logout, relogin to get this access right correct.
# Finally, you might need to run the proxmark3 client under SUDO on some systems
accessrights:
ifneq ($(wildcard /etc/arch-release),) #If user is running ArchLinux ifneq ($(wildcard /etc/arch-release),) #If user is running ArchLinux
sudo usermod -aG uucp $(USER) #Use specific command and group sudo usermod -aG uucp $(USER) #Use specific command and group
else else
@ -88,5 +141,25 @@ endif
# easy printing of MAKE VARIABLES # easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)
style:
# Make sure astyle is installed
@which astyle >/dev/null || ( echo "Please install 'astyle' package first" ; exit 1 )
# Remove spaces & tabs at EOL, add LF at EOF if needed on *.c, *.h, *.cpp. *.lua, *.py, *.pl, Makefile
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
-exec perl -pi -e 's/[ \t]+$$//' {} \; \
-exec sh -c "tail -c1 {} | xxd -p | tail -1 | grep -q -v 0a$$" \; \
-exec sh -c "echo >> {}" \;
# Apply astyle on *.c, *.h, *.cpp
find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec astyle --formatted --mode=c --suffix=none \
--indent=spaces=4 --indent-switches \
--keep-one-line-blocks --max-instatement-indent=60 \
--style=google --pad-oper --unpad-paren --pad-header \
--align-pointer=name {} \;
# Detecting weird codepages.
checks:
find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" -or -name "*.py" -or -name "*.pl" -or -name "Makefile" \) \
-exec sh -c "cat {} |recode utf8.. >/dev/null || echo {}" \;
# Dummy target to test for GNU make availability # Dummy target to test for GNU make availability
_test: _test:

4
Makefile.platform.sample Normal file
View file

@ -0,0 +1,4 @@
# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
PLATFORM=PM3RDV4
#PLATFORM_EXTRAS=BTADDON
#STANDALONE=LF_SAMYRUN

190
README.md
View file

@ -1,178 +1,76 @@
Proxmark3 RDV40 dedicated repo, based on iceman fork # Proxmark3 RDV4.0 Dedicated Github
===============
This repo is based on iceman fork for Proxmark3. It is dedicated to bringing the most out of the new features for Proxmark3 RDV4.0 new hardware and design.
[![Build status](https://ci.appveyor.com/api/projects/status/ct5blik2wa96bv0x/branch/master?svg=true)](https://ci.appveyor.com/project/iceman1001/proxmark3-ji4wj/branch/master)
[![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest) [![Latest release](https://img.shields.io/github/release/RfidResearchGroup/proxmark3.svg)](https://github.com/RfidResearchGroup/proxmark3/releases/latest)
## Notice ---
This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device.
## Coverity Scan Config & Run # PROXMARK INSTALLATION AND OVERVIEW
Download the Coverity Scan Self-buld and install it.
You will need to configure ARM-NON-EABI- Compiler for it to use:
- Configure | FAQ's & Updates | Installation | Use of the Proxmark |
| ------------------- |:-------------------:| -------------------:|
|[What has changed?](#what-has-changed) | [Setup and build for Linux](/doc/md/Installation_Instructions/Linux-Installation-Instructions.md) | [Compilation Instructions](/doc/md/Use_of_Proxmark/0_Compilation-Instructions.md)|
|[Development](#development) | [Important notes on ModemManager for Linux users](/doc/md/Installation_Instructions/ModemManager-Must-Be-Discarded.md) | [Validating proxmark client functionality](/doc/md/Use_of_Proxmark/1_Validation.md) |
|[Why didn't you base it on official PM3 Master?](#why-didnt-you-base-it-on-official-pm3-master)| [Homebrew (Mac OS X) & Upgrading HomeBrew Tap Formula](/doc/md/Installation_Instructions/Mac-OS-X-Homebrew-Installation-Instructions.md) | [First Use and Verification](/doc/md/Use_of_Proxmark/2_Configuration-and-Verification.md)|
|[PM3 GUI](#pm3-gui)|[Setup and build for Windows](/doc/md/Installation_Instructions/Windows-Installation-Instructions.md)|[Commands & Features](/doc/md/Use_of_Proxmark/3_Commands-and-Features.md)|
|[Issues](#issues)|[Blue shark manual](/doc/bt_manual_v10.md) ||
|[Notes on UART](/doc/uart_notes.md)|||
|[Notes on Frame format](/doc/new_frame_format.md)|||
|[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode) ||
|[Donations](#Donations)|||
`cov-configure --comptype gcc --compiler /opt/devkitpro/devkitARM/bin/arm-none-eabi-gcc` ## What has changed?
- Run it (I'm running on Ubuntu) On the hardware side:
`cov-build --dir cov-int make all`
- Make a tarball
`tar czvf proxmark3.tgz cov-int`
- Upload it to coverity.com
## Whats changed?
* added flash memory 256kb. * added flash memory 256kb.
* added smart card module * added smart card module
* added FPC connector * added FPC connector
--- On the software side: quite a lot, see the [Changelog file](CHANGELOG.md).
## Why didn't you based it on offical PM3 Master?
The separation from offical pm3 repo gives us very much freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the offical pm3 repo with RDV40 specific code.
## Why don't you add this or that functionality?
Give us a hint, and we'll see if we can't merge in the stuff you have.
## PM3 GUI
The official PM3-GUI from Gaucho will not work.
The new universial GUI will work.
## Development ## Development
This fork now compiles just fine on This fork now compiles just fine on
- Windows/mingw environment with Qt5.6.1 & GCC 4.8 - Windows/mingw environment with Qt5.6.1 & GCC 4.8
- Ubuntu 1404, 1510, 1604 - Ubuntu 1404, 1510, 1604, 1804, 1904
- Mac OS X / Homebrew - Mac OS X / Homebrew
- ParrotOS
- WSL (Windows subsystem linux) on Windows 10
- Docker container - Docker container
## Setup and build for UBUNTU If you intend to contribute to the code, please read the [coding style notes](HACKING.md) first.
GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04
See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux
A nice and cool install script made by @daveio is found here: - Internal notes on [Coverity Scan Config & Run](/doc/md/Development/Coverity-Scan-Config-%26-Run.md).
https://github.com/daveio/attacksurface/blob/master/proxmark3/pm3-setup.sh - Internal notes on UART
I have also added this script to the fork. - Internal notes on Frame format
https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh - Internal notes on standalone mode
- Run
`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi`
- Clone fork
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
- Get the latest commits
`git pull`
- Install the blacklist rules and add user to dialout group (if you on a Linux/ubuntu/debian). If you do this one, you need to logout and login in again to make sure your rights got changed.
`make udev`
- Clean and complete compilation
`make clean && make all`
- Flash the BOOTROM & FULLIMAGE
`client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf`
- Change into the client folder
`cd client`
- Run the client
`./proxmark3 /dev/ttyACM0`
## Setup and build for ArchLinux
- Run
`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed`
`yaourt -S termcap`
- Clone fork
`git clone https://github.com/RfidResearchGroup/proxmark3.git`
- Get the latest commits
`git pull`
- Install the blacklist rules and add user to dialout group (if you on a Linux/ubuntu/debian). If you do this one, you need to logout and login in again to make sure your rights got changed.
`make udev`
- Clean and complete compilation
`make clean && make all`
- Flash the BOOTROM & FULLIMAGE
`client/flasher /dev/ttyACM0 -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf`
- Change into the client folder
`cd client`
- Run the client
`./proxmark3 /dev/ttyACM0`
## Homebrew (Mac OS X)
These instructions comes from @Chrisfu, where I got the proxmark3.rb scriptfile from.
Further questions about Mac & Homebrew, contact @Chrisfu (https://github.com/chrisfu/)
1. Install homebrew if you haven't yet already done so: http://brew.sh/
2. Tap this repo: `brew tap RfidResearchGroup/proxmark3`
3. Install Proxmark3: `brew install proxmark3` for stable release or `brew install --HEAD proxmark3` for latest non-stable from GitHub.
Upgrading HomeBrew tap formula
-----------------------------
*This method is useful for those looking to run bleeding-edge versions of iceman's client. Keep this in mind when attempting to update your HomeBrew tap formula as this procedure could easily cause a build to break if an update is unstable on macOS.*
Tested on macOS High Sierra 10.13.2
*Note: This assumes you have already installed iceman's fork from HomeBrew as mentioned above*
1. Force HomeBrew to pull the latest source from github
`brew upgrade --fetch-HEAD RfidResearchGroup/proxmark3`
2. Flash the bootloader & fullimage.elf
* With your Proxmark3 unplugged from your machine, press and hold the button on your Proxmark 3 as you plug it into a USB port. Continue to hold the button until after this step is complete and the `proxmark3-flasher` command outputs "Have a nice day!"*
`$ sudo proxmark3-flasher /dev/tty.usbmodem881 -b /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/bootrom.elf /usr/local/Cellar/proxmark3/HEAD-6a710ef/share/firmware/fullimage.elf`
`$ sudo proxmark3-flasher /dev/tty.usbmodem881 `
4. Enjoy the update ## Why didn't you base it on official Proxmark3 Master?
The separation from official Proxmark3 repo gives us a lot of freedom to create a firmware/client that suits the RDV40 features. We don't want to mess up the official Proxmark3 repo with RDV40 specific code.
## Building on Windows ## Proxmark3 GUI
The official PM3-GUI from Gaucho will not work.
The new universal GUI will work. [Proxmark3 Universal GUI](https://github.com/burma69/PM3UniversalGUI) Almost, change needed in order to show helptext when client isn't connected to a device.
### Gator96100 distro ## Issues
Rather than download and install every one of these packages, a new ProxSpace
environment archive file will be made available for download on the project
page at @Gator96100's repo
Afterwards just clone the iceman repo or download someone elses. Please see the [Proxmark Forum](http://www.proxmark.org/forum/index.php) and see if your issue is listed in the first instance Google is your friend :) Questions will be answered via the forum by Iceman and the team.
Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/)
Links It's needed to have a good USB cable to connect Proxmark3 to USB. If you have stability problems (Proxmark3 resets, firmware hangs, especially firmware hangs just after start, etc.) - check your cable with a USB tester (or try to change it). It needs to have a resistance smaller or equal to 0.3 Ohm.
- https://github.com/Gator96100/ProxSpace/archive/master.zip
- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0)
## The end
### 7. Build and run - [@herrmann1001](https://mobile.twitter.com/herrmann1001) July 2018
- updated Feb 2019 [@5w0rdfish](https://mobile.twitter.com/5w0rdFish)
- Clone fork # Donations
`git clone https://github.com/RfidResearchGroup/proxmark3.git` Nothing says thank you as much as a donation. So if you feel the love, do feel free to become a iceman patron. For some tiers it comes with rewards.
- Get the latest commits https://www.patreon.com/iceman1001
`git pull`
- CLEAN COMPILE All support is welcome!
`make clean && make all`
Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark software where "X" is the com port number assigned to proxmark3 under Windows.
- Flash the BOOTROM & FULLIMAGE
`client/flasher.exe comX -b bootrom/obj/bootrom.elf armsrc/obj/fullimage.elf`
- Change into the client folder
`cd client`
- Run the client
`proxmark3.exe comX`
iceman at host iuse.se
July 2018, Sweden

View file

@ -66,9 +66,20 @@ clone_script:
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Fill msys\etc\fstab file..." -NoNewLine Write-Host "Fill msys2\etc\fstab file..." -NoNewLine
New-Item c:\ProxSpace\msys\etc\fstab -type file -force -value "#Win32_Path Mount_Point`nc:\ProxSpace\devkitARM /devkitARM`nc:\ProxSpace\Qt\5.6 /qt `nc:\ProxSpace\pm3 /pm3`n" New-Item c:\ProxSpace\msys2\etc\fstab -type file -force -value "# For a description of the file format, see the Users Guide`n# http://cygwin.com/cygwin-ug-net/using.html#mount-table`nnone / cygdrive binary,posix=0,noacl,user 0 0 `nC:\ProxSpace\pm3 /pm3 ntfs noacl 0 0 `nC:\ProxSpace\gcc-arm-none-eabi /gcc-arm-none-eabi ntfs noacl 0 0 `n"
Write-Host "[ OK ]" -ForegroundColor Green
Write-Host "Update msys2 packages..." -NoNewLine
$env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
install: install:
@ -84,12 +95,25 @@ install:
} }
build_script: build_script:
- ps: >- - ps: >-
$env:Path = "C:\ProxSpace\msys\bin;$env:Path" "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path"
$env:MINGW_HOME="C:\ProxSpace\msys2\mingw32"
$env:MSYS_HOME="C:\ProxSpace\msys2"
$env:MSYSTEM="MINGW32"
$env:MINGW_PREFIX="/mingw32"
$env:SHELL="/bin/bash"
$env:MSYSTEM_CHOST="i686-w64-mingw32"
#make #make
bash -lc -i "pwd;make all" bash -c -i 'pwd;make clean;make all'
#some checks #some checks
@ -137,6 +161,24 @@ build_script:
Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables Copy-Item C:\ProxSpace\pm3\client\hardnested\tables\*.bin.z C:\ProxSpace\Release\hardnested\tables
# dll files
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libgcc_s_dw2-1.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libstdc++-6.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libwinpthread-1.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Core.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Gui.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\Qt5Widgets.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libreadline*.dll C:\ProxSpace\Release
Copy-Item C:\ProxSpace\msys2\mingw32\bin\libtermcap-0.dll C:\ProxSpace\Release
Write-Host "[ OK ]" -ForegroundColor Green Write-Host "[ OK ]" -ForegroundColor Green
@ -232,8 +274,8 @@ test_script:
#--- end Job #--- end Job
[bool]$res=$false [bool]$res=$false
# Wait 60 sec timeout for Job # Wait 180 sec timeout for Job
if(Wait-Job $Job -Timeout 60){ if(Wait-Job $Job -Timeout 180){
$Results = $Job | Receive-Job $Results = $Job | Receive-Job
if($Results -like "true"){ if($Results -like "true"){
$res=$true $res=$true
@ -268,13 +310,22 @@ test_script:
#proxmark logic tests #proxmark logic tests
ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q Execute && echo Passed || echo Failed'} ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q wait && echo Passed || echo Failed'}
ExecTest "proxmark help hardnested" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q hardnested && echo Passed || echo Failed'} ExecTest "proxmark help text ISO7816" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q ISO7816 && echo Passed || echo Failed'}
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf'"} "at_enc" ExecTest "proxmark help text hardnested" "proxmark3 -t" {bash -lc 'cd ~/client;./proxmark3 -t 2>&1 | grep -q hardnested && echo Passed || echo Failed'}
ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf'"} "at_enc"
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 -c 'hf mf hardnested t 1 000000000000'"} "found:"
#proxmark crypto tests
ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 -c 'emv test'"} "Test?s? ? OK"
ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf hardnested t 1 000000000000'"} "found:"
if ($global:TestsPassed) { if ($global:TestsPassed) {
Write-Host "Tests [ OK ]" -ForegroundColor Green Write-Host "Tests [ OK ]" -ForegroundColor Green

View file

@ -30,8 +30,8 @@ static uint16_t BigBuf_hi = BIGBUF_SIZE;
static uint8_t *emulator_memory = NULL; static uint8_t *emulator_memory = NULL;
// trace related variables // trace related variables
static uint16_t traceLen = 0; static uint32_t traceLen = 0;
int tracing = 1; //Last global one.. todo static? static bool tracing = true; //todo static?
// get the address of BigBuf // get the address of BigBuf
uint8_t *BigBuf_get_addr(void) { uint8_t *BigBuf_get_addr(void) {
@ -96,10 +96,10 @@ void BigBuf_free_keep_EM(void) {
} }
void BigBuf_print_status(void) { void BigBuf_print_status(void) {
Dbprintf("Memory"); DbpString(_BLUE_("Memory"));
Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE);
Dbprintf(" Available memory........%d", BigBuf_hi); Dbprintf(" Available memory........%d", BigBuf_hi);
Dbprintf("Tracing"); DbpString(_BLUE_("Tracing"));
Dbprintf(" tracing ................%d", tracing); Dbprintf(" tracing ................%d", tracing);
Dbprintf(" traceLen ...............%d", traceLen); Dbprintf(" traceLen ...............%d", traceLen);
} }
@ -112,7 +112,7 @@ uint16_t BigBuf_max_traceLen(void) {
void clear_trace(void) { void clear_trace(void) {
traceLen = 0; traceLen = 0;
} }
void set_tracelen(uint16_t value) { void set_tracelen(uint32_t value) {
traceLen = value; traceLen = value;
} }
void set_tracing(bool enable) { void set_tracing(bool enable) {
@ -127,7 +127,7 @@ bool get_tracing(void) {
* Get the number of bytes traced * Get the number of bytes traced
* @return * @return
*/ */
uint16_t BigBuf_get_traceLen(void) { uint32_t BigBuf_get_traceLen(void) {
return traceLen; return traceLen;
} }
@ -142,8 +142,8 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
uint8_t *trace = BigBuf_get_addr(); uint8_t *trace = BigBuf_get_addr();
uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity uint32_t num_paritybytes = (iLen - 1) / 8 + 1; // number of valid paritybytes in *parity
uint16_t duration = timestamp_end - timestamp_start; uint32_t duration = timestamp_end - timestamp_start;
// Return when trace is full // Return when trace is full
if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) { if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) {
@ -195,47 +195,6 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_
return true; return true;
} }
int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) {
/**
Todo, rewrite the logger to use the generic functionality instead. It should be noted, however,
that this logger takes number of bits as argument, not number of bytes.
**/
if (!tracing) return false;
uint8_t *trace = BigBuf_get_addr();
uint16_t iLen = nbytes(iBits);
// Return when trace is full
if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false;
//Hitag traces appear to use this traceformat:
// 32 bits timestamp (little endian,Highest Bit used as readerToTag flag)
// 32 bits parity
// 8 bits size (number of bits in the trace entry, not number of bytes)
// y Bytes data
rsamples += iSamples;
trace[traceLen++] = ((rsamples >> 0) & 0xff);
trace[traceLen++] = ((rsamples >> 8) & 0xff);
trace[traceLen++] = ((rsamples >> 16) & 0xff);
trace[traceLen++] = ((rsamples >> 24) & 0xff);
if (!readerToTag) {
trace[traceLen - 1] |= 0x80;
}
trace[traceLen++] = ((dwParity >> 0) & 0xff);
trace[traceLen++] = ((dwParity >> 8) & 0xff);
trace[traceLen++] = ((dwParity >> 16) & 0xff);
trace[traceLen++] = ((dwParity >> 24) & 0xff);
trace[traceLen++] = iBits;
memcpy(trace + traceLen, btBytes, iLen);
traceLen += iLen;
return true;
}
// Emulator memory // Emulator memory
uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) { uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length) {
uint8_t *mem = BigBuf_get_EM_addr(); uint8_t *mem = BigBuf_get_EM_addr();

View file

@ -25,23 +25,22 @@
#define CARD_MEMORY_SIZE 4096 #define CARD_MEMORY_SIZE 4096
#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? #define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!?
extern uint8_t *BigBuf_get_addr(void); uint8_t *BigBuf_get_addr(void);
extern uint8_t *BigBuf_get_EM_addr(void); uint8_t *BigBuf_get_EM_addr(void);
extern uint16_t BigBuf_max_traceLen(void); uint16_t BigBuf_max_traceLen(void);
extern void BigBuf_Clear(void); void BigBuf_Clear(void);
extern void BigBuf_Clear_ext(bool verbose); void BigBuf_Clear_ext(bool verbose);
extern void BigBuf_Clear_keep_EM(void); void BigBuf_Clear_keep_EM(void);
extern void BigBuf_Clear_EM(void); void BigBuf_Clear_EM(void);
extern uint8_t *BigBuf_malloc(uint16_t); uint8_t *BigBuf_malloc(uint16_t);
extern void BigBuf_free(void); void BigBuf_free(void);
extern void BigBuf_free_keep_EM(void); void BigBuf_free_keep_EM(void);
extern void BigBuf_print_status(void); void BigBuf_print_status(void);
extern uint16_t BigBuf_get_traceLen(void); uint32_t BigBuf_get_traceLen(void);
extern void clear_trace(void); void clear_trace(void);
extern void set_tracing(bool enable); void set_tracing(bool enable);
extern void set_tracelen(uint16_t value); void set_tracelen(uint32_t value);
extern bool get_tracing(void); bool get_tracing(void);
extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
extern uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length);
#endif /* __BIGBUF_H */ #endif /* __BIGBUF_H */

View file

@ -7,8 +7,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "LCD.h" #include "LCD.h"
void LCDSend(unsigned int data) void LCDSend(unsigned int data) {
{
// 9th bit set for data, clear for command // 9th bit set for data, clear for command
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete
// For clarity's sake we pass data with 9th bit clear and commands with 9th // For clarity's sake we pass data with 9th bit clear and commands with 9th
@ -16,8 +15,7 @@ void LCDSend(unsigned int data)
AT91C_BASE_SPI->SPI_TDR = data ^ 0x100; // Send the data/command AT91C_BASE_SPI->SPI_TDR = data ^ 0x100; // Send the data/command
} }
void LCDSetXY(unsigned char x, unsigned char y) void LCDSetXY(unsigned char x, unsigned char y) {
{
LCDSend(PPASET); // page start/end ram LCDSend(PPASET); // page start/end ram
LCDSend(y); // Start Page to display to LCDSend(y); // Start Page to display to
LCDSend(131); // End Page to display to LCDSend(131); // End Page to display to
@ -27,19 +25,16 @@ void LCDSetXY(unsigned char x, unsigned char y)
LCDSend(131); // End Column to display to LCDSend(131); // End Column to display to
} }
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color) void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color) {
{
LCDSetXY(x, y); // Set position LCDSetXY(x, y); // Set position
LCDSend(PRAMWR); // Now write the pixel to the display LCDSend(PRAMWR); // Now write the pixel to the display
LCDSend(color); // Write the data in the specified Color LCDSend(color); // Write the data in the specified Color
} }
void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color) void LCDFill(unsigned char xs, unsigned char ys, unsigned char width, unsigned char height, unsigned char color) {
{
unsigned char i, j; unsigned char i, j;
for (i=0;i < height;i++) // Number of horizontal lines for (i = 0; i < height; i++) { // Number of horizontal lines
{
LCDSetXY(xs, ys + i); // Goto start of fill area (Top Left) LCDSetXY(xs, ys + i); // Goto start of fill area (Top Left)
LCDSend(PRAMWR); // Write to display LCDSend(PRAMWR); // Write to display
@ -48,8 +43,7 @@ void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned cha
} }
} }
void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) void LCDString(char *lcd_string, const char *font_style, unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) {
{
unsigned int i; unsigned int i;
unsigned char mask = 0, px, py, xme, yme, offset; unsigned char mask = 0, px, py, xme, yme, offset;
const char *data; const char *data;
@ -62,8 +56,7 @@ void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsign
data++; data++;
offset = *data; // get data bytes per font offset = *data; // get data bytes per font
do do {
{
// point to data in table to be loaded // point to data in table to be loaded
data = (font_style + offset) + (offset * (int)(*lcd_string - 32)); data = (font_style + offset) + (offset * (int)(*lcd_string - 32));
@ -87,8 +80,7 @@ void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsign
} while (*lcd_string != '\0'); // keep spitting chars out until end of string } while (*lcd_string != '\0'); // keep spitting chars out until end of string
} }
void LCDReset(void) void LCDReset(void) {
{
LED_A_ON(); LED_A_ON();
SetupSpi(SPI_LCD_MODE); SetupSpi(SPI_LCD_MODE);
LOW(GPIO_LRST); LOW(GPIO_LRST);
@ -99,8 +91,7 @@ void LCDReset(void)
LED_A_OFF(); LED_A_OFF();
} }
void LCDInit(void) void LCDInit(void) {
{
int i; int i;
LCDReset(); LCDReset();

View file

@ -1,4 +1,3 @@
#-----------------------------------------------------------------------------
# This code is licensed to you under the terms of the GNU GPL, version 2 or, # 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 # at your option, any later version. See the LICENSE.txt file for the text of
# the license. # the license.
@ -8,54 +7,34 @@
APP_INCLUDES = apps.h APP_INCLUDES = apps.h
# This Makefile might have been called directly, not via the root Makefile, so:
ifeq ($(PLTNAME),)
-include ../Makefile.platform
-include ../.Makefile.options.cache
include ../common/Makefile.hal
# detect if there were changes in the platform definitions, requiring a clean
ifeq ($(PLATFORM_CHANGED), true)
$(error platform definitions have been changed, please "make clean" at the root of the project)
endif
endif
#remove one of the following defines and comment out the relevant line #remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation. #in the next section to remove that particular feature from compilation.
# NO space,TABs after the "\" sign. # NO space,TABs after the "\" sign.
APP_CFLAGS = -DWITH_CRC \ APP_CFLAGS = $(PLATFORM_DEFS) \
-DON_DEVICE \ -DON_DEVICE \
-DWITH_LF \
-DWITH_HITAG \
-DWITH_ISO15693 \
-DWITH_LEGICRF \
-DWITH_ISO14443b \
-DWITH_ISO14443a \
-DWITH_ICLASS \
-DWITH_FELICA \
-DWITH_FLASH \
-DWITH_SMARTCARD \
-DWITH_HFSNOOP \
-DWITH_LF_SAMYRUN \
-DWITH_FPC \
-fno-strict-aliasing -ffunction-sections -fdata-sections -fno-strict-aliasing -ffunction-sections -fdata-sections
### IMPORTANT - move the commented variable below this line SRC_LF = lfops.c lfsampling.c pcf7931.c lfdemod.c
# -DWITH_LCD \
# -DWITH_EMV \
# -DWITH_FPC \
#
# Standalone Mods
#-------------------------------------------------------
# -DWITH_LF_ICERUN
# -DWITH_LF_SAMYRUN
# -DWITH_LF_PROXBRUTE
# -DWITH_LF_HIDBRUTE
# -DWITH_HF_YOUNG
# -DWITH_HF_MATTYRUN
# -DWITH_HF_COLIN
SRC_LCD = fonts.c LCD.c
SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c
SRC_ISO15693 = iso15693.c iso15693tools.c SRC_ISO15693 = iso15693.c iso15693tools.c
#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c
SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c
SRC_ISO14443b = iso14443b.c SRC_ISO14443b = iso14443b.c
SRC_FELICA = felica.c SRC_FELICA = felica.c
SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c
SRC_CRC = crc.c crc16.c crc32.c SRC_CRC = crc.c crc16.c crc32.c
SRC_ICLASS = iclass.c optimized_cipher.c SRC_ICLASS = iclass.c optimized_cipher.c
SRC_LEGIC = legicrf.c legic_prng.c SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c
SRC_BEE = bee.c # SRC_BEE = bee.c
# RDV40 related hardware support # RDV40 related hardware support
ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS))) ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS)))
@ -70,41 +49,59 @@ else
SRC_SMARTCARD = SRC_SMARTCARD =
endif endif
ifneq (,$(findstring WITH_FPC,$(APP_CFLAGS))) ifneq (,$(findstring WITH_FPC_USART,$(APP_CFLAGS)))
SRC_FPC = usart.c SRC_FPC = usart.c
else else
SRC_FPC = SRC_FPC =
endif endif
# Generic standalone Mode injection of source code ifneq (,$(findstring WITH_HITAG,$(APP_CFLAGS)))
SRC_STANDALONE = SRC_HITAG = hitag2_crypto.c hitag2.c hitagS.c
# WITH_LF_ICERUN else
ifneq (,$(findstring WITH_LF_ICERUN,$(APP_CFLAGS))) SRC_HITAG =
SRC_STANDALONE =
endif endif
# WITH_LF_SAMYRUN
ifneq (,$(findstring WITH_LF_SAMYRUN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_LCD,$(APP_CFLAGS)))
SRC_LCD = fonts.c LCD.c
else
SRC_LCD =
endif
# Generic standalone Mode injection of source code
SRC_STANDALONE = placeholder.c
# WITH_STANDALONE_LF_ICERUN
ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
SRC_STANDALONE = lf_icerun.c
endif
# WITH_STANDALONE_LF_SAMYRUN
ifneq (,$(findstring WITH_STANDALONE_LF_SAMYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = lf_samyrun.c SRC_STANDALONE = lf_samyrun.c
endif endif
# WITH_LF_PROXBRUTE # WITH_STANDALONE_LF_PROXBRUTE
ifneq (,$(findstring WITH_LF_PROXBRUTE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_PROXBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_proxbrute.c SRC_STANDALONE = lf_proxbrute.c
endif endif
# WITH_LF_HIDBRUTE # WITH_STANDALONE_LF_HIDBRUTE
ifneq (,$(findstring WITH_LF_HIDBRUTE,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_HIDBRUTE,$(APP_CFLAGS)))
SRC_STANDALONE = lf_hidbrute.c SRC_STANDALONE = lf_hidbrute.c
endif endif
# WITH_HF_YOUNG # WITH_STANDALONE_HF_YOUNG
ifneq (,$(findstring WITH_HF_YOUNG,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_YOUNG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_young.c SRC_STANDALONE = hf_young.c
endif endif
# WITH_HF_MATTYRUN # WITH_STANDALONE_HF_MATTYRUN
ifneq (,$(findstring WITH_HF_MATTYRUN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_MATTYRUN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_mattyrun.c SRC_STANDALONE = hf_mattyrun.c
endif endif
# WITH_HF_COLIN # WITH_STANDALONE_HF_COLIN
ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_HF_COLIN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_colin.c vtsend.c SRC_STANDALONE = vtsend.c hf_colin.c
endif
# WITH_STANDALONE_HF_BOG
ifneq (,$(findstring WITH_STANDALONE_HF_BOG,$(APP_CFLAGS)))
SRC_STANDALONE = hf_bog.c
endif endif
#the FPGA bitstream files. Note: order matters! #the FPGA bitstream files. Note: order matters!
@ -118,8 +115,9 @@ APP_CFLAGS += $(ZLIB_CFLAGS)
# zlib includes: # zlib includes:
APP_CFLAGS += -I../zlib APP_CFLAGS += -I../zlib
# stdint.h provided locally until GCC 4.5 becomes C99 compliant # stdint.h provided locally until GCC 4.5 becomes C99 compliant,
APP_CFLAGS += -I. # stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
APP_CFLAGS += -I. -fno-stack-protector -fno-pie
# Compile these in thumb mode (small size) # Compile these in thumb mode (small size)
THUMBSRC = start.c \ THUMBSRC = start.c \
@ -132,13 +130,14 @@ THUMBSRC = start.c \
$(SRC_FLASH) \ $(SRC_FLASH) \
$(SRC_SMARTCARD) \ $(SRC_SMARTCARD) \
$(SRC_FPC) \ $(SRC_FPC) \
$(SRC_HITAG) \
appmain.c \ appmain.c \
printf.c \ printf.c \
commonutil.c \
util.c \ util.c \
string.c \ string.c \
BigBuf.c \ BigBuf.c \
ticks.c \ ticks.c \
random.c \
hfsnoop.c hfsnoop.c
@ -171,56 +170,76 @@ all: $(OBJS)
.DELETE_ON_ERROR: .DELETE_ON_ERROR:
# version.c should be remade on every compilation # version.c should be remade on every time fullimage.stage1.elf should be remade
.PHONY: version.c version.c: default_version.c $(OBJDIR)/fpga_version_info.o $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
version.c: default_version.c $(info [-] GEN $@)
perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ $(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ $(info [-] GEN $@)
$(Q)$(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@
$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z $(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ $(info [-] GEN $@)
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@
$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR)
$(info [-] GEN $@)
ifeq ($(Q),@)
@$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ >/dev/null
else
$(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@
endif
$(FPGA_COMPRESSOR): $(FPGA_COMPRESSOR):
make -C ../client $(notdir $(FPGA_COMPRESSOR)) $(info [*] MAKE $@)
$(Q)$(MAKE) --no-print-directory -C ../client $(notdir $(FPGA_COMPRESSOR))
$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ)
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(info [=] LD $@)
$(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf $(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf
$(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ $(info [-] GEN $@)
$(Q)$(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@
$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin $(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ $(info [-] GEN $@)
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@
$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf $(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf
$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ $(info [-] GEN $@)
$(Q)$(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@
$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) $(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR)
$(info [-] GEN $@)
ifeq ($(Q),@)
@$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ >/dev/null
else
$(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@
endif
$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z $(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z
$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ $(info [-] GEN $@)
$(Q)$(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@
$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o $(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o
$(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(info [=] LD $@)
$(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^
tarbin: $(OBJS) tarbin: $(OBJS)
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) $(info TAR $@)
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf)
clean: clean:
$(DELETE) $(OBJDIR)$(PATHSEP)*.o $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
$(DELETE) $(OBJDIR)$(PATHSEP)*.elf $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
$(DELETE) $(OBJDIR)$(PATHSEP)*.map $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.map
$(DELETE) $(OBJDIR)$(PATHSEP)*.d $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.d
$(DELETE) $(OBJDIR)$(PATHSEP)*.z $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.z
$(DELETE) $(OBJDIR)$(PATHSEP)*.bin $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.bin
$(DELETE) version.c $(Q)$(DELETE) version.c
.PHONY: all clean help .PHONY: all clean help
help: help:

303
armsrc/Standalone/hf_bog.c Normal file
View file

@ -0,0 +1,303 @@
//-----------------------------------------------------------------------------
// 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 standalone HF Sniff (and ULC/NTAG/ULEV1 pwd storing)
//-----------------------------------------------------------------------------
/*
This can actually be used in two separate ways.
It can either be used to just HF 14a sniff on the go and/or grab the
authentication attempts for ULC/NTAG/ULEV1 into the flash mem (RDV4).
The retrieved sniffing session can be acquired by connecting the device
to a client that supports the reconnect capability and issue 'hf 14a list'.
In order to view the grabbed authentication attempts in the flash mem,
you can simply run 'script run read_pwd_mem' or just 'mem read l 256'
from the client to view the stored quadlets.
*/
#include "hf_bog.h"
#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8)
#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8)
// Maximum number of auth attempts per standalone session
#define MAX_PWDS_PER_SESSION 64
uint8_t FindOffsetInFlash() {
uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 };
uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF };
uint8_t memcnt = 0;
while (memcnt < 0xFF) {
Flash_ReadData(memcnt, mem, 4);
if (memcmp(mem, eom, 4) == 0) {
return memcnt;
}
memcnt += 4;
}
return 0; // wrap-around
}
void EraseMemory() {
if (!FlashInit()) {
return;
}
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase4k(0, 0);
if (DBGLEVEL > 1) Dbprintf("[!] Erased flash!");
FlashStop();
SpinDelay(100);
}
// This is actually copied from SniffIso14443a
void RAMFUNC SniffAndStore(uint8_t param) {
iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER);
// Allocate memory from BigBuf for some buffers
// free all previous allocations first
BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace();
set_tracing(true);
// Array to store the authpwds
uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION);
// The command (reader -> tag) that we're receiving.
uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE);
// The response (tag -> reader) that we're receiving.
uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE);
uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE);
// The DMA buffer, used to stream samples from the FPGA
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
uint8_t *data = dmaBuf;
uint8_t previous_data = 0;
int dataLen;
bool TagIsActive = false;
bool ReaderIsActive = false;
// Set up the demodulator for tag -> reader responses.
DemodInit(receivedResp, receivedRespPar);
// Set up the demodulator for the reader -> tag commands
UartInit(receivedCmd, receivedCmdPar);
// Setup and start DMA.
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, DMA_BUFFER_SIZE)) {
if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
return;
}
tUart *uart = GetUart();
tDemod *demod = GetDemod();
// We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a
// response from the tag.
// triggered == false -- to wait first for card
bool triggered = !(param & 0x03);
uint32_t my_rsamples = 0;
// Current captured passwords counter
uint8_t auth_attempts = 0;
SpinDelay(50);
// loop and listen
while (!BUTTON_PRESS()) {
WDT_HIT();
LED_A_ON();
int register readBufDataP = data - dmaBuf;
int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR;
if (readBufDataP <= dmaBufDataP)
dataLen = dmaBufDataP - readBufDataP;
else
dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP;
// test for length of buffer
if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly
Dbprintf("[!] blew circular buffer! | datalen %u", dataLen);
break;
}
if (dataLen < 1) continue;
// primary buffer was stopped( <-- we lost data!
if (!AT91C_BASE_PDC_SSC->PDC_RCR) {
AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE;
//Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary
}
// secondary buffer sets as primary, secondary buffer was stopped
if (!AT91C_BASE_PDC_SSC->PDC_RNCR) {
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf;
AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE;
}
LED_A_OFF();
// Need two samples to feed Miller and Manchester-Decoder
if (my_rsamples & 0x01) {
if (!TagIsActive) { // no need to try decoding reader data if the tag is sending
uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerdata, (my_rsamples - 1) * 4)) {
LED_C_ON();
// check - if there is a short 7bit request from reader
if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true;
if (triggered) {
if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) {
if (DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]);
// temporarily save the captured pwd in our array
memcpy(&capturedPwds[4 * auth_attempts], receivedCmd + 1, 4);
auth_attempts++;
}
if (!LogTrace(receivedCmd,
uart->len,
uart->startTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->endTime * 16 - DELAY_READER_AIR2ARM_AS_SNIFFER,
uart->parity,
true)) break;
}
/* ready to receive another command. */
UartReset();
/* reset the demod code, which might have been */
/* false-triggered by the commands from the reader. */
DemodReset();
LED_B_OFF();
}
ReaderIsActive = (uart->state != STATE_UNSYNCD);
}
// no need to try decoding tag data if the reader is sending - and we cannot afford the time
if (!ReaderIsActive) {
uint8_t tagdata = (previous_data << 4) | (*data & 0x0F);
if (ManchesterDecoding(tagdata, 0, (my_rsamples - 1) * 4)) {
LED_B_ON();
if (!LogTrace(receivedResp,
demod->len,
demod->startTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->endTime * 16 - DELAY_TAG_AIR2ARM_AS_SNIFFER,
demod->parity,
false)) break;
if ((!triggered) && (param & 0x01)) triggered = true;
// ready to receive another response.
DemodReset();
// reset the Miller decoder including its (now outdated) input buffer
UartReset();
//UartInit(receivedCmd, receivedCmdPar);
LED_C_OFF();
}
TagIsActive = (demod->state != DEMOD_UNSYNCD);
}
}
previous_data = *data;
my_rsamples++;
data++;
if (data == dmaBuf + DMA_BUFFER_SIZE) {
data = dmaBuf;
}
} // end main loop
FpgaDisableSscDma();
set_tracing(false);
Dbprintf("Stopped sniffing");
SpinDelay(200);
// Write stuff to flash
if (auth_attempts > 0) {
if (DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts);
// Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34)
FlashmemSetSpiBaudrate(48000000);
// Find the offset in flash mem to continue writing the auth attempts
uint8_t memoffset = FindOffsetInFlash();
if (DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset);
if ((memoffset + 4 * auth_attempts) > 0xFF) {
// We opt to keep the new data only
memoffset = 0;
if (DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data.");
}
// Get previous data from flash mem
uint8_t *previousdata = BigBuf_malloc(memoffset);
if (memoffset > 0) {
uint16_t readlen = Flash_ReadData(0, previousdata, memoffset);
if (DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen);
}
// create new bigbuf to hold all data
size_t total_size = memoffset + 4 * auth_attempts;
uint8_t *total_data = BigBuf_malloc(total_size);
// Add the previousdata array into total_data array
memcpy(total_data, previousdata, memoffset);
// Copy bytes of capturedPwds immediately following bytes of previousdata
memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts);
// Erase first page of flash mem
EraseMemory();
// Write total data to flash mem
uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts);
if (DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen);
// If pwd saved successfully, blink led A three times
if (writelen > 0) {
SpinErr(0, 200, 5); // blink led A
}
SpinDelay(100);
// Reset the SPI Baudrate to the default value (24MHz)
FlashmemSetSpiBaudrate(24000000);
}
}
void ModInfo(void) {
DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)");
}
void RunMod() {
StandAloneMode();
Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<");
Dbprintf("Starting to sniff");
// param:
// bit 0 - trigger from first card answer
// bit 1 - trigger from first reader 7-bit request
SniffAndStore(0);
LEDsoff();
SpinDelay(300);
Dbprintf("- [ End ] -> You can take shell back ...");
Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords");
}

View file

@ -0,0 +1,26 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// StandAlone Mod
//-----------------------------------------------------------------------------
#ifndef __HF_BOG_H
#define __HF_BOG_H
#include "proxmark3.h"
#include "mifareutil.h"
#include "iso14443a.h"
#include "protocols.h"
#include "util.h"
#include "standalone.h" // standalone definitions
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
#include "apps.h"
#include "printf.h"
#include "parity.h"
#endif /* __HF_BOG_H */

File diff suppressed because it is too large Load diff

View file

@ -16,39 +16,44 @@
#ifndef __HF_COLIN_H #ifndef __HF_COLIN_H
#define __HF_COLIN_H #define __HF_COLIN_H
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
#include "standalone.h" // standalone definitions
#include "proxmark3.h" #include "proxmark3.h"
#include "mifaresim.h" // mifare1ksim
#include "mifareutil.h" #include "mifareutil.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "protocols.h" #include "protocols.h"
#include "util.h" #include "util.h"
#include "standalone.h" // standalone definitions
#include <stdbool.h> // for bool
#include <stdio.h>
#include <string.h>
#include "vtsend.h" #include "vtsend.h"
#include "apps.h" #include "apps.h"
#include "usb_cmd.h" // mifare1ksim flags #include "printf.h"
#define _RED_ "\x1b[31m" #define _XRED_ "\x1b[31m"
#define _GREEN_ "\x1b[32m" #define _XGREEN_ "\x1b[32m"
#define _YELLOW_ "\x1b[33m" #define _XYELLOW_ "\x1b[33m"
#define _BLUE_ "\x1b[34m" #define _XBLUE_ "\x1b[34m"
#define _MAGENTA_ "\x1b[35m" #define _XMAGENTA_ "\x1b[35m"
#define _CYAN_ "\x1b[36m" #define _XCYAN_ "\x1b[36m"
#define _WHITE_ "\x1b[0m" #define _XWHITE_ "\x1b[0m"
#define _ORANGE_ _YELLOW_ #define _XORANGE_ _XYELLOW_
int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key); int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key);
void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); int e_MifareECardLoad(uint32_t numofsectors, uint8_t keytype);
void saMifareMakeTag(void); void saMifareMakeTag(void);
int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug); void WriteTagToFlash(uint8_t index, size_t size);
const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'}; const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'};
#define LOGO logo_kigiv //void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug);
//void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate);
//#define LOGO logo_kigiv
const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\""; const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\"";
/*
const char logo_kigiv[] = { const char logo_kigiv[] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35,
0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35,
@ -409,8 +414,9 @@ const char logo_kigiv[] = {
0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33,
0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a}; 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a};
unsigned int logo_kigiv_len = 9303; unsigned int logo_kigiv_len = 9303;
*/
const char logo_kigiv_nocolor[] = { /*const char logo_kigiv_nocolor[] = {
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
@ -494,6 +500,6 @@ const char logo_kigiv_nocolor[] = {
0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a}; 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a};
unsigned int logo_kigiv_nocolor_len = 2153; unsigned int logo_kigiv_nocolor_len = 2153;*/
#endif /* __HF_COLIN_H */ #endif /* __HF_COLIN_H */

View file

@ -35,8 +35,171 @@ on a blank card.
#include "hf_mattyrun.h" #include "hf_mattyrun.h"
uint8_t uid[10];
uint32_t cuid;
iso14a_card_select_t p_card;
//-----------------------------------------------------------------------------
// Matt's StandAlone mod.
// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn)
//-----------------------------------------------------------------------------
static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
// params
uint8_t needWipe = arg0;
// bit 0 - need get UID
// bit 1 - need wupC
// bit 2 - need HALT after sequence
// bit 3 - need init FPGA and field before sequence
// bit 4 - need reset FPGA and LED
uint8_t workFlags = arg1;
uint8_t blockNo = arg2;
// card commands
uint8_t wupC1[] = {0x40};
uint8_t wupC2[] = {0x43};
uint8_t wipeC[] = {0x41};
// variables
uint8_t isOK = 0;
uint8_t d_block[18] = {0x00};
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE];
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE];
// reset FPGA and LED
if (workFlags & 0x08) {
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false);
}
while (true) {
// get UID from chip
if (workFlags & 0x01) {
if (!iso14443a_select_card(uid, &p_card, &cuid, true, 0, true)) {
DbprintfEx(FLAG_NEWLINE, "Can't select card");
break;
};
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NEWLINE, "Halt error");
break;
};
};
// reset chip
if (needWipe) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "wupC1 error");
break;
};
ReaderTransmit(wipeC, sizeof(wipeC), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "wipeC error");
break;
};
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NEWLINE, "Halt error");
break;
};
};
// chaud
// write block
if (workFlags & 0x02) {
ReaderTransmitBitsPar(wupC1, 7, 0, NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "wupC1 error");
break;
};
ReaderTransmit(wupC2, sizeof(wupC2), NULL);
if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "wupC2 errorv");
break;
};
}
if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "write block send command error");
break;
};
memcpy(d_block, datain, 16);
AddCrc14A(d_block, 16);
ReaderTransmit(d_block, sizeof(d_block), NULL);
if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) {
DbprintfEx(FLAG_NEWLINE, "write block send data error");
break;
};
if (workFlags & 0x04) {
if (mifare_classic_halt(NULL, cuid)) {
DbprintfEx(FLAG_NEWLINE, "Halt error");
break;
};
}
isOK = 1;
break;
}
if ((workFlags & 0x10) || (!isOK)) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
}
return isOK;
}
/* the chk function is a piwied(tm) check that will try all keys for
a particular sector. also no tracing no dbg */
static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) {
DBGLEVEL = DBG_NONE;
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
set_tracing(false);
struct Crypto1State mpcs = {0, 0};
struct Crypto1State *pcs;
pcs = &mpcs;
for (int i = 0; i < keyCount; ++i) {
/* no need for anticollision. just verify tag is still here */
// if (!iso14443a_fast_select_card(cjuid, 0)) {
if (!iso14443a_select_card(uid, &p_card, &cuid, true, 0, true)) {
DbprintfEx(FLAG_NEWLINE, "FATAL : E_MF_LOSTTAG");
return -1;
}
uint64_t ui64Key = bytes_to_num(datain + i * 6, 6);
if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) {
uint8_t dummy_answer = 0;
ReaderTransmit(&dummy_answer, 1, NULL);
// wait for the card to become ready again
SpinDelayUs(AUTHENTICATION_TIMEOUT);
continue;
}
crypto1_destroy(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
*key = ui64Key;
return i;
}
crypto1_destroy(pcs);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return -1;
}
void ModInfo(void) {
DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)");
}
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
/* /*
It will check if the keys from the attacked tag are a subset from It will check if the keys from the attacked tag are a subset from
@ -52,17 +215,14 @@ void RunMod() {
messages, you MUST uncomment usb_disable(). messages, you MUST uncomment usb_disable().
*/ */
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Comment this line below if you want to see debug messages.
// usb_disable(); // Comment this line if you want to see debug messages. // usb_disable();
/* /*
Pseudo-configuration block. Pseudo-configuration block.
*/ */
char keyTypec = '?'; // 'A'/'B' or both keys '?'
bool printKeys = false; // Prints keys bool printKeys = false; // Prints keys
bool transferToEml = true; // Transfer keys to emulator memory bool transferToEml = true; // Transfer keys to emulator memory
bool ecfill = true; // Fill emulator memory with cards content.
bool simulation = true; // Simulates an exact copy of the target tag bool simulation = true; // Simulates an exact copy of the target tag
bool fillFromEmulator = false; // Dump emulator memory. bool fillFromEmulator = false; // Dump emulator memory.
@ -71,11 +231,10 @@ void RunMod() {
uint8_t sectorSize = 64; // 1k's sector size is 64 bytes. uint8_t sectorSize = 64; // 1k's sector size is 64 bytes.
uint8_t blockNo = 3; // Security block is number 3 for each sector. uint8_t blockNo = 3; // Security block is number 3 for each sector.
uint8_t sectorsCnt = (mifare_size / sectorSize); uint8_t sectorsCnt = (mifare_size / sectorSize);
uint8_t keyType; // Keytype buffer uint8_t keyType = 2; // Keytype buffer
uint64_t key64; // Defines current key uint64_t key64; // Defines current key
uint8_t *keyBlock = NULL; // Where the keys will be held in memory. uint8_t *keyBlock; // Where the keys will be held in memory.
uint8_t stKeyBlock = 20; // Set the quantity of keys in the block. uint8_t stKeyBlock = 20; // Set the quantity of keys in the block.
uint8_t filled = 0; // Used to check if the memory was filled with success.
bool keyFound = false; bool keyFound = false;
/* /*
@ -108,24 +267,6 @@ void RunMod() {
num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6));
} }
/*
Simple switch just to handle keytpes.
*/
switch (keyTypec) {
case 'a': case 'A':
keyType = !0;
break;
case 'b': case 'B':
keyType = !1;
break;
case '?':
keyType = 2;
break;
default:
Dbprintf("[!] Key type must be A , B or ?");
keyType = 2;
}
/* /*
Pretty print of the keys to be checked. Pretty print of the keys to be checked.
*/ */
@ -157,17 +298,15 @@ void RunMod() {
/* /*
Iterates through each sector checking if there is a correct key. Iterates through each sector checking if there is a correct key.
*/ */
int key = -1;
int block = 0;
bool err = 0; bool err = 0;
bool allKeysFound = true; bool allKeysFound = true;
uint32_t size = mfKeysCnt; uint32_t size = mfKeysCnt;
for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) {
block = blockNo; int block = blockNo;
for (int sec = 0; sec < sectorsCnt && !err; ++sec) { for (int sec = 0; sec < sectorsCnt && !err; ++sec) {
Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt); Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B' : 'A', mfKeysCnt);
key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); int key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64);
if (key == -1) { if (key == -1) {
LED(LED_RED, 50); //red LED(LED_RED, 50); //red
Dbprintf("\t✕ Key not found for this sector!"); Dbprintf("\t✕ Key not found for this sector!");
@ -191,16 +330,14 @@ void RunMod() {
} }
/* /*
TODO: This. TODO:
- Get UID from tag and set accordingly in emulator memory and call mifaresim with right flags (iceman)
- If at least one key was found, start a nested attack based on that key, and continue.
- Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman)
*/ */
if (!allKeysFound && keyFound) { if (!allKeysFound && keyFound) {
Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!"); Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!");
LED_C_ON(); //red LED_C_ON(); //red
LED_A_ON(); //yellow LED_A_ON(); //yellow
// no room to run nested attack on device (iceman)
// Do nested attack, set allKeysFound = true; // Do nested attack, set allKeysFound = true;
// allKeysFound = true; // allKeysFound = true;
} else { } else {
@ -229,40 +366,52 @@ void RunMod() {
} }
Dbprintf("\t✓ Found keys have been transferred to the emulator memory."); Dbprintf("\t✓ Found keys have been transferred to the emulator memory.");
if (ecfill) { if (ecfill) {
int filled;
Dbprintf("\tFilling in with key A."); Dbprintf("\tFilling in with key A.");
MifareECardLoad(sectorsCnt, 0, 0, &filled); filled = MifareECardLoad(sectorsCnt, 0);
if (filled != 1) { if (filled != PM3_SUCCESS) {
Dbprintf("\t✕ Failed filling with A."); Dbprintf("\t✕ Failed filling with A.");
} }
Dbprintf("\tFilling in with key B."); Dbprintf("\tFilling in with key B.");
MifareECardLoad(sectorsCnt, 1, 0, &filled); filled = MifareECardLoad(sectorsCnt, 1);
if (filled != 1) { if (filled != PM3_SUCCESS) {
Dbprintf("\t✕ Failed filling with B."); Dbprintf("\t✕ Failed filling with B.");
} }
if ((filled == 1) && simulation) { if ((filled == PM3_SUCCESS) && simulation) {
Dbprintf("\t✓ Filled, simulation started."); Dbprintf("\t✓ Emulator memory filled, simulation started.");
// This will tell the fpga to emulate using previous keys and current target tag content. // This will tell the fpga to emulate using previous keys and current target tag content.
Dbprintf("\t Press button to abort simulation at anytime."); Dbprintf("\t Press button to abort simulation at anytime.");
LED_B_ON(); // green LED_B_ON(); // green
// assuming arg0==0, use hardcoded uid 0xdeadbeaf // assuming arg0==0, use hardcoded uid 0xdeadbeaf
Mifare1ksim( 0, 0, 0, NULL); uint16_t simflags;
switch (p_card.uidlen) {
case 10:
simflags = FLAG_10B_UID_IN_DATA;
break;
case 7:
simflags = FLAG_7B_UID_IN_DATA;
break;
default:
simflags = FLAG_4B_UID_IN_DATA;
break;
}
Mifare1ksim(simflags | FLAG_MF_1K, 0, uid);
LED_B_OFF(); LED_B_OFF();
/* /*
Needs further testing. Needs further testing.
*/ */
if (fillFromEmulator) { if (fillFromEmulator) {
uint8_t retry = 5, cnt; uint8_t retry = 5;
Dbprintf("\t Trying to dump into blank card."); Dbprintf("\t Trying to dump into blank card.");
int flags = 0; int flags = 0;
LED_A_ON(); //yellow LED_A_ON(); //yellow
for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) { for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) {
cnt = 0; uint8_t cnt = 0;
emlGetMem(mblock, blockNum, 1); emlGetMem(mblock, blockNum, 1);
// switch on field and send magic sequence // switch on field and send magic sequence
if (blockNum == 0) flags = 0x08 + 0x02; if (blockNum == 0) flags = 0x08 + 0x02;
@ -290,8 +439,8 @@ void RunMod() {
} }
} }
} else if (filled != 1) { } else if (filled != PM3_SUCCESS) {
Dbprintf("\t✕ Memory could not be filled due to errors."); Dbprintf("\t✕ Emulator memory could not be filled due to errors.");
LED_C_ON(); LED_C_ON();
} }
} }

View file

@ -12,10 +12,11 @@
#ifndef __HF_MATTYRUN_H #ifndef __HF_MATTYRUN_H
#define __HF_MATTYRUN_H #define __HF_MATTYRUN_H
//#include <stdbool.h> // for bool
#include "standalone.h" // standalone definitions #include "standalone.h" // standalone definitions
#include "apps.h" // debugstatements, lfops? #include "apps.h" // debugstatements, lfops?
#include "usb_cmd.h" // mifare1ksim flags #include "pm3_cmd.h" // mifare1ksim flags
#include "mifaresim.h" // mifare1ksim
#include "mifareutil.h"
#define OPTS 2 #define OPTS 2

View file

@ -18,8 +18,13 @@ typedef struct {
} __attribute__((__packed__)) card_clone_t; } __attribute__((__packed__)) card_clone_t;
void ModInfo(void) {
DbpString(" HF Mifare sniff/simulation - (Craig Young)");
}
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0;
@ -34,7 +39,7 @@ void RunMod() {
for (;;) { for (;;) {
WDT_HIT(); WDT_HIT();
// exit from Standalone Mode, send a usbcommand. // exit from Standalone Mode, send a usbcommand.
if (usb_poll_validate_length()) return; if (data_available()) return;
SpinDelay(300); SpinDelay(300);
@ -42,7 +47,7 @@ void RunMod() {
iGotoRecord = 0; iGotoRecord = 0;
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_RED2, 0); LED(LED_D, 0);
// record // record
Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected); Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected);
@ -52,7 +57,7 @@ void RunMod() {
for (;;) { for (;;) {
// exit from Standalone Mode, send a usbcommand. // exit from Standalone Mode, send a usbcommand.
if (usb_poll_validate_length()) return; if (data_available()) return;
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
if (cardRead[selected]) { if (cardRead[selected]) {
@ -94,10 +99,10 @@ void RunMod() {
Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]);
Dbprintf("SAK = %02X", uids[selected].sak); Dbprintf("SAK = %02X", uids[selected].sak);
LEDsoff(); LEDsoff();
LED(LED_GREEN, 200); LED(LED_B, 200);
LED(LED_ORANGE, 200); LED(LED_A, 200);
LED(LED_GREEN, 200); LED(LED_B, 200);
LED(LED_ORANGE, 200); LED(LED_A, 200);
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
@ -113,7 +118,7 @@ void RunMod() {
iGotoClone = 0; iGotoClone = 0;
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_ORANGE, 250); LED(LED_A, 250);
// magiccards holds 4bytes uid. *usually* // magiccards holds 4bytes uid. *usually*
uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4);
@ -131,12 +136,10 @@ void RunMod() {
SpinDelay(500); SpinDelay(500);
// Begin clone function here: // Begin clone function here:
/* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards:
UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}}; SendCommandOLD(CMD_MIFARE_CSETBLOCK, params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0, data, 16);
memcpy(c.d.asBytes, data, 16);
SendCommand(&c);
Block read is similar: Block read is similar:
UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; SendCommandOLD(CMD_MIFARE_CGETBLOCK, params, blockNo, 0,...};
We need to imitate that call with blockNo 0 to set a uid. We need to imitate that call with blockNo 0 to set a uid.
The get and set commands are handled in this file: The get and set commands are handled in this file:
@ -157,15 +160,16 @@ void RunMod() {
Bytes 5-7 are reserved SAK and ATQA for mifare classic Bytes 5-7 are reserved SAK and ATQA for mifare classic
-Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it
*/ */
uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0};
// arg0 = Flags, arg1=blockNo // arg0 = Flags, arg1=blockNo
MifareCGetBlock(params, 0, oldBlock0); MifareCGetBlock(params, 0, oldBlock0);
if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) {
Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected);
playing = 1; playing = 1;
} else { } else {
uint8_t testBlock0[16] = {0};
Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]);
memcpy(newBlock0, oldBlock0, 16); memcpy(newBlock0 + 5, oldBlock0 + 5, 11);
// Copy uid for bank (2nd is for longer UIDs not supported if classic) // Copy uid for bank (2nd is for longer UIDs not supported if classic)
memcpy(newBlock0, uids[selected].uid, 4); memcpy(newBlock0, uids[selected].uid, 4);
@ -197,17 +201,17 @@ void RunMod() {
LED(selected + 1, 0); LED(selected + 1, 0);
// Begin transmitting // Begin transmitting
LED(LED_GREEN, 0); LED(LED_B, 0);
DbpString("Playing"); DbpString("Playing");
for (; ;) { for (; ;) {
// exit from Standalone Mode, send a usbcommand. // exit from Standalone Mode, send a usbcommand.
if (usb_poll_validate_length()) return; if (data_available()) return;
int button_action = BUTTON_HELD(1000); int button_action = BUTTON_HELD(1000);
if (button_action == 0) { // No button action, proceed with sim if (button_action == 0) { // No button action, proceed with sim
uint8_t flags = FLAG_4B_UID_IN_DATA; uint8_t flags = FLAG_4B_UID_IN_DATA;
uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break uint8_t data[PM3_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break
memcpy(data, uids[selected].uid, uids[selected].uidlen); memcpy(data, uids[selected].uid, uids[selected].uidlen);

View file

@ -10,7 +10,7 @@
// //
// PROXMARK3 - HID CORPORATE 1000 BRUTEFORCER (STAND-ALONE MODE) // PROXMARK3 - HID CORPORATE 1000 BRUTEFORCER (STAND-ALONE MODE)
// //
// This version of Proxmark3 firmware adds one extra stand-alone mode to proxmark3 firmware. // This version of Proxmark3 firmware adds one extra stand-alone mode.
// The new stand-alone mode allows to execute a bruteforce on HID Corporate 1000 readers, by // The new stand-alone mode allows to execute a bruteforce on HID Corporate 1000 readers, by
// reading a specific badge and bruteforcing the Card Number (incrementing and decrementing it), // reading a specific badge and bruteforcing the Card Number (incrementing and decrementing it),
// mainteining the same Facility Code of the original badge. // mainteining the same Facility Code of the original badge.
@ -26,9 +26,14 @@
//----------------------------------------------------------------------------------- //-----------------------------------------------------------------------------------
#include "lf_hidbrute.h" #include "lf_hidbrute.h"
void ModInfo(void) {
DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)");
}
// samy's sniff and repeat routine for LF // samy's sniff and repeat routine for LF
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
uint32_t high[OPTS], low[OPTS]; uint32_t high[OPTS], low[OPTS];
@ -43,7 +48,7 @@ void RunMod() {
WDT_HIT(); WDT_HIT();
// exit from SamyRun, send a usbcommand. // exit from SamyRun, send a usbcommand.
if (usb_poll_validate_length()) break; if (data_available()) break;
// Was our button held down or pressed? // Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000); int button_pressed = BUTTON_HELD(1000);
@ -53,7 +58,7 @@ void RunMod() {
if (button_pressed > 0 && cardRead == 0) { if (button_pressed > 0 && cardRead == 0) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_RED2, 0); LED(LED_D, 0);
// record // record
DbpString("[=] starting recording"); DbpString("[=] starting recording");
@ -75,11 +80,10 @@ void RunMod() {
// so next button push begins playing what we recorded // so next button push begins playing what we recorded
playing = 0; playing = 0;
cardRead = 1; cardRead = 1;
} } else if (button_pressed > 0 && cardRead == 1) {
else if (button_pressed > 0 && cardRead == 1) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_ORANGE, 0); LED(LED_A, 0);
// record // record
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
@ -118,7 +122,7 @@ void RunMod() {
// Begin transmitting // Begin transmitting
if (playing && selected != 2) { if (playing && selected != 2) {
LED(LED_GREEN, 0); LED(LED_B, 0);
DbpString("[=] playing"); DbpString("[=] playing");
// wait for button to be released // wait for button to be released
@ -140,9 +144,7 @@ void RunMod() {
playing = !playing; playing = !playing;
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
} } else if (playing && selected == 2) {
else if (playing && selected == 2)
{
// Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID. // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID.
// It is necessary only to calculate the correct parity. // It is necessary only to calculate the correct parity.
@ -153,7 +155,7 @@ void RunMod() {
continue; continue;
} }
LED(LED_GREEN, 0); LED(LED_B, 0);
DbpString("[=] entering bruteforce mode"); DbpString("[=] entering bruteforce mode");
// wait for button to be released // wait for button to be released
while (BUTTON_PRESS()) while (BUTTON_PRESS())
@ -166,7 +168,7 @@ void RunMod() {
Dbprintf("[=] Proxbrute - starting decrementing card number"); Dbprintf("[=] Proxbrute - starting decrementing card number");
while (cardnum >= 0) { while (cardnum > 0) {
// Needed for exiting from proxbrute when button is pressed // Needed for exiting from proxbrute when button is pressed
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {

View file

@ -0,0 +1,40 @@
//-----------------------------------------------------------------------------
// Christian Herrmann, 2019
//
// 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 skeleton aka IceRun by Iceman
//-----------------------------------------------------------------------------
#include "lf_icerun.h"
void ModInfo(void) {
DbpString(" LF skeleton mode - aka IceRun (iceman)");
}
// samy's sniff and repeat routine for LF
void RunMod() {
StandAloneMode();
Dbprintf("[=] LF skeleton code a.k.a IceRun started");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// the main loop for your standalone mode
for (;;) {
WDT_HIT();
// exit from IceRun, send a usbcommand.
if (data_available()) break;
// Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000);
Dbprintf("button %d", button_pressed);
if (button_pressed)
break;
}
DbpString("[=] exiting");
LEDsoff();
}

View file

@ -1,21 +1,17 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Micolous Jan 2017 // Iceman, Christian Herrmann, 2019
// Iceman Jan 2017 //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // 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 // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// pseudo rng generator. To be used when PM3 simulates Mifare tag. // StandAlone Mod
// i.e. 'hf mf sim'
// 'hf 14a sim'
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __RANDOM_H #ifndef __LF_ICERUN_H
#define __RANDOM_H #define __LF_ICERUN_H
#include "common.h" #include "standalone.h" // standalone definitions
#include "ticks.h" #include "apps.h" // debugstatements, lfops?
void fast_prand();
void fast_prandEx(uint32_t seed); #endif /* __LF_ICERUN_H */
uint32_t prand();
#endif

View file

@ -11,9 +11,14 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "lf_proxbrute.h" #include "lf_proxbrute.h"
void ModInfo(void) {
DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)");
}
// samy's sniff and repeat routine for LF // samy's sniff and repeat routine for LF
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
uint32_t high[OPTS], low[OPTS]; uint32_t high[OPTS], low[OPTS];
@ -28,7 +33,7 @@ void RunMod() {
WDT_HIT(); WDT_HIT();
// exit from SamyRun, send a usbcommand. // exit from SamyRun, send a usbcommand.
if (usb_poll_validate_length()) break; if (data_available()) break;
// Was our button held down or pressed? // Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000); int button_pressed = BUTTON_HELD(1000);
@ -38,7 +43,7 @@ void RunMod() {
if (button_pressed > 0 && cardRead == 0) { if (button_pressed > 0 && cardRead == 0) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_RED2, 0); LED(LED_D, 0);
// record // record
DbpString("[=] starting recording"); DbpString("[=] starting recording");
@ -60,11 +65,10 @@ void RunMod() {
// so next button push begins playing what we recorded // so next button push begins playing what we recorded
playing = 0; playing = 0;
cardRead = 1; cardRead = 1;
} } else if (button_pressed > 0 && cardRead == 1) {
else if (button_pressed > 0 && cardRead == 1) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_ORANGE, 0); LED(LED_A, 0);
// record // record
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
@ -101,7 +105,7 @@ void RunMod() {
// Begin transmitting // Begin transmitting
if (playing) { if (playing) {
LED(LED_GREEN, 0); LED(LED_B, 0);
DbpString("[=] playing"); DbpString("[=] playing");
// wait for button to be released // wait for button to be released
while (BUTTON_PRESS()) while (BUTTON_PRESS())
@ -121,8 +125,8 @@ void RunMod() {
if (selected == 1) { if (selected == 1) {
DbpString("[=] entering ProxBrute Mode"); DbpString("[=] entering ProxBrute Mode");
Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]); Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]);
LED(LED_ORANGE, 0); LED(LED_A, 0);
LED(LED_RED, 0); LED(LED_C, 0);
for (uint16_t i = low[selected] - 1; i > 0; i--) { for (uint16_t i = low[selected] - 1; i > 0; i--) {
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
DbpString("[-] told to stop"); DbpString("[-] told to stop");
@ -155,8 +159,7 @@ void RunMod() {
playing = !playing; playing = !playing;
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
} } else {
else {
while (BUTTON_PRESS()) while (BUTTON_PRESS())
WDT_HIT(); WDT_HIT();
} }

View file

@ -10,9 +10,14 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "lf_samyrun.h" #include "lf_samyrun.h"
void ModInfo(void) {
DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)");
}
// samy's sniff and repeat routine for LF // samy's sniff and repeat routine for LF
void RunMod() { void RunMod() {
StandAloneMode(); StandAloneMode();
Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
uint32_t high[OPTS], low[OPTS]; uint32_t high[OPTS], low[OPTS];
@ -27,7 +32,7 @@ void RunMod() {
WDT_HIT(); WDT_HIT();
// exit from SamyRun, send a usbcommand. // exit from SamyRun, send a usbcommand.
if (usb_poll_validate_length()) break; if (data_available()) break;
// Was our button held down or pressed? // Was our button held down or pressed?
int button_pressed = BUTTON_HELD(1000); int button_pressed = BUTTON_HELD(1000);
@ -39,7 +44,7 @@ void RunMod() {
if (button_pressed > 0 && cardRead == 0) { if (button_pressed > 0 && cardRead == 0) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_RED2, 0); LED(LED_D, 0);
// record // record
DbpString("[=] starting recording"); DbpString("[=] starting recording");
@ -63,11 +68,10 @@ void RunMod() {
cardRead = 1; cardRead = 1;
gotCard = true; gotCard = true;
} } else if (button_pressed > 0 && cardRead == 1) {
else if (button_pressed > 0 && cardRead == 1) {
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
LED(LED_ORANGE, 0); LED(LED_A, 0);
// record // record
Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]);
@ -106,7 +110,7 @@ void RunMod() {
// Begin transmitting // Begin transmitting
if (playing) { if (playing) {
LED(LED_GREEN, 0); LED(LED_B, 0);
DbpString("[=] playing"); DbpString("[=] playing");
// wait for button to be released // wait for button to be released
@ -128,8 +132,7 @@ void RunMod() {
playing = !playing; playing = !playing;
LEDsoff(); LEDsoff();
LED(selected + 1, 0); LED(selected + 1, 0);
} } else {
else {
while (BUTTON_PRESS()) while (BUTTON_PRESS())
WDT_HIT(); WDT_HIT();
} }

View file

@ -0,0 +1,9 @@
#include "standalone.h" // standalone definitions
#include "apps.h" // debug statements
void ModInfo(void) {
DbpString(" No standalone mode present");
}
void RunMod() {
}

View file

@ -1,18 +1,32 @@
# StandAlone Modes # Standalone Modes
This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `armsrc/Makefile`. This contains functionality for different StandAlone modes. The fullimage will be built given the correct compiler flags used. Build targets for these files are contained in `armsrc/Makefile` and `common/Makefile.hal`
If you want to implement a new standalone mode, you need to implement the methods provided in `standalone.h`. If you want to implement a new standalone mode, you need to implement the methods provided in `standalone.h`.
Have a look at the skeleton standalone mode called IceRun, in the files `lf_icerun.c lf_icerun.h`.
As it is now, you can only have one standalone mode installed at the time.
## Implementing a standalone mode ## Implementing a standalone mode
Each standalone mod needs to have its own compiler flag to be added in `armsrc\makefile` and inside the function `AppMain` inside AppMain.c. Inside Appmain a call to RunMod is needed. It looks strange because of what kinds of dependencies your mode will have. We suggest you keep your standalone code inside the `armsrc/Standalone` folder. And that you name your files according to your standalone mode name.
The `standalone.h` states that you must have two functions implemented.
The ModInfo function, which is your identification of your standalone mode. This string will show when running the command `hw status` on the client.
The RunMod function, which is your "main" function when running. You need to check for Usb commands, in order to let the pm3 client break the standalone mode. See this basic skeleton of main function RunMod() and Modinfo() below.
The RunMod function is your "main" function when running. You need to check for Usb commands, in order to let the pm3 client break the standalone mode. See this basic skeleton of main function RunMod().
```` ````
void RunMod() { void ModInfo(void) {
DbpString(" LF good description of your mode - aka FooRun (your name)");
}
void RunMod(void) {
// led show // led show
StandAloneMode(); StandAloneMode();
// Do you target LF or HF?
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
// main loop // main loop
@ -20,83 +34,105 @@ void RunMod() {
WDT_HIT(); WDT_HIT();
// exit from standalone mode, just send a usbcommand // exit from standalone mode, just send a usbcommand
if (usb_poll_validate_length()) break; if (data_available()) break;
// do your standalone stuff.. // do your standalone stuff..
} }
```` ````
As it is now, you can only have one standalone mode installed at the time. Each standalone mode needs to have its own compiler flag to be added in `armsrc/Makefile`.
## Name ## Naming your standalone mode
Use HF/LF to denote which frequence your mod is targeting.
Use you own github name/similar for perpetual honour to denote your mod
Samples of directive flag used in the `armsrc\makefile`: We suggest that you follow these guidelines:
- Use HF/LF to denote which frequency your mode is targeting.
- Use you own github name/similar for perpetual honour to denote your mode.
sample:
`LF_FOO`
Which indicates your mode targets LF and is called FOO.
This leads to your next step, your DEFINE name needed in Makefile.
`WITH_STANDALONE_LF_FOO`
## Update COMMON/MAKEFILE.HAL
Add your mode to the `common/Makefile.hal` help and modes list:
``` ```
### -DWITH_LF_ICERUN +==========================================================+
### -DWITH_LF_SAMYRUN | STANDALONE | DESCRIPTION |
### -DWITH_LF_PROXBRUTE +==========================================================+
### -DWITH_LF_HIDBRUTE ...
### -DWITH_HF_COLIN +----------------------------------------------------------+
### -DWITH_HF_YOUNG | LF_FOO | My foobar mode will make you coffee |
### -DWITH_HF_MATTYRUN +----------------------------------------------------------+
STANDALONE_MODES := LF_SAMYRUN LF_ICERUN LF_PROXBRUTE LF_HIDBRUTE LF_FOO
STANDALONE_MODES += HF_YOUNG HF_MATTYRUN HF_COLIN HF_BOG
``` ```
Add your source code file like the following sample in the `armsrc\makefile`
## Update ARMSRC/MAKEFILE
Add your source code files like the following sample in the `armsrc/Makefile`
``` ```
# WITH_HF_COLIN # WITH_STANDALONE_LF_ICERUN
ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) ifneq (,$(findstring WITH_STANDALONE_LF_ICERUN,$(APP_CFLAGS)))
SRC_STANDALONE = hf_colin.c vtsend.c SRC_STANDALONE = lf_icerun.c
else endif
SRC_STANDALONE =
# WITH_STANDALONE_LF_FOO
ifneq (,$(findstring WITH_STANDALONE_LF_FOO,$(APP_CFLAGS)))
SRC_STANDALONE = lf_foo.c
endif endif
``` ```
## Adding identification of your mode ## Adding identification string of your mode
Do please add a identification string in the function `printStandAloneModes` inside `armsrc\appmain.c` Do please add a identification string in a function called `ModInfo` inside your source code file.
This will enable an easy way to detect on client side which standalone mods has been installed on the device. This will enable an easy way to detect on client side which standalone mode has been installed on the device.
````
void ModInfo(void) {
DbpString(" LF good description of your mode - aka FooRun (your name)");
}
````
## Compiling your standalone mode
Once all this is done, you and others can now easily compile different standalone modes by just selecting one of the standalone modes (list in `common/Makefile.hal` or ) , e.g.:
- rename Makefile.platform.sample -> Makefile.platform
- edit the "STANDALONE" row inside Makefile.platform. You need to uncomment it and add your standalone mode name
Makefile.platform.sample
``` ```
#if defined(WITH_HF_COLIN) # If you want to use it, copy this file as Makefile.platform and adjust it to your needs
DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); PLATFORM=PM3RDV4
#endif #PLATFORM_EXTRAS=BTADDON
```` #STANDALONE=LF_SAMYRUN
```
becomes
Once all this is done, you and others can now easily compile different standalone modes by just swapping the -D directive in `armsrc\makefile` Makefile.platform
```
# If you want to use it, copy this file as Makefile.platform and adjust it to your needs
PLATFORM=PM3RDV4
#PLATFORM_EXTRAS=BTADDON
STANDALONE=LF_FOO
```
```` Remember only one can be selected at a time for now.
#remove one of the following defines and comment out the relevant line
#in the next section to remove that particular feature from compilation.
# NO space,TABs after the "\" sign.
APP_CFLAGS = -DWITH_CRC \
-DON_DEVICE \
-DWITH_LF \
-DWITH_HITAG \
-DWITH_ISO15693 \
-DWITH_LEGICRF \
-DWITH_ISO14443b \
-DWITH_ISO14443a \
-DWITH_ICLASS \
-DWITH_FELICA \
-DWITH_FLASH \
-DWITH_SMARTCARD \
-DWITH_HFSNOOP \
-DWITH_HF_COLIN\
-DWITH_FPC \
-fno-strict-aliasing -ffunction-sections -fdata-sections
### IMPORTANT - move the commented variable below this line The final steps is to
# -DWITH_LCD \ - force recompilation of all code. ```make clean```
# -DWITH_EMV \ - compile ```make -j8```
# -DWITH_FPC \ - flash your device
# - connect to your device
# Standalone Mods - press button long time to trigger ledshow and enter your new standalone mode
#------------------------------------------------------- - if connected with usb / fpc , you can also see debug statements from your device in standalone mode. Useful for debugging :)
# -DWITH_LF_ICERUN
# -DWITH_LF_SAMYRUN When compiling you will see a header showing what configurations your project compiled with.
# -DWITH_LF_PROXBRUTE Make sure it says your standalone mode name.
# -DWITH_LF_HIDBRUTE
# -DWITH_HF_YOUNG Happy hacking!
# -DWITH_HF_MATTYRUN
# -DWITH_HF_COLIN
````

View file

@ -14,6 +14,7 @@
#include <stdbool.h> // for bool #include <stdbool.h> // for bool
#include <inttypes.h> // PRIu64 #include <inttypes.h> // PRIu64
extern void RunMod(); void RunMod();
void ModInfo();
#endif /* __STANDALONE_H */ #endif /* __STANDALONE_H */

View file

@ -680,8 +680,7 @@ static const unsigned int rcon[] = {
* Expand the cipher key into the encryption key schedule and return the * Expand the cipher key into the encryption key schedule and return the
* number of rounds for the given cipher key size. * number of rounds for the given cipher key size.
*/ */
int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBytes) int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBytes) {
{
int i = 0; int i = 0;
unsigned int temp; unsigned int temp;
@ -766,8 +765,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
* Expand the cipher key into encryption and decryption key schedule and * Expand the cipher key into encryption and decryption key schedule and
* return the number of rounds for the given cipher key size. * return the number of rounds for the given cipher key size.
*/ */
int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char cipherKey[], int keyBytes) int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char cipherKey[], int keyBytes) {
{
int Nr, i; int Nr, i;
// expand the cipher key // expand the cipher key
@ -821,8 +819,7 @@ int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char ci
/* /*
* Encrypt the plain text into cipher * Encrypt the plain text into cipher
*/ */
void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[]) void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[]) {
{
unsigned int s0, s1, s2, s3, t0, t1, t2, t3, *iv; unsigned int s0, s1, s2, s3, t0, t1, t2, t3, *iv;
const unsigned int *rk; const unsigned int *rk;
int r; int r;
@ -947,8 +944,7 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
/* /*
* Decrypt the cipher into plain text * Decrypt the cipher into plain text
*/ */
void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[]) void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[]) {
{
unsigned int s0, s1, s2, s3, t0, t1, t2, t3, v0, v1, v2, v3, *iv; unsigned int s0, s1, s2, s3, t0, t1, t2, t3, v0, v1, v2, v3, *iv;
const unsigned int *rk; const unsigned int *rk;
int r; int r;
@ -959,10 +955,14 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
* map byte array block to cipher state * map byte array block to cipher state
* and add initial round key: * and add initial round key:
*/ */
v0 = GETU32(ct ); s0 = v0 ^ rk[0]; v0 = GETU32(ct);
v1 = GETU32(ct + 4); s1 = v1 ^ rk[1]; s0 = v0 ^ rk[0];
v2 = GETU32(ct + 8); s2 = v2 ^ rk[2]; v1 = GETU32(ct + 4);
v3 = GETU32(ct + 12); s3 = v3 ^ rk[3]; s1 = v1 ^ rk[1];
v2 = GETU32(ct + 8);
s2 = v2 ^ rk[2];
v3 = GETU32(ct + 12);
s3 = v3 ^ rk[3];
/* /*
* Nr - 1 full rounds: * Nr - 1 full rounds:
*/ */
@ -1053,10 +1053,14 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
rk[3]; rk[3];
if (pCtx->Mode) { if (pCtx->Mode) {
s0 = s0 ^ iv[0]; iv[0] = v0; s0 = s0 ^ iv[0];
s1 = s1 ^ iv[1]; iv[1] = v1; iv[0] = v0;
s2 = s2 ^ iv[2]; iv[2] = v2; s1 = s1 ^ iv[1];
s3 = s3 ^ iv[3]; iv[3] = v3; iv[1] = v1;
s2 = s2 ^ iv[2];
iv[2] = v2;
s3 = s3 ^ iv[3];
iv[3] = v3;
} }
PUTU32(pt, s0); PUTU32(pt, s0);
@ -1072,8 +1076,7 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
/* /*
* initialize AES context * initialize AES context
*/ */
int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode) int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned int KeyLen, unsigned char Mode) {
{
if (pKey == 0 || pCtx == 0 || (KeyLen != KEY128 && KeyLen != KEY192 && KeyLen != KEY256)) if (pKey == 0 || pCtx == 0 || (KeyLen != KEY128 && KeyLen != KEY192 && KeyLen != KEY256))
return -1; return -1;
@ -1097,8 +1100,7 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in
/* /*
* Encrypt plain text * Encrypt plain text
*/ */
int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen) int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsigned int DataLen) {
{
int i; int i;
if (pData == 0 || pCipher == 0 || pCtx == 0 || (DataLen & 0xf) != 0) if (pData == 0 || pCipher == 0 || pCtx == 0 || (DataLen & 0xf) != 0)
@ -1116,8 +1118,7 @@ int AesEncrypt(AesCtx *pCtx, unsigned char *pData, unsigned char *pCipher, unsig
/* /*
* Decrypt cipher * Decrypt cipher
*/ */
int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen) int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsigned int CipherLen) {
{
int i; int i;
if (pData == 0 || pCipher == 0 || pCtx == 0 || (CipherLen & 0xf) != 0) if (pData == 0 || pCipher == 0 || pCtx == 0 || (CipherLen & 0xf) != 0)
@ -1140,8 +1141,7 @@ int AesDecrypt(AesCtx *pCtx, unsigned char *pCipher, unsigned char *pData, unsig
#include <stdio.h> #include <stdio.h>
int main() int main() {
{
AesCtx ctx; AesCtx ctx;
unsigned char iv[] = "INI VECTINI VECT"; unsigned char iv[] = "INI VECTINI VECT";
unsigned char key[] = "This is a sample AESKey"; unsigned char key[] = "This is a sample AESKey";

File diff suppressed because it is too large Load diff

View file

@ -34,7 +34,6 @@ extern "C" {
extern const uint8_t OddByteParity[256]; extern const uint8_t OddByteParity[256];
extern int rsamples; // = 0; extern int rsamples; // = 0;
extern int tracing; // = TRUE;
extern uint8_t trigger; extern uint8_t trigger;
// This may be used (sparingly) to declare a function to be copied to // This may be used (sparingly) to declare a function to be copied to
@ -46,8 +45,9 @@ void ReadMem(int addr);
void __attribute__((noreturn)) AppMain(void); void __attribute__((noreturn)) AppMain(void);
//void DbpIntegers(int a, int b, int c); //void DbpIntegers(int a, int b, int c);
void DbpString(char *str); void DbpString(char *str);
void DbpStringEx(uint32_t flags, char *str);
void Dbprintf(const char *fmt, ...); void Dbprintf(const char *fmt, ...);
void DbprintfEx(uint32_t cmd, const char *fmt, ...); void DbprintfEx(uint32_t flags, const char *fmt, ...);
void Dbhexdump(int len, uint8_t *d, bool bAsci); void Dbhexdump(int len, uint8_t *d, bool bAsci);
// ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV // ADC Vref = 3300mV, and an (10M+1M):1M voltage divider on the HF input can measure voltages up to 36300 mV
@ -59,15 +59,15 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci);
uint16_t AvgAdc(int ch); uint16_t AvgAdc(int ch);
void print_result(char *name, uint8_t *buf, size_t len); void print_result(char *name, uint8_t *buf, size_t len);
void PrintToSendBuffer(void); //void PrintToSendBuffer(void);
void ToSendStuffBit(int b); void ToSendStuffBit(int b);
void ToSendReset(void); void ToSendReset(void);
void ListenReaderField(int limit); void ListenReaderField(uint8_t limit);
extern int ToSendMax; extern int ToSendMax;
extern uint8_t ToSend[]; extern uint8_t ToSend[];
extern void StandAloneMode(void); void StandAloneMode(void);
extern void printStandAloneModes(void); void printStandAloneModes(void);
/// lfops.h /// lfops.h
extern uint8_t decimation; extern uint8_t decimation;
@ -81,14 +81,17 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc);
void AcquireTiType(void); void AcquireTiType(void);
void AcquireRawBitsTI(void); void AcquireRawBitsTI(void);
void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycles); void SimulateTagLowFrequencyEx(int period, int gap, bool ledcontrol, int numcycles);
void SimulateTagLowFrequency(int period, int gap, int ledcontrol); void SimulateTagLowFrequency(int period, int gap, bool ledcontrol);
void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen); void SimulateTagLowFrequencyBidir(int divisor, int max_bitlen);
void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, int ledcontrol, int numcycles);
void CmdHIDsimTAG(uint32_t hi, uint32_t lo, int ledcontrol); void CmdHIDsimTAGEx(uint32_t hi, uint32_t lo, bool ledcontrol, int numcycles);
void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdHIDsimTAG(uint32_t hi, uint32_t lo, bool ledcontrol);
void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream);
void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream); void CmdFSKsimTAG(uint8_t fchigh, uint8_t fclow, uint8_t separator, uint8_t clk, uint16_t bitslen, uint8_t *bits, bool ledcontrol);
void CmdASKsimTAG(uint8_t encoding, uint8_t invert, uint8_t separator, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
void CmdPSKsimTag(uint8_t carrier, uint8_t invert, uint8_t clk, uint16_t size, uint8_t *bits, bool ledcontrol);
void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol);
void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26 void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol); // Realtime demodulation mode for AWID26
void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol); void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol);
@ -100,14 +103,22 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo);
void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7 void CopyIndala64toT55x7(uint32_t hi, uint32_t lo); // Clone Indala 64-bit tag by UID to T55x7
void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7 void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7); // Clone Indala 224-bit tag by UID to T55x7
void T55xxResetRead(void); void T55xxResetRead(void);
void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode); void T55xxWriteBlock(uint8_t *data);
void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode); void T55xxWriteBlockExt(uint32_t data, uint8_t blockno, uint32_t pwd, uint8_t flags);
void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd); void T55xxReadBlock(uint8_t page, bool pwd_mode, bool brute_mem, uint8_t block, uint32_t pwd);
void T55xxWakeUp(uint32_t Pwd); void T55xxWakeUp(uint32_t Pwd);
void T55xx_ChkPwds(void);
void TurnReadLFOn(uint32_t delay); void TurnReadLFOn(uint32_t delay);
void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd);
void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd); void EM4xWriteWord(uint8_t addr, uint32_t data, uint32_t pwd, uint8_t usepwd);
void Cotag(uint32_t arg0); void Cotag(uint32_t arg0);
void setT55xxConfig(uint8_t arg0, t55xx_config *c);
t55xx_config *getT55xxConfig(void);
void printT55xxConfig(void);
void loadT55xxConfig(void);
/// iso14443b.h /// iso14443b.h
void SimulateIso14443bTag(uint32_t pupi); void SimulateIso14443bTag(uint32_t pupi);
@ -115,50 +126,51 @@ void AcquireRawAdcSamplesIso14443b(uint32_t parameter);
void ReadSTMemoryIso14443b(uint8_t numofblocks); void ReadSTMemoryIso14443b(uint8_t numofblocks);
void RAMFUNC SniffIso14443b(void); void RAMFUNC SniffIso14443b(void);
void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]); void SendRawCommand14443B(uint32_t, uint32_t, uint8_t, uint8_t[]);
void SendRawCommand14443B_Ex(UsbCommand *c); void SendRawCommand14443B_Ex(PacketCommandNG *c);
void ClearFpgaShiftingRegisters(void); void ClearFpgaShiftingRegisters(void);
// iso14443a.h // iso14443a.h
void RAMFUNC SniffIso14443a(uint8_t param); void RAMFUNC SniffIso14443a(uint8_t param);
void SimulateIso14443aTag(int tagType, int flags, uint8_t *data); void ReaderIso14443a(PacketCommandNG *c);
void ReaderIso14443a(UsbCommand *c);
// Also used in iclass.c // Also used in iclass.c
//bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); //bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t len, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag);
void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *parity); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
void iso14a_set_trigger(bool enable); void iso14a_set_trigger(bool enable);
// also used in emv // also used in emv
bool prepare_allocated_tag_modulation(tag_response_info_t * response_info); //bool prepare_allocated_tag_modulation(tag_response_info_t *response_info);
int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len); //int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len);
// epa.h // epa.h
void EPA_PACE_Collect_Nonce(UsbCommand * c); void EPA_PACE_Collect_Nonce(PacketCommandNG *c);
void EPA_PACE_Replay(UsbCommand *c); void EPA_PACE_Replay(PacketCommandNG *c);
// mifarecmd.h // mifarecmd.h
void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *data); void MifareReadBlock(uint8_t blockNo, uint8_t keyType, uint8_t *datain);
void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareUC_Auth(uint8_t arg0, uint8_t *datain); void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes);
void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain); void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain);
void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
//void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain); //void MifareUWriteBlockCompat(uint8_t arg0,uint8_t *datain);
void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain); void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain);
void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain); void MifareAcquireNonces(uint32_t arg0, uint32_t flags);
void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain); void MifareChkKeys(uint8_t *datain);
void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void Mifare1ksim(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void MifareSetDbgLvl(uint16_t arg0); void MifareEMemClr(void);
void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareEMemSet(uint8_t blockno, uint8_t blockcnt, uint8_t blockwidth, uint8_t *datain);
void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void MifareEMemGet(uint8_t blockno, uint8_t blockcnt);
void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); int MifareECardLoad(uint32_t arg0, uint32_t arg1);
void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); // Work with "magic Chinese" card
void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain); void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain);
void MifareCIdent(); // is "magic chinese" card? void MifareCIdent(); // is "magic chinese" card?
void MifareSetMod(uint8_t mod, uint8_t *key);
void MifareSetMod(uint8_t *datain);
void MifareUSetPwd(uint8_t arg0, uint8_t *datain); void MifareUSetPwd(uint8_t arg0, uint8_t *datain);
void OnSuccessMagic(); void OnSuccessMagic();
void OnErrorMagic(uint8_t reason); void OnErrorMagic(uint8_t reason);
@ -207,40 +219,30 @@ void Iso15693InitReader(void);
void RAMFUNC SniffIClass(void); void RAMFUNC SniffIClass(void);
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain);
void ReaderIClass(uint8_t arg0); void ReaderIClass(uint8_t arg0);
void ReaderIClass_Replay(uint8_t arg0,uint8_t *MAC); void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac);
void iClass_Authentication(uint8_t *MAC); void iClass_Authentication(uint8_t *mac);
void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain); void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain);
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data); void iClass_WriteBlock(uint8_t blockno, uint8_t *data);
void iClass_ReadBlk(uint8_t blockNo); void iClass_ReadBlk(uint8_t blockno);
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t datalen); bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len);
void iClass_Dump(uint8_t blockno, uint8_t numblks); void iClass_Dump(uint8_t blockno, uint8_t numblks);
void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data); void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data);
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType); void iClass_ReadCheck(uint8_t blockno, uint8_t keytype);
// hitag2.h
void SnoopHitag(uint32_t type);
void SimulateHitagTag(bool tag_mem_supplied, byte_t* data);
void ReaderHitag(hitag_function htf, hitag_data* htd);
void WriterHitag(hitag_function htf, hitag_data* htd, int page);
//hitagS.h
void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data);
void ReadHitagS(hitag_function htf, hitag_data* htd);
void WritePageHitagS(hitag_function htf, hitag_data* htd,int page);
void check_challenges(bool file_given, byte_t* data);
// cmd.h // cmd.h
bool cmd_receive(UsbCommand* cmd); int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len); int reply_mix(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len);
int reply_ng(uint16_t cmd, int16_t status, uint8_t *data, size_t len);
int receive_ng(PacketCommandNG *rx);
// util.h // util.h
void HfSnoop(int , int); void HfSniff(int, int);
//felica.c //felica.c
extern void felica_sendraw(UsbCommand *c); void felica_sendraw(PacketCommandNG *c);
extern void felica_sniff(uint32_t samples, uint32_t triggers); void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip);
extern void felica_sim_lite(uint64_t uid); void felica_sim_lite(uint64_t uid);
extern void felica_dump_lite_s(); void felica_dump_lite_s();
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -20,11 +20,11 @@
#define note_7 506 #define note_7 506
#define note_8 0 #define note_8 0
extern void Ring_BEE_ONCE(uint16_t music_note); void Ring_BEE_ONCE(uint16_t music_note);
extern void Ring_BEE_TIME(uint16_t music_note,uint16_t count); void Ring_BEE_TIME(uint16_t music_note, uint16_t count);
extern void ring_2_7khz(uint16_t count); void ring_2_7khz(uint16_t count);
extern void Ring_ALL(uint16_t count); void Ring_ALL(uint16_t count);
extern void Ring_Little_Star(uint16_t count); void Ring_Little_Star(uint16_t count);
#endif #endif

View file

@ -208,9 +208,9 @@ void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){
ob = ptable[1]; ob = ptable[1];
ptable = &(ptable[2]); ptable = &(ptable[2]);
for (byte = 0; byte < ob; ++byte) { for (byte = 0; byte < ob; ++byte) {
uint8_t x,t=0; uint8_t t = 0;
for (bit = 0; bit < 8; ++bit) { for (bit = 0; bit < 8; ++bit) {
x = *ptable++ - 1; uint8_t x = *ptable++ - 1;
t <<= 1; t <<= 1;
if ((in[x / 8]) & (0x80 >> (x % 8))) { if ((in[x / 8]) & (0x80 >> (x % 8))) {
t |= 0x01; t |= 0x01;
@ -395,8 +395,7 @@ void tdes_dec(void* out, void* in, const uint8_t* key){
uint8_t *tin = (uint8_t *) in; uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out; uint8_t *tout = (uint8_t *) out;
while( length > 0 ) while (length > 0) {
{
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
tout[i] = (unsigned char)(tin[i] ^ iv[i]); tout[i] = (unsigned char)(tin[i] ^ iv[i]);
@ -421,8 +420,7 @@ void tdes_dec(void* out, void* in, const uint8_t* key){
uint8_t *tin = (uint8_t *) in; uint8_t *tin = (uint8_t *) in;
uint8_t *tout = (uint8_t *) out; uint8_t *tout = (uint8_t *) out;
while( length > 0 ) while (length > 0) {
{
memcpy(temp, tin, 8); memcpy(temp, tin, 8);
des_dec(tout, tin, (uint8_t *)key + 0); des_dec(tout, tin, (uint8_t *)key + 0);

View file

@ -89,6 +89,8 @@ void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t l
} }
size_t key_block_size(const desfirekey_t key) { size_t key_block_size(const desfirekey_t key) {
if (key == NULL)
return 0;
size_t block_size = 8; size_t block_size = 8;
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
@ -286,10 +288,8 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
} }
void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) void *mifare_cryto_postprocess_data(desfiretag_t tag, void *data, size_t *nbytes, int communication_settings) {
{
void *res = data; void *res = data;
size_t edl;
void *edata = NULL; void *edata = NULL;
uint8_t first_cmac_byte = 0x00; uint8_t first_cmac_byte = 0x00;
@ -314,7 +314,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
case AS_LEGACY: case AS_LEGACY:
if (communication_settings & MAC_VERIFY) { if (communication_settings & MAC_VERIFY) {
*nbytes -= key_macing_length(key); *nbytes -= key_macing_length(key);
if (*nbytes <= 0) { if (*nbytes == 0) {
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
@ -323,7 +323,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break; break;
} }
edl = enciphered_data_length (tag, *nbytes - 1, communication_settings); size_t edl = enciphered_data_length(tag, *nbytes - 1, communication_settings);
edata = malloc(edl); edata = malloc(edl);
memcpy(edata, data, *nbytes - 1); memcpy(edata, data, *nbytes - 1);
@ -442,7 +442,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
} }
do { do {
uint16_t crc16 =0x00; uint16_t crc_16 = 0x00;
uint32_t crc; uint32_t crc;
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
@ -451,7 +451,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
// //
crc = crc16; crc = crc_16;
break; break;
case AS_NEW: case AS_NEW:
end_crc_pos = crc_pos + 4; end_crc_pos = crc_pos + 4;
@ -512,8 +512,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
} }
void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) void mifare_cypher_single_block(desfirekey_t key, uint8_t *data, uint8_t *ivect, MifareCryptoDirection direction, MifareCryptoOperation operation, size_t block_size) {
{
uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE]; uint8_t ovect[MAX_CRYPTO_BLOCK_SIZE];
if (direction == MCD_SEND) { if (direction == MCD_SEND) {
@ -570,17 +569,14 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
} }
break; break;
case T_AES: case T_AES:
switch (operation) switch (operation) {
{ case MCO_ENCYPHER: {
case MCO_ENCYPHER:
{
AesCtx ctx; AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC); AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesEncrypt(&ctx, data, edata, sizeof(edata)); AesEncrypt(&ctx, data, edata, sizeof(edata));
break; break;
} }
case MCO_DECYPHER: case MCO_DECYPHER: {
{
AesCtx ctx; AesCtx ctx;
AesCtxIni(&ctx, ivect, key->data, KEY128, CBC); AesCtxIni(&ctx, ivect, key->data, KEY128, CBC);
AesDecrypt(&ctx, edata, data, sizeof(edata)); AesDecrypt(&ctx, edata, data, sizeof(edata));

View file

@ -103,8 +103,7 @@ uint8_t Desfire_key_get_version (desfirekey_t key) {
return version; return version;
} }
void Desfire_key_set_version (desfirekey_t key, uint8_t version) void Desfire_key_set_version(desfirekey_t key, uint8_t version) {
{
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n)); uint8_t version_bit = ((version & (1 << (7 - n))) >> (7 - n));
key->data[n] &= 0xfe; key->data[n] &= 0xfe;

View file

@ -103,12 +103,10 @@ static char iso_type = 0;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Wrapper for sending APDUs to type A and B cards // Wrapper for sending APDUs to type A and B cards
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) {
{ switch (iso_type) {
switch(iso_type)
{
case 'a': case 'a':
return iso14_apdu(apdu, (uint16_t) length, response); return iso14_apdu(apdu, (uint16_t) length, false, response, NULL);
break; break;
case 'b': case 'b':
return iso14443b_apdu(apdu, length, response); return iso14443b_apdu(apdu, length, response);
@ -122,8 +120,7 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Closes the communication channel and turns off the field // Closes the communication channel and turns off the field
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_Finish() void EPA_Finish() {
{
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LEDsoff(); LEDsoff();
iso_type = 0; iso_type = 0;
@ -144,8 +141,7 @@ void EPA_Finish()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
size_t EPA_Parse_CardAccess(uint8_t *data, size_t EPA_Parse_CardAccess(uint8_t *data,
size_t length, size_t length,
pace_version_info_t *pace_info) pace_version_info_t *pace_info) {
{
size_t index = 0; size_t index = 0;
while (index <= length - 2) { while (index <= length - 2) {
@ -166,8 +162,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
&& memcmp(data + index + 2, && memcmp(data + index + 2,
oid_pace_start, oid_pace_start,
sizeof(oid_pace_start)) == 0 // content matches sizeof(oid_pace_start)) == 0 // content matches
&& pace_info != NULL) && pace_info != NULL) {
{
// first, clear the pace_info struct // first, clear the pace_info struct
memset(pace_info, 0, sizeof(pace_version_info_t)); memset(pace_info, 0, sizeof(pace_version_info_t));
memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid)); memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid));
@ -176,8 +171,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
if (data[index] == 02 && data[index + 1] == 01) { if (data[index] == 02 && data[index + 1] == 01) {
pace_info->version = data[index + 2]; pace_info->version = data[index + 2];
index += 3; index += 3;
} } else {
else {
return index; return index;
} }
// after that there might(!) be the parameter ID // after that there might(!) be the parameter ID
@ -185,8 +179,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
pace_info->parameter_id = data[index + 2]; pace_info->parameter_id = data[index + 2];
index += 3; index += 3;
} }
} } else {
else {
// skip this OID // skip this OID
index += 2 + data[index + 1]; index += 2 + data[index + 1];
} }
@ -195,8 +188,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
// TODO: This needs to be extended to support long tags // TODO: This needs to be extended to support long tags
else if (data[index + 1] == 0) { else if (data[index + 1] == 0) {
return index; return index;
} } else {
else {
// skip this part // skip this part
// TODO: This needs to be extended to support long tags // TODO: This needs to be extended to support long tags
// TODO: This needs to be extended to support unknown elements with // TODO: This needs to be extended to support unknown elements with
@ -215,8 +207,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
// Returns -1 on failure or the length of the data on success // Returns -1 on failure or the length of the data on success
// TODO: for the moment this sends only 1 APDU regardless of the requested length // TODO: for the moment this sends only 1 APDU regardless of the requested length
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) {
{
// the response APDU of the card // the response APDU of the card
// since the card doesn't always care for the expected length we send it, // since the card doesn't always care for the expected length we send it,
// we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame)
@ -229,8 +220,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
response_apdu); response_apdu);
if (rapdu_length < 6 if (rapdu_length < 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00) {
{
DbpString("Failed to select EF.CardAccess!"); DbpString("Failed to select EF.CardAccess!");
return -1; return -1;
} }
@ -241,8 +231,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
response_apdu); response_apdu);
if (rapdu_length <= 6 if (rapdu_length <= 6
|| response_apdu[rapdu_length - 4] != 0x90 || response_apdu[rapdu_length - 4] != 0x90
|| response_apdu[rapdu_length - 3] != 0x00) || response_apdu[rapdu_length - 3] != 0x00) {
{
Dbprintf("Failed to read EF.CardAccess!"); Dbprintf("Failed to read EF.CardAccess!");
return -1; return -1;
} }
@ -259,20 +248,18 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
// Abort helper function for EPA_PACE_Collect_Nonce // Abort helper function for EPA_PACE_Collect_Nonce
// sets relevant data in ack, sends the response // sets relevant data in ack, sends the response
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) {
{
// power down the field // power down the field
EPA_Finish(); EPA_Finish();
// send the USB packet // send the USB packet
cmd_send(CMD_ACK,step,func_return,0,0,0); reply_old(CMD_ACK, step, func_return, 0, 0, 0);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Acquire one encrypted PACE nonce // Acquire one encrypted PACE nonce
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Collect_Nonce(UsbCommand *c) void EPA_PACE_Collect_Nonce(PacketCommandNG *c) {
{
/* /*
* ack layout: * ack layout:
* arg: * arg:
@ -318,15 +305,19 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
// initiate the PACE protocol // initiate the PACE protocol
// use the CAN for the password since that doesn't change // use the CAN for the password since that doesn't change
func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2);
// check if the command succeeded
if (func_return != 0) {
EPA_PACE_Collect_Nonce_Abort(4, func_return);
return;
}
// now get the nonce // now get the nonce
uint8_t nonce[256] = {0}; uint8_t nonce[256] = {0};
uint8_t requested_size = (uint8_t)c->arg[0]; uint8_t requested_size = (uint8_t)c->oldarg[0];
func_return = EPA_PACE_Get_Nonce(requested_size, nonce); func_return = EPA_PACE_Get_Nonce(requested_size, nonce);
// check if the command succeeded // check if the command succeeded
if (func_return < 0) if (func_return < 0) {
{ EPA_PACE_Collect_Nonce_Abort(5, func_return);
EPA_PACE_Collect_Nonce_Abort(4, func_return);
return; return;
} }
@ -334,7 +325,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
EPA_Finish(); EPA_Finish();
// save received information // save received information
cmd_send(CMD_ACK,0,func_return,0,nonce,func_return); reply_old(CMD_ACK, 0, func_return, 0, nonce, func_return);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -345,8 +336,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c)
// Returns the actual size of the nonce on success or a less-than-zero error // Returns the actual size of the nonce on success or a less-than-zero error
// code on failure. // code on failure.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) {
{
// build the APDU // build the APDU
uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1]; uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1];
// copy the constant part // copy the constant part
@ -364,21 +354,18 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
// check if the command succeeded // check if the command succeeded
if (send_return < 6 if (send_return < 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00) {
{
return -1; return -1;
} }
// if there is no nonce in the RAPDU, return here // if there is no nonce in the RAPDU, return here
if (send_return < 10) if (send_return < 10) {
{
// no error // no error
return 0; return 0;
} }
// get the actual length of the nonce // get the actual length of the nonce
uint8_t nonce_length = response_apdu[5]; uint8_t nonce_length = response_apdu[5];
if (nonce_length > send_return - 10) if (nonce_length > send_return - 10) {
{
nonce_length = send_return - 10; nonce_length = send_return - 10;
} }
// copy the nonce // copy the nonce
@ -391,8 +378,7 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce)
// Initializes the PACE protocol by performing the "MSE: Set AT" step // Initializes the PACE protocol by performing the "MSE: Set AT" step
// Returns 0 on success or a non-zero error code on failure // Returns 0 on success or a non-zero error code on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) {
{
// create the MSE: Set AT APDU // create the MSE: Set AT APDU
uint8_t apdu[23]; uint8_t apdu[23];
// the minimum length (will be increased as more data is added) // the minimum length (will be increased as more data is added)
@ -435,8 +421,7 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
// check if the command succeeded // check if the command succeeded
if (send_return != 6 if (send_return != 6
|| response_apdu[send_return - 4] != 0x90 || response_apdu[send_return - 4] != 0x90
|| response_apdu[send_return - 3] != 0x00) || response_apdu[send_return - 3] != 0x00) {
{
return 1; return 1;
} }
return 0; return 0;
@ -445,27 +430,25 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Perform the PACE protocol by replaying given APDUs // Perform the PACE protocol by replaying given APDUs
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void EPA_PACE_Replay(UsbCommand *c) void EPA_PACE_Replay(PacketCommandNG *c) {
{ uint32_t timings[ARRAYLEN(apdu_lengths_replay)] = {0};
uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0};
// if an APDU has been passed, save it // if an APDU has been passed, save it
if (c->arg[0] != 0) { if (c->oldarg[0] != 0) {
// make sure it's not too big // make sure it's not too big
if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) if (c->oldarg[2] > apdus_replay[c->oldarg[0] - 1].len) {
{ reply_old(CMD_ACK, 1, 0, 0, NULL, 0);
cmd_send(CMD_ACK, 1, 0, 0, NULL, 0);
} }
memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], memcpy(apdus_replay[c->oldarg[0] - 1].data + c->oldarg[1],
c->d.asBytes, c->data.asBytes,
c->arg[2]); c->oldarg[2]);
// save/update APDU length // save/update APDU length
if (c->arg[1] == 0) { if (c->oldarg[1] == 0) {
apdu_lengths_replay[c->arg[0] - 1] = c->arg[2]; apdu_lengths_replay[c->oldarg[0] - 1] = c->oldarg[2];
} else { } else {
apdu_lengths_replay[c->arg[0] - 1] += c->arg[2]; apdu_lengths_replay[c->oldarg[0] - 1] += c->oldarg[2];
} }
cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); reply_old(CMD_ACK, 0, 0, 0, NULL, 0);
return; return;
} }
@ -476,7 +459,7 @@ void EPA_PACE_Replay(UsbCommand *c)
func_return = EPA_Setup(); func_return = EPA_Setup();
if (func_return != 0) { if (func_return != 0) {
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0); reply_old(CMD_ACK, 2, func_return, 0, NULL, 0);
return; return;
} }
@ -497,15 +480,14 @@ void EPA_PACE_Replay(UsbCommand *c)
if (i < sizeof(apdu_lengths_replay) - 1 if (i < sizeof(apdu_lengths_replay) - 1
&& (func_return < 6 && (func_return < 6
|| response_apdu[func_return - 4] != 0x90 || response_apdu[func_return - 4] != 0x90
|| response_apdu[func_return - 3] != 0x00)) || response_apdu[func_return - 3] != 0x00)) {
{
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20); reply_old(CMD_ACK, 3 + i, func_return, 0, timings, 20);
return; return;
} }
} }
EPA_Finish(); EPA_Finish();
cmd_send(CMD_ACK,0,0,0,timings,20); reply_old(CMD_ACK, 0, 0, 0, timings, 20);
return; return;
} }
@ -513,21 +495,18 @@ void EPA_PACE_Replay(UsbCommand *c)
// Set up a communication channel (Card Select, PPS) // Set up a communication channel (Card Select, PPS)
// Returns 0 on success or a non-zero error code on failure // Returns 0 on success or a non-zero error code on failure
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int EPA_Setup() int EPA_Setup() {
{
int return_code = 0;
uint8_t uid[10]; uint8_t uid[10];
uint8_t pps_response[3];
uint8_t pps_response_par[1];
iso14a_card_select_t card_a_info; iso14a_card_select_t card_a_info;
iso14b_card_select_t card_b_info;
// first, look for type A cards // first, look for type A cards
// power up the field // power up the field
iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD);
// select the card // select the card
return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false); int return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false);
if (return_code == 1) { if (return_code == 1) {
uint8_t pps_response[3];
uint8_t pps_response_par[1];
// send the PPS request // send the PPS request
ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL);
return_code = ReaderReceive(pps_response, pps_response_par); return_code = ReaderReceive(pps_response, pps_response_par);
@ -542,9 +521,10 @@ int EPA_Setup()
// if we're here, there is no type A card, so we look for type B // if we're here, there is no type A card, so we look for type B
// power up the field // power up the field
iso14443b_setup(); iso14443b_setup();
iso14b_card_select_t card_b_info;
// select the card // select the card
return_code = iso14443b_select_card(&card_b_info); return_code = iso14443b_select_card(&card_b_info);
if (return_code == 1) { if (return_code == 0) {
Dbprintf("ISO 14443 Type B"); Dbprintf("ISO 14443 Type B");
iso_type = 'b'; iso_type = 'b';
return 0; return 0;

View file

@ -29,27 +29,25 @@ static uint32_t felica_timeout;
static uint32_t felica_nexttransfertime; static uint32_t felica_nexttransfertime;
static uint32_t felica_lasttime_prox2air_start; static uint32_t felica_lasttime_prox2air_start;
static void felica_setup(uint8_t fpga_minor_mode); static void iso18092_setup(uint8_t fpga_minor_mode);
static uint8_t felica_select_card(felica_card_select_t *card); static uint8_t felica_select_card(felica_card_select_t *card);
static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed); static void TransmitFor18092_AsReader(uint8_t *frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed);
bool WaitForFelicaReply(uint16_t maxbytes); bool WaitForFelicaReply(uint16_t maxbytes);
void felica_set_timeout(uint32_t timeout) { void iso18092_set_timeout(uint32_t timeout) {
felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2; felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) + 2;
} }
uint32_t felica_get_timeout(void) { uint32_t iso18092_get_timeout(void) {
return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2; return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / (16 * 8) - 2;
} }
//random service RW: 0x0009 #ifndef FELICA_MAX_FRAME_SIZE
//random service RO: 0x000B #define FELICA_MAX_FRAME_SIZE 260
#ifndef NFC_MAX_FRAME_SIZE
#define NFC_MAX_FRAME_SIZE 260
#endif #endif
//structure to hold outgoing NFC frame //structure to hold outgoing NFC frame
static uint8_t frameSpace[NFC_MAX_FRAME_SIZE+4]; static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE + 4];
//structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames
static struct { static struct {
@ -71,114 +69,114 @@ static struct {
uint8_t *framebytes; uint8_t *framebytes;
//should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc
// 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc
} NFCFrame; } FelicaFrame;
//b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in //b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in
//bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in //bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in
#ifndef SYNC_16BIT #ifndef SYNC_16BIT
# define SYNC_16BIT 0x4DB2 # define SYNC_16BIT 0xB24D
#endif #endif
static void NFCFrameReset() { static void FelicaFrameReset() {
NFCFrame.state = STATE_UNSYNCD; FelicaFrame.state = STATE_UNSYNCD;
NFCFrame.posCnt = 0; FelicaFrame.posCnt = 0;
NFCFrame.crc_ok = false; FelicaFrame.crc_ok = false;
NFCFrame.byte_offset = 0; FelicaFrame.byte_offset = 0;
} }
static void NFCInit(uint8_t *data) { static void FelicaFrameinit(uint8_t *data) {
NFCFrame.framebytes = data; FelicaFrame.framebytes = data;
NFCFrameReset(); FelicaFrameReset();
} }
//shift byte into frame, reversing it at the same time //shift byte into frame, reversing it at the same time
static void shiftInByte(uint8_t bt) { static void shiftInByte(uint8_t bt) {
uint8_t j; uint8_t j;
for(j=0; j < NFCFrame.byte_offset; j++) { for (j = 0; j < FelicaFrame.byte_offset; j++) {
NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
NFCFrame.posCnt++; FelicaFrame.posCnt++;
NFCFrame.rem_len--; FelicaFrame.rem_len--;
for(j = NFCFrame.byte_offset; j<8; j++) { for (j = FelicaFrame.byte_offset; j < 8; j++) {
NFCFrame.framebytes[NFCFrame.posCnt] = (NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
} }
static void ProcessNFCByte(uint8_t bt) { static void Process18092Byte(uint8_t bt) {
switch (NFCFrame.state) { switch (FelicaFrame.state) {
case STATE_UNSYNCD: { case STATE_UNSYNCD: {
//almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case
if (bt > 0) { if (bt > 0) {
NFCFrame.shiftReg = reflect8(bt); FelicaFrame.shiftReg = reflect8(bt);
NFCFrame.state = STATE_TRYING_SYNC; FelicaFrame.state = STATE_TRYING_SYNC;
} }
break; break;
} }
case STATE_TRYING_SYNC: { case STATE_TRYING_SYNC: {
if (bt == 0) { if (bt == 0) {
//desync //desync
NFCFrame.shiftReg = bt; FelicaFrame.shiftReg = bt;
NFCFrame.state = STATE_UNSYNCD; FelicaFrame.state = STATE_UNSYNCD;
} else { } else {
for (uint8_t i = 0; i < 8; i++) { for (uint8_t i = 0; i < 8; i++) {
if (NFCFrame.shiftReg == SYNC_16BIT) { if (FelicaFrame.shiftReg == SYNC_16BIT) {
//SYNC done! //SYNC done!
NFCFrame.state = STATE_GET_LENGTH; FelicaFrame.state = STATE_GET_LENGTH;
NFCFrame.framebytes[0] = 0xb2; FelicaFrame.framebytes[0] = 0xb2;
NFCFrame.framebytes[1] = 0x4d; //write SYNC FelicaFrame.framebytes[1] = 0x4d;
NFCFrame.byte_offset = i; FelicaFrame.byte_offset = i;
//shift in remaining byte, slowly... //shift in remaining byte, slowly...
for (uint8_t j = i; j < 8; j++) { for (uint8_t j = i; j < 8; j++) {
NFCFrame.framebytes[2] = (NFCFrame.framebytes[2] << 1) + (bt & 1); FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
NFCFrame.posCnt = 2; FelicaFrame.posCnt = 2;
if (i == 0) if (i == 0)
break; break;
} }
NFCFrame.shiftReg = (NFCFrame.shiftReg << 1) + (bt & 1); FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1);
bt >>= 1; bt >>= 1;
} }
//that byte was last byte of sync //that byte was last byte of sync
if (NFCFrame.shiftReg == SYNC_16BIT) { if (FelicaFrame.shiftReg == SYNC_16BIT) {
//Force SYNC on next byte //Force SYNC on next byte
NFCFrame.state = STATE_GET_LENGTH; FelicaFrame.state = STATE_GET_LENGTH;
NFCFrame.framebytes[0] = 0xb2; FelicaFrame.framebytes[0] = 0xb2;
NFCFrame.framebytes[1] = 0x4d; FelicaFrame.framebytes[1] = 0x4d;
NFCFrame.byte_offset = 0; FelicaFrame.byte_offset = 0;
NFCFrame.posCnt = 1; FelicaFrame.posCnt = 1;
} }
} }
break; break;
} }
case STATE_GET_LENGTH: { case STATE_GET_LENGTH: {
shiftInByte(bt); shiftInByte(bt);
NFCFrame.rem_len = NFCFrame.framebytes[2] - 1; FelicaFrame.rem_len = FelicaFrame.framebytes[2] - 1;
NFCFrame.len = NFCFrame.framebytes[2] + 4; //with crc and sync FelicaFrame.len = FelicaFrame.framebytes[2] + 4; //with crc and sync
NFCFrame.state = STATE_GET_DATA; FelicaFrame.state = STATE_GET_DATA;
break; break;
} }
case STATE_GET_DATA: { case STATE_GET_DATA: {
shiftInByte(bt); shiftInByte(bt);
if (NFCFrame.rem_len <= 0) { if (FelicaFrame.rem_len <= 0) {
NFCFrame.state = STATE_GET_CRC; FelicaFrame.state = STATE_GET_CRC;
NFCFrame.rem_len = 2; FelicaFrame.rem_len = 2;
} }
break; break;
} }
case STATE_GET_CRC: { case STATE_GET_CRC: {
shiftInByte(bt); shiftInByte(bt);
if ( NFCFrame.rem_len <= 0 ) { if (FelicaFrame.rem_len <= 0) {
// skip sync 2bytes. IF ok, residue should be 0x0000 // skip sync 2bytes. IF ok, residue should be 0x0000
NFCFrame.crc_ok = check_crc(CRC_FELICA, NFCFrame.framebytes+2, NFCFrame.len-2); FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
NFCFrame.state = STATE_FULL; FelicaFrame.state = STATE_FULL;
NFCFrame.rem_len = 0; FelicaFrame.rem_len = 0;
if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (NFCFrame.crc_ok) ? "OK" : "No" ); if (DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No");
} }
break; break;
} }
@ -207,7 +205,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
// b0 = fc/64 (212kbps) // b0 = fc/64 (212kbps)
// 0x00 = timeslot // 0x00 = timeslot
// 0x09 0x21 = crc // 0x09 0x21 = crc
static uint8_t poll[10] = {0xb2,0x4d,0x06,0x00,0xFF,0xFF,0x00,0x00,0x09,0x21}; static uint8_t poll[10] = {0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xFF, 0xFF, 0x00, 0x00, 0x09, 0x21};
int len = 20; int len = 20;
@ -219,7 +217,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0); TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0);
// polling card, break if success // polling card, break if success
if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK)
break; break;
WDT_HIT(); WDT_HIT();
@ -231,19 +229,19 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
return 1; return 1;
// wrong answer // wrong answer
if (NFCFrame.framebytes[3] != FELICA_POLL_ACK) if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK)
return 2; return 2;
// VALIDATE CRC residue is 0, hence if crc is a value it failed. // VALIDATE CRC residue is 0, hence if crc is a value it failed.
if (!check_crc(CRC_FELICA, NFCFrame.framebytes+2, NFCFrame.len-2)) if (!check_crc(CRC_FELICA, FelicaFrame.framebytes + 2, FelicaFrame.len - 2))
return 3; return 3;
// copy UID // copy UID
// idm 8 // idm 8
if (card) { if (card) {
memcpy(card->IDm, NFCFrame.framebytes + 4, 8); memcpy(card->IDm, FelicaFrame.framebytes + 4, 8);
memcpy(card->PMm, NFCFrame.framebytes + 4 + 8, 8); memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8);
//memcpy(card->servicecode, NFCFrame.framebytes + 4 + 8 + 8, 2); //memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2);
memcpy(card->code, card->IDm, 2); memcpy(card->code, card->IDm, 2);
memcpy(card->uid, card->IDm + 2, 6); memcpy(card->uid, card->IDm + 2, 6);
memcpy(card->iccode, card->PMm, 2); memcpy(card->iccode, card->PMm, 2);
@ -269,7 +267,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) { static void BuildFliteRdblk(uint8_t *idm, int blocknum, uint16_t *blocks) {
if (blocknum > 4 || blocknum <= 0) if (blocknum > 4 || blocknum <= 0)
Dbprintf("Invalid number of blocks, %d. Up to 4 are allowed.", blocknum); Dbprintf("Invalid number of blocks, %d != 4", blocknum);
uint8_t c = 0, i = 0; uint8_t c = 0, i = 0;
@ -389,19 +387,20 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
// power, no modulation // power, no modulation
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
NFCFrameReset(); FelicaFrameReset();
// clear RXRDY: // clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
uint32_t timeout = felica_get_timeout(); uint32_t timeout = iso18092_get_timeout();
for (;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
ProcessNFCByte(b); Process18092Byte(b);
if (NFCFrame.state == STATE_FULL) { if (FelicaFrame.state == STATE_FULL) {
felica_nexttransfertime = felica_nexttransfertime =
MAX( MAX(
felica_nexttransfertime, felica_nexttransfertime,
@ -410,19 +409,19 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
; ;
LogTrace( LogTrace(
NFCFrame.framebytes, FelicaFrame.framebytes,
NFCFrame.len, FelicaFrame.len,
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout, ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER - timeout,
((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER, ((GetCountSspClk() & 0xfffffff8) << 4) - DELAY_AIR2ARM_AS_READER,
NULL, NULL,
false false
); );
return true; return true;
} else if (c++ > timeout && NFCFrame.state == STATE_UNSYNCD) { } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) {
return false; return false;
} else if (NFCFrame.state == STATE_GET_CRC) { } else if (FelicaFrame.state == STATE_GET_CRC) {
Dbprintf(" Frame: "); Dbprintf(" Frame: ");
Dbhexdump(16, NFCFrame.framebytes, 0); Dbhexdump(16, FelicaFrame.framebytes, 0);
//return false; //return false;
} }
} }
@ -432,20 +431,23 @@ bool WaitForFelicaReply(uint16_t maxbytes) {
// Set up FeliCa communication (similar to iso14443a_setup) // Set up FeliCa communication (similar to iso14443a_setup)
// field is setup for "Sending as Reader" // field is setup for "Sending as Reader"
static void felica_setup(uint8_t fpga_minor_mode) { static void iso18092_setup(uint8_t fpga_minor_mode) {
LEDsoff(); LEDsoff();
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
// allocate command receive buffer // allocate command receive buffer
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
// Initialize Demod and Uart structs // Initialize Demod and Uart structs
//DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
NFCInit(BigBuf_malloc(NFC_MAX_FRAME_SIZE)); FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE));
felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER;
felica_set_timeout(2120); // 106 * 20ms maximum start-up time of card iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card
init_table(CRC_FELICA);
// connect Demodulated Signal to ADC: // connect Demodulated Signal to ADC:
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
@ -456,8 +458,6 @@ static void felica_setup(uint8_t fpga_minor_mode) {
// LSB transfer. Remember to set it back to MSB with // LSB transfer. Remember to set it back to MSB with
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
init_table(CRC_FELICA);
// Signal field is on with the appropriate LED // Signal field is on with the appropriate LED
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode);
@ -475,14 +475,14 @@ static void felica_setup(uint8_t fpga_minor_mode) {
// arg0 FeliCa flags // arg0 FeliCa flags
// arg1 len of commandbytes // arg1 len of commandbytes
// d.asBytes command bytes to send // d.asBytes command bytes to send
void felica_sendraw(UsbCommand *c) { void felica_sendraw(PacketCommandNG *c) {
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter");
felica_command_t param = c->arg[0]; felica_command_t param = c->oldarg[0];
size_t len = c->arg[1] & 0xffff; size_t len = c->oldarg[1] & 0xffff;
uint8_t *cmd = c->d.asBytes; uint8_t *cmd = c->data.asBytes;
uint32_t arg0 = 0; uint32_t arg0;
felica_card_select_t card; felica_card_select_t card;
@ -492,13 +492,13 @@ void felica_sendraw(UsbCommand *c) {
set_tracing(true); set_tracing(true);
if ((param & FELICA_CONNECT)) { if ((param & FELICA_CONNECT)) {
felica_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
// notify client selecting status. // notify client selecting status.
// if failed selecting, turn off antenna and quite. // if failed selecting, turn off antenna and quite.
if (!(param & FELICA_NO_SELECT)) { if (!(param & FELICA_NO_SELECT)) {
arg0 = felica_select_card(&card); arg0 = felica_select_card(&card);
cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); reply_old(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t));
if (arg0 > 0) if (arg0 > 0)
goto OUT; goto OUT;
} }
@ -520,13 +520,12 @@ void felica_sendraw(UsbCommand *c) {
// Don't append crc on empty bytearray... // Don't append crc on empty bytearray...
if (len > 0) { if (len > 0) {
AddCrc(buf, len); AddCrc(buf, len);
len += 2;
} }
} }
TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0); TransmitFor18092_AsReader(buf, buf[2] + 4, NULL, 1, 0);
arg0 = !WaitForFelicaReply(1024); arg0 = !WaitForFelicaReply(1024);
cmd_send(CMD_ACK, arg0, 0, 0, NFCFrame.framebytes+2, NFCFrame.len-2); reply_old(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes + 2, FelicaFrame.len - 2);
} }
if ((param & FELICA_NO_DISCONNECT)) if ((param & FELICA_NO_DISCONNECT))
@ -538,16 +537,16 @@ OUT:
//Resetting Frame mode (First set in fpgaloader.c) //Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); if (DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit");
} }
void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
int remFrames = (samplesToSkip) ? samplesToSkip : 0; int remFrames = (samplesToSkip) ? samplesToSkip : 0;
Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); Dbprintf("Sniff FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
felica_setup( FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
//the frame bits are slow enough. //the frame bits are slow enough.
int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory
@ -563,24 +562,24 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
ProcessNFCByte(dist); Process18092Byte(dist);
//to be sure we are in frame //to be sure we are in frame
if (NFCFrame.state == STATE_GET_LENGTH) { if (FelicaFrame.state == STATE_GET_LENGTH) {
//length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100%
uint16_t distance = GetCountSspClk() - endframe - 64 + (NFCFrame.byte_offset > 0 ? (8-NFCFrame.byte_offset) : 0); uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8 - FelicaFrame.byte_offset) : 0);
*dest = distance >> 8; *dest = distance >> 8;
dest++; dest++;
*dest = (distance & 0xff); *dest = (distance & 0xff);
dest++; dest++;
} }
//crc NOT checked //crc NOT checked
if (NFCFrame.state == STATE_FULL) { if (FelicaFrame.state == STATE_FULL) {
endframe = GetCountSspClk(); endframe = GetCountSspClk();
//*dest = NFCFrame.crc_ok; //kind of wasteful //*dest = FelicaFrame.crc_ok; //kind of wasteful
dest++; dest++;
for(int i=0; i < NFCFrame.len; i++) { for (int i = 0; i < FelicaFrame.len; i++) {
*dest = NFCFrame.framebytes[i]; *dest = FelicaFrame.framebytes[i];
dest++; dest++;
if (dest >= destend) break; if (dest >= destend) break;
@ -590,9 +589,9 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
if (remFrames <= 0) break; if (remFrames <= 0) break;
if (dest >= destend) break; if (dest >= destend) break;
numbts += NFCFrame.len; numbts += FelicaFrame.len;
NFCFrameReset(); FelicaFrameReset();
} }
} }
} }
@ -604,7 +603,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
set_tracelen(numbts); set_tracelen(numbts);
Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen()); Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen());
cmd_send(CMD_ACK,1, numbts,0,0,0); reply_old(CMD_ACK, 1, numbts, 0, 0, 0);
} }
#define R_POLL0_LEN 0x16 #define R_POLL0_LEN 0x16
@ -612,18 +611,18 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) {
#define R_READBLK_LEN 0x21 #define R_READBLK_LEN 0x21
//simulate NFC Tag3 card - for now only poll response works //simulate NFC Tag3 card - for now only poll response works
// second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1 // second half (4 bytes) of NDEF2 goes into nfcid2_0, first into nfcid2_1
void felica_sim_lite(uint64_t nfcid) { void felica_sim_lite(uint64_t uid) {
int i, curlen = 0; int i, curlen = 0;
uint8_t *curresp = 0; uint8_t *curresp = 0;
uint8_t ndef[8]; uint8_t ndef[8];
num_to_bytes(nfcid, 8, ndef); num_to_bytes(uid, 8, ndef);
//prepare our 3 responses... //prepare our 3 responses...
uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2, 0x4d, 0x12, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0xb3, 0x7f};
uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2, 0x4d, 0x14, FELICA_POLL_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00, 0x88, 0xb4, 0xb3, 0x7f};
uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2, 0x4d, 0x1d, FELICA_RDBLK_ACK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x04, 0x01, 0x00, 0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x23, 0xcb, 0x6e};
//NFC tag 3/ ISo technically. Many overlapping standards //NFC tag 3/ ISo technically. Many overlapping standards
DbpString("Felica Lite-S sim start"); DbpString("Felica Lite-S sim start");
@ -643,7 +642,7 @@ void felica_sim_lite(uint64_t nfcid) {
AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_poll1, resp_poll1[2]);
AddCrc(resp_readblk, resp_readblk[2]); AddCrc(resp_readblk, resp_readblk[2]);
felica_setup( FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_NOMOD);
bool listenmode = true; bool listenmode = true;
//uint32_t frtm = GetCountSspClk(); //uint32_t frtm = GetCountSspClk();
@ -657,28 +656,28 @@ void felica_sim_lite(uint64_t nfcid) {
uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR);
//frtm = GetCountSspClk(); //frtm = GetCountSspClk();
ProcessNFCByte(dist); Process18092Byte(dist);
if (NFCFrame.state == STATE_FULL) { if (FelicaFrame.state == STATE_FULL) {
if (NFCFrame.crc_ok) { if (FelicaFrame.crc_ok) {
if (NFCFrame.framebytes[2] == 6 && NFCFrame.framebytes[3] == 0) { if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) {
//polling... there are two types of polling we answer to //polling... there are two types of polling we answer to
if (NFCFrame.framebytes[6] == 0) { if (FelicaFrame.framebytes[6] == 0) {
curresp = resp_poll0; curresp = resp_poll0;
curlen = R_POLL0_LEN; curlen = R_POLL0_LEN;
listenmode = false; listenmode = false;
} }
if (NFCFrame.framebytes[6] == 1) { if (FelicaFrame.framebytes[6] == 1) {
curresp = resp_poll1; curresp = resp_poll1;
curlen = R_POLL1_LEN; curlen = R_POLL1_LEN;
listenmode = true; listenmode = true;
} }
} }
if (NFCFrame.framebytes[2] > 5 && NFCFrame.framebytes[3] == 0x06) { if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) {
//we should rebuild it depending on page size, but... //we should rebuild it depending on page size, but...
//Let's see first //Let's see first
curresp = resp_readblk; curresp = resp_readblk;
@ -686,10 +685,10 @@ void felica_sim_lite(uint64_t nfcid) {
listenmode = false; listenmode = false;
} }
//clear frame //clear frame
NFCFrameReset(); FelicaFrameReset();
} else { } else {
//frame invalid, clear it out to allow for the next one //frame invalid, clear it out to allow for the next one
NFCFrameReset(); FelicaFrameReset();
} }
} }
} }
@ -703,7 +702,7 @@ void felica_sim_lite(uint64_t nfcid) {
//switch back //switch back
FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD);
NFCFrameReset(); FelicaFrameReset();
listenmode = true; listenmode = true;
curlen = 0; curlen = 0;
curresp = NULL; curresp = NULL;
@ -721,18 +720,18 @@ void felica_sim_lite(uint64_t nfcid) {
void felica_dump_lite_s() { void felica_dump_lite_s() {
uint8_t ndef[8]; uint8_t ndef[8];
uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; uint8_t poll[10] = { 0xb2, 0x4d, 0x06, FELICA_POLL_REQ, 0xff, 0xff, 0x00, 0x00, 0x09, 0x21};
uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0}; uint16_t liteblks[28] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x90, 0x91, 0x92, 0xa0};
// setup device. // setup device.
felica_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD);
uint8_t blknum; uint8_t blknum;
bool isOK = false; bool isOK = false;
uint16_t cnt = 0, cntfails = 0; uint16_t cnt = 0, cntfails = 0;
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
while (!BUTTON_PRESS() && !usb_poll_validate_length()) { while (!BUTTON_PRESS() && !data_available()) {
WDT_HIT(); WDT_HIT();
@ -740,12 +739,12 @@ void felica_dump_lite_s() {
//TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0);
TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); TransmitFor18092_AsReader(poll, 10, NULL, 1, 0);
if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) { if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) {
// copy 8bytes to ndef. // copy 8bytes to ndef.
memcpy(ndef, NFCFrame.framebytes + 4, 8); memcpy(ndef, FelicaFrame.framebytes + 4, 8);
// for (c=0; c < 8; c++) // for (c=0; c < 8; c++)
// ndef[c] = NFCFrame.framebytes[c+4]; // ndef[c] = FelicaFrame.framebytes[c+4];
for (blknum = 0; blknum < sizeof(liteblks);) { for (blknum = 0; blknum < sizeof(liteblks);) {
@ -756,15 +755,15 @@ void felica_dump_lite_s() {
TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0); TransmitFor18092_AsReader(frameSpace, frameSpace[2] + 4, NULL, 1, 0);
// read block // read block
if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) { if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) {
dest[cnt++] = liteblks[blknum]; dest[cnt++] = liteblks[blknum];
uint8_t *fb = NFCFrame.framebytes; uint8_t *fb = FelicaFrame.framebytes;
dest[cnt++] = fb[12]; dest[cnt++] = fb[12];
dest[cnt++] = fb[13]; dest[cnt++] = fb[13];
//memcpy(dest+cnt, NFCFrame.framebytes + 15, 16); //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16);
//cnt += 16; //cnt += 16;
for (uint8_t j = 0; j < 16; j++) for (uint8_t j = 0; j < 16; j++)
dest[cnt++] = fb[15 + j]; dest[cnt++] = fb[15 + j];
@ -773,8 +772,8 @@ void felica_dump_lite_s() {
cntfails = 0; cntfails = 0;
// // print raw log. // // print raw log.
// Dbprintf("LEN %u | Dump bytes count %u ", NFCFrame.len, cnt); // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt);
Dbhexdump(NFCFrame.len, NFCFrame.framebytes+15, 0); Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes + 15, 0);
} else { } else {
cntfails++; cntfails++;
if (cntfails > 12) { if (cntfails > 12) {
@ -795,5 +794,5 @@ void felica_dump_lite_s() {
//setting tracelen - important! it was set by buffer overflow before //setting tracelen - important! it was set by buffer overflow before
set_tracelen(cnt); set_tracelen(cnt);
cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0); reply_old(CMD_ACK, isOK, cnt, 0, 0, 0);
} }

View file

@ -1,39 +1,42 @@
#include "flashmem.h" #include "flashmem.h"
/* here: use NCPS2 @ PA10: */ /* here: use NCPS2 @ PA10: */
#define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4) #define SPI_CSR_NUM 2
#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16)
/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */ /// Calculates the value of the CSR SCBR field given the baudrate and MCK.
#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3)) // 0xE - 1110 #define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8)
#define PCS_1 ((1<<0)|(0<<1)|(1<<2)|(1<<3)) // 0xD - 1101 /// Calculates the value of the CSR DLYBS field given the desired delay (in ns)
#define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011 #define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16)
#define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111 /// Calculates the value of the CSR DLYBCT field given the desired delay (in ns)
#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24)
// TODO
#if (SPI_CSR_NUM == 0)
#define SPI_MR_PCS PCS_0
#elif (SPI_CSR_NUM == 1)
#define SPI_MR_PCS PCS_1
#elif (SPI_CSR_NUM == 2)
#define SPI_MR_PCS PCS_2
#elif (SPI_CSR_NUM == 3)
#define SPI_MR_PCS PCS_3
#else
#error "SPI_CSR_NUM invalid"
// not realy - when using an external address decoder...
// but this code takes over the complete SPI-interace anyway
#endif
/* uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD;
1-256256
CS拉高
*/
void FlashSetup(void) { void FlashmemSetSpiBaudrate(uint32_t baudrate) {
// PA1 -> SPI_NCS3 chip select (MEM) FLASHMEM_SPIBAUDRATE = baudrate;
// PA10 -> SPI_NCS2 chip select (LCD) Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE / 1000000);
}
// initialize
bool FlashInit() {
FlashSetup(FLASHMEM_SPIBAUDRATE);
StartTicks();
if (Flash_CheckBusy(BUSY_TIMEOUT)) {
StopTicks();
return false;
}
return true;
}
void FlashSetup(uint32_t baudrate) {
//WDT_DISABLE
AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS;
// PA10 -> SPI_NCS2 chip select (FLASHMEM)
// PA11 -> SPI_NCS0 chip select (FPGA) // PA11 -> SPI_NCS0 chip select (FPGA)
// PA12 -> SPI_MISO Master-In Slave-Out // PA12 -> SPI_MISO Master-In Slave-Out
// PA13 -> SPI_MOSI Master-Out Slave-In // PA13 -> SPI_MOSI Master-Out Slave-In
@ -54,34 +57,83 @@ void FlashSetup(void) {
//enable the SPI Peripheral clock //enable the SPI Peripheral clock
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI);
//reset spi needs double SWRST, see atmel's errata on this case
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST;
// Enable SPI // Enable SPI
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN;
// NPCS2 Mode 0 // NPCS2 Mode 0
AT91C_BASE_SPI->SPI_MR = AT91C_BASE_SPI->SPI_MR =
( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT:
(0xB << 16) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) // If DLYBCS is less than or equal to six, six MCK periods
( 0 << 7) | // Local Loopback Disabled // will be inserted by default.
( 1 << 4) | // Mode Fault Detection disabled SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10)
(0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
(1 << 4) | // Disable ModeFault Protection
(0 << 3) | // makes spi operate at MCK (1 is MCK/2)
(0 << 2) | // Chip selects connected directly to peripheral (0 << 2) | // Chip selects connected directly to peripheral
( 0 << 1) | // Fixed Peripheral Select AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
( 1 << 0); // Master Mode AT91C_SPI_MSTR; // Master Mode
uint8_t csaat = 1;
uint32_t dlybct = 0;
uint8_t ncpha = 1;
uint8_t cpol = 0;
if (baudrate > FLASH_MINFAST) {
baudrate = FLASH_FASTBAUD;
//csaat = 0;
dlybct = 1500;
ncpha = 0;
cpol = 0;
}
// 8 bit
AT91C_BASE_SPI->SPI_CSR[2] = AT91C_BASE_SPI->SPI_CSR[2] =
( 0 << 24) | // Delay between Consecutive Transfers (32 MCK periods) SPI_DLYBCT(dlybct, MCK) | // Delay between Consecutive Transfers (32 MCK periods)
( 0 << 16) | // Delay Before SPCK (1 MCK period) SPI_DLYBS(0, MCK) | // Delay Beforce SPCK CLock
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud SPI_SCBR(baudrate, MCK) | // SPI Baudrate Selection
( 0 << 4) | // Bits per Transfer (8 bits) AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits)
( 1 << 3) | // Chip Select inactive after transfer //AT91C_SPI_CSAAT | // Chip Select inactive after transfer
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1
( 0 << 0); // Clock Polarity inactive state is logic 0 // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on
// the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been
// transferred in the shifter. This can imply for example, that the second data is sent twice.
// COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay
(csaat << 3) |
/* Spi modes:
Mode CPOL CPHA NCPHA
0 0 0 1 clock normally low read on rising edge
1 0 1 0 clock normally low read on falling edge
2 1 0 1 clock normally high read on falling edge
3 1 1 0 clock normally high read on rising edge
However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI
master mode the ATSAM7S512/256/128/64/321/32 does not sample the data
(MISO) on the opposite edge where data clocks out (MOSI) but the same
edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3
shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and
that the data changes sometime after the rising edge (about 2 ns). To
be consistent with normal SPI operation, it is probably safe to say
that the data changes on the falling edge and should be sampled on the
rising edge. Therefore, it appears that NCPHA should be treated the
same as CPHA. Thus:
Mode CPOL CPHA NCPHA
0 0 0 0 clock normally low read on rising edge
1 0 1 1 clock normally low read on falling edge
2 1 0 0 clock normally high read on falling edge
3 1 1 1 clock normally high read on rising edge
Update: for 24MHz, writing is more stable with ncpha=1, else bitflips occur.
*/
(ncpha << 1) | // Clock Phase data captured on leading edge, changes on following edge
(cpol << 0); // Clock Polarity inactive state is logic 0
// read first, empty buffer // read first, empty buffer
if (AT91C_BASE_SPI->SPI_RDR == 0) {}; if (AT91C_BASE_SPI->SPI_RDR == 0) {};
} }
void FlashStop(void) { void FlashStop(void) {
//Bof
//* Reset all the Chip Select register //* Reset all the Chip Select register
AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[0] = 0;
AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0;
@ -97,31 +149,28 @@ void FlashStop(void) {
// SPI disable // SPI disable
AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS;
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); if (DBGLEVEL > 3) Dbprintf("FlashStop");
StopTicks(); StopTicks();
} }
// send one byte over SPI // send one byte over SPI
uint16_t FlashSendByte(uint32_t data) { uint16_t FlashSendByte(uint32_t data) {
uint16_t incoming = 0;
WDT_HIT();
// wait until SPI is ready for transfer // wait until SPI is ready for transfer
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; //if you are checking for incoming data returned then the TXEMPTY flag is redundant
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {};
// send the data // send the data
AT91C_BASE_SPI->SPI_TDR = data; AT91C_BASE_SPI->SPI_TDR = data;
//while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){};
// wait recive transfer is complete // wait recive transfer is complete
while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) {};
WDT_HIT();
// reading incoming data // reading incoming data
incoming = ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF);
return incoming;
} }
// send last byte over SPI // send last byte over SPI
@ -132,41 +181,33 @@ uint16_t FlashSendLastByte(uint32_t data) {
// read state register 1 // read state register 1
uint8_t Flash_ReadStat1(void) { uint8_t Flash_ReadStat1(void) {
FlashSendByte(READSTAT1); FlashSendByte(READSTAT1);
uint8_t stat1 = FlashSendLastByte(0xFF); return FlashSendLastByte(0xFF);
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat1 [%02x]", stat1);
return stat1;
} }
// read state register 2 bool Flash_CheckBusy(uint32_t timeout) {
uint8_t Flash_ReadStat2(void) { WaitUS(WINBOND_WRITE_DELAY);
FlashSendByte(READSTAT2); StartCountUS();
uint8_t stat2 = FlashSendLastByte(0xFF); uint32_t _time = GetCountUS();
// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat2 [%02x]", stat2);
return stat2; if (DBGLEVEL > 3) Dbprintf("Checkbusy in...");
do {
if (!(Flash_ReadStat1() & BUSY)) {
return false;
}
} while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time)) {
return true;
} }
// determine whether FLASHMEM is busy return false;
bool Flash_CheckBusy(uint16_t times) {
bool ret = (Flash_ReadStat1() & BUSY);
if (!ret || !times || !(times--))
return ret;
while (times) {
WDT_HIT();
SpinDelay(1);
ret = (Flash_ReadStat1() & BUSY);
if (!ret)
break;
times--;
}
return ret;
} }
// read ID out // read ID out
uint8_t Flash_ReadID(void) { uint8_t Flash_ReadID(void) {
if (Flash_CheckBusy(100)) return 0; if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
// Manufacture ID / device ID // Manufacture ID / device ID
FlashSendByte(ID); FlashSendByte(ID);
@ -177,7 +218,7 @@ uint8_t Flash_ReadID(void) {
uint8_t man_id = FlashSendByte(0xFF); uint8_t man_id = FlashSendByte(0xFF);
uint8_t dev_id = FlashSendLastByte(0xFF); uint8_t dev_id = FlashSendLastByte(0xFF);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id); if (DBGLEVEL > 3) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id);
if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID)) if ((man_id == WINBOND_MANID) && (dev_id == WINBOND_DEVID))
return dev_id; return dev_id;
@ -188,7 +229,7 @@ uint8_t Flash_ReadID(void) {
// read unique id for chip. // read unique id for chip.
void Flash_UniqueID(uint8_t *uid) { void Flash_UniqueID(uint8_t *uid) {
if (Flash_CheckBusy(100)) return; if (Flash_CheckBusy(BUSY_TIMEOUT)) return;
// reading unique serial number // reading unique serial number
FlashSendByte(UNIQUE_ID); FlashSendByte(UNIQUE_ID);
@ -211,26 +252,58 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) {
if (!FlashInit()) return 0; if (!FlashInit()) return 0;
Flash_ReadStat1();
// length should never be zero // length should never be zero
if (!len || Flash_CheckBusy(100)) return 0; if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0;
FlashSendByte(READDATA); uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF); FlashSendByte(cmd);
FlashSendByte((address >> 0) & 0xFF); Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0; uint16_t i = 0;
for (; i < (len - 1); i++) for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF); out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF); out[i] = FlashSendLastByte(0xFF);
FlashStop(); FlashStop();
return len; return len;
} }
void Flash_TransferAdresse(uint32_t address) {
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
}
/* This ensure we can ReadData without having to cycle through initialization everytime */
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) {
// length should never be zero
if (!len) return 0;
uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA;
FlashSendByte(cmd);
Flash_TransferAdresse(address);
if (FASTFLASH) {
FlashSendByte(DUMMYBYTE);
}
uint16_t i = 0;
for (; i < (len - 1); i++)
out[i] = FlashSendByte(0xFF);
out[i] = FlashSendLastByte(0xFF);
return len;
}
////////////////////////////////////////
// Write data can only program one page. A page has 256 bytes. // Write data can only program one page. A page has 256 bytes.
// if len > 256, it might wrap around and overwrite pos 0. // if len > 256, it might wrap around and overwrite pos 0.
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
@ -252,11 +325,11 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
} }
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return 0; return 0;
} }
Flash_ReadStat1(); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_WriteEnable();
@ -275,15 +348,82 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
return len; return len;
} }
// length should never be zero
// Max 256 bytes write
// out-of-range
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) {
if (!len)
return 0;
if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0;
}
if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteDataCont, block out-of-range");
return 0;
}
FlashSendByte(PAGEPROG);
FlashSendByte((address >> 16) & 0xFF);
FlashSendByte((address >> 8) & 0xFF);
FlashSendByte((address >> 0) & 0xFF);
uint16_t i = 0;
for (; i < (len - 1); i++)
FlashSendByte(in[i]);
FlashSendLastByte(in[i]);
return len;
}
// assumes valid start 256 based 00 address
//
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) {
bool isok;
uint16_t res, bytes_sent = 0, bytes_remaining = len;
uint8_t buf[FLASH_MEM_BLOCK_SIZE];
while (bytes_remaining > 0) {
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining);
memcpy(buf, in + bytes_sent, bytes_in_packet);
res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet);
bytes_remaining -= bytes_in_packet;
bytes_sent += bytes_in_packet;
isok = (res == bytes_in_packet);
if (!isok)
goto out;
}
out:
FlashStop();
return len;
}
bool Flash_WipeMemoryPage(uint8_t page) { bool Flash_WipeMemoryPage(uint8_t page) {
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. One block erase takes 1s ( 1000ms ) // Each block is 64Kb. One block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(1000); Flash_WriteEnable();
Flash_Erase64k(page);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop(); FlashStop();
return true; return true;
@ -291,17 +431,25 @@ bool Flash_WipeMemoryPage(uint8_t page) {
// Wipes flash memory completely, fills with 0xFF // Wipes flash memory completely, fills with 0xFF
bool Flash_WipeMemory() { bool Flash_WipeMemory() {
if (!FlashInit()) { if (!FlashInit()) {
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); if (DBGLEVEL > 3) Dbprintf("Flash_WriteData init fail");
return false; return false;
} }
Flash_ReadStat1(); Flash_ReadStat1();
// Each block is 64Kb. Four blocks // Each block is 64Kb. Four blocks
// one block erase takes 1s ( 1000ms ) // one block erase takes 1s ( 1000ms )
Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000); Flash_WriteEnable();
Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000); Flash_Erase64k(0);
Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000); Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000); Flash_WriteEnable();
Flash_Erase64k(1);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(2);
Flash_CheckBusy(BUSY_TIMEOUT);
Flash_WriteEnable();
Flash_Erase64k(3);
Flash_CheckBusy(BUSY_TIMEOUT);
FlashStop(); FlashStop();
return true; return true;
@ -310,7 +458,7 @@ bool Flash_WipeMemory() {
// enable the flash write // enable the flash write
void Flash_WriteEnable() { void Flash_WriteEnable() {
FlashSendLastByte(WRITEENABLE); FlashSendLastByte(WRITEENABLE);
if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); if (DBGLEVEL > 3) Dbprintf("Flash Write enabled");
} }
// erase 4K at one time // erase 4K at one time
@ -331,7 +479,7 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector) {
// execution time: 0,3s / 300ms // execution time: 0,3s / 300ms
bool Flash_Erase32k(uint32_t address) { bool Flash_Erase32k(uint32_t address) {
if (address & (32*1024 - 1)) { if (address & (32*1024 - 1)) {
if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096"); if ( DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096");
return false; return false;
} }
FlashSendByte(BLOCK32ERASE); FlashSendByte(BLOCK32ERASE);
@ -361,57 +509,80 @@ bool Flash_Erase64k(uint8_t block) {
return true; return true;
} }
/*
// Erase chip // Erase chip
void Flash_EraseChip(void) { void Flash_EraseChip(void) {
FlashSendLastByte(CHIPERASE); FlashSendLastByte(CHIPERASE);
} }
*/
// initialize
bool FlashInit(void) {
FlashSetup();
StartTicks();
if (Flash_CheckBusy(100)) {
StopTicks();
return false;
}
if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashInit OK");
return true;
}
void Flashmem_print_status(void) { void Flashmem_print_status(void) {
DbpString("Flash memory"); DbpString(_BLUE_("Flash memory"));
Dbprintf(" Baudrate................" _GREEN_("%d MHz"), FLASHMEM_SPIBAUDRATE / 1000000);
if (!FlashInit()) { if (!FlashInit()) {
DbpString(" init....................FAIL"); DbpString(" Init...................." _RED_("FAILED"));
return; return;
} }
DbpString(" init....................OK"); DbpString(" Init...................." _GREEN_("OK"));
uint8_t dev_id = Flash_ReadID(); uint8_t dev_id = Flash_ReadID();
switch (dev_id) { switch (dev_id) {
case 0x11 : case 0x11 :
DbpString(" Memory size.............2 mbits / 256kb"); DbpString(" Memory size............." _YELLOW_("2 mbits / 256 kb"));
break; break;
case 0x10 : case 0x10 :
DbpString(" Memory size..... .......1 mbits / 128kb"); DbpString(" Memory size..... ......." _YELLOW_("1 mbits / 128 kb"));
break; break;
case 0x05 : case 0x05 :
DbpString(" Memory size.............512 kbits / 64kb"); DbpString(" Memory size............." _YELLOW_("512 kbits / 64 kb"));
break; break;
default : default :
DbpString(" Device ID............... --> Unknown <--"); DbpString(" Device ID..............." _YELLOW_(" --> Unknown <--"));
break; break;
} }
uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t uid[8] = {0, 0, 0, 0, 0, 0, 0, 0};
Flash_UniqueID(uid); Flash_UniqueID(uid);
Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf(" Unique ID...............0x%02X%02X%02X%02X%02X%02X%02X%02X",
uid[7], uid[6], uid[5], uid[4], uid[7], uid[6], uid[5], uid[4],
uid[3], uid[2], uid[1], uid[0] uid[3], uid[2], uid[1], uid[0]
); );
FlashStop(); FlashStop();
} }
void Flashmem_print_info(void) {
if (!FlashInit()) return;
DbpString(_BLUE_("Flash memory dictionary loaded"));
// load dictionary offsets.
uint8_t keysum[2];
uint16_t num;
uint16_t isok = Flash_ReadDataCont(DEFAULT_MF_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" Mifare................"_YELLOW_("%d")"keys", num);
}
isok = Flash_ReadDataCont(DEFAULT_T55XX_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" T55x7................."_YELLOW_("%d")"keys", num);
}
isok = Flash_ReadDataCont(DEFAULT_ICLASS_KEYS_OFFSET, keysum, 2);
if (isok == 2) {
num = ((keysum[1] << 8) | keysum[0]);
if (num != 0xFFFF && num != 0x0)
Dbprintf(" iClass................"_YELLOW_("%d")"keys", num);
}
FlashStop();
}

View file

@ -45,6 +45,7 @@
#define WRITEENABLE 0x06 #define WRITEENABLE 0x06
#define READDATA 0x03 #define READDATA 0x03
#define FASTREAD 0x0B
#define PAGEPROG 0x02 #define PAGEPROG 0x02
#define SECTORERASE 0x20 #define SECTORERASE 0x20
@ -57,27 +58,18 @@
// Not used or not support command // Not used or not support command
#define RELEASE 0xAB #define RELEASE 0xAB
#define POWERDOWN 0xB9 #define POWERDOWN 0xB9
#define FASTREAD 0x0B
#define SUSPEND 0x75 #define SUSPEND 0x75
#define RESUME 0x7A #define RESUME 0x7A
// Flash busy timeout: 20ms is the strict minimum when writing 256kb
#define BUSY_TIMEOUT 50000L
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Chip specific instructions //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~//
#define WINBOND_MANID 0xEF #define WINBOND_MANID 0xEF
#define WINBOND_DEVID 0x11 #define WINBOND_DEVID 0x11
#define PAGESIZE 0x100 #define PAGESIZE 0x100
#define WINBOND_WRITE_DELAY 0x02
//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~// #define SPI_CLK 48000000
#define MICROCHIP_MANID 0xBF
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
// Definitions //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
#define SPI_CLK 75000000 //Hex equivalent of 75MHz
#define BUSY 0x01 #define BUSY 0x01
#define WRTEN 0x02 #define WRTEN 0x02
@ -110,16 +102,29 @@
#define MAX_BLOCKS 4 #define MAX_BLOCKS 4
#define MAX_SECTORS 16 #define MAX_SECTORS 16
#define MCK 48000000
//#define FLASH_BAUD 24000000
#define FLASH_MINFAST 24000000 //33000000
#define FLASH_BAUD MCK/2
#define FLASH_FASTBAUD MCK
#define FLASH_MINBAUD FLASH_FASTBAUD
#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST)
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//
extern void Dbprintf(const char *fmt, ...); void Dbprintf(const char *fmt, ...);
void FlashSetup(void); void FlashmemSetSpiBaudrate(uint32_t baudrate);
bool FlashInit();
void FlashSetup(uint32_t baudrate);
void FlashStop(void); void FlashStop(void);
bool Flash_WaitIdle(void); bool Flash_WaitIdle(void);
uint8_t Flash_ReadStat1(void); uint8_t Flash_ReadStat1(void);
uint8_t Flash_ReadStat2(void); uint8_t Flash_ReadStat2(void);
uint16_t FlashSendByte(uint32_t data); uint16_t FlashSendByte(uint32_t data);
void Flash_TransferAdresse(uint32_t address);
bool Flash_CheckBusy(uint32_t timeout);
void Flash_WriteEnable(); void Flash_WriteEnable();
bool Flash_WipeMemoryPage(uint8_t page); bool Flash_WipeMemoryPage(uint8_t page);
@ -128,12 +133,14 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector);
//bool Flash_Erase32k(uint32_t address); //bool Flash_Erase32k(uint32_t address);
bool Flash_Erase64k(uint8_t block); bool Flash_Erase64k(uint8_t block);
bool FlashInit();
void Flash_UniqueID(uint8_t *uid); void Flash_UniqueID(uint8_t *uid);
uint8_t Flash_ReadID(void); uint8_t Flash_ReadID(void);
uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len);
uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len);
uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len);
uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len);
void Flashmem_print_status(void); void Flashmem_print_status(void);
void Flashmem_print_info(void);
#endif #endif

View file

@ -118,7 +118,7 @@ void SetupSpi(int mode) {
// Set up the synchronous serial port, with the one set of options that we // Set up the synchronous serial port, with the one set of options that we
// always use when we are talking to the FPGA. Both RX and TX are enabled. // always use when we are talking to the FPGA. Both RX and TX are enabled.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void FpgaSetupSscExt(uint8_t clearPCER) { void FpgaSetupSsc(void) {
// First configure the GPIOs, and get ourselves a clock. // First configure the GPIOs, and get ourselves a clock.
AT91C_BASE_PIOA->PIO_ASR = AT91C_BASE_PIOA->PIO_ASR =
GPIO_SSC_FRAME | GPIO_SSC_FRAME |
@ -127,10 +127,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) {
GPIO_SSC_CLK; GPIO_SSC_CLK;
AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT;
if ( clearPCER )
AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC);
else
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_SSC);
// Now set up the SSC proper, starting from a known state. // Now set up the SSC proper, starting from a known state.
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST;
@ -152,9 +149,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) {
AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN;
} }
void FpgaSetupSsc(void) {
FpgaSetupSscExt(true);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Set up DMA to receive samples from the FPGA. We will use the PDC, with // Set up DMA to receive samples from the FPGA. We will use the PDC, with
// a single buffer as a circular buffer (so that we just chain back to // a single buffer as a circular buffer (so that we just chain back to
@ -214,7 +209,8 @@ static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) {
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
static void fpga_inflate_free(voidpf opaque, voidpf address) { static void fpga_inflate_free(voidpf opaque, voidpf address) {
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
} }
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -233,7 +229,9 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
compressed_fpga_stream->zalloc = &fpga_inflate_malloc; compressed_fpga_stream->zalloc = &fpga_inflate_malloc;
compressed_fpga_stream->zfree = &fpga_inflate_free; compressed_fpga_stream->zfree = &fpga_inflate_free;
inflateInit2(compressed_fpga_stream, 0); int res = inflateInit2(compressed_fpga_stream, 0);
if (res < 0)
return false;
fpga_image_ptr = output_buffer; fpga_image_ptr = output_buffer;
@ -247,7 +245,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s
return false; return false;
} }
static void DownloadFPGA_byte(unsigned char w) { static void DownloadFPGA_byte(uint8_t w) {
#define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); } #define SEND_BIT(x) { if(w & (1<<x) ) HIGH(GPIO_FPGA_DIN); else LOW(GPIO_FPGA_DIN); HIGH(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK); }
SEND_BIT(7); SEND_BIT(7);
SEND_BIT(6); SEND_BIT(6);
@ -400,10 +398,11 @@ void FpgaDownloadAndGo(int bitstream_version) {
z_stream compressed_fpga_stream; z_stream compressed_fpga_stream;
uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00};
bool verbose = (MF_DBGLEVEL > 3); bool verbose = (DBGLEVEL > 3);
// make sure that we have enough memory to decompress // make sure that we have enough memory to decompress
BigBuf_free(); BigBuf_Clear_ext(verbose); BigBuf_free();
BigBuf_Clear_ext(verbose);
if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer))
return; return;
@ -420,7 +419,8 @@ void FpgaDownloadAndGo(int bitstream_version) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
// free eventually allocated BigBuf memory // free eventually allocated BigBuf memory
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -449,6 +449,9 @@ void FpgaWriteConfWord(uint8_t v) {
// the samples from the ADC always flow through the FPGA. // the samples from the ADC always flow through the FPGA.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void SetAdcMuxFor(uint32_t whichGpio) { void SetAdcMuxFor(uint32_t whichGpio) {
#ifndef WITH_FPC_USART
// When compiled without FPC USART support
AT91C_BASE_PIOA->PIO_OER = AT91C_BASE_PIOA->PIO_OER =
GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_HIPKD |
GPIO_MUXSEL_LOPKD | GPIO_MUXSEL_LOPKD |
@ -463,16 +466,24 @@ void SetAdcMuxFor(uint32_t whichGpio) {
LOW(GPIO_MUXSEL_HIPKD); LOW(GPIO_MUXSEL_HIPKD);
LOW(GPIO_MUXSEL_LOPKD); LOW(GPIO_MUXSEL_LOPKD);
#ifndef WITH_FPC
LOW(GPIO_MUXSEL_HIRAW); LOW(GPIO_MUXSEL_HIRAW);
LOW(GPIO_MUXSEL_LORAW); LOW(GPIO_MUXSEL_LORAW);
HIGH(whichGpio);
#else
if ((whichGpio == GPIO_MUXSEL_LORAW) || (whichGpio == GPIO_MUXSEL_HIRAW))
return;
// FPC USART uses HIRAW/LOWRAW pins, so they are excluded here.
AT91C_BASE_PIOA->PIO_OER = GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_LOPKD;
AT91C_BASE_PIOA->PIO_PER = GPIO_MUXSEL_HIPKD | GPIO_MUXSEL_LOPKD;
LOW(GPIO_MUXSEL_HIPKD);
LOW(GPIO_MUXSEL_LOPKD);
HIGH(whichGpio);
#endif #endif
HIGH(whichGpio);
} }
void Fpga_print_status(void) { void Fpga_print_status(void) {
Dbprintf("Currently loaded FPGA image"); DbpString(_BLUE_("Currently loaded FPGA image"));
Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream - 1]); Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream - 1]);
} }
@ -485,7 +496,7 @@ int FpgaGetCurrent(void) {
// if HF, Disable SSC DMA // if HF, Disable SSC DMA
// turn off trace and leds off. // turn off trace and leds off.
void switch_off(void) { void switch_off(void) {
if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); if (DBGLEVEL > 3) Dbprintf("switch_off");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
if (downloaded_bitstream == FPGA_BITSTREAM_HF) if (downloaded_bitstream == FPGA_BITSTREAM_HF)
FpgaDisableSscDma(); FpgaDisableSscDma();

View file

@ -27,7 +27,6 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v);
void FpgaWriteConfWord(uint8_t v); void FpgaWriteConfWord(uint8_t v);
void FpgaDownloadAndGo(int bitstream_version); void FpgaDownloadAndGo(int bitstream_version);
// void FpgaGatherVersion(int bitstream_version, char *dst, int len); // void FpgaGatherVersion(int bitstream_version, char *dst, int len);
void FpgaSetupSscExt(uint8_t clearPCER);
void FpgaSetupSsc(void); void FpgaSetupSsc(void);
void SetupSpi(int mode); void SetupSpi(int mode);
bool FpgaSetupSscDma(uint8_t *buf, int len); bool FpgaSetupSscDma(uint8_t *buf, int len);
@ -38,7 +37,7 @@ int FpgaGetCurrent(void);
void SetAdcMuxFor(uint32_t whichGpio); void SetAdcMuxFor(uint32_t whichGpio);
// extern and generel turn off the antenna method // extern and generel turn off the antenna method
extern void switch_off(void); void switch_off(void);
// definitions for multiple FPGA config files support // definitions for multiple FPGA config files support
#define FPGA_BITSTREAM_LF 1 #define FPGA_BITSTREAM_LF 1
@ -62,7 +61,9 @@ extern void switch_off(void);
#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) #define FPGA_MAJOR_MODE_HF_SNOOP (4<<5)
#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) #define FPGA_MAJOR_MODE_HF_FELICA (5<<5)
// BOTH // BOTH
#define FPGA_MAJOR_MODE_OFF_LF (6<<5)
#define FPGA_MAJOR_MODE_OFF (7<<5) #define FPGA_MAJOR_MODE_OFF (7<<5)
// Options for LF_ADC // Options for LF_ADC
#define FPGA_LF_ADC_READER_FIELD (1<<0) #define FPGA_LF_ADC_READER_FIELD (1<<0)
// Options for LF_EDGE_DETECT // Options for LF_EDGE_DETECT
@ -76,10 +77,10 @@ extern void switch_off(void);
#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) #define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1)
#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) #define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2)
// Options for the HF simulated tag, how to modulate // Options for the HF simulated tag, how to modulate
#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) // 0000 #define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000
#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) // 0001 #define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001
#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) // 0010 #define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010
#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) // 0100 #define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100
#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 #define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101
// no 848K // no 848K

View file

@ -4,10 +4,9 @@
#include "util.h" #include "util.h"
#include "usb_cdc.h" // for usb_poll_validate_length #include "usb_cdc.h" // for usb_poll_validate_length
static void RAMFUNC optimizedSnoop(void); static void RAMFUNC optimizedSniff(void);
static void RAMFUNC optimizedSnoop(void) static void RAMFUNC optimizedSniff(void) {
{
int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory
uint16_t *dest = (uint16_t *)BigBuf_get_addr(); uint16_t *dest = (uint16_t *)BigBuf_get_addr();
@ -20,13 +19,13 @@ static void RAMFUNC optimizedSnoop(void)
dest++; dest++;
} }
} }
//setting tracelen - importsnt! it was set by buffer overflow before //setting tracelen - important! it was set by buffer overflow before
set_tracelen(BigBuf_max_traceLen()); set_tracelen(BigBuf_max_traceLen());
} }
void HfSnoop(int samplesToSkip, int triggersToSkip) void HfSniff(int samplesToSkip, int triggersToSkip) {
{ BigBuf_free();
BigBuf_free(); BigBuf_Clear(); BigBuf_Clear();
Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip);
int trigger_cnt = 0; int trigger_cnt = 0;
@ -47,7 +46,7 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
SpinDelay(100); SpinDelay(100);
uint16_t r = 0; uint16_t r = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!BUTTON_PRESS() && !data_available()) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -67,14 +66,14 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY))
waitcount--; waitcount--;
} }
optimizedSnoop(); optimizedSniff();
Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r);
} }
//Resetting Frame mode (First set in fpgaloader.c) //Resetting Frame mode (First set in fpgaloader.c)
AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0);
DbpString("HF Snoop end"); DbpString("HF Sniffing end");
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
LED_D_OFF(); LED_D_OFF();
} }

File diff suppressed because it is too large Load diff

View file

@ -1,19 +1,23 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// (c) 2012 Roel Verdult
//
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // 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 // at your option, any later version. See the LICENSE.txt file for the text of
// the license. // the license.
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// ISO14443 CRC calculation code. // Hitag2 type prototyping
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#ifndef __ISO14443CRC_H #ifndef _HITAG2_H_
#define __ISO14443CRC_H #define _HITAG2_H_
#include "common.h"
//----------------------------------------------------------------------------- #include <stdint.h>
// Routines to compute the CRCs (two different flavours, just for confusion) #include <stdbool.h>
// required for ISO 14443, swiped directly from the spec. #include "hitag.h"
uint16_t UpdateCrc14443(uint8_t b, uint16_t *crc); void SniffHitag(void);
void SimulateHitagTag(bool tag_mem_supplied, uint8_t *data);
void ReaderHitag(hitag_function htf, hitag_data *htd);
void WriterHitag(hitag_function htf, hitag_data *htd, int page);
#endif #endif

116
armsrc/hitag2_crypto.c Normal file
View file

@ -0,0 +1,116 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// Hitag2 Crypto
//
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// (c) 2012 Roel Verdult
// (c) 2019 Iceman
//-----------------------------------------------------------------------------
#include "hitag2_crypto.h"
/* Following is a modified version of cryptolib.com/ciphers/hitag2/ */
// Software optimized 48-bit Philips/NXP Mifare Hitag2 PCF7936/46/47/52 stream cipher algorithm by I.C. Wiener 2006-2007.
// For educational purposes only.
// No warranties or guarantees of any kind.
// This code is released into the public domain by its author.
// Single bit Hitag2 functions:
#ifndef i4
#define i4(x,a,b,c,d) ((uint32_t)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8))
#endif
static const uint32_t ht2_f4a = 0x2C79; // 0010 1100 0111 1001
static const uint32_t ht2_f4b = 0x6671; // 0110 0110 0111 0001
static const uint32_t ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011
uint32_t _f20(const uint64_t x) {
uint32_t i5;
i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1
+ ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2
+ ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4
+ ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8
+ ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16;
return (ht2_f5c >> i5) & 1;
}
uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV) {
uint32_t i;
uint64_t x = ((key & 0xFFFF) << 32) + serial;
for (i = 0; i < 32; i++) {
x >>= 1;
x += (uint64_t)(_f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47;
}
return x;
}
uint64_t _hitag2_round(uint64_t *state) {
uint64_t x = *state;
x = (x >> 1) +
((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6)
^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22)
^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41)
^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47);
*state = x;
return _f20(x);
}
// "MIKRON" = O N M I K R
// Key = 4F 4E 4D 49 4B 52 - Secret 48-bit key
// Serial = 49 43 57 69 - Serial number of the tag, transmitted in clear
// Random = 65 6E 45 72 - Random IV, transmitted in clear
//~28~DC~80~31 = D7 23 7F CE - Authenticator value = inverted first 4 bytes of the keystream
// The code below must print out "D7 23 7F CE 8C D0 37 A9 57 49 C1 E6 48 00 8A B6".
// The inverse of the first 4 bytes is sent to the tag to authenticate.
// The rest is encrypted by XORing it with the subsequent keystream.
uint32_t _hitag2_byte(uint64_t *x) {
uint32_t i, c;
for (i = 0, c = 0; i < 8; i++) {
c += (uint32_t) _hitag2_round(x) << (i ^ 7);
}
return c;
}
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) {
uint64_t key = ((uint64_t)tag->sectors[2][2]) |
((uint64_t)tag->sectors[2][3] << 8) |
((uint64_t)tag->sectors[1][0] << 16) |
((uint64_t)tag->sectors[1][1] << 24) |
((uint64_t)tag->sectors[1][2] << 32) |
((uint64_t)tag->sectors[1][3] << 40);
uint32_t uid = ((uint32_t)tag->sectors[0][0]) |
((uint32_t)tag->sectors[0][1] << 8) |
((uint32_t)tag->sectors[0][2] << 16) |
((uint32_t)tag->sectors[0][3] << 24);
uint32_t iv_ = (((uint32_t)(iv[0]))) |
(((uint32_t)(iv[1])) << 8) |
(((uint32_t)(iv[2])) << 16) |
(((uint32_t)(iv[3])) << 24);
tag->cs = _hitag2_init(REV64(key), REV32(uid), REV32(iv_));
}
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is) {
uint8_t authenticator_should[4];
authenticator_should[0] = ~_hitag2_byte(cs);
authenticator_should[1] = ~_hitag2_byte(cs);
authenticator_should[2] = ~_hitag2_byte(cs);
authenticator_should[3] = ~_hitag2_byte(cs);
return (memcmp(authenticator_should, authenticator_is, 4) == 0);
}
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) {
int i;
for (i = 0; i < bytes; i++) data[i] ^= _hitag2_byte(cs);
for (i = 0; i < bits; i++) data[bytes] ^= _hitag2_round(cs) << (7 - i);
return 0;
}

36
armsrc/hitag2_crypto.h Normal file
View file

@ -0,0 +1,36 @@
#ifndef __HITAG2_CRYPTO_H
#define __HITAG2_CRYPTO_H
#ifdef __cplusplus
extern "C" {
#endif
#include "string.h"
#include "util.h"
struct hitag2_tag {
uint32_t uid;
enum {
TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password
TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
} state;
uint16_t active_sector;
uint8_t crypto_active;
uint64_t cs;
uint8_t sectors[12][4];
};
uint32_t _f20(const uint64_t x);
uint64_t _hitag2_init(const uint64_t key, const uint32_t serial, const uint32_t IV);
uint64_t _hitag2_round(uint64_t *state);
uint32_t _hitag2_byte(uint64_t *x);
void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv);
int hitag2_cipher_authenticate(uint64_t *cs, const uint8_t *authenticator_is);
int hitag2_cipher_transcrypt(uint64_t *cs, uint8_t *data, uint16_t bytes, uint16_t bits) ;
#ifdef __cplusplus
}
#endif
#endif

File diff suppressed because it is too large Load diff

31
armsrc/hitagS.h Normal file
View file

@ -0,0 +1,31 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// HitagS emulation (preliminary test version)
//
// (c) 2016 Oguzhan Cicek, Hendrik Schwartke, Ralf Spenneberg
// <info@os-s.de>
//-----------------------------------------------------------------------------
#ifndef _HITAGS_H_
#define _HITAGS_H_
#include <stdint.h>
#include <stdbool.h>
#include <stdlib.h>
#include "hitag2_crypto.h"
#include "hitag.h"
#include "proxmark3.h"
#include "apps.h"
#include "util.h"
#include "string.h"
#include "BigBuf.h"
void SimulateHitagSTag(bool tag_mem_supplied, uint8_t *data);
void ReadHitagS(hitag_function htf, hitag_data *htd);
void WritePageHitagS(hitag_function htf, hitag_data *htd, int page);
void check_challenges(bool file_given, uint8_t *data);
#endif

View file

@ -18,7 +18,7 @@
// //
// FIX: // FIX:
// ==== // ====
// We still have sometimes a demodulation error when snooping iClass communication. // We still have sometimes a demodulation error when sniffing iClass communication.
// The resulting trace of a read-block-03 command may look something like this: // The resulting trace of a read-block-03 command may look something like this:
// //
// + 22279: : 0c 03 e8 01 // + 22279: : 0c 03 e8 01
@ -153,7 +153,6 @@ static void uart_init(uint8_t *data){
static void uart_bit(uint8_t bit) { static void uart_bit(uint8_t bit) {
static uint8_t buf = 0xff; static uint8_t buf = 0xff;
static uint8_t n_buf; static uint8_t n_buf;
static uint8_t msg_byte;
static int nmsg_byte; static int nmsg_byte;
buf <<= 1; buf <<= 1;
buf |= bit ? 1 : 0; buf |= bit ? 1 : 0;
@ -166,6 +165,7 @@ static void uart_bit(uint8_t bit) {
nmsg_byte = 0; nmsg_byte = 0;
} }
} else { } else {
static uint8_t msg_byte;
n_buf++; n_buf++;
if (n_buf == 8) { if (n_buf == 8) {
msg_byte >>= 2; msg_byte >>= 2;
@ -629,10 +629,18 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) {
if (Demod.posCount) { if (Demod.posCount) {
switch (Demod.syncBit) { switch (Demod.syncBit) {
case 0x08: Demod.samples = 3; break; case 0x08:
case 0x04: Demod.samples = 2; break; Demod.samples = 3;
case 0x02: Demod.samples = 1; break; break;
case 0x01: Demod.samples = 0; break; case 0x04:
Demod.samples = 2;
break;
case 0x02:
Demod.samples = 1;
break;
case 0x01:
Demod.samples = 0;
break;
} }
// SOF must be long burst... otherwise stay unsynced!!! // SOF must be long burst... otherwise stay unsynced!!!
if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit))
@ -647,7 +655,6 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) {
return false; return false;
} }
} }
error = 0;
} }
return false; return false;
} }
@ -791,7 +798,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) {
// Both sides of communication! // Both sides of communication!
//============================================================================= //=============================================================================
static void iclass_setup_sniff(void) { static void iclass_setup_sniff(void) {
if (MF_DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter"); if (DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter");
LEDsoff(); LEDsoff();
@ -805,7 +812,8 @@ static void iclass_setup_sniff(void){
// Set up the synchronous serial port // Set up the synchronous serial port
FpgaSetupSsc(); FpgaSetupSsc();
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -815,7 +823,7 @@ static void iclass_setup_sniff(void){
uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE)); uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE));
//UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); //UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE));
if (MF_DBGLEVEL > 1) { if (DBGLEVEL > 1) {
// Print debug information about the buffer sizes // Print debug information about the buffer sizes
Dbprintf("[+] Sniffing buffers initialized:"); Dbprintf("[+] Sniffing buffers initialized:");
Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen());
@ -833,7 +841,7 @@ static void iclass_setup_sniff(void){
StartCountSspClk(); StartCountSspClk();
LED_A_ON(); LED_A_ON();
if (MF_DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit"); if (DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit");
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -846,7 +854,7 @@ void RAMFUNC SniffIClass(void) {
//int datalen = 0; //int datalen = 0;
uint32_t previous_data = 0; uint32_t previous_data = 0;
uint32_t time_0 = 0, time_start = 0, time_stop = 0; uint32_t time_0 = 0, time_start = 0, time_stop;
uint32_t sniffCounter = 0; uint32_t sniffCounter = 0;
bool TagIsActive = false; bool TagIsActive = false;
bool ReaderIsActive = false; bool ReaderIsActive = false;
@ -861,14 +869,14 @@ void RAMFUNC SniffIClass(void) {
// Setup and start DMA. // Setup and start DMA.
if (!FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE)) { if (!FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); if (DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting");
return; return;
} }
// time ZERO, the point from which it all is calculated. // time ZERO, the point from which it all is calculated.
time_0 = GetCountSspClk(); time_0 = GetCountSspClk();
int div = 0; int divi = 0;
uint8_t tag_byte = 0, foo = 0; uint8_t tag_byte = 0, foo = 0;
// loop and listen // loop and listen
// every sample (1byte in data), // every sample (1byte in data),
@ -894,10 +902,10 @@ void RAMFUNC SniffIClass(void) {
if (*data & 0xF) { if (*data & 0xF) {
//tag_byte <<= 1; //tag_byte <<= 1;
tag_byte ^= (1 << 4); tag_byte ^= (1 << 4);
foo ^= (1 << (3 - div)); foo ^= (1 << (3 - divi));
Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo); Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo);
} }
div++; divi++;
// every odd sample // every odd sample
if (sniffCounter & 0x01) { if (sniffCounter & 0x01) {
@ -952,11 +960,11 @@ void RAMFUNC SniffIClass(void) {
} }
tag_byte = 0; tag_byte = 0;
foo = 0; foo = 0;
div = 0; divi = 0;
} }
} // end main loop } // end main loop
if (MF_DBGLEVEL >= 1) { if (DBGLEVEL >= 1) {
DbpString("[+] Sniff statistics:"); DbpString("[+] Sniff statistics:");
Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false);
} }
@ -986,6 +994,7 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen)
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN);
// clear RXRDY: // clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
@ -1020,22 +1029,38 @@ static uint8_t encode4Bits(const uint8_t b) {
uint8_t c = b & 0xF; uint8_t c = b & 0xF;
switch (c) { switch (c) {
// 1 2 3 4 // 1 2 3 4
case 15: return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55 case 15:
case 14: return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95 return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55
case 13: return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65 case 14:
case 12: return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5 return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95
case 11: return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59 case 13:
case 10: return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99 return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65
case 9: return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69 case 12:
case 8: return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9 return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5
case 7: return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56 case 11:
case 6: return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96 return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59
case 5: return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66 case 10:
case 4: return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6 return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99
case 3: return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a case 9:
case 2: return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69
case 1: return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a case 8:
default: return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9
case 7:
return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56
case 6:
return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96
case 5:
return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66
case 4:
return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6
case 3:
return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a
case 2:
return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a
case 1:
return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a
default:
return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa
} }
} }
@ -1046,7 +1071,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) {
/* /*
* SOF comprises 3 parts; * SOF comprises 3 parts;
* * An unmodulated time of 56.64 us * * An unmodulated time of 56.64 us
* * 24 pulses of 423.75 KHz (fc/32) * * 24 pulses of 423.75 kHz (fc/32)
* * A logic 1, which starts with an unmodulated time of 18.88us * * A logic 1, which starts with an unmodulated time of 18.88us
* followed by 8 pulses of 423.75kHz (fc/32) * followed by 8 pulses of 423.75kHz (fc/32)
* *
@ -1124,7 +1149,7 @@ static void CodeIClassTagSOF() {
// turn off afterwards // turn off afterwards
void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) {
if (MF_DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter"); if (DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter");
LEDsoff(); LEDsoff();
@ -1143,7 +1168,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
//Use the emulator memory for SIM //Use the emulator memory for SIM
uint8_t *emulator = BigBuf_get_EM_addr(); uint8_t *emulator = BigBuf_get_EM_addr();
uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 }; uint8_t mac_responses[PM3_CMD_DATA_SIZE] = { 0 };
if (simType == 0) { if (simType == 0) {
// Use the CSN from commandline // Use the CSN from commandline
@ -1163,18 +1188,18 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
// in order to obtain the keys, as in the "dismantling iclass"-paper. // in order to obtain the keys, as in the "dismantling iclass"-paper.
#define EPURSE_MAC_SIZE 16 #define EPURSE_MAC_SIZE 16
int i = 0; int i = 0;
for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
// The usb data is 512 bytes, fitting 65 8-byte CSNs in there. // The usb data is 512 bytes, fitting 65 8-byte CSNs in there.
memcpy(emulator, datain + (i * 8), 8); memcpy(emulator, datain + (i * 8), 8);
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
// Button pressed // Button pressed
cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
goto out; goto out;
} }
} }
cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE);
} else if (simType == 3) { } else if (simType == 3) {
//This is 'full sim' mode, where we use the emulator storage for data. //This is 'full sim' mode, where we use the emulator storage for data.
@ -1195,26 +1220,26 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain
// attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys. // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys.
int i = 0; int i = 0;
// The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS
for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < PM3_CMD_DATA_SIZE; i++) {
memcpy(emulator, datain + (i * 8), 8); memcpy(emulator, datain + (i * 8), 8);
// keyroll 1 // keyroll 1
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) { if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE)) {
cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
// Button pressed // Button pressed
goto out; goto out;
} }
// keyroll 2 // keyroll 2
if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) { if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE)) {
cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE* 2); reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
// Button pressed // Button pressed
goto out; goto out;
} }
} }
// double the amount of collected data. // double the amount of collected data.
cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2 ); reply_old(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i * 2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2);
} else { } else {
// We may want a mode here where we hardcode the csns to use (from proxclone). // We may want a mode here where we hardcode the csns to use (from proxclone).
@ -1327,27 +1352,33 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
// First card answer: SOF // First card answer: SOF
CodeIClassTagSOF(); CodeIClassTagSOF();
memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; memcpy(resp_sof, ToSend, ToSendMax);
resp_sof_Len = ToSendMax;
// Anticollision CSN // Anticollision CSN
CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data));
memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; memcpy(resp_anticoll, ToSend, ToSendMax);
resp_anticoll_len = ToSendMax;
// CSN // CSN
CodeIClassTagAnswer(csn_data, sizeof(csn_data)); CodeIClassTagAnswer(csn_data, sizeof(csn_data));
memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; memcpy(resp_csn, ToSend, ToSendMax);
resp_csn_len = ToSendMax;
// Configuration // Configuration
CodeIClassTagAnswer(conf_data, sizeof(conf_data)); CodeIClassTagAnswer(conf_data, sizeof(conf_data));
memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; memcpy(resp_conf, ToSend, ToSendMax);
resp_conf_len = ToSendMax;
// e-Purse // e-Purse
CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data));
memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; memcpy(resp_cc, ToSend, ToSendMax);
resp_cc_len = ToSendMax;
// Application Issuer Area // Application Issuer Area
CodeIClassTagAnswer(aia_data, sizeof(aia_data)); CodeIClassTagAnswer(aia_data, sizeof(aia_data));
memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; memcpy(resp_aia, ToSend, ToSendMax);
resp_aia_len = ToSendMax;
//This is used for responding to READ-block commands or other data which is dynamically generated //This is used for responding to READ-block commands or other data which is dynamically generated
//First the 'trace'-data, not encoded for FPGA //First the 'trace'-data, not encoded for FPGA
@ -1364,7 +1395,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
// To control where we are in the protocol // To control where we are in the protocol
uint32_t time_0 = GetCountSspClk(); uint32_t time_0 = GetCountSspClk();
uint32_t t2r_stime = 0, t2r_etime = 0; uint32_t t2r_stime = 0, t2r_etime = 0;
uint32_t r2t_stime = 0, r2t_etime = 0; uint32_t r2t_stime, r2t_etime = 0;
LED_A_ON(); LED_A_ON();
bool buttonPressed = false; bool buttonPressed = false;
@ -1373,7 +1404,8 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
WDT_HIT(); WDT_HIT();
//Signal tracer, can be used to get a trigger for an oscilloscope.. //Signal tracer, can be used to get a trigger for an oscilloscope..
LED_B_OFF(); LED_C_OFF(); LED_B_OFF();
LED_C_OFF();
r2t_stime = (GetCountSspClk() - time_0) << 4; r2t_stime = (GetCountSspClk() - time_0) << 4;
if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) { if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) {
@ -1389,7 +1421,8 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
if (receivedCmd[0] == ICLASS_CMD_ACTALL) { // 0x0A if (receivedCmd[0] == ICLASS_CMD_ACTALL) { // 0x0A
// Reader in anticollission phase // Reader in anticollission phase
modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1; modulated_response = resp_sof;
modulated_response_size = resp_sof_Len; //order = 1;
trace_data = sof_data; trace_data = sof_data;
trace_data_size = sizeof(sof_data); trace_data_size = sizeof(sof_data);
// adjusted for 330 + (160*num of slot) // adjusted for 330 + (160*num of slot)
@ -1397,7 +1430,8 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
} else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C } else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C
if (len == 1) { if (len == 1) {
// Reader asks for anticollission CSN // Reader asks for anticollission CSN
modulated_response = resp_anticoll; modulated_response_size = resp_anticoll_len; //order = 2; modulated_response = resp_anticoll;
modulated_response_size = resp_anticoll_len; //order = 2;
trace_data = anticoll_data; trace_data = anticoll_data;
trace_data_size = sizeof(anticoll_data); trace_data_size = sizeof(anticoll_data);
goto send; goto send;
@ -1406,17 +1440,20 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
// block0,1,2,5 is always readable. // block0,1,2,5 is always readable.
switch (receivedCmd[1]) { switch (receivedCmd[1]) {
case 0: // csn (0c 00) case 0: // csn (0c 00)
modulated_response = resp_csn; modulated_response_size = resp_csn_len; modulated_response = resp_csn;
modulated_response_size = resp_csn_len;
trace_data = csn_data; trace_data = csn_data;
trace_data_size = sizeof(csn_data); trace_data_size = sizeof(csn_data);
break; break;
case 1: // configuration (0c 01) case 1: // configuration (0c 01)
modulated_response = resp_conf; modulated_response_size = resp_conf_len; modulated_response = resp_conf;
modulated_response_size = resp_conf_len;
trace_data = conf_data; trace_data = conf_data;
trace_data_size = sizeof(conf_data); trace_data_size = sizeof(conf_data);
break; break;
case 2: // e-purse (0c 02) case 2: // e-purse (0c 02)
modulated_response = resp_cc; modulated_response_size = resp_cc_len; modulated_response = resp_cc;
modulated_response_size = resp_cc_len;
trace_data = card_challenge_data; trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data); trace_data_size = sizeof(card_challenge_data);
// set epurse of sim2,4 attack // set epurse of sim2,4 attack
@ -1425,11 +1462,13 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
} }
break; break;
case 5:// Application Issuer Area (0c 05) case 5:// Application Issuer Area (0c 05)
modulated_response = resp_aia; modulated_response_size = resp_aia_len; modulated_response = resp_aia;
modulated_response_size = resp_aia_len;
trace_data = aia_data; trace_data = aia_data;
trace_data_size = sizeof(aia_data); trace_data_size = sizeof(aia_data);
break; break;
default: break; default:
break;
} }
goto send; goto send;
} }
@ -1437,20 +1476,23 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
} else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81
// Reader selects anticollission CSN. // Reader selects anticollission CSN.
// Tag sends the corresponding real CSN // Tag sends the corresponding real CSN
modulated_response = resp_csn; modulated_response_size = resp_csn_len; //order = 3; modulated_response = resp_csn;
modulated_response_size = resp_csn_len; //order = 3;
trace_data = csn_data; trace_data = csn_data;
trace_data_size = sizeof(csn_data); trace_data_size = sizeof(csn_data);
goto send; goto send;
} else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88 } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88
// Read e-purse (88 02) // Read e-purse (88 02)
modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; modulated_response = resp_cc;
modulated_response_size = resp_cc_len; //order = 4;
trace_data = card_challenge_data; trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data); trace_data_size = sizeof(card_challenge_data);
LED_B_ON(); LED_B_ON();
goto send; goto send;
} else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18 } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18
// Read e-purse (18 02) // Read e-purse (18 02)
modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; modulated_response = resp_cc;
modulated_response_size = resp_cc_len; //order = 4;
trace_data = card_challenge_data; trace_data = card_challenge_data;
trace_data_size = sizeof(card_challenge_data); trace_data_size = sizeof(card_challenge_data);
LED_B_ON(); LED_B_ON();
@ -1470,13 +1512,14 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
} else { } else {
// Not fullsim, we don't respond // Not fullsim, we don't respond
// We do not know what to answer, so lets keep quiet // We do not know what to answer, so lets keep quiet
modulated_response = resp_sof; modulated_response_size = 0; modulated_response = resp_sof;
modulated_response_size = 0;
trace_data = NULL; trace_data = NULL;
trace_data_size = 0; trace_data_size = 0;
if (simulationMode == MODE_EXIT_AFTER_MAC) { if (simulationMode == MODE_EXIT_AFTER_MAC) {
if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { if (DBGLEVEL == DBG_EXTENDED) {
Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]); Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]);
Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len, Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len,
receivedCmd[0], receivedCmd[1], receivedCmd[2], receivedCmd[0], receivedCmd[1], receivedCmd[2],
@ -1494,7 +1537,8 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
goto send; goto send;
} else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) { } else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) {
// Reader ends the session // Reader ends the session
modulated_response = resp_sof; modulated_response_size = 0; //order = 0; modulated_response = resp_sof;
modulated_response_size = 0; //order = 0;
trace_data = NULL; trace_data = NULL;
trace_data_size = 0; trace_data_size = 0;
goto send; goto send;
@ -1540,7 +1584,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) {
} else { } else {
//#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44
// Never seen this command before // Never seen this command before
if ( MF_DBGLEVEL == MF_DBG_EXTENDED) if (DBGLEVEL == DBG_EXTENDED)
print_result("[-] Unhandled command received ", receivedCmd, len); print_result("[-] Unhandled command received ", receivedCmd, len);
// Do not respond // Do not respond
@ -1582,7 +1626,7 @@ send:
*/ */
static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
int i = 0; int i = 0;
volatile uint8_t b = 0; volatile uint8_t b;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT);
@ -1592,7 +1636,8 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) {
// Prevent rx holding register from overflowing // Prevent rx holding register from overflowing
if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) { if ((AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {
b = AT91C_BASE_SSC->SSC_RHR; (void) b; b = AT91C_BASE_SSC->SSC_RHR;
(void) b;
} }
// Put byte into tx holding register as soon as it is ready // Put byte into tx holding register as soon as it is ready
@ -1657,7 +1702,8 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
// Prevent rx holding register from overflowing // Prevent rx holding register from overflowing
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = AT91C_BASE_SSC->SSC_RHR; (void)b; b = AT91C_BASE_SSC->SSC_RHR;
(void)b;
} }
} }
@ -1674,7 +1720,6 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void CodeIClassCommand(const uint8_t *cmd, int len) { void CodeIClassCommand(const uint8_t *cmd, int len) {
int i, j, k; int i, j, k;
uint8_t b;
ToSendReset(); ToSendReset();
@ -1686,7 +1731,7 @@ void CodeIClassCommand(const uint8_t* cmd, int len) {
// Modulate the bytes // Modulate the bytes
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
b = cmd[i]; uint8_t b = cmd[i];
for (j = 0; j < 4; j++) { for (j = 0; j < 4; j++) {
for (k = 0; k < 4; k++) { for (k = 0; k < 4; k++) {
@ -1753,6 +1798,7 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples,
// clear RXRDY: // clear RXRDY:
uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
(void)b;
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
@ -1815,7 +1861,6 @@ void setupIclassReader() {
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// Reset trace buffer
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -1824,21 +1869,19 @@ void setupIclassReader() {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD);
SpinDelay(300); SpinDelay(300);
// Start the timer
StartCountSspClk(); StartCountSspClk();
LED_A_ON(); LED_A_ON();
} }
bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, uint8_t retries) { bool sendCmdGetResponseWithRetries(uint8_t *command, size_t cmdsize, uint8_t *resp, uint8_t expected_size, uint8_t retries) {
uint8_t got_n = 0;
while (retries-- > 0) { while (retries-- > 0) {
ReaderTransmitIClass(command, cmdsize); ReaderTransmitIClass(command, cmdsize);
//iceman - if received size is bigger than expected, we smash the stack here //iceman - if received size is bigger than expected, we smash the stack here
// since its called with fixed sized arrays // since its called with fixed sized arrays
got_n = ReaderReceiveIClass(resp); uint8_t got_n = ReaderReceiveIClass(resp);
// 0xBB is the internal debug separator byte.. // 0xBB is the internal debug separator byte..
if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { if (expected_size != got_n || (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) {
@ -1939,9 +1982,7 @@ void ReaderIClass(uint8_t arg0) {
//Read App Issuer Area block CRC(0x05) => 0xde 0x64 //Read App Issuer Area block CRC(0x05) => 0xde 0x64
uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64};
int read_status = 0;
uint16_t tryCnt = 0; uint16_t tryCnt = 0;
uint8_t result_status = 0;
bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully
bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag
@ -1952,21 +1993,21 @@ void ReaderIClass(uint8_t arg0) {
setupIclassReader(); setupIclassReader();
bool userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); bool userCancelled = BUTTON_PRESS() || data_available();
while (!userCancelled) { while (!userCancelled) {
WDT_HIT(); WDT_HIT();
// if only looking for one card try 2 times if we missed it the first time // if only looking for one card try 2 times if we missed it the first time
if (try_once && tryCnt > 2) { if (try_once && tryCnt > 2) {
if (MF_DBGLEVEL > 1) DbpString("Failed to find a tag"); if (DBGLEVEL > 1) DbpString("Failed to find a tag");
break; break;
} }
tryCnt++; tryCnt++;
result_status = 0; uint8_t result_status = 0;
read_status = handshakeIclassTag_ext(card_data, use_credit_key); int read_status = handshakeIclassTag_ext(card_data, use_credit_key);
if (read_status == 0) continue; if (read_status == 0) continue;
if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN; if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN;
@ -1983,7 +2024,7 @@ void ReaderIClass(uint8_t arg0) {
result_status |= FLAG_ICLASS_READER_CONF; result_status |= FLAG_ICLASS_READER_CONF;
memcpy(card_data + 8, resp, 8); memcpy(card_data + 8, resp, 8);
} else { } else {
if (MF_DBGLEVEL > 1) DbpString("Failed to dump config block"); if (DBGLEVEL > 1) DbpString("Failed to dump config block");
} }
} }
@ -1993,7 +2034,7 @@ void ReaderIClass(uint8_t arg0) {
result_status |= FLAG_ICLASS_READER_AIA; result_status |= FLAG_ICLASS_READER_AIA;
memcpy(card_data + (8 * 5), resp, 8); memcpy(card_data + (8 * 5), resp, 8);
} else { } else {
if (MF_DBGLEVEL > 1) DbpString("Failed to dump AA block"); if (DBGLEVEL > 1) DbpString("Failed to dump AA block");
} }
} }
@ -2012,7 +2053,7 @@ void ReaderIClass(uint8_t arg0) {
// only useful if looping in arm (not try_once && not abort_after_read) // only useful if looping in arm (not try_once && not abort_after_read)
if (memcmp(last_csn, card_data, 8) != 0) { if (memcmp(last_csn, card_data, 8) != 0) {
// If caller requires that we get Conf, CC, AA, continue until we got it // If caller requires that we get Conf, CC, AA, continue until we got it
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c", Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c",
result_status, result_status,
(result_status & FLAG_ICLASS_READER_CSN) ? 'Y' : 'N', (result_status & FLAG_ICLASS_READER_CSN) ? 'Y' : 'N',
@ -2038,10 +2079,10 @@ void ReaderIClass(uint8_t arg0) {
if (flagReadConfig) if (flagReadConfig)
send |= (result_status & FLAG_ICLASS_READER_CONF); send |= (result_status & FLAG_ICLASS_READER_CONF);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SEND %c", send?'y':'n'); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("SEND %c", send ? 'y' : 'n');
if (send) { if (send) {
cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data) ); reply_old(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data));
if (abort_after_read) { if (abort_after_read) {
LED_B_OFF(); LED_B_OFF();
return; return;
@ -2051,25 +2092,25 @@ void ReaderIClass(uint8_t arg0) {
} }
} }
LED_B_OFF(); LED_B_OFF();
userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); userCancelled = BUTTON_PRESS() || data_available();
} }
if (userCancelled) { if (userCancelled) {
cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0); reply_old(CMD_ACK, 0xFF, 0, 0, card_data, 0);
switch_off(); switch_off();
} else { } else {
cmd_send(CMD_ACK, 0, 0, 0, card_data, 0); reply_old(CMD_ACK, 0, 0, 0, card_data, 0);
} }
} }
// turn off afterwards // turn off afterwards
void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { void ReaderIClass_Replay(uint8_t arg0, uint8_t *mac) {
uint8_t cardsize = 0; uint8_t cardsize = 0;
uint8_t mem = 0; uint8_t mem = 0;
uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 };
uint8_t card_data[USB_CMD_DATA_SIZE] = {0}; uint8_t card_data[PM3_CMD_DATA_SIZE] = {0};
uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; uint8_t resp[ICLASS_BUFFER_SIZE] = {0};
static struct memory_t { static struct memory_t {
@ -2090,7 +2131,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
if (read_status < 2) continue; if (read_status < 2) continue;
//for now replay captured auth (as cc not updated) //for now replay captured auth (as cc not updated)
memcpy(check+5, MAC, 4); memcpy(check + 5, mac, 4);
if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) { if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) {
DbpString("Error: Authentication Fail!"); DbpString("Error: Authentication Fail!");
@ -2117,7 +2158,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
WDT_HIT(); WDT_HIT();
//Set card_data to all zeroes, we'll fill it with data //Set card_data to all zeroes, we'll fill it with data
memset(card_data, 0x0, USB_CMD_DATA_SIZE); memset(card_data, 0x0, PM3_CMD_DATA_SIZE);
uint8_t failedRead = 0; uint8_t failedRead = 0;
uint32_t stored_data_length = 0; uint32_t stored_data_length = 0;
@ -2137,9 +2178,9 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
//Fill up the buffer //Fill up the buffer
memcpy(card_data + stored_data_length, resp, 8); memcpy(card_data + stored_data_length, resp, 8);
stored_data_length += 8; stored_data_length += 8;
if (stored_data_length + 8 > USB_CMD_DATA_SIZE) { if (stored_data_length + 8 > PM3_CMD_DATA_SIZE) {
//Time to send this off and start afresh //Time to send this off and start afresh
cmd_send(CMD_ACK, reply_old(CMD_ACK,
stored_data_length,//data length stored_data_length,//data length
failedRead,//Failed blocks? failedRead,//Failed blocks?
0,//Not used ATM 0,//Not used ATM
@ -2159,7 +2200,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
//Send off any remaining data //Send off any remaining data
if (stored_data_length > 0) { if (stored_data_length > 0) {
cmd_send(CMD_ACK, reply_old(CMD_ACK,
stored_data_length,//data length stored_data_length,//data length
failedRead,//Failed blocks? failedRead,//Failed blocks?
0,//Not used ATM 0,//Not used ATM
@ -2171,7 +2212,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
break; break;
} }
//Signal end of transmission //Signal end of transmission
cmd_send(CMD_ACK, reply_old(CMD_ACK,
0,//data length 0,//data length
0,//Failed blocks? 0,//Failed blocks?
0,//Not used ATM 0,//Not used ATM
@ -2183,12 +2224,12 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) {
// not used. ?!? ( CMD_ICLASS_READCHECK) // not used. ?!? ( CMD_ICLASS_READCHECK)
// turn off afterwards // turn off afterwards
void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { void iClass_ReadCheck(uint8_t blockno, uint8_t keytype) {
uint8_t readcheck[] = { keyType, blockNo }; uint8_t readcheck[] = { keytype, blockno };
uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0}; uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0};
size_t isOK = 0; size_t isOK = 0;
isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6);
cmd_send(CMD_ACK,isOK,0,0,0,0); reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
switch_off(); switch_off();
} }
@ -2207,7 +2248,7 @@ void iClass_Authentication(uint8_t *mac) {
// 6 retries // 6 retries
bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6);
cmd_send(CMD_ACK,isOK,0,0,0,0); reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
} }
typedef struct iclass_premac { typedef struct iclass_premac {
@ -2249,7 +2290,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
uint8_t startup_limit = 10; uint8_t startup_limit = 10;
while (read_status != 2) { while (read_status != 2) {
if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out; if (BUTTON_PRESS() && !data_available()) goto out;
read_status = handshakeIclassTag_ext(card_data, use_credit_key); read_status = handshakeIclassTag_ext(card_data, use_credit_key);
if (startup_limit-- == 0) { if (startup_limit-- == 0) {
@ -2264,7 +2305,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
for (i = 0; i < keyCount; i++) { for (i = 0; i < keyCount; i++) {
// Allow button press / usb cmd to interrupt device // Allow button press / usb cmd to interrupt device
if (BUTTON_PRESS() && !usb_poll_validate_length()) break; if (BUTTON_PRESS() && !data_available()) break;
WDT_HIT(); WDT_HIT();
LED_B_ON(); LED_B_ON();
@ -2291,7 +2332,7 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) {
out: out:
// send keyindex. // send keyindex.
cmd_send(CMD_ACK, isOK, i, 0, 0, 0); reply_mix(CMD_ACK, isOK, i, 0, 0, 0);
if (isOK >= 1 || lastChunk) { if (isOK >= 1 || lastChunk) {
switch_off(); switch_off();
@ -2304,9 +2345,9 @@ out:
// Tries to read block. // Tries to read block.
// retries 10times. // retries 10times.
bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t len) { bool iClass_ReadBlock(uint8_t blockno, uint8_t *data, uint8_t len) {
uint8_t resp[10]; uint8_t resp[10];
uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockno, 0x00, 0x00};
AddCrc(cmd + 1, 1); AddCrc(cmd + 1, 1);
// expect size 10, retry 5times // expect size 10, retry 5times
bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5); bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5);
@ -2319,7 +2360,7 @@ bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t len) {
void iClass_ReadBlk(uint8_t blockno) { void iClass_ReadBlk(uint8_t blockno) {
uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t data[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); bool isOK = iClass_ReadBlock(blockno, data, sizeof(data));
cmd_send(CMD_ACK, isOK, 0, 0, data, sizeof(data)); reply_mix(CMD_ACK, isOK, 0, 0, data, sizeof(data));
switch_off(); switch_off();
} }
@ -2353,15 +2394,15 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) {
memcpy(dataout + (blkCnt * 8), blockdata, 8); memcpy(dataout + (blkCnt * 8), blockdata, 8);
} }
//return pointer to dump memory in arg3 //return pointer to dump memory in arg3
cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); reply_mix(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0);
switch_off(); switch_off();
BigBuf_free(); BigBuf_free();
} }
bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { bool iClass_WriteBlock_ext(uint8_t blockno, uint8_t *data) {
uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t resp[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t write[] = { ICLASS_CMD_UPDATE, blockno, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
memcpy(write + 2, data, 12); // data + mac memcpy(write + 2, data, 12); // data + mac
AddCrc(write + 1, 13); AddCrc(write + 1, 13);
@ -2372,7 +2413,7 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
if (memcmp(write + 2, resp, 8)) { if (memcmp(write + 2, resp, 8)) {
//if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data)
if (blockNo != 3 && blockNo != 4) { if (blockno != 3 && blockno != 4) {
isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5);
} }
} }
@ -2381,9 +2422,9 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) {
} }
// turn off afterwards // turn off afterwards
void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { void iClass_WriteBlock(uint8_t blockno, uint8_t *data) {
bool isOK = iClass_WriteBlock_ext(blockNo, data); bool isOK = iClass_WriteBlock_ext(blockno, data);
cmd_send(CMD_ACK,isOK,0,0,0,0); reply_mix(CMD_ACK, isOK, 0, 0, 0, 0);
switch_off(); switch_off();
} }
@ -2410,6 +2451,6 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) {
else else
DbpString("Clone incomplete"); DbpString("Clone incomplete");
cmd_send(CMD_ACK,1,0,0,0,0); reply_mix(CMD_ACK, 1, 0, 0, 0, 0);
switch_off(); switch_off();
} }

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,7 @@
extern "C" { extern "C" {
#endif #endif
#include "usb_cmd.h" #include "pm3_cmd.h"
#include "cmd.h" #include "cmd.h"
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
@ -27,9 +27,19 @@ extern "C" {
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"
#include "parity.h" #include "parity.h"
#include "random.h"
#include "mifare.h" // structs #include "mifare.h" // structs
// When the PM acts as tag and is receiving it takes
// 2 ticks delay in the RF part (for the first falling edge),
// 3 ticks for the A/D conversion,
// 8 ticks on average until the start of the SSC transfer,
// 8 ticks until the SSC samples the first data
// 7*16 ticks to complete the transfer from FPGA to ARM
// 8 ticks until the next ssp_clk rising edge
// 4*16 ticks until we measure the time
// - 8*16 ticks because we measure the time of the previous transfer
#define DELAY_AIR2ARM_AS_TAG (2 + 3 + 8 + 8 + 7*16 + 8 + 4*16 - 8*16)
typedef struct { typedef struct {
enum { enum {
DEMOD_UNSYNCD, DEMOD_UNSYNCD,
@ -93,44 +103,50 @@ typedef struct {
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); #ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
extern tDemod* GetDemod(void); void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par);
extern void DemodReset(void);
extern void DemodInit(uint8_t *data, uint8_t *parity);
extern tUart* GetUart(void);
extern void UartReset(void);
extern void UartInit(uint8_t *data, uint8_t *parity);
extern RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
extern RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
extern void RAMFUNC SniffIso14443a(uint8_t param); tDemod *GetDemod(void);
extern void SimulateIso14443aTag(int tagType, int flags, uint8_t *data); void DemodReset(void);
extern void iso14443a_antifuzz(uint32_t flags); void DemodInit(uint8_t *data, uint8_t *par);
extern void ReaderIso14443a(UsbCommand *c); tUart *GetUart(void);
extern void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing); void UartReset(void);
extern void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing); void UartInit(uint8_t *data, uint8_t *par);
extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing); RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time);
extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time);
extern void iso14443a_setup(uint8_t fpga_minor_mode); void RAMFUNC SniffIso14443a(uint8_t param);
extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data);
extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); void iso14443a_antifuzz(uint32_t flags);
extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); void ReaderIso14443a(PacketCommandNG *c);
extern void iso14a_set_trigger(bool enable); void ReaderTransmit(uint8_t *frame, uint16_t len, uint32_t *timing);
void ReaderTransmitBitsPar(uint8_t *frame, uint16_t bits, uint8_t *par, uint32_t *timing);
void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32_t *timing);
int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par);
extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); void iso14443a_setup(uint8_t fpga_minor_mode);
extern int EmSend4bit(uint8_t resp); int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res);
extern int EmSendCmd(uint8_t *resp, uint16_t respLen); int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats);
extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades);
extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); void iso14a_set_trigger(bool enable);
extern int EmSendPrecompiledCmd(tag_response_info_t *response_info);
int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen);
int EmSend4bit(uint8_t resp);
int EmSendCmd(uint8_t *resp, uint16_t respLen);
int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision);
int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *par);
int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par);
int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision);
int EmSendPrecompiledCmd(tag_response_info_t *p_response);
bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *max_buffer_size);
bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity,
uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity);
//extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size);
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype); void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
void DetectNACKbug(); void DetectNACKbug();

View file

@ -159,14 +159,14 @@ static void iso14b_set_timeout(uint32_t timeout) {
timeout = MAX_TIMEOUT; timeout = MAX_TIMEOUT;
iso14b_timeout = timeout; iso14b_timeout = timeout;
if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout); if (DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout);
} }
static void iso14b_set_maxframesize(uint16_t size) { static void iso14b_set_maxframesize(uint16_t size) {
if (size > 256) if (size > 256)
size = MAX_FRAME_SIZE; size = MAX_FRAME_SIZE;
Uart.byteCntMax = size; Uart.byteCntMax = size;
if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); if (DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax);
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -180,7 +180,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
* Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig) * Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig)
* Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B) * Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B)
* *
* fc - carrier frequency 13.56mHz * fc - carrier frequency 13.56 MHz
* TR0 - Guard Time per 14443-2 * TR0 - Guard Time per 14443-2
* TR1 - Synchronization Time per 14443-2 * TR1 - Synchronization Time per 14443-2
* TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1)
@ -237,9 +237,6 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
* *
*/ */
int i,j;
uint8_t b;
ToSendReset(); ToSendReset();
// Transmit a burst of ones, as the initial thing that lets the // Transmit a burst of ones, as the initial thing that lets the
@ -252,23 +249,23 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// Send SOF. // Send SOF.
// 10-11 ETU * 4times samples ZEROS // 10-11 ETU * 4times samples ZEROS
for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
//for(i = 0; i < 10; i++) { ToSendStuffBit(0); } //for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
// 2-3 ETU * 4times samples ONES // 2-3 ETU * 4times samples ONES
for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); } for (int i = 0; i < 3; i++) { SEND4STUFFBIT(1); }
//for(i = 0; i < 3; i++) { ToSendStuffBit(1); } //for(i = 0; i < 3; i++) { ToSendStuffBit(1); }
// data // data
for(i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
// Start bit // Start bit
SEND4STUFFBIT(0); SEND4STUFFBIT(0);
//ToSendStuffBit(0); //ToSendStuffBit(0);
// Data bits // Data bits
b = cmd[i]; uint8_t b = cmd[i];
for(j = 0; j < 8; ++j) { for (int j = 0; j < 8; ++j) {
// if(b & 1) { // if(b & 1) {
// SEND4STUFFBIT(1); // SEND4STUFFBIT(1);
// //ToSendStuffBit(1); // //ToSendStuffBit(1);
@ -292,11 +289,11 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// Send EOF. // Send EOF.
// 10-11 ETU * 4 sample rate = ZEROS // 10-11 ETU * 4 sample rate = ZEROS
for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } for (int i = 0; i < 10; i++) { SEND4STUFFBIT(0); }
//for(i = 0; i < 10; i++) { ToSendStuffBit(0); } //for(i = 0; i < 10; i++) { ToSendStuffBit(0); }
// why this? // why this?
for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); } for (int i = 0; i < 40; i++) { SEND4STUFFBIT(1); }
//for(i = 0; i < 40; i++) { ToSendStuffBit(1); } //for(i = 0; i < 40; i++) { ToSendStuffBit(1); }
// Convert from last byte pos to length // Convert from last byte pos to length
@ -385,8 +382,7 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
Uart.posCnt = 0; Uart.posCnt = 0;
} }
if (Uart.bitCnt == 10) { if (Uart.bitCnt == 10) {
if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) {
{
// this is a data byte, with correct // this is a data byte, with correct
// start and stop bits // start and stop bits
Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff; Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff;
@ -442,7 +438,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
StartCountSspClk(); StartCountSspClk();
volatile uint8_t b = 0; volatile uint8_t b;
// clear receiving shift register and holding register // clear receiving shift register and holding register
// What does this loop do? Is it TR1? // What does this loop do? Is it TR1?
@ -492,11 +488,13 @@ void ClearFpgaShiftingRegisters(void){
// clear receiving shift register and holding register // clear receiving shift register and holding register
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
b = AT91C_BASE_SSC->SSC_RHR; (void) b; b = AT91C_BASE_SSC->SSC_RHR;
(void) b;
while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {};
b = AT91C_BASE_SSC->SSC_RHR; (void) b; b = AT91C_BASE_SSC->SSC_RHR;
(void) b;
// wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line)
for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never
@ -545,7 +543,8 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
// Prevent rx holding register from overflowing // Prevent rx holding register from overflowing
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
b = AT91C_BASE_SSC->SSC_RHR;(void)b; b = AT91C_BASE_SSC->SSC_RHR;
(void)b;
} }
} }
@ -566,7 +565,8 @@ void SimulateIso14443bTag(uint32_t pupi) {
FpgaSetupSsc(); FpgaSetupSsc();
// allocate command receive buffer // allocate command receive buffer
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace(); //sim clear_trace(); //sim
set_tracing(true); set_tracing(true);
@ -590,7 +590,8 @@ void SimulateIso14443bTag(uint32_t pupi) {
// supports only 106kBit/s in both directions, max frame size = 32Bytes, // supports only 106kBit/s in both directions, max frame size = 32Bytes,
// supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported:
uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19,
0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7
};
// response to HLTB and ATTRIB // response to HLTB and ATTRIB
static const uint8_t respOK[] = {0x00, 0x78, 0xF0}; static const uint8_t respOK[] = {0x00, 0x78, 0xF0};
@ -615,7 +616,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
memcpy(encodedOK, ToSend, ToSendMax); memcpy(encodedOK, ToSend, ToSendMax);
// Simulation loop // Simulation loop
while (!BUTTON_PRESS() && !usb_poll_validate_length()) { while (!BUTTON_PRESS() && !data_available()) {
WDT_HIT(); WDT_HIT();
// find reader field // find reader field
@ -704,13 +705,14 @@ void SimulateIso14443bTag(uint32_t pupi) {
} }
break; break;
} }
default: break; default:
break;
} }
++cmdsReceived; ++cmdsReceived;
} }
if (MF_DBGLEVEL >= 2) if (DBGLEVEL >= 2)
Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen());
switch_off(); //simulate switch_off(); //simulate
} }
@ -940,9 +942,8 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
* quiet: set to 'TRUE' to disable debug output * quiet: set to 'TRUE' to disable debug output
*/ */
static void GetTagSamplesFor14443bDemod() { static void GetTagSamplesFor14443bDemod() {
bool gotFrame = false, finished = false; bool finished = false;
int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; // int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
int ci = 0, cq = 0;
uint32_t time_0 = 0, time_stop = 0; uint32_t time_0 = 0, time_stop = 0;
BigBuf_free(); BigBuf_free();
@ -956,7 +957,7 @@ static void GetTagSamplesFor14443bDemod() {
// Setup and start DMA. // Setup and start DMA.
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) { if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); if (DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting");
return; return;
} }
@ -973,21 +974,21 @@ static void GetTagSamplesFor14443bDemod() {
WDT_HIT(); WDT_HIT();
// LSB is a fpga signal bit. // LSB is a fpga signal bit.
ci = upTo[0]; int ci = upTo[0];
cq = upTo[1]; int cq = upTo[1];
upTo += 2; upTo += 2;
lastRxCounter -= 2; // lastRxCounter -= 2;
// restart DMA buffer to receive again. // restart DMA buffer to receive again.
if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { if (upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
upTo = dmaBuf; upTo = dmaBuf;
lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; // lastRxCounter = ISO14443B_DMA_BUFFER_SIZE;
AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo;
AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE;
} }
// https://github.com/Proxmark/proxmark3/issues/103 // https://github.com/Proxmark/proxmark3/issues/103
gotFrame = Handle14443bTagSamplesDemod(ci, cq); bool gotFrame = Handle14443bTagSamplesDemod(ci, cq);
time_stop = GetCountSspClk() - time_0; time_stop = GetCountSspClk() - time_0;
finished = (time_stop > iso14b_timeout || gotFrame); finished = (time_stop > iso14b_timeout || gotFrame);
@ -1054,14 +1055,12 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
* QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode? * QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode?
* 1 "stuffbit" = 1ETU (9us) * 1 "stuffbit" = 1ETU (9us)
*/ */
int i;
uint8_t b;
ToSendReset(); ToSendReset();
// Send SOF // Send SOF
// 10-11 ETUs of ZERO // 10-11 ETUs of ZERO
for(i = 0; i < 10; ++i) ToSendStuffBit(0); for (int i = 0; i < 10; ++i) ToSendStuffBit(0);
// 2-3 ETUs of ONE // 2-3 ETUs of ONE
ToSendStuffBit(1); ToSendStuffBit(1);
@ -1070,11 +1069,11 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// Sending cmd, LSB // Sending cmd, LSB
// from here we add BITS // from here we add BITS
for(i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
// Start bit // Start bit
ToSendStuffBit(0); ToSendStuffBit(0);
// Data bits // Data bits
b = cmd[i]; uint8_t b = cmd[i];
// if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0);
// if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
// if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
@ -1104,13 +1103,13 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// Send EOF // Send EOF
// 10-11 ETUs of ZERO // 10-11 ETUs of ZERO
for(i = 0; i < 10; ++i) ToSendStuffBit(0); for (int i = 0; i < 10; ++i) ToSendStuffBit(0);
// Transition time. TR0 - guard time // Transition time. TR0 - guard time
// 8ETUS minum? // 8ETUS minum?
// Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF.
// I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode
for(i = 0; i < 24 ; ++i) ToSendStuffBit(1); for (int i = 0; i < 24 ; ++i) ToSendStuffBit(1);
// TR1 - Synchronization time // TR1 - Synchronization time
// Convert from last character reference to length // Convert from last character reference to length
@ -1157,7 +1156,7 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
// VALIDATE CRC // VALIDATE CRC
if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) { if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) {
if (MF_DBGLEVEL > 3) Dbprintf("crc fail ICE"); if (DBGLEVEL > 3) Dbprintf("crc fail ICE");
return 0; return 0;
} }
// copy response contents // copy response contents
@ -1408,14 +1407,14 @@ static void iso1444b_setup_sniff(void){
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
BigBuf_free(); BigBuf_free();
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
clear_trace();//setup snoop clear_trace();
set_tracing(true); set_tracing(true);
// Initialize Demod and Uart structs // Initialize Demod and Uart structs
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); UartInit(BigBuf_malloc(MAX_FRAME_SIZE));
if (MF_DBGLEVEL > 1) { if (DBGLEVEL > 1) {
// Print debug information about the buffer sizes // Print debug information about the buffer sizes
Dbprintf("[+] Sniff buffers initialized:"); Dbprintf("[+] Sniff buffers initialized:");
Dbprintf("[+] trace: %i bytes", BigBuf_max_traceLen()); Dbprintf("[+] trace: %i bytes", BigBuf_max_traceLen());
@ -1457,8 +1456,7 @@ static void iso1444b_setup_sniff(void){
*/ */
void RAMFUNC SniffIso14443b(void) { void RAMFUNC SniffIso14443b(void) {
uint32_t time_0 = 0, time_start = 0, time_stop = 0; uint32_t time_0 = 0, time_start = 0, time_stop;
int ci = 0, cq = 0;
// We won't start recording the frames that we acquire until we trigger; // We won't start recording the frames that we acquire until we trigger;
// a good trigger condition to get started is probably when we see a // a good trigger condition to get started is probably when we see a
@ -1474,7 +1472,7 @@ void RAMFUNC SniffIso14443b(void) {
// Setup and start DMA. // Setup and start DMA.
if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) { if (!FpgaSetupSscDma((uint8_t *) dmaBuf, ISO14443B_DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); if (DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
BigBuf_free(); BigBuf_free();
return; return;
} }
@ -1486,8 +1484,8 @@ void RAMFUNC SniffIso14443b(void) {
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
ci = data[0]; int ci = data[0];
cq = data[1]; int cq = data[1];
data += 2; data += 2;
if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) {
@ -1538,7 +1536,7 @@ void RAMFUNC SniffIso14443b(void) {
} }
} }
if (MF_DBGLEVEL >= 2) { if (DBGLEVEL >= 2) {
DbpString("[+] Sniff statistics:"); DbpString("[+] Sniff statistics:");
Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax);
Dbprintf("[+] trace length: %i", BigBuf_get_traceLen()); Dbprintf("[+] trace length: %i", BigBuf_get_traceLen());
@ -1562,15 +1560,16 @@ void iso14b_set_trigger(bool enable) {
* none * none
* *
*/ */
void SendRawCommand14443B_Ex(UsbCommand *c) { void SendRawCommand14443B_Ex(PacketCommandNG *c) {
iso14b_command_t param = c->arg[0]; iso14b_command_t param = c->oldarg[0];
size_t len = c->arg[1] & 0xffff; size_t len = c->oldarg[1] & 0xffff;
uint8_t *cmd = c->d.asBytes; uint32_t timeout = c->oldarg[2];
uint8_t status = 0; uint8_t *cmd = c->data.asBytes;
uint8_t status;
uint32_t sendlen = sizeof(iso14b_card_select_t); uint32_t sendlen = sizeof(iso14b_card_select_t);
uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; uint8_t buf[PM3_CMD_DATA_SIZE] = {0x00};
if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param ); if (DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param);
// turn on trigger (LED_A) // turn on trigger (LED_A)
if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER)
@ -1581,12 +1580,15 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
clear_trace(); clear_trace();
} }
if ((param & ISO14B_SET_TIMEOUT))
iso14b_set_timeout(timeout);
set_tracing(true); set_tracing(true);
if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) {
iso14b_card_select_t *card = (iso14b_card_select_t *)buf; iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
status = iso14443b_select_card(card); status = iso14443b_select_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: attrib fail, 3:crc fail, // 0: OK 2: attrib fail, 3:crc fail,
if (status > 0) goto out; if (status > 0) goto out;
} }
@ -1594,14 +1596,14 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) {
iso14b_card_select_t *card = (iso14b_card_select_t *)buf; iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
status = iso14443b_select_srx_card(card); status = iso14443b_select_srx_card(card);
cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); reply_old(CMD_ACK, status, sendlen, 0, buf, sendlen);
// 0: OK 2: demod fail, 3:crc fail, // 0: OK 2: demod fail, 3:crc fail,
if (status > 0) goto out; if (status > 0) goto out;
} }
if ((param & ISO14B_APDU) == ISO14B_APDU) { if ((param & ISO14B_APDU) == ISO14B_APDU) {
status = iso14443b_apdu(cmd, len, buf); status = iso14443b_apdu(cmd, len, buf);
cmd_send(CMD_ACK, status, status, 0, buf, status); reply_old(CMD_ACK, status, status, 0, buf, status);
} }
if ((param & ISO14B_RAW) == ISO14B_RAW) { if ((param & ISO14B_RAW) == ISO14B_RAW) {
@ -1613,9 +1615,9 @@ void SendRawCommand14443B_Ex(UsbCommand *c) {
CodeAndTransmit14443bAsReader(cmd, len); // raw CodeAndTransmit14443bAsReader(cmd, len); // raw
GetTagSamplesFor14443bDemod(); // raw GetTagSamplesFor14443bDemod(); // raw
sendlen = MIN(Demod.len, USB_CMD_DATA_SIZE); sendlen = MIN(Demod.len, PM3_CMD_DATA_SIZE);
status = (Demod.len > 0) ? 0 : 1; status = (Demod.len > 0) ? 0 : 1;
cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen); reply_old(CMD_ACK, status, sendlen, 0, Demod.output, sendlen);
} }
out: out:

View file

@ -18,7 +18,7 @@ extern "C" {
#endif #endif
#include "proxmark3.h" #include "proxmark3.h"
#include "common.h" // access to global variable: MF_DBGLEVEL #include "common.h" // access to global variable: DBGLEVEL
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
@ -34,15 +34,15 @@ extern "C" {
# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) # define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1)
#endif #endif
extern void SendRawCommand14443B_Ex(UsbCommand *c); void SendRawCommand14443B_Ex(PacketCommandNG *c);
extern void iso14443b_setup(); void iso14443b_setup();
extern uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response); uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response);
extern uint8_t iso14443b_select_card(iso14b_card_select_t* card); uint8_t iso14443b_select_card(iso14b_card_select_t *card);
extern uint8_t iso14443b_select_card_srx(iso14b_card_select_t* card); uint8_t iso14443b_select_card_srx(iso14b_card_select_t *card);
// testfunctions // testfunctions
extern void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ); void WaitForFpgaDelayQueueIsEmpty(uint16_t delay);
extern void ClearFpgaShiftingRegisters(void); void ClearFpgaShiftingRegisters(void);
// States for 14B SIM command // States for 14B SIM command
#define SIM_NOFIELD 0 #define SIM_NOFIELD 0

View file

@ -81,9 +81,9 @@
#define Logic1 Iso15693Logic1 #define Logic1 Iso15693Logic1
#define FrameEOF Iso15693FrameEOF #define FrameEOF Iso15693FrameEOF
#define Crc(data, len) crc(CRC_15693, (data), (len)) //#define Crc(data, len) Crc(CRC_15693, (data), (len))
#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) #define CheckCrc15(data, len) check_crc(CRC_15693, (data), (len))
#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) #define AddCrc15(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1)
#define sprintUID(target,uid) Iso15693sprintUID((target), (uid)) #define sprintUID(target,uid) Iso15693sprintUID((target), (uid))
@ -330,7 +330,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// Even things out by the length of the target waveform. // Even things out by the length of the target waveform.
corr0 *= 4; corr0 *= 4;
corr1 *= 4; corr1 *= 4;
// if (MF_DBGLEVEL >= MF_DBG_EXTENDED) // if (DBGLEVEL >= DBG_EXTENDED)
// Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF); // Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF);
if (corrEOF > corr1 && corrEOF > corr0) if (corrEOF > corr1 && corrEOF > corr0)
@ -356,12 +356,12 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
} }
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k);
if (mask != 0x01) { // this happens, when we miss the EOF if (mask != 0x01) { // this happens, when we miss the EOF
// TODO: for some reason this happens quite often // TODO: for some reason this happens quite often
if (MF_DBGLEVEL >= MF_DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask); if (DBGLEVEL >= DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask);
//if (mask < 0x08) k--; // discard the last uneven octet; //if (mask < 0x08) k--; // discard the last uneven octet;
// 0x08 is an assumption - but works quite often // 0x08 is an assumption - but works quite often
} }
@ -388,7 +388,7 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
uint32_t time_0 = GetCountSspClk(); uint32_t time_0 = GetCountSspClk();
uint32_t time_stop = 0; uint32_t time_stop = 0;
bool getNext = false; bool getNext = false;
int counter = 0, ci = 0, cq = 0; int counter = 0, ci, cq = 0;
uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE); uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE);
if (elapsed) *elapsed = 0; if (elapsed) *elapsed = 0;
@ -438,7 +438,7 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed) { static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed) {
bool getNext = false; bool getNext = false;
int counter = 0, ci = 0, cq = 0; int counter = 0, ci, cq = 0;
uint32_t time_0 = 0, time_stop = 0; uint32_t time_0 = 0, time_stop = 0;
uint8_t *buf = BigBuf_get_addr(); uint8_t *buf = BigBuf_get_addr();
@ -485,7 +485,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void AcquireRawAdcSamplesIso15693(void) { void AcquireRawAdcSamplesIso15693(void) {
int c = 0, getNext = false; int c = 0, getNext = false;
int ci = 0, cq = 0; int ci, cq = 0;
FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD); SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
@ -552,7 +552,7 @@ void AcquireRawAdcSamplesIso15693(void) {
void RecordRawAdcSamplesIso15693(void) { void RecordRawAdcSamplesIso15693(void) {
int c = 0, getNext = false; int c = 0, getNext = false;
int ci = 0, cq = 0; int ci, cq = 0;
Iso15693InitReader(); Iso15693InitReader();
@ -621,18 +621,18 @@ void Iso15693InitReader(void) {
// Encode (into the ToSend buffers) an identify request, which is the first // Encode (into the ToSend buffers) an identify request, which is the first
// thing that you must send to a tag to get a response. // thing that you must send to a tag to get a response.
static void BuildIdentifyRequest(uint8_t *out) { // It expects "cmdout" to be at least CMD_ID_RESP large
static void BuildIdentifyRequest(uint8_t *cmdout) {
uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0};
// flags // flags
cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
// no mask // no mask
cmd[2] = 0x00; cmd[2] = 0x00;
// CRC // CRC
AddCrc(cmd, 3); AddCrc15(cmd, 3);
// coding as high speed (1 out of 4) // coding as high speed (1 out of 4)
CodeIso15693AsReader(cmd, CMD_ID_RESP); CodeIso15693AsReader(cmd, CMD_ID_RESP);
memcpy(out, cmd, CMD_ID_RESP); memcpy(cmdout, cmd, CMD_ID_RESP);
} }
// uid is in transmission order (which is reverse of display order) // uid is in transmission order (which is reverse of display order)
@ -658,14 +658,15 @@ static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumb
// Block number to read // Block number to read
cmd[10] = blockNumber;//0x00; cmd[10] = blockNumber;//0x00;
// CRC // CRC
AddCrc(cmd, 11); AddCrc15(cmd, 11);
CodeIso15693AsReader(cmd, CMD_READ_RESP); CodeIso15693AsReader(cmd, CMD_READ_RESP);
memcpy(out, cmd, CMD_ID_RESP); memcpy(out, cmd, CMD_ID_RESP);
} }
*/ */
// Now the VICC>VCD responses when we are simulating a tag // Now the VICC>VCD responses when we are simulating a tag
static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { // It expects "out" to be at least CMD_INV_RESP large
static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid) {
uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t cmd[CMD_INV_RESP] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -684,9 +685,9 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) {
cmd[8] = uid[1]; //0x05; cmd[8] = uid[1]; //0x05;
cmd[9] = uid[0]; //0xe0; cmd[9] = uid[0]; //0xe0;
// CRC // CRC
AddCrc(cmd, 10); AddCrc15(cmd, 10);
CodeIso15693AsReader(cmd, CMD_INV_RESP); CodeIso15693AsReader(cmd, CMD_INV_RESP);
memcpy(out, cmd, CMD_ID_RESP); memcpy(cmdout, cmd, CMD_INV_RESP);
} }
// Universal Method for sending to and recv bytes from a tag // Universal Method for sending to and recv bytes from a tag
@ -735,56 +736,56 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outda
// Decodes a message from a tag and displays its metadata and content // Decodes a message from a tag and displays its metadata and content
#define DBD15STATLEN 48 #define DBD15STATLEN 48
void DbdecodeIso15693Answer(int len, uint8_t *d) { void DbdecodeIso15693Answer(int len, uint8_t *d) {
char status[DBD15STATLEN+1] = {0};
if (len > 3) { if (len > 3) {
char status[DBD15STATLEN + 1] = {0};
if (d[0] & (1 << 3)) if (d[0] & (1 << 3))
strncat(status, "ProtExt ", DBD15STATLEN); strncat(status, "ProtExt ", DBD15STATLEN - strlen(status));
if (d[0] & 1) { if (d[0] & 1) {
// error // error
strncat(status, "Error ", DBD15STATLEN); strncat(status, "Error ", DBD15STATLEN - strlen(status));
switch (d[1]) { switch (d[1]) {
case 0x01: case 0x01:
strncat(status, "01: not supported", DBD15STATLEN); strncat(status, "01: not supported", DBD15STATLEN - strlen(status));
break; break;
case 0x02: case 0x02:
strncat(status, "02: not recognized", DBD15STATLEN); strncat(status, "02: not recognized", DBD15STATLEN - strlen(status));
break; break;
case 0x03: case 0x03:
strncat(status, "03: opt not supported", DBD15STATLEN); strncat(status, "03: opt not supported", DBD15STATLEN - strlen(status));
break; break;
case 0x0f: case 0x0f:
strncat(status, "0F: no info", DBD15STATLEN); strncat(status, "0F: no info", DBD15STATLEN - strlen(status));
break; break;
case 0x10: case 0x10:
strncat(status, "10: dont exist", DBD15STATLEN); strncat(status, "10: dont exist", DBD15STATLEN - strlen(status));
break; break;
case 0x11: case 0x11:
strncat(status, "11: lock again", DBD15STATLEN); strncat(status, "11: lock again", DBD15STATLEN - strlen(status));
break; break;
case 0x12: case 0x12:
strncat(status, "12: locked", DBD15STATLEN); strncat(status, "12: locked", DBD15STATLEN - strlen(status));
break; break;
case 0x13: case 0x13:
strncat(status, "13: program error", DBD15STATLEN); strncat(status, "13: program error", DBD15STATLEN - strlen(status));
break; break;
case 0x14: case 0x14:
strncat(status, "14: lock error", DBD15STATLEN); strncat(status, "14: lock error", DBD15STATLEN - strlen(status));
break; break;
default: default:
strncat(status, "unknown error", DBD15STATLEN); strncat(status, "unknown error", DBD15STATLEN - strlen(status));
} }
strncat(status ," " ,DBD15STATLEN); strncat(status, " ", DBD15STATLEN - strlen(status));
} else { } else {
strncat(status ,"No error ", DBD15STATLEN); strncat(status, "No error ", DBD15STATLEN - strlen(status));
} }
if (CheckCrc(d, len)) if (CheckCrc15(d, len))
strncat(status, "[+] crc OK", DBD15STATLEN); strncat(status, "[+] crc OK", DBD15STATLEN - strlen(status));
else else
strncat(status, "[!] crc fail", DBD15STATLEN); strncat(status, "[!] crc fail", DBD15STATLEN - strlen(status));
if ( MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); if (DBGLEVEL >= DBG_ERROR) Dbprintf("%s", status);
} }
} }
@ -801,9 +802,6 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) {
void ReaderIso15693(uint32_t parameter) { void ReaderIso15693(uint32_t parameter) {
int answerLen1 = 0; int answerLen1 = 0;
int tsamples = 0, wait = 0, elapsed = 0; int tsamples = 0, wait = 0, elapsed = 0;
uint8_t uid[8] = {0,0,0,0,0,0,0,0};
// set up device/fpga // set up device/fpga
Iso15693InitReader(); Iso15693InitReader();
@ -828,6 +826,7 @@ void ReaderIso15693(uint32_t parameter) {
// we should do a better check than this // we should do a better check than this
if (answerLen1 >= 12) { if (answerLen1 >= 12) {
uint8_t uid[8];
uid[0] = answer1[9]; // always E0 uid[0] = answer1[9]; // always E0
uid[1] = answer1[8]; // IC Manufacturer code uid[1] = answer1[8]; // IC Manufacturer code
uid[2] = answer1[7]; uid[2] = answer1[7];
@ -837,7 +836,7 @@ void ReaderIso15693(uint32_t parameter) {
uid[6] = answer1[3]; uid[6] = answer1[3];
uid[7] = answer1[2]; uid[7] = answer1[2];
if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X",
uid[0], uid[1], uid[2], uid[3], uid[0], uid[1], uid[2], uid[3],
uid[4], uid[5], uid[5], uid[6] uid[4], uid[5], uid[5], uid[6]
@ -848,10 +847,10 @@ void ReaderIso15693(uint32_t parameter) {
// arg1 = len of response (12 bytes) // arg1 = len of response (12 bytes)
// arg2 = rtf // arg2 = rtf
// asbytes = uid. // asbytes = uid.
cmd_send(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); reply_old(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid));
} }
if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1); Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1);
DbdecodeIso15693Answer(answerLen1, answer1); DbdecodeIso15693Answer(answerLen1, answer1);
Dbhexdump(answerLen1, answer1, true); Dbhexdump(answerLen1, answer1, true);
@ -874,8 +873,8 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
LED_A_ON(); LED_A_ON();
uint32_t time_start = 0; uint32_t time_start;
int ans = 0, samples = 0, tsamples = 0; int samples = 0, tsamples = 0;
int wait = 0, elapsed = 0; int wait = 0, elapsed = 0;
Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]);
@ -890,11 +889,11 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
uint8_t cmd[CMD_INV_RESP] = {0}; uint8_t cmd[CMD_INV_RESP] = {0};
BuildInventoryResponse(cmd, uid); BuildInventoryResponse(cmd, uid);
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { while (!BUTTON_PRESS() && !data_available()) {
WDT_HIT(); WDT_HIT();
// Listen to reader // Listen to reader
ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ; int ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ;
// we should do a better check than this // we should do a better check than this
if (ans >= 1) { if (ans >= 1) {
@ -903,7 +902,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait);
LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans, Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans,
buf[0], buf[1], buf[2], buf[3], buf[0], buf[1], buf[2], buf[3],
buf[4], buf[5], buf[6], buf[7] buf[4], buf[5], buf[6], buf[7]
@ -931,7 +930,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1;
data[1] = ISO15_CMD_INVENTORY; data[1] = ISO15_CMD_INVENTORY;
data[2] = 0; // mask length data[2] = 0; // mask length
AddCrc(data, 3); AddCrc15(data, 3);
datalen += 2; datalen += 2;
recvlen = SendDataTag(data, datalen, false, speed, buf); recvlen = SendDataTag(data, datalen, false, speed, buf);
@ -950,7 +949,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
for (uint16_t i = 0; i < 256; i++) { for (uint16_t i = 0; i < 256; i++) {
data[2] = i & 0xFF; data[2] = i & 0xFF;
AddCrc(data, 4); AddCrc15(data, 4);
datalen += 2; datalen += 2;
recvlen = SendDataTag(data, datalen, false, speed, buf); recvlen = SendDataTag(data, datalen, false, speed, buf);
WDT_HIT(); WDT_HIT();
@ -977,7 +976,7 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
uint8_t buf[ISO15_MAX_FRAME]; uint8_t buf[ISO15_MAX_FRAME];
memset(buf, 0x00, sizeof(buf)); memset(buf, 0x00, sizeof(buf));
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
DbpString("[+] SEND"); DbpString("[+] SEND");
Dbhexdump(datalen, data, true); Dbhexdump(datalen, data, true);
} }
@ -988,15 +987,15 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint
buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen; buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen;
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, buflen, 0, 0, buf, buflen); reply_old(CMD_ACK, buflen, 0, 0, buf, buflen);
LED_B_OFF(); LED_B_OFF();
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
DbpString("[+] RECV"); DbpString("[+] RECV");
DbdecodeIso15693Answer(buflen, buf); DbdecodeIso15693Answer(buflen, buf);
Dbhexdump(buflen, buf, true); Dbhexdump(buflen, buf, true);
} }
} else { } else {
cmd_send(CMD_ACK,1,0,0,0,0); reply_old(CMD_ACK, 1, 0, 0, 0, 0);
} }
} }

View file

@ -1,7 +1,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch> // (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2016 Iceman // 2016 Iceman
// 2018 AntiCat (rwd rewritten) // 2018 AntiCat
// //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // 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 // at your option, any later version. See the LICENSE.txt file for the text of
@ -16,7 +16,7 @@
#include "legic_prng.h" /* legic PRNG impl */ #include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */ #include "legic.h" /* legic_card_select_t struct */
static uint8_t* legic_mem; /* card memory, used for read, write and sim */ static uint8_t *legic_mem; /* card memory, used for read, write */
static legic_card_select_t card;/* metadata of currently selected card */ static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc; static crc_t legic_crc;
@ -81,11 +81,13 @@ static inline uint8_t rx_byte_from_fpga() {
// To reduce CPU time the amplitude is approximated by using linear functions: // To reduce CPU time the amplitude is approximated by using linear functions:
// am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq)) // am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq))
// //
// Note: The SSC receiver is never synchronized the calculation my be performed // 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. // on a i/q pair from two subsequent correlations, but does not matter.
static inline int32_t sample_power() { static inline int32_t sample_power() {
int32_t q = (int8_t)rx_byte_from_fpga(); q = ABS(q); int32_t q = (int8_t)rx_byte_from_fpga();
int32_t i = (int8_t)rx_byte_from_fpga(); i = ABS(i); q = ABS(q);
int32_t i = (int8_t)rx_byte_from_fpga();
i = ABS(i);
return MAX(i, q) + (MIN(i, q) >> 1); return MAX(i, q) + (MIN(i, q) >> 1);
} }
@ -179,7 +181,7 @@ static uint32_t rx_frame(uint8_t len) {
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
uint32_t frame = 0; uint32_t frame = 0;
for(uint8_t i = 0; i < len; i++) { for (uint8_t i = 0; i < len; ++i) {
frame |= (rx_bit() ^ legic_prng_get_bit()) << i; frame |= (rx_bit() ^ legic_prng_get_bit()) << i;
legic_prng_forward(1); legic_prng_forward(1);
@ -235,7 +237,7 @@ static bool rx_ack() {
// Legic Reader // Legic Reader
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
int init_card(uint8_t cardtype, legic_card_select_t *p_card) { static int init_card(uint8_t cardtype, legic_card_select_t *p_card) {
p_card->tagtype = cardtype; p_card->tagtype = cardtype;
switch (p_card->tagtype) { switch (p_card->tagtype) {
@ -302,8 +304,8 @@ static void init_reader(bool clear_mem) {
// The setup consists of a three way handshake: // The setup consists of a three way handshake:
// - Transmit initialisation vector 7 bits // - Transmit initialisation vector 7 bits
// - Receive card type 6 bits // - Receive card type 6 bits
// - Acknowledge frame 6 bits // - Transmit Acknowledge 6 bits
static uint32_t setup_phase_reader(uint8_t iv) { static uint32_t setup_phase(uint8_t iv) {
// init coordination timestamp // init coordination timestamp
last_frame_end = GET_TICKS; last_frame_end = GET_TICKS;
@ -314,7 +316,7 @@ static uint32_t setup_phase_reader(uint8_t iv) {
legic_prng_init(0); legic_prng_init(0);
tx_frame(iv, 7); tx_frame(iv, 7);
// configure iv // configure prng
legic_prng_init(iv); legic_prng_init(iv);
legic_prng_forward(2); legic_prng_forward(2);
@ -398,9 +400,9 @@ void LegicRfInfo(void) {
init_reader(false); init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(0x01); uint8_t card_type = setup_phase(0x01);
if (init_card(card_type, &card) != 0) { if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
@ -408,7 +410,7 @@ void LegicRfInfo(void) {
for (uint8_t i = 0; i < sizeof(card.uid); ++i) { for (uint8_t i = 0; i < sizeof(card.uid); ++i) {
int16_t byte = read_byte(i, card.cmdsize); int16_t byte = read_byte(i, card.cmdsize);
if (byte == -1) { if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
card.uid[i] = byte & 0xFF; card.uid[i] = byte & 0xFF;
@ -418,12 +420,12 @@ void LegicRfInfo(void) {
int16_t mcc = read_byte(4, card.cmdsize); int16_t mcc = read_byte(4, card.cmdsize);
int16_t calc_mcc = CRC8Legic(card.uid, 4);; int16_t calc_mcc = CRC8Legic(card.uid, 4);;
if (mcc != calc_mcc) { if (mcc != calc_mcc) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
// OK // OK
cmd_send(CMD_ACK, 1, 0, 0, (uint8_t*)&card, sizeof(legic_card_select_t)); reply_old(CMD_ACK, 1, 0, 0, (uint8_t *)&card, sizeof(legic_card_select_t));
OUT: OUT:
switch_off(); switch_off();
@ -435,9 +437,9 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
init_reader(false); init_reader(false);
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(iv); uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) { if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
@ -449,14 +451,14 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) {
for (uint16_t i = 0; i < len; ++i) { for (uint16_t i = 0; i < len; ++i) {
int16_t byte = read_byte(offset + i, card.cmdsize); int16_t byte = read_byte(offset + i, card.cmdsize);
if (byte == -1) { if (byte == -1) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
legic_mem[i] = byte; legic_mem[i] = byte;
} }
// OK // OK
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len); reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
OUT: OUT:
switch_off(); switch_off();
@ -469,14 +471,14 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
// uid is not writeable // uid is not writeable
if (offset <= WRITE_LOWERLIMIT) { if (offset <= WRITE_LOWERLIMIT) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
// establish shared secret and detect card type // establish shared secret and detect card type
uint8_t card_type = setup_phase_reader(iv); uint8_t card_type = setup_phase(iv);
if (init_card(card_type, &card) != 0) { if (init_card(card_type, &card) != 0) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
@ -489,19 +491,15 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
while (len-- > 0 && !BUTTON_PRESS()) { while (len-- > 0 && !BUTTON_PRESS()) {
if (!write_byte(len + offset, data[len], card.addrsize)) { if (!write_byte(len + offset, data[len], card.addrsize)) {
Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]); Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]);
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); reply_mix(CMD_ACK, 0, 0, 0, 0, 0);
goto OUT; goto OUT;
} }
} }
// OK // OK
cmd_send(CMD_ACK, 1, len, 0, legic_mem, len); reply_old(CMD_ACK, 1, len, 0, legic_mem, len);
OUT: OUT:
switch_off(); switch_off();
StopTicks(); StopTicks();
} }
void LegicRfSimulate(int phase, int frame, int reqresp) {
cmd_send(CMD_ACK, 0, 0, 0, 0, 0); //TODO Implement
}

View file

@ -1,5 +1,6 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch> // (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2018 AntiCat
// //
// This code is licensed to you under the terms of the GNU GPL, version 2 or, // 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 // at your option, any later version. See the LICENSE.txt file for the text of
@ -13,9 +14,8 @@
#include "proxmark3.h" #include "proxmark3.h"
extern void LegicRfInfo(void); void LegicRfInfo(void);
extern void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv);
extern void LegicRfWriter(uint16_t offset, uint16_t byte, uint8_t iv, uint8_t *data); void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data);
extern void LegicRfSimulate(int phase, int frame, int reqresp);
#endif /* __LEGICRF_H */ #endif /* __LEGICRF_H */

485
armsrc/legicrfsim.c Normal file
View file

@ -0,0 +1,485 @@
//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2016 Iceman
// 2018 AntiCat
//
// 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.
//-----------------------------------------------------------------------------
// LEGIC RF simulation code
//-----------------------------------------------------------------------------
#include "legicrf.h"
#include "ticks.h" /* timers */
#include "crc.h" /* legic crc-4 */
#include "legic_prng.h" /* legic PRNG impl */
#include "legic.h" /* legic_card_select_t struct */
static uint8_t *legic_mem; /* card memory, used for sim */
static legic_card_select_t card;/* metadata of currently selected card */
static crc_t legic_crc;
//-----------------------------------------------------------------------------
// Frame timing and pseudorandom number generator
//
// The Prng is forwarded every 99.1us (TAG_BIT_PERIOD), except when the reader is
// transmitting. In that case the prng has to be forwarded every bit transmitted:
// - 31.3us for a 0 (RWD_TIME_0)
// - 99.1us for a 1 (RWD_TIME_1)
//
// The data dependent timing makes writing comprehensible code significantly
// harder. The current aproach forwards the prng data based if there is data on
// air and time based, using GetCountSspClk(), during computational and wait
// periodes. SSP Clock is clocked by the FPGA at 212 kHz (subcarrier frequency).
//
// To not have the necessity to calculate/guess exection time dependend timeouts
// tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots.
//-----------------------------------------------------------------------------
static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
#define TAG_FRAME_WAIT 70 /* 330us from READER frame end to TAG frame start */
#define TAG_ACK_WAIT 758 /* 3.57ms from READER frame end to TAG write ACK */
#define TAG_BIT_PERIOD 21 /* 99.1us */
#define RWD_TIME_PAUSE 4 /* 18.9us */
#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */
#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */
#define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */
#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */
#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */
#define RWD_PULSE 1 /* Pulse is signaled with GPIO_SSC_DIN high */
#define RWD_PAUSE 0 /* Pause is signaled with GPIO_SSC_DIN low */
//-----------------------------------------------------------------------------
// Demodulation
//-----------------------------------------------------------------------------
// Returns true if a pulse/pause is received within timeout
static inline bool wait_for(bool value, const uint32_t timeout) {
while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) {
if (GetCountSspClk() > timeout) {
return false;
}
}
return true;
}
// Returns a demedulated bit or -1 on code violation
//
// rx_bit decodes bits using a thresholds. rx_bit has to be called by as soon as
// a frame starts (first pause is received). rx_bit checks for a pause up to
// 18.9us followed by a pulse of 80.2us or 42.4us:
// - A bit length <18.9us is a code violation
// - A bit length >80.2us is a 1
// - A bit length <80.2us is a 0
// - A bit length >148.6us is a code violation
static inline int8_t rx_bit() {
// backup ts for threshold calculation
uint32_t bit_start = last_frame_end;
// wait for pause to end
if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1 * 3 / 2)) {
return -1;
}
// wait for next pause
if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1 * 3 / 2)) {
return -1;
}
// update bit and frame end
last_frame_end = GetCountSspClk();
// check for code violation (bit to short)
if (last_frame_end - bit_start < RWD_TIME_PAUSE) {
return -1;
}
// apply threshold (average of RWD_TIME_0 and )
return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2);
}
//-----------------------------------------------------------------------------
// Modulation
//
// LEGIC RF uses a very basic load modulation from card to reader:
// - Subcarrier on for a 1
// - Subcarrier off for for a 0
//
// The 212kHz subcarrier is generated by the FPGA as well as a mathcing ssp clk.
// Each bit is transfered in a 99.1us slot and the first timeslot starts 330us
// after the final 20us pause generated by the reader.
//-----------------------------------------------------------------------------
// Transmits a bit
//
// Note: The Subcarrier is not disabled during bits to prevent glitches. This is
// not mandatory but results in a cleaner signal. tx_frame will disable
// the subcarrier when the frame is done.
static inline void tx_bit(bool bit) {
LED_C_ON();
if (bit) {
// modulate subcarrier
HIGH(GPIO_SSC_DOUT);
} else {
// do not modulate subcarrier
LOW(GPIO_SSC_DOUT);
}
// wait for tx timeslot to end
last_frame_end += TAG_BIT_PERIOD;
while (GetCountSspClk() < last_frame_end) { };
LED_C_OFF();
}
//-----------------------------------------------------------------------------
// Frame Handling
//
// The LEGIC RF protocol from reader to card does not include explicit frame
// start/stop information or length information. The tag detects end of frame
// trough an extended pulse (>99.1us) without a pause.
// In reverse direction (card to reader) the number of bites is well known
// and depends only the command received (IV, ACK, READ or WRITE).
//-----------------------------------------------------------------------------
static void tx_frame(uint32_t frame, uint8_t len) {
// wait for next tx timeslot
last_frame_end += TAG_FRAME_WAIT;
legic_prng_forward(TAG_FRAME_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
// transmit frame, MSB first
for (uint8_t i = 0; i < len; ++i) {
bool bit = (frame >> i) & 0x01;
tx_bit(bit ^ legic_prng_get_bit());
legic_prng_forward(1);
};
// disable subcarrier
LOW(GPIO_SSC_DOUT);
// log
uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
}
static void tx_ack() {
// wait for ack timeslot
last_frame_end += TAG_ACK_WAIT;
legic_prng_forward(TAG_ACK_WAIT / TAG_BIT_PERIOD - 1);
while (GetCountSspClk() < last_frame_end) { };
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
// transmit ack (ack is not encrypted)
tx_bit(true);
legic_prng_forward(1);
// disable subcarrier
LOW(GPIO_SSC_DOUT);
// log
uint8_t cmdbytes[] = {1, 1};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false);
}
// Returns a demedulated frame or -1 on code violation
//
// Since TX to RX delay is arbitrary rx_frame has to:
// - detect start of frame (first pause)
// - forward prng based on ts/TAG_BIT_PERIOD
// - receive the frame
// - detect end of frame (last pause)
static int32_t rx_frame(uint8_t *len) {
int32_t frame = 0;
// add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay)
// those will be substracted at the end of the rx phase
last_frame_end -= 2;
// wait for first pause (start of frame)
for (uint8_t i = 0; true; ++i) {
// increment prng every TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD;
legic_prng_forward(1);
// if start of frame was received exit delay loop
if (wait_for(RWD_PAUSE, last_frame_end)) {
last_frame_end = GetCountSspClk();
break;
}
// check for code violation
if (i > RWD_CMD_TIMEOUT) {
return -1;
}
}
// backup ts for trace log
uint32_t last_frame_start = last_frame_end;
// receive frame
for (*len = 0; true; ++(*len)) {
// receive next bit
LED_B_ON();
int8_t bit = rx_bit();
LED_B_OFF();
// check for code violation and to short / long frame
if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) {
return -1;
}
// check for code violation caused by end of frame
if (bit < 0) {
break;
}
// append bit
frame |= (bit ^ legic_prng_get_bit()) << (*len);
legic_prng_forward(1);
}
// rx_bit sets coordination timestamp to start of pause, append pause duration
// and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to
// obtain exact end of frame.
last_frame_end += RWD_TIME_PAUSE - 2;
// log
uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)};
LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true);
return frame;
}
//-----------------------------------------------------------------------------
// Legic Simulator
//-----------------------------------------------------------------------------
static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) {
p_card->tagtype = cardtype;
switch (p_card->tagtype) {
case 0:
p_card->cmdsize = 6;
p_card->addrsize = 5;
p_card->cardsize = 22;
break;
case 1:
p_card->cmdsize = 9;
p_card->addrsize = 8;
p_card->cardsize = 256;
break;
case 2:
p_card->cmdsize = 11;
p_card->addrsize = 10;
p_card->cardsize = 1024;
break;
default:
p_card->cmdsize = 0;
p_card->addrsize = 0;
p_card->cardsize = 0;
return 2;
}
return 0;
}
static void init_tag() {
// configure FPGA
FpgaDownloadAndGo(FPGA_BITSTREAM_HF);
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR
| FPGA_HF_SIMULATOR_MODULATE_212K);
SetAdcMuxFor(GPIO_MUXSEL_HIPKD);
// configure SSC with defaults
FpgaSetupSsc();
// first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT
LOW(GPIO_SSC_DOUT);
AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT;
AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT;
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
legic_mem = BigBuf_get_EM_addr();
// start trace
clear_trace();
set_tracing(true);
// init crc calculator
crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0);
// start 212kHz timer (running from SSP Clock)
StartCountSspClk();
}
// Setup reader to card connection
//
// The setup consists of a three way handshake:
// - Receive initialisation vector 7 bits
// - Transmit card type 6 bits
// - Receive Acknowledge 6 bits
static int32_t setup_phase(legic_card_select_t *p_card) {
uint8_t len = 0;
// init coordination timestamp
last_frame_end = GetCountSspClk();
// reset prng
legic_prng_init(0);
// wait for iv
int32_t iv = rx_frame(&len);
if ((len != 7) || (iv < 0)) {
return -1;
}
// configure prng
legic_prng_init(iv);
// reply with card type
switch (p_card->tagtype) {
case 0:
tx_frame(0x0D, 6);
break;
case 1:
tx_frame(0x1D, 6);
break;
case 2:
tx_frame(0x3D, 6);
break;
}
// wait for ack
int32_t ack = rx_frame(&len);
if ((len != 6) || (ack < 0)) {
return -1;
}
// validate data
switch (p_card->tagtype) {
case 0:
if (ack != 0x19) return -1;
break;
case 1:
if (ack != 0x39) return -1;
break;
case 2:
if (ack != 0x39) return -1;
break;
}
// During rx the prng is clocked using the variable reader period.
// Since rx_frame detects end of frame by detecting a code violation,
// the prng is off by one bit period after each rx phase. Hence, tx
// code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1).
// This is not possible for back to back rx, so this quirk reduces
// the gap by one period.
last_frame_end += TAG_BIT_PERIOD;
return 0;
}
static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) {
crc_clear(&legic_crc);
crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz);
return crc_finish(&legic_crc);
}
static int32_t connected_phase(legic_card_select_t *p_card) {
uint8_t len = 0;
// wait for command
int32_t cmd = rx_frame(&len);
if (cmd < 0) {
return -1;
}
// check if command is LEGIC_READ
if (len == p_card->cmdsize) {
// prepare data
uint8_t byte = legic_mem[cmd >> 1];
uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte);
// transmit data
tx_frame((crc << 8) | byte, 12);
return 0;
}
// check if command is LEGIC_WRITE
if (len == p_card->cmdsize + 8 + 4) {
// decode data
uint16_t mask = (1 << p_card->addrsize) - 1;
uint16_t addr = (cmd >> 1) & mask;
uint8_t byte = (cmd >> p_card->cmdsize) & 0xff;
uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf;
// check received against calculated crc
uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte);
if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1;
}
// store data
legic_mem[addr] = byte;
// transmit ack
tx_ack();
return 0;
}
return -1;
}
//-----------------------------------------------------------------------------
// Command Line Interface
//
// Only this function is public / called from appmain.c
//-----------------------------------------------------------------------------
void LegicRfSimulate(uint8_t cardtype) {
// configure ARM and FPGA
init_tag();
// verify command line input
if (init_card(cardtype, &card) != 0) {
DbpString("Unknown tagtype.");
goto OUT;
}
LED_A_ON();
DbpString("Starting Legic emulator, press button to end");
while (!BUTTON_PRESS() && !data_available()) {
WDT_HIT();
// wait for carrier, restart after timeout
if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) {
continue;
}
// wait for connection, restart on error
if (setup_phase(&card)) {
continue;
}
// conection is established, process commands until one fails
while (!connected_phase(&card)) {
WDT_HIT();
}
}
OUT:
DbpString("Stopped");
switch_off();
StopTicks();
}

19
armsrc/legicrfsim.h Normal file
View file

@ -0,0 +1,19 @@
//-----------------------------------------------------------------------------
// (c) 2009 Henryk Plötz <henryk@ploetzli.ch>
// 2018 AntiCat
//
// 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.
//-----------------------------------------------------------------------------
// LEGIC RF emulation public interface
//-----------------------------------------------------------------------------
#ifndef __LEGICRFSIM_H
#define __LEGICRFSIM_H
#include "proxmark3.h"
void LegicRfSimulate(uint8_t tagtype);
#endif /* __LEGICRFSIM_H */

File diff suppressed because it is too large Load diff

View file

@ -19,8 +19,8 @@ Default LF config is set to:
sample_config config = { 1, 8, 1, 95, 0 } ; sample_config config = { 1, 8, 1, 95, 0 } ;
void printConfig() { void printConfig() {
Dbprintf("LF Sampling config"); DbpString(_BLUE_("LF Sampling config"));
Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1)); Dbprintf(" [q] divisor.............%d ( "_GREEN_("%d kHz")")", config.divisor, 12000 / (config.divisor + 1));
Dbprintf(" [b] bps.................%d", config.bits_per_sample); Dbprintf(" [b] bps.................%d", config.bits_per_sample);
Dbprintf(" [d] decimation..........%d", config.decimation); Dbprintf(" [d] decimation..........%d", config.decimation);
Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No"); Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No");
@ -29,7 +29,7 @@ void printConfig() {
/** /**
* Called from the USB-handler to set the sampling configuration * Called from the USB-handler to set the sampling configuration
* The sampling config is used for std reading and snooping. * The sampling config is used for std reading and sniffing.
* *
* Other functions may read samples and ignore the sampling config, * Other functions may read samples and ignore the sampling config,
* such as functions to read the UID from a prox tag or similar. * such as functions to read the UID from a prox tag or similar.
@ -76,8 +76,8 @@ void pushBit( BitstreamOut* stream, uint8_t bit) {
/** /**
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
* if not already loaded, sets divisor and starts up the antenna. * if not already loaded, sets divisor and starts up the antenna.
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz * @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
* 0 or 95 ==> 125 KHz * 0 or 95 ==> 125 kHz
* *
**/ **/
void LFSetupFPGAForADC(int divisor, bool lf_field) { void LFSetupFPGAForADC(int divisor, bool lf_field) {
@ -117,35 +117,46 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) {
* @return the number of bits occupied by the samples. * @return the number of bits occupied by the samples.
*/ */
uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) { uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) {
//bigbuf, to hold the aquired raw data signal
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen();
if (bits_per_sample < 1) bits_per_sample = 1; if (bits_per_sample < 1) bits_per_sample = 1;
if (bits_per_sample > 8) bits_per_sample = 8; if (bits_per_sample > 8) bits_per_sample = 8;
if (decimation < 1) decimation = 1; if (decimation < 1) decimation = 1;
// Use a bit stream to handle the output // use a bit stream to handle the output
BitstreamOut data = { dest, 0, 0}; BitstreamOut data = { dest, 0, 0};
int sample_counter = 0; int sample_counter = 0;
uint8_t sample = 0; uint8_t sample;
//If we want to do averaging
// if we want to do averaging
uint32_t sample_sum = 0 ; uint32_t sample_sum = 0 ;
uint32_t sample_total_numbers = 0; uint32_t sample_total_numbers = 0;
uint32_t sample_total_saved = 0; uint32_t sample_total_saved = 0;
uint32_t cancel_counter = 0; uint32_t cancel_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { uint16_t checker = 0;
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { while (true) {
AT91C_BASE_SSC->SSC_THR = 0x43; if ( checker == 1000 ) {
LED_D_ON(); if (BUTTON_PRESS() || data_available())
break;
else
checker = 0;
} else {
++checker;
} }
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
// Testpoint 8 (TP8) can be used to trigger oscilliscope
LED_D_OFF(); LED_D_OFF();
// threshold either high or low values 128 = center 0. if trigger = 178 // 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 ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) {
if (cancel_after > 0) { if (cancel_after > 0) {
@ -162,24 +173,26 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
if (averaging) if (averaging)
sample_sum += sample; sample_sum += sample;
//Check decimation // check decimation
if (decimation > 1) { if (decimation > 1) {
sample_counter++; sample_counter++;
if (sample_counter < decimation) continue; if (sample_counter < decimation) continue;
sample_counter = 0; sample_counter = 0;
} }
//Averaging // averaging
if (averaging && decimation > 1) { if (averaging && decimation > 1) {
sample = sample_sum / decimation; sample = sample_sum / decimation;
sample_sum = 0; sample_sum = 0;
} }
//Store the sample // store the sample
sample_total_saved ++; sample_total_saved ++;
if (bits_per_sample == 8) { if (bits_per_sample == 8) {
dest[sample_total_saved - 1] = sample; dest[sample_total_saved - 1] = sample;
data.numbits = sample_total_saved << 3;//Get the return value correct
// Get the return value correct
data.numbits = sample_total_saved << 3;
if (sample_total_saved >= bufsize) break; if (sample_total_saved >= bufsize) break;
} else { } else {
@ -190,21 +203,21 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
if (bits_per_sample > 4) pushBit(&data, sample & 0x08); if (bits_per_sample > 4) pushBit(&data, sample & 0x08);
if (bits_per_sample > 5) pushBit(&data, sample & 0x04); if (bits_per_sample > 5) pushBit(&data, sample & 0x04);
if (bits_per_sample > 6) pushBit(&data, sample & 0x02); if (bits_per_sample > 6) pushBit(&data, sample & 0x02);
//Not needed, 8bps is covered above
//if (bits_per_sample > 7) pushBit(&data, sample & 0x01);
if ((data.numbits >> 3) + 1 >= bufsize) break; if ((data.numbits >> 3) + 1 >= bufsize) break;
} }
} }
} }
if (!silent) { if (!silent) {
Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample); Dbprintf("Done, saved " _YELLOW_("%d")"out of " _YELLOW_("%d")"seen samples at " _YELLOW_("%d")"bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample);
Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...",
dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]);
} }
// Ensure that noise check is performed for any device-side processing // Ensure that DC offset removal and noise check is performed for any device-side processing
justNoise(dest, bufsize); removeSignalOffset(dest, bufsize);
computeSignalProperties(dest, bufsize);
return data.numbits; return data.numbits;
} }
@ -237,28 +250,26 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) {
if (!silent) if (!silent)
printConfig(); printConfig();
LFSetupFPGAForADC(config.divisor, activeField); LFSetupFPGAForADC(config.divisor, activeField);
return DoAcquisition_config(silent, sample_size); uint32_t ret = DoAcquisition_config(silent, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
} }
/** /**
* Initializes the FPGA for reader-mode (field on), and acquires the samples. * Initializes the FPGA for reader-mode (field on), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SampleLF(bool printCfg, int sample_size) { uint32_t SampleLF(bool silent, int sample_size) {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(true, printCfg, sample_size); return ReadLF(true, silent, sample_size);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
} }
/** /**
* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * Initializes the FPGA for sniffer-mode (field off), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SnoopLF() { uint32_t SniffLF() {
BigBuf_Clear_ext(false); BigBuf_Clear_ext(false);
uint32_t ret = ReadLF(false, true, 0); return ReadLF(false, true, 0);
FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF);
return ret;
} }
/** /**
@ -277,18 +288,27 @@ void doT55x7Acquisition(size_t sample_size) {
if (bufsize > sample_size) if (bufsize > sample_size)
bufsize = sample_size; bufsize = sample_size;
uint8_t curSample = 0, lastSample = 0; uint8_t curSample, lastSample = 0;
uint16_t i = 0, skipCnt = 0; uint16_t i = 0, skipCnt = 0;
bool startFound = false; bool startFound = false;
bool highFound = false; bool highFound = false;
bool lowFound = false; bool lowFound = false;
while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { uint16_t checker = 0;
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { while ( skipCnt < 1000 && (i < bufsize)) {
AT91C_BASE_SSC->SSC_THR = 0x43; //43 if ( checker == 1000 ) {
LED_D_ON(); if (BUTTON_PRESS() || data_available())
break;
else
checker = 0;
} else {
++checker;
} }
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF(); LED_D_OFF();
@ -346,20 +366,26 @@ void doCotagAcquisition(size_t sample_size) {
bufsize = sample_size; bufsize = sample_size;
dest[0] = 0; dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint8_t sample, firsthigh = 0, firstlow = 0;
uint16_t i = 0; uint16_t i = 0;
uint16_t noise_counter = 0; uint16_t noise_counter = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { uint16_t checker = 0;
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { while ((i < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
AT91C_BASE_SSC->SSC_THR = 0x43; if ( checker == 1000 ) {
LED_D_ON(); if (BUTTON_PRESS() || data_available())
break;
else
checker = 0;
} else {
++checker;
} }
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
// find first peak // find first peak
if (!firsthigh) { if (!firsthigh) {
@ -400,21 +426,26 @@ uint32_t doCotagAcquisitionManchester() {
bufsize = COTAG_BITS; bufsize = COTAG_BITS;
dest[0] = 0; dest[0] = 0;
uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint8_t sample, firsthigh = 0, firstlow = 0;
uint16_t sample_counter = 0, period = 0; uint16_t sample_counter = 0, period = 0;
uint8_t curr = 0, prev = 0; uint8_t curr = 0, prev = 0;
uint16_t noise_counter = 0; uint16_t noise_counter = 0;
uint16_t checker = 0;
while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { while ((sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1))) {
WDT_HIT(); if ( checker == 1000 ) {
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { if (BUTTON_PRESS() || data_available())
AT91C_BASE_SSC->SSC_THR = 0x43; break;
LED_D_ON(); else
checker = 0;
} else {
++checker;
} }
WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR;
LED_D_OFF();
// find first peak // find first peak
if (!firsthigh) { if (!firsthigh) {
@ -439,12 +470,10 @@ uint32_t doCotagAcquisitionManchester() {
if (sample > COTAG_ONE_THRESHOLD) { if (sample > COTAG_ONE_THRESHOLD) {
prev = curr; prev = curr;
curr = 1; curr = 1;
} } else if (sample < COTAG_ZERO_THRESHOLD) {
else if ( sample < COTAG_ZERO_THRESHOLD) {
prev = curr; prev = curr;
curr = 0; curr = 0;
} } else {
else {
curr = prev; curr = prev;
} }

View file

@ -30,10 +30,10 @@ void doT55x7Acquisition(size_t sample_size);
uint32_t SampleLF(bool silent, int sample_size); uint32_t SampleLF(bool silent, int sample_size);
/** /**
* Initializes the FPGA for snoop-mode (field off), and acquires the samples. * Initializes the FPGA for sniff-mode (field off), and acquires the samples.
* @return number of bits sampled * @return number of bits sampled
**/ **/
uint32_t SnoopLF(); uint32_t SniffLF();
// adds sample size to default options // adds sample size to default options
uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after); uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after);
@ -59,15 +59,15 @@ uint32_t DoAcquisition_config(bool silent, int sample_size);
/** /**
* Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream
* if not already loaded, sets divisor and starts up the antenna. * if not already loaded, sets divisor and starts up the antenna.
* @param divisor : 1, 88> 255 or negative ==> 134.8 KHz * @param divisor : 1, 88> 255 or negative ==> 134.8 kHz
* 0 or 95 ==> 125 KHz * 0 or 95 ==> 125 kHz
* *
**/ **/
void LFSetupFPGAForADC(int divisor, bool lf_field); void LFSetupFPGAForADC(int divisor, bool lf_field);
/** /**
* Called from the USB-handler to set the sampling configuration * Called from the USB-handler to set the sampling configuration
* The sampling config is used for std reading and snooping. * The sampling config is used for std reading and sniffing.
* *
* Other functions may read samples and ignore the sampling config, * Other functions may read samples and ignore the sampling config,
* such as functions to read the UID from a prox tag or similar. * such as functions to read the UID from a prox tag or similar.

File diff suppressed because it is too large Load diff

View file

@ -17,7 +17,6 @@
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"

View file

@ -24,7 +24,7 @@ bool InitDesfireCard(){
set_tracing(true); set_tracing(true);
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card");
OnError(1); OnError(1);
return false; return false;
} }
@ -52,7 +52,7 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
uint8_t resp[RECEIVE_SIZE]; uint8_t resp[RECEIVE_SIZE];
memset(resp, 0, sizeof(resp)); memset(resp, 0, sizeof(resp));
if (MF_DBGLEVEL >= 4) { if (DBGLEVEL >= 4) {
Dbprintf(" flags : %02X", flags); Dbprintf(" flags : %02X", flags);
Dbprintf(" len : %02X", datalen); Dbprintf(" len : %02X", datalen);
print_result(" RX : ", datain, datalen); print_result(" RX : ", datain, datalen);
@ -67,7 +67,7 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
} }
int len = DesfireAPDU(datain, datalen, resp); int len = DesfireAPDU(datain, datalen, resp);
if (MF_DBGLEVEL >= 4) if (DBGLEVEL >= 4)
print_result("ERR <--: ", resp, len); print_result("ERR <--: ", resp, len);
if (!len) { if (!len) {
@ -81,15 +81,15 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
if (flags & DISCONNECT) if (flags & DISCONNECT)
OnSuccess(); OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len); reply_old(CMD_ACK, 1, len, 0, resp, len);
} }
void MifareDesfireGetInformation() { void MifareDesfireGetInformation() {
int len = 0; int len = 0;
iso14a_card_select_t card; iso14a_card_select_t card;
uint8_t resp[USB_CMD_DATA_SIZE] = {0x00}; uint8_t resp[PM3_CMD_DATA_SIZE] = {0x00};
uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00}; uint8_t dataout[PM3_CMD_DATA_SIZE] = {0x00};
/* /*
1 = PCB 1 1 = PCB 1
@ -106,13 +106,13 @@ void MifareDesfireGetInformation(){
// card select - information // card select - information
if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); if (DBGLEVEL >= DBG_ERROR) DbpString("Can't select card");
OnError(1); OnError(1);
return; return;
} }
if (card.uidlen != 7) { if (card.uidlen != 7) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen);
OnError(2); OnError(2);
return; return;
} }
@ -160,34 +160,32 @@ void MifareDesfireGetInformation(){
memcpy(dataout + 7 + 7 + 7, resp + 3, 14); memcpy(dataout + 7 + 7 + 7, resp + 3, 14);
cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); reply_old(CMD_ACK, 1, 0, 0, dataout, sizeof(dataout));
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
OnSuccess(); OnSuccess();
} }
void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){ void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) {
// mode = arg0
// algo = arg1
// keyno = arg2
int len = 0; int len = 0;
//uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47};
uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f }; uint8_t PICC_MASTER_KEY16[16] = { 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f };
uint8_t null_key_data8[8] = {0x00};
//uint8_t null_key_data16[16] = {0x00}; //uint8_t null_key_data16[16] = {0x00};
//uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
//uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF};
uint8_t resp[256] = {0x00}; uint8_t resp[256] = {0x00};
uint8_t IV[16] = {0x00};
size_t datalen = datain[0]; size_t datalen = datain[0];
uint8_t cmd[40] = {0x00}; uint8_t cmd[40] = {0x00};
uint8_t encRndB[16] = {0x00}; uint8_t encRndB[16] = {0x00};
uint8_t decRndB[16] = {0x00}; uint8_t decRndB[16] = {0x00};
uint8_t nonce[16] = {0x00};
uint8_t both[32] = {0x00}; uint8_t both[32] = {0x00};
uint8_t encBoth[32] = {0x00};
InitDesfireCard(); InitDesfireCard();
@ -195,26 +193,27 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
LED_B_OFF(); LED_B_OFF();
LED_C_OFF(); LED_C_OFF();
// 3 olika sätt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32)
// 4 olika crypto algo DES, 3DES, 3K3DES, AES // 4 different crypto arg1 DES, 3DES, 3K3DES, AES
// 3 olika kommunikations sätt, PLAIN,MAC,CRYPTO // 3 different communication modes, PLAIN,MAC,CRYPTO
// des, nyckel 0, // des, key 0,
switch (mode){ switch (arg0) {
case 1: { case 1: {
uint8_t keybytes[16]; uint8_t keybytes[16];
uint8_t RndA[8] = {0x00}; uint8_t RndA[8] = {0x00};
uint8_t RndB[8] = {0x00}; uint8_t RndB[8] = {0x00};
if (algo == 2) { if (arg1 == 2) {
if (datain[1] == 0xff) { if (datain[1] == 0xff) {
memcpy(keybytes, PICC_MASTER_KEY16, 16); memcpy(keybytes, PICC_MASTER_KEY16, 16);
} else { } else {
memcpy(keybytes, datain + 1, datalen); memcpy(keybytes, datain + 1, datalen);
} }
} else { } else {
if (algo == 1) { if (arg1 == 1) {
if (datain[1] == 0xff) { if (datain[1] == 0xff) {
uint8_t null_key_data8[8] = {0x00};
memcpy(keybytes, null_key_data8, 8); memcpy(keybytes, null_key_data8, 8);
} else { } else {
memcpy(keybytes, datain + 1, datalen); memcpy(keybytes, datain + 1, datalen);
@ -225,16 +224,16 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
struct desfire_key defaultkey = {0}; struct desfire_key defaultkey = {0};
desfirekey_t key = &defaultkey; desfirekey_t key = &defaultkey;
if (algo == 2) if (arg1 == 2)
Desfire_3des_key_new_with_version(keybytes, key); Desfire_3des_key_new_with_version(keybytes, key);
else if (algo ==1) else if (arg1 == 1)
Desfire_des_key_new(keybytes, key); Desfire_des_key_new(keybytes, key);
cmd[0] = AUTHENTICATE; cmd[0] = AUTHENTICATE;
cmd[1] = keyno; //keynumber cmd[1] = arg2; //keynumber
len = DesfireAPDU(cmd, 2, resp); len = DesfireAPDU(cmd, 2, resp);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
} }
OnError(3); OnError(3);
@ -249,9 +248,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
} }
memcpy(encRndB, resp + 3, 8); memcpy(encRndB, resp + 3, 8);
if (algo == 2) if (arg1 == 2)
tdes_dec(&decRndB, &encRndB, key->data); tdes_dec(&decRndB, &encRndB, key->data);
else if (algo == 1) else if (arg1 == 1)
des_dec(&decRndB, &encRndB, key->data); des_dec(&decRndB, &encRndB, key->data);
memcpy(RndB, decRndB, 8); memcpy(RndB, decRndB, 8);
@ -262,9 +261,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
memcpy(RndA, decRndA, 8); memcpy(RndA, decRndA, 8);
uint8_t encRndA[8] = {0x00}; uint8_t encRndA[8] = {0x00};
if (algo == 2) if (arg1 == 2)
tdes_dec(&encRndA, &decRndA, key->data); tdes_dec(&encRndA, &decRndA, key->data);
else if (algo == 1) else if (arg1 == 1)
des_dec(&encRndA, &decRndA, key->data); des_dec(&encRndA, &decRndA, key->data);
memcpy(both, encRndA, 8); memcpy(both, encRndA, 8);
@ -274,9 +273,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
} }
if (algo == 2) if (arg1 == 2)
tdes_dec(&encRndB, &decRndB, key->data); tdes_dec(&encRndB, &decRndB, key->data);
else if (algo == 1) else if (arg1 == 1)
des_dec(&encRndB, &decRndB, key->data); des_dec(&encRndB, &decRndB, key->data);
memcpy(both + 8, encRndB, 8); memcpy(both + 8, encRndB, 8);
@ -286,7 +285,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
len = DesfireAPDU(cmd, 17, resp); len = DesfireAPDU(cmd, 17, resp);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
} }
OnError(3); OnError(3);
@ -302,9 +301,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
memcpy(encRndA, resp + 3, 8); memcpy(encRndA, resp + 3, 8);
if (algo == 2) if (arg1 == 2)
tdes_dec(&encRndA, &encRndA, key->data); tdes_dec(&encRndA, &encRndA, key->data);
else if (algo == 1) else if (arg1 == 1)
des_dec(&encRndA, &encRndA, key->data); des_dec(&encRndA, &encRndA, key->data);
rol(decRndA, 8); rol(decRndA, 8);
@ -320,9 +319,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
/* /*
// Current key is a 3DES key, change it to a DES key // Current key is a 3DES key, change it to a DES key
if (algo == 2) { if (arg1 == 2) {
cmd[0] = CHANGE_KEY; cmd[0] = CHANGE_KEY;
cmd[1] = keyno; cmd[1] = arg2;
uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77};
@ -362,9 +361,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
} else { } else {
// Current key is a DES key, change it to a 3DES key // Current key is a DES key, change it to a 3DES key
if (algo == 1) { if (arg1 == 1) {
cmd[0] = CHANGE_KEY; cmd[0] = CHANGE_KEY;
cmd[1] = keyno; cmd[1] = arg2;
uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f};
@ -406,10 +405,10 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
*/ */
OnSuccess(); OnSuccess();
if (algo == 2) if (arg1 == 2)
cmd_send(CMD_ACK,1,0,0,skey->data,16); reply_old(CMD_ACK, 1, 0, 0, skey->data, 16);
else if (algo == 1) else if (arg1 == 1)
cmd_send(CMD_ACK,1,0,0,skey->data,8); reply_old(CMD_ACK, 1, 0, 0, skey->data, 8);
} else { } else {
DbpString("Authentication failed."); DbpString("Authentication failed.");
OnError(6); OnError(6);
@ -418,7 +417,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
} }
break; break;
case 2: case 2:
//SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); //SendDesfireCommand(AUTHENTICATE_ISO, &arg2, resp);
break; break;
case 3: { case 3: {
@ -435,8 +434,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
Desfire_aes_key_new(keybytes, key); Desfire_aes_key_new(keybytes, key);
AesCtx ctx; AesCtx ctx;
uint8_t IV[16] = {0x00};
if (AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0) { if (AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0) {
if( MF_DBGLEVEL >= 4) { if (DBGLEVEL >= 4) {
DbpString("AES context failed to init"); DbpString("AES context failed to init");
} }
OnError(7); OnError(7);
@ -447,7 +447,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
cmd[1] = 0x00; //keynumber cmd[1] = 0x00; //keynumber
len = DesfireAPDU(cmd, 2, resp); len = DesfireAPDU(cmd, 2, resp);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
} }
OnError(3); OnError(3);
@ -459,8 +459,10 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
// dekryptera tagnonce. // dekryptera tagnonce.
AesDecrypt(&ctx, encRndB, decRndB, 16); AesDecrypt(&ctx, encRndB, decRndB, 16);
rol(decRndB, 16); rol(decRndB, 16);
uint8_t nonce[16] = {0x00};
memcpy(both, nonce, 16); memcpy(both, nonce, 16);
memcpy(both + 16, decRndB, 16); memcpy(both + 16, decRndB, 16);
uint8_t encBoth[32] = {0x00};
AesEncrypt(&ctx, both, encBoth, 32); AesEncrypt(&ctx, both, encBoth, 32);
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
@ -468,7 +470,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33 len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) { if (DBGLEVEL >= DBG_ERROR) {
DbpString("Authentication failed. Card timeout."); DbpString("Authentication failed. Card timeout.");
} }
OnError(3); OnError(3);
@ -492,10 +494,10 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
} }
OnSuccess(); OnSuccess();
cmd_send(CMD_ACK,1,len,0,resp,len); reply_old(CMD_ACK, 1, len, 0, resp, len);
} }
// 3 olika ISO sätt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) // 3 different ISO ways to send data to a DESFIRE (direct, capsuled, capsuled ISO)
// cmd = cmd bytes to send // cmd = cmd bytes to send
// cmd_len = length of cmd // cmd_len = length of cmd
// dataout = pointer to response data array // dataout = pointer to response data array
@ -503,20 +505,20 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
size_t len = 0; size_t len = 0;
size_t wrappedLen = 0; size_t wrappedLen = 0;
uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00}; uint8_t wCmd[PM3_CMD_DATA_SIZE] = {0x00};
uint8_t resp[MAX_FRAME_SIZE]; uint8_t resp[MAX_FRAME_SIZE];
uint8_t par[MAX_PARITY_SIZE]; uint8_t par[MAX_PARITY_SIZE];
wrappedLen = CreateAPDU(cmd, cmd_len, wCmd); wrappedLen = CreateAPDU(cmd, cmd_len, wCmd);
if (MF_DBGLEVEL >= 4) if (DBGLEVEL >= 4)
print_result("WCMD <--: ", wCmd, wrappedLen); print_result("WCMD <--: ", wCmd, wrappedLen);
ReaderTransmit(wCmd, wrappedLen, NULL); ReaderTransmit(wCmd, wrappedLen, NULL);
len = ReaderReceive(resp, par); len = ReaderReceive(resp, par);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= 4) Dbprintf("fukked"); if (DBGLEVEL >= 4) Dbprintf("fukked");
return false; //DATA LINK ERROR return false; //DATA LINK ERROR
} }
// if we received an I- or R(ACK)-Block with a block number equal to the // if we received an I- or R(ACK)-Block with a block number equal to the
@ -524,8 +526,7 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
else if (len >= 4 // PCB+CID+CRC = 4 bytes else if (len >= 4 // PCB+CID+CRC = 4 bytes
&& ((resp[0] & 0xC0) == 0 // I-Block && ((resp[0] & 0xC0) == 0 // I-Block
|| (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0
&& (resp[0] & 0x01) == pcb_blocknum) // equal block numbers && (resp[0] & 0x01) == pcb_blocknum) { // equal block numbers
{
pcb_blocknum ^= 1; //toggle next block pcb_blocknum ^= 1; //toggle next block
} }
@ -536,12 +537,12 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){
// CreateAPDU // CreateAPDU
size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) { size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout) {
size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); size_t cmdlen = MIN(len + 4, PM3_CMD_DATA_SIZE - 1);
uint8_t cmd[cmdlen]; uint8_t cmd[cmdlen];
memset(cmd, 0, cmdlen); memset(cmd, 0, cmdlen);
cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Särskilda bitar // cmd[0] = 0x0A; // 0x0A = send cid, 0x02 = no cid.
cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[0] |= pcb_blocknum; // OR the block number into the PCB
cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards
@ -566,6 +567,6 @@ void OnSuccess(){
} }
void OnError(uint8_t reason) { void OnError(uint8_t reason) {
cmd_send(CMD_ACK,0,reason,0,0,0); reply_old(CMD_ACK, 0, reason, 0, 0, 0);
OnSuccess(); OnSuccess();
} }

View file

@ -6,7 +6,6 @@
#include "apps.h" #include "apps.h"
#include "string.h" #include "string.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "desfire_key.h" #include "desfire_key.h"
#include "mifareutil.h" #include "mifareutil.h"

1199
armsrc/mifaresim.c Normal file

File diff suppressed because it is too large Load diff

39
armsrc/mifaresim.h Normal file
View file

@ -0,0 +1,39 @@
//-----------------------------------------------------------------------------
// Merlok - June 2011, 2012
// Gerhard de Koning Gans - May 2008
// Hagen Fritsch - June 2010
//
// 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.
//-----------------------------------------------------------------------------
// Mifare Classic Card Simulation
//-----------------------------------------------------------------------------
#ifndef __MIFARESIM_H
#define __MIFARESIM_H
#include <stdint.h>
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
void Mifare1ksim(uint16_t flags, uint8_t exitAfterNReads, uint8_t *datain);
#define AC_DATA_READ 0
#define AC_DATA_WRITE 1
#define AC_DATA_INC 2
#define AC_DATA_DEC_TRANS_REST 3
#define AC_KEYA_READ 0
#define AC_KEYA_WRITE 1
#define AC_KEYB_READ 2
#define AC_KEYB_WRITE 3
#define AC_AC_READ 4
#define AC_AC_WRITE 5
#define AUTHKEYA 0
#define AUTHKEYB 1
#define AUTHKEYNONE 0xff
#endif

View file

@ -10,6 +10,10 @@
#include "mifaresniff.h" #include "mifaresniff.h"
#ifndef CheckCrc14A
# define CheckCrc14A(data, len) check_crc(CRC_14443_A, (data), (len))
#endif
//static int sniffState = SNF_INIT; //static int sniffState = SNF_INIT;
static uint8_t sniffUIDType = 0; static uint8_t sniffUIDType = 0;
static uint8_t sniffUID[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; static uint8_t sniffUID[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
@ -35,7 +39,8 @@ void RAMFUNC SniffMifare(uint8_t param) {
// Allocate memory from BigBuf for some buffers // Allocate memory from BigBuf for some buffers
// free all previous allocations first // free all previous allocations first
BigBuf_free(); BigBuf_Clear_ext(false); BigBuf_free();
BigBuf_Clear_ext(false);
clear_trace(); clear_trace();
set_tracing(true); set_tracing(true);
@ -51,8 +56,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE);
uint8_t *data = dmaBuf; uint8_t *data = dmaBuf;
uint8_t previous_data = 0; uint8_t previous_data = 0;
int maxDataLen = 0; int dataLen, maxDataLen = 0;
int dataLen = 0;
bool ReaderIsActive = false; bool ReaderIsActive = false;
bool TagIsActive = false; bool TagIsActive = false;
@ -72,7 +76,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// Setup and start DMA. // Setup and start DMA.
// set transfer address and number of bytes. Start transfer. // set transfer address and number of bytes. Start transfer.
if (!FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE)) { if (!FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE)) {
if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); if (DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting");
return; return;
} }
@ -186,7 +190,7 @@ void MfSniffInit(void){
void MfSniffEnd(void) { void MfSniffEnd(void) {
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK,0,0,0,0,0); reply_old(CMD_ACK, 0, 0, 0, 0, 0);
LED_B_OFF(); LED_B_OFF();
} }
@ -228,7 +232,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
if ( !reader ) break; if ( !reader ) break;
if ( len != 9 ) break; if ( len != 9 ) break;
if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; if ( !CheckCrc14A(data, 9)) break;
if ( data[1] != 0x70 ) break; if ( data[1] != 0x70 ) break;
Dbprintf("[!] UID | %x", data[0]); Dbprintf("[!] UID | %x", data[0]);
@ -265,7 +269,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
} }
case SNF_SAK:{ case SNF_SAK:{
// SAK from card? // SAK from card?
if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { if ((!reader) && (len == 3) && (CheckCrc14A(data, 3))) {
sniffSAK = data[0]; sniffSAK = data[0];
// CL2 UID part to be expected // CL2 UID part to be expected
if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) {
@ -306,19 +310,18 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui
void RAMFUNC MfSniffSend() { void RAMFUNC MfSniffSend() {
uint16_t tracelen = BigBuf_get_traceLen(); uint16_t tracelen = BigBuf_get_traceLen();
uint16_t chunksize = 0;
int packlen = tracelen; // total number of bytes to send int packlen = tracelen; // total number of bytes to send
uint8_t *data = BigBuf_get_addr(); uint8_t *data = BigBuf_get_addr();
while (packlen > 0) { while (packlen > 0) {
LED_B_ON(); LED_B_ON();
chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 uint16_t chunksize = MIN(PM3_CMD_DATA_SIZE, packlen); // chunk size 512
cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); reply_old(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize);
packlen -= chunksize; packlen -= chunksize;
LED_B_OFF(); LED_B_OFF();
} }
LED_B_ON(); LED_B_ON();
cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. reply_old(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished.
LED_B_OFF(); LED_B_OFF();
} }

View file

@ -15,7 +15,6 @@
#include "apps.h" #include "apps.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "mifareutil.h" #include "mifareutil.h"

View file

@ -1,4 +1,3 @@
//-----------------------------------------------------------------------------
// Merlok, May 2011, 2012 // Merlok, May 2011, 2012
// Many authors, whom made it possible // Many authors, whom made it possible
// //
@ -10,17 +9,15 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "mifareutil.h" #include "mifareutil.h"
int MF_DBGLEVEL = MF_DBG_ERROR; int DBGLEVEL = DBG_ERROR;
// crypto1 helpers // crypto1 helpers
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out) { void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out) {
uint8_t bt = 0;
int i;
if (len != 1) { if (len != 1) {
for (i = 0; i < len; i++) for (int i = 0; i < len; i++)
data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i];
} else { } else {
uint8_t bt = 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0; bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1; bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1;
bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2; bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2;
@ -35,13 +32,16 @@ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){
} }
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) {
uint8_t bt = 0; mf_crypto1_encryptEx(pcs, data, NULL, data, len, par);
}
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par) {
int i; int i;
par[0] = 0; par[0] = 0;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
bt = data[i]; uint8_t bt = data_in[i];
data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; data_out[i] = crypto1_byte(pcs, keystream ? keystream[i] : 0x00, 0) ^ data_in[i];
if ((i & 0x0007) == 0) if ((i & 0x0007) == 0)
par[ i >> 3 ] = 0; par[ i >> 3 ] = 0;
par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01) << (7 - (i & 0x0007))); par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01) << (7 - (i & 0x0007)));
@ -66,7 +66,7 @@ int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answe
ReaderTransmit(dcmd, sizeof(dcmd), timing); ReaderTransmit(dcmd, sizeof(dcmd), timing);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); if (DBGLEVEL >= DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd);
len = ReaderReceive(answer, answer_parity); len = ReaderReceive(answer, answer_parity);
} }
return len; return len;
@ -74,7 +74,7 @@ int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answe
// send 2 byte commands // send 2 byte commands
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
uint16_t pos, res; uint16_t pos;
uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; uint8_t dcmd[4] = {cmd, data, 0x00, 0x00};
uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00};
uint8_t par[1] = {0x00}; // 1 Byte parity is enough here uint8_t par[1] = {0x00}; // 1 Byte parity is enough here
@ -98,7 +98,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
if (crypted == CRYPT_ALL) { if (crypted == CRYPT_ALL) {
if (len == 1) { if (len == 1) {
res = 0; uint16_t res = 0;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1;
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2;
@ -152,7 +152,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
} }
// some statistic // some statistic
if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) if (!ntptr && (DBGLEVEL >= DBG_EXTENDED))
Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt);
// save Nt // save Nt
@ -182,14 +182,14 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
// Receive 4 byte tag answer // Receive 4 byte tag answer
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout.");
return 2; return 2;
} }
ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0); ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0, 0);
if (ntpp != bytes_to_num(receivedAnswer, 4)) { if (ntpp != bytes_to_num(receivedAnswer, 4)) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Authentication failed. Error card response.");
return 3; return 3;
} }
return 0; return 0;
@ -204,18 +204,18 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
if (len != 18) { if (len != 18) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len);
return 2; return 2;
} }
memcpy(bt, receivedAnswer + 16, 2); memcpy(bt, receivedAnswer + 16, 2);
AddCrc14A(receivedAnswer, 16); AddCrc14A(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); if (DBGLEVEL >= DBG_INFO) Dbprintf("Cmd CRC response error.");
return 3; return 3;
} }
@ -232,17 +232,17 @@ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){
uint8_t key[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t key[4] = {0x00, 0x00, 0x00, 0x00};
memcpy(key, keybytes, 4); memcpy(key, keybytes, 4);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]);
len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL);
if (len != 4) { if (len != 4) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len);
return 0; return 0;
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) if (DBGLEVEL >= DBG_EXTENDED)
Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]); Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0], resp[1], resp[2], resp[3]);
memcpy(pack, resp, 4); memcpy(pack, resp, 4);
@ -267,7 +267,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
// REQUEST AUTHENTICATION // REQUEST AUTHENTICATION
len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar, NULL); len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar, NULL);
if (len != 11) { if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0; return 0;
} }
@ -280,7 +280,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
memcpy(rnd_ab, random_a, 8); memcpy(rnd_ab, random_a, 8);
memcpy(rnd_ab + 8, random_b, 8); memcpy(rnd_ab + 8, random_b, 8);
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x",
enc_random_b[0], enc_random_b[1], enc_random_b[2], enc_random_b[3], enc_random_b[4], enc_random_b[5], enc_random_b[6], enc_random_b[7]); enc_random_b[0], enc_random_b[1], enc_random_b[2], enc_random_b[3], enc_random_b[4], enc_random_b[5], enc_random_b[6], enc_random_b[7]);
@ -299,7 +299,7 @@ int mifare_ultra_auth(uint8_t *keybytes){
len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL);
if (len != 11) { if (len != 11) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]);
return 0; return 0;
} }
@ -310,11 +310,11 @@ int mifare_ultra_auth(uint8_t *keybytes){
// decrypt out, in, length, key, iv // decrypt out, in, length, key, iv
tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b);
if (memcmp(resp_random_a, random_a, 8) != 0) { if (memcmp(resp_random_a, random_a, 8) != 0) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); if (DBGLEVEL >= DBG_ERROR) Dbprintf("failed authentication");
return 0; return 0;
} }
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3], rnd_ab[0], rnd_ab[1], rnd_ab[2], rnd_ab[3],
rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]); rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
@ -342,22 +342,22 @@ int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) {
len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
if (len != 18) { if (len != 18) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len);
return 2; return 2;
} }
memcpy(bt, receivedAnswer + 16, 2); memcpy(bt, receivedAnswer + 16, 2);
AddCrc14A(receivedAnswer, 16); AddCrc14A(receivedAnswer, 16);
if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd CRC response error.");
return 3; return 3;
} }
memcpy(blockData, receivedAnswer, 14); memcpy(blockData, receivedAnswer, 16);
return 0; return 0;
} }
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) {
@ -384,7 +384,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
uint16_t len = 0; uint16_t len = 0;
uint32_t pos = 0; uint32_t pos = 0;
uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send
byte_t res = 0; uint8_t res = 0;
uint8_t d_block[18], d_block_enc[18]; uint8_t d_block[18], d_block_enc[18];
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
@ -394,7 +394,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
@ -419,7 +419,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3;
if ((len != 1) || (res != 0x0A)) { if ((len != 1) || (res != 0x0A)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res);
return 2; return 2;
} }
return 0; return 0;
@ -436,7 +436,7 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
@ -449,7 +449,7 @@ int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) {
len = ReaderReceive(receivedAnswer, receivedAnswerPar); len = ReaderReceive(receivedAnswer, receivedAnswerPar);
if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len);
return 2; return 2;
} }
@ -469,7 +469,7 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd(MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL);
if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len); Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0], len);
return 1; return 1;
} }
@ -479,7 +479,7 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs) {
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) { if (len != 0) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
return 1; return 1;
} }
return 0; return 0;
@ -493,7 +493,7 @@ int mifare_ultra_halt() {
uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00};
len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL);
if (len != 0) { if (len != 0) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len);
return 1; return 1;
} }
return 0; return 0;
@ -529,9 +529,9 @@ void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
memcpy(data, emCARD + blockNum * 16, blocksCount * 16); memcpy(data, emCARD + blockNum * 16, blocksCount * 16);
} }
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { void emlGetMemBt(uint8_t *data, int offset, int byteCount) {
uint8_t *emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(data, emCARD + bytePtr, byteCount); memcpy(data, emCARD + offset, byteCount);
} }
int emlCheckValBl(int blockNum) { int emlCheckValBl(int blockNum) {
@ -592,7 +592,7 @@ void emlClearMem(void) {
memset(emCARD, 0, CARD_MEMORY_SIZE); memset(emCARD, 0, CARD_MEMORY_SIZE);
// fill sectors trailer data // fill sectors trailer data
for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) for (uint16_t b = 3; b <= MIFARE_4K_MAXBLOCK; ((b <= MIFARE_2K_MAXBLOCK) ? (b += 4) : (b += 16)))
emlSetMem((uint8_t *)trailer, b, 1); emlSetMem((uint8_t *)trailer, b, 1);
// uid // uid
@ -600,6 +600,19 @@ void emlClearMem(void) {
return; return;
} }
uint8_t SectorTrailer(uint8_t blockNo) {
if (blockNo <= MIFARE_2K_MAXBLOCK) {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x03));
return (blockNo | 0x03);
} else {
if (DBGLEVEL >= DBG_EXTENDED) Dbprintf("Sector Trailer for block %d : %d", blockNo, (blockNo | 0x0f));
return (blockNo | 0x0f);
}
}
bool IsSectorTrailer(uint8_t blockNo) {
return (blockNo == SectorTrailer(blockNo));
}
// Mifare desfire commands // Mifare desfire commands
int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
@ -609,7 +622,7 @@ int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cm
ReaderTransmit(dcmd, sizeof(dcmd), NULL); ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1; return 1;
} }
return len; return len;
@ -624,7 +637,7 @@ int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t c
ReaderTransmit(dcmd, sizeof(dcmd), NULL); ReaderTransmit(dcmd, sizeof(dcmd), NULL);
int len = ReaderReceive(answer, answer_parity); int len = ReaderReceive(answer, answer_parity);
if (!len) { if (!len) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); if (DBGLEVEL >= DBG_ERROR) Dbprintf("Authentication failed. Card timeout.");
return 1; return 1;
} }
return len; return len;
@ -640,13 +653,13 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer, receivedAnswerPar, NULL);
if (len == 1) { if (len == 1) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Cmd Error: %02x", receivedAnswer[0]); Dbprintf("Cmd Error: %02x", receivedAnswer[0]);
return 1; return 1;
} }
if (len == 12) { if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4], receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9], receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],
@ -670,13 +683,13 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){
len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL); len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar, NULL);
if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) {
if (MF_DBGLEVEL >= MF_DBG_ERROR) if (DBGLEVEL >= DBG_ERROR)
Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]);
return 1; return 1;
} }
if (len == 12) { if (len == 12) {
if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { if (DBGLEVEL >= DBG_EXTENDED) {
Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4], receivedAnswer[0], receivedAnswer[1], receivedAnswer[2], receivedAnswer[3], receivedAnswer[4],
receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9], receivedAnswer[5], receivedAnswer[6], receivedAnswer[7], receivedAnswer[8], receivedAnswer[9],

View file

@ -17,11 +17,9 @@
#include "parity.h" #include "parity.h"
#include "util.h" #include "util.h"
#include "string.h" #include "string.h"
#include "iso14443crc.h"
#include "iso14443a.h" #include "iso14443a.h"
#include "crapto1/crapto1.h" #include "crapto1/crapto1.h"
#include "des.h" #include "des.h"
#include "random.h" // fast_prand, prand
// mifare authentication // mifare authentication
#define CRYPT_NONE 0 #define CRYPT_NONE 0
@ -33,30 +31,38 @@
#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation)
#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication #define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication
// mifare 4bit card answers // reader voltage field detector
#define CARD_ACK 0x0A // 1010 - ACK #define MF_MINFIELDV 4000
#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed)
#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error
// Mifare 4k/2k/1k/mini Max Block / Max Sector
#define MIFARE_4K_MAXBLOCK 256
#define MIFARE_2K_MAXBLOCK 128
#define MIFARE_1K_MAXBLOCK 64
#define MIFARE_MINI_MAXBLOCK 20
#define MIFARE_MINI_MAXSECTOR 5
#define MIFARE_1K_MAXSECTOR 16
#define MIFARE_2K_MAXSECTOR 32
#define MIFARE_4K_MAXSECTOR 40
//mifare emulator states //mifare emulator states
#define MFEMUL_NOFIELD 0 #define MFEMUL_NOFIELD 0
#define MFEMUL_IDLE 1 #define MFEMUL_IDLE 1
#define MFEMUL_SELECT1 2 #define MFEMUL_SELECT 2
#define MFEMUL_SELECT2 3 #define MFEMUL_AUTH1 3
#define MFEMUL_SELECT3 4 #define MFEMUL_WORK 4
#define MFEMUL_AUTH1 5 #define MFEMUL_WRITEBL2 5
#define MFEMUL_AUTH2 6 #define MFEMUL_INTREG_INC 6
#define MFEMUL_WORK 7 #define MFEMUL_INTREG_DEC 7
#define MFEMUL_WRITEBL2 8 #define MFEMUL_INTREG_REST 8
#define MFEMUL_INTREG_INC 9 #define MFEMUL_HALTED 9
#define MFEMUL_INTREG_DEC 10
#define MFEMUL_INTREG_REST 11
#define MFEMUL_HALTED 12
#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); #define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF();
#ifndef MifareBlockToSector
#define MifareBlockToSector(block) (block < 128 ? block / 4 : (block - 128) / 16 + 32)
#endif
//functions //functions
int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
@ -70,8 +76,8 @@ int mifare_classic_halt_ex(struct Crypto1State *pcs);
int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
// Ultralight/NTAG... // Ultralight/NTAG...
int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack);
int mifare_ultra_auth(uint8_t *key); int mifare_ultra_auth(uint8_t *keybytes);
int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData);
//int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData); //int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData);
int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData);
@ -84,21 +90,25 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData);
int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData);
// crypto functions // crypto functions
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len);
void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out); void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out);
void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par);
void mf_crypto1_encryptEx(struct Crypto1State *pcs, uint8_t *data_in, uint8_t *keystream, uint8_t *data_out, uint16_t len, uint8_t *par);
uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data);
// Mifare memory structure // Mifare memory structure
uint8_t NumBlocksPerSector(uint8_t sectorNo); uint8_t NumBlocksPerSector(uint8_t sectorNo);
uint8_t FirstBlockOfSector(uint8_t sectorNo); uint8_t FirstBlockOfSector(uint8_t sectorNo);
bool IsSectorTrailer(uint8_t blockNo);
uint8_t SectorTrailer(uint8_t blockNo);
// emulator functions // emulator functions
void emlClearMem(void); void emlClearMem(void);
void emlSetMem(uint8_t *data, int blockNum, int blocksCount); void emlSetMem(uint8_t *data, int blockNum, int blocksCount);
void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); void emlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth);
void emlGetMem(uint8_t *data, int blockNum, int blocksCount); void emlGetMem(uint8_t *data, int blockNum, int blocksCount);
void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount); void emlGetMemBt(uint8_t *data, int offset, int byteCount);
uint64_t emlGetKey(int sectorNum, int keyType); uint64_t emlGetKey(int sectorNum, int keyType);
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum);
int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum);

View file

@ -22,7 +22,7 @@
* *
* This is free software: you can redistribute it and/or modify * This is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as published * it under the terms of the GNU General Public License version 2 as published
* by the Free Software Foundation. * by the Free Software Foundation, or, at your option, any later version.
* *
* This file is distributed in the hope that it will be useful, * This file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -111,9 +111,8 @@ void opt_successor(const uint8_t* k, State *s, bool y, State* successor) {
void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes) { void opt_suc(const uint8_t *k, State *s, uint8_t *in, uint8_t length, bool add32Zeroes) {
State x2; State x2;
int i; for (int i = 0; i < length; i++) {
uint8_t head = 0; uint8_t head;
for (i = 0; i < length; i++) {
head = 1 & (in[i] >> 7); head = 1 & (in[i] >> 7);
opt_successor(k, s, head, &x2); opt_successor(k, s, head, &x2);
@ -141,7 +140,7 @@ void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Z
//For tag MAC, an additional 32 zeroes //For tag MAC, an additional 32 zeroes
if (add32Zeroes) { if (add32Zeroes) {
for (i = 0; i < 16; i++) { for (int i = 0; i < 16; i++) {
opt_successor(k, s, 0, &x2); opt_successor(k, s, 0, &x2);
opt_successor(k, &x2, 0, s); opt_successor(k, &x2, 0, s);
} }
@ -149,11 +148,9 @@ void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Z
} }
void opt_output(const uint8_t *k, State *s, uint8_t *buffer) { void opt_output(const uint8_t *k, State *s, uint8_t *buffer) {
uint8_t times = 0;
uint8_t bout = 0;
State temp = {0, 0, 0, 0}; State temp = {0, 0, 0, 0};
for ( ; times < 4; times++) { for (uint8_t times = 0; times < 4; times++) {
bout =0; uint8_t bout = 0;
bout |= (s->r & 0x4) << 5; bout |= (s->r & 0x4) << 5;
opt_successor(k, s, 0, &temp); opt_successor(k, s, 0, &temp);
bout |= (temp.r & 0x4) << 4; bout |= (temp.r & 0x4) << 4;

View file

@ -3,8 +3,7 @@
#define T0_PCF 8 //period for the pcf7931 in us #define T0_PCF 8 //period for the pcf7931 in us
#define ALLOC 16 #define ALLOC 16
int DemodPCF7931(uint8_t **outBlocks) { size_t DemodPCF7931(uint8_t **outBlocks) {
uint8_t bits[256] = {0x00}; uint8_t bits[256] = {0x00};
uint8_t blocks[8][16]; uint8_t blocks[8][16];
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
@ -13,25 +12,19 @@ int DemodPCF7931(uint8_t **outBlocks) {
if (GraphTraceLen > 18000) if (GraphTraceLen > 18000)
GraphTraceLen = 18000; GraphTraceLen = 18000;
int i, j, lastval, bitidx, half_switch; int i = 2, j, lastval, bitidx, half_switch;
int clock = 64; int clock = 64;
int tolerance = clock / 8; int tolerance = clock / 8;
int pmc, block_done; int pmc, block_done;
int lc, warnings = 0; int lc, warnings = 0;
int num_blocks = 0; size_t num_blocks = 0;
int lmin=128, lmax=128; int lmin = 64, lmax = 192;
uint8_t dir; uint8_t dir;
//clear read buffer
BigBuf_Clear_keep_EM();
BigBuf_Clear_keep_EM();
LFSetupFPGAForADC(95, true); LFSetupFPGAForADC(95, true);
DoAcquisition_default(0, true); DoAcquisition_default(0, true);
lmin = 64;
lmax = 192;
i = 2;
/* Find first local max/min */ /* Find first local max/min */
if (dest[1] > dest[0]) { if (dest[1] > dest[0]) {
while (i < GraphTraceLen) { while (i < GraphTraceLen) {
@ -40,8 +33,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
i++; i++;
} }
dir = 0; dir = 0;
} } else {
else {
while (i < GraphTraceLen) { while (i < GraphTraceLen) {
if (!(dest[i] < dest[i - 1]) && dest[i] < lmin) if (!(dest[i] < dest[i - 1]) && dest[i] < lmin)
break; break;
@ -55,10 +47,8 @@ int DemodPCF7931(uint8_t **outBlocks) {
pmc = 0; pmc = 0;
block_done = 0; block_done = 0;
for (bitidx = 0; i < GraphTraceLen; i++) for (bitidx = 0; i < GraphTraceLen; i++) {
{ if ((dest[i - 1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i - 1] < dest[i] && dir == 0 && dest[i] < lmin)) {
if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin))
{
lc = i - lastval; lc = i - lastval;
lastval = i; lastval = i;
@ -72,8 +62,7 @@ int DemodPCF7931(uint8_t **outBlocks) {
lastval = i; lastval = i;
pmc = 0; pmc = 0;
block_done = 1; block_done = 1;
} } else {
else {
pmc = i; pmc = i;
} }
} else if (ABS(lc - clock / 2) < tolerance) { } else if (ABS(lc - clock / 2) < tolerance) {
@ -84,38 +73,35 @@ int DemodPCF7931(uint8_t **outBlocks) {
lastval = i; lastval = i;
pmc = 0; pmc = 0;
block_done = 1; block_done = 1;
} } else if (half_switch == 1) {
else if(half_switch == 1) {
bits[bitidx++] = 0; bits[bitidx++] = 0;
half_switch = 0; half_switch = 0;
} } else
else
half_switch++; half_switch++;
} else if (ABS(lc - clock) < tolerance) { } else if (ABS(lc - clock) < tolerance) {
// 64TO // 64TO
bits[bitidx++] = 1; bits[bitidx++] = 1;
} else { } else {
// Error // Error
warnings++; if (++warnings > 10) {
if (warnings > 10) Dbprintf("Error: too many detection errors, aborting.");
{
Dbprintf("Error: too many detection errors, aborting...");
return 0; return 0;
} }
} }
if (block_done == 1) { if (block_done == 1) {
if (bitidx == 128) { if (bitidx == 128) {
for(j=0; j<16; j++) { for (j = 0; j < 16; ++j) {
blocks[num_blocks][j] = 128*bits[j*8+7]+ blocks[num_blocks][j] =
128 * bits[j * 8 + 7] +
64 * bits[j * 8 + 6] + 64 * bits[j * 8 + 6] +
32 * bits[j * 8 + 5] + 32 * bits[j * 8 + 5] +
16 * bits[j * 8 + 4] + 16 * bits[j * 8 + 4] +
8 * bits[j * 8 + 3] + 8 * bits[j * 8 + 3] +
4 * bits[j * 8 + 2] + 4 * bits[j * 8 + 2] +
2 * bits[j * 8 + 1] + 2 * bits[j * 8 + 1] +
bits[j*8]; bits[j * 8]
;
} }
num_blocks++; num_blocks++;
} }
@ -135,185 +121,210 @@ int DemodPCF7931(uint8_t **outBlocks) {
return num_blocks; return num_blocks;
} }
int IsBlock0PCF7931(uint8_t *Block) { bool IsBlock0PCF7931(uint8_t *block) {
// Assume RFU means 0 :) // assuming all RFU bits are set to 0
if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled // if PAC is enabled password is set to 0
return 1; if (block[7] == 0x01) {
if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ? if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return 1; return true;
return 0; } else if (block[7] == 0x00) {
if (!memcmp(block + 9, "\x00\x00\x00\x00\x00\x00\x00", 7))
return true;
}
return false;
} }
int IsBlock1PCF7931(uint8_t *Block) { bool IsBlock1PCF7931(uint8_t *block) {
// Assume RFU means 0 :) // assuming all RFU bits are set to 0
if( Block[10] == 0 && if (block[10] == 0
Block[11] == 0 && && block[11] == 0
Block[12] == 0 && && block[12] == 0
Block[13] == 0) && block[13] == 0) {
if ( (Block[14] & 0x7f) <= 9 && Block[15] <= 9)
return 1; if ((block[14] & 0x7f) <= 9
return 0; && block[15] <= 9) {
return true;
}
}
return false;
} }
void ReadPCF7931() { void ReadPCF7931() {
uint8_t Blocks[8][17]; int found_blocks = 0; // successfully read blocks
uint8_t tmpBlocks[4][16]; int max_blocks = 8; // readable blocks
int i, j, ind, ind2, n; uint8_t memory_blocks[8][17]; // PCF content
int num_blocks = 0; uint8_t single_blocks[8][17]; // PFC blocks with unknown position
int max_blocks = 8; int single_blocks_cnt = 0;
int ident = 0;
int error = 0;
int tries = 0;
memset(Blocks, 0, 8*17*sizeof(uint8_t)); size_t n = 0; // transmitted blocks
uint8_t tmp_blocks[4][16]; // temporary read buffer
uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found
int errors = 0; // error counter
int tries = 0; // tries counter
memset(memory_blocks, 0, 8 * 17 * sizeof(uint8_t));
memset(single_blocks, 0, 8 * 17 * sizeof(uint8_t));
int i = 0, j = 0;
do { do {
memset(tmpBlocks, 0, 4*16*sizeof(uint8_t)); i = 0;
n = DemodPCF7931((uint8_t**)tmpBlocks);
memset(tmp_blocks, 0, 4 * 16 * sizeof(uint8_t));
n = DemodPCF7931((uint8_t **)tmp_blocks);
if (!n) if (!n)
error++; ++errors;
if(error==10 && num_blocks == 0) {
// exit if no block is received
if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) {
Dbprintf("Error, no tag or bad tag"); Dbprintf("Error, no tag or bad tag");
return; return;
} }
else if (tries==20 || error==10) { // exit if too many errors during reading
if (tries > 50 && (2 * errors > tries)) {
Dbprintf("Error reading the tag"); Dbprintf("Error reading the tag");
Dbprintf("Here is the partial content"); Dbprintf("Here is the partial content");
goto end; goto end;
} }
for(i=0; i<n; i++) // our logic breaks if we don't get at least two blocks
Dbprintf("(dbg) %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", if (n < 2) {
tmpBlocks[i][0], tmpBlocks[i][1], tmpBlocks[i][2], tmpBlocks[i][3], tmpBlocks[i][4], tmpBlocks[i][5], tmpBlocks[i][6], tmpBlocks[i][7], if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16))
tmpBlocks[i][8], tmpBlocks[i][9], tmpBlocks[i][10], tmpBlocks[i][11], tmpBlocks[i][12], tmpBlocks[i][13], tmpBlocks[i][14], tmpBlocks[i][15]); continue;
if(!ident) {
for(i=0; i<n; i++) { if (single_blocks_cnt < max_blocks) {
if(IsBlock0PCF7931(tmpBlocks[i])) { for (i = 0; i < single_blocks_cnt; ++i) {
// Found block 0 ? if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) {
if(i < n-1 && IsBlock1PCF7931(tmpBlocks[i+1])) { j = 1;
// Found block 1!
// \o/
ident = 1;
memcpy(Blocks[0], tmpBlocks[i], 16);
Blocks[0][ALLOC] = 1;
memcpy(Blocks[1], tmpBlocks[i+1], 16);
Blocks[1][ALLOC] = 1;
max_blocks = MAX((Blocks[1][14] & 0x7f), Blocks[1][15]) + 1;
// Debug print
Dbprintf("(dbg) Max blocks: %d", max_blocks);
num_blocks = 2;
// Handle following blocks
for(j=i+2, ind2=2; j!=i; j++, ind2++, num_blocks++) {
if(j==n) j=0;
if(j==i) break;
memcpy(Blocks[ind2], tmpBlocks[j], 16);
Blocks[ind2][ALLOC] = 1;
}
break; break;
} }
} }
if (j != 1) {
memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16);
single_blocks_cnt++;
} }
j = 0;
} }
else { ++tries;
for(i=0; i<n; i++) { // Look for identical block in known blocks continue;
if(memcmp(tmpBlocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { // Block is not full of 00
for(j=0; j<max_blocks; j++) {
if(Blocks[j][ALLOC] == 1 && !memcmp(tmpBlocks[i], Blocks[j], 16)) {
// Found an identical block
for(ind=i-1,ind2=j-1; ind >= 0; ind--,ind2--) {
if(ind2 < 0)
ind2 = max_blocks;
if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found
// Dbprintf("Tmp %d -> Block %d", ind, ind2);
memcpy(Blocks[ind2], tmpBlocks[ind], 16);
Blocks[ind2][ALLOC] = 1;
num_blocks++;
if(num_blocks == max_blocks) goto end;
} }
Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors);
i = 0;
if (!found_0_1) {
while (i < n - 1) {
if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i + 1])) {
found_0_1 = 1;
memcpy(memory_blocks[0], tmp_blocks[i], 16);
memcpy(memory_blocks[1], tmp_blocks[i + 1], 16);
memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1;
// block 1 tells how many blocks are going to be sent
max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1;
found_blocks = 2;
Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks);
// handle the following blocks
for (j = i + 2; j < n; ++j) {
memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16);
memory_blocks[found_blocks][ALLOC] = 1;
++found_blocks;
} }
for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) { break;
if(ind2 > max_blocks) }
ind2 = 0; ++i;
if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found }
// Dbprintf("Tmp %d -> Block %d", ind, ind2); } else {
memcpy(Blocks[ind2], tmpBlocks[ind], 16); // Trying to re-order blocks
Blocks[ind2][ALLOC] = 1; // Look for identical block in memory blocks
num_blocks++; while (i < n - 1) {
if(num_blocks == max_blocks) goto end; // skip all zeroes blocks
if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 1; j < max_blocks - 1; ++j) {
if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j + 1][ALLOC]) {
memcpy(memory_blocks[j + 1], tmp_blocks[i + 1], 16);
memory_blocks[j + 1][ALLOC] = 1;
if (++found_blocks >= max_blocks) goto end;
} }
} }
} }
if (memcmp(tmp_blocks[i + 1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) {
for (j = 0; j < max_blocks; ++j) {
if (!memcmp(tmp_blocks[i + 1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) - 1][ALLOC]) {
if (j == 0) {
memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16);
memory_blocks[max_blocks - 1][ALLOC] = 1;
} else {
memcpy(memory_blocks[j - 1], tmp_blocks[i], 16);
memory_blocks[j - 1][ALLOC] = 1;
}
if (++found_blocks >= max_blocks) goto end;
} }
} }
} }
++i;
} }
tries++; }
if (BUTTON_PRESS()) return; ++tries;
} while (num_blocks != max_blocks); if (BUTTON_PRESS()) {
Dbprintf("Button pressed, stopping.");
goto end;
}
} while (found_blocks != max_blocks);
end: end:
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
Dbprintf("Memory content:"); Dbprintf("Memory content:");
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
for(i=0; i<max_blocks; i++) { for (i = 0; i < max_blocks; ++i) {
if(Blocks[i][ALLOC]==1) if (memory_blocks[i][ALLOC])
Dbprintf("%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", print_result("Block", memory_blocks[i], 16);
Blocks[i][0], Blocks[i][1], Blocks[i][2], Blocks[i][3], Blocks[i][4], Blocks[i][5], Blocks[i][6], Blocks[i][7],
Blocks[i][8], Blocks[i][9], Blocks[i][10], Blocks[i][11], Blocks[i][12], Blocks[i][13], Blocks[i][14], Blocks[i][15]);
else else
Dbprintf("<missing block %d>", i); Dbprintf("<missing block %d>", i);
} }
Dbprintf("-----------------------------------------"); Dbprintf("-----------------------------------------");
cmd_send(CMD_ACK,0,0,0,0,0); if (found_blocks < max_blocks) {
Dbprintf("-----------------------------------------");
Dbprintf("Blocks with unknown position:");
Dbprintf("-----------------------------------------");
for (i = 0; i < single_blocks_cnt; ++i)
print_result("Block", single_blocks[i], 16);
Dbprintf("-----------------------------------------");
}
reply_old(CMD_ACK, 0, 0, 0, 0, 0);
} }
static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
/* Write on a byte of a PCF7931 tag
* @param address : address of the block to write
@param byte : address of the byte to write
@param data : data to write
*/
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data)
{
uint32_t tab[1024] = {0}; // data times frame uint32_t tab[1024] = {0}; // data times frame
uint32_t u = 0; uint32_t u = 0;
uint8_t parity = 0; uint8_t parity = 0;
bool comp = 0; bool comp = 0;
//BUILD OF THE DATA FRAME //BUILD OF THE DATA FRAME
//alimentation of the tag (time for initializing) //alimentation of the tag (time for initializing)
AddPatternPCF7931(init_delay, 0, 8192 / 2 * T0_PCF, tab); AddPatternPCF7931(init_delay, 0, 8192 / 2 * T0_PCF, tab);
//PMC
Dbprintf("Initialization delay : %d us", init_delay);
AddPatternPCF7931(8192 / 2 * T0_PCF + 319 * T0_PCF + 70, 3 * T0_PCF, 29 * T0_PCF, tab); AddPatternPCF7931(8192 / 2 * T0_PCF + 319 * T0_PCF + 70, 3 * T0_PCF, 29 * T0_PCF, tab);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
//password indication bit //password indication bit
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
//password (on 56 bits) //password (on 56 bits)
Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); AddBytePCF7931(pass[0], tab, l, p);
AddBytePCF7931(pass1, tab, l, p); AddBytePCF7931(pass[1], tab, l, p);
AddBytePCF7931(pass2, tab, l, p); AddBytePCF7931(pass[2], tab, l, p);
AddBytePCF7931(pass3, tab, l, p); AddBytePCF7931(pass[3], tab, l, p);
AddBytePCF7931(pass4, tab, l, p); AddBytePCF7931(pass[4], tab, l, p);
AddBytePCF7931(pass5, tab, l, p); AddBytePCF7931(pass[5], tab, l, p);
AddBytePCF7931(pass6, tab, l, p); AddBytePCF7931(pass[6], tab, l, p);
AddBytePCF7931(pass7, tab, l, p);
//programming mode (0 or 1) //programming mode (0 or 1)
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
//block adress on 6 bits //block adress on 6 bits
Dbprintf("Block address : %02x", address); for (u = 0; u < 6; ++u) {
for (u=0; u<6; u++)
{
if (address & (1 << u)) { // bit 1 if (address & (1 << u)) { // bit 1
parity++; ++parity;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} else { // bit 0 } else { // bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
@ -321,59 +332,66 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui
} }
//byte address on 4 bits //byte address on 4 bits
Dbprintf("Byte address : %02x", byte); for (u = 0; u < 4; ++u) {
for (u=0; u<4; u++)
{
if (byte & (1 << u)) { // bit 1 if (byte & (1 << u)) { // bit 1
parity++; parity++;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} else{ // bit 0 } else // bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
} }
}
//data on 8 bits //data on 8 bits
Dbprintf("Data : %02x", data); for (u = 0; u < 8; u++) {
for (u=0; u<8; u++)
{
if (data & (1 << u)) { // bit 1 if (data & (1 << u)) { // bit 1
parity++; parity++;
AddBitPCF7931(1, tab, l, p); AddBitPCF7931(1, tab, l, p);
} else{ //bit 0 } else //bit 0
AddBitPCF7931(0, tab, l, p); AddBitPCF7931(0, tab, l, p);
} }
}
//parity bit //parity bit
if((parity%2)==0){ if ((parity % 2) == 0)
AddBitPCF7931(0, tab, l, p); //even parity AddBitPCF7931(0, tab, l, p); //even parity
}else{ else
AddBitPCF7931(1, tab, l, p);//odd parity AddBitPCF7931(1, tab, l, p);//odd parity
}
//time access memory //time access memory
AddPatternPCF7931(5120 + 2680, 0, 0, tab); AddPatternPCF7931(5120 + 2680, 0, 0, tab);
//conversion of the scale time //conversion of the scale time
for(u=0;u<500;u++){ for (u = 0; u < 500; ++u)
tab[u] = (tab[u] * 3) / 2; tab[u] = (tab[u] * 3) / 2;
}
//compensation of the counter reload //compensation of the counter reload
while (!comp) { while (!comp) {
comp = 1; comp = 1;
for(u=0;tab[u]!=0;u++){ for (u = 0; tab[u] != 0; ++u)
if (tab[u] > 0xFFFF) { if (tab[u] > 0xFFFF) {
tab[u] -= 0xFFFF; tab[u] -= 0xFFFF;
comp = 0; comp = 0;
} }
} }
}
SendCmdPCF7931(tab); SendCmdPCF7931(tab);
} }
/* Write on a byte of a PCF7931 tag
* @param address : address of the block to write
@param byte : address of the byte to write
@param data : data to write
*/
void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) {
Dbprintf("Initialization delay : %d us", init_delay);
Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p);
Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7);
Dbprintf("Block address : %02x", address);
Dbprintf("Byte address : %02x", byte);
Dbprintf("Data : %02x", data);
uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7};
RealWritePCF7931(password, init_delay, l, p, address, byte, data);
}
/* Send a trame to a PCF7931 tags /* Send a trame to a PCF7931 tags
@ -386,9 +404,7 @@ void SendCmdPCF7931(uint32_t * tab){
Dbprintf("Sending data frame..."); Dbprintf("Sending data frame...");
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU);
LED_A_ON(); LED_A_ON();
@ -405,21 +421,22 @@ void SendCmdPCF7931(uint32_t * tab){
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN;
AT91C_BASE_TCB->TCB_BCR = 1; AT91C_BASE_TCB->TCB_BCR = 1;
tempo = AT91C_BASE_TC0->TC_CV; tempo = AT91C_BASE_TC0->TC_CV;
for (u = 0; tab[u] != 0; u += 3) { for (u = 0; tab[u] != 0; u += 3) {
// modulate antenna // modulate antenna
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u]) tempo = AT91C_BASE_TC0->TC_CV; while (tempo != tab[u])
tempo = AT91C_BASE_TC0->TC_CV;
// stop modulating antenna // stop modulating antenna
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
while(tempo != tab[u+1]) tempo = AT91C_BASE_TC0->TC_CV; while (tempo != tab[u + 1])
tempo = AT91C_BASE_TC0->TC_CV;
// modulate antenna // modulate antenna
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
while(tempo != tab[u+2]) tempo = AT91C_BASE_TC0->TC_CV; while (tempo != tab[u + 2])
tempo = AT91C_BASE_TC0->TC_CV;
} }
LED_A_OFF(); LED_A_OFF();
@ -437,18 +454,16 @@ void SendCmdPCF7931(uint32_t * tab){
* @param l : offset on low pulse width * @param l : offset on low pulse width
* @param p : offset on low pulse positioning * @param p : offset on low pulse positioning
*/ */
bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p) { bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p) {
uint32_t u; uint32_t u;
for ( u=0; u<8; u++) for (u = 0; u < 8; ++u) {
{ if (byte & (1 << u)) { //bit is 1
if (byte&(1<<u)) { //bit à 1
if (AddBitPCF7931(1, tab, l, p) == 1) return 1; if (AddBitPCF7931(1, tab, l, p) == 1) return 1;
} else { //bit à 0 } else { //bit is 0
if (AddBitPCF7931(0, tab, l, p) == 1) return 1; if (AddBitPCF7931(0, tab, l, p) == 1) return 1;
} }
} }
return 0; return 0;
} }

View file

@ -7,9 +7,9 @@
#include "pcf7931.h" #include "pcf7931.h"
#include "string.h" #include "string.h"
int DemodPCF7931(uint8_t **outBlocks); size_t DemodPCF7931(uint8_t **outBlocks);
int IsBlock0PCF7931(uint8_t *Block); bool IsBlock0PCF7931(uint8_t *block);
int IsBlock1PCF7931(uint8_t *Block); bool IsBlock1PCF7931(uint8_t *block);
void ReadPCF7931(); void ReadPCF7931();
void SendCmdPCF7931(uint32_t *tab); void SendCmdPCF7931(uint32_t *tab);
bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p); bool AddBytePCF7931(uint8_t byte, uint32_t *tab, int32_t l, int32_t p);

View file

@ -59,14 +59,11 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz";
* The buffer pointed to by `nbuf' must have length >= MAXNBUF. * The buffer pointed to by `nbuf' must have length >= MAXNBUF.
*/ */
static char * static char *
ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) {
{ char *p = nbuf;
char *p, c;
p = nbuf;
*p = '\0'; *p = '\0';
do { do {
c = hex2ascii(num % base); char c = hex2ascii(num % base);
*++p = upper ? toupper(c) : c; *++p = upper ? toupper(c) : c;
} while (num /= base); } while (num /= base);
if (lenp) if (lenp)
@ -101,8 +98,7 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
* ("%*D", len, ptr, " " -> XX XX XX XX ... * ("%*D", len, ptr, " " -> XX XX XX XX ...
*/ */
int int
kvsprintf(char const *fmt, void *arg, int radix, va_list ap) kvsprintf(char const *fmt, void *arg, int radix, va_list ap) {
{
#define PCHAR(c) {int cc=(c); *d++ = cc; retval++; } #define PCHAR(c) {int cc=(c); *d++ = cc; retval++; }
char nbuf[MAXNBUF]; char nbuf[MAXNBUF];
char *d; char *d;
@ -134,10 +130,22 @@ kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
return (retval); return (retval);
} }
percent = fmt - 1; percent = fmt - 1;
qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; qflag = 0;
sign = 0; dot = 0; dwidth = 0; upper = 0; lflag = 0;
cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; ladjust = 0;
reswitch: switch (ch = (u_char)*fmt++) { sharpflag = 0;
neg = 0;
sign = 0;
dot = 0;
dwidth = 0;
upper = 0;
cflag = 0;
hflag = 0;
jflag = 0;
tflag = 0;
zflag = 0;
reswitch:
switch (ch = (u_char) * fmt++) {
case '.': case '.':
dot = 1; dot = 1;
goto reswitch; goto reswitch;
@ -169,8 +177,15 @@ reswitch: switch (ch = (u_char)*fmt++) {
padc = '0'; padc = '0';
goto reswitch; goto reswitch;
} }
case '1': case '2': case '3': case '4': case '1':
case '5': case '6': case '7': case '8': case '9': case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (n = 0;; ++fmt) { for (n = 0;; ++fmt) {
n = n * 10 + ch - '0'; n = n * 10 + ch - '0';
ch = *fmt; ch = *fmt;
@ -411,14 +426,12 @@ number:
#undef PCHAR #undef PCHAR
} }
int vsprintf(char *dest, const char *fmt, va_list ap) int vsprintf(char *dest, const char *fmt, va_list ap) {
{
return kvsprintf(fmt, dest, 10, ap); return kvsprintf(fmt, dest, 10, ap);
} }
int int
sprintf(char *dest, const char *fmt, ...) sprintf(char *dest, const char *fmt, ...) {
{
/* http://www.pagetable.com/?p=298 */ /* http://www.pagetable.com/?p=298 */
int retval; int retval;
va_list ap; va_list ap;

View file

@ -15,8 +15,8 @@
#include <stddef.h> #include <stddef.h>
#include "string.h" #include "string.h"
int kvsprintf(const char *format, void *arg, int radix, va_list ap) __attribute__ ((format (printf, 1, 0))); int kvsprintf(const char *fmt, void *arg, int radix, va_list ap) __attribute__((format(printf, 1, 0)));
int vsprintf(char *str, const char *format, va_list ap) __attribute__ ((format (printf, 2, 0))); int vsprintf(char *dest, const char *fmt, va_list ap) __attribute__((format(printf, 2, 0)));
int sprintf(char *str, const char *format, ...) __attribute__ ((format (printf, 2, 3))); int sprintf(char *dest, const char *fmt, ...) __attribute__((format(printf, 2, 3)));
#endif #endif

View file

@ -21,8 +21,7 @@ static uint8_t *next_free_memory;
extern struct common_area common_area; extern struct common_area common_area;
extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__; extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __bss_end__;
static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) {
{
uint8_t *allocated_memory; uint8_t *allocated_memory;
allocated_memory = next_free_memory; allocated_memory = next_free_memory;
@ -30,13 +29,11 @@ static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size)
return allocated_memory; return allocated_memory;
} }
static void inflate_free(voidpf opaque, voidpf address) static void inflate_free(voidpf opaque, voidpf address) {
{
// nothing to do // nothing to do
} }
static void uncompress_data_section(void) static void uncompress_data_section(void) {
{
z_stream data_section; z_stream data_section;
next_free_memory = BigBuf_get_addr(); next_free_memory = BigBuf_get_addr();
@ -51,7 +48,9 @@ static void uncompress_data_section(void)
data_section.opaque = NULL; data_section.opaque = NULL;
// initialize zlib for inflate // initialize zlib for inflate
inflateInit2(&data_section, 15); int res = inflateInit2(&data_section, 15);
if (res < 0)
return;
// uncompress data segment to RAM // uncompress data segment to RAM
inflate(&data_section, Z_FINISH); inflate(&data_section, Z_FINISH);
@ -60,8 +59,7 @@ static void uncompress_data_section(void)
common_area.arg1 = data_section.total_in; common_area.arg1 = data_section.total_in;
} }
void __attribute__((section(".startos"))) Vector(void) void __attribute__((section(".startos"))) Vector(void) {
{
/* Stack should have been set up by the bootloader */ /* Stack should have been set up by the bootloader */
// char *src; // char *src;
char *dst, *end; char *dst, *end;

View file

@ -9,8 +9,7 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#include "string.h" #include "string.h"
void *memcpy(void *dest, const void *src, int len) void *memcpy(void *dest, const void *src, int len) {
{
uint8_t *d = dest; uint8_t *d = dest;
const uint8_t *s = src; const uint8_t *s = src;
while ((len--) > 0) { while ((len--) > 0) {
@ -21,8 +20,7 @@ void *memcpy(void *dest, const void *src, int len)
return dest; return dest;
} }
void *memset(void *dest, int c, int len) void *memset(void *dest, int c, int len) {
{
uint8_t *d = dest; uint8_t *d = dest;
while ((len--) > 0) { while ((len--) > 0) {
*d = c; *d = c;
@ -31,8 +29,7 @@ void *memset(void *dest, int c, int len)
return dest; return dest;
} }
int memcmp(const void *av, const void *bv, int len) int memcmp(const void *av, const void *bv, int len) {
{
const uint8_t *a = av; const uint8_t *a = av;
const uint8_t *b = bv; const uint8_t *b = bv;
@ -51,18 +48,14 @@ void memxor(uint8_t * dest, uint8_t * src, size_t len) {
*dest ^= *src; *dest ^= *src;
} }
int strlen(const char *str) int strlen(const char *str) {
{ const char *p;
int l = 0; for (p = str; *p != '\0'; ++p) {
while(*str) {
l++;
str++;
} }
return l; return p - str;
} }
char* strncat(char *dest, const char *src, unsigned int n) char *strncat(char *dest, const char *src, unsigned int n) {
{
unsigned int dest_len = strlen(dest); unsigned int dest_len = strlen(dest);
unsigned int i; unsigned int i;
@ -73,8 +66,7 @@ char* strncat(char *dest, const char *src, unsigned int n)
return dest; return dest;
} }
char* strcat(char *dest, const char *src) char *strcat(char *dest, const char *src) {
{
unsigned int dest_len = strlen(dest); unsigned int dest_len = strlen(dest);
unsigned int i; unsigned int i;
@ -87,20 +79,18 @@ char* strcat(char *dest, const char *src)
////////////////////////////////////////// code to do 'itoa' ////////////////////////////////////////// code to do 'itoa'
/* reverse: reverse string s in place */ /* reverse: reverse string s in place */
void strreverse(char s[]) void strreverse(char s[]) {
{ int j = strlen(s) - 1;
int c, i, j;
for (i = 0, j = strlen(s)-1; i<j; i++, j--) { for (int i = 0; i < j; i++, j--) {
c = s[i]; int c = s[i];
s[i] = s[j]; s[i] = s[j];
s[j] = c; s[j] = c;
} }
} }
/* itoa: convert n to characters in s */ /* itoa: convert n to characters in s */
void itoa(int n, char s[]) void itoa(int n, char s[]) {
{
int i, sign; int i, sign;
if ((sign = n) < 0) /* record sign */ if ((sign = n) < 0) /* record sign */

View file

@ -62,6 +62,13 @@ uint32_t RAMFUNC GetTickCount(void){
return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2;
} }
uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks) {
uint32_t stop_ticks = AT91C_BASE_RTTC->RTTC_RTVR;
if (stop_ticks > start_ticks)
return stop_ticks - start_ticks;
return (UINT32_MAX - start_ticks) + stop_ticks;
}
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// microseconds timer // microseconds timer
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------

View file

@ -27,6 +27,7 @@ void SpinDelayUs(int us);
void StartTickCount(void); void StartTickCount(void);
uint32_t RAMFUNC GetTickCount(void); uint32_t RAMFUNC GetTickCount(void);
uint32_t RAMFUNC GetTickCountDelta(uint32_t start_ticks);
void StartCountUS(void); void StartCountUS(void);
uint32_t RAMFUNC GetCountUS(void); uint32_t RAMFUNC GetCountUS(void);
@ -37,11 +38,11 @@ void StartCountSspClk();
void ResetSspClk(void); void ResetSspClk(void);
uint32_t RAMFUNC GetCountSspClk(); uint32_t RAMFUNC GetCountSspClk();
extern void StartTicks(void); void StartTicks(void);
extern uint32_t GetTicks(void); uint32_t GetTicks(void);
extern void WaitTicks(uint32_t ticks); void WaitTicks(uint32_t ticks);
extern void WaitUS(uint16_t us); void WaitUS(uint16_t us);
extern void WaitMS(uint16_t ms); void WaitMS(uint16_t ms);
extern void StopTicks(void); void StopTicks(void);
#endif #endif

View file

@ -1,77 +0,0 @@
#include <tlv.h>
int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag)
{
uint8_t tag[TAG_LENGTH] = {0x00,0x00};
uint16_t length = 0;
//uint8_t value[VALUE_LENGTH];
uint8_t lenlen = 0;
int i = 0;
int z = 0;
//decode tag
tag[0] = data[0];
if((tag[0] & TLV_TAG_NUMBER_MASK) == TLV_TAG_NUMBER_MASK) { //see subsequent bytes
i++;
tag[i] = data[i];
//assume tag is only two bytes long for now
/*
while((data[i] & TLV_TAG_MASK) == TLV_TAG_MASK){
i++;
tag[i] = data[i];
}
*/
}
i++;
//decode length
if((data[i] & TLV_LENGTH_MASK) == TLV_LENGTH_MASK) {
lenlen = data[i] ^ TLV_LENGTH_MASK;
i++;
length = (uint16_t)data[i];
z = 1;
while(z < lenlen){
i++;
z++;
length <<= 8;
length += (uint16_t)data[i];
}
i++;
}
else {
length = (uint16_t)data[i];
i++;
}
//copy results into the structure and return
memcpy(returnedtag->tag, tag, TAG_LENGTH);
(*returnedtag).valuelength = length; //return length of tag value
(*returnedtag).fieldlength = length + i + 1; //return length of total field
memcpy(returnedtag->value, &(data[i]), length);
return 0;
}
//generate a TLV tag off input data
int encode_ber_tlv_item(uint8_t* tag, uint8_t taglen, uint8_t* data, uint32_t datalen, uint8_t* outputtag, uint32_t* outputtaglen)
{
if(!tag || !data || !outputtag || !outputtaglen) //null pointer check
return 0;
uint8_t datafieldlen = (datalen / 128) + 1; //field length of the tag
uint8_t tlvtotallen = taglen + datafieldlen + datalen; //total length of the tag
uint8_t returnedtag[tlvtotallen]; //buffer for the returned tag
uint8_t counter = 0;
memcpy(returnedtag, tag, taglen); //copy tag into buffer
counter += taglen;
if(datalen < 128){ // 1 byte length value
returnedtag[counter++] = datalen;
}
else{
returnedtag[counter++] = datafieldlen | 0x80; //high bit set and number of length bytes
for(uint8_t i=datafieldlen; i !=0; i--){
returnedtag[counter++] = (datalen >> (i * 8)) & 0xFF; //get current byte
}
}
memcpy(&returnedtag[counter], data, datalen);
*outputtaglen = tlvtotallen;
memcpy(outputtag, returnedtag,tlvtotallen);
return 0;
}

View file

@ -1,33 +0,0 @@
#ifndef __TLV_H
#define __TLV_H
#include <stdint.h>
#include <string.h>
#include <stddef.h>
//structure buffer definitions
#define TAG_LENGTH 2
#define VALUE_LENGTH 1024
//masks
//if TLV_TAG_NUMBER_MASK bits are set, refer to the next byte for the tag number
//otherwise its located in bits 1-5
#define TLV_TAG_NUMBER_MASK 0x1f
//if TLV_DATA_MASK set then its a 'constructed data object'
//otherwise a 'primitive data object'
#define TLV_DATA_MASK 0x20
#define TLV_TAG_MASK 0x80
#define TLV_LENGTH_MASK 0x80
//tlv tag structure, tag can be max of 2 bytes, length up to 65535 and value 1024 bytes long
typedef struct {
uint8_t tag[TAG_LENGTH];
uint16_t fieldlength;
uint16_t valuelength;
uint8_t value[VALUE_LENGTH];
}tlvtag;
//decode a BER TLV
extern int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag);
extern int encode_ber_tlv_item(uint8_t* tag, uint8_t taglen, uint8_t*data, uint32_t datalen, uint8_t* outputtag, uint32_t* outputtaglen);
#endif //__TLV_H

View file

@ -13,109 +13,63 @@ size_t nbytes(size_t nbits) {
return (nbits >> 3) + ((nbits % 8) > 0); return (nbits >> 3) + ((nbits % 8) > 0);
} }
/*
ref http://www.csm.ornl.gov/~dunigan/crc.html
Returns the value v with the bottom b [0,32] bits reflected.
Example: reflect(0x3e23L,3) == 0x3e26
*/
uint32_t reflect(uint32_t v, int b) {
uint32_t t = v;
for ( int i = 0; i < b; ++i) {
if (t & 1)
v |= BITMASK((b-1)-i);
else
v &= ~BITMASK((b-1)-i);
t>>=1;
}
return v;
}
uint8_t reflect8(uint8_t b) {
return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
}
uint16_t reflect16(uint16_t b) {
uint16_t v = 0;
v |= (b & 0x8000) >> 15;
v |= (b & 0x4000) >> 13;
v |= (b & 0x2000) >> 11;
v |= (b & 0x1000) >> 9;
v |= (b & 0x0800) >> 7;
v |= (b & 0x0400) >> 5;
v |= (b & 0x0200) >> 3;
v |= (b & 0x0100) >> 1;
v |= (b & 0x0080) << 1;
v |= (b & 0x0040) << 3;
v |= (b & 0x0020) << 5;
v |= (b & 0x0010) << 7;
v |= (b & 0x0008) << 9;
v |= (b & 0x0004) << 11;
v |= (b & 0x0002) << 13;
v |= (b & 0x0001) << 15;
return v;
}
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) {
while (len--) {
dest[len] = (uint8_t) n;
n >>= 8;
}
}
uint64_t bytes_to_num(uint8_t* src, size_t len) {
uint64_t num = 0;
while (len--) {
num = (num << 8) | (*src);
src++;
}
return num;
}
// RotateLeft - Ultralight, Desfire
void rol(uint8_t *data, const size_t len) {
uint8_t first = data[0];
for (size_t i = 0; i < len-1; i++) {
data[i] = data[i+1];
}
data[len-1] = first;
}
void lsl (uint8_t *data, size_t len) {
for (size_t n = 0; n < len - 1; n++) {
data[n] = (data[n] << 1) | (data[n+1] >> 7);
}
data[len - 1] <<= 1;
}
int32_t le24toh (uint8_t data[3]) {
return (data[2] << 16) | (data[1] << 8) | data[0];
}
//convert hex digit to integer //convert hex digit to integer
uint8_t hex2int(char hexchar) { uint8_t hex2int(char hexchar) {
switch (hexchar) { switch (hexchar) {
case '0': return 0; break; case '0':
case '1': return 1; break; return 0;
case '2': return 2; break; break;
case '3': return 3; break; case '1':
case '4': return 4; break; return 1;
case '5': return 5; break; break;
case '6': return 6; break; case '2':
case '7': return 7; break; return 2;
case '8': return 8; break; break;
case '9': return 9; break; case '3':
return 3;
break;
case '4':
return 4;
break;
case '5':
return 5;
break;
case '6':
return 6;
break;
case '7':
return 7;
break;
case '8':
return 8;
break;
case '9':
return 9;
break;
case 'a': case 'a':
case 'A': return 10; break; case 'A':
return 10;
break;
case 'b': case 'b':
case 'B': return 11; break; case 'B':
return 11;
break;
case 'c': case 'c':
case 'C': return 12; break; case 'C':
return 12;
break;
case 'd': case 'd':
case 'D': return 13; break; case 'D':
return 13;
break;
case 'e': case 'e':
case 'E': return 14; break; case 'E':
return 14;
break;
case 'f': case 'f':
case 'F': return 15; break; case 'F':
return 15;
break;
default: default:
return 0; return 0;
} }
@ -128,15 +82,14 @@ void LEDsoff() {
LED_D_OFF(); LED_D_OFF();
} }
// LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8]
void LED(int led, int ms) { void LED(int led, int ms) {
if (led & LED_RED) if (led & LED_A) // Proxmark3 historical mapping: LED_ORANGE
LED_C_ON();
if (led & LED_ORANGE)
LED_A_ON(); LED_A_ON();
if (led & LED_GREEN) if (led & LED_B) // Proxmark3 historical mapping: LED_GREEN
LED_B_ON(); LED_B_ON();
if (led & LED_RED2) if (led & LED_C) // Proxmark3 historical mapping: LED_RED
LED_C_ON();
if (led & LED_D) // Proxmark3 historical mapping: LED_RED2
LED_D_ON(); LED_D_ON();
if (!ms) if (!ms)
@ -144,16 +97,79 @@ void LED(int led, int ms) {
SpinDelay(ms); SpinDelay(ms);
if (led & LED_RED) if (led & LED_A)
LED_C_OFF();
if (led & LED_ORANGE)
LED_A_OFF(); LED_A_OFF();
if (led & LED_GREEN) if (led & LED_B)
LED_B_OFF(); LED_B_OFF();
if (led & LED_RED2) if (led & LED_C)
LED_C_OFF();
if (led & LED_D)
LED_D_OFF(); LED_D_OFF();
} }
void SpinOff(uint32_t pause) {
LED_A_OFF();
LED_B_OFF();
LED_C_OFF();
LED_D_OFF();
SpinDelay(pause);
}
// 0=A, 1=B, 2=C, 3=D
void SpinErr(uint8_t led, uint32_t speed, uint8_t times) {
SpinOff(speed);
NTIME(times) {
switch (led) {
case 0:
LED_A_INV();
break;
case 1:
LED_B_INV();
break;
case 2:
LED_C_INV();
break;
case 3:
LED_D_INV();
break;
}
SpinDelay(speed);
}
}
void SpinDown(uint32_t speed) {
SpinOff(speed);
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
}
void SpinUp(uint32_t speed) {
SpinOff(speed);
LED_A_ON();
SpinDelay(speed);
LED_A_OFF();
LED_B_ON();
SpinDelay(speed);
LED_B_OFF();
LED_C_ON();
SpinDelay(speed);
LED_C_OFF();
LED_D_ON();
SpinDelay(speed);
LED_D_OFF();
}
// Determine if a button is double clicked, single clicked, // Determine if a button is double clicked, single clicked,
// not clicked, or held down (for ms || 1sec) // not clicked, or held down (for ms || 1sec)
// In general, don't use this function unless you expect a // In general, don't use this function unless you expect a
@ -176,16 +192,13 @@ int BUTTON_CLICKED(int ms) {
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
int letoff = 0; int letoff = 0;
for(;;) for (;;) {
{
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// We haven't let off the button yet // We haven't let off the button yet
if (!letoff) if (!letoff) {
{
// We just let it off! // We just let it off!
if (!BUTTON_PRESS()) if (!BUTTON_PRESS()) {
{
letoff = 1; letoff = 1;
// reset our timer for 500ms // reset our timer for 500ms
@ -207,8 +220,7 @@ int BUTTON_CLICKED(int ms) {
return BUTTON_DOUBLE_CLICK; return BUTTON_DOUBLE_CLICK;
// Have we ran out of time to double click? // Have we ran out of time to double click?
else else if (now == (uint16_t)(start + ticks))
if (now == (uint16_t)(start + ticks))
// At least we did a single click // At least we did a single click
return BUTTON_SINGLE_CLICK; return BUTTON_SINGLE_CLICK;
@ -237,8 +249,7 @@ int BUTTON_HELD(int ms) {
uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
for(;;) for (;;) {
{
uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR;
// As soon as our button let go, we didn't hold long enough // As soon as our button let go, we didn't hold long enough
@ -246,8 +257,7 @@ int BUTTON_HELD(int ms) {
return BUTTON_SINGLE_CLICK; return BUTTON_SINGLE_CLICK;
// Have we waited the full second? // Have we waited the full second?
else else if (now == (uint16_t)(start + ticks))
if (now == (uint16_t)(start + ticks))
return BUTTON_HOLD; return BUTTON_HOLD;
WDT_HIT(); WDT_HIT();
@ -290,3 +300,11 @@ void FormatVersionInformation(char *dst, int len, const char *prefix, void *vers
strncat(dst, v->buildtime, len - strlen(dst) - 1); strncat(dst, v->buildtime, len - strlen(dst) - 1);
strncat(dst, "\n", len - strlen(dst) - 1); strncat(dst, "\n", len - strlen(dst) - 1);
} }
bool data_available(void) {
#ifdef WITH_FPC_USART_HOST
return usb_poll_validate_length() || (usart_rxdata_available() > 0);
#else
return usb_poll_validate_length();
#endif
}

View file

@ -12,50 +12,86 @@
#define __UTIL_H #define __UTIL_H
#include "common.h" #include "common.h"
#include "commonutil.h"
#include "proxmark3.h" #include "proxmark3.h"
#include "string.h" #include "string.h"
#include "BigBuf.h" #include "BigBuf.h"
#include "ticks.h" #include "ticks.h"
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff ) // Basic macros
#ifndef SHORT_COIL
#define SHORT_COIL() LOW(GPIO_SSC_DOUT)
#endif
#ifndef OPEN_COIL
#define OPEN_COIL() HIGH(GPIO_SSC_DOUT)
#endif
#ifndef BYTEx
#define BYTEx(x, n) (((x) >> (n * 8)) & 0xff )
#endif
// Proxmark3 RDV4.0 LEDs
#define LED_A 1
#define LED_B 2
#define LED_C 4
#define LED_D 8
// Proxmark3 historical LEDs
#define LED_ORANGE LED_A
#define LED_GREEN LED_B
#define LED_RED LED_C
#define LED_RED2 LED_D
#define LED_RED 1
#define LED_ORANGE 2
#define LED_GREEN 4
#define LED_RED2 8
#define BUTTON_HOLD 1 #define BUTTON_HOLD 1
#define BUTTON_NO_CLICK 0 #define BUTTON_NO_CLICK 0
#define BUTTON_SINGLE_CLICK -1 #define BUTTON_SINGLE_CLICK -1
#define BUTTON_DOUBLE_CLICK -2 #define BUTTON_DOUBLE_CLICK -2
#define BUTTON_ERROR -99 #define BUTTON_ERROR -99
#ifndef BSWAP_16 #ifndef REV8
# define BSWAP_16(x) ((( ((x) & 0xFF00 ) >> 8))| ( (((x) & 0x00FF) << 8))) #define REV8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7))
#endif #endif
#ifndef BITMASK
# define BITMASK(X) (1 << (X)) #ifndef REV16
#define REV16(x) (REV8(x) + (REV8 (x >> 8) << 8))
#endif #endif
#ifndef ARRAYLEN
# define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0])) #ifndef REV32
#define REV32(x) (REV16(x) + (REV16(x >> 16) << 16))
#endif
#ifndef REV64
#define REV64(x) (REV32(x) + (REV32(x >> 32) << 32))
#endif
#ifndef BIT32
#define BIT32(x,n) ((((x)[(n)>>5])>>((n)))&1)
#endif
#ifndef INV32
#define INV32(x,i,n) ((x)[(i)>>5]^=((uint32_t)(n))<<((i)&31))
#endif
#ifndef ROTL64
#define ROTL64(x, n) ((((uint64_t)(x))<<((n)&63))+(((uint64_t)(x))>>((0-(n))&63)))
#endif #endif
size_t nbytes(size_t nbits); size_t nbytes(size_t nbits);
extern uint32_t reflect(uint32_t v, int b); // used in crc.c ...
extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal
extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal
void num_to_bytes(uint64_t n, size_t len, uint8_t* dest);
uint64_t bytes_to_num(uint8_t* src, size_t len);
void rol(uint8_t *data, const size_t len);
void lsl (uint8_t *data, size_t len);
int32_t le24toh (uint8_t data[3]);
uint8_t hex2int(char hexchar); uint8_t hex2int(char hexchar);
void LED(int led, int ms); void LED(int led, int ms);
void LEDsoff(); void LEDsoff(void);
void SpinOff(uint32_t pause);
void SpinErr(uint8_t led, uint32_t speed, uint8_t times);
void SpinDown(uint32_t speed);
void SpinUp(uint32_t speed);
int BUTTON_CLICKED(int ms); int BUTTON_CLICKED(int ms);
int BUTTON_HELD(int ms); int BUTTON_HELD(int ms);
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information); void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information);
bool data_available(void);
#endif #endif

View file

@ -8,8 +8,7 @@
# DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code # DO NOT use thumb mode in the phase 1 bootloader since that generates a section with glue code
ARMSRC = ARMSRC =
THUMBSRC = cmd.c \ THUMBSRC = usb_cdc.c \
usb_cdc.c \
bootrom.c bootrom.c
ASMSRC = ram-reset.s flash-reset.s ASMSRC = ram-reset.s flash-reset.s
@ -25,6 +24,10 @@ VERSIONSRC = version.c
# stdint.h provided locally until GCC 4.5 becomes C99 compliant # stdint.h provided locally until GCC 4.5 becomes C99 compliant
APP_CFLAGS = -I. -fno-strict-aliasing -ffunction-sections -fdata-sections APP_CFLAGS = -I. -fno-strict-aliasing -ffunction-sections -fdata-sections
# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc
APP_CFLAGS += -fno-stack-protector -fno-pie
# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC
include ../common/Makefile.common include ../common/Makefile.common
@ -32,23 +35,26 @@ OBJS = $(OBJDIR)/bootrom.s19
# version.c should be remade on every compilation # version.c should be remade on every compilation
version.c: default_version.c version.c: default_version.c
perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ $(info [=] GEN $@)
$(Q)perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@
all: $(OBJS) all: $(OBJS)
tarbin: $(OBJS) tarbin: $(OBJS)
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=bootrom/%) $(OBJS:%.s19=bootrom/%.elf) $(info [=] GEN $@)
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=bootrom/%) $(OBJS:%.s19=bootrom/%.elf)
$(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ) $(OBJDIR)/bootrom.elf: $(VERSIONOBJ) $(ASMOBJ) $(ARMOBJ) $(THUMBOBJ)
$(CC) $(LDFLAGS) -Wl,-T,ldscript-flash,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) $(info [=] LD $@)
$(Q)$(CC) $(LDFLAGS) -Wl,-T,ldscript-flash,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS)
clean: clean:
$(DELETE) $(OBJDIR)$(PATHSEP)*.o $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.o
$(DELETE) $(OBJDIR)$(PATHSEP)*.elf $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.elf
$(DELETE) $(OBJDIR)$(PATHSEP)*.s19 $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.s19
$(DELETE) $(OBJDIR)$(PATHSEP)*.map $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.map
$(DELETE) $(OBJDIR)$(PATHSEP)*.d $(Q)$(DELETE) $(OBJDIR)$(PATHSEP)*.d
$(DELETE) version.c $(Q)$(DELETE) version.c
.PHONY: all clean help .PHONY: all clean help
help: help:

View file

@ -8,19 +8,46 @@
#include <proxmark3.h> #include <proxmark3.h>
#include "usb_cdc.h" #include "usb_cdc.h"
#include "cmd.h"
struct common_area common_area __attribute__((section(".commonarea"))); struct common_area common_area __attribute__((section(".commonarea")));
unsigned int start_addr, end_addr, bootrom_unlocked; unsigned int start_addr, end_addr, bootrom_unlocked;
extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end; extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end;
extern uint32_t _osimage_entry; extern uint32_t _osimage_entry;
static int reply_old(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len) {
PacketResponseOLD txcmd;
for (size_t i = 0; i < sizeof(PacketResponseOLD); i++)
((uint8_t *)&txcmd)[i] = 0x00;
// Compose the outgoing command frame
txcmd.cmd = cmd;
txcmd.arg[0] = arg0;
txcmd.arg[1] = arg1;
txcmd.arg[2] = arg2;
// Add the (optional) content to the frame, with a maximum size of PM3_CMD_DATA_SIZE
if (data && len) {
len = MIN(len, PM3_CMD_DATA_SIZE);
for (size_t i = 0; i < len; i++) {
txcmd.d.asBytes[i] = ((uint8_t *)data)[i];
}
}
int result = PM3_EUNDEF;
// Send frame and make sure all bytes are transmitted
result = usb_write((uint8_t *)&txcmd, sizeof(PacketResponseOLD));
return result;
}
void DbpString(char *str) { void DbpString(char *str) {
byte_t len = 0; uint8_t len = 0;
while (str[len] != 0x00) while (str[len] != 0x00)
len++; len++;
cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t*)str, len); reply_old(CMD_DEBUG_PRINT_STRING, len, 0, 0, (uint8_t *)str, len);
} }
static void ConfigClocks(void) { static void ConfigClocks(void) {
@ -86,10 +113,9 @@ static void Fatal(void) {
void UsbPacketReceived(uint8_t *packet, int len) { void UsbPacketReceived(uint8_t *packet, int len) {
int i, dont_ack = 0; int i, dont_ack = 0;
UsbCommand* c = (UsbCommand *)packet; PacketCommandOLD *c = (PacketCommandOLD *)packet;
volatile uint32_t *p;
//if ( len != sizeof(UsbCommand)) Fatal(); //if ( len != sizeof(PacketCommandOLD`)) Fatal();
uint32_t arg0 = (uint32_t)c->arg[0]; uint32_t arg0 = (uint32_t)c->arg[0];
@ -101,17 +127,19 @@ void UsbPacketReceived(uint8_t *packet, int len) {
if (common_area.flags.osimage_present) if (common_area.flags.osimage_present)
arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT;
cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0); reply_old(CMD_DEVICE_INFO, arg0, 1, 2, 0, 0);
} break; }
break;
case CMD_SETUP_WRITE: { case CMD_SETUP_WRITE: {
/* The temporary write buffer of the embedded flash controller is mapped to the /* The temporary write buffer of the embedded flash controller is mapped to the
* whole memory region, only the last 8 bits are decoded. * whole memory region, only the last 8 bits are decoded.
*/ */
p = (volatile uint32_t *)&_flash_start; volatile uint32_t *p = (volatile uint32_t *)&_flash_start;
for (i = 0; i < 12; i++) for (i = 0; i < 12; i++)
p[i + arg0] = c->d.asDwords[i]; p[i + arg0] = c->d.asDwords[i];
} break; }
break;
case CMD_FINISH_WRITE: { case CMD_FINISH_WRITE: {
uint32_t *flash_mem = (uint32_t *)(&_flash_start); uint32_t *flash_mem = (uint32_t *)(&_flash_start);
@ -126,7 +154,7 @@ void UsbPacketReceived(uint8_t *packet, int len) {
if (((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr)) { if (((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr)) {
/* Disallow write */ /* Disallow write */
dont_ack = 1; dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0); reply_old(CMD_NACK, 0, 0, 0, 0, 0);
} else { } else {
uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE;
/* Translate address to flash page and do flash, update here for the 512k part */ /* Translate address to flash page and do flash, update here for the 512k part */
@ -140,15 +168,17 @@ void UsbPacketReceived(uint8_t *packet, int len) {
while (!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); while (!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY));
if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { if (sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) {
dont_ack = 1; dont_ack = 1;
cmd_send(CMD_NACK,sr,0,0,0,0); reply_old(CMD_NACK, sr, 0, 0, 0, 0);
} }
} }
} break; }
break;
case CMD_HARDWARE_RESET: { case CMD_HARDWARE_RESET: {
usb_disable(); usb_disable();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
} break; }
break;
case CMD_START_FLASH: { case CMD_START_FLASH: {
if (c->arg[2] == START_FLASH_MAGIC) if (c->arg[2] == START_FLASH_MAGIC)
@ -174,24 +204,29 @@ void UsbPacketReceived(uint8_t *packet, int len) {
} else { } else {
start_addr = end_addr = 0; start_addr = end_addr = 0;
dont_ack = 1; dont_ack = 1;
cmd_send(CMD_NACK,0,0,0,0,0); reply_old(CMD_NACK, 0, 0, 0, 0, 0);
} }
} break; }
break;
default: { default: {
Fatal(); Fatal();
} break; }
break;
} }
if (!dont_ack) if (!dont_ack)
cmd_send(CMD_ACK,arg0,0,0,0,0); reply_old(CMD_ACK, arg0, 0, 0, 0, 0);
} }
static void flash_mode(int externally_entered) { static void flash_mode(void) {
start_addr = 0; start_addr = 0;
end_addr = 0; end_addr = 0;
bootrom_unlocked = 0; bootrom_unlocked = 0;
byte_t rx[sizeof(UsbCommand)]; uint8_t rx[sizeof(PacketCommandOLD)];
common_area.command = COMMON_AREA_COMMAND_NONE;
if (!common_area.flags.button_pressed && BUTTON_PRESS())
common_area.flags.button_pressed = 1;
usb_enable(); usb_enable();
@ -202,20 +237,23 @@ static void flash_mode(int externally_entered) {
WDT_HIT(); WDT_HIT();
// Check if there is a usb packet available // Check if there is a usb packet available
if ( cmd_receive( (UsbCommand*)rx ) ) if (usb_poll_validate_length()) {
UsbPacketReceived(rx, sizeof(UsbCommand) ); if (usb_read(rx, sizeof(rx))) {
UsbPacketReceived(rx, sizeof(rx));
}
}
if (!externally_entered && !BUTTON_PRESS()) { if (common_area.flags.button_pressed && !BUTTON_PRESS()) {
common_area.flags.button_pressed = 0;
}
if (!common_area.flags.button_pressed && BUTTON_PRESS()) {
/* Perform a reset to leave flash mode */ /* Perform a reset to leave flash mode */
common_area.flags.button_pressed = 1;
usb_disable(); usb_disable();
LED_B_ON(); LED_B_ON();
AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST;
for (;;) {}; for (;;) {};
} }
if (externally_entered && BUTTON_PRESS()) {
/* Let the user's button press override the automatic leave */
externally_entered = 0;
}
} }
} }
@ -303,18 +341,16 @@ void BootROM(void) {
common_area.magic = COMMON_AREA_MAGIC; common_area.magic = COMMON_AREA_MAGIC;
common_area.version = 1; common_area.version = 1;
common_area.flags.bootrom_present = 1;
} }
common_area.flags.bootrom_present = 1; common_area.flags.bootrom_present = 1;
if (common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) {
common_area.command = COMMON_AREA_COMMAND_NONE; if ((common_area.command == COMMON_AREA_COMMAND_ENTER_FLASH_MODE) ||
flash_mode(1); (!common_area.flags.button_pressed && BUTTON_PRESS()) ||
} else if (BUTTON_PRESS()) { (_osimage_entry == 0xffffffffU)) {
flash_mode(0); flash_mode();
} else if (_osimage_entry == 0xffffffffU) {
flash_mode(1);
} else { } else {
// clear button status, even if button still pressed
common_area.flags.button_pressed = 0;
// jump to Flash address of the osimage entry point (LSBit set for thumb mode) // jump to Flash address of the osimage entry point (LSBit set for thumb mode)
__asm("bx %0\n" : : "r"(((int)&_osimage_entry) | 0x1)); __asm("bx %0\n" : : "r"(((int)&_osimage_entry) | 0x1));
} }

View file

@ -9,6 +9,12 @@
# Add -DNOFORCE to disable the -F switch # Add -DNOFORCE to disable the -F switch
# Add -DPRESETS to compile with preset models (edit config.h) # Add -DPRESETS to compile with preset models (edit config.h)
# Hide full compilation line:
ifneq ($(V),1)
Q?=@
endif
# To see full command lines, use make V=1
CC = gcc CC = gcc
CXX = g++ CXX = g++
LD = g++ LD = g++
@ -20,23 +26,39 @@ MV = mv
ENV_LDFLAGS := $(LDFLAGS) ENV_LDFLAGS := $(LDFLAGS)
ENV_CFLAGS := $(CFLAGS) ENV_CFLAGS := $(CFLAGS)
platform = $(shell uname)
VPATH = ../common ../zlib ../uart VPATH = ../common ../zlib ../uart
OBJDIR = obj OBJDIR = obj
LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm
LUALIB = ../liblua/liblua.a LUALIB = ../liblua/liblua.a
JANSSONLIBPATH = ./jansson
JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a
MBEDTLSLIBPATH = ../common/mbedtls
MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a
CBORLIBPATH = ./tinycbor
CBORLIB = $(CBORLIBPATH)/tinycbor.a
LIBS = -I../zlib -I../uart -I../liblua -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH)
INCLUDES_CLIENT = -I. -I../include -I../common -I/opt/local/include $(LIBS)
LDFLAGS = $(ENV_LDFLAGS) LDFLAGS = $(ENV_LDFLAGS)
INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua
CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3
ifneq (,$(findstring MINGW,$(platform)))
CFLAGS += -mno-ms-bitfields
endif
CXXFLAGS = -I../include -Wall -O3 CXXFLAGS = -I../include -Wall -O3
LUAPLATFORM = generic LUAPLATFORM = generic
platform = $(shell uname)
ifneq (,$(findstring MINGW,$(platform))) ifneq (,$(findstring MINGW,$(platform)))
LUAPLATFORM = mingw LUAPLATFORM = mingw
else else
ifeq ($(platform),Darwin) ifeq ($(platform),Darwin)
LUAPLATFORM = macosx LUAPLATFORM = macosx
OBJCSRCS = util_darwin.m
LDFLAGS += -framework Foundation -framework AppKit
LDLIBS := -L/usr/local/opt/readline/lib $(LDLIBS)
LIBS := -I/usr/local/opt/readline/include $(LIBS)
else else
LUALIB += -ldl LUALIB += -ldl
LDLIBS += -ltermcap -lncurses LDLIBS += -ltermcap -lncurses
@ -81,9 +103,6 @@ else
QTGUIOBJS = $(OBJDIR)/guidummy.o QTGUIOBJS = $(OBJDIR)/guidummy.o
endif endif
# RDV40 flag enables flashmemory commands in client. comment out if you don't have rdv40
CFLAGS += -DWITH_FLASH -DWITH_SMARTCARD
# Flags to generate temporary dependency files # Flags to generate temporary dependency files
DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td
# make temporary to final dependeny files after successful compilation # make temporary to final dependeny files after successful compilation
@ -92,32 +111,35 @@ POSTCOMPILE = $(MV) -f $(OBJDIR)/$*.Td $(OBJDIR)/$*.d
CORESRCS = uart_posix.c \ CORESRCS = uart_posix.c \
uart_win32.c \ uart_win32.c \
ui.c \ ui.c \
commonutil.c \
util.c \ util.c \
util_posix.c \ util_posix.c \
scandir.c scandir.c \
crc16.c \
comms.c
CMDSRCS = crapto1/crapto1.c \ CMDSRCS = crapto1/crapto1.c \
crapto1/crypto1.c \ crapto1/crypto1.c \
mfkey.c \ mifare/mfkey.c \
tea.c \ tea.c \
polarssl/des.c \ fido/additional_ca.c \
polarssl/aes.c \ fido/cose.c \
polarssl/bignum.c \ fido/cbortools.c \
polarssl/rsa.c \ fido/fidocore.c \
polarssl/sha1.c \ crypto/asn1dump.c \
polarssl/sha256.c \ crypto/libpcrypto.c\
polarssl/base64.c \ crypto/asn1utils.c\
cliparser/argtable3.c\
cliparser/cliparser.c\
loclass/cipher.c \ loclass/cipher.c \
loclass/cipherutils.c \ loclass/cipherutils.c \
loclass/ikeys.c \ loclass/ikeys.c \
loclass/hash1_brute.c \
loclass/elite_crack.c \ loclass/elite_crack.c \
loclass/fileutils.c \ loclass/fileutils.c \
whereami.c \ whereami.c \
mifarehost.c \ mifare/mifarehost.c \
parity.c \ parity.c \
crc.c \ crc.c \
crc16.c \
crc64.c \ crc64.c \
legic_prng.c \ legic_prng.c \
iso15693tools.c \ iso15693tools.c \
@ -136,12 +158,17 @@ CMDSRCS = crapto1/crapto1.c \
emv/tlv.c \ emv/tlv.c \
emv/emv_tags.c \ emv/emv_tags.c \
emv/dol.c \ emv/dol.c \
emv/emvjson.c\
emv/emvcore.c \ emv/emvcore.c \
emv/test/crypto_test.c\ emv/test/crypto_test.c\
emv/test/sda_test.c\ emv/test/sda_test.c\
emv/test/dda_test.c\ emv/test/dda_test.c\
emv/test/cda_test.c\ emv/test/cda_test.c\
emv/cmdemv.c \ emv/cmdemv.c \
emv/emv_roca.c \
mifare/mifare4.c \
mifare/mad.c \
mifare/ndef.c \
cmdanalyse.c \ cmdanalyse.c \
cmdhf.c \ cmdhf.c \
cmdhflist.c \ cmdhflist.c \
@ -153,10 +180,12 @@ CMDSRCS = crapto1/crapto1.c \
cmdhficlass.c \ cmdhficlass.c \
cmdhfmf.c \ cmdhfmf.c \
cmdhfmfu.c \ cmdhfmfu.c \
cmdhfmfp.c \
cmdhfmfhard.c \ cmdhfmfhard.c \
hardnested/hardnested_bruteforce.c \ hardnested/hardnested_bruteforce.c \
cmdhfmfdes.c \ cmdhfmfdes.c \
cmdhftopaz.c \ cmdhftopaz.c \
cmdhffido.c \
cmdhffelica.c \ cmdhffelica.c \
cmdhw.c \ cmdhw.c \
cmdlf.c \ cmdlf.c \
@ -170,6 +199,7 @@ CMDSRCS = crapto1/crapto1.c \
cmdlfio.c \ cmdlfio.c \
cmdlfindala.c \ cmdlfindala.c \
cmdlfjablotron.c \ cmdlfjablotron.c \
cmdlfkeri.c \
cmdlfnexwatch.c \ cmdlfnexwatch.c \
cmdlfnedap.c \ cmdlfnedap.c \
cmdlfnoralsy.c \ cmdlfnoralsy.c \
@ -186,6 +216,7 @@ CMDSRCS = crapto1/crapto1.c \
cmdtrace.c \ cmdtrace.c \
cmdflashmem.c \ cmdflashmem.c \
cmdsmartcard.c \ cmdsmartcard.c \
cmdusart.c \
cmdparser.c \ cmdparser.c \
cmdmain.c \ cmdmain.c \
pm3_binlib.c \ pm3_binlib.c \
@ -200,7 +231,6 @@ CMDSRCS = crapto1/crapto1.c \
reveng/bmpbit.c \ reveng/bmpbit.c \
reveng/model.c \ reveng/model.c \
reveng/poly.c \ reveng/poly.c \
reveng/getopt.c \
bucketsort.c bucketsort.c
cpu_arch = $(shell uname -m) cpu_arch = $(shell uname -m)
@ -222,6 +252,7 @@ QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp guidummy.cpp
COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o)
CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o)
OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o)
ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o) ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o)
MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \
$(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \ $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \
@ -247,82 +278,124 @@ ifeq "$(SUPPORTS_AVX512)" "True"
endif endif
BINS = proxmark3 flasher fpga_compress BINS = proxmark3 flasher fpga_compress
WINBINS = $(patsubst %, %.exe, $(BINS)) CLEAN = $(BINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/pm3_cmd.lua lualibs/mf_default_keys.lua
CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua
# need to assign dependancies to build these first... # need to assign dependancies to build these first...
all: lua_build $(BINS) all: lua_build jansson_build mbedtls_build cbor_build $(BINS)
all-static: LDLIBS:=-static $(LDLIBS) all-static: LDLIBS:=-static $(LDLIBS)
all-static: proxmark3 flasher fpga_compress all-static: proxmark3 flasher fpga_compress
proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS)
proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/pm3_cmd.lua lualibs/mf_default_keys.lua
$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ $(info [=] LD $@)
$(Q)$(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@
flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) $(OBJCOBJS)
$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ $(info [=] LD $@)
$(Q)$(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@
fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS) fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS)
$(LD) $(LDFLAGS) $(ZLIBFLAGS) $^ $(LDLIBS) -o $@ $(info [=] LD $@)
$(Q)$(LD) $(LDFLAGS) $(ZLIBFLAGS) $^ $(LDLIBS) -o $@
proxgui.cpp: ui/ui_overlays.h proxgui.cpp: ui/ui_overlays.h
proxguiqt.moc.cpp: proxguiqt.h proxguiqt.moc.cpp: proxguiqt.h
$(MOC) -o$@ $^ $(info [-] MOC $@)
$(Q)$(MOC) -o$@ $^
ui/ui_overlays.h: ui/overlays.ui ui/ui_overlays.h: ui/overlays.ui
$(UIC) $^ > $@ $(info [-] UIC $@)
$(Q)$(UIC) $^ > $@
lualibs/usb_cmd.lua: ../include/usb_cmd.h lualibs/pm3_cmd.lua: ../include/pm3_cmd.h
awk -f usb_cmd_h2lua.awk $^ > $@ $(info [=] GEN $@)
$(Q)awk -f pm3_cmd_h2lua.awk $^ > $@
lualibs/mf_default_keys.lua : default_keys.dic lualibs/mf_default_keys.lua : default_keys.dic
awk -f default_keys_dic2lua.awk $^ > $@ $(info [=] GEN $@)
$(Q)awk -f default_keys_dic2lua.awk $^ > $@
clean: clean:
$(RM) $(CLEAN) $(Q)$(RM) $(CLEAN)
cd ../liblua && make clean $(Q)$(MAKE) --no-print-directory -C ../liblua clean
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) clean
$(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) clean
tarbin: $(BINS) tarbin: $(BINS)
$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) $(info [=] TAR ../proxmark3-$(platform)-bin.tar)
$(Q)$(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%)
lua_build: lua_build:
@echo Compiling liblua, using platform $(LUAPLATFORM) $(info [*] MAKE liblua for $(LUAPLATFORM))
cd ../liblua && make $(LUAPLATFORM) $(Q)$(MAKE) --no-print-directory -C ../liblua $(LUAPLATFORM)
jansson_build:
$(info [*] MAKE jansson)
$(Q)$(MAKE) --no-print-directory -C $(JANSSONLIBPATH) all
mbedtls_build:
$(info [*] MAKE mbedtls)
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) all
cbor_build:
$(info [*] MAKE tinycbor)
$(Q)$(MAKE) --no-print-directory -C $(CBORLIBPATH) all
.PHONY: all clean .PHONY: all clean
# easy printing of MAKE VARIABLES # easy printing of MAKE VARIABLES
print-%: ; @echo $* = $($*) print-%: ; @echo $* = $($*)
$(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_NOSIMD.o : %.c $(OBJDIR)/%_NOSIMD.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $< $(info [-] CC(NOSIMD) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_NOSIMD.Td) $(CFLAGS) $(HARD_SWITCH_NOSIMD) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_NOSIMD.Td $(OBJDIR)/$*_NOSIMD.d
$(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_MMX.o : %.c $(OBJDIR)/%_MMX.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $< $(info [-] CC(MMX) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_MMX.Td) $(CFLAGS) $(HARD_SWITCH_MMX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_MMX.Td $(OBJDIR)/$*_MMX.d
$(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_SSE2.o : %.c $(OBJDIR)/%_SSE2.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $< $(info [-] CC(SSE2) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_SSE2.Td) $(CFLAGS) $(HARD_SWITCH_SSE2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_SSE2.Td $(OBJDIR)/$*_SSE2.d
$(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_AVX.o : %.c $(OBJDIR)/%_AVX.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $< $(info [-] CC(AVX) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX.Td) $(CFLAGS) $(HARD_SWITCH_AVX) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX.Td $(OBJDIR)/$*_AVX.d
$(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_AVX2.o : %.c $(OBJDIR)/%_AVX2.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $< $(info [-] CC(AVX2) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX2.Td) $(CFLAGS) $(HARD_SWITCH_AVX2) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX2.Td $(OBJDIR)/$*_AVX2.d
$(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%_AVX512.o : %.c $(OBJDIR)/%_AVX512.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $< $(info [-] CC(AVX512) $<)
$(Q)$(CC) $(DEPFLAGS:%.Td=%_AVX512.Td) $(CFLAGS) $(HARD_SWITCH_AVX512) -c -o $@ $<
$(Q)$(MV) -f $(OBJDIR)/$*_AVX512.Td $(OBJDIR)/$*_AVX512.d
%.o: %.c %.o: %.c
$(OBJDIR)/%.o : %.c $(OBJDIR)/%.d $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d
$(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $< $(info [-] CC $<)
$(POSTCOMPILE) $(Q)$(CC) $(DEPFLAGS) $(CFLAGS) $(ZLIBFLAGS) -c -o $@ $<
$(Q)$(POSTCOMPILE)
%.o: %.cpp %.o: %.cpp
$(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d
$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(QTINCLUDES) -c -o $@ $< $(info [-] CXX $<)
$(POSTCOMPILE) $(Q)$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(QTINCLUDES) -c -o $@ $<
$(Q)$(POSTCOMPILE)
%.o: %.m
$(OBJDIR)/%.o : %.m $(OBJDIR)/%.d
$(info [-] CC $<)
$(Q)$(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $<
$(Q)$(POSTCOMPILE)
#$(CMDOBJS) $(COREOBJS): $(notdir $(%.c)) %.d #$(CMDOBJS) $(COREOBJS): $(notdir $(%.c)) %.d
# $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< # $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $<
@ -336,8 +409,10 @@ $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d
# $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c -o $@ $< # $(CXX) $(DEPFLAGS) $(CXXFLAGS) -c -o $@ $<
# $(POSTCOMPILE) # $(POSTCOMPILE)
DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBSRCS) $(MULTIARCHSRCS)) \ DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBSRCS)) \
$(patsubst %.o, %.d, $(MULTIARCHOBJS)) \
$(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \
$(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \
$(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d
$(DEPENDENCY_FILES): ; $(DEPENDENCY_FILES): ;

1
client/aidlist.json Normal file

File diff suppressed because one or more lines are too long

21
client/amiitool/LICENSE Normal file
View file

@ -0,0 +1,21 @@
(c) 2015-2017 Marcos Del Sol Vives
(c) 2016 javiMaD
(c) 2016 Michael Armbruster
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

180
client/amiitool/amiibo.c Normal file
View file

@ -0,0 +1,180 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
* (c) 2016 javiMaD
*
* SPDX-License-Identifier: MIT
*/
#include "amiibo.h"
#include "mbedtls/md.h"
#include "mbedtls/aes.h"
#define HMAC_POS_DATA 0x008
#define HMAC_POS_TAG 0x1B4
void nfc3d_amiibo_calc_seed(const uint8_t *dump, uint8_t *key) {
memcpy(key + 0x00, dump + 0x029, 0x02);
memset(key + 0x02, 0x00, 0x0E);
memcpy(key + 0x10, dump + 0x1D4, 0x08);
memcpy(key + 0x18, dump + 0x1D4, 0x08);
memcpy(key + 0x20, dump + 0x1E8, 0x20);
}
void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys *masterKeys, const uint8_t *dump, nfc3d_keygen_derivedkeys *derivedKeys) {
uint8_t seed[NFC3D_KEYGEN_SEED_SIZE];
nfc3d_amiibo_calc_seed(dump, seed);
nfc3d_keygen(masterKeys, seed, derivedKeys);
}
void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys *keys, const uint8_t *in, uint8_t *out) {
mbedtls_aes_context aes;
size_t nc_off = 0;
unsigned char nonce_counter[16];
unsigned char stream_block[16];
mbedtls_aes_setkey_enc(&aes, keys->aesKey, 128);
memset(nonce_counter, 0, sizeof(nonce_counter));
memset(stream_block, 0, sizeof(stream_block));
memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter));
mbedtls_aes_crypt_ctr(&aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C);
memcpy(out + 0x000, in + 0x000, 0x008);
// Data signature NOT copied
memcpy(out + 0x028, in + 0x028, 0x004);
// Tag signature NOT copied
memcpy(out + 0x1D4, in + 0x1D4, 0x034);
}
void nfc3d_amiibo_tag_to_internal(const uint8_t *tag, uint8_t *intl) {
memcpy(intl + 0x000, tag + 0x008, 0x008);
memcpy(intl + 0x008, tag + 0x080, 0x020);
memcpy(intl + 0x028, tag + 0x010, 0x024);
memcpy(intl + 0x04C, tag + 0x0A0, 0x168);
memcpy(intl + 0x1B4, tag + 0x034, 0x020);
memcpy(intl + 0x1D4, tag + 0x000, 0x008);
memcpy(intl + 0x1DC, tag + 0x054, 0x02C);
}
void nfc3d_amiibo_internal_to_tag(const uint8_t *intl, uint8_t *tag) {
memcpy(tag + 0x008, intl + 0x000, 0x008);
memcpy(tag + 0x080, intl + 0x008, 0x020);
memcpy(tag + 0x010, intl + 0x028, 0x024);
memcpy(tag + 0x0A0, intl + 0x04C, 0x168);
memcpy(tag + 0x034, intl + 0x1B4, 0x020);
memcpy(tag + 0x000, intl + 0x1D4, 0x008);
memcpy(tag + 0x054, intl + 0x1DC, 0x02C);
}
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain) {
uint8_t internal[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys dataKeys;
nfc3d_keygen_derivedkeys tagKeys;
// Convert format
nfc3d_amiibo_tag_to_internal(tag, internal);
// Generate keys
nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys);
nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys);
// Decrypt
nfc3d_amiibo_cipher(&dataKeys, internal, plain);
// Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC!
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, plain + HMAC_POS_TAG);
// Regenerate data HMAC
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey),
plain + 0x029, 0x1DF, plain + HMAC_POS_DATA);
return
memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 &&
memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0;
}
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag) {
uint8_t cipher[NFC3D_AMIIBO_SIZE];
nfc3d_keygen_derivedkeys tagKeys;
nfc3d_keygen_derivedkeys dataKeys;
// Generate keys
nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys);
nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys);
// Generate tag HMAC
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey),
plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG);
// Init mbedtls HMAC context
mbedtls_md_context_t ctx;
mbedtls_md_init(&ctx);
mbedtls_md_setup(&ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
// Generate data HMAC
mbedtls_md_hmac_starts(&ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey));
mbedtls_md_hmac_update(&ctx, plain + 0x029, 0x18B); // Data
mbedtls_md_hmac_update(&ctx, cipher + HMAC_POS_TAG, 0x20); // Tag HMAC
mbedtls_md_hmac_update(&ctx, plain + 0x1D4, 0x34); // Here be dragons
mbedtls_md_hmac_finish(&ctx, cipher + HMAC_POS_DATA);
// HMAC cleanup
mbedtls_md_free(&ctx);
// Encrypt
nfc3d_amiibo_cipher(&dataKeys, plain, cipher);
// Convert back to hardware
nfc3d_amiibo_internal_to_tag(cipher, tag);
}
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path) {
FILE *f = fopen(path, "rb");
if (!f) {
return false;
}
if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) {
fclose(f);
return false;
}
fclose(f);
if (
(amiiboKeys->data.magicBytesSize > 16) ||
(amiiboKeys->tag.magicBytesSize > 16)
) {
return false;
}
return true;
}
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst) {
//uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29);
//uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4);
/* increment write counters */
//*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1);
//*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1);
uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1;
uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1;
num_to_bytes(ami_nb_wr, 2, dst + 0x29);
num_to_bytes(cfg_nb_wr, 2, dst + 0xB4);
/* copy flags */
dst[0x2C] = src[0x2C];
/* copy programID */
memcpy(dst + 0xAC, src + 0xAC, 8);
/* copy AppID */
memcpy(dst + 0xB6, src + 0xB6, 4);
/* copy AppData */
memcpy(dst + 0xDC, src + 0xDC, 216);
}

32
client/amiitool/amiibo.h Normal file
View file

@ -0,0 +1,32 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
* (c) 2016 javiMaD
*
* SPDX-License-Identifier: MIT
*/
#ifndef HAVE_NFC3D_AMIIBO_H
#define HAVE_NFC3D_AMIIBO_H
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
#include "keygen.h"
#include "util.h"
#define NFC3D_AMIIBO_SIZE 520
#pragma pack(1)
typedef struct {
nfc3d_keygen_masterkeys data;
nfc3d_keygen_masterkeys tag;
} nfc3d_amiibo_keys;
#pragma pack()
bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *tag, uint8_t *plain);
void nfc3d_amiibo_pack(const nfc3d_amiibo_keys *amiiboKeys, const uint8_t *plain, uint8_t *tag);
bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys *amiiboKeys, const char *path);
void nfc3d_amiibo_copy_app_data(const uint8_t *src, uint8_t *dst);
#endif

175
client/amiitool/amiitool.c Normal file
View file

@ -0,0 +1,175 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
* (c) 2016 javiMaD
*
* SPDX-License-Identifier: MIT
*/
#include <amiibo.h>
#include <stdio.h>
#include <string.h>
#include "../loclass/fileutils.h"
#define NTAG215_SIZE 540
static char *self;
void amiitool_usage() {
fprintf(stderr,
"amiitool build %i (commit %s-%08x)\n"
"by Marcos Del Sol Vives <marcos@dracon.es>\n"
"\n"
"Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n"
" -e encrypt and sign amiibo\n"
" -d decrypt and test amiibo\n"
" -c decrypt, copy AppData and encrypt amiibo\n"
" -k key set file. For retail amiibo, use \"retail unfixed\" key set\n"
" -i input file. If not specified, stdin will be used.\n"
" -s input save file, save from this file will replace input file ones.\n"
" -o output file. If not specified, stdout will be used.\n"
" -l decrypt files with invalid signatures.\n",
, self
);
}
static bool LoadAmiikey(nfc3d_amiibo_keys keys, char *keyfile) {
if (!nfc3d_amiibo_load_keys(&keys, keyfile)) {
PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile);
return false;
}
return true;
}
int main(int argc, char **argv) {
self = argv[0];
char *infile = NULL;
char *savefile = NULL;
char *outfile = NULL;
char *keyfile = NULL;
char op = '\0';
bool lenient = false;
char c;
while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) {
switch (c) {
case 'e':
case 'd':
case 'c':
op = c;
break;
case 'i':
infile = optarg;
break;
case 's':
savefile = optarg;
break;
case 'o':
outfile = optarg;
break;
case 'l':
lenient = true;
break;
default:
amiitool_usage();
return 2;
}
}
if (op == '\0' || keyfile == NULL) {
amiitool_usage();
return 1;
}
nfc3d_amiibo_keys amiiboKeys;
uint8_t original[NTAG215_SIZE];
uint8_t modified[NFC3D_AMIIBO_SIZE];
FILE *f = stdin;
if (infile) {
f = fopen(infile, "rb");
if (!f) {
fprintf(stderr, "Could not open input file\n");
return 3;
}
}
size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f);
if (readPages < NFC3D_AMIIBO_SIZE / 4) {
fprintf(stderr, "Could not read from input\n");
fclose(f);
return 3;
}
fclose(f);
if (op == 'e') {
nfc3d_amiibo_pack(&amiiboKeys, original, modified);
} else if (op == 'd') {
if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) {
fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
if (!lenient) {
return 6;
}
}
} else { /* copy */
uint8_t plain_base[NFC3D_AMIIBO_SIZE];
uint8_t plain_save[NFC3D_AMIIBO_SIZE];
if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) {
fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
if (!lenient) {
return 6;
}
}
if (savefile) {
f = fopen(savefile, "rb");
if (!f) {
fprintf(stderr, "Could not open save file\n");
return 3;
}
}
size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f);
if (readPages < NFC3D_AMIIBO_SIZE / 4) {
fprintf(stderr, "Could not read from save\n");
fclose(f);
return 3;
}
fclose(f);
if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) {
fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n");
if (!lenient) {
return 6;
}
}
nfc3d_amiibo_copy_app_data(plain_save, plain_base);
nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified);
}
f = stdout;
if (outfile) {
f = fopen(outfile, "wb");
if (!f) {
fprintf(stderr, "Could not open output file\n");
return 4;
}
}
if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) {
fprintf(stderr, "Could not write to output\n");
fclose(f);
return 4;
}
if (readPages > NFC3D_AMIIBO_SIZE / 4) {
if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) {
fprintf(stderr, "Could not write to output:\n");
fclose(f);
return 4;
}
}
fclose(f);
return 0;
}

78
client/amiitool/drbg.c Normal file
View file

@ -0,0 +1,78 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
* (c) 2016 javiMaD
*
* SPDX-License-Identifier: MIT
*/
#include "drbg.h"
#include <assert.h>
#include <string.h>
#include <mbedtls/md.h>
void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize) {
assert(ctx != NULL);
assert(hmacKey != NULL);
assert(seed != NULL);
assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE);
// Initialize primitives
ctx->used = false;
ctx->iteration = 0;
ctx->bufferSize = sizeof(ctx->iteration) + seedSize;
// The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start
memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize);
// Initialize underlying HMAC context
mbedtls_md_init(&ctx->hmacCtx);
mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1);
mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize);
}
void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output) {
assert(ctx != NULL);
assert(output != NULL);
if (ctx->used) {
// If used at least once, reinitialize the HMAC
mbedtls_md_hmac_reset(&ctx->hmacCtx);
} else {
ctx->used = true;
}
// Store counter in big endian, and increment it
ctx->buffer[0] = ctx->iteration >> 8;
ctx->buffer[1] = ctx->iteration >> 0;
ctx->iteration++;
// Do HMAC magic
mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize);
mbedtls_md_hmac_finish(&ctx->hmacCtx, output);
}
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx) {
assert(ctx != NULL);
mbedtls_md_free(&ctx->hmacCtx);
}
void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize) {
uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE];
nfc3d_drbg_ctx rngCtx;
nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize);
while (outputSize > 0) {
if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) {
nfc3d_drbg_step(&rngCtx, temp);
memcpy(output, temp, outputSize);
break;
}
nfc3d_drbg_step(&rngCtx, output);
output += NFC3D_DRBG_OUTPUT_SIZE;
outputSize -= NFC3D_DRBG_OUTPUT_SIZE;
}
nfc3d_drbg_cleanup(&rngCtx);
}

33
client/amiitool/drbg.h Normal file
View file

@ -0,0 +1,33 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
* (c) 2016 javiMaD
*
* SPDX-License-Identifier: MIT
*/
#ifndef HAVE_NFC3D_DRBG_H
#define HAVE_NFC3D_DRBG_H
#include <stdbool.h>
#include <stdint.h>
#include "mbedtls/md.h"
#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */
#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */
typedef struct {
mbedtls_md_context_t hmacCtx;
bool used;
uint16_t iteration;
uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE];
size_t bufferSize;
} nfc3d_drbg_ctx;
void nfc3d_drbg_init(nfc3d_drbg_ctx *ctx, const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize);
void nfc3d_drbg_step(nfc3d_drbg_ctx *ctx, uint8_t *output);
void nfc3d_drbg_cleanup(nfc3d_drbg_ctx *ctx);
void nfc3d_drbg_generate_bytes(const uint8_t *hmacKey, size_t hmacKeySize, const uint8_t *seed, size_t seedSize, uint8_t *output, size_t outputSize);
#endif

Binary file not shown.

53
client/amiitool/keygen.c Normal file
View file

@ -0,0 +1,53 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
*
* SPDX-License-Identifier: MIT
*/
#include "drbg.h"
#include "keygen.h"
#include <assert.h>
#include <stdio.h>
#include <string.h>
void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, uint8_t *output, size_t *outputSize) {
assert(baseKeys != NULL);
assert(baseSeed != NULL);
assert(output != NULL);
assert(outputSize != NULL);
uint8_t *start = output;
// 1: Copy whole type string
output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString));
// 2: Append (16 - magicBytesSize) from the input seed
size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize;
memcpy(output, baseSeed, leadingSeedBytes);
output += leadingSeedBytes;
// 3: Append all bytes from magicBytes
memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize);
output += baseKeys->magicBytesSize;
// 4: Append bytes 0x10-0x1F from input seed
memcpy(output, baseSeed + 0x10, 16);
output += 16;
// 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them
unsigned int i;
for (i = 0; i < 32; i++) {
output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i];
}
output += 32;
*outputSize = output - start;
}
void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys) {
uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE];
size_t preparedSeedSize;
nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize);
nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys));
}

34
client/amiitool/keygen.h Normal file
View file

@ -0,0 +1,34 @@
/*
* (c) 2015-2017 Marcos Del Sol Vives
*
* SPDX-License-Identifier: MIT
*/
#ifndef HAVE_NFC3D_KEYGEN_H
#define HAVE_NFC3D_KEYGEN_H
#include <stdint.h>
#include <stdbool.h>
#define NFC3D_KEYGEN_SEED_SIZE 64
#pragma pack(1)
typedef struct {
uint8_t hmacKey[16];
char typeString[14];
uint8_t rfu;
uint8_t magicBytesSize;
uint8_t magicBytes[16];
uint8_t xorPad[32];
} nfc3d_keygen_masterkeys;
typedef struct {
const uint8_t aesKey[16];
const uint8_t aesIV[16];
const uint8_t hmacKey[16];
} nfc3d_keygen_derivedkeys;
#pragma pack()
void nfc3d_keygen(const nfc3d_keygen_masterkeys *baseKeys, const uint8_t *baseSeed, nfc3d_keygen_derivedkeys *derivedKeys);
#endif

View file

@ -1,58 +0,0 @@
//-----------------------------------------------------------------------------
// 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.
//-----------------------------------------------------------------------------
// Command line binary
//-----------------------------------------------------------------------------
#include <stdio.h>
#include "util_posix.h"
#include "ui.h"
//#include "proxusb.h"
#include "cmdmain.h"
#define HANDLE_ERROR if (error_occured) { \
error_occured = 0;\
break;\
}
int main(int argc, char **argv)
{
if (argc != 3 && argc != 4)
{
printf("\n\tusage: cli <command 1> <command 2> [logfile (default cli.log)]\n");
printf("\n");
printf("\texample: cli hi14asnoop hi14alist h14a.log\n");
printf("\n");
return -1;
}
usb_init();
if (argc == 4)
SetLogFilename(argv[3]);
else
SetLogFilename("cli.log");
return_on_error = 1;
while (1) {
while (!OpenProxmark()) { sleep(1); }
while (1) {
UsbCommand cmdbuf;
CommandReceived(argv[1]);
HANDLE_ERROR;
ReceiveCommand(&cmdbuf);
HANDLE_ERROR;
for (int i = 0; i < 5; ++i) {
ReceiveCommandPoll(&cmdbuf);
}
HANDLE_ERROR;
CommandReceived(argv[2]);
HANDLE_ERROR;
}
}
CloseProxmark();
return 0;
}

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