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.

159
Makefile
View file

@ -1,60 +1,98 @@
# 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
# Windows yields literal "", on Linux yields an empty line # Windows yields literal "", on Linux yields an empty line
ifeq ($(shell echo ""),) ifeq ($(shell echo ""),)
# This is probably a proper system, so we can use uname # This is probably a proper system, so we can use uname
DELETE=rm -rf DELETE=rm -rf
FLASH_TOOL=client/flasher FLASH_TOOL=client/flasher
platform=$(shell uname) platform=$(shell uname)
ifneq (,$(findstring MINGW,$(platform))) ifneq (,$(findstring MINGW,$(platform)))
FLASH_PORT=com3 FLASH_PORT=com3
PATHSEP=\\# PATHSEP=\\#
else
FLASH_PORT=/dev/ttyACM0
PATHSEP=/
endif
else else
FLASH_PORT=/dev/ttyACM0 # Assume that we are running on native Windows
PATHSEP=/ DELETE=del /q
endif FLASH_TOOL=client/flasher.exe
else platform=Windows
# Assume that we are running on native Windows FLASH_PORT=com3
DELETE=del /q PATHSEP=\\#
FLASH_TOOL=client/flasher.exe
platform=Windows
FLASH_PORT=com3
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

@ -13,7 +13,7 @@
// BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces. // BigBuf is the large multi-purpose buffer, typically used to hold A/D samples or traces.
// Also used to hold various smaller buffers and the Mifare Emulator Memory. // Also used to hold various smaller buffers and the Mifare Emulator Memory.
// declare it as uint32_t to achieve alignment to 4 Byte boundary // declare it as uint32_t to achieve alignment to 4 Byte boundary
static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)]; static uint32_t BigBuf[BIGBUF_SIZE / sizeof(uint32_t)];
/* BigBuf memory layout: /* BigBuf memory layout:
Pointer to highest available memory: BigBuf_hi Pointer to highest available memory: BigBuf_hi
@ -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) {
@ -79,7 +79,7 @@ uint8_t *BigBuf_malloc(uint16_t chunksize) {
} }
// free ALL allocated chunks. The whole BigBuf is available for traces or samples again. // free ALL allocated chunks. The whole BigBuf is available for traces or samples again.
void BigBuf_free(void){ void BigBuf_free(void) {
BigBuf_hi = BIGBUF_SIZE; BigBuf_hi = BIGBUF_SIZE;
emulator_memory = NULL; emulator_memory = NULL;
// shouldn't this empty BigBuf also? // shouldn't this empty BigBuf also?
@ -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,52 +195,11 @@ 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();
if (offset + length < CARD_MEMORY_SIZE) { if (offset + length < CARD_MEMORY_SIZE) {
memcpy(mem+offset, data, length); memcpy(mem + offset, data, length);
return 0; return 0;
} }
Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE);

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,17 +7,15 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#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
// bit set since they're implemented as defines, se we need to invert bit // bit set since they're implemented as defines, se we need to invert bit
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,31 +25,27 @@ 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
for (j=0;j < width;j++) // pixels per line for (j = 0; j < width; j++) // pixels per line
LCDSend(color); LCDSend(color);
} }
} }
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;
data = font_style; // point to the start of the font table data = font_style; // point to the start of the font table
@ -62,33 +56,31 @@ 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));
for (i=0;i < yme;i++) { for (i = 0; i < yme; i++) {
mask |=0x80; mask |= 0x80;
for (px=x; px < (x + xme); px++) { for (px = x; px < (x + xme); px++) {
py= y + i; py = y + i;
if (*data & mask) LCDSetPixel (px,py,fcolor); if (*data & mask) LCDSetPixel(px, py, fcolor);
else LCDSetPixel (px,py,bcolor); else LCDSetPixel(px, py, bcolor);
mask>>=1; mask >>= 1;
} }
data++; data++;
} }
x+=xme; x += xme;
lcd_string++; // next character in string lcd_string++; // next character in string
} 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();
@ -121,29 +112,29 @@ void LCDInit(void)
LCDSend(0xDC); LCDSend(0xDC);
// clear display // clear display
LCDSetXY(0,0); LCDSetXY(0, 0);
LCDSend(PRAMWR); // Write to display LCDSend(PRAMWR); // Write to display
i=LCD_XRES*LCD_YRES; i = LCD_XRES * LCD_YRES;
while(i--) LCDSend(WHITE); while (i--) LCDSend(WHITE);
// test text on different colored backgrounds // test text on different colored backgrounds
LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); LCDString(" The quick brown fox ", (char *)&FONT6x8, 1, 1 + 8 * 0, WHITE, BLACK);
LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE ); LCDString(" jumped over the ", (char *)&FONT6x8, 1, 1 + 8 * 1, BLACK, WHITE);
LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED ); LCDString(" lazy dog. ", (char *)&FONT6x8, 1, 1 + 8 * 2, YELLOW, RED);
LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN ); LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8, 1, 1 + 8 * 3, RED, GREEN);
LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE ); LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8, 1, 1 + 8 * 4, MAGENTA, BLUE);
LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8, 1, 1 + 8 * 5, BLUE, YELLOW);
LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN ); LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8, 1, 1 + 8 * 6, BLACK, CYAN);
LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8, 1, 1 + 8 * 7, BLUE, MAGENTA);
// color bands // color bands
LCDFill(0, 1+8* 8, 132, 8, BLACK); LCDFill(0, 1 + 8 * 8, 132, 8, BLACK);
LCDFill(0, 1+8* 9, 132, 8, WHITE); LCDFill(0, 1 + 8 * 9, 132, 8, WHITE);
LCDFill(0, 1+8*10, 132, 8, RED); LCDFill(0, 1 + 8 * 10, 132, 8, RED);
LCDFill(0, 1+8*11, 132, 8, GREEN); LCDFill(0, 1 + 8 * 11, 132, 8, GREEN);
LCDFill(0, 1+8*12, 132, 8, BLUE); LCDFill(0, 1 + 8 * 12, 132, 8, BLUE);
LCDFill(0, 1+8*13, 132, 8, YELLOW); LCDFill(0, 1 + 8 * 13, 132, 8, YELLOW);
LCDFill(0, 1+8*14, 132, 8, CYAN); LCDFill(0, 1 + 8 * 14, 132, 8, CYAN);
LCDFill(0, 1+8*15, 132, 8, MAGENTA); LCDFill(0, 1 + 8 * 15, 132, 8, MAGENTA);
} }

View file

@ -124,7 +124,7 @@ void LCDInit(void);
void LCDReset(void); void LCDReset(void);
void LCDSetXY(unsigned char x, unsigned char y); void LCDSetXY(unsigned char x, unsigned char y);
void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color); void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color);
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);
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);
#endif #endif

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.
@ -70,12 +230,11 @@ void RunMod() {
uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now) uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now)
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;
/* /*
@ -105,25 +264,7 @@ void RunMod() {
int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t);
for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) {
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;
} }
/* /*
@ -133,8 +274,8 @@ void RunMod() {
Dbprintf("[+] Printing mf keys"); Dbprintf("[+] Printing mf keys");
for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++) for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++)
Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt,
(keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6 * keycnt)[0], (keyBlock + 6 * keycnt)[1], (keyBlock + 6 * keycnt)[2],
(keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); (keyBlock + 6 * keycnt)[3], (keyBlock + 6 * keycnt)[4], (keyBlock + 6 * keycnt)[5], 6);
DbpString("--------------------------------------------------------"); DbpString("--------------------------------------------------------");
} }
@ -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!");
@ -181,8 +320,8 @@ void RunMod() {
validKey[type][sec] = true; validKey[type][sec] = true;
keyFound = true; keyFound = true;
Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n",
(keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2], (keyBlock + 6 * key)[0], (keyBlock + 6 * key)[1], (keyBlock + 6 * key)[2],
(keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5] (keyBlock + 6 * key)[3], (keyBlock + 6 * key)[4], (keyBlock + 6 * key)[5]
); );
} }
@ -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 {
@ -221,7 +358,7 @@ void RunMod() {
emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4) emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4)
for (uint16_t t = 0; t < 2; t++) { for (uint16_t t = 0; t < 2; t++) {
if (validKey[t][sectorNo]) { if (validKey[t][sectorNo]) {
memcpy(mblock + t*10, foundKey[t][sectorNo], 6); memcpy(mblock + t * 10, foundKey[t][sectorNo], 6);
} }
} }
emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1);
@ -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,15 +57,15 @@ 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]) {
Dbprintf("Button press detected -- replaying card in bank[%d]", selected); Dbprintf("Button press detected -- replaying card in bank[%d]", selected);
break; break;
} else if (cardRead[(selected+1) % OPTS]) { } else if (cardRead[(selected + 1) % OPTS]) {
Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected + 1) % OPTS);
selected = (selected+1) % OPTS; selected = (selected + 1) % OPTS;
break; // playing = 1; break; // playing = 1;
} else { } else {
Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); Dbprintf("Button press detected but no stored tag to play. (Ignoring button)");
@ -74,12 +79,12 @@ void RunMod() {
Dbprintf("Read UID:"); Dbprintf("Read UID:");
Dbhexdump(card[selected].uidlen, card[selected].uid, 0); Dbhexdump(card[selected].uidlen, card[selected].uid, 0);
if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { if (memcmp(uids[(selected + 1) % OPTS].uid, card[selected].uid, card[selected].uidlen) == 0) {
Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping.");
} else { } else {
uids[selected].sak = card[selected].sak; uids[selected].sak = card[selected].sak;
uids[selected].uidlen = card[selected].uidlen; uids[selected].uidlen = card[selected].uidlen;
memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); memcpy(uids[selected].uid, card[selected].uid, uids[selected].uidlen);
memcpy(uids[selected].atqa, card[selected].atqa, 2); memcpy(uids[selected].atqa, card[selected].atqa, 2);
if (uids[selected].uidlen > 4) if (uids[selected].uidlen > 4)
@ -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);
@ -109,11 +114,11 @@ void RunMod() {
} }
/* MF Classic UID clone */ /* MF Classic UID clone */
else if (iGotoClone==1) { else if (iGotoClone == 1) {
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);
@ -175,7 +179,7 @@ void RunMod() {
MifareCSetBlock(params, 0, newBlock0); MifareCSetBlock(params, 0, newBlock0);
MifareCGetBlock(params, 0, testBlock0); MifareCGetBlock(params, 0, testBlock0);
if (memcmp(testBlock0, newBlock0, 16)==0) { if (memcmp(testBlock0, newBlock0, 16) == 0) {
DbpString("Cloned successfull!"); DbpString("Cloned successfull!");
cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it
playing = 0; playing = 0;
@ -192,28 +196,28 @@ void RunMod() {
// Change where to record (or begin playing) // Change where to record (or begin playing)
// button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected])
else if (playing==1) { else if (playing == 1) {
LEDsoff(); LEDsoff();
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);
uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen);
if ( uids[selected].uidlen == 7 ) { if (uids[selected].uidlen == 7) {
flags = FLAG_7B_UID_IN_DATA; flags = FLAG_7B_UID_IN_DATA;
Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected);
} else { } else {

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,13 +58,13 @@ 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");
// wait for button to be released // wait for button to be released
while(BUTTON_PRESS()) while (BUTTON_PRESS())
WDT_HIT(); WDT_HIT();
/* need this delay to prevent catching some weird data */ /* need this delay to prevent catching some weird data */
@ -75,17 +80,16 @@ 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]);
// wait for button to be released // wait for button to be released
while(BUTTON_PRESS()) while (BUTTON_PRESS())
WDT_HIT(); WDT_HIT();
/* need this delay to prevent catching some weird data */ /* need this delay to prevent catching some weird data */
@ -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,20 +144,18 @@ 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.
// Brute force code // Brute force code
// Check if the badge is an HID Corporate 1000 // Check if the badge is an HID Corporate 1000
if( (high[selected] & 0xFFFFFFF8) != 0x28 ) { if ((high[selected] & 0xFFFFFFF8) != 0x28) {
DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce."); DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce.");
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())
@ -161,12 +163,12 @@ void RunMod() {
// Calculate Facility Code and Card Number from high and low // Calculate Facility Code and Card Number from high and low
uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF; uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF;
uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21); uint32_t fc = ((high[selected] & 1) << 11) | (low[selected] >> 21);
uint32_t original_cardnum = cardnum; uint32_t original_cardnum = cardnum;
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()) {
@ -234,7 +236,7 @@ void RunMod() {
LED(selected + 1, 0); LED(selected + 1, 0);
} else { } else {
while(BUTTON_PRESS()) while (BUTTON_PRESS())
WDT_HIT(); WDT_HIT();
} }
} }
@ -246,7 +248,7 @@ out:
} }
// Function that calculate next value for the brutforce of HID corporate 1000 // Function that calculate next value for the brutforce of HID corporate 1000
void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) { void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) {
uint32_t new_high = 0; uint32_t new_high = 0;
uint32_t new_low = 0; uint32_t new_low = 0;
@ -263,8 +265,8 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6; uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6;
n_ones = 0; n_ones = 0;
// Calculate number of ones in low number // Calculate number of ones in low number
for ( i = 1; i != 0; i <<= 1) { for (i = 1; i != 0; i <<= 1) {
if( parity_bit_34_low & i ) if (parity_bit_34_low & i)
n_ones++; n_ones++;
} }
// Calculate number of ones in high number // Calculate number of ones in high number
@ -281,15 +283,15 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
n_ones = 0; n_ones = 0;
// Calculate number of ones in low number // Calculate number of ones in low number
for ( i=1; i != 0; i <<= 1) { for (i = 1; i != 0; i <<= 1) {
if( parity_bit_1_low & i ) if (parity_bit_1_low & i)
n_ones++; n_ones++;
} }
// Calculate number of ones in high number // Calculate number of ones in high number
if ( new_high & 0x1) if (new_high & 0x1)
n_ones++; n_ones++;
if ( new_high & 0x2) if (new_high & 0x2)
n_ones++; n_ones++;
// Set parity bit (Odd parity) // Set parity bit (Odd parity)
@ -300,14 +302,14 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo
n_ones = 0; n_ones = 0;
// Calculate number of ones in low number (all bit of low, bitmask unnecessary) // Calculate number of ones in low number (all bit of low, bitmask unnecessary)
for (i = 1; i != 0; i <<= 1) { for (i = 1; i != 0; i <<= 1) {
if ( new_low & i ) if (new_low & i)
n_ones++; n_ones++;
} }
// Calculate number of ones in high number // Calculate number of ones in high number
if ( new_high & 0x1) if (new_high & 0x1)
n_ones++; n_ones++;
if ( new_high & 0x2) if (new_high & 0x2)
n_ones++; n_ones++;
// Set parity bit (Odd parity) // Set parity bit (Odd parity)

View file

@ -19,6 +19,6 @@
#define OPTS 3 #define OPTS 3
void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc); void hid_corporate_1000_calculate_checksum_and_set(uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc);
#endif /* __LF_HIDBRUTE_H */ #endif /* __LF_HIDBRUTE_H */

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())
@ -118,12 +122,12 @@ void RunMod() {
worked or not, so its a crap shoot. One option is to time how long worked or not, so its a crap shoot. One option is to time how long
it takes to get a valid ID then start from scratch every time. it takes to get a valid ID then start from scratch every time.
*/ */
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");
break; break;
@ -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,12 +680,11 @@ 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;
rk[0] = GETU32(cipherKey ); rk[0] = GETU32(cipherKey);
rk[1] = GETU32(cipherKey + 4); rk[1] = GETU32(cipherKey + 4);
rk[2] = GETU32(cipherKey + 8); rk[2] = GETU32(cipherKey + 8);
rk[3] = GETU32(cipherKey + 12); rk[3] = GETU32(cipherKey + 12);
@ -695,7 +694,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[4] = rk[0] ^ rk[4] = rk[0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i]; rcon[i];
rk[5] = rk[1] ^ rk[4]; rk[5] = rk[1] ^ rk[4];
@ -715,7 +714,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[ 6] = rk[ 0] ^ rk[ 6] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i]; rcon[i];
rk[ 7] = rk[ 1] ^ rk[ 6]; rk[ 7] = rk[ 1] ^ rk[ 6];
@ -737,7 +736,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
rk[ 8] = rk[ 0] ^ rk[ 8] = rk[ 0] ^
(Te4[(temp >> 16) & 0xff] & 0xff000000) ^ (Te4[(temp >> 16) & 0xff] & 0xff000000) ^
(Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 8) & 0xff] & 0x00ff0000) ^
(Te4[(temp ) & 0xff] & 0x0000ff00) ^ (Te4[(temp) & 0xff] & 0x0000ff00) ^
(Te4[(temp >> 24) ] & 0x000000ff) ^ (Te4[(temp >> 24) ] & 0x000000ff) ^
rcon[i]; rcon[i];
rk[ 9] = rk[ 1] ^ rk[ 8]; rk[ 9] = rk[ 1] ^ rk[ 8];
@ -751,7 +750,7 @@ int aes_setkey_enc(unsigned int rk[], const unsigned char cipherKey[], int keyBy
(Te4[(temp >> 24) ] & 0xff000000) ^ (Te4[(temp >> 24) ] & 0xff000000) ^
(Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(temp >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(temp >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(temp ) & 0xff] & 0x000000ff); (Te4[(temp) & 0xff] & 0x000000ff);
rk[13] = rk[ 5] ^ rk[12]; rk[13] = rk[ 5] ^ rk[12];
rk[14] = rk[ 6] ^ rk[13]; rk[14] = rk[ 6] ^ rk[13];
rk[15] = rk[ 7] ^ rk[14]; rk[15] = rk[ 7] ^ rk[14];
@ -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
@ -790,22 +788,22 @@ int AesGenKeySched(unsigned int rk[], unsigned int rrk[], const unsigned char ci
Td0[Te4[(rk[0] >> 24) ] & 0xff] ^ Td0[Te4[(rk[0] >> 24) ] & 0xff] ^
Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^ Td1[Te4[(rk[0] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^ Td2[Te4[(rk[0] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[0] ) & 0xff] & 0xff]; Td3[Te4[(rk[0]) & 0xff] & 0xff];
rrk[1] = rrk[1] =
Td0[Te4[(rk[1] >> 24) ] & 0xff] ^ Td0[Te4[(rk[1] >> 24) ] & 0xff] ^
Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^ Td1[Te4[(rk[1] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^ Td2[Te4[(rk[1] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[1] ) & 0xff] & 0xff]; Td3[Te4[(rk[1]) & 0xff] & 0xff];
rrk[2] = rrk[2] =
Td0[Te4[(rk[2] >> 24) ] & 0xff] ^ Td0[Te4[(rk[2] >> 24) ] & 0xff] ^
Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^ Td1[Te4[(rk[2] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^ Td2[Te4[(rk[2] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[2] ) & 0xff] & 0xff]; Td3[Te4[(rk[2]) & 0xff] & 0xff];
rrk[3] = rrk[3] =
Td0[Te4[(rk[3] >> 24) ] & 0xff] ^ Td0[Te4[(rk[3] >> 24) ] & 0xff] ^
Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^ Td1[Te4[(rk[3] >> 16) & 0xff] & 0xff] ^
Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^ Td2[Te4[(rk[3] >> 8) & 0xff] & 0xff] ^
Td3[Te4[(rk[3] ) & 0xff] & 0xff]; Td3[Te4[(rk[3]) & 0xff] & 0xff];
} }
// invert the order of the last round keys // invert the order of the last round keys
rrk -= 4; rrk -= 4;
@ -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;
@ -833,7 +830,7 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
* map byte array block to cipher state * map byte array block to cipher state
* and add initial round key: * and add initial round key:
*/ */
s0 = GETU32(pt ) ^ rk[0]; s0 = GETU32(pt) ^ rk[0];
s1 = GETU32(pt + 4) ^ rk[1]; s1 = GETU32(pt + 4) ^ rk[1];
s2 = GETU32(pt + 8) ^ rk[2]; s2 = GETU32(pt + 8) ^ rk[2];
s3 = GETU32(pt + 12) ^ rk[3]; s3 = GETU32(pt + 12) ^ rk[3];
@ -852,25 +849,25 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
Te0[(s0 >> 24) ] ^ Te0[(s0 >> 24) ] ^
Te1[(s1 >> 16) & 0xff] ^ Te1[(s1 >> 16) & 0xff] ^
Te2[(s2 >> 8) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^
Te3[(s3 ) & 0xff] ^ Te3[(s3) & 0xff] ^
rk[4]; rk[4];
t1 = t1 =
Te0[(s1 >> 24) ] ^ Te0[(s1 >> 24) ] ^
Te1[(s2 >> 16) & 0xff] ^ Te1[(s2 >> 16) & 0xff] ^
Te2[(s3 >> 8) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^
Te3[(s0 ) & 0xff] ^ Te3[(s0) & 0xff] ^
rk[5]; rk[5];
t2 = t2 =
Te0[(s2 >> 24) ] ^ Te0[(s2 >> 24) ] ^
Te1[(s3 >> 16) & 0xff] ^ Te1[(s3 >> 16) & 0xff] ^
Te2[(s0 >> 8) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^
Te3[(s1 ) & 0xff] ^ Te3[(s1) & 0xff] ^
rk[6]; rk[6];
t3 = t3 =
Te0[(s3 >> 24) ] ^ Te0[(s3 >> 24) ] ^
Te1[(s0 >> 16) & 0xff] ^ Te1[(s0 >> 16) & 0xff] ^
Te2[(s1 >> 8) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^
Te3[(s2 ) & 0xff] ^ Te3[(s2) & 0xff] ^
rk[7]; rk[7];
rk += 8; rk += 8;
@ -882,25 +879,25 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
Te0[(t0 >> 24) ] ^ Te0[(t0 >> 24) ] ^
Te1[(t1 >> 16) & 0xff] ^ Te1[(t1 >> 16) & 0xff] ^
Te2[(t2 >> 8) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^
Te3[(t3 ) & 0xff] ^ Te3[(t3) & 0xff] ^
rk[0]; rk[0];
s1 = s1 =
Te0[(t1 >> 24) ] ^ Te0[(t1 >> 24) ] ^
Te1[(t2 >> 16) & 0xff] ^ Te1[(t2 >> 16) & 0xff] ^
Te2[(t3 >> 8) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^
Te3[(t0 ) & 0xff] ^ Te3[(t0) & 0xff] ^
rk[1]; rk[1];
s2 = s2 =
Te0[(t2 >> 24) ] ^ Te0[(t2 >> 24) ] ^
Te1[(t3 >> 16) & 0xff] ^ Te1[(t3 >> 16) & 0xff] ^
Te2[(t0 >> 8) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^
Te3[(t1 ) & 0xff] ^ Te3[(t1) & 0xff] ^
rk[2]; rk[2];
s3 = s3 =
Te0[(t3 >> 24) ] ^ Te0[(t3 >> 24) ] ^
Te1[(t0 >> 16) & 0xff] ^ Te1[(t0 >> 16) & 0xff] ^
Te2[(t1 >> 8) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^
Te3[(t2 ) & 0xff] ^ Te3[(t2) & 0xff] ^
rk[3]; rk[3];
} }
/* /*
@ -911,28 +908,28 @@ void AesEncBlk(AesCtx *pCtx, const unsigned char pt[], unsigned char ct[])
(Te4[(t0 >> 24) ] & 0xff000000) ^ (Te4[(t0 >> 24) ] & 0xff000000) ^
(Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t3 ) & 0xff] & 0x000000ff) ^ (Te4[(t3) & 0xff] & 0x000000ff) ^
rk[0]; rk[0];
PUTU32(ct , s0); PUTU32(ct, s0);
s1 = s1 =
(Te4[(t1 >> 24) ] & 0xff000000) ^ (Te4[(t1 >> 24) ] & 0xff000000) ^
(Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t0 ) & 0xff] & 0x000000ff) ^ (Te4[(t0) & 0xff] & 0x000000ff) ^
rk[1]; rk[1];
PUTU32(ct + 4, s1); PUTU32(ct + 4, s1);
s2 = s2 =
(Te4[(t2 >> 24) ] & 0xff000000) ^ (Te4[(t2 >> 24) ] & 0xff000000) ^
(Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t1 ) & 0xff] & 0x000000ff) ^ (Te4[(t1) & 0xff] & 0x000000ff) ^
rk[2]; rk[2];
PUTU32(ct + 8, s2); PUTU32(ct + 8, s2);
s3 = s3 =
(Te4[(t3 >> 24) ] & 0xff000000) ^ (Te4[(t3 >> 24) ] & 0xff000000) ^
(Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Te4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Te4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(Te4[(t2 ) & 0xff] & 0x000000ff) ^ (Te4[(t2) & 0xff] & 0x000000ff) ^
rk[3]; rk[3];
PUTU32(ct + 12, s3); PUTU32(ct + 12, s3);
@ -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:
*/ */
@ -972,25 +972,25 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
Td0[(s0 >> 24) ] ^ Td0[(s0 >> 24) ] ^
Td1[(s3 >> 16) & 0xff] ^ Td1[(s3 >> 16) & 0xff] ^
Td2[(s2 >> 8) & 0xff] ^ Td2[(s2 >> 8) & 0xff] ^
Td3[(s1 ) & 0xff] ^ Td3[(s1) & 0xff] ^
rk[4]; rk[4];
t1 = t1 =
Td0[(s1 >> 24) ] ^ Td0[(s1 >> 24) ] ^
Td1[(s0 >> 16) & 0xff] ^ Td1[(s0 >> 16) & 0xff] ^
Td2[(s3 >> 8) & 0xff] ^ Td2[(s3 >> 8) & 0xff] ^
Td3[(s2 ) & 0xff] ^ Td3[(s2) & 0xff] ^
rk[5]; rk[5];
t2 = t2 =
Td0[(s2 >> 24) ] ^ Td0[(s2 >> 24) ] ^
Td1[(s1 >> 16) & 0xff] ^ Td1[(s1 >> 16) & 0xff] ^
Td2[(s0 >> 8) & 0xff] ^ Td2[(s0 >> 8) & 0xff] ^
Td3[(s3 ) & 0xff] ^ Td3[(s3) & 0xff] ^
rk[6]; rk[6];
t3 = t3 =
Td0[(s3 >> 24) ] ^ Td0[(s3 >> 24) ] ^
Td1[(s2 >> 16) & 0xff] ^ Td1[(s2 >> 16) & 0xff] ^
Td2[(s1 >> 8) & 0xff] ^ Td2[(s1 >> 8) & 0xff] ^
Td3[(s0 ) & 0xff] ^ Td3[(s0) & 0xff] ^
rk[7]; rk[7];
rk += 8; rk += 8;
@ -1002,25 +1002,25 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
Td0[(t0 >> 24) ] ^ Td0[(t0 >> 24) ] ^
Td1[(t3 >> 16) & 0xff] ^ Td1[(t3 >> 16) & 0xff] ^
Td2[(t2 >> 8) & 0xff] ^ Td2[(t2 >> 8) & 0xff] ^
Td3[(t1 ) & 0xff] ^ Td3[(t1) & 0xff] ^
rk[0]; rk[0];
s1 = s1 =
Td0[(t1 >> 24) ] ^ Td0[(t1 >> 24) ] ^
Td1[(t0 >> 16) & 0xff] ^ Td1[(t0 >> 16) & 0xff] ^
Td2[(t3 >> 8) & 0xff] ^ Td2[(t3 >> 8) & 0xff] ^
Td3[(t2 ) & 0xff] ^ Td3[(t2) & 0xff] ^
rk[1]; rk[1];
s2 = s2 =
Td0[(t2 >> 24) ] ^ Td0[(t2 >> 24) ] ^
Td1[(t1 >> 16) & 0xff] ^ Td1[(t1 >> 16) & 0xff] ^
Td2[(t0 >> 8) & 0xff] ^ Td2[(t0 >> 8) & 0xff] ^
Td3[(t3 ) & 0xff] ^ Td3[(t3) & 0xff] ^
rk[2]; rk[2];
s3 = s3 =
Td0[(t3 >> 24) ] ^ Td0[(t3 >> 24) ] ^
Td1[(t2 >> 16) & 0xff] ^ Td1[(t2 >> 16) & 0xff] ^
Td2[(t1 >> 8) & 0xff] ^ Td2[(t1 >> 8) & 0xff] ^
Td3[(t0 ) & 0xff] ^ Td3[(t0) & 0xff] ^
rk[3]; rk[3];
} }
/* /*
@ -1031,35 +1031,39 @@ void AesDecBlk(AesCtx *pCtx, const unsigned char ct[], unsigned char pt[])
(Td4[(t0 >> 24) ] & 0xff000000) ^ (Td4[(t0 >> 24) ] & 0xff000000) ^
(Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t1 ) & 0xff] & 0x000000ff) ^ (Td4[(t1) & 0xff] & 0x000000ff) ^
rk[0]; rk[0];
s1 = s1 =
(Td4[(t1 >> 24) ] & 0xff000000) ^ (Td4[(t1 >> 24) ] & 0xff000000) ^
(Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t2 ) & 0xff] & 0x000000ff) ^ (Td4[(t2) & 0xff] & 0x000000ff) ^
rk[1]; rk[1];
s2 = s2 =
(Td4[(t2 >> 24) ] & 0xff000000) ^ (Td4[(t2 >> 24) ] & 0xff000000) ^
(Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t3 ) & 0xff] & 0x000000ff) ^ (Td4[(t3) & 0xff] & 0x000000ff) ^
rk[2]; rk[2];
s3 = s3 =
(Td4[(t3 >> 24) ] & 0xff000000) ^ (Td4[(t3 >> 24) ] & 0xff000000) ^
(Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
(Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
(Td4[(t0 ) & 0xff] & 0x000000ff) ^ (Td4[(t0) & 0xff] & 0x000000ff) ^
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);
PUTU32(pt + 4, s1); PUTU32(pt + 4, s1);
PUTU32(pt + 8, s2); PUTU32(pt + 8, s2);
PUTU32(pt + 12, s3); PUTU32(pt + 12, s3);
@ -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;
@ -1082,9 +1085,9 @@ int AesCtxIni(AesCtx *pCtx, unsigned char *pIV, unsigned char *pKey, unsigned in
// initialize IV // initialize IV
if (pIV != 0) { if (pIV != 0) {
pCtx->Iv[0] = GETU32(pIV ); pCtx->Iv[0] = GETU32(pIV);
pCtx->Iv[1] = GETU32(pIV + 4 ); pCtx->Iv[1] = GETU32(pIV + 4);
pCtx->Iv[2] = GETU32(pIV + 8 ); pCtx->Iv[2] = GETU32(pIV + 8);
pCtx->Iv[3] = GETU32(pIV + 12); pCtx->Iv[3] = GETU32(pIV + 12);
} }
@ -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";
@ -1149,18 +1149,18 @@ int main()
// initialize context and encrypt data at one end // initialize context and encrypt data at one end
if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0) if (AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
printf("init error\n"); printf("init error\n");
if (AesEncrypt(&ctx, databuf, databuf, sizeof(databuf) ) < 0) if (AesEncrypt(&ctx, databuf, databuf, sizeof(databuf)) < 0)
printf("error in encryption\n"); printf("error in encryption\n");
// initialize context and decrypt cipher at other end // initialize context and decrypt cipher at other end
if( AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0) if (AesCtxIni(&ctx, iv, key, KEY128, CBC) < 0)
printf("init error\n"); printf("init error\n");
if (AesDecrypt(&ctx, databuf, databuf, sizeof(databuf) ) < 0) if (AesDecrypt(&ctx, databuf, databuf, sizeof(databuf)) < 0)
printf("error in decryption\n"); printf("error in decryption\n");
printf("%s\n", databuf); printf("%s\n", databuf);

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,84 +126,85 @@ 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);
int32_t dist_nt(uint32_t nt1, uint32_t nt2); int32_t dist_nt(uint32_t nt1, uint32_t nt2);
void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ); void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype);
//void RAMFUNC SniffMifare(uint8_t param); //void RAMFUNC SniffMifare(uint8_t param);
//desfire //desfire
void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain); void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain);
void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain);
// mifaredesfire.h // mifaredesfire.h
bool InitDesfireCard(); bool InitDesfireCard();
void MifareSendCommand(uint8_t arg0,uint8_t arg1, uint8_t *datain); void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain);
void MifareDesfireGetInformation(); void MifareDesfireGetInformation();
void MifareDES_Auth1(uint8_t arg0,uint8_t arg1,uint8_t arg2, uint8_t *datain); void MifareDES_Auth1(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain);
void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t * datain); void ReaderMifareDES(uint32_t param, uint32_t param2, uint8_t *datain);
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout); int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout);
size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout); size_t CreateAPDU(uint8_t *datain, size_t len, uint8_t *dataout);
void OnSuccess(); void OnSuccess();
void OnError(uint8_t reason); void OnError(uint8_t reason);
// desfire_crypto.h // desfire_crypto.h
void *mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings); void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings);
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 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);
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation); void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation);
size_t key_block_size (const desfirekey_t key); size_t key_block_size(const desfirekey_t key);
size_t padded_data_length (const size_t nbytes, const size_t block_size); size_t padded_data_length(const size_t nbytes, const size_t block_size);
size_t maced_data_length (const desfirekey_t key, const size_t nbytes); size_t maced_data_length(const desfirekey_t key, const size_t nbytes);
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings); size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings);
void cmac_generate_subkeys (desfirekey_t key); void cmac_generate_subkeys(desfirekey_t key);
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac); void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac);
// iso15693.h // iso15693.h
void RecordRawAdcSamplesIso15693(void); void RecordRawAdcSamplesIso15693(void);
@ -200,47 +212,37 @@ void AcquireRawAdcSamplesIso15693(void);
void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg
void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg
void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox
void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox
void Iso15693InitReader(void); void Iso15693InitReader(void);
// iclass.h // iclass.h
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

@ -8,11 +8,11 @@ void Ring_BEE_ONCE(uint16_t music_note) {
} }
void ring_2_7khz(uint16_t count) { void ring_2_7khz(uint16_t count) {
Ring_BEE_TIME(n_2_7khz,count); Ring_BEE_TIME(n_2_7khz, count);
} }
void Ring_BEE_TIME(uint16_t music_note,uint16_t count) { void Ring_BEE_TIME(uint16_t music_note, uint16_t count) {
for(uint16_t i=0 ; i < count; i++) for (uint16_t i = 0 ; i < count; i++)
Ring_BEE_ONCE(music_note); Ring_BEE_ONCE(music_note);
SpinDelay(9); SpinDelay(9);
} }
@ -29,13 +29,13 @@ void Ring_ALL(uint16_t count) {
} }
void Ring_Little_Star(uint16_t count) { void Ring_Little_Star(uint16_t count) {
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1, count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5, count);
Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5, count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6, count);
Ring_BEE_TIME(note_5,2*count); Ring_BEE_TIME(note_5, 2 * count);
LED_A_ON(); LED_A_ON();
/* /*
Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count);

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

@ -71,7 +71,7 @@ const uint8_t sbox[256] = {
0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B 0x21, 0xE7, 0x4A, 0x8D, 0xFC, 0x90, 0x35, 0x6B
}; };
const uint8_t e_permtab[] ={ const uint8_t e_permtab[] = {
4, 6, /* 4 bytes in 6 bytes out*/ 4, 6, /* 4 bytes in 6 bytes out*/
32, 1, 2, 3, 4, 5, 32, 1, 2, 3, 4, 5,
4, 5, 6, 7, 8, 9, 4, 5, 6, 7, 8, 9,
@ -83,7 +83,7 @@ const uint8_t e_permtab[] ={
28, 29, 30, 31, 32, 1 28, 29, 30, 31, 32, 1
}; };
const uint8_t p_permtab[] ={ const uint8_t p_permtab[] = {
4, 4, /* 32 bit -> 32 bit */ 4, 4, /* 32 bit -> 32 bit */
16, 7, 20, 21, 16, 7, 20, 21,
29, 12, 28, 17, 29, 12, 28, 17,
@ -95,7 +95,7 @@ const uint8_t p_permtab[] ={
22, 11, 4, 25 22, 11, 4, 25
}; };
const uint8_t ip_permtab[] ={ const uint8_t ip_permtab[] = {
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
58, 50, 42, 34, 26, 18, 10, 2, 58, 50, 42, 34, 26, 18, 10, 2,
60, 52, 44, 36, 28, 20, 12, 4, 60, 52, 44, 36, 28, 20, 12, 4,
@ -107,7 +107,7 @@ const uint8_t ip_permtab[] ={
63, 55, 47, 39, 31, 23, 15, 7 63, 55, 47, 39, 31, 23, 15, 7
}; };
const uint8_t inv_ip_permtab[] ={ const uint8_t inv_ip_permtab[] = {
8, 8, /* 64 bit -> 64 bit */ 8, 8, /* 64 bit -> 64 bit */
40, 8, 48, 16, 56, 24, 64, 32, 40, 8, 48, 16, 56, 24, 64, 32,
39, 7, 47, 15, 55, 23, 63, 31, 39, 7, 47, 15, 55, 23, 63, 31,
@ -119,7 +119,7 @@ const uint8_t inv_ip_permtab[] ={
33, 1, 41, 9, 49, 17, 57, 25 33, 1, 41, 9, 49, 17, 57, 25
}; };
const uint8_t pc1_permtab[] ={ const uint8_t pc1_permtab[] = {
8, 7, /* 64 bit -> 56 bit*/ 8, 7, /* 64 bit -> 56 bit*/
57, 49, 41, 33, 25, 17, 9, 57, 49, 41, 33, 25, 17, 9,
1, 58, 50, 42, 34, 26, 18, 1, 58, 50, 42, 34, 26, 18,
@ -131,7 +131,7 @@ const uint8_t pc1_permtab[] ={
21, 13, 5, 28, 20, 12, 4 21, 13, 5, 28, 20, 12, 4
}; };
const uint8_t pc2_permtab[] ={ const uint8_t pc2_permtab[] = {
7, 6, /* 56 bit -> 48 bit */ 7, 6, /* 56 bit -> 48 bit */
14, 17, 11, 24, 1, 5, 14, 17, 11, 24, 1, 5,
3, 28, 15, 6, 21, 10, 3, 28, 15, 6, 21, 10,
@ -202,27 +202,27 @@ const uint8_t shiftkeyinv_permtab[] = {
#define ROTTABLE_INV 0x3F7E #define ROTTABLE_INV 0x3F7E
/******************************************************************************/ /******************************************************************************/
void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){ void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out) {
uint8_t ob; /* in-bytes and out-bytes */ uint8_t ob; /* in-bytes and out-bytes */
uint8_t byte, bit; /* counter for bit and byte */ uint8_t byte, bit; /* counter for bit and byte */
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;
} }
} }
out[byte]=t; out[byte] = t;
} }
} }
/******************************************************************************/ /******************************************************************************/
void changeendian32(uint32_t * a){ void changeendian32(uint32_t *a) {
*a = (*a & 0x000000FF) << 24 | *a = (*a & 0x000000FF) << 24 |
(*a & 0x0000FF00) << 8 | (*a & 0x0000FF00) << 8 |
(*a & 0x00FF0000) >> 8 | (*a & 0x00FF0000) >> 8 |
@ -231,65 +231,65 @@ void changeendian32(uint32_t * a){
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey(uint8_t *key){ void shiftkey(uint8_t *key) {
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkey_permtab, k, key); permute((uint8_t *)shiftkey_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
void shiftkey_inv(uint8_t *key){ void shiftkey_inv(uint8_t *key) {
uint8_t k[7]; uint8_t k[7];
memcpy(k, key, 7); memcpy(k, key, 7);
permute((uint8_t*)shiftkeyinv_permtab, k, key); permute((uint8_t *)shiftkeyinv_permtab, k, key);
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint64_t splitin6bitwords(uint64_t a){ uint64_t splitin6bitwords(uint64_t a) {
uint64_t ret=0; uint64_t ret = 0;
a &= 0x0000ffffffffffffLL; a &= 0x0000ffffffffffffLL;
permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); permute((uint8_t *)splitin6bitword_permtab, (uint8_t *)&a, (uint8_t *)&ret);
return ret; return ret;
} }
/******************************************************************************/ /******************************************************************************/
static inline static inline
uint8_t substitute(uint8_t a, uint8_t * sbp){ uint8_t substitute(uint8_t a, uint8_t *sbp) {
uint8_t x; uint8_t x;
x = sbp[a>>1]; x = sbp[a >> 1];
x = (a&1)?x&0x0F:x>>4; x = (a & 1) ? x & 0x0F : x >> 4;
return x; return x;
} }
/******************************************************************************/ /******************************************************************************/
uint32_t des_f(uint32_t r, uint8_t* kr){ uint32_t des_f(uint32_t r, uint8_t *kr) {
uint8_t i; uint8_t i;
uint32_t t=0,ret; uint32_t t = 0, ret;
uint64_t data; uint64_t data;
uint8_t *sbp; /* sboxpointer */ uint8_t *sbp; /* sboxpointer */
permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); permute((uint8_t *)e_permtab, (uint8_t *)&r, (uint8_t *)&data);
for(i=0; i<6; ++i) for (i = 0; i < 6; ++i)
((uint8_t*)&data)[i] ^= kr[i]; ((uint8_t *)&data)[i] ^= kr[i];
/* Sbox substitution */ /* Sbox substitution */
data = splitin6bitwords(data); data = splitin6bitwords(data);
sbp=(uint8_t*)sbox; sbp = (uint8_t *)sbox;
for(i=0; i<8; ++i){ for (i = 0; i < 8; ++i) {
uint8_t x; uint8_t x;
x = substitute(((uint8_t*)&data)[i], sbp); x = substitute(((uint8_t *)&data)[i], sbp);
t<<=4; t <<= 4;
t |= x; t |= x;
sbp += 32; sbp += 32;
} }
changeendian32(&t); changeendian32(&t);
permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); permute((uint8_t *)p_permtab, (uint8_t *)&t, (uint8_t *)&ret);
return ret; return ret;
} }
@ -305,26 +305,26 @@ typedef struct {
#define R (data.d.v32[1]) #define R (data.d.v32[1])
#define L (data.d.v32[0]) #define L (data.d.v32[0])
void des_enc(void* out, const void* in, const void* key){ void des_enc(void *out, const void *in, const void *key) {
uint8_t kr[6], k[7]; uint8_t kr[6], k[7];
uint8_t i; uint8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for(i=0; i<8; ++i){ for (i = 0; i < 8; ++i) {
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+0))) ) if (ROTTABLE & ((1 << ((i << 1) + 0))))
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
L ^= des_f(R, kr); L ^= des_f(R, kr);
shiftkey(k); shiftkey(k);
if(ROTTABLE&((1<<((i<<1)+1))) ) if (ROTTABLE & ((1 << ((i << 1) + 1))))
shiftkey(k); shiftkey(k);
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
} }
@ -333,32 +333,32 @@ void des_enc(void* out, const void* in, const void* key){
L ^= R; L ^= R;
R ^= L; R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
} }
/******************************************************************************/ /******************************************************************************/
void des_dec(void* out, const void* in, const uint8_t* key){ void des_dec(void *out, const void *in, const uint8_t *key) {
uint8_t kr[6],k[7]; uint8_t kr[6], k[7];
int8_t i; int8_t i;
data_t data; data_t data;
permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t *)ip_permtab, (uint8_t *)in, data.d.v8);
permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); permute((uint8_t *)pc1_permtab, (const uint8_t *)key, k);
for(i=7; i>=0; --i){ for (i = 7; i >= 0; --i) {
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
L ^= des_f(R, kr); L ^= des_f(R, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+1))) ){ if (ROTTABLE & ((1 << ((i << 1) + 1)))) {
shiftkey_inv(k); shiftkey_inv(k);
} }
permute((uint8_t*)pc2_permtab, k, kr); permute((uint8_t *)pc2_permtab, k, kr);
R ^= des_f(L, kr); R ^= des_f(L, kr);
shiftkey_inv(k); shiftkey_inv(k);
if(ROTTABLE&((1<<((i<<1)+0))) ){ if (ROTTABLE & ((1 << ((i << 1) + 0)))) {
shiftkey_inv(k); shiftkey_inv(k);
} }
@ -368,77 +368,75 @@ void des_dec(void* out, const void* in, const uint8_t* key){
L ^= R; L ^= R;
R ^= L; R ^= L;
permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); permute((uint8_t *)inv_ip_permtab, data.d.v8, (uint8_t *)out);
} }
/******************************************************************************/ /******************************************************************************/
void tdes_enc(void* out, void* in, const void* key){ void tdes_enc(void *out, void *in, const void *key) {
des_enc(out, in, (uint8_t*)key + 0); des_enc(out, in, (uint8_t *)key + 0);
des_dec(out, out, (uint8_t*)key + 8); des_dec(out, out, (uint8_t *)key + 8);
des_enc(out, out, (uint8_t*)key +16); des_enc(out, out, (uint8_t *)key + 16);
} }
/******************************************************************************/ /******************************************************************************/
void tdes_dec(void* out, void* in, const uint8_t* key){ void tdes_dec(void *out, void *in, const uint8_t *key) {
des_dec(out, in, (uint8_t*)key +16); des_dec(out, in, (uint8_t *)key + 16);
des_enc(out, out, (uint8_t*)key + 8); des_enc(out, out, (uint8_t *)key + 8);
des_dec(out, out, (uint8_t*)key + 0); des_dec(out, out, (uint8_t *)key + 0);
} }
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) {
if( length % 8 ) return; if (length % 8) return;
uint8_t i; uint8_t i;
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] );
des_enc(tout, tin, (uint8_t*)key + 0); des_enc(tout, tin, (uint8_t *)key + 0);
des_dec(tout, tout, (uint8_t*)key + 8); des_dec(tout, tout, (uint8_t *)key + 8);
des_enc(tout, tout, (uint8_t*)key + 0); des_enc(tout, tout, (uint8_t *)key + 0);
memcpy( iv, tout, 8 ); memcpy(iv, tout, 8);
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 8; length -= 8;
} }
} }
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]) {
if( length % 8 ) return; if (length % 8) return;
uint8_t i; uint8_t i;
unsigned char temp[8]; unsigned char temp[8];
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);
des_enc(tout, tout, (uint8_t*)key + 8); des_enc(tout, tout, (uint8_t *)key + 8);
des_dec(tout, tout, (uint8_t*)key + 0); des_dec(tout, tout, (uint8_t *)key + 0);
for( i = 0; i < 8; i++ ) for (i = 0; i < 8; i++)
tout[i] = (unsigned char)( tout[i] ^ iv[i] ); tout[i] = (unsigned char)(tout[i] ^ iv[i]);
memcpy( iv, temp, 8 ); memcpy(iv, temp, 8);
tin += 8; tin += 8;
tout += 8; tout += 8;
length -= 8; length -= 8;
} }
} }
/******************************************************************************/ /******************************************************************************/

