Commit Graph
144 Commits
Author SHA1 Message Date
iceman1001andClaude Opus 5 54e004e252 hf mfdes: add NORTIC travel card parser
NORTIC (Norwegian Ticketing Interoperable Concept) is the Norwegian
national public transport card, on DESFire since 2008 and specified by
Statens vegvesen, now Jernbanedirektoratet, in Handbok V821.

Decodes the card issuer header, file 0C of AID 578000. That file is
free to read, so the parser produces output on any Norwegian card
without key material: country code, format, choice bitmap, card serial
number, validity end date, application owner company, retailer
organisation and card key version.

The transport application, AID 578001, is listed by file with its role
and the key it needs, and any file that was read is dumped as hex. Its
field layouts are in Handbok V821 Del 18, which has no download link,
and every file needs read key 7, which is not public. Nothing there is
guessed at.

NORTIC is EN 1545 and packs fields most significant bit first, which is
the opposite of the RKF Type CL-1 layout in parserkf.c where RKF-0022
7.4.1 numbers bits from the least significant end. Reading a NORTIC
header the RKF way gives country code 144 instead of 578, so the self
test asserts that as a negative control.

Verified field by field against the published card issuer header, every
field matching its documented value, including the validity date 6938
decoding to 2015-12-31. 'hf mfdes view --selftest' runs the checks,
including a round trip through an encoder.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 11:19:24 +02:00
iceman1001andClaude Opus 5 28d49510e2 hf mf: add RKF travel card parser
The RKF travel card (Resekortsföreningen i Norden) is the Nordic public
transport card, specified 2001-2002 on MIFARE Classic and deployed by
Västtrafik, SL Stockholm, Länstrafiken and the Danish Rejsekort.

Decodes the card issuer and support layers (CMI, TCCI, TCAS, TCDI) and
every application object the specification pins down: TCPU purse, TCEL
event log, TCDB, TCCP, TCST, and TCTI/TCCO through an identifier chain
walker covering all 18 data element groups. AID owners are named from
RKF-0019.

Three things the specification does not state, determined from 21 cards:

  - RKF-0022 7.7.1 calls the block checksum 'standard CRC-8' without
    naming the parameters. It is CRC-8/MIFARE-MAD, poly 0x1D init 0xC7,
    which the tree already ships as CRC8Mad().

  - The MAC trio is the final 24 bits of a MACed object. The RKF-0023
    tables list Free (bits) as a trailing summary row, which reads as if
    the authenticator follows a gap after the key identifier; it does
    not. Measured on the fact that MACAlgorithmIdentifier must be 0:
    TCST 42/42 against 15/42, TCCP 20/20 against 13/20.

  - TCPU version 4 drops EndDate and moves Value to bit 16.

Cards reporting a version other than 2 are flagged, and a MAC algorithm
the specification does not define is reported as a layout failure rather
than printed as data.

MAC values are not verified. The master key is in RKF-0018, which was
never published. des_mac() is added to libpcrypto for when that changes,
with the FIPS 113 worked example as its test.

Verified against a Danish Rejsekort whose provenance notes give the
purchase timestamp, card number and balance; the parser reproduces all
three. 48 self test checks on 'hf mf view --selftest', no false
positives across 460 local dumps.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-22 11:14:44 +02:00
Philippe Teuwen e2acee8a85 Revert "Release v4.23346 - Frosty Lemon"
This reverts commit dc0110c29d.
2026-09-18 00:22:18 +02:00
Philippe Teuwen dc0110c29d Release v4.23346 - Frosty Lemon 2026-09-18 00:22:18 +02:00
iceman1001andClaude Opus 5 e648438306 hf 14b view: decode MyKey / COGES keys on SRIX4K
The SRIX4K block scrambler in cmdhf14b.c was a three entry lookup table with
its callers commented out, so `hf 14b valid` printed hard coded values and
nothing ever decoded. The scrambler is a 4x4 transpose of the block read as
sixteen crumbs. A transpose is its own inverse and it reproduces all three
entries of the old table, so the stub is replaced by a working parser.

client/src/parsers/parsemykey.c reads the application off a dump: key id,
production date, operations counter, vendor code, lock id, current and
previous credit, and the eight slot transaction ring. Every block carries a
checksum in its top byte and the parser reports how many hold up, which
catches a wrong UID or a torn write. The credit blocks are XORed with a
session key derived from the UID, the vendor code and the count down counter
in block 6, so the file name has to carry the UID.

`hf 14b valid` is removed. Checking that the maths holds is now
`hf 14b view --selftest`, following `hf mf view --selftest`, and it runs
against traces/hf-14b-D0021F673CB26556-dump.json, a dump of a real reset key.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-16 10:58:57 +02:00
iceman1001 c0a109dbc6 text 2026-09-16 02:39:42 +02:00
iceman1001andClaude Opus 5 (1M context) ee2d55fafb hf mfdes: put a DESFire card image in emulator memory
Adds the on-device card image a DESFire simulation will read, the client
side that packs a dump into it, and eload / esave / eview.

