Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1157aee3c0 | |||
| edaaf90cbc | |||
|
|
ba072f16f6 | ||
|
|
dd0ce5caa6 | ||
|
|
987c3dab3a | ||
|
|
77db13ef90 | ||
|
|
519e475b09 | ||
|
|
fa3573cfb6 | ||
|
|
c24b6ac572 | ||
|
|
593315f7d4 | ||
|
|
9fed51206f | ||
|
|
809f3bc62c | ||
|
|
b13beeac09 | ||
|
|
9d9f01fba4 | ||
|
|
34d42e5e47 | ||
|
|
2316ad0815 | ||
|
|
0970559b97 | ||
|
|
e36025bb25 | ||
|
|
f172064f98 | ||
|
|
48156f9bf0 | ||
|
|
e2cf90202a | ||
|
|
eac78225eb | ||
|
|
51bae1e1c8 | ||
|
|
0976e6f285 | ||
|
|
eff3dc0d5f | ||
|
|
7ff1465409 | ||
|
|
c346e2af72 | ||
|
|
86caca5f6b | ||
|
|
00eae36f89 | ||
|
|
3b5be84676 | ||
|
|
f3ebde09ef | ||
|
|
b872a328e3 | ||
|
|
30ce00aa8e | ||
|
|
f3a793dc0c | ||
|
|
5d8bf95968 | ||
|
|
1eac72641c | ||
|
|
f3558144d8 | ||
|
|
f13efb0a6d | ||
|
|
a1be79d0ff | ||
|
|
b31ac50224 | ||
|
|
290a075956 | ||
|
|
2fa70fb3d3 | ||
|
|
e1a2b0225f | ||
|
|
222ba1838c | ||
|
|
fa47ca0223 | ||
|
|
9b37ccd725 | ||
|
|
e5024608f3 | ||
|
|
ba7e75cd16 | ||
|
|
0c2d2b5894 | ||
|
|
9a02d34ede | ||
|
|
6b65fb4ca2 | ||
|
|
0406f0002e | ||
|
|
b1bc800c83 | ||
|
|
166a1467c2 | ||
|
|
2b16dc7ff8 | ||
|
|
35489b09a1 | ||
|
|
ab826c9fe8 | ||
|
|
e52c737242 | ||
|
|
205050848c | ||
|
|
ed16dec250 | ||
|
|
d10f2e0bdb | ||
|
|
1c5af20e98 | ||
|
|
d65d57d06e | ||
|
|
6674459a57 | ||
|
|
c004dd2c2c | ||
|
|
051d70e2ed | ||
|
|
6048309a13 | ||
|
|
2596aeac80 | ||
|
|
10699271f6 | ||
|
|
87d6203b88 | ||
|
|
1a2ed65879 | ||
|
|
02afffce07 | ||
|
|
25e1b8a3c6 | ||
|
|
451f2fa29c | ||
|
|
bc109b9252 | ||
|
|
435de61cc5 | ||
|
|
3b02985173 | ||
|
|
262e206b0a | ||
|
|
3545975303 | ||
|
|
f4282f0f5d | ||
|
|
8962d407c0 | ||
|
|
9187b97249 | ||
|
|
b27b742472 | ||
|
|
478d3d92eb | ||
|
|
08195d70ee | ||
|
|
68b71ea26c | ||
|
|
5c62782645 | ||
|
|
ea0c8a7047 | ||
|
|
2be6d8ddef | ||
|
|
c3808a240c | ||
|
|
ece9619e6d | ||
|
|
a3ddbf6a32 | ||
|
|
55c3296983 | ||
|
|
21b58f0bf6 | ||
|
|
5e3f177ee6 | ||
|
|
367f0d050e | ||
|
|
3b2b569f0d | ||
|
|
2ff463b5c1 | ||
|
|
658d77ec0d | ||
|
|
a13df02f79 | ||
|
|
001049599f | ||
|
|
a978ac16a9 | ||
|
|
1c2ff2b263 | ||
|
|
d1c676b01d | ||
|
|
9e636c9885 | ||
|
|
ef75599d75 | ||
|
|
e076683dea | ||
|
|
4d1ce73772 | ||
|
|
dafa6e42db | ||
|
|
c973c3cd81 | ||
|
|
6a3977545e | ||
|
|
af8ec581be | ||
|
|
d4eb0e3eba | ||
|
|
0320ded902 |
23
.gitignore
vendored
Normal file
23
.gitignore
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
INSTALL
|
||||||
|
Makefile
|
||||||
|
Makefile.in
|
||||||
|
aclocal.m4
|
||||||
|
autom4te.cache/
|
||||||
|
config.h
|
||||||
|
config.h.in
|
||||||
|
config.log
|
||||||
|
config.status
|
||||||
|
configure
|
||||||
|
compile
|
||||||
|
depcomp
|
||||||
|
install-sh
|
||||||
|
missing
|
||||||
|
src/*.lo
|
||||||
|
src/*.o
|
||||||
|
src/.deps/
|
||||||
|
src/Makefile
|
||||||
|
src/Makefile.in
|
||||||
|
src/mfoc
|
||||||
|
src/mfoc.exe
|
||||||
|
stamp-h1
|
||||||
|
|
||||||
2
AUTHORS
2
AUTHORS
@ -6,4 +6,4 @@ Pavol Luptak - project leader, minor coding, testing and bugreporting
|
|||||||
= Contributors
|
= Contributors
|
||||||
|
|
||||||
Michal Boska <boska.michal@gmail.com> - porting to libnfc 1.3.3
|
Michal Boska <boska.michal@gmail.com> - porting to libnfc 1.3.3
|
||||||
Romuald Conty <romuald@libnfc.org> - porting to libnfc 1.3.9
|
Romuald Conty <romuald@libnfc.org> - porting to libnfc 1.3.9 and upper
|
||||||
|
|||||||
243
ChangeLog
243
ChangeLog
@ -0,0 +1,243 @@
|
|||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* ChangeLog: Update outdated email addresses
|
||||||
|
|
||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/crapto1.c, src/crapto1.h, src/crypto1.c, src/mfoc.c,
|
||||||
|
src/mfoc.h: Format source code with "make style"
|
||||||
|
|
||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* Makefile.am: Add "make style" directive to format source code
|
||||||
|
|
||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac, src/mfoc.c: Updates source to use libnfc 1.7.0
|
||||||
|
|
||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mifare.c, src/mifare.h, src/nfc-utils.c, src/nfc-utils.h:
|
||||||
|
Update mifare.* and nfc-utils.* from libnfc utils directory
|
||||||
|
|
||||||
|
2013-01-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* .gitignore: Ignore generated files in source repository
|
||||||
|
|
||||||
|
2012-10-14 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: Fix tolerance (-T) option (Fixes issue 102) Thanks to
|
||||||
|
fnargwibble
|
||||||
|
|
||||||
|
2012-06-03 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mifare.c: do not display an error when authentication failed
|
||||||
|
|
||||||
|
2012-06-03 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mfoc.h: use authuid instead uid name when handling
|
||||||
|
the authentication uid bytes (different from UID with 7bytes MIFARE
|
||||||
|
Classic
|
||||||
|
|
||||||
|
2012-06-03 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/crapto1.h, src/mfoc.c, src/mfoc.h, src/mifare.c,
|
||||||
|
src/mifare.h, src/nfc-utils.c, src/nfc-utils.h: some code clean up:
|
||||||
|
find . -name '*.[ch]' | xargs perl -pi -e 's/\t+$//; s/ +$//'
|
||||||
|
|
||||||
|
2012-06-02 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mifare.h: Allow to find default keys using 7bytes
|
||||||
|
UID MIFARE Classic tags
|
||||||
|
|
||||||
|
2012-06-02 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: Remove not requiered anticol and configuration, its
|
||||||
|
speed up default keys search
|
||||||
|
|
||||||
|
2012-06-02 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: Enhance default keys search result: '/', '\' and 'x'
|
||||||
|
means respectively A, B and both key(s) found.
|
||||||
|
|
||||||
|
2012-06-01 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* INSTALL, configure.ac, debian/control, src/Makefile.am,
|
||||||
|
src/crapto1.c, src/mfoc.c, src/mfoc.h, src/mifare.c: foc> source
|
||||||
|
code maintenance: - upgrade to last libnfc devel API - removes various warnings - update debian package
|
||||||
|
|
||||||
|
2012-05-28 Ludovic Rousseau <ludovic.rousseau@gmail.com>
|
||||||
|
|
||||||
|
* debian/watch: Update upstream URL Closes Issue #92
|
||||||
|
|
||||||
|
2012-05-22 Ludovic Rousseau <ludovic.rousseau@gmail.com>
|
||||||
|
|
||||||
|
* debian/control: Upgrade libnfc-dev version in Build-Depends: Closes Issue #91
|
||||||
|
|
||||||
|
2012-05-14 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* src/crapto1.h: Export lfsr_rollback_word().
|
||||||
|
|
||||||
|
2012-05-14 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mfoc.h: Drop unused argument.
|
||||||
|
|
||||||
|
2012-05-14 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mfoc.h: Fix a bunch of signed/unsigned
|
||||||
|
comparisons.
|
||||||
|
|
||||||
|
2012-05-14 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* configure.ac: Complete configure.ac.
|
||||||
|
|
||||||
|
2012-05-14 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* src/Makefile.am: Rely on variables set by the autotools.
|
||||||
|
|
||||||
|
2012-01-26 Audrey Diacre <adiacre@il4p.fr>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mfoc.h, src/mifare.c, src/mifare.h,
|
||||||
|
src/nfc-utils.c, src/nfc-utils.h: update to use libnfc's trunk
|
||||||
|
|
||||||
|
2011-10-17 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac, src/Makefile.am: compilation improvements (Thanks to
|
||||||
|
Thomas Hood)
|
||||||
|
|
||||||
|
2011-09-28 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac, src/mfoc.c, src/mifare.c: Sync w/ libnfc-1.5.1
|
||||||
|
(Fixes Issue 79)
|
||||||
|
|
||||||
|
2011-07-11 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/nfc-utils.c: sync nfc-utils.c with libnfc trunk.
|
||||||
|
|
||||||
|
2011-05-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* debian/control, debian/watch: debian: update pam_nfc, mfoc and
|
||||||
|
libfreefare packages to use dh7.
|
||||||
|
|
||||||
|
2011-05-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* INSTALL, debian/control: debian: silent lintian warning
|
||||||
|
|
||||||
|
2011-05-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: usage output is now more standard (Thanks to Thomas
|
||||||
|
Hood)
|
||||||
|
|
||||||
|
2011-05-20 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* debian/changelog, debian/control, debian/rules: debian package now
|
||||||
|
use dh_autoreconf to build against svn.
|
||||||
|
|
||||||
|
2011-05-19 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* debian/rules: in some cases ./configure file needs to be chmoded
|
||||||
|
(dpkg-source -b mfoc).
|
||||||
|
|
||||||
|
2011-05-19 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* AUTHORS, debian/changelog, debian/compat, debian/control,
|
||||||
|
debian/copyright, debian/docs, debian/manpages, debian/rules,
|
||||||
|
debian/source/format, debian/watch: import debian files (Thanks to
|
||||||
|
Thomas Hood)
|
||||||
|
|
||||||
|
2011-05-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/Makefile.am, src/mfoc.1: add manpage (Thanks to Thomas Hood)
|
||||||
|
|
||||||
|
2011-05-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: read multiple keys from command line (Thanks to Frank
|
||||||
|
Morgner) (Fixes Issue 63)
|
||||||
|
|
||||||
|
2011-05-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* ChangeLog, configure.ac: prepare 0.10.2 release
|
||||||
|
|
||||||
|
2011-05-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: improve tests made before running and show tag info
|
||||||
|
using print_nfc_iso14443a_info()
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: try to disconnect() the device on error.
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: show errors then exit on mf_configure()
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: apply a patch suggested by Valentijn Sessink. See
|
||||||
|
Issue 56.
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: minors fixes and indent.
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: show error (using nfc_perror) then exit if some nfc_*
|
||||||
|
functions failed on init.
|
||||||
|
|
||||||
|
2011-04-08 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: minor debug improvements.
|
||||||
|
|
||||||
|
2011-04-04 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac, src/mfoc.c: minor fixes/enhancements and version
|
||||||
|
bumping
|
||||||
|
|
||||||
|
2011-04-04 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c, src/mifare.c: hide authentication errors
|
||||||
|
|
||||||
|
2011-04-04 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mifare.c, src/mifare.h, src/nfc-utils.c, src/nfc-utils.h: sync
|
||||||
|
nfc-utils.h/c and mifare.c/h with libnfc's ones.
|
||||||
|
|
||||||
|
2011-02-21 Romain Tartiere <romain.tartiere@gmail.com>
|
||||||
|
|
||||||
|
* src/Makefile.am: mfox: Unbreak autotools on FreeBSD.
|
||||||
|
|
||||||
|
2011-02-02 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/mfoc.c: use strtoll() function in order to retrieve 64bits
|
||||||
|
wide value. (Fixes Issue 55)
|
||||||
|
|
||||||
|
2010-11-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac: bump package version
|
||||||
|
|
||||||
|
2010-11-18 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* src/nfc-utils.c, src/nfc-utils.h: sync nfc-utils.* from libnfc
|
||||||
|
|
||||||
|
2010-11-02 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* configure.ac, src/mfoc.c, src/mfoc.h, src/nfc-utils.c,
|
||||||
|
src/nfc-utils.h: upgrade code to work with develoment version of
|
||||||
|
libnfc (upcomming 1.4.0) Update code to match with the new API; Sync
|
||||||
|
nfc-utils.[ch] from libnfc's repo; Update ./configure to detect
|
||||||
|
libnfc 1.4.0;
|
||||||
|
|
||||||
|
2010-09-14 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* AUTHORS, Makefile.in, aclocal.m4, autogen.sh, config.h,
|
||||||
|
config.h.in, configure, configure.ac, depcomp, install-sh, missing,
|
||||||
|
src/Makefile.am, src/mfoc.c, src/mifare.c, src/mifare.h,
|
||||||
|
src/nfc-utils.c, src/nfc-utils.h: update code in order to use libnfc
|
||||||
|
1.3.9, minor clean up, and minor enhancements.
|
||||||
|
|
||||||
|
2010-09-14 Romuald Conty <romuald@libnfc.org>
|
||||||
|
|
||||||
|
* Import MFOC 0.08 from http://www.nethemba.com/mfoc.tar.bz2 on 13th
|
||||||
|
Sept 2010
|
||||||
|
|
||||||
10
Makefile.am
10
Makefile.am
@ -1,4 +1,10 @@
|
|||||||
SUBDIRS = src
|
SUBDIRS = src
|
||||||
|
|
||||||
#pkgconfigdir = $(libdir)/pkgconfig
|
style:
|
||||||
#pkgconfig_DATA = libnfc.pc
|
find . -name "*.[ch]" -exec perl -pi -e 's/[ \t]+$$//' {} \;
|
||||||
|
find . -name "*.[ch]" -exec astyle --formatted --mode=c --suffix=none \
|
||||||
|
--indent=spaces=2 --indent-switches --indent-preprocessor \
|
||||||
|
--keep-one-line-blocks --max-instatement-indent=60 \
|
||||||
|
--brackets=linux --pad-oper --unpad-paren --pad-header \
|
||||||
|
--align-pointer=name {} \;
|
||||||
|
|
||||||
|
|||||||
20
README.md
Normal file
20
README.md
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
MFOC is an open source implementation of "offline nested" attack by Nethemba.
|
||||||
|
|
||||||
|
This program allow to recover authentication keys from MIFARE Classic card.
|
||||||
|
|
||||||
|
Please note MFOC is able to recover keys from target only if it have a known key: default one (hardcoded in MFOC) or custom one (user provided using command line).
|
||||||
|
|
||||||
|
# Build from source
|
||||||
|
|
||||||
|
```
|
||||||
|
autoreconf -is
|
||||||
|
./configure
|
||||||
|
make && sudo make install
|
||||||
|
```
|
||||||
|
|
||||||
|
# Usage #
|
||||||
|
Put one MIFARE Classic tag that you want keys recovering;
|
||||||
|
Lauching mfoc, you will need to pass options, see
|
||||||
|
```
|
||||||
|
mfoc -h
|
||||||
|
```
|
||||||
21
configure.ac
21
configure.ac
@ -1,32 +1,41 @@
|
|||||||
AC_INIT([mfoc], [0.09], [mifare@nethemba.com])
|
AC_INIT([mfoc],[0.10.7],[mifare@nethemba.com])
|
||||||
|
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
|
|
||||||
AC_PROG_CC
|
|
||||||
|
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
AC_CONFIG_SRCDIR([src/mfoc.c])
|
AC_CONFIG_SRCDIR([src/mfoc.c])
|
||||||
|
|
||||||
AM_INIT_AUTOMAKE
|
AM_INIT_AUTOMAKE(dist-bzip2 no-dist-gzip)
|
||||||
|
|
||||||
|
AC_PROG_CC
|
||||||
|
|
||||||
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
|
||||||
|
|
||||||
# Checks for pkg-config modules.
|
# Checks for pkg-config modules.
|
||||||
LIBNFC_REQUIRED_VERSION=1.3.9
|
LIBNFC_REQUIRED_VERSION=1.7.0
|
||||||
PKG_CHECK_MODULES([LIBNFC], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])])
|
PKG_CHECK_MODULES([libnfc], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])])
|
||||||
|
|
||||||
PKG_CONFIG_REQUIRES="libnfc"
|
PKG_CONFIG_REQUIRES="libnfc"
|
||||||
AC_SUBST([PKG_CONFIG_REQUIRES])
|
AC_SUBST([PKG_CONFIG_REQUIRES])
|
||||||
|
|
||||||
|
AC_C_INLINE
|
||||||
|
|
||||||
# Checks for typedefs, structures, and compiler characteristics.
|
# Checks for typedefs, structures, and compiler characteristics.
|
||||||
AC_HEADER_STDBOOL
|
AC_HEADER_STDBOOL
|
||||||
|
AC_TYPE_SIZE_T
|
||||||
|
AC_TYPE_UINT8_T
|
||||||
|
AC_TYPE_UINT16_T
|
||||||
AC_TYPE_UINT32_T
|
AC_TYPE_UINT32_T
|
||||||
AC_TYPE_UINT64_T
|
AC_TYPE_UINT64_T
|
||||||
|
|
||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_FUNC_MALLOC
|
AC_FUNC_MALLOC
|
||||||
AC_FUNC_REALLOC
|
AC_FUNC_REALLOC
|
||||||
|
AC_CHECK_FUNCS([memset])
|
||||||
|
|
||||||
|
# C99
|
||||||
|
CFLAGS="$CFLAGS -std=c99"
|
||||||
|
|
||||||
AC_CONFIG_FILES([Makefile
|
AC_CONFIG_FILES([Makefile
|
||||||
src/Makefile])
|
src/Makefile])
|
||||||
|
|||||||
67
debian/changelog
vendored
Normal file
67
debian/changelog
vendored
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
mfoc (0.10.7+git20180724-1) unstable; urgency=medium
|
||||||
|
|
||||||
|
* New upstream version 0.10.7+git20180724
|
||||||
|
|
||||||
|
-- Samuel Henrique <samueloph@debian.org> Tue, 24 Jul 2018 01:19:50 -0300
|
||||||
|
|
||||||
|
mfoc (0.10.7+git20150512-0kali1) kali; urgency=medium
|
||||||
|
|
||||||
|
* Import upstream (Closes: 0002240)
|
||||||
|
* Update debian files: watch, copyright
|
||||||
|
* Use debhelper 9
|
||||||
|
|
||||||
|
-- Sophie Brun <sophie@freexian.com> Tue, 12 May 2015 12:05:24 +0200
|
||||||
|
|
||||||
|
mfoc (0.10.7-0kali2) kali; urgency=low
|
||||||
|
|
||||||
|
* Updated watch file
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sun, 12 Jan 2014 18:06:21 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.7-0kali1) kali; urgency=low
|
||||||
|
|
||||||
|
* Upstream import
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Tue, 17 Dec 2013 09:12:38 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.6-0kali0) kali; urgency=low
|
||||||
|
|
||||||
|
* Upstream import
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Mon, 19 Aug 2013 10:37:12 -0400
|
||||||
|
|
||||||
|
mfoc (0.10.5-0kali0) kali; urgency=low
|
||||||
|
|
||||||
|
* Upstream import.
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sun, 24 Mar 2013 05:49:58 -0400
|
||||||
|
|
||||||
|
mfoc (0.10.3-1kali4) kali; urgency=low
|
||||||
|
|
||||||
|
* Removed desktop file
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sat, 15 Dec 2012 14:23:37 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.3-1kali3) kali; urgency=low
|
||||||
|
|
||||||
|
* Fixed compilation issue
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Tue, 04 Dec 2012 06:43:46 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.3-1kali2) kali; urgency=low
|
||||||
|
|
||||||
|
* Version bump
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sat, 01 Dec 2012 16:23:29 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.3-1kali1) kali; urgency=low
|
||||||
|
|
||||||
|
* Version bump
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sat, 01 Dec 2012 16:13:27 -0500
|
||||||
|
|
||||||
|
mfoc (0.10.3-1kali0) kali; urgency=low
|
||||||
|
|
||||||
|
* Initial release
|
||||||
|
|
||||||
|
-- Mati Aharoni <muts@kali.org> Sat, 01 Dec 2012 13:42:57 -0500
|
||||||
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
11
|
||||||
18
debian/control
vendored
Normal file
18
debian/control
vendored
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
Source: mfoc
|
||||||
|
Section: utils
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Debian Security Tools <team+pkg-security@tracker.debian.org>
|
||||||
|
Uploaders: Samuel Henrique <samueloph@debian.org>
|
||||||
|
Build-Depends: debhelper (>= 11), libnfc-dev, pkg-config
|
||||||
|
Standards-Version: 4.1.5
|
||||||
|
Homepage: https://github.com/nfc-tools/mfoc
|
||||||
|
Vcs-Browser: https://salsa.debian.org/pkg-security-team/mfoc
|
||||||
|
Vcs-Git: https://salsa.debian.org/pkg-security-team/mfoc.git
|
||||||
|
|
||||||
|
Package: mfoc
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${shlibs:Depends}, ${misc:Depends}
|
||||||
|
Description: MIFARE Classic offline cracker
|
||||||
|
This package includes the mfoc program which cracks the
|
||||||
|
encryption keys of the MIFARE Classic chip and dumps the
|
||||||
|
chip's memory contents to a file.
|
||||||
73
debian/copyright
vendored
Normal file
73
debian/copyright
vendored
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
Format: http://dep.debian.net/deps/dep5
|
||||||
|
Upstream-Name: MFOC
|
||||||
|
Source: https://github.com/nfc-tools/mfoc
|
||||||
|
|
||||||
|
Files: *
|
||||||
|
Copyright: 2009 Norbert Szetei
|
||||||
|
2009 Pavol Luptak
|
||||||
|
2010 Micahal Boska
|
||||||
|
2010-2011 Romuald Conty <romuald@libnfc.org>
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: src/crypto1.c src/crapto1.c src/crapto1.h
|
||||||
|
Copyright: 2008-2009 bla <blapost@gmail.com>
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: src/slre.c src/slre.h
|
||||||
|
Copyright: 2013 Cesanta Software Limited
|
||||||
|
2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
Files: src/nfc-utils.c src/mifare.c src/mifare.h src/nfc-utils.h
|
||||||
|
Copyright: 2010-2013 Philippe Teuwen
|
||||||
|
2009-2013 Romuald Conty <romuald@libnfc.org>
|
||||||
|
2009 Roel Verdult
|
||||||
|
2012-2013 Ludovic Rousseau <ludovic.rousseau@gmail.com>
|
||||||
|
2010-2012 Romain Tartière <romain.tartiere@gmail.com>
|
||||||
|
License: BSD-2-clause
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
.
|
||||||
|
1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer.
|
||||||
|
.
|
||||||
|
2 )Redistributions in binary form must reproduce the above copyright
|
||||||
|
notice, this list of conditions and the following disclaimer in the
|
||||||
|
documentation and/or other materials provided with the distribution.
|
||||||
|
.
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
Files: debian/*
|
||||||
|
Copyright: 2011 Thomas Hood <jdthood@gmail.com>
|
||||||
|
2012-2014 Mati Aharoni <muts@kali.org>
|
||||||
|
2015 Sophie Brun <sophie@freexian.com
|
||||||
|
2018 Samuel Henrique <samueloph@debian.org>
|
||||||
|
License: GPL-2+
|
||||||
|
|
||||||
|
License: GPL-2+
|
||||||
|
This package is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 2 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
.
|
||||||
|
This package is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
.
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
.
|
||||||
|
On Debian systems, the complete text of the GNU General Public
|
||||||
|
License version 2 can be found in "/usr/share/common-licenses/GPL-2".
|
||||||
|
|
||||||
1
debian/docs
vendored
Normal file
1
debian/docs
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
AUTHORS
|
||||||
1
debian/manpages
vendored
Normal file
1
debian/manpages
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
src/mfoc.1
|
||||||
8
debian/rules
vendored
Executable file
8
debian/rules
vendored
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
export DEB_BUILD_MAINT_OPTIONS = hardening=+all
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@
|
||||||
|
|
||||||
|
override_dh_installchangelogs:
|
||||||
|
dh_installchangelogs ChangeLog
|
||||||
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.0 (quilt)
|
||||||
3
debian/watch
vendored
Normal file
3
debian/watch
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
version=4
|
||||||
|
|
||||||
|
https://github.com/nfc-tools/mfoc/tags/ .*/mfoc-(.*)\.tar\.gz
|
||||||
@ -1,7 +1,10 @@
|
|||||||
|
AM_CFLAGS = @libnfc_CFLAGS@
|
||||||
|
|
||||||
bin_PROGRAMS = mfoc
|
bin_PROGRAMS = mfoc
|
||||||
|
|
||||||
noinst_HEADERS = crapto1.h mfoc.h mifare.h nfc-utils.h
|
noinst_HEADERS = crapto1.h mfoc.h mifare.h nfc-utils.h
|
||||||
mfoc_SOURCES = crapto1.c crypto1.c mfoc.c mifare.c nfc-utils.c
|
|
||||||
mfoc_LDADD = @LIBNFC_LIBS@
|
|
||||||
|
|
||||||
# dist_man_MANS = mfoc.1
|
mfoc_SOURCES = crapto1.c crypto1.c mfoc.c mifare.c nfc-utils.c
|
||||||
|
mfoc_LDADD = @libnfc_LIBS@
|
||||||
|
|
||||||
|
dist_man_MANS = mfoc.1
|
||||||
|
|||||||
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#if !defined LOWMEM && defined __GNUC__
|
#if !defined LOWMEM && defined __GNUC__
|
||||||
static uint8_t filterlut[1 << 20];
|
static uint8_t filterlut[1 << 20];
|
||||||
static void __attribute__((constructor)) fill_lut()
|
static void __attribute__((constructor)) fill_lut(void)
|
||||||
{
|
{
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
for (i = 0; i < 1 << 20; ++i)
|
for (i = 0; i < 1 << 20; ++i)
|
||||||
@ -126,8 +126,7 @@ extend_table_simple(uint32_t *tbl, uint32_t **end, int bit)
|
|||||||
static struct Crypto1State *
|
static struct Crypto1State *
|
||||||
recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
||||||
uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem,
|
uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem,
|
||||||
struct Crypto1State *sl, uint32_t in)
|
struct Crypto1State *sl, uint32_t in) {
|
||||||
{
|
|
||||||
uint32_t *o, *e, i;
|
uint32_t *o, *e, i;
|
||||||
|
|
||||||
if (rem == -1) {
|
if (rem == -1) {
|
||||||
@ -163,8 +162,7 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
|||||||
e_tail = binsearch(e_head, e = e_tail);
|
e_tail = binsearch(e_head, e = e_tail);
|
||||||
sl = recover(o_tail--, o, oks,
|
sl = recover(o_tail--, o, oks,
|
||||||
e_tail--, e, eks, rem, sl, in);
|
e_tail--, e, eks, rem, sl, in);
|
||||||
}
|
} else if (*o_tail > *e_tail)
|
||||||
else if(*o_tail > *e_tail)
|
|
||||||
o_tail = binsearch(o_head, o_tail) - 1;
|
o_tail = binsearch(o_head, o_tail) - 1;
|
||||||
else
|
else
|
||||||
e_tail = binsearch(e_head, e_tail) - 1;
|
e_tail = binsearch(e_head, e_tail) - 1;
|
||||||
@ -176,8 +174,7 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks,
|
|||||||
* additionally you can use the in parameter to specify the value
|
* additionally you can use the in parameter to specify the value
|
||||||
* that was fed into the lfsr at the time the keystream was generated
|
* that was fed into the lfsr at the time the keystream was generated
|
||||||
*/
|
*/
|
||||||
struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in)
|
struct Crypto1State *lfsr_recovery32(uint32_t ks2, uint32_t in) {
|
||||||
{
|
|
||||||
struct Crypto1State *statelist;
|
struct Crypto1State *statelist;
|
||||||
uint32_t *odd_head = 0, *odd_tail = 0, oks = 0;
|
uint32_t *odd_head = 0, *odd_tail = 0, oks = 0;
|
||||||
uint32_t *even_head = 0, *even_tail = 0, eks = 0;
|
uint32_t *even_head = 0, *even_tail = 0, eks = 0;
|
||||||
@ -220,29 +217,32 @@ out:
|
|||||||
|
|
||||||
static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214,
|
static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214,
|
||||||
0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83,
|
0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83,
|
||||||
0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA};
|
0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA
|
||||||
|
};
|
||||||
static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60,
|
static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60,
|
||||||
0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8,
|
0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8,
|
||||||
0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20,
|
0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20,
|
||||||
0x7EC7EE90, 0x7F63F748, 0x79117020};
|
0x7EC7EE90, 0x7F63F748, 0x79117020
|
||||||
|
};
|
||||||
static const uint32_t T1[] = {
|
static const uint32_t T1[] = {
|
||||||
0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66,
|
0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66,
|
||||||
0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B,
|
0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B,
|
||||||
0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615,
|
0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615,
|
||||||
0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C};
|
0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C
|
||||||
|
};
|
||||||
static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0,
|
static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0,
|
||||||
0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268,
|
0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268,
|
||||||
0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0,
|
0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0,
|
||||||
0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0,
|
0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0,
|
||||||
0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950,
|
0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950,
|
||||||
0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0};
|
0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0
|
||||||
|
};
|
||||||
static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD};
|
static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD};
|
||||||
static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0};
|
static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0};
|
||||||
/** Reverse 64 bits of keystream into possible cipher states
|
/** Reverse 64 bits of keystream into possible cipher states
|
||||||
* Variation mentioned in the paper. Somewhat optimized version
|
* Variation mentioned in the paper. Somewhat optimized version
|
||||||
*/
|
*/
|
||||||
struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3)
|
struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3) {
|
||||||
{
|
|
||||||
struct Crypto1State *statelist, *sl;
|
struct Crypto1State *statelist, *sl;
|
||||||
uint8_t oks[32], eks[32], hi[32];
|
uint8_t oks[32], eks[32], hi[32];
|
||||||
uint32_t low = 0, win = 0;
|
uint32_t low = 0, win = 0;
|
||||||
@ -302,12 +302,17 @@ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3)
|
|||||||
sl->even = win;
|
sl->even = win;
|
||||||
++sl;
|
++sl;
|
||||||
sl->odd = sl->even = 0;
|
sl->odd = sl->even = 0;
|
||||||
continue2:;
|
continue2:
|
||||||
|
;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return statelist;
|
return statelist;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb);
|
||||||
|
uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb);
|
||||||
|
uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd);
|
||||||
|
|
||||||
/** lfsr_rollback_bit
|
/** lfsr_rollback_bit
|
||||||
* Rollback the shift register in order to get previous states
|
* Rollback the shift register in order to get previous states
|
||||||
*/
|
*/
|
||||||
@ -369,11 +374,18 @@ int nonce_distance(uint32_t from, uint32_t to)
|
|||||||
}
|
}
|
||||||
return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535;
|
return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535;
|
||||||
}
|
}
|
||||||
|
bool validate_prng_nonce(uint32_t nonce)
|
||||||
|
{
|
||||||
|
// init prng table:
|
||||||
|
nonce_distance(nonce, nonce);
|
||||||
|
return ((65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535) == 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static uint32_t fastfwd[2][8] = {
|
static uint32_t fastfwd[2][8] = {
|
||||||
{ 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB},
|
{ 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB},
|
||||||
{ 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}};
|
{ 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/** lfsr_prefix_ks
|
/** lfsr_prefix_ks
|
||||||
@ -415,8 +427,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd)
|
|||||||
*/
|
*/
|
||||||
static struct Crypto1State *
|
static struct Crypto1State *
|
||||||
check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
|
check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
|
||||||
uint32_t odd, uint32_t even, struct Crypto1State* sl)
|
uint32_t odd, uint32_t even, struct Crypto1State *sl) {
|
||||||
{
|
|
||||||
uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;
|
uint32_t ks1, nr, ks2, rr, ks3, c, good = 1;
|
||||||
|
|
||||||
for (c = 0; good && c < 8; ++c) {
|
for (c = 0; good && c < 8; ++c) {
|
||||||
@ -444,6 +455,8 @@ check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Crypto1State *lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]);
|
||||||
|
|
||||||
/** lfsr_common_prefix
|
/** lfsr_common_prefix
|
||||||
* Implentation of the common prefix attack.
|
* Implentation of the common prefix attack.
|
||||||
* Requires the 29 bit constant prefix used as reader nonce (pfx)
|
* Requires the 29 bit constant prefix used as reader nonce (pfx)
|
||||||
@ -454,8 +467,7 @@ check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8],
|
|||||||
* tag nonce was fed in
|
* tag nonce was fed in
|
||||||
*/
|
*/
|
||||||
struct Crypto1State *
|
struct Crypto1State *
|
||||||
lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8])
|
lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) {
|
||||||
{
|
|
||||||
struct Crypto1State *statelist, *s;
|
struct Crypto1State *statelist, *s;
|
||||||
uint32_t *odd, *even, *o, *e, top;
|
uint32_t *odd, *even, *o, *e, top;
|
||||||
|
|
||||||
|
|||||||
@ -20,6 +20,7 @@
|
|||||||
#ifndef CRAPTO1_INCLUDED
|
#ifndef CRAPTO1_INCLUDED
|
||||||
#define CRAPTO1_INCLUDED
|
#define CRAPTO1_INCLUDED
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
@ -37,7 +38,9 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in);
|
|||||||
struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3);
|
struct Crypto1State *lfsr_recovery64(uint32_t ks2, uint32_t ks3);
|
||||||
|
|
||||||
void lfsr_rollback(struct Crypto1State *s, uint32_t in, int fb);
|
void lfsr_rollback(struct Crypto1State *s, uint32_t in, int fb);
|
||||||
|
uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb);
|
||||||
int nonce_distance(uint32_t from, uint32_t to);
|
int nonce_distance(uint32_t from, uint32_t to);
|
||||||
|
bool validate_prng_nonce(uint32_t nonce);
|
||||||
#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\
|
#define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\
|
||||||
uint32_t __n = 0,__M = 0, N = 0;\
|
uint32_t __n = 0,__M = 0, N = 0;\
|
||||||
int __i;\
|
int __i;\
|
||||||
@ -61,7 +64,7 @@ static inline int parity(uint32_t x)
|
|||||||
x ^= x >> 4;
|
x ^= x >> 4;
|
||||||
return BIT(0x6996, x & 0xf);
|
return BIT(0x6996, x & 0xf);
|
||||||
#else
|
#else
|
||||||
asm( "movl %1, %%eax\n"
|
__asm__("movl %1, %%eax\n"
|
||||||
"mov %%ax, %%cx\n"
|
"mov %%ax, %%cx\n"
|
||||||
"shrl $0x10, %%eax\n"
|
"shrl $0x10, %%eax\n"
|
||||||
"xor %%ax, %%cx\n"
|
"xor %%ax, %%cx\n"
|
||||||
|
|||||||
@ -23,8 +23,7 @@
|
|||||||
#define SWAPENDIAN(x)\
|
#define SWAPENDIAN(x)\
|
||||||
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
|
(x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16)
|
||||||
|
|
||||||
struct Crypto1State * crypto1_create(uint64_t key)
|
struct Crypto1State *crypto1_create(uint64_t key) {
|
||||||
{
|
|
||||||
struct Crypto1State *s = malloc(sizeof(*s));
|
struct Crypto1State *s = malloc(sizeof(*s));
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|||||||
41
src/mfoc.1
Normal file
41
src/mfoc.1
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
.\" Hey, EMACS: -*- nroff -*-
|
||||||
|
.TH MFOC 1 "May 13, 2011"
|
||||||
|
.SH NAME
|
||||||
|
mfoc \- MIFARE Classic offline cracker
|
||||||
|
.SH SYNOPSIS
|
||||||
|
.B mfoc
|
||||||
|
[ \fB\-h\fP ]
|
||||||
|
[ \fB\-k\fP \fIKEY\fR ]...
|
||||||
|
[ \fB\-O\fP \fIFILE\fR ]
|
||||||
|
[ \fB\-P\fP \fINUM\fR ]
|
||||||
|
[ \fB\-T\fP \fINUM\fR ]
|
||||||
|
.SH DESCRIPTION
|
||||||
|
This manual page documents briefly the
|
||||||
|
.B mfoc
|
||||||
|
command.
|
||||||
|
.PP
|
||||||
|
\fBmfoc\fP is a program that cracks the encryption of a MIFARE Classic chip and dumps the chip's keys and decrypted memory contents to a file.
|
||||||
|
To run it you need to have access to an NFC reader and, of course, a card equipped with a MIFARE Classic chip.
|
||||||
|
.SH OPTIONS
|
||||||
|
A summary of options is included below.
|
||||||
|
.TP
|
||||||
|
\fB\-h\fP
|
||||||
|
Show summary of options.
|
||||||
|
.TP
|
||||||
|
\fB\-k\fP \fIKEY\fR
|
||||||
|
Initially try KEY in addition to the default keys.
|
||||||
|
.TP
|
||||||
|
\fB\-O\fP \fIFILE\fR
|
||||||
|
Dump card contents to FILE.
|
||||||
|
.TP
|
||||||
|
\fB\-P\fP \fINUM\fR
|
||||||
|
Probe each sector up to NUM times. Default is 20.
|
||||||
|
.TP
|
||||||
|
\fB\-T\fP \fINUM\fR
|
||||||
|
Set half the range for a possible distance tolerance to NUM. Default is 20 (for a total range of 40).
|
||||||
|
.SH AUTHOR
|
||||||
|
.B mfoc
|
||||||
|
was written by Norbert Szetei and Pavol Luptak with contributions by others.
|
||||||
|
.PP
|
||||||
|
This manual page was written by Thomas Hood <jdthood@gmail.com>.
|
||||||
|
MIFARE is a trade mark of NXP bv, Netherlands.
|
||||||
867
src/mfoc.c
867
src/mfoc.c
File diff suppressed because it is too large
Load Diff
60
src/mfoc.h
60
src/mfoc.h
@ -2,10 +2,24 @@
|
|||||||
#define TRY_KEYS 50
|
#define TRY_KEYS 50
|
||||||
|
|
||||||
// Number of trailers == number of sectors
|
// Number of trailers == number of sectors
|
||||||
// 16x64b = 16
|
// Mifare Classic 1k 16x64b = 16
|
||||||
#define NR_TRAILERS_1k (16)
|
#define NR_TRAILERS_1k (16)
|
||||||
// 32x64b + 8*256b = 40
|
// Mifare Classic Mini
|
||||||
|
#define NR_TRAILERS_MINI (5)
|
||||||
|
// Mifare Classic 4k 32x64b + 8*256b = 40
|
||||||
#define NR_TRAILERS_4k (40)
|
#define NR_TRAILERS_4k (40)
|
||||||
|
// Mifare Classic 2k 32x64b
|
||||||
|
#define NR_TRAILERS_2k (32)
|
||||||
|
|
||||||
|
// Number of blocks
|
||||||
|
// Mifare Classic 1k
|
||||||
|
#define NR_BLOCKS_1k 0x3f
|
||||||
|
// Mifare Classic Mini
|
||||||
|
#define NR_BLOCKS_MINI 0x13
|
||||||
|
// Mifare Classic 4k
|
||||||
|
#define NR_BLOCKS_4k 0xff
|
||||||
|
// Mifare Classic 2k
|
||||||
|
#define NR_BLOCKS_2k 0x7f
|
||||||
|
|
||||||
#define MAX_FRAME_LEN 264
|
#define MAX_FRAME_LEN 264
|
||||||
|
|
||||||
@ -24,29 +38,28 @@
|
|||||||
#define odd_parity(i) (( (i) ^ (i)>>1 ^ (i)>>2 ^ (i)>>3 ^ (i)>>4 ^ (i)>>5 ^ (i)>>6 ^ (i)>>7 ^ 1) & 0x01)
|
#define odd_parity(i) (( (i) ^ (i)>>1 ^ (i)>>2 ^ (i)>>3 ^ (i)>>4 ^ (i)>>5 ^ (i)>>6 ^ (i)>>7 ^ 1) & 0x01)
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t KeyA[6];
|
uint8_t KeyA[6];
|
||||||
byte_t KeyB[6];
|
uint8_t KeyB[6];
|
||||||
bool foundKeyA;
|
bool foundKeyA;
|
||||||
bool foundKeyB;
|
bool foundKeyB;
|
||||||
byte_t trailer; // Value of a trailer block
|
uint8_t trailer; // Value of a trailer block
|
||||||
} sector;
|
} sector;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
u_int32_t *distances;
|
uint32_t *distances;
|
||||||
u_int32_t median;
|
uint32_t median;
|
||||||
u_int32_t num_distances;
|
uint32_t num_distances;
|
||||||
u_int32_t tolerance;
|
uint32_t tolerance;
|
||||||
byte_t parity[3]; // used for 3 bits of parity information
|
uint8_t parity[3]; // used for 3 bits of parity information
|
||||||
} denonce; // Revealed information about nonce
|
} denonce; // Revealed information about nonce
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nfc_target_info_t ti;
|
nfc_target nt;
|
||||||
sector *sectors; // Allocate later, we do not know the number of sectors yet
|
sector *sectors; // Allocate later, we do not know the number of sectors yet
|
||||||
sector e_sector; // Exploit sector
|
sector e_sector; // Exploit sector
|
||||||
uint32_t num_sectors;
|
uint8_t num_sectors;
|
||||||
uint32_t num_blocks;
|
uint8_t num_blocks;
|
||||||
uint32_t uid;
|
uint32_t authuid;
|
||||||
bool b4K;
|
|
||||||
} mftag;
|
} mftag;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -60,7 +73,7 @@ typedef struct {
|
|||||||
} bKeys;
|
} bKeys;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
nfc_device_t *pdi;
|
nfc_device *pdi;
|
||||||
} mfreader;
|
} mfreader;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -69,18 +82,19 @@ typedef struct {
|
|||||||
} countKeys;
|
} countKeys;
|
||||||
|
|
||||||
|
|
||||||
void usage(FILE * stream, int errno);
|
void usage(FILE *stream, int code);
|
||||||
void mf_init(mftag *t, mfreader *r);
|
void mf_init(mfreader *r);
|
||||||
void mf_configure(nfc_device_t* pdi);
|
void mf_configure(nfc_device *pdi);
|
||||||
void mf_select_tag(nfc_device_t* pdi, nfc_target_info_t* ti);
|
void mf_select_tag(nfc_device *pdi, nfc_target *pnt);
|
||||||
int trailer_block(uint32_t block);
|
int trailer_block(uint32_t block);
|
||||||
int find_exploit_sector(mftag t);
|
int find_exploit_sector(mftag t);
|
||||||
void mf_anticollision(mftag t, mfreader r);
|
void mf_anticollision(mftag t, mfreader r);
|
||||||
|
bool get_rats_is_2k(mftag t, mfreader r);
|
||||||
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA);
|
int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d, pKeys *pk, char mode, bool dumpKeysA);
|
||||||
uint32_t median(denonce d);
|
uint32_t median(denonce d);
|
||||||
int compar_int(const void *a, const void *b);
|
int compar_int(const void *a, const void *b);
|
||||||
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, byte_t * parity);
|
int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity);
|
||||||
int compar_special_int(const void *a, const void *b);
|
int compar_special_int(const void *a, const void *b);
|
||||||
countKeys *uniqsort(uint64_t *possibleKeys, uint32_t size);
|
countKeys *uniqsort(uint64_t *possibleKeys, uint32_t size);
|
||||||
void num_to_bytes(uint64_t n, uint32_t len, byte_t* dest);
|
void num_to_bytes(uint64_t n, uint32_t len, uint8_t *dest);
|
||||||
long long unsigned int bytes_to_num(byte_t* src, uint32_t len);
|
long long unsigned int bytes_to_num(uint8_t *src, uint32_t len);
|
||||||
|
|||||||
109
src/mifare.c
109
src/mifare.c
@ -1,3 +1,50 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Roel Verdult
|
||||||
|
* Copyright (C) 2010 Romain Tartière
|
||||||
|
* Copyright (C) 2010, 2011, 2013 Romuald Conty
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file mifare.c
|
||||||
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This implementation was written based on information provided by the
|
||||||
|
* following document:
|
||||||
|
*
|
||||||
|
* MIFARE Classic Specification
|
||||||
|
* MF1ICS50
|
||||||
|
* Functional specification
|
||||||
|
* Rev. 5.3 - 29 January 2008
|
||||||
|
* http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf
|
||||||
|
*/
|
||||||
|
|
||||||
#include "mifare.h"
|
#include "mifare.h"
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -5,29 +52,33 @@
|
|||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Execute a MIFARE Classic Command
|
* @brief Execute a MIFARE Classic command
|
||||||
* @return Returns true if action was successfully performed; otherwise returns false.
|
* @return Returns NFC_SUCCESS if action was successfully performed; otherwise returns error code (negative value).
|
||||||
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
|
* @param pmp Some commands need additional information. This information should be supplied in the mifare_param union.
|
||||||
*
|
*
|
||||||
* The specified MIFARE command will be executed on the tag. There are different commands possible, they all require the destination block number.
|
* The specified MIFARE command will be executed on the tag. There are
|
||||||
|
* different commands possible, they all require the destination block number.
|
||||||
|
*
|
||||||
* @note There are three different types of information (Authenticate, Data and Value).
|
* @note There are three different types of information (Authenticate, Data and Value).
|
||||||
*
|
*
|
||||||
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
|
* First an authentication must take place using Key A or B. It requires a 48 bit Key (6 bytes) and the UID.
|
||||||
* They are both used to initialize the internal cipher-state of the PN53X chip (http://libnfc.org/hardware/pn53x-chip).
|
|
||||||
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
* After a successful authentication it will be possible to execute other commands (e.g. Read/Write).
|
||||||
* The MIFARE Classic Specification (http://www.nxp.com/acrobat/other/identification/M001053_MF1ICS50_rev5_3.pdf) explains more about this process.
|
*
|
||||||
|
* Like libnfc's functions, this one returns negative value on error (libnfc's
|
||||||
|
* error code) but two of them need a special attention in this context (MIFARE
|
||||||
|
* Classic):
|
||||||
|
* - NFC_EMFCAUTHFAIL, "MIFARE authentication failed", means key is not valid
|
||||||
|
* on specified sector.
|
||||||
|
* - NFC_ERFTRANS, "Invalid received frame", when occurs on MIFARE command
|
||||||
|
* read or write after a successful authentication, means permissions allowed
|
||||||
|
* by current acces bytes are not sufficient to process the command.
|
||||||
*/
|
*/
|
||||||
bool
|
int
|
||||||
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
|
nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp)
|
||||||
{
|
{
|
||||||
byte_t abtRx[265];
|
uint8_t abtRx[265];
|
||||||
size_t szRxLen;
|
|
||||||
size_t szParamLen;
|
size_t szParamLen;
|
||||||
byte_t abtCmd[265];
|
uint8_t abtCmd[265];
|
||||||
|
|
||||||
// Make sure we are dealing with a active device
|
|
||||||
if (!pnd->bActive)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
abtCmd[0] = mc; // The MIFARE Classic command
|
abtCmd[0] = mc; // The MIFARE Classic command
|
||||||
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
|
||||||
@ -42,45 +93,49 @@ nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t
|
|||||||
// Authenticate command
|
// Authenticate command
|
||||||
case MC_AUTH_A:
|
case MC_AUTH_A:
|
||||||
case MC_AUTH_B:
|
case MC_AUTH_B:
|
||||||
szParamLen = sizeof (mifare_param_auth);
|
szParamLen = sizeof(struct mifare_param_auth);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Data command
|
// Data command
|
||||||
case MC_WRITE:
|
case MC_WRITE:
|
||||||
szParamLen = sizeof (mifare_param_data);
|
szParamLen = sizeof(struct mifare_param_data);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Value command
|
// Value command
|
||||||
case MC_DECREMENT:
|
case MC_DECREMENT:
|
||||||
case MC_INCREMENT:
|
case MC_INCREMENT:
|
||||||
case MC_TRANSFER:
|
case MC_TRANSFER:
|
||||||
szParamLen = sizeof (mifare_param_value);
|
szParamLen = sizeof(struct mifare_param_value);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Please fix your code, you never should reach this statement
|
// Please fix your code, you never should reach this statement
|
||||||
default:
|
default:
|
||||||
return false;
|
return NFC_EINVARG;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
// When available, copy the parameter bytes
|
// When available, copy the parameter bytes
|
||||||
if (szParamLen)
|
if (szParamLen)
|
||||||
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
|
memcpy(abtCmd + 2, (uint8_t *) pmp, szParamLen);
|
||||||
|
|
||||||
// Fire the mifare command
|
// FIXME: Save and restore bEasyFraming
|
||||||
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRxLen)) {
|
int res;
|
||||||
if (pnd->iLastError != 0x14)
|
if ((res = nfc_device_set_property_bool(pnd, NP_EASY_FRAMING, true)) < 0) {
|
||||||
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
|
return res;
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
// Fire the mifare command
|
||||||
|
if ((res = nfc_initiator_transceive_bytes(pnd, abtCmd, 2 + szParamLen, abtRx, sizeof(abtRx), -1)) < 0) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
// When we have executed a read command, copy the received bytes into the param
|
// When we have executed a read command, copy the received bytes into the param
|
||||||
if (mc == MC_READ) {
|
if (mc == MC_READ) {
|
||||||
if (szRxLen == 16) {
|
if (res == 16) {
|
||||||
memcpy(pmp->mpd.abtData, abtRx, 16);
|
memcpy(pmp->mpd.abtData, abtRx, 16);
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return NFC_EINVARG;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Command succesfully executed
|
// Command succesfully executed
|
||||||
return true;
|
return NFC_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|||||||
117
src/mifare.h
117
src/mifare.h
@ -1,23 +1,36 @@
|
|||||||
|
/*-
|
||||||
|
* Public platform independent Near Field Communication (NFC) library examples
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Roel Verdult
|
||||||
|
* Copyright (C) 2010 Romain Tartière
|
||||||
|
* Copyright (C) 2010, 2011, 2013 Romuald Conty
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public platform independent Near Field Communication (NFC) library
|
* @file mifare.h
|
||||||
*
|
|
||||||
* Copyright (C) 2009, Roel Verdult, 2010, Romuald Conty
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @file mifaretag.h
|
|
||||||
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -26,7 +39,7 @@
|
|||||||
|
|
||||||
#include <nfc/nfc-types.h>
|
#include <nfc/nfc-types.h>
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 uint8_t for compatibility
|
||||||
#pragma pack(1)
|
#pragma pack(1)
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@ -41,50 +54,50 @@ typedef enum {
|
|||||||
} mifare_cmd;
|
} mifare_cmd;
|
||||||
|
|
||||||
// MIFARE command params
|
// MIFARE command params
|
||||||
typedef struct {
|
struct mifare_param_auth {
|
||||||
byte_t abtKey[6];
|
uint8_t abtKey[6];
|
||||||
byte_t abtUid[4];
|
uint8_t abtAuthUid[4];
|
||||||
} mifare_param_auth;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mifare_param_data {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifare_param_data;
|
};
|
||||||
|
|
||||||
typedef struct {
|
struct mifare_param_value {
|
||||||
byte_t abtValue[4];
|
uint8_t abtValue[4];
|
||||||
} mifare_param_value;
|
};
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
mifare_param_auth mpa;
|
struct mifare_param_auth mpa;
|
||||||
mifare_param_data mpd;
|
struct mifare_param_data mpd;
|
||||||
mifare_param_value mpv;
|
struct mifare_param_value mpv;
|
||||||
} mifare_param;
|
} mifare_param;
|
||||||
|
|
||||||
// Reset struct alignment to default
|
// Reset struct alignment to default
|
||||||
# pragma pack()
|
# pragma pack()
|
||||||
|
|
||||||
bool nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp);
|
int nfc_initiator_mifare_cmd(nfc_device *pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param *pmp);
|
||||||
|
|
||||||
// Compiler directive, set struct alignment to 1 byte_t for compatibility
|
// Compiler directive, set struct alignment to 1 uint8_t for compatibility
|
||||||
# pragma pack(1)
|
# pragma pack(1)
|
||||||
|
|
||||||
// MIFARE Classic
|
// MIFARE Classic
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtUID[4];
|
uint8_t abtUID[4];
|
||||||
byte_t btBCC;
|
uint8_t btBCC;
|
||||||
byte_t btUnknown;
|
uint8_t btUnknown;
|
||||||
byte_t abtATQA[2];
|
uint8_t abtATQA[2];
|
||||||
byte_t abtUnknown[8];
|
uint8_t abtUnknown[8];
|
||||||
} mifare_classic_block_manufacturer;
|
} mifare_classic_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifare_classic_block_data;
|
} mifare_classic_block_data;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtKeyA[6];
|
uint8_t abtKeyA[6];
|
||||||
byte_t abtAccessBits[4];
|
uint8_t abtAccessBits[4];
|
||||||
byte_t abtKeyB[6];
|
uint8_t abtKeyB[6];
|
||||||
} mifare_classic_block_trailer;
|
} mifare_classic_block_trailer;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
@ -99,17 +112,17 @@ typedef struct {
|
|||||||
|
|
||||||
// MIFARE Ultralight
|
// MIFARE Ultralight
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t sn0[3];
|
uint8_t sn0[3];
|
||||||
byte_t btBCC0;
|
uint8_t btBCC0;
|
||||||
byte_t sn1[4];
|
uint8_t sn1[4];
|
||||||
byte_t btBCC1;
|
uint8_t btBCC1;
|
||||||
byte_t internal;
|
uint8_t internal;
|
||||||
byte_t lock[2];
|
uint8_t lock[2];
|
||||||
byte_t otp[4];
|
uint8_t otp[4];
|
||||||
} mifareul_block_manufacturer;
|
} mifareul_block_manufacturer;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
byte_t abtData[16];
|
uint8_t abtData[16];
|
||||||
} mifareul_block_data;
|
} mifareul_block_data;
|
||||||
|
|
||||||
typedef union {
|
typedef union {
|
||||||
|
|||||||
171
src/nfc-utils.c
171
src/nfc-utils.c
@ -1,44 +1,65 @@
|
|||||||
|
/*-
|
||||||
|
* Free/Libre Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Libnfc historical contributors:
|
||||||
|
* Copyright (C) 2009 Roel Verdult
|
||||||
|
* Copyright (C) 2009-2013 Romuald Conty
|
||||||
|
* Copyright (C) 2010-2012 Romain Tartière
|
||||||
|
* Copyright (C) 2010-2013 Philippe Teuwen
|
||||||
|
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||||
|
* Additional contributors of this file:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* @file nfc-utils.c
|
||||||
|
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
|
||||||
|
*/
|
||||||
#include <nfc/nfc.h>
|
#include <nfc/nfc.h>
|
||||||
|
#include <err.h>
|
||||||
|
|
||||||
#include "nfc-utils.h"
|
#include "nfc-utils.h"
|
||||||
|
|
||||||
static const byte_t OddParity[256] = {
|
uint8_t
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
oddparity(const uint8_t bt)
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0,
|
|
||||||
1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1
|
|
||||||
};
|
|
||||||
|
|
||||||
byte_t
|
|
||||||
oddparity (const byte_t bt)
|
|
||||||
{
|
{
|
||||||
return OddParity[bt];
|
// cf http://graphics.stanford.edu/~seander/bithacks.html#ParityParallel
|
||||||
|
return (0x9669 >> ((bt ^(bt >> 4)) & 0xF)) & 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
oddparity_bytes_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar)
|
oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar)
|
||||||
{
|
{
|
||||||
size_t szByteNr;
|
size_t szByteNr;
|
||||||
// Calculate the parity bits for the command
|
// Calculate the parity bits for the command
|
||||||
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
for (szByteNr = 0; szByteNr < szLen; szByteNr++) {
|
||||||
pbtPar[szByteNr] = OddParity[pbtData[szByteNr]];
|
pbtPar[szByteNr] = oddparity(pbtData[szByteNr]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex (const byte_t * pbtData, const size_t szBytes)
|
print_hex(const uint8_t *pbtData, const size_t szBytes)
|
||||||
{
|
{
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
|
|
||||||
@ -49,7 +70,7 @@ print_hex (const byte_t * pbtData, const size_t szBytes)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex_bits (const byte_t * pbtData, const size_t szBits)
|
print_hex_bits(const uint8_t *pbtData, const size_t szBits)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
@ -71,7 +92,7 @@ print_hex_bits (const byte_t * pbtData, const size_t szBits)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar)
|
print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar)
|
||||||
{
|
{
|
||||||
uint8_t uRemainder;
|
uint8_t uRemainder;
|
||||||
size_t szPos;
|
size_t szPos;
|
||||||
@ -79,7 +100,7 @@ print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDa
|
|||||||
|
|
||||||
for (szPos = 0; szPos < szBytes; szPos++) {
|
for (szPos = 0; szPos < szBytes; szPos++) {
|
||||||
printf("%02x", pbtData[szPos]);
|
printf("%02x", pbtData[szPos]);
|
||||||
if (OddParity[pbtData[szPos]] != pbtDataPar[szPos]) {
|
if (oddparity(pbtData[szPos]) != pbtDataPar[szPos]) {
|
||||||
printf("! ");
|
printf("! ");
|
||||||
} else {
|
} else {
|
||||||
printf(" ");
|
printf(" ");
|
||||||
@ -97,95 +118,11 @@ print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDa
|
|||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SAK_ISO14443_4_COMPLIANT 0x20
|
|
||||||
#define SAK_ISO18092_COMPLIANT 0x40
|
|
||||||
|
|
||||||
void
|
void
|
||||||
print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai)
|
print_nfc_target(const nfc_target *pnt, bool verbose)
|
||||||
{
|
{
|
||||||
printf (" ATQA (SENS_RES): ");
|
char *s;
|
||||||
print_hex (nai.abtAtqa, 2);
|
str_nfc_target(&s, pnt, verbose);
|
||||||
printf (" UID (NFCID%c): ", (nai.abtUid[0] == 0x08 ? '3' : '1'));
|
printf("%s", s);
|
||||||
print_hex (nai.abtUid, nai.szUidLen);
|
nfc_free(s);
|
||||||
printf (" SAK (SEL_RES): ");
|
|
||||||
print_hex (&nai.btSak, 1);
|
|
||||||
if (nai.szAtsLen) {
|
|
||||||
printf (" ATS (ATR): ");
|
|
||||||
print_hex (nai.abtAts, nai.szAtsLen);
|
|
||||||
}
|
|
||||||
if ((nai.btSak & SAK_ISO14443_4_COMPLIANT) || (nai.btSak & SAK_ISO18092_COMPLIANT)) {
|
|
||||||
printf (" Compliant with: ");
|
|
||||||
if (nai.btSak & SAK_ISO14443_4_COMPLIANT)
|
|
||||||
printf ("ISO/IEC 14443-4 ");
|
|
||||||
if (nai.btSak & SAK_ISO18092_COMPLIANT)
|
|
||||||
printf ("ISO/IEC 18092");
|
|
||||||
printf ("\n");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_felica_info (const nfc_felica_info_t nfi)
|
|
||||||
{
|
|
||||||
printf (" ID (NFCID2): ");
|
|
||||||
print_hex (nfi.abtId, 8);
|
|
||||||
printf (" Parameter (PAD): ");
|
|
||||||
print_hex (nfi.abtPad, 8);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi)
|
|
||||||
{
|
|
||||||
printf (" ATQB: ");
|
|
||||||
print_hex (nbi.abtAtqb, 12);
|
|
||||||
printf (" ID: ");
|
|
||||||
print_hex (nbi.abtId, 4);
|
|
||||||
printf (" CID: %02x\n", nbi.btCid);
|
|
||||||
if (nbi.szInfLen > 0) {
|
|
||||||
printf (" INF: ");
|
|
||||||
print_hex (nbi.abtInf, nbi.szInfLen);
|
|
||||||
}
|
|
||||||
printf (" PARAMS: %02x %02x %02x %02x\n", nbi.btParam1, nbi.btParam2, nbi.btParam3, nbi.btParam4);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Tries to parse arguments to find device descriptions.
|
|
||||||
* @return Returns the list of found device descriptions.
|
|
||||||
*/
|
|
||||||
nfc_device_desc_t *
|
|
||||||
parse_device_desc (int argc, const char *argv[], size_t * szFound)
|
|
||||||
{
|
|
||||||
nfc_device_desc_t *pndd = 0;
|
|
||||||
int arg;
|
|
||||||
*szFound = 0;
|
|
||||||
|
|
||||||
// Get commandline options
|
|
||||||
for (arg = 1; arg < argc; arg++) {
|
|
||||||
|
|
||||||
if (0 == strcmp (argv[arg], "--device")) {
|
|
||||||
|
|
||||||
if (argc > arg + 1) {
|
|
||||||
char buffer[256];
|
|
||||||
|
|
||||||
pndd = malloc (sizeof (nfc_device_desc_t));
|
|
||||||
|
|
||||||
strncpy (buffer, argv[++arg], 256);
|
|
||||||
|
|
||||||
// Driver.
|
|
||||||
pndd->pcDriver = (char *) malloc (256);
|
|
||||||
strcpy (pndd->pcDriver, strtok (buffer, ":"));
|
|
||||||
|
|
||||||
// Port.
|
|
||||||
pndd->pcPort = (char *) malloc (256);
|
|
||||||
strcpy (pndd->pcPort, strtok (NULL, ":"));
|
|
||||||
|
|
||||||
// Speed.
|
|
||||||
sscanf (strtok (NULL, ":"), "%u", &pndd->uiSpeed);
|
|
||||||
|
|
||||||
*szFound = 1;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pndd;
|
|
||||||
}
|
}
|
||||||
|
|||||||
114
src/nfc-utils.h
114
src/nfc-utils.h
@ -1,22 +1,39 @@
|
|||||||
|
/*-
|
||||||
|
* Free/Libre Near Field Communication (NFC) library
|
||||||
|
*
|
||||||
|
* Libnfc historical contributors:
|
||||||
|
* Copyright (C) 2009 Roel Verdult
|
||||||
|
* Copyright (C) 2009-2013 Romuald Conty
|
||||||
|
* Copyright (C) 2010-2012 Romain Tartière
|
||||||
|
* Copyright (C) 2010-2013 Philippe Teuwen
|
||||||
|
* Copyright (C) 2012-2013 Ludovic Rousseau
|
||||||
|
* Additional contributors of this file:
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* 1) Redistributions of source code must retain the above copyright notice,
|
||||||
|
* this list of conditions and the following disclaimer.
|
||||||
|
* 2 )Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||||
|
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||||
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||||
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||||
|
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||||
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||||
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||||
|
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||||
|
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||||
|
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||||
|
* POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*
|
||||||
|
* Note that this license only applies on the examples, NFC library itself is under LGPL
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Public platform independent Near Field Communication (NFC) library
|
|
||||||
*
|
|
||||||
* Copyright (C) 2010, Romuald Conty
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify it
|
|
||||||
* under the terms of the GNU Lesser General Public License as published by the
|
|
||||||
* Free Software Foundation, either version 3 of the License, or (at your
|
|
||||||
* option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
||||||
* more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU Lesser General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @file nfc-utils.h
|
* @file nfc-utils.h
|
||||||
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
|
* @brief Provide some examples shared functions like print, parity calculation, options parsing.
|
||||||
*/
|
*/
|
||||||
@ -26,18 +43,61 @@
|
|||||||
|
|
||||||
# include <stdlib.h>
|
# include <stdlib.h>
|
||||||
# include <string.h>
|
# include <string.h>
|
||||||
|
# include <err.h>
|
||||||
|
|
||||||
byte_t oddparity (const byte_t bt);
|
/**
|
||||||
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);
|
* @macro DBG
|
||||||
|
* @brief Print a message of standard output only in DEBUG mode
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define DBG(...) do { \
|
||||||
|
warnx ("DBG %s:%d", __FILE__, __LINE__); \
|
||||||
|
warnx (" " __VA_ARGS__ ); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define DBG(...) {}
|
||||||
|
#endif
|
||||||
|
|
||||||
void print_hex (const byte_t * pbtData, const size_t szLen);
|
/**
|
||||||
void print_hex_bits (const byte_t * pbtData, const size_t szBits);
|
* @macro WARN
|
||||||
void print_hex_par (const byte_t * pbtData, const size_t szBits, const byte_t * pbtDataPar);
|
* @brief Print a warn message
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define WARN(...) do { \
|
||||||
|
warnx ("WARNING %s:%d", __FILE__, __LINE__); \
|
||||||
|
warnx (" " __VA_ARGS__ ); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define WARN(...) warnx ("WARNING: " __VA_ARGS__ )
|
||||||
|
#endif
|
||||||
|
|
||||||
void print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai);
|
/**
|
||||||
void print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi);
|
* @macro ERR
|
||||||
void print_nfc_felica_info (const nfc_felica_info_t nfi);
|
* @brief Print a error message
|
||||||
|
*/
|
||||||
|
#ifdef DEBUG
|
||||||
|
# define ERR(...) do { \
|
||||||
|
warnx ("ERROR %s:%d", __FILE__, __LINE__); \
|
||||||
|
warnx (" " __VA_ARGS__ ); \
|
||||||
|
} while (0)
|
||||||
|
#else
|
||||||
|
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
|
||||||
|
#endif
|
||||||
|
|
||||||
nfc_device_desc_t *parse_device_desc (int argc, const char *argv[], size_t * szFound);
|
#ifndef MIN
|
||||||
|
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
#ifndef MAX
|
||||||
|
#define MAX(a,b) (((a) > (b)) ? (a) : (b))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint8_t oddparity(const uint8_t bt);
|
||||||
|
void oddparity_bytes_ts(const uint8_t *pbtData, const size_t szLen, uint8_t *pbtPar);
|
||||||
|
|
||||||
|
void print_hex(const uint8_t *pbtData, const size_t szLen);
|
||||||
|
void print_hex_bits(const uint8_t *pbtData, const size_t szBits);
|
||||||
|
void print_hex_par(const uint8_t *pbtData, const size_t szBits, const uint8_t *pbtDataPar);
|
||||||
|
|
||||||
|
void print_nfc_target(const nfc_target *pnt, bool verbose);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
437
src/slre.c
Normal file
437
src/slre.c
Normal file
@ -0,0 +1,437 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
|
* Copyright (c) 2013 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* This library is dual-licensed: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation. For the terms of this
|
||||||
|
* license, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* You are free to use this library under the terms of the GNU General
|
||||||
|
* Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* Alternatively, you can license this library under a commercial
|
||||||
|
* license, as set out in <http://cesanta.com/products.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "slre.h"
|
||||||
|
|
||||||
|
#define MAX_BRANCHES 100
|
||||||
|
#define MAX_BRACKETS 100
|
||||||
|
#define FAIL_IF(condition, error_code) if (condition) return (error_code)
|
||||||
|
|
||||||
|
#ifndef ARRAY_SIZE
|
||||||
|
#define ARRAY_SIZE(ar) (sizeof(ar) / sizeof((ar)[0]))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef SLRE_DEBUG
|
||||||
|
# ifndef DBG
|
||||||
|
# define DBG(x) printf x
|
||||||
|
# endif
|
||||||
|
#else
|
||||||
|
# ifndef DBG
|
||||||
|
# define DBG(x)
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct bracket_pair {
|
||||||
|
const char *ptr; /* Points to the first char after '(' in regex */
|
||||||
|
int len; /* Length of the text between '(' and ')' */
|
||||||
|
int branches; /* Index in the branches array for this pair */
|
||||||
|
int num_branches; /* Number of '|' in this bracket pair */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct branch {
|
||||||
|
int bracket_index; /* index for 'struct bracket_pair brackets' */
|
||||||
|
/* array defined below */
|
||||||
|
const char *schlong; /* points to the '|' character in the regex */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct regex_info {
|
||||||
|
/*
|
||||||
|
* Describes all bracket pairs in the regular expression.
|
||||||
|
* First entry is always present, and grabs the whole regex.
|
||||||
|
*/
|
||||||
|
struct bracket_pair brackets[MAX_BRACKETS];
|
||||||
|
int num_brackets;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Describes alternations ('|' operators) in the regular expression.
|
||||||
|
* Each branch falls into a specific branch pair.
|
||||||
|
*/
|
||||||
|
struct branch branches[MAX_BRANCHES];
|
||||||
|
int num_branches;
|
||||||
|
|
||||||
|
/* Array of captures provided by the user */
|
||||||
|
struct slre_cap *caps;
|
||||||
|
int num_caps;
|
||||||
|
|
||||||
|
/* E.g. SLRE_IGNORE_CASE. See enum below */
|
||||||
|
int flags;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int is_metacharacter(const unsigned char *s) {
|
||||||
|
static const char *metacharacters = "^$().[]*+?|\\Ssdbfnrtv";
|
||||||
|
return strchr(metacharacters, *s) != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int op_len(const char *re) {
|
||||||
|
return re[0] == '\\' && re[1] == 'x' ? 4 : re[0] == '\\' ? 2 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int set_len(const char *re, int re_len) {
|
||||||
|
int len = 0;
|
||||||
|
|
||||||
|
while (len < re_len && re[len] != ']') {
|
||||||
|
len += op_len(re + len);
|
||||||
|
}
|
||||||
|
|
||||||
|
return len <= re_len ? len + 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_op_len(const char *re, int re_len) {
|
||||||
|
return re[0] == '[' ? set_len(re + 1, re_len - 1) + 1 : op_len(re);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_quantifier(const char *re) {
|
||||||
|
return re[0] == '*' || re[0] == '+' || re[0] == '?';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int toi(int x) {
|
||||||
|
return isdigit(x) ? x - '0' : x - 'W';
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hextoi(const unsigned char *s) {
|
||||||
|
return (toi(tolower(s[0])) << 4) | toi(tolower(s[1]));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int match_op(const unsigned char *re, const unsigned char *s,
|
||||||
|
struct regex_info *info) {
|
||||||
|
int result = 0;
|
||||||
|
switch (*re) {
|
||||||
|
case '\\':
|
||||||
|
/* Metacharacters */
|
||||||
|
switch (re[1]) {
|
||||||
|
case 'S': FAIL_IF(isspace(*s), SLRE_NO_MATCH); result++; break;
|
||||||
|
case 's': FAIL_IF(!isspace(*s), SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'd': FAIL_IF(!isdigit(*s), SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'b': FAIL_IF(*s != '\b', SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'f': FAIL_IF(*s != '\f', SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'n': FAIL_IF(*s != '\n', SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'r': FAIL_IF(*s != '\r', SLRE_NO_MATCH); result++; break;
|
||||||
|
case 't': FAIL_IF(*s != '\t', SLRE_NO_MATCH); result++; break;
|
||||||
|
case 'v': FAIL_IF(*s != '\v', SLRE_NO_MATCH); result++; break;
|
||||||
|
|
||||||
|
case 'x':
|
||||||
|
/* Match byte, \xHH where HH is hexadecimal byte representaion */
|
||||||
|
FAIL_IF(hextoi(re + 2) != *s, SLRE_NO_MATCH);
|
||||||
|
result++;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/* Valid metacharacter check is done in bar() */
|
||||||
|
FAIL_IF(re[1] != s[0], SLRE_NO_MATCH);
|
||||||
|
result++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '|': FAIL_IF(1, SLRE_INTERNAL_ERROR); break;
|
||||||
|
case '$': FAIL_IF(1, SLRE_NO_MATCH); break;
|
||||||
|
case '.': result++; break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
if (info->flags & SLRE_IGNORE_CASE) {
|
||||||
|
FAIL_IF(tolower(*re) != tolower(*s), SLRE_NO_MATCH);
|
||||||
|
} else {
|
||||||
|
FAIL_IF(*re != *s, SLRE_NO_MATCH);
|
||||||
|
}
|
||||||
|
result++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int match_set(const char *re, int re_len, const char *s,
|
||||||
|
struct regex_info *info) {
|
||||||
|
int len = 0, result = -1, invert = re[0] == '^';
|
||||||
|
|
||||||
|
if (invert) re++, re_len--;
|
||||||
|
|
||||||
|
while (len <= re_len && re[len] != ']' && result <= 0) {
|
||||||
|
/* Support character range */
|
||||||
|
if (re[len] != '-' && re[len + 1] == '-' && re[len + 2] != ']' &&
|
||||||
|
re[len + 2] != '\0') {
|
||||||
|
result = info->flags && SLRE_IGNORE_CASE ?
|
||||||
|
*s >= re[len] && *s <= re[len + 2] :
|
||||||
|
tolower(*s) >= tolower(re[len]) && tolower(*s) <= tolower(re[len + 2]);
|
||||||
|
len += 3;
|
||||||
|
} else {
|
||||||
|
result = match_op((unsigned char *) re + len, (unsigned char *) s, info);
|
||||||
|
len += op_len(re + len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (!invert && result > 0) || (invert && result <= 0) ? 1 : -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int doh(const char *s, int s_len, struct regex_info *info, int bi);
|
||||||
|
|
||||||
|
static int bar(const char *re, int re_len, const char *s, int s_len,
|
||||||
|
struct regex_info *info, int bi) {
|
||||||
|
/* i is offset in re, j is offset in s, bi is brackets index */
|
||||||
|
int i, j, n, step;
|
||||||
|
|
||||||
|
for (i = j = 0; i < re_len && j <= s_len; i += step) {
|
||||||
|
|
||||||
|
/* Handle quantifiers. Get the length of the chunk. */
|
||||||
|
step = re[i] == '(' ? info->brackets[bi + 1].len + 2 :
|
||||||
|
get_op_len(re + i, re_len - i);
|
||||||
|
|
||||||
|
DBG(("%s [%.*s] [%.*s] re_len=%d step=%d i=%d j=%d\n", __func__,
|
||||||
|
re_len - i, re + i, s_len - j, s + j, re_len, step, i, j));
|
||||||
|
|
||||||
|
FAIL_IF(is_quantifier(&re[i]), SLRE_UNEXPECTED_QUANTIFIER);
|
||||||
|
FAIL_IF(step <= 0, SLRE_INVALID_CHARACTER_SET);
|
||||||
|
|
||||||
|
if (i + step < re_len && is_quantifier(re + i + step)) {
|
||||||
|
DBG(("QUANTIFIER: [%.*s]%c [%.*s]\n", step, re + i,
|
||||||
|
re[i + step], s_len - j, s + j));
|
||||||
|
if (re[i + step] == '?') {
|
||||||
|
int result = bar(re + i, step, s + j, s_len - j, info, bi);
|
||||||
|
j += result > 0 ? result : 0;
|
||||||
|
i++;
|
||||||
|
} else if (re[i + step] == '+' || re[i + step] == '*') {
|
||||||
|
int j2 = j, nj = j, n1, n2 = -1, ni, non_greedy = 0;
|
||||||
|
|
||||||
|
/* Points to the regexp code after the quantifier */
|
||||||
|
ni = i + step + 1;
|
||||||
|
if (ni < re_len && re[ni] == '?') {
|
||||||
|
non_greedy = 1;
|
||||||
|
ni++;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if ((n1 = bar(re + i, step, s + j2, s_len - j2, info, bi)) > 0) {
|
||||||
|
j2 += n1;
|
||||||
|
}
|
||||||
|
if (re[i + step] == '+' && n1 < 0) break;
|
||||||
|
|
||||||
|
if (ni >= re_len) {
|
||||||
|
/* After quantifier, there is nothing */
|
||||||
|
nj = j2;
|
||||||
|
} else if ((n2 = bar(re + ni, re_len - ni, s + j2,
|
||||||
|
s_len - j2, info, bi)) >= 0) {
|
||||||
|
/* Regex after quantifier matched */
|
||||||
|
nj = j2 + n2;
|
||||||
|
}
|
||||||
|
if (nj > j && non_greedy) break;
|
||||||
|
} while (n1 > 0);
|
||||||
|
|
||||||
|
if (n1 < 0 && re[i + step] == '*' &&
|
||||||
|
(n2 = bar(re + ni, re_len - ni, s + j, s_len - j, info, bi)) > 0) {
|
||||||
|
nj = j + n2;
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(("STAR/PLUS END: %d %d %d %d %d\n", j, nj, re_len - ni, n1, n2));
|
||||||
|
FAIL_IF(re[i + step] == '+' && nj == j, SLRE_NO_MATCH);
|
||||||
|
|
||||||
|
/* If while loop body above was not executed for the * quantifier, */
|
||||||
|
/* make sure the rest of the regex matches */
|
||||||
|
FAIL_IF(nj == j && ni < re_len && n2 < 0, SLRE_NO_MATCH);
|
||||||
|
|
||||||
|
/* Returning here cause we've matched the rest of RE already */
|
||||||
|
return nj;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (re[i] == '[') {
|
||||||
|
n = match_set(re + i + 1, re_len - (i + 2), s + j, info);
|
||||||
|
DBG(("SET %.*s [%.*s] -> %d\n", step, re + i, s_len - j, s + j, n));
|
||||||
|
FAIL_IF(n <= 0, SLRE_NO_MATCH);
|
||||||
|
j += n;
|
||||||
|
} else if (re[i] == '(') {
|
||||||
|
n = SLRE_NO_MATCH;
|
||||||
|
bi++;
|
||||||
|
FAIL_IF(bi >= info->num_brackets, SLRE_INTERNAL_ERROR);
|
||||||
|
DBG(("CAPTURING [%.*s] [%.*s] [%s]\n",
|
||||||
|
step, re + i, s_len - j, s + j, re + i + step));
|
||||||
|
|
||||||
|
if (re_len - (i + step) <= 0) {
|
||||||
|
/* Nothing follows brackets */
|
||||||
|
n = doh(s + j, s_len - j, info, bi);
|
||||||
|
} else {
|
||||||
|
int j2;
|
||||||
|
for (j2 = 0; j2 <= s_len - j; j2++) {
|
||||||
|
if ((n = doh(s + j, s_len - (j + j2), info, bi)) >= 0 &&
|
||||||
|
bar(re + i + step, re_len - (i + step),
|
||||||
|
s + j + n, s_len - (j + n), info, bi) >= 0) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DBG(("CAPTURED [%.*s] [%.*s]:%d\n", step, re + i, s_len - j, s + j, n));
|
||||||
|
FAIL_IF(n < 0, n);
|
||||||
|
if (info->caps != NULL) {
|
||||||
|
info->caps[bi - 1].ptr = s + j;
|
||||||
|
info->caps[bi - 1].len = n;
|
||||||
|
}
|
||||||
|
j += n;
|
||||||
|
} else if (re[i] == '^') {
|
||||||
|
FAIL_IF(j != 0, SLRE_NO_MATCH);
|
||||||
|
} else if (re[i] == '$') {
|
||||||
|
FAIL_IF(j != s_len, SLRE_NO_MATCH);
|
||||||
|
} else {
|
||||||
|
FAIL_IF(j >= s_len, SLRE_NO_MATCH);
|
||||||
|
n = match_op((unsigned char *) (re + i), (unsigned char *) (s + j), info);
|
||||||
|
FAIL_IF(n <= 0, n);
|
||||||
|
j += n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Process branch points */
|
||||||
|
static int doh(const char *s, int s_len, struct regex_info *info, int bi) {
|
||||||
|
const struct bracket_pair *b = &info->brackets[bi];
|
||||||
|
int i = 0, len, result;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
do {
|
||||||
|
p = i == 0 ? b->ptr : info->branches[b->branches + i - 1].schlong + 1;
|
||||||
|
len = b->num_branches == 0 ? b->len :
|
||||||
|
i == b->num_branches ? (int) (b->ptr + b->len - p) :
|
||||||
|
(int) (info->branches[b->branches + i].schlong - p);
|
||||||
|
DBG(("%s %d %d [%.*s] [%.*s]\n", __func__, bi, i, len, p, s_len, s));
|
||||||
|
result = bar(p, len, s, s_len, info, bi);
|
||||||
|
DBG(("%s <- %d\n", __func__, result));
|
||||||
|
} while (result <= 0 && i++ < b->num_branches); /* At least 1 iteration */
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int baz(const char *s, int s_len, struct regex_info *info) {
|
||||||
|
int i, result = -1, is_anchored = info->brackets[0].ptr[0] == '^';
|
||||||
|
|
||||||
|
for (i = 0; i <= s_len; i++) {
|
||||||
|
result = doh(s + i, s_len - i, info, 0);
|
||||||
|
if (result >= 0) {
|
||||||
|
result += i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (is_anchored) break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void setup_branch_points(struct regex_info *info) {
|
||||||
|
int i, j;
|
||||||
|
struct branch tmp;
|
||||||
|
|
||||||
|
/* First, sort branches. Must be stable, no qsort. Use bubble algo. */
|
||||||
|
for (i = 0; i < info->num_branches; i++) {
|
||||||
|
for (j = i + 1; j < info->num_branches; j++) {
|
||||||
|
if (info->branches[i].bracket_index > info->branches[j].bracket_index) {
|
||||||
|
tmp = info->branches[i];
|
||||||
|
info->branches[i] = info->branches[j];
|
||||||
|
info->branches[j] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* For each bracket, set their branch points. This way, for every bracket
|
||||||
|
* (i.e. every chunk of regex) we know all branch points before matching.
|
||||||
|
*/
|
||||||
|
for (i = j = 0; i < info->num_brackets; i++) {
|
||||||
|
info->brackets[i].num_branches = 0;
|
||||||
|
info->brackets[i].branches = j;
|
||||||
|
while (j < info->num_branches && info->branches[j].bracket_index == i) {
|
||||||
|
info->brackets[i].num_branches++;
|
||||||
|
j++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int foo(const char *re, int re_len, const char *s, int s_len,
|
||||||
|
struct regex_info *info) {
|
||||||
|
int i, step, depth = 0;
|
||||||
|
|
||||||
|
/* First bracket captures everything */
|
||||||
|
info->brackets[0].ptr = re;
|
||||||
|
info->brackets[0].len = re_len;
|
||||||
|
info->num_brackets = 1;
|
||||||
|
|
||||||
|
/* Make a single pass over regex string, memorize brackets and branches */
|
||||||
|
for (i = 0; i < re_len; i += step) {
|
||||||
|
step = get_op_len(re + i, re_len - i);
|
||||||
|
|
||||||
|
if (re[i] == '|') {
|
||||||
|
FAIL_IF(info->num_branches >= (int) ARRAY_SIZE(info->branches),
|
||||||
|
SLRE_TOO_MANY_BRANCHES);
|
||||||
|
info->branches[info->num_branches].bracket_index =
|
||||||
|
info->brackets[info->num_brackets - 1].len == -1 ?
|
||||||
|
info->num_brackets - 1 : depth;
|
||||||
|
info->branches[info->num_branches].schlong = &re[i];
|
||||||
|
info->num_branches++;
|
||||||
|
} else if (re[i] == '\\') {
|
||||||
|
FAIL_IF(i >= re_len - 1, SLRE_INVALID_METACHARACTER);
|
||||||
|
if (re[i + 1] == 'x') {
|
||||||
|
/* Hex digit specification must follow */
|
||||||
|
FAIL_IF(re[i + 1] == 'x' && i >= re_len - 3,
|
||||||
|
SLRE_INVALID_METACHARACTER);
|
||||||
|
FAIL_IF(re[i + 1] == 'x' && !(isxdigit(re[i + 2]) &&
|
||||||
|
isxdigit(re[i + 3])), SLRE_INVALID_METACHARACTER);
|
||||||
|
} else {
|
||||||
|
FAIL_IF(!is_metacharacter((unsigned char *) re + i + 1),
|
||||||
|
SLRE_INVALID_METACHARACTER);
|
||||||
|
}
|
||||||
|
} else if (re[i] == '(') {
|
||||||
|
FAIL_IF(info->num_brackets >= (int) ARRAY_SIZE(info->brackets),
|
||||||
|
SLRE_TOO_MANY_BRACKETS);
|
||||||
|
depth++; /* Order is important here. Depth increments first. */
|
||||||
|
info->brackets[info->num_brackets].ptr = re + i + 1;
|
||||||
|
info->brackets[info->num_brackets].len = -1;
|
||||||
|
info->num_brackets++;
|
||||||
|
FAIL_IF(info->num_caps > 0 && info->num_brackets - 1 > info->num_caps,
|
||||||
|
SLRE_CAPS_ARRAY_TOO_SMALL);
|
||||||
|
} else if (re[i] == ')') {
|
||||||
|
int ind = info->brackets[info->num_brackets - 1].len == -1 ?
|
||||||
|
info->num_brackets - 1 : depth;
|
||||||
|
info->brackets[ind].len = (int) (&re[i] - info->brackets[ind].ptr);
|
||||||
|
DBG(("SETTING BRACKET %d [%.*s]\n",
|
||||||
|
ind, info->brackets[ind].len, info->brackets[ind].ptr));
|
||||||
|
depth--;
|
||||||
|
FAIL_IF(depth < 0, SLRE_UNBALANCED_BRACKETS);
|
||||||
|
FAIL_IF(i > 0 && re[i - 1] == '(', SLRE_NO_MATCH);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FAIL_IF(depth != 0, SLRE_UNBALANCED_BRACKETS);
|
||||||
|
setup_branch_points(info);
|
||||||
|
|
||||||
|
return baz(s, s_len, info);
|
||||||
|
}
|
||||||
|
|
||||||
|
int slre_match(const char *regexp, const char *s, int s_len,
|
||||||
|
struct slre_cap *caps, int num_caps, int flags) {
|
||||||
|
struct regex_info info;
|
||||||
|
|
||||||
|
/* Initialize info structure */
|
||||||
|
info.flags = flags;
|
||||||
|
info.num_brackets = info.num_branches = 0;
|
||||||
|
info.num_caps = num_caps;
|
||||||
|
info.caps = caps;
|
||||||
|
|
||||||
|
DBG(("========================> [%s] [%.*s]\n", regexp, s_len, s));
|
||||||
|
return foo(regexp, (int) strlen(regexp), s, s_len, &info);
|
||||||
|
}
|
||||||
60
src/slre.h
Normal file
60
src/slre.h
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2004-2013 Sergey Lyubka <valenok@gmail.com>
|
||||||
|
* Copyright (c) 2013 Cesanta Software Limited
|
||||||
|
* All rights reserved
|
||||||
|
*
|
||||||
|
* This library is dual-licensed: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License version 2 as
|
||||||
|
* published by the Free Software Foundation. For the terms of this
|
||||||
|
* license, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* You are free to use this library under the terms of the GNU General
|
||||||
|
* Public License, but WITHOUT ANY WARRANTY; without even the implied
|
||||||
|
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* Alternatively, you can license this library under a commercial
|
||||||
|
* license, as set out in <http://cesanta.com/products.html>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This is a regular expression library that implements a subset of Perl RE.
|
||||||
|
* Please refer to README.md for a detailed reference.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SLRE_HEADER_DEFINED
|
||||||
|
#define SLRE_HEADER_DEFINED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct slre_cap {
|
||||||
|
const char *ptr;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
int slre_match(const char *regexp, const char *buf, int buf_len,
|
||||||
|
struct slre_cap *caps, int num_caps, int flags);
|
||||||
|
|
||||||
|
/* Possible flags for slre_match() */
|
||||||
|
enum { SLRE_IGNORE_CASE = 1 };
|
||||||
|
|
||||||
|
|
||||||
|
/* slre_match() failure codes */
|
||||||
|
#define SLRE_NO_MATCH -1
|
||||||
|
#define SLRE_UNEXPECTED_QUANTIFIER -2
|
||||||
|
#define SLRE_UNBALANCED_BRACKETS -3
|
||||||
|
#define SLRE_INTERNAL_ERROR -4
|
||||||
|
#define SLRE_INVALID_CHARACTER_SET -5
|
||||||
|
#define SLRE_INVALID_METACHARACTER -6
|
||||||
|
#define SLRE_CAPS_ARRAY_TOO_SMALL -7
|
||||||
|
#define SLRE_TOO_MANY_BRANCHES -8
|
||||||
|
#define SLRE_TOO_MANY_BRACKETS -9
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SLRE_HEADER_DEFINED */
|
||||||
Loading…
x
Reference in New Issue
Block a user