View file

@ -56,7 +56,7 @@
* \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from
* \param key pointer to the key (64 bit = 8 byte) * \param key pointer to the key (64 bit = 8 byte)
*/ */
void des_enc(void* out, const void* in, const void* key); void des_enc(void *out, const void *in, const void *key);
/** \fn void des_dec(void* out, const void* in, const void* key) /** \fn void des_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with DES * \brief decrypt a block with DES
@ -71,7 +71,7 @@ void des_enc(void* out, const void* in, const void* key);
* \param key pointer to the key (64 bit = 8 byte) * \param key pointer to the key (64 bit = 8 byte)
*/ */
//void des_dec(void* out, const void* in, const void* key); //void des_dec(void* out, const void* in, const void* key);
void des_dec(void* out, const void* in, const uint8_t* key); void des_dec(void *out, const void *in, const uint8_t *key);
/** \fn void tdes_enc(void* out, const void* in, const void* key) /** \fn void tdes_enc(void* out, const void* in, const void* key)
* \brief encrypt a block with Tripple-DES * \brief encrypt a block with Tripple-DES
@ -86,7 +86,7 @@ void des_dec(void* out, const void* in, const uint8_t* key);
* \param key pointer to the key (192 bit = 24 byte) * \param key pointer to the key (192 bit = 24 byte)
*/ */
//void tdes_enc(void* out, const void* in, const void* key); //void tdes_enc(void* out, const void* in, const void* key);
void tdes_enc(void* out, void* in, const void* key); void tdes_enc(void *out, void *in, const void *key);
/** \fn void tdes_dec(void* out, const void* in, const void* key) /** \fn void tdes_dec(void* out, const void* in, const void* key)
* \brief decrypt a block with Tripple-DES * \brief decrypt a block with Tripple-DES
@ -100,11 +100,11 @@ void tdes_enc(void* out, void* in, const void* key);
* \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from
* \param key pointer to the key (192 bit = 24 byte) * \param key pointer to the key (192 bit = 24 byte)
*/ */
//void tdes_dec(void* out, const void* in, const void* key); //void tdes_dec(void* out, const void* in, const void* key);
void tdes_dec(void* out, void* in, const uint8_t* key); void tdes_dec(void *out, void *in, const uint8_t *key);
void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); void tdes_2key_enc(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); void tdes_2key_dec(void *out, const void *in, size_t length, const void *key, unsigned char iv[8]);
// Copied from des.h in desfire imp. // Copied from des.h in desfire imp.
typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */ typedef unsigned long DES_KS[16][2]; /* Single-key DES key schedule */