The layout is in include/desfire_em.h. Tables grow up from the header,
file data grows down from the end, and an allocation only has to leave
the two frontiers apart -- so a three-file card spends a few hundred
bytes rather than a worst case, and the space between them is what the
card has left. The PICC is application 000000 and uses the same struct
as any other application, so key settings and keys are always stated
against an AID. Delete sets a tombstone rather than compacting, which is
not a shortcut: a real card does not reclaim on delete either, measured
as 2080 bytes free with zero applications before an experiment and 2560
after FormatPICC.

Two size limits, and a reader only ever sees the first. cardsize is what
the emulated card claims to hold, so GetFreeMem answers from that and
CreateFile will refuse with OUT_OF_EEPROM when it runs out. Without it a
card impersonating a 2K part would report 7434 bytes free, which no 2K
part does. The image size is what emulator memory physically holds, is
the harder limit, and is never visible.

cardsize is anchored to the free memory the real card reported when the
dump was taken -- observed free plus what we reserve for the same content
-- so the emulation answers what its original answered. That is also a
check on the reservation rule rather than only a convenience: for the
bench card it computed 576 bytes spent, and 1984 + 576 is 2560, exactly
what that card reports when formatted.

Reservation follows what CommitTransaction covers. Backup data, value and
record files each get a shadow region because writes to them are staged
until commit; a standard data file writes through and does not. Sizes
round to a 32 byte granule, which is the granule a real card allocates in.
It deliberately does not reproduce NXP's allocator -- that is
undocumented and does not fit a simple model, a declared 1024 byte record
file costs 1088 on silicon -- so what matters is that the figure is
self-consistent and shrinks as the reader writes.

No new device command. Emulator memory is one shared region, so
CMD_HF_MIFARE_EML_MEMSET and BIG_BUF_EML already reach it, and both
inherit the bounds checking those paths gained earlier.

Verified with the client only, no simulation yet: packing a dump taken
from a DESFire EV2 and walking it back reproduces every field including
file contents byte for byte, the same round trip through the device via
eload and esave is identical, and an image too large is refused by name
rather than truncated -- 'Out of emulator memory laying out AID 112233
file 00: needs 4066 more bytes'.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-14 19:48:45 +02:00
iceman1001 b82f603622 urmet parsing 2026-09-14 12:11:42 +02:00
iceman1001 7142ddc9bd added hexact parser 2026-09-13 12:55:43 +02:00
iceman1001andClaude Opus 5 (1M context) a9105c5089 hf mf: split HID and VIGIK decoding into client/src/parsers/
The shared viewer had the VIGIK sector assembly inlined, and the HID PACS
decode sat in hf mf mad's file branch where hf mf view and hf mf dump --ns
could not reach it. Neither scheme had a home of its own.

Give each one a parser next to parsehrt.c, same shape as that one - an
is_valid_x_card() detector and an x_parser_parse() that prints:

  parsers/parsehid.c    MAD aid 0x484d, PACS sector, Wiegand decode
  parsers/parsevigik.c  MAD aid 0x4910/0x4916, sector assembly

parsevigik.c also takes vigik_get_service(), vigik_verify() and
vigik_annotate() out of mifare/mifarehost.c, 306 lines that were VIGIK only
with a single caller.

mf_view_dump() is now two detector calls, so hf mf view -f and hf mf dump --ns
both decode a HID credential off a live card for the first time, and adding a
scheme is a new file plus two lines. hf mf mad -f keeps its HID decode through
the same parser.

The sector copy in the VIGIK path gains a bounds check; a MAD entry pointing
past the end of a short dump used to read past the buffer.

All three source lists get the new files: client/Makefile,
client/CMakeLists.txt and client/experimental_lib/CMakeLists.txt. The library
one matters because vigik_annotate() moved; without it anything linking
libpm3rrg_rdv4 loses the symbol.

hf mf mad against a card still cannot decode PACS. It authenticates with the
MAD key alone and never reads the application sector, so it has no credential
bytes to work with - unchanged here.