View file

@ -27,68 +27,70 @@
*/ */
#include "desfire_crypto.h" #include "desfire_crypto.h"
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len); static void xor(const uint8_t *ivect, uint8_t *data, const size_t len);
static size_t key_macing_length (desfirekey_t key); static size_t key_macing_length(desfirekey_t key);
// iceman, see memxor inside string.c, dest/src swapped.. // iceman, see memxor inside string.c, dest/src swapped..
static void xor (const uint8_t *ivect, uint8_t *data, const size_t len) { static void xor(const uint8_t *ivect, uint8_t *data, const size_t len) {
for (size_t i = 0; i < len; i++) { for (size_t i = 0; i < len; i++) {
data[i] ^= ivect[i]; data[i] ^= ivect[i];
} }
} }
void cmac_generate_subkeys ( desfirekey_t key) { void cmac_generate_subkeys(desfirekey_t key) {
int kbs = key_block_size (key); int kbs = key_block_size(key);
const uint8_t R = (kbs == 8) ? 0x1B : 0x87; const uint8_t R = (kbs == 8) ? 0x1B : 0x87;
uint8_t l[kbs]; uint8_t l[kbs];
memset (l, 0, kbs); memset(l, 0, kbs);
uint8_t ivect[kbs]; uint8_t ivect[kbs];
memset (ivect, 0, kbs); memset(ivect, 0, kbs);
mifare_cypher_blocks_chained (NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER); mifare_cypher_blocks_chained(NULL, key, ivect, l, kbs, MCD_RECEIVE, MCO_ENCYPHER);
bool xor = false; bool xor = false;
// Used to compute CMAC on complete blocks // Used to compute CMAC on complete blocks
memcpy (key->cmac_sk1, l, kbs); memcpy(key->cmac_sk1, l, kbs);
xor = l[0] & 0x80; xor = l[0] & 0x80;
lsl (key->cmac_sk1, kbs); lsl(key->cmac_sk1, kbs);
if (xor) if (xor)
key->cmac_sk1[kbs-1] ^= R; key->cmac_sk1[kbs - 1] ^= R;
// Used to compute CMAC on the last block if non-complete // Used to compute CMAC on the last block if non-complete
memcpy (key->cmac_sk2, key->cmac_sk1, kbs); memcpy(key->cmac_sk2, key->cmac_sk1, kbs);
xor = key->cmac_sk1[0] & 0x80; xor = key->cmac_sk1[0] & 0x80;
lsl (key->cmac_sk2, kbs); lsl(key->cmac_sk2, kbs);
if (xor) if (xor)
key->cmac_sk2[kbs-1] ^= R; key->cmac_sk2[kbs - 1] ^= R;
} }
void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) { void cmac(const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t len, uint8_t *cmac) {
int kbs = key_block_size (key); int kbs = key_block_size(key);
uint8_t *buffer = malloc (padded_data_length (len, kbs)); uint8_t *buffer = malloc(padded_data_length(len, kbs));
memcpy (buffer, data, len); memcpy(buffer, data, len);
if ((!len) || (len % kbs)) { if ((!len) || (len % kbs)) {
buffer[len++] = 0x80; buffer[len++] = 0x80;
while (len % kbs) { while (len % kbs) {
buffer[len++] = 0x00; buffer[len++] = 0x00;
} }
xor (key->cmac_sk2, buffer + len - kbs, kbs); xor(key->cmac_sk2, buffer + len - kbs, kbs);
} else { } else {
xor (key->cmac_sk1, buffer + len - kbs, kbs); xor(key->cmac_sk1, buffer + len - kbs, kbs);
} }
mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); mifare_cypher_blocks_chained(NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER);
memcpy (cmac, ivect, kbs); memcpy(cmac, ivect, kbs);
free(buffer); free(buffer);
} }
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:
@ -106,7 +108,7 @@ size_t key_block_size (const desfirekey_t key) {
/* /*
* Size of MACing produced with the key. * Size of MACing produced with the key.
*/ */
static size_t key_macing_length (const desfirekey_t key) { static size_t key_macing_length(const desfirekey_t key) {
size_t mac_length = MAC_LENGTH; size_t mac_length = MAC_LENGTH;
switch (key->type) { switch (key->type) {
case T_DES: case T_DES:
@ -124,7 +126,7 @@ static size_t key_macing_length (const desfirekey_t key) {
/* /*
* Size required to store nbytes of data in a buffer of size n*block_size. * Size required to store nbytes of data in a buffer of size n*block_size.
*/ */
size_t padded_data_length (const size_t nbytes, const size_t block_size) { size_t padded_data_length(const size_t nbytes, const size_t block_size) {
if ((!nbytes) || (nbytes % block_size)) if ((!nbytes) || (nbytes % block_size))
return ((nbytes / block_size) + 1) * block_size; return ((nbytes / block_size) + 1) * block_size;
else else
@ -134,13 +136,13 @@ size_t padded_data_length (const size_t nbytes, const size_t block_size) {
/* /*
* Buffer size required to MAC nbytes of data * Buffer size required to MAC nbytes of data
*/ */
size_t maced_data_length (const desfirekey_t key, const size_t nbytes) { size_t maced_data_length(const desfirekey_t key, const size_t nbytes) {
return nbytes + key_macing_length (key); return nbytes + key_macing_length(key);
} }
/* /*
* Buffer size required to encipher nbytes of data and a two bytes CRC. * Buffer size required to encipher nbytes of data and a two bytes CRC.
*/ */
size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int communication_settings) { size_t enciphered_data_length(const desfiretag_t tag, const size_t nbytes, int communication_settings) {
size_t crc_length = 0; size_t crc_length = 0;
if (!(communication_settings & NO_CRC)) { if (!(communication_settings & NO_CRC)) {
switch (DESFIRE(tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
@ -153,12 +155,12 @@ size_t enciphered_data_length (const desfiretag_t tag, const size_t nbytes, int
} }
} }
size_t block_size = DESFIRE(tag)->session_key ? key_block_size (DESFIRE(tag)->session_key) : 1; size_t block_size = DESFIRE(tag)->session_key ? key_block_size(DESFIRE(tag)->session_key) : 1;
return padded_data_length (nbytes + crc_length, block_size); return padded_data_length(nbytes + crc_length, block_size);
} }
void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) { void *mifare_cryto_preprocess_data(desfiretag_t tag, void *data, size_t *nbytes, size_t offset, int communication_settings) {
uint8_t *res = data; uint8_t *res = data;
uint8_t mac[4]; uint8_t mac[4];
size_t edl; size_t edl;
@ -193,40 +195,40 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
break; break;
/* pass through */ /* pass through */
edl = padded_data_length (*nbytes - offset, key_block_size (DESFIRE(tag)->session_key)) + offset; edl = padded_data_length(*nbytes - offset, key_block_size(DESFIRE(tag)->session_key)) + offset;
// Fill in the crypto buffer with data ... // Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
// ... and 0 padding // ... and 0 padding
memset (res + *nbytes, 0, edl - *nbytes); memset(res + *nbytes, 0, edl - *nbytes);
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER); mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, edl - offset, MCD_SEND, MCO_ENCYPHER);
memcpy (mac, res + edl - 8, 4); memcpy(mac, res + edl - 8, 4);
// Copy again provided data (was overwritten by mifare_cypher_blocks_chained) // Copy again provided data (was overwritten by mifare_cypher_blocks_chained)
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
if (!(communication_settings & MAC_COMMAND)) if (!(communication_settings & MAC_COMMAND))
break; break;
// Append MAC // Append MAC
size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset; size_t bla = maced_data_length(DESFIRE(tag)->session_key, *nbytes - offset) + offset;
bla++; bla++;
memcpy (res + *nbytes, mac, 4); memcpy(res + *nbytes, mac, 4);
*nbytes += 4; *nbytes += 4;
break; break;
case AS_NEW: case AS_NEW:
if (!(communication_settings & CMAC_COMMAND)) if (!(communication_settings & CMAC_COMMAND))
break; break;
cmac (key, DESFIRE (tag)->ivect, res, *nbytes, DESFIRE (tag)->cmac); cmac(key, DESFIRE(tag)->ivect, res, *nbytes, DESFIRE(tag)->cmac);
if (append_mac) { if (append_mac) {
size_t len = maced_data_length (key, *nbytes); size_t len = maced_data_length(key, *nbytes);
++len; ++len;
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); memcpy(res + *nbytes, DESFIRE(tag)->cmac, CMAC_LENGTH);
*nbytes += CMAC_LENGTH; *nbytes += CMAC_LENGTH;
} }
break; break;
@ -251,29 +253,29 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes
if (!(communication_settings & ENC_COMMAND)) if (!(communication_settings & ENC_COMMAND))
break; break;
edl = enciphered_data_length (tag, *nbytes - offset, communication_settings) + offset; edl = enciphered_data_length(tag, *nbytes - offset, communication_settings) + offset;
// Fill in the crypto buffer with data ... // Fill in the crypto buffer with data ...
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
if (!(communication_settings & NO_CRC)) { if (!(communication_settings & NO_CRC)) {
// ... CRC ... // ... CRC ...
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
AddCrc14A(res + offset, *nbytes - offset); AddCrc14A(res + offset, *nbytes - offset);
*nbytes += 2; *nbytes += 2;
break; break;
case AS_NEW: case AS_NEW:
crc32_append (res, *nbytes); crc32_append(res, *nbytes);
*nbytes += 4; *nbytes += 4;
break; break;
} }
} }
// ... and padding // ... and padding
memset (res + *nbytes, 0, edl - *nbytes); memset(res + *nbytes, 0, edl - *nbytes);
*nbytes = edl; *nbytes = edl;
mifare_cypher_blocks_chained (tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER); mifare_cypher_blocks_chained(tag, NULL, NULL, res + offset, *nbytes - offset, MCD_SEND, (AS_NEW == DESFIRE(tag)->authentication_scheme) ? MCO_ENCYPHER : MCO_DECYPHER);
break; break;
default: default:
@ -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;
@ -310,34 +310,34 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
/* pass through */ /* pass through */
case MDCM_MACED: case MDCM_MACED:
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
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
Dbprintf ("No room for MAC!"); Dbprintf("No room for MAC!");
#endif #endif
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);
memset ((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1); memset((uint8_t *)edata + *nbytes - 1, 0, edl - *nbytes + 1);
mifare_cypher_blocks_chained (tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER); mifare_cypher_blocks_chained(tag, NULL, NULL, edata, edl, MCD_SEND, MCO_ENCYPHER);
if (0 != memcmp ((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) { if (0 != memcmp((uint8_t *)data + *nbytes - 1, (uint8_t *)edata + edl - 8, 4)) {
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
Dbprintf ("MACing not verified"); Dbprintf("MACing not verified");
hexdump ((uint8_t *)data + *nbytes - 1, key_macing_length (key), "Expect ", 0); hexdump((uint8_t *)data + *nbytes - 1, key_macing_length(key), "Expect ", 0);
hexdump ((uint8_t *)edata + edl - 8, key_macing_length (key), "Actual ", 0); hexdump((uint8_t *)edata + edl - 8, key_macing_length(key), "Actual ", 0);
#endif #endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
} }
@ -353,21 +353,21 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break; break;
} }
first_cmac_byte = ((uint8_t *)data)[*nbytes - 9]; first_cmac_byte = ((uint8_t *)data)[*nbytes - 9];
((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes-1]; ((uint8_t *)data)[*nbytes - 9] = ((uint8_t *)data)[*nbytes - 1];
} }
int n = (communication_settings & CMAC_VERIFY) ? 8 : 0; int n = (communication_settings & CMAC_VERIFY) ? 8 : 0;
cmac (key, DESFIRE (tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE (tag)->cmac); cmac(key, DESFIRE(tag)->ivect, ((uint8_t *)data), *nbytes - n, DESFIRE(tag)->cmac);
if (communication_settings & CMAC_VERIFY) { if (communication_settings & CMAC_VERIFY) {
((uint8_t *)data)[*nbytes - 9] = first_cmac_byte; ((uint8_t *)data)[*nbytes - 9] = first_cmac_byte;
if (0 != memcmp (DESFIRE (tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) { if (0 != memcmp(DESFIRE(tag)->cmac, (uint8_t *)data + *nbytes - 9, 8)) {
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
Dbprintf ("CMAC NOT verified :-("); Dbprintf("CMAC NOT verified :-(");
hexdump ((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0); hexdump((uint8_t *)data + *nbytes - 9, 8, "Expect ", 0);
hexdump (DESFIRE (tag)->cmac, 8, "Actual ", 0); hexdump(DESFIRE(tag)->cmac, 8, "Actual ", 0);
#endif #endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
} else { } else {
@ -377,7 +377,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break; break;
} }
free (edata); free(edata);
break; break;
case MDCM_ENCIPHERED: case MDCM_ENCIPHERED:
@ -409,14 +409,14 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
* `------------------' * `------------------'
*/ */
mifare_cypher_blocks_chained (tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER); mifare_cypher_blocks_chained(tag, NULL, NULL, res, *nbytes, MCD_RECEIVE, MCO_DECYPHER);
/* /*
* Look for the CRC and ensure it is followed by NULL padding. We * Look for the CRC and ensure it is followed by NULL padding. We
* can't start by the end because the CRC is supposed to be 0 when * can't start by the end because the CRC is supposed to be 0 when
* verified, and accumulating 0's in it should not change it. * verified, and accumulating 0's in it should not change it.
*/ */
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks crc_pos = *nbytes - 8 - 1; // The CRC can be over two blocks
if (crc_pos < 0) { if (crc_pos < 0) {
@ -426,15 +426,15 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break; break;
case AS_NEW: case AS_NEW:
/* Move status between payload and CRC */ /* Move status between payload and CRC */
res = DESFIRE (tag)->crypto_buffer; res = DESFIRE(tag)->crypto_buffer;
memcpy (res, data, *nbytes); memcpy(res, data, *nbytes);
crc_pos = (*nbytes) - 16 - 3; crc_pos = (*nbytes) - 16 - 3;
if (crc_pos < 0) { if (crc_pos < 0) {
/* Single block */ /* Single block */
crc_pos = 0; crc_pos = 0;
} }
memcpy ((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos); memcpy((uint8_t *)res + crc_pos + 1, (uint8_t *)res + crc_pos, *nbytes - crc_pos);
((uint8_t *)res)[crc_pos] = 0x00; ((uint8_t *)res)[crc_pos] = 0x00;
crc_pos++; crc_pos++;
*nbytes += 1; *nbytes += 1;
@ -442,33 +442,33 @@ 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:
AddCrc14A( (uint8_t*)res, end_crc_pos); AddCrc14A((uint8_t *)res, end_crc_pos);
end_crc_pos = crc_pos + 2; end_crc_pos = crc_pos + 2;
// //
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;
crc32_ex (res, end_crc_pos, (uint8_t *)&crc); crc32_ex(res, end_crc_pos, (uint8_t *)&crc);
break; break;
} }
if (!crc) { if (!crc) {
verified = true; verified = true;
for (int n = end_crc_pos; n < *nbytes - 1; n++) { for (int n = end_crc_pos; n < *nbytes - 1; n++) {
uint8_t byte = ((uint8_t *)res)[n]; uint8_t byte = ((uint8_t *)res)[n];
if (!( (0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos)) )) if (!((0x00 == byte) || ((0x80 == byte) && (n == end_crc_pos))))
verified = false; verified = false;
} }
} }
if (verified) { if (verified) {
*nbytes = crc_pos; *nbytes = crc_pos;
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
((uint8_t *)data)[(*nbytes)++] = 0x00; ((uint8_t *)data)[(*nbytes)++] = 0x00;
break; break;
@ -477,7 +477,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
break; break;
} }
} else { } else {
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
break; break;
case AS_NEW: case AS_NEW:
@ -495,7 +495,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte
/* FIXME In some configurations, the file is transmitted PLAIN */ /* FIXME In some configurations, the file is transmitted PLAIN */
Dbprintf("CRC not verified in decyphered stream"); Dbprintf("CRC not verified in decyphered stream");
#endif #endif
DESFIRE (tag)->last_pcd_error = CRYPTO_ERROR; DESFIRE(tag)->last_pcd_error = CRYPTO_ERROR;
*nbytes = -1; *nbytes = -1;
res = NULL; res = NULL;
} }
@ -512,14 +512,13 @@ 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) {
xor (ivect, data, block_size); xor(ivect, data, block_size);
} else { } else {
memcpy (ovect, data, block_size); memcpy(ovect, data, block_size);
} }
uint8_t edata[MAX_CRYPTO_BLOCK_SIZE]; uint8_t edata[MAX_CRYPTO_BLOCK_SIZE];
@ -543,7 +542,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
tdes_enc(edata,data, key->data); tdes_enc(edata, data, key->data);
break; break;
case MCO_DECYPHER: case MCO_DECYPHER:
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT);
@ -556,7 +555,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
case T_3K3DES: case T_3K3DES:
switch (operation) { switch (operation) {
case MCO_ENCYPHER: case MCO_ENCYPHER:
tdes_enc(edata,data, key->data); tdes_enc(edata, data, key->data);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT);
// DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT);
// DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT);
@ -570,19 +569,16 @@ 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));
break; break;
} }
@ -590,13 +586,13 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
break; break;
} }
memcpy (data, edata, block_size); memcpy(data, edata, block_size);
if (direction == MCD_SEND) { if (direction == MCD_SEND) {
memcpy (ivect, data, block_size); memcpy(ivect, data, block_size);
} else { } else {
xor (ivect, data, block_size); xor(ivect, data, block_size);
memcpy (ivect, ovect, block_size); memcpy(ivect, ovect, block_size);
} }
} }
@ -610,29 +606,29 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect
* Because the tag may contain additional data, one may need to call this * Because the tag may contain additional data, one may need to call this
* function with tag, key and ivect defined. * function with tag, key and ivect defined.
*/ */
void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) { void mifare_cypher_blocks_chained(desfiretag_t tag, desfirekey_t key, uint8_t *ivect, uint8_t *data, size_t data_size, MifareCryptoDirection direction, MifareCryptoOperation operation) {
size_t block_size; size_t block_size;
if (tag) { if (tag) {
if (!key) if (!key)
key = DESFIRE (tag)->session_key; key = DESFIRE(tag)->session_key;
if (!ivect) if (!ivect)
ivect = DESFIRE (tag)->ivect; ivect = DESFIRE(tag)->ivect;
switch (DESFIRE (tag)->authentication_scheme) { switch (DESFIRE(tag)->authentication_scheme) {
case AS_LEGACY: case AS_LEGACY:
memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); memset(ivect, 0, MAX_CRYPTO_BLOCK_SIZE);
break; break;
case AS_NEW: case AS_NEW:
break; break;
} }
} }
block_size = key_block_size (key); block_size = key_block_size(key);
size_t offset = 0; size_t offset = 0;
while (offset < data_size) { while (offset < data_size) {
mifare_cypher_single_block (key, data + offset, ivect, direction, operation, block_size); mifare_cypher_single_block(key, data + offset, ivect, direction, operation, block_size);
offset += block_size; offset += block_size;
} }
} }

View file

@ -19,9 +19,9 @@
#include "desfire_key.h" #include "desfire_key.h"
static inline void update_key_schedules (desfirekey_t key); static inline void update_key_schedules(desfirekey_t key);
static inline void update_key_schedules (desfirekey_t key) { static inline void update_key_schedules(desfirekey_t key) {
// DES_set_key ((DES_cblock *)key->data, &(key->ks1)); // DES_set_key ((DES_cblock *)key->data, &(key->ks1));
// DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2)); // DES_set_key ((DES_cblock *)(key->data + 8), &(key->ks2));
// if (T_3K3DES == key->type) { // if (T_3K3DES == key->type) {
@ -29,72 +29,72 @@ static inline void update_key_schedules (desfirekey_t key) {
// } // }
} }
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) { void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key) {
uint8_t data[8]; uint8_t data[8];
memcpy (data, value, 8); memcpy(data, value, 8);
for (int n=0; n < 8; n++) for (int n = 0; n < 8; n++)
data[n] &= 0xfe; data[n] &= 0xfe;
Desfire_des_key_new_with_version (data, key); Desfire_des_key_new_with_version(data, key);
} }
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) { void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key) {
if ( key != NULL) { if (key != NULL) {
key->type = T_DES; key->type = T_DES;
memcpy (key->data, value, 8); memcpy(key->data, value, 8);
memcpy (key->data+8, value, 8); memcpy(key->data + 8, value, 8);
update_key_schedules (key); update_key_schedules(key);
} }
} }
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) { void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key) {
uint8_t data[16]; uint8_t data[16];
memcpy (data, value, 16); memcpy(data, value, 16);
for (int n=0; n < 8; n++) for (int n = 0; n < 8; n++)
data[n] &= 0xfe; data[n] &= 0xfe;
for (int n=8; n < 16; n++) for (int n = 8; n < 16; n++)
data[n] |= 0x01; data[n] |= 0x01;
Desfire_3des_key_new_with_version (data, key); Desfire_3des_key_new_with_version(data, key);
} }
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) { void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key) {
if ( key != NULL ){ if (key != NULL) {
key->type = T_3DES; key->type = T_3DES;
memcpy (key->data, value, 16); memcpy(key->data, value, 16);
memcpy (key->data + 16, value, 8); memcpy(key->data + 16, value, 8);
update_key_schedules (key); update_key_schedules(key);
} }
} }
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) { void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key) {
uint8_t data[24]; uint8_t data[24];
memcpy (data, value, 24); memcpy(data, value, 24);
for (int n=0; n < 8; n++) for (int n = 0; n < 8; n++)
data[n] &= 0xfe; data[n] &= 0xfe;
Desfire_3k3des_key_new_with_version (data, key); Desfire_3k3des_key_new_with_version(data, key);
} }
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) { void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key) {
if ( key != NULL){ if (key != NULL) {
key->type = T_3K3DES; key->type = T_3K3DES;
memcpy (key->data, value, 24); memcpy(key->data, value, 24);
update_key_schedules (key); update_key_schedules(key);
} }
} }
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) { void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key) {
Desfire_aes_key_new_with_version (value, 0, key); Desfire_aes_key_new_with_version(value, 0, key);
} }
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) { void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key) {
if (key != NULL) { if (key != NULL) {
memcpy (key->data, value, 16); memcpy(key->data, value, 16);
key->type = T_AES; key->type = T_AES;
key->aes_version = version; key->aes_version = version;
} }
} }
uint8_t Desfire_key_get_version (desfirekey_t key) { uint8_t Desfire_key_get_version(desfirekey_t key) {
uint8_t version = 0; uint8_t version = 0;
for (int n = 0; n < 8; n++) { for (int n = 0; n < 8; n++) {
@ -103,54 +103,53 @@ 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;
key->data[n] |= version_bit; key->data[n] |= version_bit;
if (key->type == T_DES) { if (key->type == T_DES) {
key->data[n+8] = key->data[n]; key->data[n + 8] = key->data[n];
} else { } else {
// Write ~version to avoid turning a 3DES key into a DES key // Write ~version to avoid turning a 3DES key into a DES key
key->data[n+8] &= 0xfe; key->data[n + 8] &= 0xfe;
key->data[n+8] |= ~version_bit; key->data[n + 8] |= ~version_bit;
} }
} }
} }
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) { void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key) {
uint8_t buffer[24]; uint8_t buffer[24];
switch (authkey->type) { switch (authkey->type) {
case T_DES: case T_DES:
memcpy (buffer, rnda, 4); memcpy(buffer, rnda, 4);
memcpy (buffer+4, rndb, 4); memcpy(buffer + 4, rndb, 4);
Desfire_des_key_new_with_version (buffer, key); Desfire_des_key_new_with_version(buffer, key);
break; break;
case T_3DES: case T_3DES:
memcpy (buffer, rnda, 4); memcpy(buffer, rnda, 4);
memcpy (buffer+4, rndb, 4); memcpy(buffer + 4, rndb, 4);
memcpy (buffer+8, rnda+4, 4); memcpy(buffer + 8, rnda + 4, 4);
memcpy (buffer+12, rndb+4, 4); memcpy(buffer + 12, rndb + 4, 4);
Desfire_3des_key_new_with_version (buffer, key); Desfire_3des_key_new_with_version(buffer, key);
break; break;
case T_3K3DES: case T_3K3DES:
memcpy (buffer, rnda, 4); memcpy(buffer, rnda, 4);
memcpy (buffer+4, rndb, 4); memcpy(buffer + 4, rndb, 4);
memcpy (buffer+8, rnda+6, 4); memcpy(buffer + 8, rnda + 6, 4);
memcpy (buffer+12, rndb+6, 4); memcpy(buffer + 12, rndb + 6, 4);
memcpy (buffer+16, rnda+12, 4); memcpy(buffer + 16, rnda + 12, 4);
memcpy (buffer+20, rndb+12, 4); memcpy(buffer + 20, rndb + 12, 4);
Desfire_3k3des_key_new (buffer, key); Desfire_3k3des_key_new(buffer, key);
break; break;
case T_AES: case T_AES:
memcpy (buffer, rnda, 4); memcpy(buffer, rnda, 4);
memcpy (buffer+4, rndb, 4); memcpy(buffer + 4, rndb, 4);
memcpy (buffer+8, rnda+12, 4); memcpy(buffer + 8, rnda + 12, 4);
memcpy (buffer+12, rndb+12, 4); memcpy(buffer + 12, rndb + 12, 4);
Desfire_aes_key_new (buffer, key); Desfire_aes_key_new(buffer, key);
break; break;
} }
} }

View file