Co-Authored-By: Claude Opus 5 (1M context)
2026-09-13 08:37:17 +02:00
Niel Nielsen 028aae180d Add cmdbwm.c to CMakeLists.txt
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-09-12 17:07:50 +02:00
Julian Isaac 71ca59a8ad Moved the new tool to tools/kgh and renamed it legic_kgh_tool. Added some validation so we don't return random bytes from non-kgh cards. Applied some styling to the new code. Added GPL header to new source file. Cleaned up the static build. 2026-09-04 23:14:22 +02:00
Julian Isaac 1d5d09b073 Merge branch 'master' into feature/add_kgh_tools 2026-09-04 22:23:13 +02:00
YoungJules 08cf2e430e Added possibilty to write a found stamp to a binary file. 2026-08-31 13:14:35 +02:00
MsprgandClaude Fable 5 d852118de5 client: build the tab completion vocabulary at runtime from the command tree
Tab completion used a generated table (pm3line_vocabulary.h, refreshed by
hand via `make commands`) that drifted from the real command tables: new
commands were missing (e.g. `hw bwm*`), removed ones lingered, and the
"offline" flag depended on the platform of whoever regenerated it
(IfPm5() returns true offline on PM5 builds).

Build the vocabulary at startup instead:

- cmdparser: add walkCommandsRecursive(), a tree walk using a fourth
  internal sentinel (XX_internal_command_walk_XX) next to the dump ones.
  It hands each leaf to a visitor as its command_t chain (ancestors +
  leaf). A dispatch counter detects entries shown like a category but
  with their own parser (reveng) and reports them as leaves.
- pm3line_vocabulary: dynamic vocabulary holding the IsAvailable()
  predicates of every command and its ancestor categories, so completion
  applies exactly the rule CmdsHelp() uses, live, for both offline and
  connected devices. Script entries ("script run <relpath>") come from
  the same directories `script list` scans, sorted, including
  subdirectories with the path `script run` needs.
- pm3line: readline and linenoise completers consume the live vocabulary.
  The walk runs with output disabled so category handlers stay silent.
- Drop pm3_help2list.py and the header regeneration from `make commands`.

Behaviour change: entries whose category is hidden by `help` (e.g. `mem`,
`usart` offline) are no longer offered, matching `help`; when connected,
commands the device does not support are no longer offered either.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-28 14:29:04 +02:00
Niel Nielsen 3156f0bfd7 Add ble_posix.c to CMakeLists.txt
Signed-off-by: Niel Nielsen <nieldk@gmail.com>
2026-08-26 16:07:37 +02:00
kormax f3bca6c291 Determine IDi and PMi in 'hf felica info' for cards with known keys 2026-08-26 11:34:57 +03:00
YoungJules 9def79f8be Fix extra segments identification if first segment also the last 2026-08-25 17:24:09 +02:00
iceman1001 26c23f6808 fix missing files 2026-08-21 23:15:01 +02:00
Cole Munz 0b40585124 Set the stringop-overflow flags before add_subdirectory(deps)
With the linker pin in place the proxspace job gets past the bootrom and
dies later instead, in the cmake build:

  client/deps/jansson/load.c:193:35: error: writing 1 byte into a region
  of size 0 [-Werror=stringop-overflow=]

client/CMakeLists.txt already turns that false positive off for GCC 10
and newer, but it does it at line 876 while add_subdirectory(deps) runs
at line 295. CMake copies the calling scope into a subdirectory at the
add_subdirectory call, so anything set afterwards never reaches the
bundled deps, and jansson is built without the suppression that the rest
of the client gets.

Move the block above the add_subdirectory call in both client and
experimental_lib. Checked by configuring before and after: 0 of 17 deps
targets carried -Wno-error=stringop-overflow in their flags.make before,
17 of 17 after.

ubuntu-cmake and macos-cmake stay green either way; their compilers do
not emit this particular false positive, which is why the gap went
unnoticed while the bootrom link was failing first.