@ -6,15 +6,15 @@
#include "iso14443a.h" #include "iso14443a.h"
#include "desfire.h" #include "desfire.h"
//#include "mifare.h" // iso14a_card_select_t struct //#include "mifare.h" // iso14a_card_select_t struct
void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key); void Desfire_des_key_new(const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key); void Desfire_3des_key_new(const uint8_t value[16], desfirekey_t key);
void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key); void Desfire_des_key_new_with_version(const uint8_t value[8], desfirekey_t key);
void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key); void Desfire_3des_key_new_with_version(const uint8_t value[16], desfirekey_t key);
void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key); void Desfire_3k3des_key_new(const uint8_t value[24], desfirekey_t key);
void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key); void Desfire_3k3des_key_new_with_version(const uint8_t value[24], desfirekey_t key);
void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key); void Desfire_aes_key_new(const uint8_t value[16], desfirekey_t key);
void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key); void Desfire_aes_key_new_with_version(const uint8_t value[16], uint8_t version, desfirekey_t key);
uint8_t Desfire_key_get_version (desfirekey_t key); uint8_t Desfire_key_get_version(desfirekey_t key);
void Desfire_key_set_version (desfirekey_t key, uint8_t version); void Desfire_key_set_version(desfirekey_t key, uint8_t version);
void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); void Desfire_session_key_new(const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key);
#endif #endif

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) {
@ -156,7 +152,7 @@ size_t EPA_Parse_CardAccess(uint8_t *data,
index += 2; index += 2;
// check for extended length // check for extended length
if ((data[index - 1] & 0x80) != 0) { if ((data[index - 1] & 0x80) != 0) {
index += (data[index-1] & 0x7F); index += (data[index - 1] & 0x7F);
} }
} }
// OID // OID
@ -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;
} }
@ -251,7 +240,7 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length)
// length of data available: apdu_length - 4 (ISO frame) - 2 (SW) // length of data available: apdu_length - 4 (ISO frame) - 2 (SW)
size_t to_copy = rapdu_length - 6; size_t to_copy = rapdu_length - 6;
to_copy = to_copy < max_length ? to_copy : max_length; to_copy = to_copy < max_length ? to_copy : max_length;
memcpy(buffer, response_apdu+2, to_copy); memcpy(buffer, response_apdu + 2, to_copy);
return to_copy; return to_copy;
} }
@ -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 {
@ -69,116 +67,116 @@ static struct {
uint16_t len; uint16_t len;
uint8_t byte_offset; uint8_t byte_offset;
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();
@ -227,27 +225,27 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
} while (--len); } while (--len);
// timed-out // timed-out
if ( len == 0 ) if (len == 0)
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);
memcpy(card->mrt, card->PMm+2, 6); memcpy(card->mrt, card->PMm + 2, 6);
} }
// more status bytes? // more status bytes?
@ -266,10 +264,10 @@ static uint8_t felica_select_card(felica_card_select_t *card) {
// Felica standard has a different file system, AFAIK, // Felica standard has a different file system, AFAIK,
// 8-byte IDm, number of blocks, blocks numbers // 8-byte IDm, number of blocks, blocks numbers
// number of blocks limited to 4 for FelicaLite(S) // number of blocks limited to 4 for FelicaLite(S)
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;
@ -300,7 +298,7 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
//number of blocks //number of blocks
frameSpace[c++] = blocknum; frameSpace[c++] = blocknum;
for (i=0; i < blocknum; i++) { for (i = 0; i < blocknum; i++) {
//3-byte block //3-byte block
if (blocks[i] >= 256) { if (blocks[i] >= 256) {
@ -314,15 +312,15 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) {
} }
//set length //set length
frameSpace[2] = c-2; frameSpace[2] = c - 2;
AddCrc(frameSpace, c-2); AddCrc(frameSpace, c - 2);
} }
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) {
uint8_t flags = FPGA_MAJOR_MODE_ISO18092; uint8_t flags = FPGA_MAJOR_MODE_ISO18092;
if ( power ) if (power)
flags |= FPGA_HF_ISO18092_FLAG_READER; flags |= FPGA_HF_ISO18092_FLAG_READER;
if (highspeed) if (highspeed)
flags |= FPGA_HF_ISO18092_FLAG_424K; flags |= FPGA_HF_ISO18092_FLAG_424K;
@ -358,25 +356,25 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing
} }
} }
/**/ /**/
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay
while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {};
AT91C_BASE_SSC->SSC_THR = 0x00; //spin AT91C_BASE_SSC->SSC_THR = 0x00; //spin
/**/ /**/
// log // log
LogTrace( LogTrace(
frame, frame,
len, len,
(felica_lasttime_prox2air_start<<4) + DELAY_ARM2AIR_AS_READER, (felica_lasttime_prox2air_start << 4) + DELAY_ARM2AIR_AS_READER,
((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start)<<4) + DELAY_ARM2AIR_AS_READER, ((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start) << 4) + DELAY_ARM2AIR_AS_READER,
NULL, NULL,
true true
); );
felica_nexttransfertime = MAX(felica_nexttransfertime ,felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME); felica_nexttransfertime = MAX(felica_nexttransfertime, felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME);
} }
// Wait for tag reply // Wait for tag reply
@ -389,40 +387,41 @@ 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,
(GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FELICA_FRAME_DELAY_TIME (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER) / 16 + FELICA_FRAME_DELAY_TIME
) )
; ;
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,14 +492,14 @@ 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;
} }
} }
@ -507,26 +507,25 @@ void felica_sendraw(UsbCommand *c) {
if ((param & FELICA_RAW)) { if ((param & FELICA_RAW)) {
// 2 sync, 1 len, 2crc == 5 // 2 sync, 1 len, 2crc == 5
uint8_t *buf = BigBuf_malloc(len+5); uint8_t *buf = BigBuf_malloc(len + 5);
// add sync bits // add sync bits
buf[0] = 0xb2; buf[0] = 0xb2;
buf[1] = 0x4d; buf[1] = 0x4d;
buf[2] = len; buf[2] = len;
// copy command // copy command
memcpy(buf+2, cmd, len); memcpy(buf + 2, cmd, len);
if ((param & FELICA_APPEND_CRC)) { if ((param & FELICA_APPEND_CRC)) {
// 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,61 +537,61 @@ 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
int numbts = 0; int numbts = 0;
uint8_t *dest = (uint8_t *)BigBuf_get_addr(); uint8_t *dest = (uint8_t *)BigBuf_get_addr();
uint8_t *destend = dest + n-2; uint8_t *destend = dest + n - 2;
uint32_t endframe = GetCountSspClk(); uint32_t endframe = GetCountSspClk();
while (dest <= destend) { while (dest <= destend) {
WDT_HIT(); WDT_HIT();
if( BUTTON_PRESS()) break; if (BUTTON_PRESS()) break;
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;
} }
remFrames--; remFrames--;
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");
@ -632,10 +631,10 @@ void felica_sim_lite(uint64_t nfcid) {
); );
//fill in blanks //fill in blanks
for( i=0; i<8; i++) { for (i = 0; i < 8; i++) {
resp_poll0[i+4] = ndef[i]; resp_poll0[i + 4] = ndef[i];
resp_poll1[i+4] = ndef[i]; resp_poll1[i + 4] = ndef[i];
resp_readblk[i+4] = ndef[i]; resp_readblk[i + 4] = ndef[i];
} }
//calculate and set CRC //calculate and set CRC
@ -643,12 +642,12 @@ 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();
for(;;) { for (;;) {
if( BUTTON_PRESS()) break; if (BUTTON_PRESS()) break;
WDT_HIT(); WDT_HIT();
if (listenmode) { if (listenmode) {
@ -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,41 +739,41 @@ 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);) {
// block to read. // block to read.
BuildFliteRdblk(ndef, 1, &liteblks[blknum]); BuildFliteRdblk(ndef, 1, &liteblks[blknum]);
//TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0);
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];
blknum++; blknum++;
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 << 2) | // Chip selects connected directly to peripheral (0 << 7) | // Disable LLB (1=MOSI2MISO test mode)
( 0 << 1) | // Fixed Peripheral Select (1 << 4) | // Disable ModeFault Protection
( 1 << 0); // Master Mode (0 << 3) | // makes spi operate at MCK (1 is MCK/2)
(0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
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;
}
// determine whether FLASHMEM is busy if (DBGLEVEL > 3) Dbprintf("Checkbusy in...");
bool Flash_CheckBusy(uint16_t times) {
bool ret = (Flash_ReadStat1() & BUSY);
if (!ret || !times || !(times--)) do {
return ret; if (!(Flash_ReadStat1() & BUSY)) {
return false;
while (times) {
WDT_HIT();
SpinDelay(1);
ret = (Flash_ReadStat1() & BUSY);
if (!ret)
break;
times--;
} }
return ret; } while ((GetCountUS() - _time) < timeout);
if (timeout <= (GetCountUS() - _time)) {
return true;
}
return false;
} }
// 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,9 +218,9 @@ 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;
return 0; return 0;
@ -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) {
@ -241,22 +314,22 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) {
// Max 256 bytes write // Max 256 bytes write
if (((address & 0xFF) + len) > 256) { if (((address & 0xFF) + len) > 256) {
Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF) + len, len);
return 0; return 0;
} }
// out-of-range // out-of-range
if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { if (((address >> 16) & 0xFF) > MAX_BLOCKS) {
Dbprintf("Flash_WriteData, block out-of-range"); Dbprintf("Flash_WriteData, block out-of-range");
return 0; return 0;
} }
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

@ -7,103 +7,103 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
const char FONT6x8[97][8] = { const char FONT6x8[97][8] = {
{0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char {0x06, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00}, // columns, rows, bytes per char
{0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, // space
{0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // ! {0x20, 0x20, 0x20, 0x20, 0x20, 0x00, 0x20, 0x00}, // !
{0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // " {0x50, 0x50, 0x50, 0x00, 0x00, 0x00, 0x00, 0x00}, // "
{0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // # {0x50, 0x50, 0xF8, 0x50, 0xF8, 0x50, 0x50, 0x00}, // #
{0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $ {0x20, 0x78, 0xA0, 0x70, 0x28, 0xF0, 0x20, 0x00}, // $
{0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // % {0xC0, 0xC8, 0x10, 0x20, 0x40, 0x98, 0x18, 0x00}, // %
{0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // & {0x40, 0xA0, 0xA0, 0x40, 0xA8, 0x90, 0x68, 0x00}, // &
{0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // ' {0x30, 0x30, 0x20, 0x40, 0x00, 0x00, 0x00, 0x00}, // '
{0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // ( {0x10, 0x20, 0x40, 0x40, 0x40, 0x20, 0x10, 0x00}, // (
{0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // ) {0x40, 0x20, 0x10, 0x10, 0x10, 0x20, 0x40, 0x00}, // )
{0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // * {0x00, 0x20, 0xA8, 0x70, 0x70, 0xA8, 0x20, 0x00}, // *
{0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // + {0x00, 0x20, 0x20, 0xF8, 0x20, 0x20, 0x00, 0x00}, // +
{0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // , {0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x20, 0x40}, // ,
{0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // - {0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0x00, 0x00}, // -
{0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // . {0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x30, 0x00}, // .
{0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // / {0x00, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00, 0x00}, // /
{0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0 {0x70, 0x88, 0x88, 0xA8, 0x88, 0x88, 0x70, 0x00}, // 0
{0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1 {0x20, 0x60, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // 1
{0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2 {0x70, 0x88, 0x08, 0x70, 0x80, 0x80, 0xF8, 0x00}, // 2
{0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3 {0xF8, 0x08, 0x10, 0x30, 0x08, 0x88, 0x70, 0x00}, // 3
{0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4 {0x10, 0x30, 0x50, 0x90, 0xF8, 0x10, 0x10, 0x00}, // 4
{0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5 {0xF8, 0x80, 0xF0, 0x08, 0x08, 0x88, 0x70, 0x00}, // 5
{0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6 {0x38, 0x40, 0x80, 0xF0, 0x88, 0x88, 0x70, 0x00}, // 6
{0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7 {0xF8, 0x08, 0x08, 0x10, 0x20, 0x40, 0x80, 0x00}, // 7
{0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8 {0x70, 0x88, 0x88, 0x70, 0x88, 0x88, 0x70, 0x00}, // 8
{0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9 {0x70, 0x88, 0x88, 0x78, 0x08, 0x10, 0xE0, 0x00}, // 9
{0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // : {0x00, 0x00, 0x20, 0x00, 0x20, 0x00, 0x00, 0x00}, // :
{0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ; {0x00, 0x00, 0x20, 0x00, 0x20, 0x20, 0x40, 0x00}, // ;
{0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // < {0x08, 0x10, 0x20, 0x40, 0x20, 0x10, 0x08, 0x00}, // <
{0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // = {0x00, 0x00, 0xF8, 0x00, 0xF8, 0x00, 0x00, 0x00}, // =
{0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // > {0x40, 0x20, 0x10, 0x08, 0x10, 0x20, 0x40, 0x00}, // >
{0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ? {0x70, 0x88, 0x08, 0x30, 0x20, 0x00, 0x20, 0x00}, // ?
{0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @ {0x70, 0x88, 0xA8, 0xB8, 0xB0, 0x80, 0x78, 0x00}, // @
{0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A {0x20, 0x50, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x00}, // A
{0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B {0xF0, 0x88, 0x88, 0xF0, 0x88, 0x88, 0xF0, 0x00}, // B
{0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C {0x70, 0x88, 0x80, 0x80, 0x80, 0x88, 0x70, 0x00}, // C
{0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D {0xF0, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0x00}, // D
{0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0xF8, 0x00}, // E
{0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F {0xF8, 0x80, 0x80, 0xF0, 0x80, 0x80, 0x80, 0x00}, // F
{0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G {0x78, 0x88, 0x80, 0x80, 0x98, 0x88, 0x78, 0x00}, // G
{0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H {0x88, 0x88, 0x88, 0xF8, 0x88, 0x88, 0x88, 0x00}, // H
{0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I {0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // I
{0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J {0x38, 0x10, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // J
{0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K {0x88, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x88, 0x00}, // K
{0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L {0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xF8, 0x00}, // L
{0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M {0x88, 0xD8, 0xA8, 0xA8, 0xA8, 0x88, 0x88, 0x00}, // M
{0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N {0x88, 0x88, 0xC8, 0xA8, 0x98, 0x88, 0x88, 0x00}, // N
{0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O {0x70, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // O
{0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P {0xF0, 0x88, 0x88, 0xF0, 0x80, 0x80, 0x80, 0x00}, // P
{0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q {0x70, 0x88, 0x88, 0x88, 0xA8, 0x90, 0x68, 0x00}, // Q
{0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R {0xF0, 0x88, 0x88, 0xF0, 0xA0, 0x90, 0x88, 0x00}, // R
{0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S {0x70, 0x88, 0x80, 0x70, 0x08, 0x88, 0x70, 0x00}, // S
{0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T {0xF8, 0xA8, 0x20, 0x20, 0x20, 0x20, 0x20, 0x00}, // T
{0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U {0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x70, 0x00}, // U
{0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V {0x88, 0x88, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // V
{0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W {0x88, 0x88, 0x88, 0xA8, 0xA8, 0xA8, 0x50, 0x00}, // W
{0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X {0x88, 0x88, 0x50, 0x20, 0x50, 0x88, 0x88, 0x00}, // X
{0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y {0x88, 0x88, 0x50, 0x20, 0x20, 0x20, 0x20, 0x00}, // Y
{0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z {0xF8, 0x08, 0x10, 0x70, 0x40, 0x80, 0xF8, 0x00}, // Z
{0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [ {0x78, 0x40, 0x40, 0x40, 0x40, 0x40, 0x78, 0x00}, // [
{0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash {0x00, 0x80, 0x40, 0x20, 0x10, 0x08, 0x00, 0x00}, // backslash
{0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ] {0x78, 0x08, 0x08, 0x08, 0x08, 0x08, 0x78, 0x00}, // ]
{0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^ {0x20, 0x50, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00}, // ^
{0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _ {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00}, // _
{0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // ` {0x60, 0x60, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00}, // `
{0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a {0x00, 0x00, 0x60, 0x10, 0x70, 0x90, 0x78, 0x00}, // a
{0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b {0x80, 0x80, 0xB0, 0xC8, 0x88, 0xC8, 0xB0, 0x00}, // b
{0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c {0x00, 0x00, 0x70, 0x88, 0x80, 0x88, 0x70, 0x00}, // c
{0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d {0x08, 0x08, 0x68, 0x98, 0x88, 0x98, 0x68, 0x00}, // d
{0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e {0x00, 0x00, 0x70, 0x88, 0xF8, 0x80, 0x70, 0x00}, // e
{0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f {0x10, 0x28, 0x20, 0x70, 0x20, 0x20, 0x20, 0x00}, // f
{0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g {0x00, 0x00, 0x70, 0x98, 0x98, 0x68, 0x08, 0x70}, // g
{0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h {0x80, 0x80, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // h
{0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i {0x20, 0x00, 0x60, 0x20, 0x20, 0x20, 0x70, 0x00}, // i
{0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j {0x10, 0x00, 0x10, 0x10, 0x10, 0x90, 0x60, 0x00}, // j
{0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k {0x80, 0x80, 0x90, 0xA0, 0xC0, 0xA0, 0x90, 0x00}, // k
{0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l {0x60, 0x20, 0x20, 0x20, 0x20, 0x20, 0x70, 0x00}, // l
{0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m {0x00, 0x00, 0xD0, 0xA8, 0xA8, 0xA8, 0xA8, 0x00}, // m
{0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n {0x00, 0x00, 0xB0, 0xC8, 0x88, 0x88, 0x88, 0x00}, // n
{0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o {0x00, 0x00, 0x70, 0x88, 0x88, 0x88, 0x70, 0x00}, // o
{0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p {0x00, 0x00, 0xB0, 0xC8, 0xC8, 0xB0, 0x80, 0x80}, // p
{0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q {0x00, 0x00, 0x68, 0x98, 0x98, 0x68, 0x08, 0x08}, // q
{0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r {0x00, 0x00, 0xB0, 0xC8, 0x80, 0x80, 0x80, 0x00}, // r
{0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s {0x00, 0x00, 0x78, 0x80, 0x70, 0x08, 0xF0, 0x00}, // s
{0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t {0x20, 0x20, 0xF8, 0x20, 0x20, 0x28, 0x10, 0x00}, // t
{0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u {0x00, 0x00, 0x88, 0x88, 0x88, 0x98, 0x68, 0x00}, // u
{0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v {0x00, 0x00, 0x88, 0x88, 0x88, 0x50, 0x20, 0x00}, // v
{0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w {0x00, 0x00, 0x88, 0x88, 0xA8, 0xA8, 0x50, 0x00}, // w
{0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x {0x00, 0x00, 0x88, 0x50, 0x20, 0x50, 0x88, 0x00}, // x
{0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y {0x00, 0x00, 0x88, 0x88, 0x78, 0x08, 0x88, 0x70}, // y
{0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z {0x00, 0x00, 0xF8, 0x10, 0x20, 0x40, 0xF8, 0x00}, // z
{0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // { {0x10, 0x20, 0x20, 0x40, 0x20, 0x20, 0x10, 0x00}, // {
{0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // | {0x20, 0x20, 0x20, 0x00, 0x20, 0x20, 0x20, 0x00}, // |
{0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // } {0x40, 0x20, 0x20, 0x10, 0x20, 0x20, 0x40, 0x00}, // }
{0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~ {0x40, 0xA8, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00}, // ~
{0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL {0x70, 0xD8, 0xD8, 0x70, 0x00, 0x00, 0x00, 0x00} // DEL
}; };
/* /*
const char FONT8x8F[97][8] = { const char FONT8x8F[97][8] = {

View file

@ -70,24 +70,24 @@ void SetupSpi(int mode) {
switch (mode) { switch (mode) {
case SPI_FPGA_MODE: case SPI_FPGA_MODE:
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 (take default: 6 MCK periods)
(0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11) (0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11)
( 0 << 7) | // Local Loopback Disabled (0 << 7) | // Local Loopback Disabled
AT91C_SPI_MODFDIS | // Mode Fault Detection disabled AT91C_SPI_MODFDIS | // Mode Fault Detection disabled
( 0 << 2) | // Chip selects connected directly to peripheral (0 << 2) | // Chip selects connected directly to peripheral
AT91C_SPI_PS_FIXED | // Fixed Peripheral Select AT91C_SPI_PS_FIXED | // Fixed Peripheral Select
AT91C_SPI_MSTR; // Master Mode AT91C_SPI_MSTR; // Master Mode
AT91C_BASE_SPI->SPI_CSR[0] = AT91C_BASE_SPI->SPI_CSR[0] =
( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) (1 << 24) | // Delay between Consecutive Transfers (32 MCK periods)
( 1 << 16) | // Delay Before SPCK (1 MCK period) (1 << 16) | // Delay Before SPCK (1 MCK period)
( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud (6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud
AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits)
( 0 << 3) | // Chip Select inactive after transfer (0 << 3) | // Chip Select inactive after transfer
AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 (0 << 0); // Clock Polarity inactive state is logic 0
break; break;
/* /*
case SPI_LCD_MODE: case SPI_LCD_MODE:
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 (take default: 6 MCK periods)
@ -107,7 +107,7 @@ void SetupSpi(int mode) {
( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge
( 0 << 0); // Clock Polarity inactive state is logic 0 ( 0 << 0); // Clock Polarity inactive state is logic 0
break; break;
*/ */
default: default:
DisableSpi(); DisableSpi();
break; break;
@ -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
@ -200,7 +195,7 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8
// 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. // 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc.
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) { while ((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) {
// skip undesired data belonging to other bitstream_versions // skip undesired data belonging to other bitstream_versions
get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer);
} }
@ -209,12 +204,13 @@ static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga
} }
static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) {
return BigBuf_malloc(items*size); return BigBuf_malloc(items * 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);
@ -301,12 +299,12 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
i = 100000; i = 100000;
// wait for FPGA ready to accept data signal // wait for FPGA ready to accept data signal
while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) { while ((i) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT))) {
i--; i--;
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i == 0) {
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; return;
@ -323,12 +321,12 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
// continue to clock FPGA until ready signal goes high // continue to clock FPGA until ready signal goes high
i = 100000; i = 100000;
while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { while ((i--) && (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE))) {
HIGH(GPIO_FPGA_CCLK); HIGH(GPIO_FPGA_CCLK);
LOW(GPIO_FPGA_CCLK); LOW(GPIO_FPGA_CCLK);
} }
// crude error indicator, leave both red LEDs on and return // crude error indicator, leave both red LEDs on and return
if (i==0){ if (i == 0) {
LED_C_ON(); LED_C_ON();
LED_D_ON(); LED_D_ON();
return; return;
@ -344,9 +342,9 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp
*/ */
static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) {
int result = 0; int result = 0;
#define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section
uint16_t numbytes = 0; uint16_t numbytes = 0;
while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { while (numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) {
char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer);
numbytes++; numbytes++;
uint32_t current_length = 0; uint32_t current_length = 0;
@ -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,17 +466,25 @@ 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]);
} }
int FpgaGetCurrent(void) { int FpgaGetCurrent(void) {
@ -485,9 +496,9 @@ 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();
set_tracing(false); set_tracing(false);
LEDsoff(); LEDsoff();

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,29 +4,28 @@
#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();
uint16_t *destend = dest + n-1; uint16_t *destend = dest + n - 1;
// Reading data loop // Reading data loop
while(dest <= destend) { while (dest <= destend) {
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) {
*dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR);
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)) {
@ -62,19 +61,19 @@ void HfSnoop(int samplesToSkip, int triggersToSkip)
if (!BUTTON_PRESS()) { if (!BUTTON_PRESS()) {
int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0
while(waitcount != 0) { while (waitcount != 0) {
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

File diff suppressed because it is too large Load diff

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,45 +103,51 @@ 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();
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -38,7 +38,7 @@
// 4sample // 4sample
#define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x); #define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);
//#define SEND4STUFFBIT(x) ToSendStuffBit(x); //#define SEND4STUFFBIT(x) ToSendStuffBit(x);
// iceman, this threshold value, what makes 8 a good amplitude for this IQ values? // iceman, this threshold value, what makes 8 a good amplitude for this IQ values?
#ifndef SUBCARRIER_DETECT_THRESHOLD #ifndef SUBCARRIER_DETECT_THRESHOLD
# define SUBCARRIER_DETECT_THRESHOLD 8 # define SUBCARRIER_DETECT_THRESHOLD 8
#endif #endif
@ -107,10 +107,10 @@ static struct {
uint16_t bitCount; uint16_t bitCount;
int posCount; int posCount;
int thisBit; int thisBit;
/* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. /* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented.
int metric; int metric;
int metricN; int metricN;
*/ */
uint16_t shiftReg; uint16_t shiftReg;
uint8_t *output; uint8_t *output;
uint16_t len; uint16_t len;
@ -154,19 +154,19 @@ static void DemodInit(uint8_t *data) {
* @param timeout is in frame wait time, fwt, measured in ETUs * @param timeout is in frame wait time, fwt, measured in ETUs
*/ */
static void iso14b_set_timeout(uint32_t timeout) { static void iso14b_set_timeout(uint32_t timeout) {
#define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16) #define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16)
if(timeout > MAX_TIMEOUT) if (timeout > MAX_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);
@ -276,7 +273,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) {
// SEND4STUFFBIT(0); // SEND4STUFFBIT(0);
// //ToSendStuffBit(0); // //ToSendStuffBit(0);
// } // }
SEND4STUFFBIT( b & 1 ); SEND4STUFFBIT(b & 1);
b >>= 1; b >>= 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
@ -358,7 +355,7 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) {
case STATE_AWAITING_START_BIT: case STATE_AWAITING_START_BIT:
Uart.posCnt++; Uart.posCnt++;
if (bit) { if (bit) {
if (Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs if (Uart.posCnt > 50 / 2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs
// stayed high for too long between characters, error // stayed high for too long between characters, error
Uart.state = STATE_UNSYNCD; Uart.state = STATE_UNSYNCD;
} }
@ -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,12 +438,12 @@ 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?
// loop is a wait/delay ? // loop is a wait/delay ?
/* /*
for(uint8_t c = 0; c < 10;) { for(uint8_t c = 0; c < 10;) {
// keep tx buffer in a defined state anyway. // keep tx buffer in a defined state anyway.
@ -461,7 +457,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
UartInit(received); UartInit(received);
uint8_t mask; uint8_t mask;
while( !BUTTON_PRESS() ) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
// keep tx buffer in a defined state anyway. // keep tx buffer in a defined state anyway.
@ -470,12 +466,12 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
} }
// Wait for byte be become available in rx holding register // Wait for byte be become available in rx holding register
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;
for ( mask = 0x80; mask != 0; mask >>= 1) { for (mask = 0x80; mask != 0; mask >>= 1) {
if ( Handle14443bReaderUartBit(b & mask)) { if (Handle14443bReaderUartBit(b & mask)) {
*len = Uart.byteCnt; *len = Uart.byteCnt;
return true; return true;
} }
@ -485,18 +481,20 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) {
return false; return false;
} }
void ClearFpgaShiftingRegisters(void){ void ClearFpgaShiftingRegisters(void) {
volatile uint8_t b; volatile uint8_t b;
// 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
@ -508,18 +506,18 @@ void ClearFpgaShiftingRegisters(void){
//AT91C_BASE_SSC->SSC_THR = 0xFF; //AT91C_BASE_SSC->SSC_THR = 0xFF;
} }
void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ){ void WaitForFpgaDelayQueueIsEmpty(uint16_t delay) {
// Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again:
uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3,
for (uint8_t i = 0; i <= fpga_queued_bits/8 + 1; ) { for (uint8_t i = 0; i <= fpga_queued_bits / 8 + 1;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0xFF; AT91C_BASE_SSC->SSC_THR = 0xFF;
i++; i++;
} }
} }
} }
static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) { static void TransmitFor14443b_AsTag(uint8_t *response, uint16_t len) {
volatile uint32_t b; volatile uint32_t b;
@ -536,16 +534,17 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) {
FpgaSetupSsc(); FpgaSetupSsc();
// Transmit the response. // Transmit the response.
for(uint16_t i = 0; i < len;) { for (uint16_t i = 0; i < len;) {
// Put byte into tx holding register as soon as it is ready // Put byte into tx holding register as soon as it is ready
if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) {
AT91C_BASE_SSC->SSC_THR = response[++i]; AT91C_BASE_SSC->SSC_THR = response[++i];
} }
// 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,14 +590,15 @@ 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};
// ...PUPI/UID supplied from user. Adjust ATQB response accordingly // ...PUPI/UID supplied from user. Adjust ATQB response accordingly
if ( pupi > 0 ) { if (pupi > 0) {
num_to_bytes(pupi, 4, respATQB+1); num_to_bytes(pupi, 4, respATQB + 1);
AddCrc14B(respATQB, 12); AddCrc14B(respATQB, 12);
} }
@ -615,13 +616,13 @@ 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
if (cardSTATE == SIM_NOFIELD) { if (cardSTATE == SIM_NOFIELD) {
vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10;
if ( vHf > MF_MINFIELDV ) { if (vHf > MF_MINFIELDV) {
cardSTATE = SIM_IDLE; cardSTATE = SIM_IDLE;
LED_A_ON(); LED_A_ON();
} }
@ -637,9 +638,9 @@ void SimulateIso14443bTag(uint32_t pupi) {
// ISO14443-B protocol states: // ISO14443-B protocol states:
// REQ or WUP request in ANY state // REQ or WUP request in ANY state
// WUP in HALTED state // WUP in HALTED state
if (len == 5 ) { if (len == 5) {
if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) || if ((receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8) == 0x8 && cardSTATE == SIM_HALTED) ||
receivedCmd[0] == ISO14443B_REQB ){ receivedCmd[0] == ISO14443B_REQB) {
LogTrace(receivedCmd, len, 0, 0, NULL, true); LogTrace(receivedCmd, len, 0, 0, NULL, true);
cardSTATE = SIM_SELECTING; cardSTATE = SIM_SELECTING;
} }
@ -663,27 +664,27 @@ void SimulateIso14443bTag(uint32_t pupi) {
break; break;
} }
case SIM_SELECTING: { case SIM_SELECTING: {
TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen ); TransmitFor14443b_AsTag(encodedATQB, encodedATQBLen);
LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false); LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false);
cardSTATE = SIM_WORK; cardSTATE = SIM_WORK;
break; break;
} }
case SIM_HALTING: { case SIM_HALTING: {
TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
cardSTATE = SIM_HALTED; cardSTATE = SIM_HALTED;
break; break;
} }
case SIM_ACKNOWLEDGE: { case SIM_ACKNOWLEDGE: {
TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); TransmitFor14443b_AsTag(encodedOK, encodedOKLen);
LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false);
cardSTATE = SIM_IDLE; cardSTATE = SIM_IDLE;
break; break;
} }
case SIM_WORK: { case SIM_WORK: {
if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) { if (len == 7 && receivedCmd[0] == ISO14443B_HALT) {
cardSTATE = SIM_HALTED; cardSTATE = SIM_HALTED;
} else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) { } else if (len == 11 && receivedCmd[0] == ISO14443B_ATTRIB) {
cardSTATE = SIM_ACKNOWLEDGE; cardSTATE = SIM_ACKNOWLEDGE;
} else { } else {
// Todo: // Todo:
@ -693,7 +694,7 @@ void SimulateIso14443bTag(uint32_t pupi) {
Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived);
// CRC Check // CRC Check
if (len >= 3){ // if crc exists if (len >= 3) { // if crc exists
if (!check_crc(CRC_14443_B, receivedCmd, len)) if (!check_crc(CRC_14443_B, receivedCmd, len))
DbpString("+++CRC fail"); DbpString("+++CRC fail");
@ -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
} }
@ -790,7 +792,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
//note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow //note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow
#define CHECK_FOR_SUBCARRIER() { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); } #define CHECK_FOR_SUBCARRIER() { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); }
switch(Demod.state) { switch (Demod.state) {
case DEMOD_UNSYNCD: case DEMOD_UNSYNCD:
CHECK_FOR_SUBCARRIER(); CHECK_FOR_SUBCARRIER();
@ -834,7 +836,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
Demod.posCount = 0; // start of SOF sequence Demod.posCount = 0; // start of SOF sequence
} else { } else {
// maximum length of TR1 = 200 1/fs // maximum length of TR1 = 200 1/fs
if (Demod.posCount > 200/4) Demod.state = DEMOD_UNSYNCD; if (Demod.posCount > 200 / 4) Demod.state = DEMOD_UNSYNCD;
} }
Demod.posCount++; Demod.posCount++;
break; break;
@ -846,7 +848,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
if (v > 0) { if (v > 0) {
// low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges
if (Demod.posCount < 9*2) { if (Demod.posCount < 9 * 2) {
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
} else { } else {
LED_C_ON(); // Got SOF LED_C_ON(); // Got SOF
@ -856,7 +858,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
} }
} else { } else {
// low phase of SOF too long (> 12 etu) // low phase of SOF too long (> 12 etu)
if (Demod.posCount > 14*2) { if (Demod.posCount > 14 * 2) {
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
LED_C_OFF(); LED_C_OFF();
} }
@ -869,7 +871,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
MAKE_SOFT_DECISION(); MAKE_SOFT_DECISION();
if (v > 0) { if (v > 0) {
if (Demod.posCount > 6*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs if (Demod.posCount > 6 * 2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs
Demod.state = DEMOD_UNSYNCD; Demod.state = DEMOD_UNSYNCD;
LED_C_OFF(); LED_C_OFF();
} }
@ -907,7 +909,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) {
uint16_t s = Demod.shiftReg; uint16_t s = Demod.shiftReg;
// stop bit == '1', start bit == '0' // stop bit == '1', start bit == '0'
if ((s & 0x200) && (s & 0x001) == 0 ) { if ((s & 0x200) && (s & 0x001) == 0) {
// left shift to drop the startbit // left shift to drop the startbit
uint8_t b = (s >> 1); uint8_t b = (s >> 1);
Demod.output[Demod.len] = b; Demod.output[Demod.len] = b;
@ -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();
@ -951,12 +952,12 @@ static void GetTagSamplesFor14443bDemod() {
DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); DemodInit(BigBuf_malloc(MAX_FRAME_SIZE));
// The DMA buffer, used to stream samples from the FPGA // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *upTo = dmaBuf; int8_t *upTo = dmaBuf;
// 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;
} }
@ -967,27 +968,27 @@ static void GetTagSamplesFor14443bDemod() {
time_0 = GetCountSspClk(); time_0 = GetCountSspClk();
// rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read) // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read)
while ( !finished ) { while (!finished) {
LED_A_INV(); LED_A_INV();
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);
@ -995,10 +996,10 @@ static void GetTagSamplesFor14443bDemod() {
FpgaDisableSscDma(); FpgaDisableSscDma();
if ( upTo ) if (upTo)
upTo = NULL; upTo = NULL;
if ( Demod.len > 0 ) if (Demod.len > 0)
LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false);
} }
@ -1016,16 +1017,16 @@ static void TransmitFor14443b_AsReader(void) {
// loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why?
// 80*9 = 720us. // 80*9 = 720us.
for(c = 0; c < 50;) { for (c = 0; c < 50;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0xFF; AT91C_BASE_SSC->SSC_THR = 0xFF;
c++; c++;
} }
} }
// Send frame loop // Send frame loop
for(c = 0; c < ToSendMax;) { for (c = 0; c < ToSendMax;) {
// Put byte into tx holding register as soon as it is ready // Put byte into tx holding register as soon as it is ready
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
@ -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);
@ -1084,14 +1083,14 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) {
// if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
// if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0);
ToSendStuffBit( b & 1); ToSendStuffBit(b & 1);
ToSendStuffBit( (b>>1) & 1); ToSendStuffBit((b >> 1) & 1);
ToSendStuffBit( (b>>2) & 1); ToSendStuffBit((b >> 2) & 1);
ToSendStuffBit( (b>>3) & 1); ToSendStuffBit((b >> 3) & 1);
ToSendStuffBit( (b>>4) & 1); ToSendStuffBit((b >> 4) & 1);
ToSendStuffBit( (b>>5) & 1); ToSendStuffBit((b >> 5) & 1);
ToSendStuffBit( (b>>6) & 1); ToSendStuffBit((b >> 6) & 1);
ToSendStuffBit( (b>>7) & 1); ToSendStuffBit((b >> 7) & 1);
// Stop bit // Stop bit
ToSendStuffBit(1); ToSendStuffBit(1);
@ -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
@ -1128,9 +1127,9 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) {
TransmitFor14443b_AsReader(); TransmitFor14443b_AsReader();
if(trigger) LED_A_ON(); if (trigger) LED_A_ON();
LogTrace(cmd, len, time_start, GetCountSspClk()-time_start, NULL, true); LogTrace(cmd, len, time_start, GetCountSspClk() - time_start, NULL, true);
} }
/* Sends an APDU to the tag /* Sends an APDU to the tag
@ -1152,16 +1151,16 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no
// get response // get response
GetTagSamplesFor14443bDemod(); //no GetTagSamplesFor14443bDemod(); //no
if(Demod.len < 3) if (Demod.len < 3)
return 0; return 0;
// 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
if(response != NULL) if (response != NULL)
memcpy(response, Demod.output, Demod.len); memcpy(response, Demod.output, Demod.len);
return Demod.len; return Demod.len;
@ -1170,7 +1169,7 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r
/** /**
* SRx Initialise. * SRx Initialise.
*/ */
uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) { uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card) {
// INITIATE command: wake up the tag using the INITIATE // INITIATE command: wake up the tag using the INITIATE
static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b }; static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b };
// SELECT command (with space for CRC) // SELECT command (with space for CRC)
@ -1230,7 +1229,7 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) {
* TODO: Support multiple cards (perform anticollision) * TODO: Support multiple cards (perform anticollision)
* TODO: Verify CRC checksums * TODO: Verify CRC checksums
*/ */
uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { uint8_t iso14443b_select_card(iso14b_card_select_t *card) {
// WUPB command (including CRC) // WUPB command (including CRC)
// Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state
static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 };
@ -1251,8 +1250,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
if (card) { if (card) {
card->uidlen = 4; card->uidlen = 4;
memcpy(card->uid, Demod.output+1, 4); memcpy(card->uid, Demod.output + 1, 4);
memcpy(card->atqb, Demod.output+5, 7); memcpy(card->atqb, Demod.output + 5, 7);
} }
// copy the PUPI to ATTRIB ( PUPI == UID ) // copy the PUPI to ATTRIB ( PUPI == UID )
@ -1266,11 +1265,11 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
GetTagSamplesFor14443bDemod();//select_card GetTagSamplesFor14443bDemod();//select_card
// Answer to ATTRIB too short? // Answer to ATTRIB too short?
if(Demod.len < 3) if (Demod.len < 3)
return 2; return 2;
// VALIDATE CRC // VALIDATE CRC
if (!check_crc(CRC_14443_B, Demod.output, Demod.len) ) if (!check_crc(CRC_14443_B, Demod.output, Demod.len))
return 3; return 3;
if (card) { if (card) {
@ -1290,9 +1289,9 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) {
// FWT // FWT
uint8_t fwt = card->atqb[6] >> 4; uint8_t fwt = card->atqb[6] >> 4;
if ( fwt < 16 ){ if (fwt < 16) {
uint32_t fwt_time = (302 << fwt); uint32_t fwt_time = (302 << fwt);
iso14b_set_timeout( fwt_time); iso14b_set_timeout(fwt_time);
} }
} }
// reset PCB block number // reset PCB block number
@ -1363,11 +1362,11 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
iso14443b_setup(); iso14443b_setup();
iso14b_card_select_t *card = (iso14b_card_select_t*)buf; iso14b_card_select_t *card = (iso14b_card_select_t *)buf;
uint8_t res = iso14443b_select_srx_card(card); uint8_t res = iso14443b_select_srx_card(card);
// 0: OK 2: attrib fail, 3:crc fail, // 0: OK 2: attrib fail, 3:crc fail,
if ( res > 0 ) goto out; if (res > 0) goto out;
Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks); Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks);
@ -1390,8 +1389,8 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) {
// Now print out the memory location: // Now print out the memory location:
Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i,
(Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], (Demod.output[3] << 24) + (Demod.output[2] << 16) + (Demod.output[1] << 8) + Demod.output[0],
(Demod.output[4]<<8)+Demod.output[5]); (Demod.output[4] << 8) + Demod.output[5]);
if (i == 0xff) break; if (i == 0xff) break;
++i; ++i;
@ -1402,20 +1401,20 @@ out:
SpinDelay(20); SpinDelay(20);
} }
static void iso1444b_setup_sniff(void){ static void iso1444b_setup_sniff(void) {
LEDsoff(); LEDsoff();
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
@ -1469,12 +1467,12 @@ void RAMFUNC SniffIso14443b(void) {
iso1444b_setup_sniff(); iso1444b_setup_sniff();
// The DMA buffer, used to stream samples from the FPGA // The DMA buffer, used to stream samples from the FPGA
int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int8_t *dmaBuf = (int8_t *) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE);
int8_t *data = dmaBuf; int8_t *data = dmaBuf;
// 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,31 +1580,34 @@ 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;
} }
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) {
if((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { if ((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) {
AddCrc14B(cmd, len); AddCrc14B(cmd, len);
len += 2; len += 2;
} }
@ -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))
@ -105,7 +105,7 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendReset(); ToSendReset();
// Give it a bit of slack at the beginning // Give it a bit of slack at the beginning
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
// SOF for 1of4 // SOF for 1of4
@ -117,10 +117,10 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(0); ToSendStuffBit(0);
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(1); ToSendStuffBit(1);
for(i = 0; i < n; i++) { for (i = 0; i < n; i++) {
for(j = 0; j < 8; j += 2) { for (j = 0; j < 8; j += 2) {
int these = (cmd[i] >> j) & 3; int these = (cmd[i] >> j) & 3;
switch(these) { switch (these) {
case 0: case 0:
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(0); ToSendStuffBit(0);
@ -171,7 +171,7 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
// And slack at the end, too. // And slack at the end, too.
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
} }
@ -184,7 +184,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendReset(); ToSendReset();
// Give it a bit of slack at the beginning // Give it a bit of slack at the beginning
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
// SOF for 1of256 // SOF for 1of256
@ -197,7 +197,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
ToSendStuffBit(0); ToSendStuffBit(0);
for(i = 0; i < n; i++) { for (i = 0; i < n; i++) {
for (j = 0; j <= 255; j++) { for (j = 0; j <= 255; j++) {
if (cmd[i] == j) { if (cmd[i] == j) {
ToSendStuffBit(1); ToSendStuffBit(1);
@ -215,7 +215,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) {
ToSendStuffBit(1); ToSendStuffBit(1);
// And slack at the end, too. // And slack at the end, too.
for(i = 0; i < 24; i++) for (i = 0; i < 24; i++)
ToSendStuffBit(1); ToSendStuffBit(1);
} }
@ -236,10 +236,10 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w
} }
c = 0; c = 0;
for(;;) { for (;;) {
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c]; AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break; if (++c >= len) break;
} }
WDT_HIT(); WDT_HIT();
} }
@ -270,10 +270,10 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int
} }
c = 0; c = 0;
for(;;) { for (;;) {
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = cmd[c]; AT91C_BASE_SSC->SSC_THR = cmd[c];
if( ++c >= len) break; if (++c >= len) break;
} }
WDT_HIT(); WDT_HIT();
} }
@ -297,8 +297,8 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// First, correlate for SOF // First, correlate for SOF
for (i = 0; i < samplecount; i++) { for (i = 0; i < samplecount; i++) {
int corr = 0; int corr = 0;
for ( j = 0; j < ARRAYLEN(FrameSOF); j += skip) { for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) {
corr += FrameSOF[j] * dest[i+(j/skip)]; corr += FrameSOF[j] * dest[i + (j / skip)];
} }
if (corr > max) { if (corr > max) {
max = corr; max = corr;
@ -308,7 +308,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
// DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip)); // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip));
// greg - If correlation is less than 1 then there's little point in continuing // greg - If correlation is less than 1 then there's little point in continuing
if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1) if ((max / (ARRAYLEN(FrameSOF) / skip)) < 1)
return k; return k;
i = maxPos + ARRAYLEN(FrameSOF) / skip; i = maxPos + ARRAYLEN(FrameSOF) / skip;
@ -316,21 +316,21 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
uint8_t outBuf[ISO15_MAX_FRAME]; uint8_t outBuf[ISO15_MAX_FRAME];
memset(outBuf, 0, sizeof(outBuf)); memset(outBuf, 0, sizeof(outBuf));
uint8_t mask = 0x01; uint8_t mask = 0x01;
for(;;) { for (;;) {
int corr0 = 0, corr1 = 0, corrEOF = 0; int corr0 = 0, corr1 = 0, corrEOF = 0;
for (j = 0; j < ARRAYLEN(Logic0); j += skip) { for (j = 0; j < ARRAYLEN(Logic0); j += skip) {
corr0 += Logic0[j] * dest[i+(j/skip)]; corr0 += Logic0[j] * dest[i + (j / skip)];
} }
for (j = 0; j < ARRAYLEN(Logic1); j += skip) { for (j = 0; j < ARRAYLEN(Logic1); j += skip) {
corr1 += Logic1[j] * dest[i+(j/skip)]; corr1 += Logic1[j] * dest[i + (j / skip)];
} }
for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) {
corrEOF += FrameEOF[j] * dest[i+(j/skip)]; corrEOF += FrameEOF[j] * dest[i + (j / skip)];
} }
// 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)
@ -350,23 +350,23 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) {
mask = 0x01; mask = 0x01;
} }
if ( ( i + (int)ARRAYLEN(FrameEOF)) >= samplecount-1) { if ((i + (int)ARRAYLEN(FrameEOF)) >= samplecount - 1) {
//Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1); //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1);
break; break;
} }
} }
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
} }
for(i = 0; i < k; i++) for (i = 0; i < k; i++)
received[i] = outBuf[i]; received[i] = outBuf[i];
// return the number of bytes demodulated // return the number of bytes demodulated
@ -388,20 +388,20 @@ 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;
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = 0x00; //0x43; AT91C_BASE_SSC->SSC_THR = 0x00; //0x43;
// To make use of exact timing of next command from reader!! // To make use of exact timing of next command from reader!!
if (elapsed) (*elapsed)++; if (elapsed)(*elapsed)++;
} }
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -415,7 +415,7 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) {
// iceman 2016, amplitude sqrt(abs(i) + abs(q)) // iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) { if (getNext) {
buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if (counter >= SIGNAL_BUFF_SIZE) if (counter >= SIGNAL_BUFF_SIZE)
break; break;
@ -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();
@ -447,7 +447,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -461,9 +461,9 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap
// close to what we want. // close to what we want.
if (getNext) { if (getNext) {
buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); buf[counter++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if(counter >= 20000) if (counter >= 20000)
break; break;
} else { } else {
cq = ci; cq = ci;
@ -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);
@ -503,13 +503,13 @@ void AcquireRawAdcSamplesIso15693(void) {
// sending command // sending command
c = 0; c = 0;
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) {
AT91C_BASE_SSC->SSC_THR = ToSend[c]; AT91C_BASE_SSC->SSC_THR = ToSend[c];
c++; c++;
if(c == ToSendMax + 3) { if (c == ToSendMax + 3) {
break; break;
} }
} }
@ -521,7 +521,7 @@ void AcquireRawAdcSamplesIso15693(void) {
FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR);
c = 0; c = 0;
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -536,7 +536,7 @@ void AcquireRawAdcSamplesIso15693(void) {
// iceman 2016, amplitude sqrt(abs(i) + abs(q)) // iceman 2016, amplitude sqrt(abs(i) + abs(q))
if (getNext) { if (getNext) {
buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if (c >= 7000) break; if (c >= 7000) break;
@ -552,13 +552,13 @@ 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();
uint8_t *buf = BigBuf_get_addr(); uint8_t *buf = BigBuf_get_addr();
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
@ -571,9 +571,9 @@ void RecordRawAdcSamplesIso15693(void) {
// close to what we want. // close to what we want.
if (getNext) { if (getNext) {
buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); buf[c++] = (uint8_t)(MAX(ci, cq) + (MIN(ci, cq) >> 1));
if(c >= 7000) if (c >= 7000)
break; break;
} else { } else {
cq = ci; cq = ci;
@ -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,16 +658,17 @@ 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};
// one sub-carrier, inventory, 1 slot, fast rate // one sub-carrier, inventory, 1 slot, fast rate
// AFI is at bit 5 (1<<4) when doing an INVENTORY // AFI is at bit 5 (1<<4) when doing an INVENTORY
@ -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) {
if (d[0] & ( 1 << 3 )) char status[DBD15STATLEN + 1] = {0};
strncat(status, "ProtExt ", DBD15STATLEN); if (d[0] & (1 << 3))
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();
@ -819,7 +817,7 @@ void ReaderIso15693(uint32_t parameter) {
// THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME
uint32_t time_start = GetCountSspClk(); uint32_t time_start = GetCountSspClk();
uint8_t cmd[CMD_ID_RESP] = {0}; uint8_t cmd[CMD_ID_RESP] = {0};
BuildIdentifyRequest( cmd ); BuildIdentifyRequest(cmd);
TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait); TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait);
LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true);
@ -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,20 +889,20 @@ 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) {
time_start = GetCountSspClk(); time_start = GetCountSspClk();
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]
@ -918,7 +917,7 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) {
// (some manufactures offer a way to read the AFI, though) // (some manufactures offer a way to read the AFI, though)
void BruteforceIso15693Afi(uint32_t speed) { void BruteforceIso15693Afi(uint32_t speed) {
uint8_t data[7] = {0,0,0,0,0,0,0}; uint8_t data[7] = {0, 0, 0, 0, 0, 0, 0};
uint8_t buf[ISO15_MAX_FRAME]; uint8_t buf[ISO15_MAX_FRAME];
memset(buf, 0x00, sizeof(buf)); memset(buf, 0x00, sizeof(buf));
int datalen = 0, recvlen = 0; int datalen = 0, recvlen = 0;
@ -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);
@ -939,7 +938,7 @@ void BruteforceIso15693Afi(uint32_t speed) {
WDT_HIT(); WDT_HIT();
if (recvlen >= 12) { if (recvlen >= 12) {
Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) ); Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2));
} }
// now with AFI // now with AFI
@ -950,12 +949,12 @@ 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();
if (recvlen >= 12) { if (recvlen >= 12) {
Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2) ); Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2));
} }
if (BUTTON_PRESS()) { if (BUTTON_PRESS()) {
@ -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;
@ -50,18 +50,18 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */
#define WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */ #define WRITE_LOWERLIMIT 4 /* UID and MCC are not writable */
#define INPUT_THRESHOLD 8 /* heuristically determined, lower values */ #define INPUT_THRESHOLD 8 /* heuristically determined, lower values */
/* lead to detecting false ack during write */ /* lead to detecting false ack during write */
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// I/O interface abstraction (FPGA -> ARM) // I/O interface abstraction (FPGA -> ARM)
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
static inline uint8_t rx_byte_from_fpga() { static inline uint8_t rx_byte_from_fpga() {
for(;;) { for (;;) {
WDT_HIT(); WDT_HIT();
// wait for byte be become available in rx holding register // wait for byte be become available in rx holding register
if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) {
return AT91C_BASE_SSC->SSC_RHR; return AT91C_BASE_SSC->SSC_RHR;
} }
} }
@ -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);
} }
@ -100,7 +102,7 @@ static inline int32_t sample_power() {
static inline bool rx_bit() { static inline bool rx_bit() {
int32_t power; int32_t power;
for(size_t i = 0; i<5; ++i) { for (size_t i = 0; i < 5; ++i) {
power = sample_power(); power = sample_power();
} }
@ -120,12 +122,12 @@ static inline void tx_bit(bool bit) {
// insert pause // insert pause
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE; last_frame_end += RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
// return to high, wait for bit periode to end // return to high, wait for bit periode to end
last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE; last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -143,13 +145,13 @@ static void tx_frame(uint32_t frame, uint8_t len) {
// wait for next tx timeslot // wait for next tx timeslot
last_frame_end += RWD_FRAME_WAIT; last_frame_end += RWD_FRAME_WAIT;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
// backup ts for trace log // backup ts for trace log
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
// transmit frame, MSB first // transmit frame, MSB first
for(uint8_t i = 0; i < len; ++i) { for (uint8_t i = 0; i < len; ++i) {
bool bit = (frame >> i) & 0x01; bool bit = (frame >> i) & 0x01;
tx_bit(bit ^ legic_prng_get_bit()); tx_bit(bit ^ legic_prng_get_bit());
legic_prng_forward(1); legic_prng_forward(1);
@ -158,7 +160,7 @@ static void tx_frame(uint32_t frame, uint8_t len) {
// add pause to mark end of the frame // add pause to mark end of the frame
LOW(GPIO_SSC_DOUT); LOW(GPIO_SSC_DOUT);
last_frame_end += RWD_TIME_PAUSE; last_frame_end += RWD_TIME_PAUSE;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
HIGH(GPIO_SSC_DOUT); HIGH(GPIO_SSC_DOUT);
// log // log
@ -173,19 +175,19 @@ static uint32_t rx_frame(uint8_t len) {
// hold sampling until card is expected to respond // hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT; last_frame_end += TAG_FRAME_WAIT;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
// backup ts for trace log // backup ts for trace log
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);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
} }
// log // log
@ -203,23 +205,23 @@ static bool rx_ack() {
// hold sampling until card is expected to respond // hold sampling until card is expected to respond
last_frame_end += TAG_FRAME_WAIT; last_frame_end += TAG_FRAME_WAIT;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
// backup ts for trace log // backup ts for trace log
uint32_t last_frame_start = last_frame_end; uint32_t last_frame_start = last_frame_end;
uint32_t ack = 0; uint32_t ack = 0;
for(uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) { for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) {
// sample bit // sample bit
ack = rx_bit(); ack = rx_bit();
legic_prng_forward(1); legic_prng_forward(1);
// rx_bit runs only 95us, resync to TAG_BIT_PERIOD // rx_bit runs only 95us, resync to TAG_BIT_PERIOD
last_frame_end += TAG_BIT_PERIOD; last_frame_end += TAG_BIT_PERIOD;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
// check if it was an ACK // check if it was an ACK
if(ack) { if (ack) {
break; break;
} }
} }
@ -235,10 +237,10 @@ 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) {
case 0x0d: case 0x0d:
p_card->cmdsize = 6; p_card->cmdsize = 6;
p_card->addrsize = 5; p_card->addrsize = 5;
@ -282,7 +284,7 @@ static void init_reader(bool clear_mem) {
// reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier.
legic_mem = BigBuf_get_EM_addr(); legic_mem = BigBuf_get_EM_addr();
if(legic_mem) { if (legic_mem) {
memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE); memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE);
} }
@ -302,19 +304,19 @@ 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;
// Switch on carrier and let the card charge for 5ms. // Switch on carrier and let the card charge for 5ms.
last_frame_end += 7500; last_frame_end += 7500;
while(GET_TICKS < last_frame_end) { }; while (GET_TICKS < last_frame_end) { };
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);
@ -359,7 +361,7 @@ static int16_t read_byte(uint16_t index, uint8_t cmd_sz) {
// check received against calculated crc // check received against calculated crc
uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte); uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte);
if(calc_crc != crc) { if (calc_crc != crc) {
Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc);
return -1; return -1;
} }
@ -398,17 +400,17 @@ 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;
} }
// read UID // read UID
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;
@ -417,13 +419,13 @@ void LegicRfInfo(void) {
// read MCC and check against UID // read MCC and check against UID
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,28 +437,28 @@ 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;
} }
// do not read beyond card memory // do not read beyond card memory
if(len + offset > card.cardsize) { if (len + offset > card.cardsize) {
len = card.cardsize - offset; len = card.cardsize - offset;
} }
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();
@ -468,40 +470,36 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) {
init_reader(false); init_reader(false);
// 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;
} }
// do not write beyond card memory // do not write beyond card memory
if(len + offset > card.cardsize) { if (len + offset > card.cardsize) {
len = card.cardsize - offset; len = card.cardsize - offset;
} }
// write in reverse order, only then is DCF (decremental field) writable // write in reverse order, only then is DCF (decremental field) writable
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.
@ -39,23 +39,23 @@ void printConfig() {
* @param sc * @param sc
*/ */
void setSamplingConfig(sample_config *sc) { void setSamplingConfig(sample_config *sc) {
if(sc->divisor != 0) config.divisor = sc->divisor; if (sc->divisor != 0) config.divisor = sc->divisor;
if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; if (sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample;
if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; if (sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold;
config.decimation = (sc->decimation != 0) ? sc->decimation : 1; config.decimation = (sc->decimation != 0) ? sc->decimation : 1;
config.averaging = sc->averaging; config.averaging = sc->averaging;
if(config.bits_per_sample > 8) config.bits_per_sample = 8; if (config.bits_per_sample > 8) config.bits_per_sample = 8;
printConfig(); printConfig();
} }
sample_config* getSamplingConfig() { sample_config *getSamplingConfig() {
return &config; return &config;
} }
struct BitstreamOut { struct BitstreamOut {
uint8_t * buffer; uint8_t *buffer;
uint32_t numbits; uint32_t numbits;
uint32_t position; uint32_t position;
}; };
@ -65,10 +65,10 @@ struct BitstreamOut {
* @param stream * @param stream
* @param bit * @param bit
*/ */
void pushBit( BitstreamOut* stream, uint8_t bit) { void pushBit(BitstreamOut *stream, uint8_t bit) {
int bytepos = stream->position >> 3; // divide by 8 int bytepos = stream->position >> 3; // divide by 8
int bitpos = stream->position & 7; int bitpos = stream->position & 7;
*(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); *(stream->buffer + bytepos) |= (bit > 0) << (7 - bitpos);
stream->position++; stream->position++;
stream->numbits++; stream->numbits++;
} }
@ -76,13 +76,13 @@ 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) {
FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaDownloadAndGo(FPGA_BITSTREAM_LF);
if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) if ((divisor == 1) || (divisor < 0) || (divisor > 255))
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz
else if (divisor == 0) else if (divisor == 0)
FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz
@ -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
uint32_t sample_sum =0 ; // if we want to do averaging
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;
} }
@ -217,16 +230,16 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag
* @return number of bits sampled * @return number of bits sampled
*/ */
uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { uint32_t DoAcquisition_default(int trigger_threshold, bool silent) {
return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0); return DoAcquisition(1, 8, 0, trigger_threshold, silent, 0, 0);
} }
uint32_t DoAcquisition_config( bool silent, int sample_size) { uint32_t DoAcquisition_config(bool silent, int sample_size) {
return DoAcquisition(config.decimation return DoAcquisition(config.decimation
,config.bits_per_sample , config.bits_per_sample
,config.averaging , config.averaging
,config.trigger_threshold , config.trigger_threshold
,silent , silent
,sample_size , sample_size
,0); , 0);
} }
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) {
@ -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;
} }
/** /**
@ -267,28 +278,37 @@ uint32_t SnoopLF() {
**/ **/
void doT55x7Acquisition(size_t sample_size) { void doT55x7Acquisition(size_t sample_size) {
#define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph
#define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph
#define T55xx_READ_TOL 5 #define T55xx_READ_TOL 5
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
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();
@ -313,7 +333,7 @@ void doT55x7Acquisition(size_t sample_size) {
} }
// skip until first high samples begin to change // skip until first high samples begin to change
if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){ if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL) {
// if just found start - recover last sample // if just found start - recover last sample
if (!startFound) { if (!startFound) {
dest[i++] = lastSample; dest[i++] = lastSample;
@ -342,27 +362,33 @@ void doCotagAcquisition(size_t sample_size) {
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > sample_size ) if (bufsize > 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) {
if (sample < COTAG_ONE_THRESHOLD) { if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
@ -370,8 +396,8 @@ void doCotagAcquisition(size_t sample_size) {
noise_counter = 0; noise_counter = 0;
firsthigh = 1; firsthigh = 1;
} }
if ( !firstlow ){ if (!firstlow) {
if (sample > COTAG_ZERO_THRESHOLD ) { if (sample > COTAG_ZERO_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
} }
@ -381,12 +407,12 @@ void doCotagAcquisition(size_t sample_size) {
++i; ++i;
if ( sample > COTAG_ONE_THRESHOLD) if (sample > COTAG_ONE_THRESHOLD)
dest[i] = 255; dest[i] = 255;
else if ( sample < COTAG_ZERO_THRESHOLD) else if (sample < COTAG_ZERO_THRESHOLD)
dest[i] = 0; dest[i] = 0;
else else
dest[i] = dest[i-1]; dest[i] = dest[i - 1];
} }
} }
} }
@ -396,28 +422,33 @@ uint32_t doCotagAcquisitionManchester() {
uint8_t *dest = BigBuf_get_addr(); uint8_t *dest = BigBuf_get_addr();
uint16_t bufsize = BigBuf_max_traceLen(); uint16_t bufsize = BigBuf_max_traceLen();
if ( bufsize > COTAG_BITS ) if (bufsize > COTAG_BITS)
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) {
if (sample < COTAG_ONE_THRESHOLD) { if (sample < COTAG_ONE_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
@ -426,8 +457,8 @@ uint32_t doCotagAcquisitionManchester() {
firsthigh = 1; firsthigh = 1;
} }
if ( !firstlow ){ if (!firstlow) {
if (sample > COTAG_ZERO_THRESHOLD ) { if (sample > COTAG_ZERO_THRESHOLD) {
noise_counter++; noise_counter++;
continue; continue;
} }
@ -436,20 +467,18 @@ uint32_t doCotagAcquisitionManchester() {
} }
// set sample 255, 0, or previous // set sample 255, 0, or previous
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;
} }
// full T1 periods, // full T1 periods,
if ( period > 0 ) { if (period > 0) {
--period; --period;
continue; continue;
} }

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.
@ -78,7 +78,7 @@ void LFSetupFPGAForADC(int divisor, bool lf_field);
*/ */
void setSamplingConfig(sample_config *sc); void setSamplingConfig(sample_config *sc);
sample_config * getSamplingConfig(); sample_config *getSamplingConfig();
void printConfig(); void printConfig();

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

@ -10,13 +10,13 @@
// the block number for the ISO14443-4 PCB // the block number for the ISO14443-4 PCB
uint8_t pcb_blocknum = 0; uint8_t pcb_blocknum = 0;
// Deselect card by sending a s-block. the crc is precalced for speed // Deselect card by sending a s-block. the crc is precalced for speed
static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; static uint8_t deselect_cmd[] = {0xc2, 0xe0, 0xb4};
//static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 }; //static uint8_t __msg[MAX_FRAME_SIZE] = { 0x0A, 0x00, 0x00, /* ..., */ 0x00 };
/* PCB CID CMD PAYLOAD */ /* PCB CID CMD PAYLOAD */
//static uint8_t __res[MAX_FRAME_SIZE]; //static uint8_t __res[MAX_FRAME_SIZE];
bool InitDesfireCard(){ bool InitDesfireCard() {
iso14a_card_select_t card; iso14a_card_select_t card;
@ -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;
} }
@ -40,7 +40,7 @@ enum {
BAR = 0x08, BAR = 0x08,
} CmdOptions ; } CmdOptions ;
void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain) {
/* ARG0 contains flags. /* ARG0 contains flags.
0x01 = init card. 0x01 = init card.
@ -50,27 +50,27 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
uint8_t flags = arg0; uint8_t flags = arg0;
size_t datalen = arg1; size_t datalen = arg1;
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);
} }
if ( flags & CLEARTRACE ) if (flags & CLEARTRACE)
clear_trace(); clear_trace();
if ( flags & INIT ){ if (flags & INIT) {
if ( !InitDesfireCard() ) if (!InitDesfireCard())
return; return;
} }
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) {
OnError(2); OnError(2);
return; return;
} }
@ -78,18 +78,18 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){
// reset the pcb_blocknum, // reset the pcb_blocknum,
pcb_blocknum = 0; pcb_blocknum = 0;
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
@ -105,14 +105,14 @@ void MifareDesfireGetInformation(){
iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN);
// 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;
} }
@ -127,7 +127,7 @@ void MifareDesfireGetInformation(){
size_t cmd_len = sizeof(cmd); size_t cmd_len = sizeof(cmd);
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if (!len) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
@ -135,12 +135,12 @@ void MifareDesfireGetInformation(){
LED_A_OFF(); LED_A_OFF();
LED_B_ON(); LED_B_ON();
memcpy(dataout+7,resp+3,7); memcpy(dataout + 7, resp + 3, 7);
// ADDITION_FRAME 1 // ADDITION_FRAME 1
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if (!len) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
@ -148,46 +148,44 @@ void MifareDesfireGetInformation(){
LED_B_OFF(); LED_B_OFF();
LED_C_ON(); LED_C_ON();
memcpy(dataout+7+7,resp+3,7); memcpy(dataout + 7 + 7, resp + 3, 7);
// ADDITION_FRAME 2 // ADDITION_FRAME 2
len = DesfireAPDU(cmd, cmd_len, resp); len = DesfireAPDU(cmd, cmd_len, resp);
if ( !len ) { if (!len) {
print_result("ERROR <--: ", resp, len); print_result("ERROR <--: ", resp, len);
OnError(3); OnError(3);
return; return;
} }
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,29 +193,30 @@ 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) {
memcpy(keybytes,null_key_data8,8); uint8_t null_key_data8[8] = {0x00};
} else{ memcpy(keybytes, null_key_data8, 8);
memcpy(keybytes, datain+1, datalen); } else {
memcpy(keybytes, datain + 1, datalen);
} }
} }
} }
@ -225,46 +224,46 @@ 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);
return; return;
} }
if ( resp[2] == 0xaf ){ if (resp[2] == 0xaf) {
} else { } else {
DbpString("Authentication failed. Invalid key number."); DbpString("Authentication failed. Invalid key number.");
OnError(3); OnError(3);
return; return;
} }
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);
rol(decRndB,8); rol(decRndB, 8);
// This should be random // This should be random
uint8_t decRndA[8] = {0x00}; uint8_t decRndA[8] = {0x00};
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,40 +273,40 @@ 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);
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, both, 16 ); memcpy(cmd + 1, both, 16);
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);
return; return;
} }
if ( resp[2] == 0x00 ){ if (resp[2] == 0x00) {
struct desfire_key sessionKey = {0}; struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey; desfirekey_t skey = &sessionKey;
Desfire_session_key_new( RndA, RndB , key, skey ); Desfire_session_key_new(RndA, RndB, key, skey);
//print_result("SESSION : ", skey->data, 8); //print_result("SESSION : ", skey->data, 8);
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);
for (int x = 0; x < 8; x++) { for (int x = 0; x < 8; x++) {
if (decRndA[x] != encRndA[x]) { if (decRndA[x] != encRndA[x]) {
DbpString("Authentication failed. Cannot varify PICC."); DbpString("Authentication failed. Cannot varify PICC.");
@ -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,25 +417,26 @@ 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: {
//defaultkey //defaultkey
uint8_t keybytes[16] = {0x00}; uint8_t keybytes[16] = {0x00};
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);
} }
struct desfire_key defaultkey = {0x00}; struct desfire_key defaultkey = {0x00};
desfirekey_t key = &defaultkey; desfirekey_t key = &defaultkey;
Desfire_aes_key_new( keybytes, key); Desfire_aes_key_new(keybytes, key);
AesCtx ctx; AesCtx ctx;
if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){ uint8_t IV[16] = {0x00};
if( MF_DBGLEVEL >= 4) { if (AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0) {
if (DBGLEVEL >= 4) {
DbpString("AES context failed to init"); DbpString("AES context failed to init");
} }
OnError(7); OnError(7);
@ -446,40 +446,42 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain
cmd[0] = AUTHENTICATE_AES; cmd[0] = AUTHENTICATE_AES;
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);
return; return;
} }
memcpy( encRndB, resp+3, 16); memcpy(encRndB, resp + 3, 16);
// dekryptera tagnonce. // dekryptera tagnonce.
AesDecrypt(&ctx, encRndB, decRndB, 16); AesDecrypt(&ctx, encRndB, decRndB, 16);
rol(decRndB,16); rol(decRndB, 16);
memcpy(both, nonce,16); uint8_t nonce[16] = {0x00};
memcpy(both+16, decRndB ,16 ); memcpy(both, nonce, 16);
AesEncrypt(&ctx, both, encBoth, 32 ); memcpy(both + 16, decRndB, 16);
uint8_t encBoth[32] = {0x00};
AesEncrypt(&ctx, both, encBoth, 32);
cmd[0] = ADDITIONAL_FRAME; cmd[0] = ADDITIONAL_FRAME;
memcpy(cmd+1, encBoth, 32 ); memcpy(cmd + 1, encBoth, 32);
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);
return; return;
} }
if ( resp[2] == 0x00 ){ if (resp[2] == 0x00) {
// Create AES Session key // Create AES Session key
struct desfire_key sessionKey = {0}; struct desfire_key sessionKey = {0};
desfirekey_t skey = &sessionKey; desfirekey_t skey = &sessionKey;
Desfire_session_key_new( nonce, decRndB , key, skey ); Desfire_session_key_new(nonce, decRndB, key, skey);
print_result("SESSION : ", skey->data, 16); print_result("SESSION : ", skey->data, 16);
} else { } else {
DbpString("Authentication failed."); DbpString("Authentication failed.");
@ -492,31 +494,31 @@ 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
int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ 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
} }
@ -534,38 +535,38 @@ 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
memcpy(cmd+2, datain, len); memcpy(cmd + 2, datain, len);
AddCrc14A(cmd, len+2); AddCrc14A(cmd, len + 2);
memcpy(dataout, cmd, cmdlen); memcpy(dataout, cmd, cmdlen);
return cmdlen; return cmdlen;
} }
// crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */
// crc_update(&desfire_crc32, addr, addr_sz); // crc_update(&desfire_crc32, addr, addr_sz);
// crc_update(&desfire_crc32, byte, 8); // crc_update(&desfire_crc32, byte, 8);
// uint32_t crc = crc_finish(&desfire_crc32); // uint32_t crc = crc_finish(&desfire_crc32);
void OnSuccess(){ void OnSuccess() {
pcb_blocknum = 0; pcb_blocknum = 0;
ReaderTransmit(deselect_cmd, 3 , NULL); ReaderTransmit(deselect_cmd, 3, NULL);
mifare_ultra_halt(); mifare_ultra_halt();
switch_off(); switch_off();
} }
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,10 +10,14 @@
#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};
static uint8_t sniffATQA[2] = {0,0}; static uint8_t sniffATQA[2] = {0, 0};
static uint8_t sniffSAK = 0; static uint8_t sniffSAK = 0;
static uint8_t sniffBuf[17]; static uint8_t sniffBuf[17];
static uint32_t timerData = 0; static uint32_t timerData = 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;
@ -71,13 +75,13 @@ 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;
} }
tUart* uart = GetUart(); tUart *uart = GetUart();
tDemod* demod = GetDemod(); tDemod *demod = GetDemod();
MfSniffInit(); MfSniffInit();
@ -86,7 +90,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
while (!BUTTON_PRESS()) { while (!BUTTON_PRESS()) {
WDT_HIT(); WDT_HIT();
LED_A_ON(); LED_A_ON();
/* /*
if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time
// check if a transaction is completed (timeout after 2000ms). // check if a transaction is completed (timeout after 2000ms).
// if yes, stop the DMA transfer and send what we have so far to the client // if yes, stop the DMA transfer and send what we have so far to the client
@ -143,7 +147,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// no need to try decoding tag data if the reader is sending // no need to try decoding tag data if the reader is sending
if (!TagIsActive) { if (!TagIsActive) {
uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4);
if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { if (MillerDecoding(readerbyte, (sniffCounter - 1) * 4)) {
LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); LogTrace(receivedCmd, uart->len, 0, 0, NULL, true);
DemodReset(); DemodReset();
UartReset(); UartReset();
@ -154,7 +158,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
// no need to try decoding tag data if the reader is sending // no need to try decoding tag data if the reader is sending
if (!ReaderIsActive) { if (!ReaderIsActive) {
uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F);
if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { if (ManchesterDecoding(tagbyte, 0, (sniffCounter - 1) * 4)) {
LogTrace(receivedResp, demod->len, 0, 0, NULL, false); LogTrace(receivedResp, demod->len, 0, 0, NULL, false);
DemodReset(); DemodReset();
UartReset(); UartReset();
@ -175,7 +179,7 @@ void RAMFUNC SniffMifare(uint8_t param) {
switch_off(); switch_off();
} }
void MfSniffInit(void){ void MfSniffInit(void) {
memset(sniffUID, 0x00, sizeof(sniffUID)); memset(sniffUID, 0x00, sizeof(sniffUID));
memset(sniffATQA, 0x00, sizeof(sniffATQA)); memset(sniffATQA, 0x00, sizeof(sniffATQA));
memset(sniffBuf, 0x00, sizeof(sniffBuf)); memset(sniffBuf, 0x00, sizeof(sniffBuf));
@ -184,9 +188,9 @@ void MfSniffInit(void){
timerData = 0; timerData = 0;
} }
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;
@ -30,21 +27,24 @@ void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, u
return; return;
} }
void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len) {
mf_crypto1_decryptEx(pcs, data, len, data); mf_crypto1_decryptEx(pcs, data, len, data);
} }
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)));
} }
} }
@ -58,23 +58,23 @@ uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) {
} }
// send X byte basic commands // send X byte basic commands
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) {
uint8_t dcmd[data_size+3]; uint8_t dcmd[data_size + 3];
dcmd[0] = cmd; dcmd[0] = cmd;
memcpy(dcmd+1, data, data_size); memcpy(dcmd + 1, data, data_size);
AddCrc14A(dcmd, data_size+1); AddCrc14A(dcmd, data_size + 1);
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;
} }
// 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
@ -85,7 +85,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd,
par[0] = 0; par[0] = 0;
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7 - pos));
} }
ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing);
} else { } else {
@ -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;
@ -122,12 +122,12 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
uint32_t pos, nt, ntpp; // Supplied tag nonce uint32_t pos, nt, ntpp; // Supplied tag nonce
uint8_t par[1] = {0x00}; uint8_t par[1] = {0x00};
uint8_t nr[4]; uint8_t nr[4];
uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; uint8_t mf_nr_ar[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// "random" reader nonce: // "random" reader nonce:
num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); num_to_bytes(prng_successor(GetTickCount(), 32), 4, nr);
// Transmit MIFARE_CLASSIC_AUTH // Transmit MIFARE_CLASSIC_AUTH
len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing);
@ -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
@ -163,7 +163,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
par[0] = 0; par[0] = 0;
for (pos = 0; pos < 4; pos++) { for (pos = 0; pos < 4; pos++) {
mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos];
par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7 - pos));
} }
// Skip 32 bits in pseudo random generator // Skip 32 bits in pseudo random generator
@ -171,9 +171,9 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN
// ar+parity // ar+parity
for (pos = 4; pos < 8; pos++) { for (pos = 4; pos < 8; pos++) {
nt = prng_successor(nt,8); nt = prng_successor(nt, 8);
mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); mf_nr_ar[pos] = crypto1_byte(pcs, 0x00, 0) ^ (nt & 0xff);
par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7 - pos));
} }
// Transmit reader nonce and reader answer // Transmit reader nonce and reader answer
@ -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;
} }
@ -224,7 +224,7 @@ int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blo
} }
// mifare ultralight commands // mifare ultralight commands
int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack) {
uint16_t len = 0; uint16_t len = 0;
uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00};
@ -232,27 +232,27 @@ 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);
return 1; return 1;
} }
int mifare_ultra_auth(uint8_t *keybytes){ int mifare_ultra_auth(uint8_t *keybytes) {
/// 3des2k /// 3des2k
uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; uint8_t random_a[8] = {1, 1, 1, 1, 1, 1, 1, 1};
uint8_t random_b[8] = {0x00}; uint8_t random_b[8] = {0x00};
uint8_t enc_random_b[8] = {0x00}; uint8_t enc_random_b[8] = {0x00};
uint8_t rnd_ab[16] = {0x00}; uint8_t rnd_ab[16] = {0x00};
@ -262,36 +262,36 @@ int mifare_ultra_auth(uint8_t *keybytes){
uint16_t len = 0; uint16_t len = 0;
uint8_t resp[19] = {0x00}; uint8_t resp[19] = {0x00};
uint8_t respPar[3] = {0,0,0}; uint8_t respPar[3] = {0, 0, 0};
// 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;
} }
// tag nonce. // tag nonce.
memcpy(enc_random_b,resp+1,8); memcpy(enc_random_b, resp + 1, 8);
// decrypt nonce. // decrypt nonce.
tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); tdes_2key_dec((void *)random_b, (void *)enc_random_b, sizeof(random_b), (const void *)key, IV);
rol(random_b,8); rol(random_b, 8);
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]);
Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x",
random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); random_b[0], random_b[1], random_b[2], random_b[3], random_b[4], random_b[5], random_b[6], random_b[7]);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
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[0], rnd_ab[1], rnd_ab[2], rnd_ab[3], rnd_ab[4], rnd_ab[5], rnd_ab[6], rnd_ab[7]);
Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11], rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
} }
// encrypt out, in, length, key, iv // encrypt out, in, length, key, iv
@ -299,37 +299,37 @@ 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;
} }
uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; uint8_t enc_resp[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; uint8_t resp_random_a[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
memcpy(enc_resp, resp+1, 8); memcpy(enc_resp, resp + 1, 8);
// 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]);
Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x",
rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], rnd_ab[8], rnd_ab[9], rnd_ab[10], rnd_ab[11],
rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); rnd_ab[12], rnd_ab[13], rnd_ab[14], rnd_ab[15]);
Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x",
random_a[0],random_a[1],random_a[2],random_a[3], random_a[0], random_a[1], random_a[2], random_a[3],
random_a[4],random_a[5],random_a[6],random_a[7]); random_a[4], random_a[5], random_a[6], random_a[7]);
Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x",
resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], resp_random_a[0], resp_random_a[1], resp_random_a[2], resp_random_a[3],
resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); resp_random_a[4], resp_random_a[5], resp_random_a[6], resp_random_a[7]);
} }
return 1; return 1;
} }
@ -342,33 +342,33 @@ 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) {
#define MFU_MAX_RETRIES 5 #define MFU_MAX_RETRIES 5
uint8_t res; uint8_t res;
for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) {
res = mifare_ultra_readblockEx(blockNo, blockData); res = mifare_ultra_readblockEx(blockNo, blockData);
// break if OK, or NACK. // break if OK, or NACK.
switch ( res ) { switch (res) {
case 0: case 0:
case 1: case 1:
return res; return res;
@ -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;
} }
@ -404,7 +404,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl
// crypto // crypto
for (pos = 0; pos < 18; pos++) { for (pos = 0; pos < 18; pos++) {
d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos];
par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); par[pos >> 3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos & 0x0007)));
} }
ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL);
@ -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;
} }
@ -464,13 +464,13 @@ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) {
uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00};
// command MIFARE_CLASSIC_WRITEBLOCK // command MIFARE_CLASSIC_WRITEBLOCK
memcpy(block+1, blockData, 4); memcpy(block + 1, blockData, 4);
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;
} }
return 0; return 0;
@ -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;
@ -510,7 +510,7 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) {
if (sectorNo < 32) if (sectorNo < 32)
return sectorNo * 4; return sectorNo * 4;
else else
return 32*4 + (sectorNo - 32) * 16; return 32 * 4 + (sectorNo - 32) * 16;
} }
@ -520,23 +520,23 @@ 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) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth); memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth);
} }
void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { void emlGetMem(uint8_t *data, int blockNum, int blocksCount) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
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) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16; uint8_t *data = emCARD + blockNum * 16;
if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) ||
(data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) ||
@ -550,8 +550,8 @@ int emlCheckValBl(int blockNum) {
} }
int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16; uint8_t *data = emCARD + blockNum * 16;
if (emlCheckValBl(blockNum)) if (emlCheckValBl(blockNum))
return 1; return 1;
@ -562,8 +562,8 @@ 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) {
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
uint8_t* data = emCARD + blockNum * 16; uint8_t *data = emCARD + blockNum * 16;
memcpy(data + 0, &blReg, 4); memcpy(data + 0, &blReg, 4);
memcpy(data + 8, &blReg, 4); memcpy(data + 8, &blReg, 4);
@ -580,7 +580,7 @@ int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) {
uint64_t emlGetKey(int sectorNum, int keyType) { uint64_t emlGetKey(int sectorNum, int keyType) {
uint8_t key[6] = {0x00}; uint8_t key[6] = {0x00};
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6);
return bytes_to_num(key, 6); return bytes_to_num(key, 6);
} }
@ -588,11 +588,11 @@ uint64_t emlGetKey(int sectorNum, int keyType) {
void emlClearMem(void) { void emlClearMem(void) {
const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04};
uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t *emCARD = BigBuf_get_EM_addr();
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,57 +600,70 @@ 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) {
uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00}; uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00};
AddCrc14A(dcmd, 3); AddCrc14A(dcmd, 3);
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;
} }
int mifare_sendcmd_special2(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_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) {
uint8_t dcmd[20] = {0x00}; uint8_t dcmd[20] = {0x00};
dcmd[0] = cmd; dcmd[0] = cmd;
memcpy(dcmd+1,data,17); memcpy(dcmd + 1, data, 17);
AddCrc14A(dcmd, 18); AddCrc14A(dcmd, 18);
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;
} }
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData) {
int len; int len;
// load key, keynumber // load key, keynumber
uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; uint8_t data[2] = {MFDES_AUTHENTICATE, 0x00};
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
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],
receivedAnswer[10],receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return 0;
@ -658,29 +671,29 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){
return 1; return 1;
} }
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) {
int len; int len;
uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME};
memcpy(data+1,key,16); memcpy(data + 1, key, 16);
uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00};
uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00};
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],
receivedAnswer[10],receivedAnswer[11]); receivedAnswer[10], receivedAnswer[11]);
} }
memcpy(blockData, receivedAnswer, 12); memcpy(blockData, receivedAnswer, 12);
return 0; return 0;

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,72 +31,84 @@
#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);
// mifare classic // mifare classic
int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested);
int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing);
int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData);
int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid);
int mifare_classic_halt_ex(struct Crypto1State *pcs); 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);
int mifare_ultra_halt(); int mifare_ultra_halt();
// desfire // desfire
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);
int mifare_sendcmd_special2(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_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t *data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing);
int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); 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
@ -96,7 +96,7 @@ uint8_t xopt__select(bool x, bool y, uint8_t r)
} }
*/ */
void opt_successor(const uint8_t* k, State *s, bool y, State* successor) { void opt_successor(const uint8_t *k, State *s, bool y, State *successor) {
uint8_t Tt = 1 & opt_T(s); uint8_t Tt = 1 & opt_T(s);
successor->t = (s->t >> 1); successor->t = (s->t >> 1);
@ -105,15 +105,14 @@ void opt_successor(const uint8_t* k, State *s, bool y, State* successor) {
successor->b = s->b >> 1; successor->b = s->b >> 1;
successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7;
successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ; successor->r = (k[opt__select(Tt, y, s->r)] ^ successor->b) + s->l ;
successor->l = successor->r+s->r; successor->l = successor->r + s->r;
} }
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,19 +140,17 @@ 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);
} }
} }
} }
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; State temp = {0, 0, 0, 0};
for (uint8_t times = 0; times < 4; times++) {
uint8_t bout = 0; uint8_t bout = 0;
State temp = {0,0,0,0};
for ( ; times < 4; times++) {
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;
@ -174,7 +171,7 @@ void opt_output(const uint8_t* k,State* s, uint8_t *buffer) {
} }
} }
void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) { void opt_MAC(uint8_t *k, uint8_t *input, uint8_t *out) {
State _init = { State _init = {
((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l
((k[0] ^ 0x4c) + 0x21) & 0xFF,// r ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r
@ -182,8 +179,8 @@ void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) {
0xE012 // t 0xE012 // t
}; };
opt_suc(k,&_init,input,12, false); opt_suc(k, &_init, input, 12, false);
opt_output(k,&_init, out); opt_output(k, &_init, out);
} }
uint8_t rev_byte(uint8_t b) { uint8_t rev_byte(uint8_t b) {
@ -193,23 +190,23 @@ uint8_t rev_byte(uint8_t b) {
return b; return b;
} }
void opt_reverse_arraybytecpy(uint8_t* dest, uint8_t *src, size_t len) { void opt_reverse_arraybytecpy(uint8_t *dest, uint8_t *src, size_t len) {
uint8_t i; uint8_t i;
for ( i =0; i< len ; i++) for (i = 0; i < len ; i++)
dest[i] = rev_byte(src[i]); dest[i] = rev_byte(src[i]);
} }
void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) {
static uint8_t cc_nr[12]; static uint8_t cc_nr[12];
opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12); opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12);
uint8_t dest [] = {0,0,0,0,0,0,0,0}; uint8_t dest [] = {0, 0, 0, 0, 0, 0, 0, 0};
opt_MAC(div_key_p, cc_nr, dest); opt_MAC(div_key_p, cc_nr, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest, 4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }
void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
static uint8_t cc_nr[8+4+4]; static uint8_t cc_nr[8 + 4 + 4];
opt_reverse_arraybytecpy(cc_nr, cc_p, 12); opt_reverse_arraybytecpy(cc_nr, cc_p, 12);
State _init = { State _init = {
((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l
@ -218,10 +215,10 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) {
0xE012 // t 0xE012 // t
}; };
opt_suc(div_key_p, &_init, cc_nr, 12, true); opt_suc(div_key_p, &_init, cc_nr, 12, true);
uint8_t dest [] = {0,0,0,0}; uint8_t dest [] = {0, 0, 0, 0};
opt_output(div_key_p, &_init, dest); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }
@ -254,14 +251,14 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) {
* @param mac - where to store the MAC * @param mac - where to store the MAC
* @param div_key_p - the key to use * @param div_key_p - the key to use
*/ */
void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p) { void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p) {
static uint8_t _nr[4]; static uint8_t _nr[4];
opt_reverse_arraybytecpy(_nr, nr, 4); opt_reverse_arraybytecpy(_nr, nr, 4);
opt_suc(div_key_p, &_init,_nr, 4, true); opt_suc(div_key_p, &_init, _nr, 4, true);
uint8_t dest [] = {0,0,0,0}; uint8_t dest [] = {0, 0, 0, 0};
opt_output(div_key_p, &_init, dest); opt_output(div_key_p, &_init, dest);
//The output MAC must also be reversed //The output MAC must also be reversed
opt_reverse_arraybytecpy(mac, dest,4); opt_reverse_arraybytecpy(mac, dest, 4);
return; return;
} }

View file

@ -46,6 +46,6 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p);
* @param mac - where to store the MAC * @param mac - where to store the MAC
* @param div_key_p - the key to use * @param div_key_p - the key to use
*/ */
void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p); void opt_doTagMAC_2(State _init, uint8_t *nr, uint8_t mac[4], const uint8_t *div_key_p);
#endif // OPTIMIZED_CIPHER_H #endif // OPTIMIZED_CIPHER_H

View file

@ -3,47 +3,39 @@
#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();
int GraphTraceLen = BigBuf_max_traceLen(); int GraphTraceLen = BigBuf_max_traceLen();
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) {
if( !(dest[i] > dest[i-1]) && dest[i] > lmax) if (!(dest[i] > dest[i - 1]) && dest[i] > lmax)
break; break;
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;
i++; i++;
} }
@ -55,67 +47,61 @@ 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;
// Switch depending on lc length: // Switch depending on lc length:
// Tolerance is 1/8 of clock rate (arbitrary) // Tolerance is 1/8 of clock rate (arbitrary)
if (ABS(lc-clock/4) < tolerance) { if (ABS(lc - clock / 4) < tolerance) {
// 16T0 // 16T0
if((i - pmc) == lc) { /* 16T0 was previous one */ if ((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */ /* It's a PMC ! */
i += (128+127+16+32+33+16)-1; i += (128 + 127 + 16 + 32 + 33 + 16) - 1;
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) {
// 32TO // 32TO
if((i - pmc) == lc) { /* 16T0 was previous one */ if ((i - pmc) == lc) { /* 16T0 was previous one */
/* It's a PMC ! */ /* It's a PMC ! */
i += (128+127+16+32+33)-1; i += (128 + 127 + 16 + 32 + 33) - 1;
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] =
64*bits[j*8+6]+ 128 * bits[j * 8 + 7] +
32*bits[j*8+5]+ 64 * bits[j * 8 + 6] +
16*bits[j*8+4]+ 32 * bits[j * 8 + 5] +
8*bits[j*8+3]+ 16 * bits[j * 8 + 4] +
4*bits[j*8+2]+ 8 * bits[j * 8 + 3] +
2*bits[j*8+1]+ 4 * bits[j * 8 + 2] +
bits[j*8]; 2 * bits[j * 8 + 1] +
bits[j * 8]
;
} }
num_blocks++; num_blocks++;
} }
@ -123,273 +109,303 @@ int DemodPCF7931(uint8_t **outBlocks) {
block_done = 0; block_done = 0;
half_switch = 0; half_switch = 0;
} }
if(i < GraphTraceLen) if (i < GraphTraceLen)
dir =(dest[i-1] > dest[i]) ? 0 : 1; dir = (dest[i - 1] > dest[i]) ? 0 : 1;
} }
if(bitidx==255) if (bitidx == 255)
bitidx=0; bitidx = 0;
warnings = 0; warnings = 0;
if(num_blocks == 4) break; if (num_blocks == 4) break;
} }
memcpy(outBlocks, blocks, 16*num_blocks); memcpy(outBlocks, blocks, 16 * num_blocks);
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);
if(!n) memset(tmp_blocks, 0, 4 * 16 * sizeof(uint8_t));
error++; n = DemodPCF7931((uint8_t **)tmp_blocks);
if(error==10 && num_blocks == 0) { if (!n)
++errors;
// 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()) {
end: Dbprintf("Button pressed, stopping.");
goto end;
}
} while (found_blocks != max_blocks);
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);
AddPatternPCF7931(8192 / 2 * T0_PCF + 319 * T0_PCF + 70, 3 * T0_PCF, 29 * 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);
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
{ ++parity;
if (address&(1<<u)) { // bit 1
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);
} }
} }
//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
* @param tab : array of the data frame * @param tab : array of the data frame
*/ */
void SendCmdPCF7931(uint32_t * tab){ void SendCmdPCF7931(uint32_t *tab) {
uint16_t u=0, tempo=0; uint16_t u = 0, tempo = 0;
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 is 0
} else { //bit à 0 if (AddBitPCF7931(0, tab, l, p) == 1) return 1;
if (AddBitPCF7931(0, tab, l, p)==1) return 1;
} }
} }
return 0; return 0;
} }
@ -458,30 +473,30 @@ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){
* @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 AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){ bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p) {
uint8_t u = 0; uint8_t u = 0;
//we put the cursor at the last value of the array //we put the cursor at the last value of the array
for ( u = 0; tab[u] != 0; u += 3 ) { } for (u = 0; tab[u] != 0; u += 3) { }
if ( b == 1 ) { //add a bit 1 if (b == 1) { //add a bit 1
if ( u == 0 ) if (u == 0)
tab[u] = 34 * T0_PCF + p; tab[u] = 34 * T0_PCF + p;
else else
tab[u] = 34 * T0_PCF + tab[u-1] + p; tab[u] = 34 * T0_PCF + tab[u - 1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l; tab[u + 1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p; tab[u + 2] = 88 * T0_PCF + tab[u + 1] - l - p;
return 0; return 0;
} else { //add a bit 0 } else { //add a bit 0
if ( u == 0 ) if (u == 0)
tab[u] = 98 * T0_PCF + p; tab[u] = 98 * T0_PCF + p;
else else
tab[u] = 98 * T0_PCF + tab[u-1] + p; tab[u] = 98 * T0_PCF + tab[u - 1] + p;
tab[u+1] = 6 * T0_PCF + tab[u] + l; tab[u + 1] = 6 * T0_PCF + tab[u] + l;
tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p; tab[u + 2] = 24 * T0_PCF + tab[u + 1] - l - p;
return 0; return 0;
} }
return 1; return 1;
@ -493,13 +508,13 @@ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){
* @param c : delay of the last high pulse * @param c : delay of the last high pulse
* @param tab : array of the data frame * @param tab : array of the data frame
*/ */
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab) {
uint32_t u = 0; uint32_t u = 0;
for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array for (u = 0; tab[u] != 0; u += 3) {} //we put the cursor at the last value of the array
tab[u] = (u == 0) ? a : a + tab[u-1]; tab[u] = (u == 0) ? a : a + tab[u - 1];
tab[u+1] = b + tab[u]; tab[u + 1] = b + tab[u];
tab[u+2] = c + tab[u+1]; tab[u + 2] = c + tab[u + 1];
return 0; return 0;
} }

View file

@ -7,14 +7,14 @@
#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);
bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p); bool AddBitPCF7931(bool b, uint32_t *tab, int32_t l, int32_t p);
bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab); bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t *tab);
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); 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);
#endif #endif

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;
@ -128,16 +124,28 @@ kvsprintf(char const *fmt, void *arg, int radix, va_list ap)
for (;;) { for (;;) {
padc = ' '; padc = ' ';
width = 0; width = 0;
while ((ch = (u_char)*fmt++) != '%' || stop) { while ((ch = (u_char) * fmt++) != '%' || stop) {
PCHAR(ch); PCHAR(ch);
if (ch == '\0') if (ch == '\0')
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;
@ -213,12 +228,12 @@ reswitch: switch (ch = (u_char)*fmt++) {
p = va_arg(ap, char *); p = va_arg(ap, char *);
if (!width) if (!width)
width = 16; width = 16;
while(width--) { while (width--) {
PCHAR(hex2ascii(*up >> 4)); PCHAR(hex2ascii(*up >> 4));
PCHAR(hex2ascii(*up & 0x0f)); PCHAR(hex2ascii(*up & 0x0f));
up++; up++;
if (width) if (width)
for (q=p;*q;q++) for (q = p; *q; q++)
PCHAR(*q); PCHAR(*q);
} }
break; break;
@ -282,7 +297,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
if (p == NULL) if (p == NULL)
p = "(null)"; p = "(null)";
if (!dot) if (!dot)
n = strlen (p); n = strlen(p);
else else
for (n = 0; n < dwidth && p[n]; n++) for (n = 0; n < dwidth && p[n]; n++)
continue; continue;
@ -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,22 +21,19 @@ 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;
next_free_memory += items*size; next_free_memory += items * 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;
@ -71,7 +69,7 @@ void __attribute__((section(".startos"))) Vector(void)
/* Set up (that is: clear) BSS. */ /* Set up (that is: clear) BSS. */
dst = &__bss_start__; dst = &__bss_start__;
end = &__bss_end__; end = &__bss_end__;
while(dst < end) *dst++ = 0; while (dst < end) *dst++ = 0;
// Set up data segment: Copy from flash to ram // Set up data segment: Copy from flash to ram
// src = &__data_src_start__; // src = &__data_src_start__;

View file

@ -9,11 +9,10 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
#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) {
*d = *s; *d = *s;
d++; d++;
s++; s++;
@ -21,23 +20,21 @@ 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;
d++; d++;
} }
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;
while((len--) > 0) { while ((len--) > 0) {
if(*a != *b) { if (*a != *b) {
return *a - *b; return *a - *b;
} }
a++; a++;
@ -46,23 +43,19 @@ int memcmp(const void *av, const void *bv, int len)
return 0; return 0;
} }
void memxor(uint8_t * dest, uint8_t * src, size_t len) { void memxor(uint8_t *dest, uint8_t *src, size_t len) {
for( ; len > 0; len--,dest++,src++) for (; len > 0; len--, dest++, src++)
*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

@ -18,7 +18,7 @@ int strlen(const char *str);
void *memcpy(void *dest, const void *src, int len); void *memcpy(void *dest, const void *src, int len);
void *memset(void *dest, int c, int len); void *memset(void *dest, int c, int len);
int memcmp(const void *av, const void *bv, int len); int memcmp(const void *av, const void *bv, int len);
void memxor(uint8_t * dest, uint8_t * src, size_t len); void memxor(uint8_t *dest, uint8_t *src, size_t len);
char *strncat(char *dest, const char *src, unsigned int n); char *strncat(char *dest, const char *src, unsigned int n);
char *strcat(char *dest, const char *src); char *strcat(char *dest, const char *src);
void strreverse(char s[]); void strreverse(char s[]);

View file

@ -24,7 +24,7 @@ void SpinDelayUs(int us) {
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;
if (now == (uint16_t)(start + ticks)) if (now == (uint16_t)(start + ticks))
return; return;
@ -35,7 +35,7 @@ void SpinDelayUs(int us) {
void SpinDelay(int ms) { void SpinDelay(int ms) {
// convert to uS and call microsecond delay function // convert to uS and call microsecond delay function
SpinDelayUs(ms*1000); SpinDelayUs(ms * 1000);
} }
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
// timer lib // timer lib
@ -51,17 +51,24 @@ void StartTickCount(void) {
// We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register.
uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency
// set RealTimeCounter divider to count at 1kHz: // set RealTimeCounter divider to count at 1kHz:
AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf / 2)) / mainf);
// note: worst case precision is approx 2.5% // note: worst case precision is approx 2.5%
} }
/* /*
* Get the current count. * Get the current count.
*/ */
uint32_t RAMFUNC GetTickCount(void){ 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
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
@ -88,7 +95,7 @@ void StartCountUS(void) {
while (AT91C_BASE_TC1->TC_CV > 0); while (AT91C_BASE_TC1->TC_CV > 0);
} }
uint32_t RAMFUNC GetCountUS(void){ uint32_t RAMFUNC GetCountUS(void) {
//return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10); //return (AT91C_BASE_TC1->TC_CV * 0x8000) + ((AT91C_BASE_TC0->TC_CV / 15) * 10);
// By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548 // By suggestion from PwPiwi, http://www.proxmark.org/forum/viewtopic.php?pid=17548#p17548
return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3; return ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3;
@ -138,9 +145,9 @@ void StartCountSspClk(void) {
// synchronize the counter with the ssp_frame signal. // synchronize the counter with the ssp_frame signal.
// Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame) while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame)
while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low
while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high
// note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame
// it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge
@ -172,7 +179,7 @@ uint32_t RAMFUNC GetCountSspClk(void) {
// Timer for bitbanging, or LF stuff when you need a very precis timer // Timer for bitbanging, or LF stuff when you need a very precis timer
// 1us = 1.5ticks // 1us = 1.5ticks
// ------------------------------------------------------------------------- // -------------------------------------------------------------------------
void StartTicks(void){ void StartTicks(void) {
// initialization of the timer // initialization of the timer
AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1);
AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE;
@ -211,30 +218,30 @@ uint32_t GetTicks(void) {
do { do {
hi = AT91C_BASE_TC1->TC_CV; hi = AT91C_BASE_TC1->TC_CV;
lo = AT91C_BASE_TC0->TC_CV; lo = AT91C_BASE_TC0->TC_CV;
} while(hi != AT91C_BASE_TC1->TC_CV); } while (hi != AT91C_BASE_TC1->TC_CV);
return (hi << 16) | lo; return (hi << 16) | lo;
} }
// Wait - Spindelay in ticks. // Wait - Spindelay in ticks.
// if called with a high number, this will trigger the WDT... // if called with a high number, this will trigger the WDT...
void WaitTicks(uint32_t ticks){ void WaitTicks(uint32_t ticks) {
if ( ticks == 0 ) return; if (ticks == 0) return;
ticks += GetTicks(); ticks += GetTicks();
while (GetTicks() < ticks); while (GetTicks() < ticks);
} }
// Wait / Spindelay in us (microseconds) // Wait / Spindelay in us (microseconds)
// 1us = 1.5ticks. // 1us = 1.5ticks.
void WaitUS(uint16_t us){ void WaitUS(uint16_t us) {
WaitTicks( (uint32_t)us * 3/2 ); WaitTicks((uint32_t)us * 3 / 2);
} }
void WaitMS(uint16_t ms){ void WaitMS(uint16_t ms) {
WaitTicks( (uint32_t)ms * 1500 ); WaitTicks((uint32_t)ms * 1500);
} }
// stop clock // stop clock
void StopTicks(void){ void StopTicks(void) {
AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS;
AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS;
} }

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

@ -10,112 +10,66 @@
#include "util.h" #include "util.h"
size_t nbytes(size_t nbits) { 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();
@ -263,9 +273,9 @@ int BUTTON_HELD(int ms) {
* prefix in dst. * prefix in dst.
*/ */
void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) { void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) {
struct version_information *v = (struct version_information*)version_information; struct version_information *v = (struct version_information *)version_information;
dst[0] = 0; dst[0] = 0;
strncat(dst, prefix, len-1); strncat(dst, prefix, len - 1);
if (v->magic != VERSION_INFORMATION_MAGIC) { if (v->magic != VERSION_INFORMATION_MAGIC) {
strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1); strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1);
return; return;
@ -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) {
@ -32,12 +59,12 @@ static void ConfigClocks(void) {
// enable the clock to the following peripherals // enable the clock to the following peripherals
AT91C_BASE_PMC->PMC_PCER = AT91C_BASE_PMC->PMC_PCER =
(1<<AT91C_ID_PIOA) | (1 << AT91C_ID_PIOA) |
(1<<AT91C_ID_ADC) | (1 << AT91C_ID_ADC) |
(1<<AT91C_ID_SPI) | (1 << AT91C_ID_SPI) |
(1<<AT91C_ID_SSC) | (1 << AT91C_ID_SSC) |
(1<<AT91C_ID_PWMC) | (1 << AT91C_ID_PWMC) |
(1<<AT91C_ID_UDP); (1 << AT91C_ID_UDP);
// worst case scenario, with MAINCK = 16Mhz xtal, startup delay is 1.4ms // worst case scenario, with MAINCK = 16Mhz xtal, startup delay is 1.4ms
// if SLCK slow clock runs at its worst case (max) frequency of 42khz // if SLCK slow clock runs at its worst case (max) frequency of 42khz
@ -49,7 +76,7 @@ static void ConfigClocks(void) {
PMC_MAIN_OSC_STARTUP_DELAY(8); PMC_MAIN_OSC_STARTUP_DELAY(8);
// wait for main oscillator to stabilize // wait for main oscillator to stabilize
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS) ) {}; while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS)) {};
// PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00 // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00
// PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10
@ -63,7 +90,7 @@ static void ConfigClocks(void) {
PMC_PLL_USB_DIVISOR(1); PMC_PLL_USB_DIVISOR(1);
// wait for PLL to lock // wait for PLL to lock
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) ) {}; while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK)) {};
// we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz
// datasheet recommends that this register is programmed in two operations // datasheet recommends that this register is programmed in two operations
@ -71,62 +98,63 @@ static void ConfigClocks(void) {
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2;
// wait for main clock ready signal // wait for main clock ready signal
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
// set the source to PLL // set the source to PLL
AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK; AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK;
// wait for main clock ready signal // wait for main clock ready signal
while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; while (!(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY)) {};
} }
static void Fatal(void) { static void Fatal(void) {
for(;;) {}; for (;;) {};
} }
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];
switch(c->cmd) { switch (c->cmd) {
case CMD_DEVICE_INFO: { case CMD_DEVICE_INFO: {
dont_ack = 1; dont_ack = 1;
arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM |
DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH;
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);
for ( int j=0; j<2; j++) { for (int j = 0; j < 2; j++) {
for(i = 0+(64*j); i < 64+(64*j); i++) { for (i = 0 + (64 * j); i < 64 + (64 * j); i++) {
flash_mem[i] = c->d.asDwords[i]; flash_mem[i] = c->d.asDwords[i];
} }
uint32_t flash_address = arg0 + (0x100*j); uint32_t flash_address = arg0 + (0x100 * j);
/* Check that the address that we are supposed to write to is within our allowed region */ /* Check that the address that we are supposed to write to is within our allowed region */
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 */
@ -137,18 +165,20 @@ void UsbPacketReceived(uint8_t *packet, int len) {
// Wait until flashing of page finishes // Wait until flashing of page finishes
uint32_t sr; uint32_t sr;
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)
@ -166,55 +196,63 @@ void UsbPacketReceived(uint8_t *packet, int len) {
/* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected
* bootrom area. In any case they must be within the flash area. * bootrom area. In any case they must be within the flash area.
*/ */
if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) && if ((bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) &&
(cmd_start >= allow_start) && (cmd_start >= allow_start) &&
(cmd_end <= allow_end) ) { (cmd_end <= allow_end)) {
start_addr = cmd_start; start_addr = cmd_start;
end_addr = cmd_end; end_addr = cmd_end;
} 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();
// wait for reset to be complete? // wait for reset to be complete?
for (volatile size_t i=0; i<0x100000; i++) {}; for (volatile size_t i = 0; i < 0x100000; i++) {};
for(;;) { for (;;) {
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;
} }
} }
} }
@ -272,8 +310,8 @@ void BootROM(void) {
AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// 9 = 256, 10+ is 512kb // 9 = 256, 10+ is 512kb
uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; uint8_t id = (*(AT91C_DBGU_CIDR) & 0xF00) >> 8;
if ( id > 9 ) if (id > 9)
AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48);
// Initialize all system clocks // Initialize all system clocks
@ -287,35 +325,33 @@ void BootROM(void) {
case AT91C_RSTC_RSTTYP_SOFTWARE: case AT91C_RSTC_RSTTYP_SOFTWARE:
case AT91C_RSTC_RSTTYP_USER: case AT91C_RSTC_RSTTYP_USER:
/* In these cases the common_area in RAM should be ok, retain it if it's there */ /* In these cases the common_area in RAM should be ok, retain it if it's there */
if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) if (common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1)
common_area_present = 1; common_area_present = 1;
break; break;
default: /* Otherwise, initialize it from scratch */ default: /* Otherwise, initialize it from scratch */
break; break;
} }
if (!common_area_present){ if (!common_area_present) {
/* Common area not ok, initialize it */ /* Common area not ok, initialize it */
int i; int i;
/* Makeshift memset, no need to drag util.c into this */ /* Makeshift memset, no need to drag util.c into this */
for(i=0; i<sizeof(common_area); i++) for (i = 0; i < sizeof(common_area); i++)
((char*)&common_area)[i] = 0; ((char *)&common_area)[i] = 0;
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);
}

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