Signed-off-by: Cole Munz <Munzzyy1@proton.me>
2026-08-19 13:18:46 +02:00
YoungJules 51752c3e1d Updated documentation to add usage, how to build in Linux as well as Windows (ProxSpace) 2026-08-19 12:22:30 +02:00
Philippe Teuwen a061f080ed experimental_lib: add missing cmdfpga.c 2026-08-19 12:04:32 +02:00
YoungJules 2b463e4bf9 Remove suffix from repo name in build doco 2026-08-19 11:53:06 +02:00
YoungJules e3ca960ae0 Update wording 2026-08-19 11:32:36 +02:00
YoungJules 89c23828a0 Create a small kgh_tools.exe that runs in Windows and can be used from another program to read a badge number, write a new KGH badge (given a badge number). You also have to provide a stamp (as .bin file, 4 bytes). The tool can also get a full set of info from a KGH badge in JSON form (including checking KGH crc for correctness). All based on publicly available knowledge, existing lua scripts, and careful obeservations! 2026-08-19 10:50:05 +02:00
Sanduuz 02a83c62e6 Add experimental client lib cmdlftrovan missing sources to CMakeLists 2026-07-31 12:15:35 +03:00
iceman1001 c6d01e6e72 update helptexts 2026-06-29 23:51:37 +02:00
Sanduuz e3ddd6a833 Merge branch 'RfidResearchGroup:master' into feature/hrt_parser 2026-06-24 19:14:04 +03:00
Philippe Teuwen 6550610ad0 Migrate from MINGW64 to UCRT64 as arm-none-eabi-gcc is not available anymore in MINGW64
cf https://github.com/msys2/MINGW-packages/commit/bb4125054bf0a400c77a64adb07b64658554083b
2026-06-23 11:04:34 +02:00
Sanduuz 4ff1a50288 Moved HRT parser logic under client/src/parsers + Restructured parser calling code to its own file that is hooked from hf mfdes info command 2026-06-20 23:55:55 +03:00
Sanduuz f71071eb94 Initial commit for HRT parser 2026-06-17 19:24:06 +03:00
Sanduuz 3bea6eaea7 Fail client experimental lib building at compile-time if there are undefined symbols on Linux 2026-06-12 20:31:42 +03:00
Sanduuz e83e2e58a3 Add missing files to CMakeLists for experimental client lib 2026-06-12 19:02:54 +03:00
Connor Milligan cc7b235a5b Native client support for FM11RF08S SEN recovery 2026-05-21 01:19:15 +02:00
Philippe Teuwen 729a8748d9 Fix vec dep with cmake 2026-05-19 09:36:32 +02:00
Sanduuz 2d1fbc12c0 Add prime.c containing mifare_prime_get_version_str symbol to experimental client lib CMakeLists.txt 2026-05-13 15:43:52 +03:00
kormax fa414f3b65 Implement 'hf mfd verifycert' command 2026-05-04 22:07:33 +03:00
kormax d06106b538 Add 'hf calypso info' command 2026-05-01 22:41:42 +03:00
Antiklesys 8d6e474a75 hf iclass legbrute speed improvements #1
Imported updates from legbrute hashcat modules to speed up hf iclass legbrute

1. Bitslicing — biggest win (~32×)
Kernel stores each cipher register (l, r, b, t) as 32 parallel 1-bit lanes in u32s (m64000_a3-pure.cl:147-201, bs_iclass_tick) and computes 32 MACs per tick. The CPU doMAC_brute does 1 at a time. A 64-bit bitslice port would give ~64× per core; AVX2 gets 256×. This is the single largest speedup lever.

2. Early-reject after 8 output ticks
In m64000_sxx (m64000_a3-pure.cl:534-535) the kernel breaks out as soon as the first MAC byte can't match. doMAC_brute always produces the full 32 output bits before memcmp. Comparing byte-by-byte as bits are produced saves ~3× on the output phase since 255/256 keys fail after byte 0.

3. Pre-expanded y_ccnr bit array
Kernel expands the 96 input bits into a flat array once (m64000_a3-pure.cl:239-247) and reuses it for every candidate. suc_bytes in cipher.c:181 re-does b >>= 1 shifts for every key. Pre-expanding lets the inner loop be branch-free and vectorizable.

4. Widen lanes to 256/512 via AVX2/AVX-512. The bitslice code is written against a single uint64_t lane type — swapping for __m256i/__m512i (or an abstracted bs_word_t) gives 4×/8× throughput on hosts that support it, with scalar u64 fallback on ARM/older x86. NEON gives 2× for ARM.
2026-04-15 01:09:19 +08:00
Philippe Teuwen 961e59b5d1 Revert "Release v4.21611 - BREAKMEIFYOUCAN!"
This reverts commit aaacc75e9f.
2026-04-14 10:19:30 +02:00
Philippe Teuwen aaacc75e9f Release v4.21611 - BREAKMEIFYOUCAN! 2026-04-14 10:19:30 +02:00
Philippe Teuwen d6c823bea3 fix lib cmakelist & fix cmakelist alphabetic order 2026-04-13 21:44:50 +02:00
iceman1001 c502d2d88d fix cmake 2026-04-11 08:06:48 +07:00
kormax c8a4314353 Add hf gst commands 2026-03-14 17:34:58 +02:00
pingu2211 c07d688597 Implement Gallagher MIFARE Classic card writing and update MAD sector functionality 2026-03-10 15:13:42 +11:00
Philippe Teuwen c529895e68 remove Qt support from experimental_lib 2026-03-01 00:13:48 +01:00
kormax de94afa4f6 Add 'hf aliro info' command 2026-02-27 20:26:50 +02:00
iceman1001 338ab9c81a Revert "Release v4.21128 - Permafrost"
This reverts commit b10235b03b.
2026-02-25 16:15:01 +01:00
iceman1001 b10235b03b Release v4.21128 - Permafrost 2026-02-25 16:15:01 +01:00
Sanduuz 192c5237b8 Added pla.c to experimental client lib CMakeLists 2025-12-30 22:51:19 +02:00