diff --git a/.vscode/launch.json b/.vscode/launch.json index d3d86ee80..f6a030c7c 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -18,13 +18,21 @@ "text": "-enable-pretty-printing", "ignoreFailures": true } - ] + ], + "windows": { + "processId": "${input:ProcessIDWindows}", + "miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe", + "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while + "environment": [{ + "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" + }] + } },{ "name": "(gdb) Build & Launch", "type": "cppdbg", "request": "launch", "program": "${cwd}/client/proxmark3", - "args": ["/dev/ttyACM0"], + "args": ["/dev/ttyACM0"], "stopAtEntry": false, "cwd": "${workspaceFolder}", "environment": [], @@ -38,7 +46,15 @@ } ], "preLaunchTask": "client: Debug: clean & make", - "miDebuggerPath": "/usr/bin/gdb" + "miDebuggerPath": "/usr/bin/gdb", + "windows": { + "args": ["COM5"], + "miDebuggerPath": "${workspaceFolder}/../../msys2/mingw64/bin/gdb.exe", + "externalConsole": true,//for ProxSpace externalConsole=true is required, because the internal cosole stops updating after a while + "environment": [{ + "name": "PATH","value": "${workspaceFolder}/../../msys2/mingw64/bin;${workspaceFolder}/../../msys2/usr/local/bin;${workspaceFolder}/../../msys2/usr/bin;${workspaceFolder}/../../msys2/bin" + }] + } } ], "inputs": [ @@ -50,6 +66,15 @@ "args": { "command": "pgrep -n proxmark3", } + + },{ + "id": "ProcessIDWindows", + "type": "command", + "command": "shellCommand.execute", + "args": { + "command": "${workspaceFolder}/../../runme64.bat -c \"cat /proc/$(pgrep -n proxmark3)/winpid\"", + } + } ] } \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json index 155aa80cd..7354a8a2d 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -7,6 +7,18 @@ "label": "all: Make & run", "type": "shell", "command": "make -j && ./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [ "$gcc" ], @@ -19,6 +31,18 @@ "label": "choose: Make", "type": "shell", "command": "make ${input:componentType} -j", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [ "$gcc" ], @@ -28,6 +52,18 @@ "label": "client: Debug: make", "type": "shell", "command": "make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [ "$gcc" ], @@ -37,6 +73,18 @@ "label": "client: Debug: clean & make", "type": "shell", "command": "make client/clean && make client -j DEBUG=1", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [ "$gcc" ], @@ -46,18 +94,54 @@ "label": "fullimage: Make & Flash", "type": "shell", "command": "make fullimage && ./pm3-flash-fullimage", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [] }, { "label": "BOOTROM: Make & Flash", "type": "shell", "command": "make bootrom && ./pm3-flash-bootrom", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [] }, { "label": "Run client", "type": "shell", "command": "./pm3", + "windows": { + "options": { + "cwd": "${workspaceFolder}/../..", + "shell": { + "executable": "${workspaceFolder}/../../runme64.bat", + "args": [ + "-c \"cd ${workspaceFolderBasename} &&" + ], + + } + } + }, "problemMatcher": [] } ], diff --git a/CHANGELOG.md b/CHANGELOG.md index e63bead6f..e9bb8d98f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,10 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'hf iclass wrbl' - dealing with tags in unsecured vs secured pagemode now is correct (@iceman1001) - Change many commands to cliparser (@iceman1001, @tcprst, @mwalker33,...) - ... + - Added compilation options for 256k Proxmark versions, see doc (@doegox) - Added support for 10b UID in `hf 14a sim` (@doegox) - Added `HF_TCPRST` standalone mode which read and emulate IKEA Rothult cards (@tcprst) - Add Gallagher key checking/KDF on MIFARE Desfire (@NZSmartie) diff --git a/Makefile.defs b/Makefile.defs index 16d5ec9e5..48567214b 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -27,7 +27,7 @@ LD = g++ SH = sh BASH = bash PERL = perl -CCC =foo +SWIG = swig CC_VERSION = $(shell $(CC) -dumpversion 2>/dev/null|sed 's/\..*//') CC_VERSION := $(or $(strip $(CC_VERSION)),0) diff --git a/README.md b/README.md index 330faaef6..e61260b54 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ |[Notes on file formats used with Proxmark3](/doc/extensions_notes.md)|[Notes on MFU binary format](/doc/mfu_binary_format_notes.md)|[Notes on FPGA & ARM](/doc/fpga_arm_notes.md)| |[Developing standalone mode](/armsrc/Standalone/readme.md)|[Wiki about standalone mode](https://github.com/RfidResearchGroup/proxmark3/wiki/Standalone-mode)|[Notes on Magic cards](/doc/magic_cards_notes.md)| |[Notes on Color usage](/doc/colors_notes.md)|[Makefile vs CMake](/doc/md/Development/Makefile-vs-CMake.md)|[Notes on Cloner guns](/doc/cloner_notes.md)| -|[Notes on cliparser usage](/doc/cliparser.md)||| +|[Notes on cliparser usage](/doc/cliparser.md)|[Notes on clocks](/doc/clocks.md)|| ## Build for non-RDV4 Proxmark3 platforms @@ -57,7 +57,7 @@ On the software side: quite a lot, see the [Changelog file](CHANGELOG.md). This repo compiles nicely on - Proxspace v3.x - - [latest release v3.7](https://github.com/Gator96100/ProxSpace/releases) + - [latest release v3.7.1](https://github.com/Gator96100/ProxSpace/releases) - Windows/mingw environment with Qt5.6.1 & GCC 4.9 - Ubuntu 16.04 -> 20.04 - ParrotOS, Gentoo, Pentoo, Kali, Nethunter, Archlinux, Fedora, Debian diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 03f7dcbba..86d8094b7 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1776,13 +1776,19 @@ void iClass_Dump(uint8_t *msg) { BigBuf_free(); } -static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac) { +static bool iclass_writeblock_ext(uint8_t blockno, uint8_t *data, uint8_t *mac, bool use_mac) { // write command: cmd, 1 blockno, 8 data, 4 mac - uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, blockno }; + uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, blockno }; + uint8_t write_len = 14; memcpy(write + 2, data, 8); - memcpy(write + 10, mac, 4); - AddCrc(write + 1, 13); + + if (use_mac) { + memcpy(write + 10, mac, 4); + } else { + AddCrc(write + 1, 9); + write_len -= 2; + } uint8_t resp[10] = {0}; uint32_t eof_time = 0, start_time = 0; @@ -1819,7 +1825,8 @@ void iClass_WriteBlock(uint8_t *msg) { iclass_writeblock_req_t *payload = (iclass_writeblock_req_t *)msg; - uint8_t write[16] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno }; + uint8_t write[14] = { 0x80 | ICLASS_CMD_UPDATE, payload->req.blockno }; + uint8_t write_len = 14; Iso15693InitReader(); @@ -1844,23 +1851,30 @@ void iClass_WriteBlock(uint8_t *msg) { } } - // calc new mac for write - uint8_t wb[9]; - wb[0] = payload->req.blockno; - memcpy(wb + 1, payload->data, 8); + // new block data + memcpy(write + 2, payload->data, 8); - if (payload->req.use_replay) { - doMAC_N(wb, sizeof(wb), payload->req.key + 4, mac); + uint8_t pagemap = get_pagemap(&hdr); + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { + // Unsecured tags uses CRC16, but don't include the UPDATE operation code + // byte0 = update op + // byte1 = block no + // byte2..9 = new block data + AddCrc(write + 1, 9); + write_len -= 2; } else { + // Secure tags uses MAC + uint8_t wb[9]; + wb[0] = payload->req.blockno; + memcpy(wb + 1, payload->data, 8); + if (payload->req.use_credit_key) doMAC_N(wb, sizeof(wb), hdr.key_c, mac); else doMAC_N(wb, sizeof(wb), hdr.key_d, mac); - } - memcpy(write + 2, payload->data, 8); // data - memcpy(write + 10, mac, sizeof(mac)); // mac - AddCrc(write + 1, 13); + memcpy(write + 10, mac, sizeof(mac)); + } start_time = eof_time + DELAY_ICLASS_VICC_TO_VCD_READER; @@ -1869,7 +1883,7 @@ void iClass_WriteBlock(uint8_t *msg) { uint8_t tries = 3; while (tries-- > 0) { - iclass_send_as_reader(write, sizeof(write), &start_time, &eof_time); + iclass_send_as_reader(write, write_len, &start_time, &eof_time); if (tearoff_hook() == PM3_ETEAROFF) { // tearoff occured res = false; @@ -1961,22 +1975,30 @@ void iClass_Restore(iclass_restore_req_t *msg) { } // main loop + bool use_mac; for (uint8_t i = 0; i < msg->item_cnt; i++) { iclass_restore_item_t item = msg->blocks[i]; - // calc new mac for data, using 1b blockno, 8b data, - uint8_t wb[9] = {0}; - wb[0] = item.blockno; - memcpy(wb + 1, item.data, 8); + uint8_t pagemap = get_pagemap(&hdr); + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { + // Unsecured tags uses CRC16 + use_mac = false; + } else { + // Secure tags uses MAC + use_mac = true; + uint8_t wb[9] = {0}; + wb[0] = item.blockno; + memcpy(wb + 1, item.data, 8); - if (msg->req.use_credit_key) - doMAC_N(wb, sizeof(wb), hdr.key_c, mac); - else - doMAC_N(wb, sizeof(wb), hdr.key_d, mac); + if (msg->req.use_credit_key) + doMAC_N(wb, sizeof(wb), hdr.key_c, mac); + else + doMAC_N(wb, sizeof(wb), hdr.key_d, mac); + } // data + mac - if (iclass_writeblock_ext(item.blockno, item.data, mac)) { + if (iclass_writeblock_ext(item.blockno, item.data, mac, use_mac)) { Dbprintf("Write block [%02x] " _GREEN_("successful"), item.blockno); written++; } else { diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index a70b9b953..806c63091 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -1301,7 +1301,7 @@ void SimulateIso14443aTag(uint8_t tagType, uint8_t flags, uint8_t *data) { // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - iso14a_set_timeout(201400); // 106 * 19ms default + iso14a_set_timeout(201400); // 106 * 19ms default *100? int len = 0; @@ -2903,9 +2903,11 @@ void ReaderIso14443a(PacketCommandNG *c) { goto OUT; } } - - if ((param & ISO14A_SET_TIMEOUT)) + uint32_t save_iso14a_timeout = 0; + if ((param & ISO14A_SET_TIMEOUT)) { + save_iso14a_timeout = iso14a_get_timeout(); iso14a_set_timeout(timeout); + } if ((param & ISO14A_APDU)) { uint8_t res; @@ -2969,6 +2971,10 @@ void ReaderIso14443a(PacketCommandNG *c) { if ((param & ISO14A_REQUEST_TRIGGER)) iso14a_set_trigger(false); + if ((param & ISO14A_SET_TIMEOUT)) { + iso14a_set_timeout(save_iso14a_timeout); + } + if ((param & ISO14A_NO_DISCONNECT)) return; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 36fb7455c..7faa0c268 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -2082,9 +2082,10 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain) { if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { if (DBGLEVEL >= DBG_ERROR) Dbprintf("Can't select card"); errormsg = MAGIC_UID; + mifare_classic_halt_ex(NULL); + break; } mifare_classic_halt_ex(NULL); - break; } // wipe tag, fill it with zeros diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index ed5802185..92888a0fa 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -188,7 +188,6 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/emv/crypto.c ${PM3_ROOT}/client/src/emv/crypto_polarssl.c ${PM3_ROOT}/client/src/emv/dol.c - ${PM3_ROOT}/client/src/emv/dump.c ${PM3_ROOT}/client/src/emv/emv_pk.c ${PM3_ROOT}/client/src/emv/emv_pki.c ${PM3_ROOT}/client/src/emv/emv_pki_priv.c @@ -289,6 +288,7 @@ set (TARGET_SOURCES ${PM3_ROOT}/client/src/graph.c ${PM3_ROOT}/client/src/jansson_path.c ${PM3_ROOT}/client/src/preferences.c + ${PM3_ROOT}/client/src/pm3.c ${PM3_ROOT}/client/src/pm3_binlib.c ${PM3_ROOT}/client/src/pm3_bitlib.c ${PM3_ROOT}/client/src/prng.c @@ -361,7 +361,7 @@ if (NOT SKIPPYTHON EQUAL 1) add_definitions(-DHAVE_PYTHON) set(ADDITIONAL_DIRS ${PYTHON3_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) set(ADDITIONAL_LNK ${PYTHON3_LIBRARIES} ${ADDITIONAL_LNK}) - set(ADDITIONAL_LNKDIRS ${PYTHON3_LIBRARY_DIRS} ${ADDITIONAL_LNKDIRS}) + set(ADDITIONAL_LNKDIRS ${PYTHON3_LIBRARY_DIRS} ${ADDITIONAL_LNKDIRS}) endif (PYTHON3EMBED_FOUND) endif (NOT SKIPPYTHON EQUAL 1) @@ -425,7 +425,7 @@ if (SKIPPYTHON EQUAL 1) else (SKIPPYTHON EQUAL 1) if (PYTHON3EMBED_FOUND) message(STATUS "Python3 library: Python3 embed found, enabled") - elseif (PYTHON_FOUND) + elseif (PYTHON3_FOUND) message(STATUS "Python3 library: Python3 found, enabled") else (PYTHON3EMBED_FOUND) message(STATUS "Python3 library: Python3 not found, disabled") @@ -455,6 +455,28 @@ else (SKIPWHEREAMISYSTEM EQUAL 1) message(STATUS "Whereami library: system library not found, using local library") endif (WHEREAMI_FOUND) endif (SKIPWHEREAMISYSTEM EQUAL 1) + +# Lua SWIG +if (EXISTS ${PM3_ROOT}/client/src/pm3_luawrap.c) + set (TARGET_SOURCES + ${PM3_ROOT}/client/src/pm3_luawrap.c + ${TARGET_SOURCES}) + add_definitions(-DHAVE_LUA_SWIG) + message(STATUS "Lua SWIG: wrapper found") +endif (EXISTS ${PM3_ROOT}/client/src/pm3_luawrap.c) + +# Python SWIG +if (NOT SKIPPYTHON EQUAL 1) + if (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) + if (EXISTS ${PM3_ROOT}/client/src/pm3_pywrap.c) + set (TARGET_SOURCES + ${PM3_ROOT}/client/src/pm3_pywrap.c + ${TARGET_SOURCES}) + add_definitions(-DHAVE_PYTHON_SWIG) + message(STATUS "Python SWIG: wrapper found") + endif (EXISTS ${PM3_ROOT}/client/src/pm3_pywrap.c) + endif (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) +endif (NOT SKIPPYTHON EQUAL 1) message(STATUS "===================================================================") add_executable(proxmark3 diff --git a/client/Makefile b/client/Makefile index dcfadb340..2f0899bc8 100644 --- a/client/Makefile +++ b/client/Makefile @@ -285,11 +285,24 @@ ifneq ($(SKIPREADLINE),1) READLINE_FOUND = 1 endif +######## +# SWIG # +######## + +ifneq ("$(wildcard src/pm3_luawrap.c)","") + SWIG_LUA_FOUND = 1 +endif +ifeq ($(PYTHON_FOUND),1) + ifneq ("$(wildcard src/pm3_pywrap.c)","") + SWIG_PYTHON_FOUND = 1 + endif +endif + ####################################################################################################### CFLAGS ?= $(DEFCFLAGS) # We cannot just use CFLAGS+=... because it has impact on sub-makes if CFLAGS is defined in env: PM3CFLAGS = $(CFLAGS) -PM3CFLAGS += -I./src -I../include -I../common -I../common_fpga $(INCLUDES) +PM3CFLAGS += -I./src -I./include -I../include -I../common -I../common_fpga $(INCLUDES) # WIP Testing #PM3CFLAGS += -std=c11 -pedantic @@ -315,10 +328,16 @@ ifeq ($(PYTHON_FOUND),1) PM3CFLAGS += -DHAVE_PYTHON endif +ifeq ($(SWIG_LUA_FOUND),1) + PM3CFLAGS += -DHAVE_LUA_SWIG +endif +ifeq ($(SWIG_PYTHON_FOUND),1) + PM3CFLAGS += -DHAVE_PYTHON_SWIG +endif CXXFLAGS ?= -Wall -Werror -O3 PM3CXXFLAGS = $(CXXFLAGS) -PM3CXXFLAGS += -I../include +PM3CXXFLAGS += -I../include -I./include ifeq ($(QT_FOUND),1) PM3CFLAGS += -DHAVE_GUI @@ -414,6 +433,13 @@ else endif endif +ifeq ($(SWIG_LUA_FOUND),1) + $(info Lua SWIG: wrapper found) +endif +ifeq ($(SWIG_PYTHON_FOUND),1) + $(info Python SWIG: wrapper found) +endif + $(info compiler version: $(shell $(CC) --version|head -n 1)) $(info ===================================================================) @@ -506,7 +532,6 @@ SRCS = aiddesfire.c \ emv/crypto.c\ emv/crypto_polarssl.c\ emv/dol.c \ - emv/dump.c \ emv/emv_pk.c\ emv/emv_pki.c\ emv/emv_pki_priv.c\ @@ -540,6 +565,7 @@ SRCS = aiddesfire.c \ mifare/mifaredefault.c \ mifare/mifarehost.c \ mifare/ndef.c \ + pm3.c \ pm3_binlib.c \ pm3_bitlib.c \ preferences.c \ @@ -572,6 +598,16 @@ SRCS += bucketsort.c \ parity.c \ util_posix.c +# swig + +SWIGSRCS = +ifeq ($(SWIG_LUA_FOUND),1) + SWIGSRCS += pm3_luawrap.c +endif +ifeq ($(SWIG_PYTHON_FOUND),1) + SWIGSRCS += pm3_pywrap.c +endif + # gui ifeq ($(QT_FOUND),1) CXXSRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp @@ -585,6 +621,7 @@ ifeq ($(platform),Darwin) endif OBJS = $(SRCS:%.c=$(OBJDIR)/%.o) +OBJS += $(SWIGSRCS:%.c=$(OBJDIR)/%.o) OBJS += $(CXXSRCS:%.cpp=$(OBJDIR)/%.o) OBJS += $(OBJCSRCS:%.m=$(OBJDIR)/%.o) @@ -649,6 +686,7 @@ endif ifneq (,$(INSTALLSHARE)) $(Q)$(MKDIR) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) $(Q)$(CP) $(INSTALLSHARE) $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH) + $(Q)$(CP) src/pm3.py $(DESTDIR)$(PREFIX)$(PATHSEP)$(INSTALLSHARERELPATH)/pyscripts endif @true @@ -711,6 +749,18 @@ ifneq ($(WHEREAMI_FOUND),1) $(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all endif +######## +# SWIG # +######## + +src/pm3_luawrap.c: pm3.i + $(info [=] GEN $@) + $(Q)$(SWIG) -lua -o $@ $< + +src/pm3_pywrap.c: pm3.i + $(info [=] GEN $@) + $(Q)$(SWIG) -python -o $@ $< + ######## # misc # ######## @@ -725,6 +775,14 @@ src/version.c: default_version.c # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) +# SWIG files emit a number of warnings, we've to ignore them +%wrap.o: %wrap.c +$(OBJDIR)/%wrap.o : %wrap.c $(OBJDIR)/%.d + $(info [-] CC $<) + $(Q)$(MKDIR) $(dir $@) + $(Q)$(CC) $(DEPFLAGS) $(PM3CFLAGS) -Wno-missing-prototypes -Wno-missing-declarations -Wno-missing-field-initializers -c -o $@ $< + $(Q)$(POSTCOMPILE) + %.o: %.c $(OBJDIR)/%.o : %.c $(OBJDIR)/%.d $(info [-] CC $<) @@ -747,6 +805,7 @@ $(OBJDIR)/%.o : %.m $(OBJDIR)/%.d $(Q)$(POSTCOMPILE) DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(SRCS)) \ + $(patsubst %wrap.c, $(OBJDIR)/%.d, $(SWIGSRCS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(CXXSRCS)) \ $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) diff --git a/client/android/CMakeLists.txt b/client/android/CMakeLists.txt index 3df923c3c..f459748b2 100644 --- a/client/android/CMakeLists.txt +++ b/client/android/CMakeLists.txt @@ -66,7 +66,6 @@ add_library(pm3rrg_rdv4 SHARED ${PM3_ROOT}/client/src/emv/crypto.c ${PM3_ROOT}/client/src/emv/crypto_polarssl.c ${PM3_ROOT}/client/src/emv/dol.c - ${PM3_ROOT}/client/src/emv/dump.c ${PM3_ROOT}/client/src/emv/emv_pk.c ${PM3_ROOT}/client/src/emv/emv_pki.c ${PM3_ROOT}/client/src/emv/emv_pki_priv.c diff --git a/client/android/pm3_main.c b/client/android/pm3_main.c index 5fa056a44..3d2ef917d 100644 --- a/client/android/pm3_main.c +++ b/client/android/pm3_main.c @@ -64,7 +64,7 @@ int push_cmdscriptfile(char *path, bool stayafter) { return PM3_SUCCESS; } static bool OpenPm3(void) { if (conn.run) { return true; } // Open with LocalSocket. Not a tcp connection! - bool ret = OpenProxmark("socket:"PM3_LOCAL_SOCKET_SERVER, false, 1000, false, 115200); + bool ret = OpenProxmark(session.current_device, "socket:"PM3_LOCAL_SOCKET_SERVER, false, 1000, false, 115200); return ret; } diff --git a/client/deps/cliparser/cliparser.c b/client/deps/cliparser/cliparser.c index f2d9fa8fd..f55b7a8f7 100644 --- a/client/deps/cliparser/cliparser.c +++ b/client/deps/cliparser/cliparser.c @@ -35,8 +35,7 @@ int CLIParserInit(CLIParserContext **ctx, const char *vprogramName, const char *vprogramHint, const char *vprogramHelp) { *ctx = malloc(sizeof(CLIParserContext)); if (!*ctx) { - printf("ERROR: Insufficient memory\n"); - fflush(stdout); + PrintAndLogEx(ERR, "ERROR: Insufficient memory\n"); return 2; } (*ctx)->argtable = NULL; @@ -220,16 +219,15 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int res = param_gethex_to_eol((char *)tmpstr, 0, data, maxdatalen, datalen); switch (res) { case 1: - printf("Parameter error: Invalid HEX value\n"); + PrintAndLogEx(ERR, "Parameter error: Invalid HEX value\n"); break; case 2: - printf("Parameter error: parameter too large\n"); + PrintAndLogEx(ERR, "Parameter error: parameter too large\n"); break; case 3: - printf("Parameter error: Hex string must have EVEN number of digits\n"); + PrintAndLogEx(ERR, "Parameter error: Hex string must have EVEN number of digits\n"); break; } - fflush(stdout); return res; } @@ -246,8 +244,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int int len = strlen(argstr->sval[i]); if (len > ((sizeof(tmpstr) / 2) - ibuf)) { - printf("Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2)); - fflush(stdout); + PrintAndLogEx(ERR, "Parameter error: string too long (%i chars), expect MAX %zu chars\n", len + ibuf, (sizeof(tmpstr) / 2)); return 2; } @@ -263,8 +260,7 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; if (ibuf > maxdatalen) { - printf("Parameter error: string too long (%i chars), expected MAX %i chars\n", ibuf, maxdatalen); - fflush(stdout); + PrintAndLogEx(ERR, "Parameter error: string too long (%i chars), expected MAX %i chars\n", ibuf, maxdatalen); return 2; } diff --git a/client/deps/hardnested.cmake b/client/deps/hardnested.cmake index f9248b82d..dc569641c 100644 --- a/client/deps/hardnested.cmake +++ b/client/deps/hardnested.cmake @@ -118,6 +118,7 @@ set_property(TARGET pm3rrg_rdv4_hardnested PROPERTY POSITION_INDEPENDENT_CODE ON target_include_directories(pm3rrg_rdv4_hardnested PRIVATE ../../common ../../include + ../include ../src jansson) target_include_directories(pm3rrg_rdv4_hardnested INTERFACE hardnested) diff --git a/client/deps/hardnested/Makefile b/client/deps/hardnested/Makefile index 079516977..624eb730f 100644 --- a/client/deps/hardnested/Makefile +++ b/client/deps/hardnested/Makefile @@ -1,5 +1,5 @@ MYSRCPATHS = -MYINCLUDES = -I../../../common -I../../../include -I../../src -I../jansson +MYINCLUDES = -I../../../common -I../../../include -I../../src -I../../include -I../jansson MYCFLAGS = MYDEFS = MYSRCS = hardnested_bruteforce.c diff --git a/client/dictionaries/mfc_default_keys.dic b/client/dictionaries/mfc_default_keys.dic index 8c9611c56..b3bf93312 100644 --- a/client/dictionaries/mfc_default_keys.dic +++ b/client/dictionaries/mfc_default_keys.dic @@ -1132,8 +1132,6 @@ e2a9e88bfe16 aade86b1f9c1 5ea088c824c9 c67beb41ffbf -5ea088c824c9 -c67beb41ffbf b84d52971107 52b0d3f6116e # @@ -1209,3 +1207,72 @@ FEE2A3FBC5B6 0602721E8F06 FC0B50AF8700 F7BA51A9434E +# +# eskart +# eskisehir transport card +E902395C1744 +4051A85E7F2D +7357EBD483CC +D8BA1AA9ABA0 +76939DDD9E97 +3BF391815A8D +# +# muzekart +# museum card for turkey +7C87013A648A +E8794FB14C63 +9F97C182585B +EC070A52E539 +C229CE5123D5 +E495D6E69D9C +26BF1A68B00F +B1D3BC5A7CCA +734EBE504CE8 +974A36E2B1BA +C197AE6D6990 +4D80A10649DF +037F64F470AD +C9CD8D7C65E5 +B70B1957FE71 +CE7712C5071D +C0AD1B72921A +45FEE09C1D06 +E592ED478E59 +F3C1F1DB1D83 +704A81DDACED +89E00BC444EF +AFAAFCC40DEC +ECC58C5D34CA +57D83754711D +D0DDDF2933EC +240F0BB84681 +9E7168064993 +2F8A867B06B4 +# +# bursakart +# bursa transport card +# +A0A1A2A3A4A5 +755D49191A78 +DAC7E0CBA8FD +68D3263A8CD6 +865B6472B1C0 +0860318A3A89 +1927A45A83D3 +B2FE3B2875A6 +# +# playland +# maltepe park +# +ABCC1276FCB0 +AABAFFCC7612 +# +# lunasan +# kocaeli fair +# +26107E7006A0 +# +# gamefactory +# ozdilek +# +17D071403C20 \ No newline at end of file diff --git a/client/experimental_client_with_swig/00make_swig.sh b/client/experimental_client_with_swig/00make_swig.sh new file mode 100755 index 000000000..626a87986 --- /dev/null +++ b/client/experimental_client_with_swig/00make_swig.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd .. +make src/pm3_luawrap.c +make src/pm3_pywrap.c diff --git a/client/experimental_client_with_swig/01make_client_cmake.sh b/client/experimental_client_with_swig/01make_client_cmake.sh new file mode 100755 index 000000000..48a5bd4f2 --- /dev/null +++ b/client/experimental_client_with_swig/01make_client_cmake.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +cd .. +rm -rf build +mkdir build +( + cd build + cmake .. + make -j +) diff --git a/client/experimental_client_with_swig/01make_client_cmake_continue.sh b/client/experimental_client_with_swig/01make_client_cmake_continue.sh new file mode 100755 index 000000000..abd022c97 --- /dev/null +++ b/client/experimental_client_with_swig/01make_client_cmake_continue.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +cd .. +( + cd build + make -j +) diff --git a/client/experimental_client_with_swig/01make_client_makefile.sh b/client/experimental_client_with_swig/01make_client_makefile.sh new file mode 100755 index 000000000..93ab04ca2 --- /dev/null +++ b/client/experimental_client_with_swig/01make_client_makefile.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +cd .. +make -j diff --git a/client/experimental_client_with_swig/02a_run_test_lua.sh b/client/experimental_client_with_swig/02a_run_test_lua.sh new file mode 100755 index 000000000..8e04b30f5 --- /dev/null +++ b/client/experimental_client_with_swig/02a_run_test_lua.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +../../pm3 -c "script run testembedded.lua" diff --git a/client/experimental_client_with_swig/02b_run_test_py.sh b/client/experimental_client_with_swig/02b_run_test_py.sh new file mode 100755 index 000000000..e613a6adf --- /dev/null +++ b/client/experimental_client_with_swig/02b_run_test_py.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +../../pm3 -c "script run testembedded.py" diff --git a/client/experimental_client_with_swig/02b_run_test_py_grabber.sh b/client/experimental_client_with_swig/02b_run_test_py_grabber.sh new file mode 100755 index 000000000..8aed5b8bb --- /dev/null +++ b/client/experimental_client_with_swig/02b_run_test_py_grabber.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +../../pm3 -c "script run testembedded_grab.py" -i diff --git a/client/experimental_client_with_swig/output_grabber.py b/client/experimental_client_with_swig/output_grabber.py new file mode 100755 index 000000000..ad405c9d9 --- /dev/null +++ b/client/experimental_client_with_swig/output_grabber.py @@ -0,0 +1,78 @@ +import os +import sys +import threading +import time + +# From https://stackoverflow.com/a/29834357 +class OutputGrabber(object): + """ + Class used to grab standard output or another stream. + """ + escape_char = "\b" + + def __init__(self, stream=None, threaded=False): + self.origstream = stream + self.threaded = threaded + if self.origstream is None: + self.origstream = sys.stdout + self.origstreamfd = self.origstream.fileno() + self.capturedtext = "" + # Create a pipe so the stream can be captured: + self.pipe_out, self.pipe_in = os.pipe() + + def __enter__(self): + self.start() + return self + + def __exit__(self, type, value, traceback): + self.stop() + + def start(self): + """ + Start capturing the stream data. + """ + self.capturedtext = "" + # Save a copy of the stream: + self.streamfd = os.dup(self.origstreamfd) + # Replace the original stream with our write pipe: + os.dup2(self.pipe_in, self.origstreamfd) + if self.threaded: + # Start thread that will read the stream: + self.workerThread = threading.Thread(target=self.readOutput) + self.workerThread.start() + # Make sure that the thread is running and os.read() has executed: + time.sleep(0.01) + + def stop(self): + """ + Stop capturing the stream data and save the text in `capturedtext`. + """ + # Print the escape character to make the readOutput method stop: + self.origstream.write(self.escape_char) + # Flush the stream to make sure all our data goes in before + # the escape character: + self.origstream.flush() + if self.threaded: + # wait until the thread finishes so we are sure that + # we have until the last character: + self.workerThread.join() + else: + self.readOutput() + # Close the pipe: + os.close(self.pipe_in) + os.close(self.pipe_out) + # Restore the original stream: + os.dup2(self.streamfd, self.origstreamfd) + # Close the duplicate stream: + os.close(self.streamfd) + + def readOutput(self): + """ + Read the stream data (one byte at a time) + and save the text in `capturedtext`. + """ + while True: + char = os.read(self.pipe_out,1).decode(self.origstream.encoding) + if not char or self.escape_char in char: + break + self.capturedtext += char diff --git a/client/experimental_client_with_swig/testembedded.lua b/client/experimental_client_with_swig/testembedded.lua new file mode 100755 index 000000000..469bfff7a --- /dev/null +++ b/client/experimental_client_with_swig/testembedded.lua @@ -0,0 +1,4 @@ +local pm3 = require("pm3") +p=pm3.pm3() +p:console("hw status") +print(p.name) diff --git a/client/experimental_client_with_swig/testembedded.py b/client/experimental_client_with_swig/testembedded.py new file mode 100755 index 000000000..12ae8b741 --- /dev/null +++ b/client/experimental_client_with_swig/testembedded.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import pm3 +p=pm3.pm3() +p.console("hw status") +print("Device:", p.name) diff --git a/client/experimental_client_with_swig/testembedded_grab.py b/client/experimental_client_with_swig/testembedded_grab.py new file mode 100755 index 000000000..caec75769 --- /dev/null +++ b/client/experimental_client_with_swig/testembedded_grab.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import pm3 +from output_grabber import OutputGrabber + +out = OutputGrabber() +p=pm3.pm3() +print("Device:", p.name) +with out: + p.console("hw status") +for line in out.capturedtext.split('\n'): + if "Unique ID" in line: + print(line) diff --git a/client/experimental_lib/.gitignore b/client/experimental_lib/.gitignore new file mode 100644 index 000000000..567609b12 --- /dev/null +++ b/client/experimental_lib/.gitignore @@ -0,0 +1 @@ +build/ diff --git a/client/experimental_lib/00make_swig.sh b/client/experimental_lib/00make_swig.sh new file mode 100755 index 000000000..626a87986 --- /dev/null +++ b/client/experimental_lib/00make_swig.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +cd .. +make src/pm3_luawrap.c +make src/pm3_pywrap.c diff --git a/client/experimental_lib/01make_lib_continue.sh b/client/experimental_lib/01make_lib_continue.sh new file mode 100755 index 000000000..7869bdefa --- /dev/null +++ b/client/experimental_lib/01make_lib_continue.sh @@ -0,0 +1,7 @@ +#!/bin/bash + +( + cd build + make -j +) + diff --git a/client/experimental_lib/CMakeLists.txt b/client/experimental_lib/CMakeLists.txt new file mode 100644 index 000000000..2bc02fd4b --- /dev/null +++ b/client/experimental_lib/CMakeLists.txt @@ -0,0 +1,556 @@ +# Usage: +# mkdir build +# cd build +# cmake .. (see below for options) +# make (VERBOSE=1 if needed) +# +# MINGW: +# On ProxSpace 3.4: +# cmake -G"MSYS Makefiles" .. +# On Proxspace 3.3 or less, you need to install cmake: +# pacman -S mingw-w64-x86_64-cmake +# /mingw64/bin/cmake -G"MSYS Makefiles" .. +# +# Android cross-compilation: (ANDROID_ABI=arm64-v8a for a 64b version) +# cmake \ +# -DCMAKE_TOOLCHAIN_FILE=/build/cmake/android.toolchain.cmake \ +# -DANDROID_ABI=armeabi-v7a \ +# -DANDROID_NATIVE_API_LEVEL=android-19 \ +# -DSKIPBT=1 -DSKIPPYTHON=1 -DSKIPPTHREAD=1 .. + +message(STATUS "CMake ${CMAKE_VERSION}") +cmake_minimum_required(VERSION 3.10) +project(proxmark3) +SET (PM3_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..) + +if(CMAKE_VERSION VERSION_LESS "3.7.0") + set(CMAKE_INCLUDE_CURRENT_DIR ON) +endif() + +find_package(PkgConfig) + +if (NOT SKIPQT EQUAL 1) + if(APPLE AND EXISTS /usr/local/opt/qt5) + # Homebrew installs Qt5 (up to at least 5.11.0) in + # /usr/local/qt5. Ensure that it can be found by CMake + # since it is not in the default /usr/local prefix. + # Add it to PATHS so that it doesn't override the + # CMAKE_PREFIX_PATH environment variable. + # QT_FIND_PACKAGE_OPTIONS should be passed to find_package, + # e.g. find_package(Qt5Core ${QT_FIND_PACKAGE_OPTIONS}) + list(APPEND QT_FIND_PACKAGE_OPTIONS PATHS /usr/local/opt/qt5) + endif(APPLE AND EXISTS /usr/local/opt/qt5) + set(QT_PACKAGELIST + Qt5Core + Qt5Widgets + Qt5Gui + ) + set(Qt5_FOUND ON) + foreach(_qt_package IN LISTS QT_PACKAGELIST) + find_package(${_qt_package} QUIET ${QT_FIND_PACKAGE_OPTIONS}) + set(Qt5_LIBRARIES ${${_qt_package}_LIBRARIES} ${Qt5_LIBRARIES}) + if(NOT ${_qt_package}_FOUND) + set(Qt5_FOUND OFF) + endif(NOT ${_qt_package}_FOUND) + endforeach() +endif (NOT SKIPQT EQUAL 1) + +if (NOT SKIPBT EQUAL 1) + pkg_search_module(BLUEZ QUIET bluez) +endif (NOT SKIPBT EQUAL 1) + +if (NOT SKIPPYTHON EQUAL 1) + pkg_search_module(PYTHON3 QUIET python3) + pkg_search_module(PYTHON3EMBED QUIET python3-embed) +endif (NOT SKIPPYTHON EQUAL 1) + +# If cross-compiled, we need to init source and build. +if (CMAKE_TOOLCHAIN_FILE) + set(CFLAGS_EXTERNAL_LIB "CFLAGS=--target=${CMAKE_C_COMPILER_TARGET} -w") + set(EMBED_READLINE ON) + set(EMBED_BZIP2 ON) +endif (CMAKE_TOOLCHAIN_FILE) + +if (EMBED_READLINE OR EMBED_BZIP2) + include(ExternalProject) +endif (EMBED_READLINE OR EMBED_BZIP2) + +if (NOT SKIPREADLINE EQUAL 1) + if (APPLE) + find_path(READLINE_INCLUDE_DIRS readline/readline.h /usr/local/opt/readline/include /opt/local/include /opt/include /usr/local/include /usr/include NO_DEFAULT_PATH) + find_library(READLINE_LIBRARIES readline /usr/local/opt/readline/lib /opt/local/lib /opt/lib /usr/local/lib /usr/lib NO_DEFAULT_PATH) + endif (APPLE) + if (EMBED_READLINE) + ExternalProject_Add(ncurses + URL http://ftp.gnu.org/pub/gnu/ncurses/ncurses-6.0.tar.gz + PREFIX deps/ncurses + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/ncurses + CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --disable-database --with-fallbacks=ansi-generic,ansi-mini,color_xterm,dtterm,dumb,Eterm,Eterm-256color,Eterm-88color,eterm-color,gnome,gnome-256color,guru,hurd,iTerm.app,konsole,konsole-16color,konsole-256color,konsole-base,konsole-linux,konsole-solaris,konsole-vt100,kterm,kterm-color,linux,linux-16color,linux-basic,mac,mlterm,mlterm-256color,mrxvt,mrxvt-256color,mterm,mterm-ansi,mvterm,nsterm,nsterm-16color,nsterm-256color,pty,putty,putty-256color,putty-vt100,rxvt,rxvt-16color,rxvt-256color,rxvt-88color,rxvt-basic,rxvt-color,screen,screen-16color,screen-256color,simpleterm,st-16color,st-256color,st52,st52-color,stv52,tt,tt52,unknown,vt100,vt102,vte,vte-256color,xterm,xterm-16color,xterm-256color,xterm-88color,xterm-basic,xterm-bold,xterm-color,xterm-utf8,xterm-vt220,xterm-vt52,xterm1,xtermc,xtermm --enable-termcap --without-ada --without-debug --without-dlsym --without-gpm --without-develop --without-tests --without-cxx-binding --with-termlib + BUILD_IN_SOURCE ON + BUILD_COMMAND make libs + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + ExternalProject_Add_StepTargets(ncurses configure build install) + + ExternalProject_Add(readline + URL ftp://ftp.gnu.org/gnu/readline/readline-7.0.tar.gz + PREFIX deps/readline + DOWNLOAD_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/readline + CONFIGURE_COMMAND ./configure CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} --host=arm --enable-static + BUILD_IN_SOURCE ON + BUILD_COMMAND make + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + ExternalProject_Add_StepTargets(readline configure build install) + set(READLINE_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/readline/src/) + set(READLINE_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/readline/src/readline/libreadline.a ${CMAKE_CURRENT_BINARY_DIR}/deps/ncurses/src/ncurses/lib/libtinfo.a) + else (EMBED_READLINE) + find_path(READLINE_INCLUDE_DIRS readline/readline.h) + find_library(READLINE_LIBRARIES readline) + endif (EMBED_READLINE) + if (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) + set(READLINE_FOUND ON) + endif (READLINE_INCLUDE_DIRS AND READLINE_LIBRARIES) +endif (NOT SKIPREADLINE EQUAL 1) + +if (NOT SKIPJANSSONSYSTEM EQUAL 1) + pkg_check_modules(PC_JANSSON QUIET jansson) + find_path(JANSSON_INCLUDE_DIRS + NAMES jansson.h + HINTS ${PC_JANSSON_INCLUDEDIR} ${PC_JANSSON_INCLUDE_DIRS}) + find_library(JANSSON_LIBRARIES + NAMES jansson libjansson + HINTS ${PC_JANSSON_LIBDIR} ${PC_JANSSON_LIBRARY_DIRS}) + if (JANSSON_INCLUDE_DIRS AND JANSSON_LIBRARIES) + set(JANSSON_FOUND ON) + endif (JANSSON_INCLUDE_DIRS AND JANSSON_LIBRARIES) +endif (NOT SKIPJANSSONSYSTEM EQUAL 1) + +if(EMBED_BZIP2) + set(BZIP2_BUILD_DIR ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2) + ExternalProject_Add(bzip2 + GIT_REPOSITORY https://android.googlesource.com/platform/external/bzip2 + GIT_TAG platform-tools-30.0.2 + PREFIX deps/bzip2 + SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/deps/bzip2 + CONFIGURE_COMMAND mkdir -p ${BZIP2_BUILD_DIR} && git archive --format tar HEAD | tar -C ${BZIP2_BUILD_DIR} -x + BUILD_IN_SOURCE ON + BUILD_COMMAND make -C ${BZIP2_BUILD_DIR} -j4 CC=${CMAKE_C_COMPILER} CXX=${CMAKE_CXX_COMPILER} LD=${CMAKE_C_COMPILER} AR=${CMAKE_AR} RANLIB=${CMAKE_RANLIB} ${CFLAGS_EXTERNAL_LIB} libbz2.a + INSTALL_COMMAND "" + LOG_DOWNLOAD ON + ) + ExternalProject_Add_StepTargets(bzip2 configure build install) + set(BZIP2_INCLUDE_DIRS ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2) + set(BZIP2_LIBRARIES ${CMAKE_CURRENT_BINARY_DIR}/deps/bzip2/src/bzip2/libbz2.a) + set(BZIP2_FOUND ON) +else(EMBED_BZIP2) + find_package (BZip2 REQUIRED) +endif(EMBED_BZIP2) + +if (NOT SKIPWHEREAMISYSTEM EQUAL 1) + find_path(WHEREAMI_INCLUDE_DIRS whereami.h) + find_library(WHEREAMI_LIBRARIES whereami) + if (WHEREAMI_INCLUDE_DIRS AND WHEREAMI_LIBRARIES) + set(WHEREAMI_FOUND ON) + endif (WHEREAMI_INCLUDE_DIRS AND WHEREAMI_LIBRARIES) +endif (NOT SKIPWHEREAMISYSTEM EQUAL 1) + +add_subdirectory(${PM3_ROOT}/client/deps deps) + +set (TARGET_SOURCES + ${PM3_ROOT}/common/commonutil.c + ${PM3_ROOT}/common/util_posix.c + ${PM3_ROOT}/common/parity.c + ${PM3_ROOT}/common/bucketsort.c + ${PM3_ROOT}/common/crapto1/crapto1.c + ${PM3_ROOT}/common/crapto1/crypto1.c + ${PM3_ROOT}/common/crc.c + ${PM3_ROOT}/common/crc16.c + ${PM3_ROOT}/common/crc32.c + ${PM3_ROOT}/common/crc64.c + ${PM3_ROOT}/common/lfdemod.c + ${PM3_ROOT}/common/legic_prng.c + ${PM3_ROOT}/common/iso15693tools.c + ${PM3_ROOT}/common/cardhelper.c + ${PM3_ROOT}/common/generator.c + ${PM3_ROOT}/client/src/crypto/asn1dump.c + ${PM3_ROOT}/client/src/crypto/asn1utils.c + ${PM3_ROOT}/client/src/crypto/libpcrypto.c + ${PM3_ROOT}/client/src/emv/test/cda_test.c + ${PM3_ROOT}/client/src/emv/test/crypto_test.c + ${PM3_ROOT}/client/src/emv/test/cryptotest.c + ${PM3_ROOT}/client/src/emv/test/dda_test.c + ${PM3_ROOT}/client/src/emv/test/sda_test.c + ${PM3_ROOT}/client/src/emv/apduinfo.c + ${PM3_ROOT}/client/src/emv/cmdemv.c + ${PM3_ROOT}/client/src/emv/crypto.c + ${PM3_ROOT}/client/src/emv/crypto_polarssl.c + ${PM3_ROOT}/client/src/emv/dol.c + ${PM3_ROOT}/client/src/emv/emv_pk.c + ${PM3_ROOT}/client/src/emv/emv_pki.c + ${PM3_ROOT}/client/src/emv/emv_pki_priv.c + ${PM3_ROOT}/client/src/emv/emv_roca.c + ${PM3_ROOT}/client/src/emv/emv_tags.c + ${PM3_ROOT}/client/src/emv/emvcore.c + ${PM3_ROOT}/client/src/emv/emvjson.c + ${PM3_ROOT}/client/src/emv/tlv.c + ${PM3_ROOT}/client/src/fido/additional_ca.c + ${PM3_ROOT}/client/src/fido/cbortools.c + ${PM3_ROOT}/client/src/fido/cose.c + ${PM3_ROOT}/client/src/fido/fidocore.c + ${PM3_ROOT}/client/src/loclass/cipher.c + ${PM3_ROOT}/client/src/loclass/cipherutils.c + ${PM3_ROOT}/client/src/loclass/elite_crack.c + ${PM3_ROOT}/client/src/loclass/hash1_brute.c + ${PM3_ROOT}/client/src/loclass/ikeys.c + ${PM3_ROOT}/client/src/mifare/mad.c + ${PM3_ROOT}/client/src/mifare/mfkey.c + ${PM3_ROOT}/client/src/mifare/mifare4.c + ${PM3_ROOT}/client/src/mifare/mifaredefault.c + ${PM3_ROOT}/client/src/mifare/mifarehost.c + ${PM3_ROOT}/client/src/mifare/ndef.c + ${PM3_ROOT}/client/src/mifare/desfire_crypto.c + ${PM3_ROOT}/client/src/uart/uart_posix.c + ${PM3_ROOT}/client/src/uart/uart_win32.c + ${PM3_ROOT}/client/src/ui/overlays.ui + ${PM3_ROOT}/client/src/aiddesfire.c + ${PM3_ROOT}/client/src/aidsearch.c + ${PM3_ROOT}/client/src/cmdanalyse.c + ${PM3_ROOT}/client/src/cmdcrc.c + ${PM3_ROOT}/client/src/cmddata.c + ${PM3_ROOT}/client/src/cmdflashmem.c + ${PM3_ROOT}/client/src/cmdflashmemspiffs.c + ${PM3_ROOT}/client/src/cmdhf.c + ${PM3_ROOT}/client/src/cmdhf14a.c + ${PM3_ROOT}/client/src/cmdhf14b.c + ${PM3_ROOT}/client/src/cmdhf15.c + ${PM3_ROOT}/client/src/cmdhfcryptorf.c + ${PM3_ROOT}/client/src/cmdhfepa.c + ${PM3_ROOT}/client/src/cmdhffelica.c + ${PM3_ROOT}/client/src/cmdhffido.c + ${PM3_ROOT}/client/src/cmdhficlass.c + ${PM3_ROOT}/client/src/cmdhflegic.c + ${PM3_ROOT}/client/src/cmdhflist.c + ${PM3_ROOT}/client/src/cmdhflto.c + ${PM3_ROOT}/client/src/cmdhfmf.c + ${PM3_ROOT}/client/src/cmdhfmfdes.c + ${PM3_ROOT}/client/src/cmdhfmfhard.c + ${PM3_ROOT}/client/src/cmdhfmfp.c + ${PM3_ROOT}/client/src/cmdhfmfu.c + ${PM3_ROOT}/client/src/cmdhfst.c + ${PM3_ROOT}/client/src/cmdhfthinfilm.c + ${PM3_ROOT}/client/src/cmdhftopaz.c + ${PM3_ROOT}/client/src/cmdhfwaveshare.c + ${PM3_ROOT}/client/src/cmdhw.c + ${PM3_ROOT}/client/src/cmdlf.c + ${PM3_ROOT}/client/src/cmdlfawid.c + ${PM3_ROOT}/client/src/cmdlfcotag.c + ${PM3_ROOT}/client/src/cmdlfdestron.c + ${PM3_ROOT}/client/src/cmdlfem4x.c + ${PM3_ROOT}/client/src/cmdlfem4x05.c + ${PM3_ROOT}/client/src/cmdlfem4x50.c + ${PM3_ROOT}/client/src/cmdlffdxb.c + ${PM3_ROOT}/client/src/cmdlfgallagher.c + ${PM3_ROOT}/client/src/cmdlfguard.c + ${PM3_ROOT}/client/src/cmdlfhid.c + ${PM3_ROOT}/client/src/cmdlfhitag.c + ${PM3_ROOT}/client/src/cmdlfidteck.c + ${PM3_ROOT}/client/src/cmdlfindala.c + ${PM3_ROOT}/client/src/cmdlfio.c + ${PM3_ROOT}/client/src/cmdlfjablotron.c + ${PM3_ROOT}/client/src/cmdlfkeri.c + ${PM3_ROOT}/client/src/cmdlfmotorola.c + ${PM3_ROOT}/client/src/cmdlfnedap.c + ${PM3_ROOT}/client/src/cmdlfnexwatch.c + ${PM3_ROOT}/client/src/cmdlfnoralsy.c + ${PM3_ROOT}/client/src/cmdlfpac.c + ${PM3_ROOT}/client/src/cmdlfparadox.c + ${PM3_ROOT}/client/src/cmdlfpcf7931.c + ${PM3_ROOT}/client/src/cmdlfpresco.c + ${PM3_ROOT}/client/src/cmdlfpyramid.c + ${PM3_ROOT}/client/src/cmdlfsecurakey.c + ${PM3_ROOT}/client/src/cmdlft55xx.c + ${PM3_ROOT}/client/src/cmdlfti.c + ${PM3_ROOT}/client/src/cmdlfviking.c + ${PM3_ROOT}/client/src/cmdlfvisa2000.c + ${PM3_ROOT}/client/src/cmdmain.c + ${PM3_ROOT}/client/src/cmdparser.c + ${PM3_ROOT}/client/src/cmdscript.c + ${PM3_ROOT}/client/src/cmdsmartcard.c + ${PM3_ROOT}/client/src/cmdtrace.c + ${PM3_ROOT}/client/src/cmdusart.c + ${PM3_ROOT}/client/src/cmdwiegand.c + ${PM3_ROOT}/client/src/comms.c + ${PM3_ROOT}/client/src/fileutils.c + ${PM3_ROOT}/client/src/flash.c + ${PM3_ROOT}/client/src/graph.c + ${PM3_ROOT}/client/src/jansson_path.c + ${PM3_ROOT}/client/src/preferences.c + ${PM3_ROOT}/client/src/pm3.c + ${PM3_ROOT}/client/src/pm3_binlib.c + ${PM3_ROOT}/client/src/pm3_bitlib.c + ${PM3_ROOT}/client/src/prng.c + ${PM3_ROOT}/client/src/scandir.c + ${PM3_ROOT}/client/src/scripting.c + ${PM3_ROOT}/client/src/tea.c + ${PM3_ROOT}/client/src/ui.c + ${PM3_ROOT}/client/src/util.c + ${PM3_ROOT}/client/src/wiegand_formats.c + ${PM3_ROOT}/client/src/wiegand_formatutils.c + ${CMAKE_BINARY_DIR}/version.c + ) + +add_custom_command( + OUTPUT ${CMAKE_BINARY_DIR}/version.c + COMMAND sh ${PM3_ROOT}/tools/mkversion.sh > ${CMAKE_BINARY_DIR}/version.c || perl ${PM3_ROOT}/tools/mkversion.pl > ${CMAKE_BINARY_DIR}/version.c || ${CMAKE_COMMAND} -E copy ${PM3_ROOT}/common/default_version.c ${CMAKE_BINARY_DIR}/version.c + DEPENDS ${PM3_ROOT}/common/default_version.c +) + +set(ADDITIONAL_SRC "") +set(ADDITIONAL_LNK "") +set(ADDITIONAL_DIRS "") +set(ADDITIONAL_LNKDIRS "") +set(X86_CPUS x86 x86_64 i686) + +message(STATUS "CMAKE_SYSTEM_PROCESSOR := ${CMAKE_SYSTEM_PROCESSOR}") + +if (APPLE) + message(STATUS "Apple device detected.") + set(ADDITIONAL_SRC ${PM3_ROOT}/client/src/util_darwin.h ${PM3_ROOT}/client/src/util_darwin.m ${ADDITIONAL_SRC}) + set(ADDITIONAL_LNK "-framework Foundation" "-framework AppKit") +endif (APPLE) + +if ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND)) + set(CMAKE_AUTOMOC ON) + set(CMAKE_AUTORCC ON) + set(CMAKE_AUTOUIC ON) + set (TARGET_SOURCES + ${PM3_ROOT}/client/src/proxgui.cpp + ${PM3_ROOT}/client/src/proxguiqt.cpp + ${TARGET_SOURCES}) + + add_definitions("-DHAVE_GUI") + set(ADDITIONAL_LNK ${Qt5_LIBRARIES} ${ADDITIONAL_LNK}) +else ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND)) + set(TARGET_SOURCES + ${PM3_ROOT}/client/src/guidummy.cpp + ${TARGET_SOURCES}) +endif ((NOT SKIPQT EQUAL 1) AND (Qt5_FOUND)) + +if (NOT SKIPBT EQUAL 1) + if (BLUEZ_FOUND) + add_definitions("-DHAVE_BLUEZ") + set(ADDITIONAL_LNK ${BLUEZ_LIBRARIES} ${ADDITIONAL_LNK}) + endif (BLUEZ_FOUND) +endif(NOT SKIPBT EQUAL 1) + +if (JANSSON_FOUND) + set(ADDITIONAL_DIRS ${JANSSON_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${JANSSON_LIBRARIES} ${ADDITIONAL_LNK}) +endif (JANSSON_FOUND) + +if (NOT SKIPPYTHON EQUAL 1) + if (PYTHON3EMBED_FOUND) + add_definitions(-DHAVE_PYTHON) + set(ADDITIONAL_DIRS ${PYTHON3EMBED_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${PYTHON3EMBED_LIBRARIES} ${ADDITIONAL_LNK}) + set(ADDITIONAL_LNKDIRS ${PYTHON3EMBED_LIBRARY_DIRS} ${ADDITIONAL_LNKDIRS}) + elseif (PYTHON3_FOUND) + add_definitions(-DHAVE_PYTHON) + set(ADDITIONAL_DIRS ${PYTHON3_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${PYTHON3_LIBRARIES} ${ADDITIONAL_LNK}) + set(ADDITIONAL_LNKDIRS ${PYTHON3_LIBRARY_DIRS} ${ADDITIONAL_LNKDIRS}) + endif (PYTHON3EMBED_FOUND) +endif (NOT SKIPPYTHON EQUAL 1) + +if (NOT SKIPREADLINE EQUAL 1) + if (READLINE_FOUND) + add_definitions("-DHAVE_READLINE") + set(ADDITIONAL_DIRS ${READLINE_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${READLINE_LIBRARIES} ${ADDITIONAL_LNK}) + endif (READLINE_FOUND) +endif(NOT SKIPREADLINE EQUAL 1) + +if (BZIP2_FOUND) + set(ADDITIONAL_DIRS ${BZIP2_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${BZIP2_LIBRARIES} ${ADDITIONAL_LNK}) +endif (BZIP2_FOUND) + +if (WHEREAMI_FOUND) + set(ADDITIONAL_DIRS ${WHEREAMI_INCLUDE_DIRS} ${ADDITIONAL_DIRS}) + set(ADDITIONAL_LNK ${WHEREAMI_LIBRARIES} ${ADDITIONAL_LNK}) +endif (WHEREAMI_FOUND) + +message(STATUS "===================================================================") +if (SKIPQT EQUAL 1) + message(STATUS "GUI support: skipped") +else (SKIPQT EQUAL 1) + if (Qt5_FOUND) + message(STATUS "GUI support: QT5 found, enabled") + else (Qt5_FOUND) + message(STATUS "GUI support: QT5 not found, disabled") + endif (Qt5_FOUND) +endif (SKIPQT EQUAL 1) + +if (SKIPBT EQUAL 1) + message(STATUS "native BT support: skipped") +else (SKIPBT EQUAL 1) + if (BLUEZ_FOUND) + message(STATUS "native BT support: Bluez found, enabled") + else (BLUEZ_FOUND) + message(STATUS "native BT support: Bluez not found, disabled") + endif (BLUEZ_FOUND) +endif(SKIPBT EQUAL 1) + +if (EMBED_BZIP2) + message(STATUS "Bzip2 library: embedded") +else (EMBED_BZIP2) + message(STATUS "Bzip2 library: system library found") +endif (EMBED_BZIP2) + +if (SKIPJANSSONSYSTEM EQUAL 1) + message(STATUS "Jansson library: local library forced") +else (SKIPJANSSONSYSTEM EQUAL 1) + if (JANSSON_FOUND) + message(STATUS "Jansson library: system library found") + else (JANSSON_FOUND) + message(STATUS "Jansson library: system library not found, using local library") + endif (JANSSON_FOUND) +endif (SKIPJANSSONSYSTEM EQUAL 1) + +if (SKIPPYTHON EQUAL 1) + message(STATUS "Python3 library: skipped") +else (SKIPPYTHON EQUAL 1) + if (PYTHON3EMBED_FOUND) + message(STATUS "Python3 library: Python3 embed found, enabled") + elseif (PYTHON_FOUND) + message(STATUS "Python3 library: Python3 found, enabled") + else (PYTHON3EMBED_FOUND) + message(STATUS "Python3 library: Python3 not found, disabled") + endif (PYTHON3EMBED_FOUND) +endif(SKIPPYTHON EQUAL 1) + +if (SKIPREADLINE EQUAL 1) + message(STATUS "Readline library: skipped") +else (SKIPREADLINE EQUAL 1) + if (READLINE_FOUND) + if (EMBED_READLINE) + message(STATUS "Readline library: embedded") + else (EMBED_READLINE) + message(STATUS "Readline library: system library found") + endif (EMBED_READLINE) + else (READLINE_FOUND) + message(STATUS "Readline library: Readline not found, disabled") + endif (READLINE_FOUND) +endif(SKIPREADLINE EQUAL 1) + +if (SKIPWHEREAMISYSTEM EQUAL 1) + message(STATUS "Whereami library: local library forced") +else (SKIPWHEREAMISYSTEM EQUAL 1) + if (WHEREAMI_FOUND) + message(STATUS "Whereami library: system library found") + else (WHEREAMI_FOUND) + message(STATUS "Whereami library: system library not found, using local library") + endif (WHEREAMI_FOUND) +endif (SKIPWHEREAMISYSTEM EQUAL 1) + +# Lua SWIG +if (EXISTS ${PM3_ROOT}/client/src/pm3_luawrap.c) + set (TARGET_SOURCES + ${PM3_ROOT}/client/src/pm3_luawrap.c + ${TARGET_SOURCES}) + add_definitions(-DHAVE_LUA_SWIG) + message(STATUS "Lua SWIG: wrapper found") +endif (EXISTS ${PM3_ROOT}/client/src/pm3_luawrap.c) + +# Python SWIG +if (NOT SKIPPYTHON EQUAL 1) + if (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) + if (EXISTS ${PM3_ROOT}/client/src/pm3_pywrap.c) + set (TARGET_SOURCES + ${PM3_ROOT}/client/src/pm3_pywrap.c + ${TARGET_SOURCES}) + add_definitions(-DHAVE_PYTHON_SWIG) + message(STATUS "Python SWIG: wrapper found") + endif (EXISTS ${PM3_ROOT}/client/src/pm3_pywrap.c) + endif (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) +endif (NOT SKIPPYTHON EQUAL 1) +message(STATUS "===================================================================") + +add_library(pm3rrg_rdv4 SHARED + ${PM3_ROOT}/client/src/proxmark3.c + ${TARGET_SOURCES} + ${ADDITIONAL_SRC} +) + +target_compile_definitions(pm3rrg_rdv4 PRIVATE LIBPM3) + +target_compile_options(pm3rrg_rdv4 PUBLIC -Wall -Werror -O3) +if (EMBED_READLINE) + if (NOT SKIPREADLINE EQUAL 1) + add_dependencies(pm3rrg_rdv4 ncurses readline) + endif (NOT SKIPREADLINE EQUAL 1) +endif (EMBED_READLINE) +if (EMBED_BZIP2) + add_dependencies(pm3rrg_rdv4 bzip2) +endif (EMBED_BZIP2) + +if (MINGW) + # Mingw uses by default Microsoft printf, we want the GNU printf (e.g. for %z) + # and setting _ISOC99_SOURCE sets internally __USE_MINGW_ANSI_STDIO=1 + # FTR __USE_MINGW_ANSI_STDIO seems deprecated in Mingw32 + # but not Mingw64 https://fr.osdn.net/projects/mingw/lists/archive/users/2019-January/000199.html + target_compile_definitions(pm3rrg_rdv4 PRIVATE _ISOC99_SOURCE) + + set(CMAKE_C_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-mno-ms-bitfields -fexec-charset=cp850 ${CMAKE_CXX_FLAGS}") +endif (MINGW) + +target_include_directories(pm3rrg_rdv4 PRIVATE + ${PM3_ROOT}/common + ${PM3_ROOT}/common_fpga + ${PM3_ROOT}/include + ${PM3_ROOT}/client/src + ${PM3_ROOT}/client/include + ${ADDITIONAL_DIRS} +) + +if (NOT APPLE) + # required for Raspberry Pi, but breaks with clang (OSX). Need to be at the end of the linker line. + set(ADDITIONAL_LNK ${ADDITIONAL_LNK} -Wl,--as-needed -latomic -Wl,--no-as-needed) +endif (NOT APPLE) + +if (NOT JANSSON_FOUND) + set(ADDITIONAL_LNK pm3rrg_rdv4_jansson ${ADDITIONAL_LNK}) +endif (NOT JANSSON_FOUND) +if (NOT WHEREAMI_FOUND) + set(ADDITIONAL_LNK pm3rrg_rdv4_whereami ${ADDITIONAL_LNK}) +endif (NOT WHEREAMI_FOUND) + +target_link_libraries(pm3rrg_rdv4 PRIVATE + m + pm3rrg_rdv4_mbedtls + pm3rrg_rdv4_cliparser + pm3rrg_rdv4_lua + pm3rrg_rdv4_tinycbor + pm3rrg_rdv4_amiibo + pm3rrg_rdv4_reveng + pm3rrg_rdv4_hardnested + ${ADDITIONAL_LNK}) + +if (NOT SKIPPTHREAD EQUAL 1) + target_link_libraries(pm3rrg_rdv4 PRIVATE pthread) +endif (NOT SKIPPTHREAD EQUAL 1) + +if (NOT SKIPPYTHON EQUAL 1) + # OSX have a hard time compiling python3 dependency with older cmake. + if (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) + if (NOT CMAKE_VERSION VERSION_LESS 3.13) + target_link_directories(pm3rrg_rdv4 PRIVATE ${ADDITIONAL_LNKDIRS}) + elseif (APPLE) + message( SEND_ERROR "Your CMAKE version is too old for Apple platform, please update to a version >=3.13" ) + endif (NOT CMAKE_VERSION VERSION_LESS 3.13) + endif (PYTHON3EMBED_FOUND OR PYTHON3_FOUND) +endif (NOT SKIPPYTHON EQUAL 1) diff --git a/client/experimental_lib/example_c/01make_test.sh b/client/experimental_lib/example_c/01make_test.sh new file mode 100755 index 000000000..1ce6357ff --- /dev/null +++ b/client/experimental_lib/example_c/01make_test.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +gcc -o test test.c -I../../include -lpm3rrg_rdv4 -L../build -lpthread diff --git a/client/experimental_lib/example_c/02run_test.sh b/client/experimental_lib/example_c/02run_test.sh new file mode 100755 index 000000000..a3e4ec057 --- /dev/null +++ b/client/experimental_lib/example_c/02run_test.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +LD_LIBRARY_PATH=../build ./test diff --git a/client/experimental_lib/example_c/test.c b/client/experimental_lib/example_c/test.c new file mode 100644 index 000000000..a3cf212dc --- /dev/null +++ b/client/experimental_lib/example_c/test.c @@ -0,0 +1,8 @@ +#include "pm3.h" + +int main(int argc, char *argv[]) { + pm3 *p; + p = pm3_open("/dev/ttyACM0"); + pm3_console(p, "hw status"); + pm3_close(p); +} diff --git a/client/experimental_lib/example_lua/01link_lib.sh b/client/experimental_lib/example_lua/01link_lib.sh new file mode 100755 index 000000000..5f9fb5f68 --- /dev/null +++ b/client/experimental_lib/example_lua/01link_lib.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +ln -fs ../build/libpm3rrg_rdv4.so pm3.so diff --git a/client/experimental_lib/example_lua/02run_test.sh b/client/experimental_lib/example_lua/02run_test.sh new file mode 100755 index 000000000..32fb1ae55 --- /dev/null +++ b/client/experimental_lib/example_lua/02run_test.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +# pm3.so somewhere in default LUA_CPATH : +# /usr/local/lib/lua/5.2/pm3.so +# /usr/lib/lua/5.2/pm3.so +# ./pm3.so + +./test.lua diff --git a/client/experimental_lib/example_lua/test.lua b/client/experimental_lib/example_lua/test.lua new file mode 100755 index 000000000..be12f1d5b --- /dev/null +++ b/client/experimental_lib/example_lua/test.lua @@ -0,0 +1,6 @@ +#!/usr/bin/env lua + +local pm3 = require("pm3") +p=pm3.pm3("/dev/ttyACM0") +p:console("hw status") +print(p.name) diff --git a/client/experimental_lib/example_py/01link_lib.sh b/client/experimental_lib/example_py/01link_lib.sh new file mode 100755 index 000000000..8cd153d41 --- /dev/null +++ b/client/experimental_lib/example_py/01link_lib.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +ln -fs ../build/libpm3rrg_rdv4.so _pm3.so diff --git a/client/experimental_lib/example_py/02run_test.sh b/client/experimental_lib/example_py/02run_test.sh new file mode 100755 index 000000000..67ab20525 --- /dev/null +++ b/client/experimental_lib/example_py/02run_test.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +#/usr/local/lib/python3/dist-packages/_pm3.cpython-38.so +#/usr/local/lib/python3/dist-packages/_pm3.abi3.so +#/usr/local/lib/python3/dist-packages/pm3.py +#/usr/lib/python3/dist-packages/_pm3.cpython-38.so +#/usr/lib/python3/dist-packages/_pm3.abi3.so +#/usr/lib/python3/dist-packages/pm3.py + +# need access to pm3.py +PYTHONPATH=../../src ./test.py diff --git a/client/experimental_lib/example_py/02run_test_grab_interactive.sh b/client/experimental_lib/example_py/02run_test_grab_interactive.sh new file mode 100755 index 000000000..d7dd7dd16 --- /dev/null +++ b/client/experimental_lib/example_py/02run_test_grab_interactive.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +PYTHONPATH=../../src ipython3 -i ./test_grab.py diff --git a/client/experimental_lib/example_py/02run_test_interactive.sh b/client/experimental_lib/example_py/02run_test_interactive.sh new file mode 100755 index 000000000..701dbb5cf --- /dev/null +++ b/client/experimental_lib/example_py/02run_test_interactive.sh @@ -0,0 +1,3 @@ +#!/bin/bash + +PYTHONPATH=../../src ipython3 -i ./test.py diff --git a/client/experimental_lib/example_py/output_grabber.py b/client/experimental_lib/example_py/output_grabber.py new file mode 100755 index 000000000..ad405c9d9 --- /dev/null +++ b/client/experimental_lib/example_py/output_grabber.py @@ -0,0 +1,78 @@ +import os +import sys +import threading +import time + +# From https://stackoverflow.com/a/29834357 +class OutputGrabber(object): + """ + Class used to grab standard output or another stream. + """ + escape_char = "\b" + + def __init__(self, stream=None, threaded=False): + self.origstream = stream + self.threaded = threaded + if self.origstream is None: + self.origstream = sys.stdout + self.origstreamfd = self.origstream.fileno() + self.capturedtext = "" + # Create a pipe so the stream can be captured: + self.pipe_out, self.pipe_in = os.pipe() + + def __enter__(self): + self.start() + return self + + def __exit__(self, type, value, traceback): + self.stop() + + def start(self): + """ + Start capturing the stream data. + """ + self.capturedtext = "" + # Save a copy of the stream: + self.streamfd = os.dup(self.origstreamfd) + # Replace the original stream with our write pipe: + os.dup2(self.pipe_in, self.origstreamfd) + if self.threaded: + # Start thread that will read the stream: + self.workerThread = threading.Thread(target=self.readOutput) + self.workerThread.start() + # Make sure that the thread is running and os.read() has executed: + time.sleep(0.01) + + def stop(self): + """ + Stop capturing the stream data and save the text in `capturedtext`. + """ + # Print the escape character to make the readOutput method stop: + self.origstream.write(self.escape_char) + # Flush the stream to make sure all our data goes in before + # the escape character: + self.origstream.flush() + if self.threaded: + # wait until the thread finishes so we are sure that + # we have until the last character: + self.workerThread.join() + else: + self.readOutput() + # Close the pipe: + os.close(self.pipe_in) + os.close(self.pipe_out) + # Restore the original stream: + os.dup2(self.streamfd, self.origstreamfd) + # Close the duplicate stream: + os.close(self.streamfd) + + def readOutput(self): + """ + Read the stream data (one byte at a time) + and save the text in `capturedtext`. + """ + while True: + char = os.read(self.pipe_out,1).decode(self.origstream.encoding) + if not char or self.escape_char in char: + break + self.capturedtext += char diff --git a/client/experimental_lib/example_py/test.py b/client/experimental_lib/example_py/test.py new file mode 100755 index 000000000..39cee5301 --- /dev/null +++ b/client/experimental_lib/example_py/test.py @@ -0,0 +1,6 @@ +#!/usr/bin/env python3 + +import pm3 +p=pm3.pm3("/dev/ttyACM0") +p.console("hw status") +print("Device:", p.name) diff --git a/client/experimental_lib/example_py/test_grab.py b/client/experimental_lib/example_py/test_grab.py new file mode 100755 index 000000000..7cec5a94f --- /dev/null +++ b/client/experimental_lib/example_py/test_grab.py @@ -0,0 +1,13 @@ +#!/usr/bin/env python3 + +import pm3 +from output_grabber import OutputGrabber + +out = OutputGrabber() +p=pm3.pm3("/dev/ttyACM1") +print("Device:", p.name) +with out: + p.console("hw status") +for line in out.capturedtext.split('\n'): + if "Unique ID" in line: + print(line) diff --git a/client/include/pm3.h b/client/include/pm3.h new file mode 100644 index 000000000..cfdb69944 --- /dev/null +++ b/client/include/pm3.h @@ -0,0 +1,11 @@ +#ifndef LIBPM3_H +#define LIBPM3_H + +typedef struct pm3_device pm3; + +pm3 *pm3_open(char *port); +int pm3_console(pm3* dev, char *cmd); +const char *pm3_name_get(pm3* dev); +void pm3_close(pm3* dev); +pm3 *pm3_get_current_dev(void); +#endif // LIBPM3_H diff --git a/client/lualibs/7816_error.lua b/client/lualibs/7816_error.lua index 15f4ef471..34f9847ce 100644 --- a/client/lualibs/7816_error.lua +++ b/client/lualibs/7816_error.lua @@ -68,10 +68,11 @@ end _errorcodes.tostring = function(command) if(type(command) == 'string') then - return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command) + return ("%s (%s)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command) end if(type(command) == 'number') then - return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command) + local hx = ("%04X"):format(command) + return ("%s (0x%s)"):format(_reverse_lookup[hx] or "ERROR UNDEFINED!", hx) end return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) end diff --git a/client/src/cmdhf14a.c b/client/src/cmdhf14a.c index e402cb48e..c8d0a57eb 100644 --- a/client/src/cmdhf14a.c +++ b/client/src/cmdhf14a.c @@ -29,12 +29,11 @@ #include "aidsearch.h" #include "cmdhf.h" // handle HF plot #include "protocols.h" // MAGIC_GEN_1A -#include "emv/dump.h" // dump_buffer bool APDUInFramingEnable = true; static int CmdHelp(const char *Cmd); -static int waitCmd(uint8_t iSelect, uint32_t timeout); +static int waitCmd(bool i_select, uint32_t timeout); static const manufactureName manufactureMapping[] = { // ID, "Vendor Country" @@ -246,20 +245,7 @@ static int usage_hf_14a_sniff(void) { PrintAndLogEx(NORMAL, _YELLOW_(" hf 14a sniff c r")); return PM3_SUCCESS; } -static int usage_hf_14a_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-k] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -k keep signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte"); - PrintAndLogEx(NORMAL, " -t timeout in ms"); - PrintAndLogEx(NORMAL, " -T use Topaz protocol to send command"); - PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)"); - return PM3_SUCCESS; -} + static int usage_hf_14a_reader(void) { PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); PrintAndLogEx(NORMAL, " k keep the field active after command executed"); @@ -551,8 +537,8 @@ static int CmdHF14AReader(const char *Cmd) { res = PM3_ESOFT; goto plot; } + PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); if (!(silent && continuous)) { - PrintAndLogEx(SUCCESS, " UID: " _GREEN_("%s"), sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(SUCCESS, "ATQA: " _GREEN_("%02x %02x"), card.atqa[1], card.atqa[0]); PrintAndLogEx(SUCCESS, " SAK: " _GREEN_("%02x [%" PRIu64 "]"), card.sak, resp.oldarg[0]); @@ -1027,7 +1013,7 @@ static int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool return 4; } - return 0; + return PM3_SUCCESS; } int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { @@ -1118,14 +1104,14 @@ static int CmdHF14AAPDU(const char *Cmd) { CLIParserInit(&ctx, "hf 14a apdu", "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL). works with all apdu types from ISO 7816-4:2013", "hf 14a apdu -st 00A404000E325041592E5359532E444446303100\n" - "hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n" - "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n" + "hf 14a apdu -sd 00A404000E325041592E5359532E444446303100 -> decode apdu\n" + "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -l 256 -> encode standard apdu\n" "hf 14a apdu -sm 00A40400 325041592E5359532E4444463031 -el 65536 -> encode extended apdu\n"); void *argtable[] = { arg_param_begin, arg_lit0("s", "select", "activate field and select card"), - arg_lit0("k", "keep", "leave the signal field ON after receive response"), + arg_lit0("k", "keep", "keep signal field ON after receive"), arg_lit0("t", "tlv", "executes TLV decoder if it possible"), arg_lit0("d", "decapdu", "decode apdu request if it possible"), arg_str0("m", "make", "", "make apdu with head from this field and data from data field. Must be 4 bytes length: "), @@ -1146,7 +1132,7 @@ static int CmdHF14AAPDU(const char *Cmd) { if (makeAPDU && headerlen != 4) { PrintAndLogEx(ERR, "header length must be 4 bytes instead of %d", headerlen); CLIParserFree(ctx); - return 1; + return PM3_EINVARG; } extendedAPDU = arg_get_lit(ctx, 6); le = arg_get_int_def(ctx, 7, 0); @@ -1172,19 +1158,19 @@ static int CmdHF14AAPDU(const char *Cmd) { if (APDUEncode(&apdu, data, &datalen)) { PrintAndLogEx(ERR, "can't make apdu with provided parameters."); CLIParserFree(ctx); - return 2; + return PM3_EINVARG; } } else { if (extendedAPDU) { PrintAndLogEx(ERR, "make mode not set but here `e` option."); CLIParserFree(ctx); - return 3; + return PM3_EINVARG; } if (le > 0) { PrintAndLogEx(ERR, "make mode not set but here `l` option."); CLIParserFree(ctx); - return 3; + return PM3_EINVARG; } // len = data + PCB(1b) + CRC(2b) @@ -1192,7 +1178,12 @@ static int CmdHF14AAPDU(const char *Cmd) { } CLIParserFree(ctx); - PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel " : "", leaveSignalON ? "keep " : "", decodeTLV ? "TLV" : "", sprint_hex(data, datalen)); + PrintAndLogEx(SUCCESS, "( " _YELLOW_("%s%s%s")" )", + activateField ? "select" : "", + leaveSignalON ? ", keep" : "", + decodeTLV ? ", TLV" : "" + ); + PrintAndLogEx(SUCCESS, ">>> %s", sprint_hex_inrow(data, datalen)); if (decodeAPDU) { APDUStruct apdu; @@ -1208,110 +1199,66 @@ static int CmdHF14AAPDU(const char *Cmd) { if (res) return res; - PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); - - PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + PrintAndLogEx(SUCCESS, "<<< %s | %s", sprint_hex_inrow(data, datalen), sprint_ascii(data, datalen)); + PrintAndLogEx(SUCCESS, "<<< status: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); // TLV decoder if (decodeTLV && datalen > 4) { TLVPrintFromBuffer(data, datalen - 2); } - return 0; + return PM3_SUCCESS; } static int CmdHF14ACmdRaw(const char *Cmd) { - bool reply = 1; - bool crc = false; - bool keep_field_on = false; - bool active = false; - bool active_select = false; - bool no_rats = false; - uint16_t numbits = 0; - bool bTimeout = false; - uint32_t timeout = 0; - bool topazmode = false; - char buf[5] = ""; - int i = 0; + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf 14a raw", + "Sends an raw bytes over ISO14443a. With option to use TOPAZ 14a mode.", + "hf 14a raw -sc 3000 -> select, crc, where 3000 == 'read block 00'\n" + "hf 14a raw -ak -b 7 40 -> send 7 bit byte 0x40\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("a", NULL, "active signal field ON without select"), + arg_int0("b", NULL, "", "number of bits to send. Useful for send partial byte"), + arg_lit0("c", NULL, "calculate and append CRC"), + arg_lit0("k", NULL, "keep signal field ON after receive"), + arg_lit0("3", NULL, "ISO14443-3 select only (skip RATS)"), + arg_lit0("r", NULL, "do not read response"), + arg_lit0("s", NULL, "active signal field ON with select"), + arg_int0("t", "timeout", "", "timeout in milliseconds"), + arg_lit0(NULL, "topaz", "use Topaz protocol to send command"), + arg_strx1(NULL, NULL, "", "raw bytes to send"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + + + bool active = arg_get_lit(ctx, 1); + uint16_t numbits = (uint16_t)arg_get_int_def(ctx, 2, 0); + bool crc = arg_get_lit(ctx, 3); + bool keep_field_on = arg_get_lit(ctx, 4); + bool no_rats = arg_get_lit(ctx, 5); + bool reply = (arg_get_lit(ctx, 6) == false); + bool active_select = arg_get_lit(ctx, 7); + uint32_t timeout = (uint32_t)arg_get_int_def(ctx, 8, 0); + bool topazmode = arg_get_lit(ctx, 9); + + int datalen = 0; uint8_t data[PM3_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; + CLIGetHexWithReturn(ctx, 10, data, &datalen); + CLIParserFree(ctx); - if (strlen(Cmd) < 2) return usage_hf_14a_raw(); + bool bTimeout = (timeout) ? true : false; - // strip - while (*Cmd == ' ' || *Cmd == '\t') Cmd++; - - while (Cmd[i] != '\0') { - if (Cmd[i] == ' ' || Cmd[i] == '\t') { i++; continue; } - if (Cmd[i] == '-') { - switch (Cmd[i + 1]) { - case 'H': - case 'h': - return usage_hf_14a_raw(); - case 'r': - reply = false; - break; - case 'c': - crc = true; - break; - case 'k': - keep_field_on = true; - break; - case 'a': - active = true; - break; - case 's': - active_select = true; - break; - case 'b': - sscanf(Cmd + i + 2, "%u", &temp); - numbits = temp & 0xFFFF; - i += 3; - while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } - i -= 2; - break; - case 't': - bTimeout = true; - sscanf(Cmd + i + 2, "%u", &temp); - timeout = temp; - i += 3; - while (Cmd[i] != ' ' && Cmd[i] != '\0') { i++; } - i -= 2; - break; - case 'T': - topazmode = true; - break; - case '3': - no_rats = true; - break; - default: - return usage_hf_14a_raw(); - } - i += 2; - continue; + // ensure we can add 2byte crc to input data + if (datalen >= sizeof(data) + 2) { + if (crc) { + PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data"); + return PM3_EINVARG; } - if ((Cmd[i] >= '0' && Cmd[i] <= '9') || - (Cmd[i] >= 'a' && Cmd[i] <= 'f') || - (Cmd[i] >= 'A' && Cmd[i] <= 'F')) { - buf[strlen(buf) + 1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; - - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - *buf = 0; - if (++datalen >= sizeof(data)) { - if (crc) - PrintAndLogEx(FAILED, "Buffer is full, we can't add CRC to your data"); - break; - } - } - continue; - } - PrintAndLogEx(FAILED, "Invalid char on input"); - return PM3_ESOFT; } if (crc && datalen > 0 && datalen < sizeof(data) - 2) { @@ -1367,19 +1314,19 @@ static int CmdHF14ACmdRaw(const char *Cmd) { if (reply) { int res = 0; if (active_select) - res = waitCmd(1, timeout); - if (!res && datalen > 0) - waitCmd(0, timeout); + res = waitCmd(true, timeout); + if (res == PM3_SUCCESS && datalen > 0) + waitCmd(false, timeout); } return PM3_SUCCESS; } -static int waitCmd(uint8_t iSelect, uint32_t timeout) { +static int waitCmd(bool i_select, uint32_t timeout) { PacketResponseNG resp; if (WaitForResponseTimeout(CMD_ACK, &resp, timeout + 1500)) { uint16_t len = (resp.oldarg[0] & 0xFFFF); - if (iSelect) { + if (i_select) { len = (resp.oldarg[1] & 0xFFFF); if (len) { PrintAndLogEx(SUCCESS, "Card selected. UID[%u]:", len); @@ -1391,28 +1338,30 @@ static int waitCmd(uint8_t iSelect, uint32_t timeout) { } if (!len) - return 1; + return PM3_ESOFT; uint8_t *data = resp.data.asBytes; - if (iSelect == 0 && len >= 3) { + if (i_select == false && len >= 3) { bool crc = check_crc(CRC_14443_A, data, len); - PrintAndLogEx(SUCCESS, "%s[%02X %02X] %s", - sprint_hex(data, len - 2), - data[len - 2], - data[len - 1], - (crc) ? _GREEN_("ok") : _RED_("fail") - ); + char s[16]; + sprintf(s, + (crc) ? _GREEN_("%02X %02X") : _RED_("%02X %02X"), + data[len - 2], + data[len - 1] + ); + + PrintAndLogEx(SUCCESS, "%s[ %s ]", sprint_hex(data, len - 2), s); } else { PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len)); } } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 3; + return PM3_ETIMEOUT; } - return 0; + return PM3_SUCCESS; } static int CmdHF14AAntiFuzz(const char *Cmd) { @@ -2038,7 +1987,7 @@ int infoHF14A(bool verbose, bool do_nack_test, bool do_aid_search) { break; } } else { - dump_buffer(&card.ats[pos], calen, NULL, 1); + PrintAndLogEx(SUCCESS, " %s", sprint_hex_inrow(card.ats + pos, calen)); } } diff --git a/client/src/cmdhf15.c b/client/src/cmdhf15.c index 8754c7a05..593eaaece 100644 --- a/client/src/cmdhf15.c +++ b/client/src/cmdhf15.c @@ -1326,7 +1326,7 @@ static int CmdHF15Dump(const char *Cmd) { if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); fptr += sprintf(fptr, "hf-15-"); - FillFileNameByUID(fptr, uid, "-dump", sizeof(uid)); + FillFileNameByUID(fptr, SwapEndian64(uid, sizeof(uid), 8), "-dump", sizeof(uid)); } // detect blocksize from card :) diff --git a/client/src/cmdhffido.c b/client/src/cmdhffido.c index 53cb10c98..7535a5ef4 100644 --- a/client/src/cmdhffido.c +++ b/client/src/cmdhffido.c @@ -19,9 +19,7 @@ //----------------------------------------------------------------------------- #include "cmdhffido.h" - #include - #include "cmdparser.h" // command_t #include "commonutil.h" #include "comms.h" @@ -33,10 +31,10 @@ #include "crypto/libpcrypto.h" #include "fido/cbortools.h" #include "fido/fidocore.h" -#include "emv/dump.h" #include "ui.h" #include "cmdhf14a.h" #include "cmdtrace.h" +#include "util.h" static int CmdHelp(const char *Cmd); @@ -88,7 +86,7 @@ static int cmd_hf_fido_info(const char *cmd) { } else { PrintAndLogEx(INFO, "FIDO authenticator detected (not standard U2F)."); PrintAndLogEx(INFO, "Non U2F authenticator version:"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); + print_buffer((const unsigned char *)buf, len, 1); } } else { PrintAndLogEx(INFO, "FIDO U2F authenticator detected. Version: %.*s", (int)len, buf); @@ -292,11 +290,11 @@ static int cmd_hf_fido_register(const char *cmd) { if (APDULogging) PrintAndLogEx(INFO, "---------------------------------------------------------------"); - PrintAndLogEx(NORMAL, "data len: %zu", len); + PrintAndLogEx(INFO, "data len: %zu", len); if (verbose2) { PrintAndLogEx(INFO, "------------ " _CYAN_("data") " ----------------------"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); + print_buffer((const unsigned char *)buf, len, 1); PrintAndLogEx(INFO, "-------------" _CYAN_("data") " ----------------------"); } @@ -312,13 +310,14 @@ static int cmd_hf_fido_register(const char *cmd) { int derp = 67 + keyHandleLen; int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; if (verbose2) { - PrintAndLogEx(NORMAL, "DER certificate[%d]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); - PrintAndLogEx(NORMAL, "\n----------------DER---------------------"); + PrintAndLogEx(INFO, "DER certificate[%d]:", derLen); + PrintAndLogEx(INFO, "------------------DER-------------------"); + PrintAndLogEx(INFO, "%s", sprint_hex(buf + derp, derLen)); + PrintAndLogEx(INFO, "----------------DER---------------------"); } else { if (verbose) - PrintAndLogEx(NORMAL, "------------------DER-------------------"); - PrintAndLogEx(NORMAL, "DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); + PrintAndLogEx(INFO, "------------------DER-------------------"); + PrintAndLogEx(INFO, "DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); } // check and print DER certificate @@ -326,9 +325,9 @@ static int cmd_hf_fido_register(const char *cmd) { // print DER certificate in TLV view if (showDERTLV) { - PrintAndLogEx(NORMAL, "----------------DER TLV-----------------"); + PrintAndLogEx(INFO, "----------------DER TLV-----------------"); asn1_print(&buf[derp], derLen, " "); - PrintAndLogEx(NORMAL, "----------------DER TLV-----------------"); + PrintAndLogEx(INFO, "----------------DER TLV-----------------"); } FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key)); @@ -341,10 +340,10 @@ static int cmd_hf_fido_register(const char *cmd) { uint8_t rval[300] = {0}; uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); - if (!res) { + if (res == PM3_SUCCESS) { if (verbose) { - PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32)); + PrintAndLogEx(INFO, " r: %s", sprint_hex(rval, 32)); + PrintAndLogEx(INFO, " s: %s", sprint_hex(sval, 32)); } uint8_t xbuf[4096] = {0}; @@ -357,7 +356,7 @@ static int cmd_hf_fido_register(const char *cmd) { &buf[1], 65, // user public key NULL, 0); (void)res; - //PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + //PrintAndLogEx(INFO, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(MBEDTLS_ECP_DP_SECP256R1, public_key, xbuf, xbuflen, &buf[hashp], len - hashp, true); if (res) { if (res == MBEDTLS_ERR_ECP_VERIFY_FAILED) { @@ -574,7 +573,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) { return PM3_ESOFT; } - PrintAndLogEx(NORMAL, "---------------------------------------------------------------"); + PrintAndLogEx(INFO, "---------------------------------------------------------------"); PrintAndLogEx(SUCCESS, "User presence: %s", (buf[0] ? "verified" : "not verified")); uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); PrintAndLogEx(SUCCESS, "Counter: %d", cntr); @@ -584,10 +583,10 @@ static int cmd_hf_fido_authenticate(const char *cmd) { uint8_t rval[300] = {0}; uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); - if (!res) { + if (res == PM3_SUCCESS) { if (verbose) { - PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32)); + PrintAndLogEx(INFO, " r: %s", sprint_hex(rval, 32)); + PrintAndLogEx(INFO, " s: %s", sprint_hex(sval, 32)); } if (public_key_loaded) { uint8_t xbuf[4096] = {0}; @@ -599,7 +598,7 @@ static int cmd_hf_fido_authenticate(const char *cmd) { data, 32, // challenge parameter NULL, 0); (void)res; - //PrintAndLogEx(NORMAL, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + //PrintAndLogEx(INFO, "--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(MBEDTLS_ECP_DP_SECP256R1, public_key, xbuf, xbuflen, &buf[5], len - 5, true); if (res) { if (res == MBEDTLS_ERR_ECP_VERIFY_FAILED) { @@ -718,7 +717,7 @@ static int cmd_hf_fido_2make_credential(const char *cmd) { PrintAndLogEx(ERR, "ERROR: Can't found the json file."); return res; } - PrintAndLogEx(NORMAL, "fname: %s\n", fname); + PrintAndLogEx(INFO, "fname: %s\n", fname); json_t *root = json_load_file(fname, 0, &error); if (!root) { PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text); @@ -843,7 +842,7 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { PrintAndLogEx(ERR, "ERROR: Can't found the json file."); return res; } - PrintAndLogEx(NORMAL, "fname: %s\n", fname); + PrintAndLogEx(INFO, "fname: %s\n", fname); json_t *root = json_load_file(fname, 0, &error); if (!root) { PrintAndLogEx(ERR, "ERROR: json error on line %d: %s", error.line, error.text); @@ -876,9 +875,9 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { if (showCBOR) { PrintAndLogEx(SUCCESS, "CBOR get assertion request:"); - PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------"); + PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------"); TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); - PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------"); + PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------"); } res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); @@ -901,9 +900,9 @@ static int cmd_hf_fido_2get_assertion(const char *cmd) { PrintAndLogEx(SUCCESS, "GetAssertion result (%zu b) OK.", len); if (showCBOR) { PrintAndLogEx(SUCCESS, "CBOR get assertion response:"); - PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------"); + PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------"); TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); - PrintAndLogEx(NORMAL, "---------------- " _CYAN_("CBOR") " ------------------"); + PrintAndLogEx(INFO, "---------------- " _CYAN_("CBOR") " ------------------"); } // parse returned cbor diff --git a/client/src/cmdhficlass.c b/client/src/cmdhficlass.c index 38a313186..284317a47 100644 --- a/client/src/cmdhficlass.c +++ b/client/src/cmdhficlass.c @@ -43,11 +43,11 @@ static int CmdHelp(const char *Cmd); static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { { 0xAE, 0xA6, 0x84, 0xA6, 0xDA, 0xB2, 0x32, 0x78 }, { 0x76, 0x65, 0x54, 0x43, 0x32, 0x21, 0x10, 0x00 }, - { 0x5B, 0x7C, 0x62, 0xC4, 0x91, 0xc1, 0x1b, 0x39 }, { 0xF0, 0xE1, 0xD2, 0xC3, 0xB4, 0xA5, 0x96, 0x87 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } }; @@ -71,74 +71,6 @@ static int usage_hf_iclass_sim(void) { PrintAndLogEx(NORMAL, ""); return PM3_SUCCESS; } - -static int usage_hf_iclass_esave(void) { - PrintAndLogEx(NORMAL, "Save emulator memory to file."); - PrintAndLogEx(NORMAL, "if not filename is supplied, CSN will be used."); - PrintAndLogEx(NORMAL, "Number of bytes to download defaults to 256. Other value is 2048\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass esave [h] [f ] [s ]\n"); - PrintAndLogEx(NORMAL, "Options"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " f : filename of dump"); - PrintAndLogEx(NORMAL, " s : (256|2048) number of bytes to save (default 256)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave f hf-iclass-dump.bin")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass esave s 2048 f hf-iclass-dump.bin")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} -static int usage_hf_iclass_eview(void) { - PrintAndLogEx(NORMAL, "It displays emulator memory"); - PrintAndLogEx(NORMAL, "Number of bytes to download defaults to 256. Other value is 2048\n"); - PrintAndLogEx(NORMAL, " Usage: hf iclass eview [s ] "); - PrintAndLogEx(NORMAL, " s : (256|2048) number of bytes to save (default 256)"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview")); - PrintAndLogEx(NORMAL, _YELLOW_(" hf iclass eview s 2048 v")); - return PM3_SUCCESS; -} -static int usage_hf_iclass_decrypt(void) { - PrintAndLogEx(NORMAL, "3DES decrypt data\n"); - PrintAndLogEx(NORMAL, "This is naive implementation, it tries to decrypt every block after block 6."); - PrintAndLogEx(NORMAL, "Correct behaviour would be to decrypt only the application areas where the key is valid,"); - PrintAndLogEx(NORMAL, "which is defined by the configuration block."); - PrintAndLogEx(NORMAL, "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); - PrintAndLogEx(NORMAL, "in the resources directory. The file should be 16 bytes binary data\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass decrypt d f k \n"); - PrintAndLogEx(NORMAL, "Options"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " d : 16 bytes hex"); - PrintAndLogEx(NORMAL, " f : filename of dump"); - PrintAndLogEx(NORMAL, " k : 16 bytes hex"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass decrypt f hf-iclass-AA162D30F8FF12F1-dump.bin")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass decrypt f hf-iclass-AA162D30F8FF12F1-dump.bin k 000102030405060708090a0b0c0d0e0f")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass decrypt d 1122334455667788 k 000102030405060708090a0b0c0d0e0f")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} -static int usage_hf_iclass_encrypt(void) { - PrintAndLogEx(NORMAL, "3DES encrypt data\n"); - PrintAndLogEx(NORMAL, "OBS! In order to use this function, the file " _YELLOW_("'iclass_decryptionkey.bin'") " must reside"); - PrintAndLogEx(NORMAL, "in the resources directory. The file should be 16 bytes binary data\n"); - PrintAndLogEx(NORMAL, "Usage: hf iclass encrypt d k \n"); - PrintAndLogEx(NORMAL, "Options"); - PrintAndLogEx(NORMAL, " h : Show this help"); - PrintAndLogEx(NORMAL, " d : 16 bytes hex"); - PrintAndLogEx(NORMAL, " k : 16 bytes hex"); - PrintAndLogEx(NORMAL, " v : verbose output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass encrypt d 0102030405060708")); - PrintAndLogEx(NORMAL, _YELLOW_("\thf iclass encrypt d 0102030405060708 k 00112233445566778899AABBCCDDEEFF")); - PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; -} static int usage_hf_iclass_dump(void) { PrintAndLogEx(NORMAL, "Dump all memory from a iCLASS tag\n"); PrintAndLogEx(NORMAL, "Usage: hf iclass dump f k c [e|r|v]\n"); @@ -779,7 +711,7 @@ static int CmdHFiClassSim(const char *Cmd) { SendCommandMIX(CMD_HF_ICLASS_SIMULATE, sim_type, numberOfCSNs, 1, CSN, 8); if (sim_type == ICLASS_SIM_MODE_FULL) - PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass esave h") "` to save the emulator memory to file"); + PrintAndLogEx(HINT, "Try `" _YELLOW_("hf iclass esave -h") "` to save the emulator memory to file"); break; } } @@ -961,47 +893,36 @@ static int CmdHFiClassELoad(const char *Cmd) { PrintAndLogEx(SUCCESS, "sent %d bytes of data to device emulator memory", bytes_sent); return PM3_SUCCESS; } - static int CmdHFiClassESave(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass esave", + "Save emulator memory to file.\n" + "if filename is not supplied, CSN will be used.", + "hf iclass esave\n" + "hf iclass esave -f hf-iclass-dump\n" + "hf iclass esave -s 2048 -f hf-iclass-dump"); + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of dumpfile"), + arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + int fnlen = 0; char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); char *fnameptr = filename; - int len = 0; - uint16_t bytes = 256; - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_esave(); - case 'f': - len = param_getstr(Cmd, cmdp + 1, filename, FILE_PATH_SIZE); - if (len >= FILE_PATH_SIZE) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - case 's': - bytes = param_get32ex(Cmd, cmdp + 1, 256, 10); - if (bytes > 4096) { - PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes); - bytes = 4096; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + + uint16_t bytes = arg_get_int_def(ctx, 2, 256); + + if (bytes > 4096) { + PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes); + bytes = 4096; } - //Validations - if (errors) { - return usage_hf_iclass_esave(); - } + CLIParserFree(ctx); uint8_t *dump = calloc(bytes, sizeof(uint8_t)); if (dump == NULL) { @@ -1017,7 +938,7 @@ static int CmdHFiClassESave(const char *Cmd) { } // user supplied filename? - if (len < 1) { + if (fnlen < 1) { fnameptr += snprintf(fnameptr, sizeof(filename), "hf-iclass-"); FillFileNameByUID(fnameptr, dump, "-dump", 8); } @@ -1032,44 +953,37 @@ static int CmdHFiClassESave(const char *Cmd) { } static int CmdHFiClassEView(const char *Cmd) { + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf iclass eview", + "Display emulator memory.\n" + "Number of bytes to download defaults to 256. Other value is 2048.", + "hf iclass eview\n" + "hf iclass eview -s 2048\n" + "hf iclass eview -s 2048 -v"); - uint16_t blocks = 32, bytes = 256; - bool errors = false, verbose = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_eview(); - case 's': - bytes = param_get32ex(Cmd, cmdp + 1, 256, 10); + void *argtable[] = { + arg_param_begin, + arg_int0("s", "size", "<256|2048>", "number of bytes to save (default 256)"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); - if (bytes > 4096) { - PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes); - bytes = 4096; - } + uint16_t blocks = 32; + uint16_t bytes = arg_get_int_def(ctx, 1, 256); + bool verbose = arg_get_lit(ctx, 2); + blocks = bytes / 8; - if (bytes % 8 != 0) { - bytes &= 0xFFF8; - PrintAndLogEx(WARNING, "Number not divided by 8, truncating to %u", bytes); - } + CLIParserFree(ctx); - blocks = bytes / 8; - cmdp += 2; - break; - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + if (bytes > 4096) { + PrintAndLogEx(WARNING, "Emulator memory is max 4096bytes. Truncating %u to 4096", bytes); + bytes = 4096; } - //Validations - if (errors || bytes == 0) { - return usage_hf_iclass_eview(); + if (bytes % 8 != 0) { + bytes &= 0xFFF8; + PrintAndLogEx(WARNING, "Number not divided by 8, truncating to %u", bytes); } uint8_t *dump = calloc(bytes, sizeof(uint8_t)); @@ -1096,74 +1010,82 @@ static int CmdHFiClassEView(const char *Cmd) { free(dump); return PM3_SUCCESS; } - static int CmdHFiClassDecrypt(const char *Cmd) { + CLIParserContext *clictx; + CLIParserInit(&clictx, "hf iclass decrypt", + "3DES decrypt data\n" + "This is a naive implementation, it tries to decrypt every block after block 6.\n" + "Correct behaviour would be to decrypt only the application areas where the key is valid,\n" + "which is defined by the configuration block.\n" + "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside\n" + "in the resources directory. The file should be 16 bytes binary data", + "hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin\n" + "hf iclass decrypt -f hf-iclass-AA162D30F8FF12F1-dump.bin -k 000102030405060708090a0b0c0d0e0f\n" + "hf iclass decrypt -d 1122334455667788 -k 000102030405060708090a0b0c0d0e0f"); - bool errors = false; - bool have_key = false; - bool have_data = false; - bool have_file = false; - bool verbose = false; - uint8_t cmdp = 0; + void *argtable[] = { + arg_param_begin, + arg_str0("f", "file", "", "filename of dumpfile"), + arg_str0("d", "data", "", "3DES encrypted data"), + arg_str0("k", "key", "", "3DES transport key"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(clictx, Cmd, argtable, false); - uint8_t enc_data[8] = {0}; - uint8_t dec_data[8] = {0}; - - size_t keylen = 0; - uint8_t key[32] = {0}; - uint8_t *keyptr = NULL; + int fnlen = 0; + char filename[FILE_PATH_SIZE] = {0}; + CLIParamStrToBuf(arg_get_str(clictx, 1), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen); size_t decryptedlen = 0; uint8_t *decrypted = NULL; - char filename[FILE_PATH_SIZE]; + bool have_file = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_decrypt(); - case 'd': - if (param_gethex(Cmd, cmdp + 1, enc_data, 16)) { - PrintAndLogEx(ERR, "Data must be 16 HEX symbols"); - errors = true; - break; - } - have_data = true; - cmdp += 2; - break; - case 'f': - if (param_getstr(Cmd, cmdp + 1, filename, sizeof(filename)) == 0) { - PrintAndLogEx(WARNING, "No filename found after f"); - errors = true; - break; - } - - if (loadFile_safe(filename, "", (void **)&decrypted, &decryptedlen) != PM3_SUCCESS) { - errors = true; - break; - } - have_file = true; - cmdp += 2; - break; - case 'k': - if (param_gethex(Cmd, cmdp + 1, key, 32)) { - PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); - errors = true; - } - have_key = true; - cmdp += 2; - break; - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; + if (fnlen > 0) { + if (loadFile_safe(filename, "", (void **)&decrypted, &decryptedlen) != PM3_SUCCESS) { + CLIParserFree(clictx); + return PM3_EINVARG; } + have_file = true; } - if (errors || cmdp < 1) return usage_hf_iclass_decrypt(); + int enc_data_len = 0; + uint8_t enc_data[8] = {0}; + bool have_data = false; + + CLIGetHexWithReturn(clictx, 2, enc_data, &enc_data_len); + + if (enc_data_len > 0) { + if (enc_data_len != 8) { + PrintAndLogEx(ERR, "Data must be 8 bytes (16 HEX characters)"); + CLIParserFree(clictx); + return PM3_EINVARG; + } + have_data = true; + } + + int key_len = 0; + uint8_t key[16] = {0}; + uint8_t *keyptr = NULL; + bool have_key = false; + + CLIGetHexWithReturn(clictx, 3, key, &key_len); + + if (key_len > 0) { + if (key_len != 16) { + PrintAndLogEx(ERR, "Transport key must be 16 bytes (32 HEX characters)"); + CLIParserFree(clictx); + return PM3_EINVARG; + } + have_key = true; + } + + bool verbose = arg_get_lit(clictx, 4); + + CLIParserFree(clictx); + + size_t keylen = 0; + uint8_t dec_data[8] = {0}; bool use_sc = IsCryptoHelperPresent(verbose); @@ -1330,45 +1252,53 @@ static void iclass_encrypt_block_data(uint8_t *blk_data, uint8_t *key) { } static int CmdHFiClassEncryptBlk(const char *Cmd) { - bool errors = false; - bool have_key = false; - bool verbose = false; - uint8_t blk_data[8] = {0}; - uint8_t key[16] = {0}; - uint8_t *keyptr = NULL; - uint8_t cmdp = 0; + CLIParserContext *clictx; + CLIParserInit(&clictx, "hf iclass encrypt", + "3DES encrypt data\n" + "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside\n" + "in the resources directory. The file should be 16 bytes binary data", + "hf iclass encrypt -d 0102030405060708\n" + "hf iclass encrypt -d 0102030405060708 -k 00112233445566778899AABBCCDDEEFF"); - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_iclass_encrypt(); - case 'd': - if (param_gethex(Cmd, cmdp + 1, blk_data, 16)) { - PrintAndLogEx(ERR, "Block data must include 16 HEX symbols"); - errors = true; - } - cmdp += 2; - break; - case 'k': - if (param_gethex(Cmd, cmdp + 1, key, 32)) { - PrintAndLogEx(ERR, "Transport key must include 32 HEX symbols"); - errors = true; - } - have_key = true; - cmdp += 2; - break; - case 'v': - verbose = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } + void *argtable[] = { + arg_param_begin, + arg_str1("d", "data", "", "data to encrypt"), + arg_str0("k", "key", "", "3DES transport key"), + arg_lit0("v", "verbose", "verbose output"), + arg_param_end + }; + CLIExecWithReturn(clictx, Cmd, argtable, false); + + int blk_data_len = 0; + uint8_t blk_data[8] = {0}; + + CLIGetHexWithReturn(clictx, 1, blk_data, &blk_data_len); + + if (blk_data_len != 8) { + PrintAndLogEx(ERR, "Block data must be 8 bytes (16 HEX characters)"); + CLIParserFree(clictx); + return PM3_EINVARG; } - if (errors || cmdp < 1) return usage_hf_iclass_encrypt(); + int key_len = 0; + uint8_t key[16] = {0}; + uint8_t *keyptr = NULL; + bool have_key = false; + + CLIGetHexWithReturn(clictx, 2, key, &key_len); + + if (key_len > 0) { + if (key_len != 16) { + PrintAndLogEx(ERR, "Transport key must be 16 bytes (32 HEX characters)"); + CLIParserFree(clictx); + return PM3_EINVARG; + } + have_key = true; + } + + bool verbose = arg_get_lit(clictx, 3); + + CLIParserFree(clictx); bool use_sc = IsCryptoHelperPresent(verbose); @@ -1760,7 +1690,7 @@ write_dump: return PM3_SUCCESS; } -static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose) { +static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_credit_key, bool elite, bool rawkey, bool replay, bool verbose, bool use_secure_pagemode) { iclass_writeblock_req_t payload = { .req.use_raw = rawkey, @@ -1769,7 +1699,7 @@ static int iclass_write_block(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bo .req.use_replay = replay, .req.blockno = blockno, .req.send_reply = true, - .req.do_auth = true, + .req.do_auth = use_secure_pagemode, }; memcpy(payload.req.key, KEY, 8); memcpy(payload.data, bldata, sizeof(payload.data)); @@ -1804,6 +1734,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { bool use_replay = false; bool errors = false; bool verbose = false; + bool use_secure_pagemode = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -1848,6 +1779,7 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { PrintAndLogEx(WARNING, "\nERROR: Credit Key is incorrect length\n"); errors = true; } + use_secure_pagemode = true; cmdp += 2; break; case 'r': @@ -1880,9 +1812,9 @@ static int CmdHFiClass_WriteBlock(const char *Cmd) { errors = true; } - if (errors || cmdp < 6) return usage_hf_iclass_writeblock(); + if (errors || cmdp < 4) return usage_hf_iclass_writeblock(); - int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose); + int isok = iclass_write_block(blockno, bldata, KEY, use_credit_key, elite, rawkey, use_replay, verbose, use_secure_pagemode); switch (isok) { case PM3_SUCCESS: PrintAndLogEx(SUCCESS, "Wrote block %02X successful", blockno); @@ -3425,6 +3357,7 @@ static int CmdHFiClassPermuteKey(const char *Cmd) { return PM3_SUCCESS; } +/* static int CmdHFiClassAutopwn(const char *Cmd) { CLIParserContext *ctx; @@ -3446,6 +3379,7 @@ static int CmdHFiClassAutopwn(const char *Cmd) { PrintAndLogEx(INFO, "to be implemented"); return PM3_SUCCESS; } +*/ static command_t CommandTable[] = { {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("operations") " ---------------------"}, @@ -3461,7 +3395,7 @@ static command_t CommandTable[] = { {"wrbl", CmdHFiClass_WriteBlock, IfPm3Iclass, "[options..] Write Picopass / iCLASS block"}, {"-----------", CmdHelp, AlwaysAvailable, "--------------------- " _CYAN_("recovery") " ---------------------"}, - {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "[options..] Automatic key recovery tool for iCLASS"}, +// {"autopwn", CmdHFiClassAutopwn, IfPm3Iclass, "[options..] Automatic key recovery tool for iCLASS"}, {"chk", CmdHFiClassCheckKeys, IfPm3Iclass, "[options..] Check keys"}, {"loclass", CmdHFiClass_loclass, AlwaysAvailable, "[options..] Use loclass to perform bruteforce reader attack"}, {"lookup", CmdHFiClassLookUp, AlwaysAvailable, "[options..] Uses authentication trace to check for key in dictionary file"}, @@ -3565,10 +3499,11 @@ int info_iclass(void) { PrintAndLogEx(INFO, "------------------------ " _CYAN_("Fingerprint") " -----------------------"); uint8_t aia[8]; - if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) + if (pagemap == PICOPASS_NON_SECURE_PAGEMODE) { memcpy(aia, ns_hdr->app_issuer_area, sizeof(aia)); - else + } else { memcpy(aia, hdr->app_issuer_area, sizeof(aia)); + } // if CSN ends with FF12E0, it's inside HID CSN range. bool isHidRange = (memcmp(hdr->csn + 5, "\xFF\x12\xE0", 3) == 0); @@ -3583,11 +3518,13 @@ int info_iclass(void) { if (se_enabled) PrintAndLogEx(SUCCESS, " Credential... " _GREEN_("iCLASS SE")); } else { - PrintAndLogEx(SUCCESS, " CSN..-....... " _YELLOW_("outside HID range")); + PrintAndLogEx(SUCCESS, " CSN.......... " _YELLOW_("outside HID range")); } uint8_t cardtype = get_mem_config(hdr); PrintAndLogEx(SUCCESS, " Card type.... " _GREEN_("%s"), card_types[cardtype]); + + } DropField(); diff --git a/client/src/cmdhflto.c b/client/src/cmdhflto.c index ab79423a4..69dab2108 100644 --- a/client/src/cmdhflto.c +++ b/client/src/cmdhflto.c @@ -28,6 +28,7 @@ If you have access to datasheet, le me know! LTO w Type info 00 01 has 101 blocks. + LTO w Type info 00 02 has 95 blocks. LTO w Type info 00 03 has 255 blocks. LTO w Type info 00 xx has NN blocks. */ @@ -242,18 +243,18 @@ static int CmdHfLTOList(const char *Cmd) { return CmdTraceList(args); } -static int lto_rdbl(uint8_t blk, uint8_t *block_responce, uint8_t *block_cnt_responce, bool verbose) { +static int lto_rdbl(uint8_t blk, uint8_t *block_response, uint8_t *block_cnt_response, bool verbose) { uint16_t resp_len = 18; uint8_t rdbl_cmd[] = {0x30, blk}; uint8_t rdbl_cnt_cmd[] = {0x80}; - int status = lto_send_cmd_raw(rdbl_cmd, sizeof(rdbl_cmd), block_responce, &resp_len, true, false, verbose); + int status = lto_send_cmd_raw(rdbl_cmd, sizeof(rdbl_cmd), block_response, &resp_len, true, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { return PM3_EWRONGANSWER; // READ BLOCK failed } - status = lto_send_cmd_raw(rdbl_cnt_cmd, sizeof(rdbl_cnt_cmd), block_cnt_responce, &resp_len, false, false, verbose); + status = lto_send_cmd_raw(rdbl_cnt_cmd, sizeof(rdbl_cnt_cmd), block_cnt_response, &resp_len, false, false, verbose); if (status == PM3_ETIMEOUT || status == PM3_ESOFT) { return PM3_EWRONGANSWER; // READ BLOCK CONTINUE failed } diff --git a/client/src/cmdhfmf.c b/client/src/cmdhfmf.c index b6a1592bb..481a5ce14 100644 --- a/client/src/cmdhfmf.c +++ b/client/src/cmdhfmf.c @@ -16,7 +16,6 @@ #include "comms.h" // clearCommandBuffer #include "fileutils.h" #include "cmdtrace.h" -#include "emv/dump.h" #include "mifare/mifaredefault.h" // mifare default key array #include "cliparser.h" // argtable #include "hardnested_bf_core.h" // SetSIMDInstr @@ -5095,7 +5094,7 @@ static int CmdHFMFNDEF(const char *Cmd) { if (verbose2) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("MFC NDEF raw") " ----------------"); - dump_buffer(data, datalen, stdout, 1); + print_buffer(data, datalen, 1); } NDEFDecodeAndPrint(data, datalen, verbose); @@ -5445,7 +5444,7 @@ static command_t CommandTable[] = { {"esave", CmdHF14AMfESave, IfPm3Iso14443a, "Save to file emul dump"}, {"eset", CmdHF14AMfESet, IfPm3Iso14443a, "Set simulator memory block"}, {"eview", CmdHF14AMfEView, IfPm3Iso14443a, "View emul memory"}, - {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic") " -----------------------"}, + {"-----------", CmdHelp, IfPm3Iso14443a, "----------------------- " _CYAN_("magic gen1") " -----------------------"}, {"cgetblk", CmdHF14AMfCGetBlk, IfPm3Iso14443a, "Read block"}, {"cgetsc", CmdHF14AMfCGetSc, IfPm3Iso14443a, "Read sector"}, {"cload", CmdHF14AMfCLoad, IfPm3Iso14443a, "Load dump"}, diff --git a/client/src/cmdhfmfdes.c b/client/src/cmdhfmfdes.c index 135798737..f2282dbfd 100644 --- a/client/src/cmdhfmfdes.c +++ b/client/src/cmdhfmfdes.c @@ -35,12 +35,22 @@ #include "mifare/mad.h" #include "generator.h" #include "aiddesfire.h" +#include "util.h" #define MAX_KEY_LEN 24 #define MAX_KEYS_LIST_LEN 1024 #define status(x) ( ((uint16_t)(0x91<<8)) + (uint16_t)x ) +#ifndef DropFieldDesfire +#define DropFieldDesfire() { \ + clearCommandBuffer(); \ + SendCommandNG(CMD_HF_DROPFIELD, NULL, 0); \ + tag->rf_field_on = false; \ + PrintAndLogEx(DEBUG, "field dropped"); \ + } +#endif + struct desfire_key default_key = {0}; uint8_t desdefaultkeys[3][8] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, //Official @@ -60,7 +70,7 @@ uint8_t k3kdefaultkeys[1][24] = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 struct desfire_tag mf_state = {.session_key = NULL, .authentication_scheme = AS_LEGACY, .authenticated_key_no = NOT_YET_AUTHENTICATED, .crypto_buffer = NULL, .crypto_buffer_size = 0, .selected_application = 0}; static desfiretag_t tag = &mf_state; -typedef struct { +typedef struct mfdes_authinput { uint8_t mode; uint8_t algo; uint8_t keyno; @@ -85,7 +95,7 @@ typedef struct mfdes_data { uint8_t *data; } PACKED mfdes_data_t; -typedef struct { +typedef struct mfdes_info_res { uint8_t isOK; uint8_t uid[7]; uint8_t uidlen; @@ -94,7 +104,6 @@ typedef struct { uint8_t details[14]; } PACKED mfdes_info_res_t; - typedef struct mfdes_value { uint8_t fileno; //01 uint8_t value[16]; @@ -340,11 +349,19 @@ typedef enum { NTAG413DNA, } nxp_cardtype_t; -typedef struct { +typedef struct dfname { uint8_t aid[3]; uint8_t fid[2]; uint8_t name[16]; -} dfname_t; +} PACKED dfname_t; + +typedef struct aidhdr { + uint8_t aid[3]; + uint8_t keysetting1; + uint8_t keysetting2; + uint8_t fid[2]; + uint8_t name[16]; +} PACKED aidhdr_t; static int CmdHelp(const char *Cmd); @@ -378,9 +395,9 @@ static char *getCardSizeStr(uint8_t fsize) { // is LSB set? if (fsize & 1) - snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d - %d bytes") ")", fsize, usize, lsize); + snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d - %d bytes") " )", fsize, usize, lsize); else - snprintf(retStr, sizeof(buf), "0x%02X (" _GREEN_("%d bytes") ")", fsize, lsize); + snprintf(retStr, sizeof(buf), "0x%02X ( " _GREEN_("%d bytes") " )", fsize, lsize); return buf; } @@ -390,14 +407,14 @@ static char *getProtocolStr(uint8_t id, bool hw) { char *retStr = buf; if (id == 0x04) { - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3 MIFARE, 14443-4") ")", id); + snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3 MIFARE, 14443-4") " )", id); } else if (id == 0x05) { if (hw) - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-2, 14443-3") ")", id); + snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-2, 14443-3") " )", id); else - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("ISO 14443-3, 14443-4") ")", id); + snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("ISO 14443-3, 14443-4") " )", id); } else { - snprintf(retStr, sizeof(buf), "0x%02X (" _YELLOW_("Unknown") ")", id); + snprintf(retStr, sizeof(buf), "0x%02X ( " _YELLOW_("Unknown") " )", id); } return buf; } @@ -408,19 +425,21 @@ static char *getVersionStr(uint8_t major, uint8_t minor) { char *retStr = buf; if (major == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire MF3ICD40") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire MF3ICD40") " )", major, minor); else if (major == 0x01 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV1") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV1") " )", major, minor); else if (major == 0x12 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV2") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor); + else if (major == 0x42 && minor == 0x00) + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV2") " )", major, minor); else if (major == 0x33 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire EV3") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire EV3") " )", major, minor); else if (major == 0x30 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("DESFire Light") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("DESFire Light") " )", major, minor); else if (major == 0x10 && minor == 0x00) - snprintf(retStr, sizeof(buf), "%x.%x (" _GREEN_("NTAG413DNA") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _GREEN_("NTAG413DNA") " )", major, minor); else - snprintf(retStr, sizeof(buf), "%x.%x (" _YELLOW_("Unknown") ")", major, minor); + snprintf(retStr, sizeof(buf), "%x.%x ( " _YELLOW_("Unknown") " )", major, minor); return buf; //04 01 01 01 00 1A 05 @@ -435,7 +454,7 @@ static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, int res = 0; if (activate_field) { - DropField(); + DropFieldDesfire(); msleep(50); } @@ -458,6 +477,11 @@ static int DESFIRESendApdu(bool activate_field, bool leavefield_on, sAPDU apdu, return res; } + if (activate_field) { + PrintAndLogEx(DEBUG, "field up"); + tag->rf_field_on = true; + } + if (GetAPDULogging() || (g_debugMode > 1)) PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(result, *result_len)); @@ -625,7 +649,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *r int res = DESFIRESendApdu(select, true, *apdu, data, sizeof(data), &resplen, sw); if (res != PM3_SUCCESS) { PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); - DropField(); + DropFieldDesfire(); return res; } if (dest != NULL) { @@ -650,7 +674,7 @@ static int send_desfire_cmd(sAPDU *apdu, bool select, uint8_t *dest, uint32_t *r res = DESFIRESendApdu(false, true, *apdu, data, sizeof(data), &resplen, sw); if (res != PM3_SUCCESS) { PrintAndLogEx(DEBUG, "%s", GetErrorString(res, sw)); - DropField(); + DropFieldDesfire(); return res; } @@ -696,7 +720,7 @@ static int mfdes_get_info(mfdes_info_res_t *info) { if (WaitForResponseTimeout(CMD_HF_DESFIRE_INFO, &resp, 1500) == false) { PrintAndLogEx(WARNING, "Command execute timeout"); - DropField(); + DropFieldDesfire(); return PM3_ETIMEOUT; } @@ -721,7 +745,6 @@ static int mfdes_get_info(mfdes_info_res_t *info) { return PM3_SUCCESS; } - static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rpayload) { // 3 different way to authenticate AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 different crypto arg1 DES, 3DES, 3K3DES, AES @@ -770,9 +793,7 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp if (payload->kdfAlgo == MFDES_KDF_ALGO_AN10922) { mifare_kdf_an10922(key, payload->kdfInput, payload->kdfInputLen); - if (g_debugMode) { - PrintAndLogEx(INFO, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); - } + PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); } else if (payload->kdfAlgo == MFDES_KDF_ALGO_GALLAGHER) { // We will overrite any provided KDF input since a gallagher specific KDF was requested. payload->kdfInputLen = 11; @@ -782,11 +803,9 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } mifare_kdf_an10922(key, payload->kdfInput, payload->kdfInputLen); + PrintAndLogEx(DEBUG, " KDF Input: " _YELLOW_("%s"), sprint_hex(payload->kdfInput, payload->kdfInputLen)); + PrintAndLogEx(DEBUG, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); - if (g_debugMode) { - PrintAndLogEx(INFO, " KDF Input: " _YELLOW_("%s"), sprint_hex(payload->kdfInput, payload->kdfInputLen)); - PrintAndLogEx(INFO, " Derrived key: " _GREEN_("%s"), sprint_hex(key->data, key_block_size(key))); - } } uint8_t subcommand = MFDES_AUTHENTICATE; @@ -859,8 +878,8 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } if (g_debugMode > 1) { - PrintAndLogEx(INFO, "encRndB: %s", sprint_hex(encRndB, 8)); - PrintAndLogEx(INFO, "RndB: %s", sprint_hex(RndB, 8)); + PrintAndLogEx(DEBUG, "encRndB: %s", sprint_hex(encRndB, 8)); + PrintAndLogEx(DEBUG, "RndB: %s", sprint_hex(RndB, 8)); } // - Rotate RndB by 8 bits @@ -886,24 +905,24 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); - PrintAndLogEx(INFO, "Both: %s", sprint_hex(tmp, 16)); + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both: %s", sprint_hex(tmp, 16)); } tdes_nxp_send(tmp, both, 16, key->data, IV, 2); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "EncBoth: %s", sprint_hex(both, 16)); + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 16)); } } else if (payload->algo == MFDES_ALGO_3K3DES) { uint8_t tmp[32] = {0x00}; memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); - PrintAndLogEx(INFO, "Both3k3: %s", sprint_hex(tmp, 32)); + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32)); } tdes_nxp_send(tmp, both, 32, key->data, IV, 3); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "EncBoth: %s", sprint_hex(both, 32)); + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); } } } else if (payload->mode == MFDES_AUTH_AES) { @@ -911,8 +930,8 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp memcpy(tmp, RndA, rndlen); memcpy(tmp + rndlen, rotRndB, rndlen); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); - PrintAndLogEx(INFO, "Both3k3: %s", sprint_hex(tmp, 32)); + PrintAndLogEx(DEBUG, "rotRndB: %s", sprint_hex(rotRndB, rndlen)); + PrintAndLogEx(DEBUG, "Both3k3: %s", sprint_hex(tmp, 32)); } if (payload->algo == MFDES_ALGO_AES) { if (mbedtls_aes_setkey_enc(&ctx, key->data, 128) != 0) { @@ -920,7 +939,7 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp } mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, 32, IV, tmp, both); if (g_debugMode > 1) { - PrintAndLogEx(INFO, "EncBoth: %s", sprint_hex(both, 32)); + PrintAndLogEx(DEBUG, "EncBoth: %s", sprint_hex(both, 32)); } } } @@ -989,8 +1008,8 @@ static int handler_desfire_auth(mfdes_authinput_t *payload, mfdes_auth_res_t *rp for (uint32_t x = 0; x < rndlen; x++) { if (RndA[x] != encRndA[x]) { if (g_debugMode > 1) { - PrintAndLogEx(INFO, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); - PrintAndLogEx(INFO, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); + PrintAndLogEx(DEBUG, "Expected_RndA : %s", sprint_hex(RndA, rndlen)); + PrintAndLogEx(DEBUG, "Generated_RndA : %s", sprint_hex(encRndA, rndlen)); } return 11; } @@ -1055,7 +1074,7 @@ static int test_desfire_authenticate(void) { int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); if (res == PM3_SUCCESS) if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1070,7 +1089,7 @@ static int test_desfire_authenticate_iso(void) { int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); if (res == PM3_SUCCESS) if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1085,7 +1104,7 @@ static int test_desfire_authenticate_aes(void) { int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, 0, false); if (res == PM3_SUCCESS) if (sw == status(MFDES_ADDITIONAL_FRAME)) { - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1158,27 +1177,40 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n break; } } + /* + keyno 1b + key 8b + cpy 8b + crc 2b + padding + */ - // Variable length ciphered key data 26-42 bytes plus padding.. + // Variable length ciphered key data 24-42 bytes plus padding.. uint8_t data[64] = {key_no}; sAPDU apdu = {0x90, MFDES_CHANGE_KEY, 0x00, 0x00, 0x01, data}; // 0xC4 + size_t cmdcnt = 0; + uint8_t new_key_length = 16; switch (new_algo) { case MFDES_ALGO_DES: - new_key_length = 8; + // double + memcpy(data + cmdcnt + 1, new_key, new_key_length); + memcpy(data + cmdcnt + 1 + new_key_length, new_key, new_key_length); break; case MFDES_ALGO_3DES: case MFDES_ALGO_AES: new_key_length = 16; + memcpy(data + cmdcnt + 1, new_key, new_key_length); break; case MFDES_ALGO_3K3DES: new_key_length = 24; + memcpy(data + cmdcnt + 1, new_key, new_key_length); break; } - size_t cmdcnt = 0; - memcpy(data + cmdcnt + 1, new_key, new_key_length); + + if ((tag->authenticated_key_no & 0x0f) != (key_no & 0x0f)) { if (old_key) { @@ -1234,7 +1266,7 @@ static int mifare_desfire_change_key(uint8_t key_no, uint8_t *new_key, uint8_t n if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't change key -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } @@ -1278,7 +1310,7 @@ static int desfire_print_signature(uint8_t *uid, uint8_t uidlen, uint8_t *signat {"DESFire EV3", "041DB46C145D0A36539C6544BD6D9B0AA62FF91EC48CBC6ABAE36E0089A46F0D08C8A715EA40A63313B92E90DDC1730230E0458A33276FB743"}, {"NTAG424DNA, NTAG424DNATT, DESFire Light EV2", "04B304DC4C615F5326FE9383DDEC9AA892DF3A57FA7FFB3276192BC0EAA252ED45A865E3B093A3D0DCE5BE29E92F1392CE7DE321E3E5C52B3B"}, {"DESFire Light", "040E98E117AAA36457F43173DC920A8757267F44CE4EC5ADD3C54075571AEBBF7B942A9774A1D94AD02572427E5AE0A2DD36591B1FB34FCF3D"}, - {"Mifare Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"} + {"MIFARE Plus EV1", "044409ADC42F91A8394066BA83D872FB1D16803734E911170412DDF8BAD1A4DADFD0416291AFE1C748253925DA39A5F39A1C557FFACD34C62E"} }; @@ -1347,19 +1379,47 @@ static int handler_desfire_signature(uint8_t *signature, size_t *signature_len) *signature_len = recv_len; } } - DropField(); + DropFieldDesfire(); return res; } -// --- KEY SETTING -static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) { +// --- KEY VERSION +static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) { + PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version); + return PM3_SUCCESS; +} + +static int handler_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { + if (num_versions == NULL) { + PrintAndLogEx(DEBUG, "NUM_VERSIONS=NULL"); + return PM3_EINVARG; + } + sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64 + uint32_t recv_len = 0; + uint16_t sw = 0; + int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true); + + if (res != PM3_SUCCESS) + return res; + + if (sw != status(MFDES_S_OPERATION_OK)) + return PM3_ESOFT; + + return res; +} + +// --- KEY SETTING Application Master Key +static int desfire_print_amk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) { PrintAndLogEx(SUCCESS, " AID Key settings : 0x%02x", key_settings); // 2 MSB denotes const char *str = " Max key number and type : %d, " _YELLOW_("%s"); - if (algo == MFDES_ALGO_DES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "(3)DES"); - else if (algo == MFDES_ALGO_AES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "AES"); - else if (algo == MFDES_ALGO_3K3DES) PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "3K3DES"); + if (algo == MFDES_ALGO_DES) + PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "(3)DES"); + else if (algo == MFDES_ALGO_AES) + PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "AES"); + else if (algo == MFDES_ALGO_3K3DES) + PrintAndLogEx(SUCCESS, str, num_keys & 0x3F, "3K3DES"); //PrintAndLogEx(SUCCESS, " Max number of keys in AID : %d", num_keys & 0x3F); PrintAndLogEx(INFO, "-------------------------------------------------------------"); @@ -1378,14 +1438,69 @@ static int desfire_print_keysetting(uint8_t key_settings, uint8_t num_keys, int PrintAndLogEx(SUCCESS, " -- All keys (except AMK,see Bit0) within this application are frozen"); break; default: - PrintAndLogEx(SUCCESS, " -- Authentication with the specified key is necessary to change any key.\nA change key and a PICC master key (CMK) can only be changed after authentication with the master key.\nFor keys other then the master or change key, an authentication with the same key is needed."); + PrintAndLogEx(SUCCESS, + " -- Authentication with the specified key is necessary to change any key.\n" + "A change key and a PICC master key (CMK) can only be changed after authentication with the master key.\n" + "For keys other then the master or change key, an authentication with the same key is needed." + ); break; } - PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO"); - PrintAndLogEx(SUCCESS, " [0x04] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [0x02] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES"); - PrintAndLogEx(SUCCESS, " [0x01] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO"); + PrintAndLogEx(SUCCESS, " [1000] AMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, " [0100] AMK required for create/delete : %s", (key_settings & (1 << 2)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0010] Directory list access with AMK : %s", (key_settings & (1 << 1)) ? "NO" : "YES"); + PrintAndLogEx(SUCCESS, " [0001] AMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + return PM3_SUCCESS; +} + +// --- KEY SETTING PICC Master Key (CMK) +static int desfire_print_piccmk_keysetting(uint8_t key_settings, uint8_t num_keys, int algo) { + //PrintAndLogEx(INFO, "--- " _CYAN_("PICC Master Key (CMK) settings")); + // number of Master keys (0x01) + PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F)); + const char *str = " Operation of PICC master key : " _YELLOW_("%s"); + + if (algo == MFDES_ALGO_DES) + PrintAndLogEx(SUCCESS, str, "(3)DES"); + else if (algo == MFDES_ALGO_AES) + PrintAndLogEx(SUCCESS, str, "AES"); + else if (algo == MFDES_ALGO_3K3DES) + PrintAndLogEx(SUCCESS, str, "3K3DES"); + + uint8_t cmk_num_versions = 0; + if (handler_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions); + } + + PrintAndLogEx(INFO, " ----------------------------------------------------------"); + + // Authentication tests + int res = test_desfire_authenticate(); + if (res == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); + + res = test_desfire_authenticate_iso(); + if (res == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); + + res = test_desfire_authenticate_aes(); + if (res == PM3_SUCCESS) + PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); + + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, " Key setting: 0x%02X [%c%c%c%c]", + key_settings, + (key_settings & (1 << 3)) ? '1' : '0', + (key_settings & (1 << 2)) ? '1' : '0', + (key_settings & (1 << 1)) ? '1' : '0', + (key_settings & (1 << 0)) ? '1' : '0' + ); + + PrintAndLogEx(SUCCESS, " [1...] CMK Configuration changeable : %s", (key_settings & (1 << 3)) ? _GREEN_("YES") : "NO (frozen)"); + PrintAndLogEx(SUCCESS, " [.1..] CMK required for create/delete : %s", (key_settings & (1 << 2)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, " [..1.] Directory list access with CMK : %s", (key_settings & (1 << 1)) ? _GREEN_("NO") : "YES"); + PrintAndLogEx(SUCCESS, " [...1] CMK is changeable : %s", (key_settings & (1 << 0)) ? _GREEN_("YES") : "NO (frozen)"); + return PM3_SUCCESS; } @@ -1415,31 +1530,6 @@ static int handler_desfire_getkeysettings(uint8_t *key_settings, uint8_t *num_ke return res; } -// --- KEY VERSION -static int desfire_print_keyversion(uint8_t key_idx, uint8_t key_version) { - PrintAndLogEx(SUCCESS, " Key [%u] Version : %d (0x%02x)", key_idx, key_version, key_version); - return PM3_SUCCESS; -} - -static int handler_desfire_keyversion(uint8_t curr_key, uint8_t *num_versions) { - if (num_versions == NULL) { - PrintAndLogEx(DEBUG, "NUM_VERSIONS=NULL"); - return PM3_EINVARG; - } - sAPDU apdu = {0x90, MFDES_GET_KEY_VERSION, 0x00, 0x00, 0x01, &curr_key}; //0x64 - uint32_t recv_len = 0; - uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, false, num_versions, &recv_len, &sw, 0, true); - - if (res != PM3_SUCCESS) - return res; - - if (sw != status(MFDES_S_OPERATION_OK)) - return PM3_ESOFT; - - return res; -} - static int handler_desfire_getuid(uint8_t *uid) { if (uid == NULL) { PrintAndLogEx(DEBUG, "UID=NULL"); @@ -1544,16 +1634,26 @@ static int handler_desfire_dfnames(dfname_t *dest, uint8_t *dfname_count) { static int handler_desfire_select_application(uint8_t *aid) { if (g_debugMode > 1) { - if (aid == NULL) PrintAndLogEx(ERR, "AID=NULL"); + if (aid == NULL) { + PrintAndLogEx(ERR, "AID=NULL"); + } } - if (aid == NULL) return PM3_EINVARG; + if (aid == NULL) { + return PM3_EINVARG; + } + sAPDU apdu = {0x90, MFDES_SELECT_APPLICATION, 0x00, 0x00, 0x03, aid}; //0x5a uint32_t recv_len = 0; uint16_t sw = 0; - int res = send_desfire_cmd(&apdu, true, NULL, &recv_len, &sw, sizeof(dfname_t), true); + + int res = send_desfire_cmd(&apdu, !tag->rf_field_on, NULL, &recv_len, &sw, sizeof(dfname_t), true); if (res != PM3_SUCCESS) { - PrintAndLogEx(WARNING, _RED_(" Can't select AID 0x%X -> %s"), (aid[2] << 16) + (aid[1] << 8) + aid[0], GetErrorString(res, &sw)); - DropField(); + PrintAndLogEx(WARNING, + _RED_(" Can't select AID 0x%X -> %s"), + (aid[2] << 16) + (aid[1] << 8) + aid[0], + GetErrorString(res, &sw) + ); + DropFieldDesfire(); return res; } memcpy(&tag->selected_application, aid, 3); @@ -1595,7 +1695,7 @@ static int handler_desfire_fileids(uint8_t *dest, uint32_t *file_ids_len) { int res = send_desfire_cmd(&apdu, false, dest, &recv_len, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't get file ids -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } *file_ids_len = recv_len; @@ -1614,62 +1714,62 @@ static int handler_desfire_filesettings(uint8_t file_id, uint8_t *dest, uint32_t int res = send_desfire_cmd(&apdu, false, dest, destlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't get file settings -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; } -typedef struct { - uint8_t aid[3]; - uint8_t keysetting1; - uint8_t keysetting2; - uint8_t fid[2]; - uint8_t name[16]; -} aidhdr_t; - static int handler_desfire_createapp(aidhdr_t *aidhdr, bool usename, bool usefid) { if (aidhdr == NULL) return PM3_EINVARG; sAPDU apdu = {0x90, MFDES_CREATE_APPLICATION, 0x00, 0x00, sizeof(aidhdr_t), (uint8_t *)aidhdr}; // 0xCA - if (!usename) { - apdu.Lc = apdu.Lc - 16; + if (usename == false) { + apdu.Lc = apdu.Lc - sizeof(aidhdr->name); } - if (!usefid) { - apdu.Lc = apdu.Lc - 2; + if (usefid == false) { + apdu.Lc = apdu.Lc - sizeof(aidhdr->fid); } uint8_t *data = NULL; - if (!usefid && usename) { - data = (uint8_t *)malloc(apdu.Lc); + + // skip over FID if not used. + if (usefid == false && usename) { + data = calloc(apdu.Lc, sizeof(uint8_t)); apdu.data = data; - memcpy(data, aidhdr, apdu.Lc); - memcpy(&data[3 + 1 + 1], aidhdr->name, 16); + + memcpy(data, aidhdr->aid, sizeof(aidhdr->aid)); + data[3] = aidhdr->keysetting1; + data[4] = aidhdr->keysetting2; + memcpy(data + 5, aidhdr->name, sizeof(aidhdr->name)); + + PrintAndLogEx(INFO, "new data: %s", sprint_hex_inrow(data, apdu.Lc)); } uint16_t sw = 0; uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); - if (data != NULL) free(data); + if (data != NULL) { + free(data); + } if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create aid -> %s"), GetErrorString(res, &sw)); - DropField(); - return res; + DropFieldDesfire(); } - return res; } static int handler_desfire_deleteapp(const uint8_t *aid) { - if (aid == NULL) return PM3_EINVARG; + if (aid == NULL) { + return PM3_EINVARG; + } sAPDU apdu = {0x90, MFDES_DELETE_APPLICATION, 0x00, 0x00, 3, (uint8_t *)aid}; // 0xDA uint16_t sw = 0; uint32_t recvlen = 0; int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't delete aid -> %s"), GetErrorString(res, &sw)); - DropField(); - return res; + DropFieldDesfire(); } return res; } @@ -1687,7 +1787,7 @@ static int handler_desfire_credit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't credit value -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1706,7 +1806,7 @@ static int handler_desfire_limitedcredit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't credit limited value -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1725,7 +1825,7 @@ static int handler_desfire_debit(mfdes_value_t *value, uint8_t cs) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't debit value -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1747,7 +1847,7 @@ static int handler_desfire_readdata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, int res = send_desfire_cmd(&apdu, false, data->data, &resplen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } @@ -1777,7 +1877,7 @@ static int handler_desfire_getvalue(mfdes_value_t *value, uint32_t *resplen, uin int res = send_desfire_cmd(&apdu, false, value->value, resplen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't read data -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } size_t dlen = (size_t)resplen; @@ -1832,7 +1932,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't write data -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } offset += datasize; @@ -1842,7 +1942,7 @@ static int handler_desfire_writedata(mfdes_data_t *data, MFDES_FILE_TYPE_T type, if (type == MFDES_RECORD_FILE) { if (handler_desfire_commit_transaction() != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } } @@ -1857,7 +1957,7 @@ static int handler_desfire_deletefile(uint8_t fileno) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't delete file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1871,13 +1971,13 @@ static int handler_desfire_clearrecordfile(uint8_t fileno) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't clear record file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } else { res = handler_desfire_commit_transaction(); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't commit transaction -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } } @@ -1894,7 +1994,7 @@ static int handler_desfire_create_value_file(mfdes_value_file_t *value) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create value -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1909,7 +2009,7 @@ static int handler_desfire_create_std_file(mfdes_file_t *file) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1925,7 +2025,7 @@ static int handler_desfire_create_linearrecordfile(mfdes_linear_t *file) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create linear record file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1941,7 +2041,7 @@ static int handler_desfire_create_cyclicrecordfile(mfdes_linear_t *file) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create cyclic record file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1957,7 +2057,7 @@ static int handler_desfire_create_backup_file(mfdes_file_t *file) { int res = send_desfire_cmd(&apdu, false, NULL, &recvlen, &sw, 0, true); if (res != PM3_SUCCESS) { PrintAndLogEx(WARNING, _RED_(" Can't create backup file -> %s"), GetErrorString(res, &sw)); - DropField(); + DropFieldDesfire(); return res; } return res; @@ -1966,6 +2066,8 @@ static int handler_desfire_create_backup_file(mfdes_file_t *file) { static int getKeySettings(uint8_t *aid) { if (aid == NULL) return PM3_EINVARG; + uint8_t num_keys = 0; + uint8_t key_setting = 0; int res = 0; if (memcmp(aid, "\x00\x00\x00", 3) == 0) { @@ -1973,50 +2075,15 @@ static int getKeySettings(uint8_t *aid) { //PrintAndLogEx(INFO, "--- " _CYAN_("CMK - PICC, Card Master Key settings")); // KEY Settings - AMK - uint8_t num_keys = 0; - uint8_t key_setting = 0; mifare_des_authalgo_t algo = MFDES_ALGO_DES; res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys); if (res == PM3_SUCCESS) { - // number of Master keys (0x01) - PrintAndLogEx(SUCCESS, " Number of Masterkeys : " _YELLOW_("%u"), (num_keys & 0x3F)); - - PrintAndLogEx(SUCCESS, " [0x08] Configuration changeable : %s", (key_setting & (1 << 3)) ? _GREEN_("YES") : "NO"); - PrintAndLogEx(SUCCESS, " [0x04] CMK required for create/delete : %s", (key_setting & (1 << 2)) ? _GREEN_("YES") : "NO"); - PrintAndLogEx(SUCCESS, " [0x02] Directory list access with CMK : %s", (key_setting & (1 << 1)) ? _GREEN_("YES") : "NO"); - PrintAndLogEx(SUCCESS, " [0x01] CMK is changeable : %s", (key_setting & (1 << 0)) ? _GREEN_("YES") : "NO"); + desfire_print_piccmk_keysetting(key_setting, num_keys, algo); } else { - PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); + PrintAndLogEx(WARNING, _RED_(" Can't read PICC Master key settings")); } - const char *str = " Operation of PICC master key : " _YELLOW_("%s"); - - if (algo == MFDES_ALGO_DES) PrintAndLogEx(SUCCESS, str, "(3)DES"); - else if (algo == MFDES_ALGO_AES) PrintAndLogEx(SUCCESS, str, "AES"); - else if (algo == MFDES_ALGO_3K3DES) PrintAndLogEx(SUCCESS, str, "3K3DES"); - - uint8_t cmk_num_versions = 0; - if (handler_desfire_keyversion(0, &cmk_num_versions) == PM3_SUCCESS) { - PrintAndLogEx(SUCCESS, " PICC Master key Version : " _YELLOW_("%d (0x%02x)"), cmk_num_versions, cmk_num_versions); - PrintAndLogEx(INFO, " ----------------------------------------------------------"); - } - - // Authentication tests - res = test_desfire_authenticate(); - if (res == PM3_ETIMEOUT) return res; - PrintAndLogEx(SUCCESS, " [0x0A] Authenticate : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - res = test_desfire_authenticate_iso(); - if (res == PM3_ETIMEOUT) return res; - PrintAndLogEx(SUCCESS, " [0x1A] Authenticate ISO : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - res = test_desfire_authenticate_aes(); - if (res == PM3_ETIMEOUT) return res; - PrintAndLogEx(SUCCESS, " [0xAA] Authenticate AES : %s", (res == PM3_SUCCESS) ? _YELLOW_("YES") : "NO"); - - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - } else { // AID - APPLICATION MASTER KEYS @@ -2025,12 +2092,10 @@ static int getKeySettings(uint8_t *aid) { if (res != PM3_SUCCESS) return res; // KEY Settings - AMK - uint8_t num_keys = 0; - uint8_t key_setting = 0; mifare_des_authalgo_t algo = MFDES_ALGO_DES; res = key_setting_to_algo(aid, &key_setting, &algo, &num_keys); if (res == PM3_SUCCESS) { - desfire_print_keysetting(key_setting, num_keys, algo); + desfire_print_amk_keysetting(key_setting, num_keys, algo); } else { PrintAndLogEx(WARNING, _RED_(" Can't read Application Master key settings")); } @@ -2058,7 +2123,7 @@ static int getKeySettings(uint8_t *aid) { } } - DropField(); + DropFieldDesfire(); return PM3_SUCCESS; } @@ -2196,7 +2261,7 @@ static int CmdHF14ADesGetUID(const char *Cmd) { uint8_t uid[16] = {0}; int res = handler_desfire_getuid(uid); if (res != PM3_SUCCESS) { - DropField(); + DropFieldDesfire(); PrintAndLogEx(ERR, "Error on getting uid."); return res; } @@ -2231,11 +2296,11 @@ static int CmdHF14ADesSelectApp(const char *Cmd) { int res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { - DropField(); PrintAndLogEx(ERR, "Error on selecting aid."); - return res; + DropFieldDesfire(); + } else { + PrintAndLogEx(SUCCESS, "Successfully selected aid."); } - PrintAndLogEx(SUCCESS, "Successfully selected aid."); return res; } @@ -2243,7 +2308,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes createaid", "Create Application ID", - "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E -n Test" + "hf mfdes createaid -a 123456 -f 1111 -k 0E -l 2E --name Test" ); void *argtable[] = { @@ -2252,7 +2317,7 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { arg_strx0("f", "fid", "", "File ID to create (optional)"), arg_strx0("k", "ks1", "", "Key Setting 1 (Application Master Key Settings)"), arg_strx0("l", "ks2", "", "Key Setting 2"), - arg_str0("n", "name", "", "App ISO-4 Name (optional)"), + arg_str0(NULL, "name", "", "App ISO-4 Name (optional)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, false); @@ -2350,20 +2415,35 @@ static int CmdHF14ADesCreateApp(const char *Cmd) { aidhdr.keysetting1 = keysetting1[0]; aidhdr.keysetting2 = keysetting2[0]; - if (usefid) memcpy(aidhdr.fid, fid, sizeof(fid)); + if (usefid) + memcpy(aidhdr.fid, fid, sizeof(aidhdr.fid)); - if (usename) memcpy(aidhdr.name, name, sizeof(name)); + if (usename) + memcpy(aidhdr.name, name, sizeof(aidhdr.name)); - uint8_t rootaid[3] = {0x00, 0x00, 0x00}; - int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { - DropField(); - return res; + PrintAndLogEx(INFO, "Creating AID using:"); + PrintAndLogEx(INFO, "AID %s", sprint_hex_inrow(aidhdr.aid, sizeof(aidhdr.aid))); + PrintAndLogEx(INFO, "Key set1 0x%02X", aidhdr.keysetting1); + PrintAndLogEx(INFO, "Key Set2 0x%02X", aidhdr.keysetting2); + if (usefid) + PrintAndLogEx(INFO, "FID %s", sprint_hex_inrow(aidhdr.fid, sizeof(aidhdr.fid))); + if (usename) + PrintAndLogEx(INFO, "DF Name %s", aidhdr.name); + + /* + uint8_t rootaid[3] = {0x00, 0x00, 0x00}; + int res = handler_desfire_select_application(rootaid); + if (res != PM3_SUCCESS) { + DropFieldDesfire(); + return res; + } + */ + + int res = handler_desfire_createapp(&aidhdr, usename, usefid); + DropFieldDesfire(); + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Successfully created aid."); } - - res = handler_desfire_createapp(&aidhdr, usename, usefid); - DropField(); - PrintAndLogEx(SUCCESS, "Successfully created aid."); return res; } @@ -2371,7 +2451,6 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes deleteaid", "Delete Application ID", -// "Usage:\n\t-a aid (3 hex bytes, big endian)\n\n" "hf mfdes deleteaid -a 123456" ); @@ -2396,12 +2475,12 @@ static int CmdHF14ADesDeleteApp(const char *Cmd) { return PM3_ESOFT; } - uint8_t rootaid[3] = {0x00, 0x00, 0x00}; - int res = handler_desfire_select_application(rootaid); - if (res != PM3_SUCCESS) { DropField(); return res;} - res = handler_desfire_deleteapp(aid); - DropField(); - PrintAndLogEx(SUCCESS, "Successfully deleted aid."); + int res = handler_desfire_deleteapp(aid); + DropFieldDesfire(); + + if (res == PM3_SUCCESS) { + PrintAndLogEx(SUCCESS, "Successfully deleted aid."); + } return res; } @@ -2488,7 +2567,7 @@ static int CmdHF14ADesClearRecordFile(const char *Cmd) { } else { PrintAndLogEx(ERR, "Error on deleting file : %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -2548,7 +2627,7 @@ static int CmdHF14ADesDeleteFile(const char *Cmd) { } else { PrintAndLogEx(ERR, "Error on deleting file : %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -2638,12 +2717,12 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { if (aidlength != 3 && aidlength != 0) { PrintAndLogEx(ERR, _RED_(" The given aid must have 3 bytes (big endian).")); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } else if (aidlength == 0) { if (memcmp(&tag->selected_application, aid, 3) == 0) { PrintAndLogEx(ERR, _RED_(" You need to select an aid first.")); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } memcpy(aid, (uint8_t *)&tag->selected_application, 3); @@ -2652,7 +2731,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { int res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { PrintAndLogEx(ERR, "Couldn't select aid. Error %d", res); - DropField(); + DropFieldDesfire(); return res; } @@ -2666,7 +2745,7 @@ static int CmdHF14ADesCreateFile(const char *Cmd) { else PrintAndLogEx(ERR, "Couldn't create standard/backup file. Error %d", res); - DropField(); + DropFieldDesfire(); return res; } @@ -2737,7 +2816,7 @@ static int CmdHF14ADesGetValueData(const char *Cmd) { } else { PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -2853,12 +2932,12 @@ static int CmdHF14ADesReadData(const char *Cmd) { } } else { PrintAndLogEx(ERR, "Couldn't read data. Error %d", res); - DropField(); + DropFieldDesfire(); return res; } free(data); } - DropField(); + DropFieldDesfire(); return res; } @@ -2954,7 +3033,7 @@ static int CmdHF14ADesChangeValue(const char *Cmd) { } else { PrintAndLogEx(ERR, "Couldn't change value in value file. Error %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -3048,7 +3127,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { uint8_t cs = 0; if (selectfile(aid, _fileno[0], &cs) != PM3_SUCCESS) { PrintAndLogEx(ERR, _RED_(" Error on selecting file.")); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } @@ -3060,7 +3139,7 @@ static int CmdHF14ADesWriteData(const char *Cmd) { } else { PrintAndLogEx(ERR, "Couldn't read data. Error %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -3196,7 +3275,7 @@ static int CmdHF14ADesCreateRecordFile(const char *Cmd) { } else { PrintAndLogEx(ERR, "Couldn't create linear/cyclic record file. Error %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -3328,7 +3407,7 @@ static int CmdHF14ADesCreateValueFile(const char *Cmd) { } else { PrintAndLogEx(ERR, "Couldn't create value file. Error %d", res); } - DropField(); + DropFieldDesfire(); return res; } @@ -3354,13 +3433,13 @@ static int CmdHF14ADesFormatPICC(const char *Cmd) { } else { PrintAndLogEx(INFO, "Card successfully reset"); } - DropField(); + DropFieldDesfire(); return res; } static int CmdHF14ADesInfo(const char *Cmd) { (void)Cmd; // Cmd is not used so far - DropField(); + DropFieldDesfire(); mfdes_info_res_t info; int res = mfdes_get_info(&info); @@ -3382,6 +3461,8 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, " Production date: week " _GREEN_("%02x") " / " _GREEN_("20%02x"), info.details[12], info.details[13]); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Hardware Information")); + PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionHW, sizeof(info.versionHW))); + PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionHW[0])); PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionHW[1]); PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionHW[2]); @@ -3390,6 +3471,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { PrintAndLogEx(INFO, " Protocol: %s", getProtocolStr(info.versionHW[6], true)); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("Software Information")); + PrintAndLogEx(INFO, " raw: %s", sprint_hex_inrow(info.versionSW, sizeof(info.versionSW))); PrintAndLogEx(INFO, " Vendor Id: " _YELLOW_("%s"), getTagInfo(info.versionSW[0])); PrintAndLogEx(INFO, " Type: " _YELLOW_("0x%02X"), info.versionSW[1]); PrintAndLogEx(INFO, " Subtype: " _YELLOW_("0x%02X"), info.versionSW[2]); @@ -3467,7 +3549,7 @@ static int CmdHF14ADesInfo(const char *Cmd) { */ - DropField(); + DropFieldDesfire(); return PM3_SUCCESS; } @@ -3603,8 +3685,22 @@ static int DecodeFileSettings(uint8_t *src, int src_len, int maclen) { } static int CmdHF14ADesDump(const char *Cmd) { + + CLIParserContext *ctx; + CLIParserInit(&ctx, "hf mfdes dump", + "Tries to dump all files on a DESFire tag", + "hf mfdes dump"); + + void *argtable[] = { + arg_param_begin, +// arg_strx0("a", "aid", "", "Use specific AID (3 hex bytes, big endian)"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + (void)Cmd; // Cmd is not used so far - DropField(); + DropFieldDesfire(); uint8_t aid[3] = {0}; uint8_t app_ids[78] = {0}; @@ -3620,7 +3716,7 @@ static int CmdHF14ADesDump(const char *Cmd) { if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Can't get list of applications on tag"); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } @@ -3629,7 +3725,7 @@ static int CmdHF14ADesDump(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-- Mifare DESFire Dump ----------------------"); + PrintAndLogEx(INFO, "-- " _CYAN_("MIFARE DESFire Dump") " ----------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); for (uint32_t i = 0; i < app_ids_len; i += 3) { @@ -3684,7 +3780,7 @@ static int CmdHF14ADesDump(const char *Cmd) { uint8_t *data = (uint8_t *)calloc(filesize, sizeof(uint8_t)); if (data == NULL) { - DropField(); + DropFieldDesfire(); return PM3_EMALLOC; } @@ -3731,7 +3827,7 @@ static int CmdHF14ADesDump(const char *Cmd) { memset(fdata.length, 0, 3); uint8_t *data = (uint8_t *)calloc(filesize, sizeof(uint8_t)); if (data == NULL) { - DropField(); + DropFieldDesfire(); return PM3_EMALLOC; } @@ -3761,14 +3857,14 @@ static int CmdHF14ADesDump(const char *Cmd) { } PrintAndLogEx(INFO, "-------------------------------------------------------------"); - DropField(); + DropFieldDesfire(); return PM3_SUCCESS; } static int CmdHF14ADesEnumApplications(const char *Cmd) { (void)Cmd; // Cmd is not used so far - DropField(); + DropFieldDesfire(); uint8_t aid[3] = {0}; uint8_t app_ids[78] = {0}; @@ -3782,7 +3878,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Can't get list of applications on tag"); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } @@ -3791,7 +3887,7 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "-- Mifare DESFire Enumerate applications --------------------"); + PrintAndLogEx(INFO, "-- MIFARE DESFire Enumerate applications --------------------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(SUCCESS, " Tag report " _GREEN_("%d") " application%c", app_ids_len / 3, (app_ids_len == 3) ? ' ' : 's'); @@ -3852,12 +3948,12 @@ static int CmdHF14ADesEnumApplications(const char *Cmd) { } PrintAndLogEx(INFO, "-------------------------------------------------------------"); - DropField(); + DropFieldDesfire(); return PM3_SUCCESS; } static int CmdHF14ADesChangeKey(const char *Cmd) { - //DropField(); + //DropFieldDesfire(); // NR DESC KEYLENGHT // ------------------------ // 1 = DES 8 @@ -3868,7 +3964,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { uint8_t newkeylength = 8; CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes changekey", - "Changes Mifare DESFire Key\n" + "Changes MIFARE DESFire Key\n" "Make sure to select aid or authenticate aid before running this command.", "hf mfdes changekey -n 0 -t 1 -k 0000000000000000 -u 1 -j 0102030405060708 -> DES,keynumber 0" ); @@ -3958,7 +4054,7 @@ static int CmdHF14ADesChangeKey(const char *Cmd) { // #define BUFSIZE 256 static int CmdHF14ADesAuth(const char *Cmd) { - //DropField(); + //DropFieldDesfire(); // NR DESC KEYLENGHT // ------------------------ // 1 = DES 8 @@ -3969,7 +4065,7 @@ static int CmdHF14ADesAuth(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes auth", - "Authenticates Mifare DESFire using Key", + "Authenticates MIFARE DESFire using Key", "hf mfdes auth -m 3 -t 4 -a 808301 -n 0 -k 00000000000000000000000000000000 -> AES,keynumber 0, aid 0x803201\n" "hf mfdes auth -m 2 -t 2 -a 000000 -n 1 -k 00000000000000000000000000000000 -> 3DES,keynumber 1, aid 0x000000\n" "hf mfdes auth -m 1 -t 1 -a 000000 -n 2 -k 0000000000000000 -> DES,keynumber 2, aid 0x000000\n" @@ -4221,7 +4317,7 @@ static int AuthCheckDesfire(uint8_t *aid, break; } else if (error < 7) { badlen = true; - DropField(); + DropFieldDesfire(); res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { return res; @@ -4253,7 +4349,7 @@ static int AuthCheckDesfire(uint8_t *aid, break; } else if (error < 7) { badlen = true; - DropField(); + DropFieldDesfire(); res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { return res; @@ -4285,7 +4381,7 @@ static int AuthCheckDesfire(uint8_t *aid, break; } else if (error < 7) { badlen = true; - DropField(); + DropFieldDesfire(); res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { return res; @@ -4317,7 +4413,7 @@ static int AuthCheckDesfire(uint8_t *aid, break; } else if (error < 7) { badlen = true; - DropField(); + DropFieldDesfire(); res = handler_desfire_select_application(aid); if (res != PM3_SUCCESS) { return res; @@ -4332,7 +4428,7 @@ static int AuthCheckDesfire(uint8_t *aid, } } } - DropField(); + DropFieldDesfire(); return PM3_SUCCESS; } @@ -4348,7 +4444,7 @@ static int CmdHF14aDesChk(const char *Cmd) { CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes chk", - "Checks keys with Mifare Desfire card.", + "Checks keys with MIFARE DESFire card.", "hf mfdes chk -a 123456 -k 000102030405060708090a0b0c0d0e0f -> check key on aid 0x123456\n" "hf mfdes chk -d mfdes_default_keys -> check keys from dictionary against all existing aid on card\n" "hf mfdes chk -d mfdes_default_keys -a 123456 -> check keys from dictionary against aid 0x123456\n" @@ -4530,7 +4626,7 @@ static int CmdHF14aDesChk(const char *Cmd) { if (handler_desfire_appids(app_ids, &app_ids_len) != PM3_SUCCESS) { PrintAndLogEx(ERR, "Can't get list of applications on tag"); - DropField(); + DropFieldDesfire(); return PM3_ESOFT; } @@ -4587,7 +4683,7 @@ static int CmdHF14aDesChk(const char *Cmd) { // save keys to json if ((jsonnamelen > 0) && result) { - // Mifare Desfire info + // MIFARE DESFire info SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_CONNECT, 0, 0, NULL, 0); PacketResponseNG resp; @@ -4630,7 +4726,7 @@ static int CmdHF14ADesList(const char *Cmd) { /* static int CmdHF14aDesNDEF(const char *Cmd) { - DropField(); + DropFieldDesfire(); CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes ndef", @@ -4644,7 +4740,6 @@ static int CmdHF14aDesNDEF(const char *Cmd) { arg_litn("v", "verbose", 0, 2, "show technical data"), arg_str0("", "aid", "", "replace default aid for NDEF"), arg_str0("k", "key", "", "replace default key for NDEF"), - arg_lit0("b", "keyb", "use key B for access sectors (by default: key A)"), arg_param_end }; CLIExecWithReturn(ctx, Cmd, argtable, true); @@ -4657,22 +4752,24 @@ static int CmdHF14aDesNDEF(const char *Cmd) { uint8_t key[16] = {0}; int keylen; CLIGetHexWithReturn(ctx, 3, key, &keylen); - bool keyB = arg_get_lit(ctx, 4); CLIParserFree(ctx); - uint16_t ndefAID = 0xe103; - if (aidlen == 2) - ndefAID = (aid[0] << 8) + aid[1]; + uint32_t ndefAID = 0xEEEE10; + if (aidlen == 2) { + ndefAID = (aid[0] << 16) | (aid[1] << 8) | aid[2]; + } + // set default NDEF key uint8_t ndefkey[16] = {0}; memcpy(ndefkey, g_mifarep_ndef_key, 16); + + // user supplied key if (keylen == 16) { memcpy(ndefkey, key, 16); } - uint8_t data[4096] = {0}; - int datalen = 0; + int file_ids_len = 0; for (int j = (int)file_ids_len - 1; j >= 0; j--) { PrintAndLogEx(SUCCESS, "\n\n Fileid %d (0x%02x)", file_ids[j], file_ids[j]); @@ -4680,7 +4777,7 @@ static int CmdHF14aDesNDEF(const char *Cmd) { uint8_t filesettings[20] = {0}; uint32_t fileset_len = 0; - res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len); + int res = handler_desfire_filesettings(file_ids[j], filesettings, &fileset_len); if (res != PM3_SUCCESS) continue; int maclen = 0; // To be implemented @@ -4694,23 +4791,24 @@ static int CmdHF14aDesNDEF(const char *Cmd) { uint8_t *data = (uint8_t *)calloc(filesize, sizeof(uint8_t)); if (data == NULL) { - DropField(); + DropFieldDesfire(); return PM3_EMALLOC; } - fdata.data = data; - int res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE, filesettings[1]); - if (res == PM3_SUCCESS) { - uint32_t len = le24toh(fdata.length); - NDEFDecodeAndPrint(data, datalen, verbose); + fdata.data = data; + res = handler_desfire_readdata(&fdata, MFDES_DATA_FILE, filesettings[1]); + if (res == PM3_SUCCESS) { + uint32_t len = le24toh(fdata.length); + NDEFDecodeAndPrint(data, datalen, verbose); - } else { - PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); - res = handler_desfire_select_application(aid); - if (res != PM3_SUCCESS) continue; + } else { + PrintAndLogEx(ERR, "Couldn't read value. Error %d", res); + res = handler_desfire_select_application(aid); + if (res != PM3_SUCCESS) continue; + } + + free(data); } - - free(data); } // PrintAndLogEx(INFO, "reading data from tag"); @@ -4722,17 +4820,17 @@ static int CmdHF14aDesNDEF(const char *Cmd) { if (verbose2) { PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(INFO, "--- " _CYAN_("DESfire NDEF raw") " ----------------"); - dump_buffer(data, datalen, stdout, 1); + PrintAndLogEx(INFO, "--- " _CYAN_("DESFire NDEF raw") " ----------------"); + print_buffer(data, datalen, 1); } + PrintAndLogEx(HINT, "Try " _YELLOW_("`hf mfdes ndef -vv`") " for more details"); return PM3_SUCCESS; } */ - /* static int CmdHF14aDesMAD(const char *Cmd) { - DropField(); + DropFieldDesfire(); CLIParserContext *ctx; CLIParserInit(&ctx, "hf mfdes mad", diff --git a/client/src/cmdhfmfp.c b/client/src/cmdhfmfp.c index 5ef2ac826..1f0d47ae5 100644 --- a/client/src/cmdhfmfp.c +++ b/client/src/cmdhfmfp.c @@ -15,12 +15,12 @@ #include "commonutil.h" // ARRAYLEN #include "comms.h" #include "ui.h" +#include "util.h" #include "cmdhf14a.h" #include "mifare/mifare4.h" #include "mifare/mad.h" #include "mifare/ndef.h" #include "cliparser.h" -#include "emv/dump.h" #include "mifare/mifaredefault.h" #include "util_posix.h" #include "fileutils.h" @@ -1551,7 +1551,7 @@ static int CmdHFMFPNDEF(const char *Cmd) { if (verbose2) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "--- " _CYAN_("MF Plus NDEF raw") " ----------------"); - dump_buffer(data, datalen, stdout, 1); + print_buffer(data, datalen, 1); } NDEFDecodeAndPrint(data, datalen, verbose); diff --git a/client/src/cmdhfwaveshare.c b/client/src/cmdhfwaveshare.c index 96547668f..932012f98 100644 --- a/client/src/cmdhfwaveshare.c +++ b/client/src/cmdhfwaveshare.c @@ -83,9 +83,9 @@ static model_t models[] = { {"2.9 inch e-paper", 16, 296, 128}, {"4.2 inch e-paper", 100, 400, 300}, // tested {"7.5 inch e-paper", 120, 800, 480}, - {"2.7 inch e-paper", 121, 276, 176}, - {"2.13 inch e-paper B (with red)", 106, 212, 104}, - {"1.54 inch e-paper B (with red)", 100, 200, 200}, + {"2.7 inch e-paper", 121, 176, 276}, // tested + {"2.13 inch e-paper B (with red)", 106, 104, 212}, // tested + {"1.54 inch e-paper B (with red)", 100, 200, 200}, // tested {"7.5 inch e-paper HD", 120, 880, 528}, }; @@ -563,7 +563,6 @@ static int transceive_blocking(uint8_t *txBuf, uint16_t txBufLen, uint8_t *rxBuf PacketResponseNG resp; SendCommandMIX(CMD_HF_ISO14443A_READER, ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, txBufLen, 0, txBuf, txBufLen); rxBuf[0] = 1; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { if (resp.oldarg[0] > rxBufLen) { PrintAndLogEx(WARNING, "Received %"PRIu64 " bytes, rxBuf too small (%u)", resp.oldarg[0], rxBufLen); @@ -856,7 +855,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { } else if (model_nr == M2in13B) { //2.13inch B for (i = 0; i < 26; i++) { read_black(i, step8, model_nr, black); - ret = transceive_blocking(step8, 109, rx, 20, actrxlen, true); // cd 08 + ret = transceive_blocking(step8, 109, rx, 20, actrxlen, false); // cd 08 if (ret != PM3_SUCCESS) { return ret; } @@ -920,7 +919,7 @@ static int start_drawing(uint8_t model_nr, uint8_t *black, uint8_t *red) { for (i = 0; i < 26; i++) { read_red(i, step13, model_nr, red); //memset(&step13[3], 0xfE, 106); - ret = transceive_blocking(step13, 109, rx, 20, actrxlen, true); + ret = transceive_blocking(step13, 109, rx, 20, actrxlen, false); if (ret != PM3_SUCCESS) { return ret; } diff --git a/client/src/cmdhw.c b/client/src/cmdhw.c index 2743df820..3f2b3407a 100644 --- a/client/src/cmdhw.c +++ b/client/src/cmdhw.c @@ -666,15 +666,15 @@ static int CmdConnect(const char *Cmd) { } if (session.pm3_present) { - CloseProxmark(); + CloseProxmark(session.current_device); } // 10 second timeout - OpenProxmark(port, false, 10, false, baudrate); + OpenProxmark(&session.current_device, port, false, 10, false, baudrate); - if (session.pm3_present && (TestProxmark() != PM3_SUCCESS)) { + if (session.pm3_present && (TestProxmark(session.current_device) != PM3_SUCCESS)) { PrintAndLogEx(ERR, _RED_("ERROR:") " cannot communicate with the Proxmark3\n"); - CloseProxmark(); + CloseProxmark(session.current_device); return PM3_ENOTTY; } return PM3_SUCCESS; diff --git a/client/src/cmdlfem4x05.c b/client/src/cmdlfem4x05.c index e1f8e10ad..3b260ed2e 100644 --- a/client/src/cmdlfem4x05.c +++ b/client/src/cmdlfem4x05.c @@ -429,7 +429,7 @@ int em4x05_clone_tag(uint32_t *blockdata, uint8_t numblocks, uint32_t pwd, bool } if (res == 0) - PrintAndLogEx(SUCCESS, "Success writing to tag"); + PrintAndLogEx(SUCCESS, "Data written and verified"); return PM3_SUCCESS; } @@ -824,7 +824,7 @@ int CmdEM4x05Write(const char *Cmd) { uint32_t dummy = 0; int status = em4x05_demod_resp(&dummy, true); if (status == PM3_SUCCESS) - PrintAndLogEx(SUCCESS, "Success writing to tag"); + PrintAndLogEx(SUCCESS, "Data written and verified"); else if (status == PM3_EFAILED) PrintAndLogEx(ERR, "Tag denied %s operation", protectOperation ? "Protect" : "Write"); else @@ -1431,7 +1431,7 @@ static int unlock_write_protect(bool use_pwd, uint32_t pwd, uint32_t data, bool uint32_t dummy = 0; int status = em4x05_demod_resp(&dummy, true); if (status == PM3_SUCCESS && verbose) - PrintAndLogEx(SUCCESS, "Success writing to tag"); + PrintAndLogEx(SUCCESS, "Data written and verified"); else if (status == PM3_EFAILED) PrintAndLogEx(ERR, "Tag denied PROTECT operation"); else @@ -1882,7 +1882,8 @@ uint32_t static em4x05_Sniff_GetBlock(char *bits, bool fwd) { if (parity != (bits[35] - '0')) parityerror = true; - if (parityerror) printf("parity error : "); + if (parityerror) + PrintAndLogEx(ERR, "parity error : "); if (!fwd) { uint32_t t1 = value; @@ -1997,10 +1998,10 @@ int CmdEM4x05Sniff(const char *Cmd) { ((strncmp(bits, "01010", 5) == 0) && (bitidx == 50))) { memmove(bits, &bits[1], bitidx - 1); bitidx--; - printf("Trim leading 0\n"); + PrintAndLogEx(INFO, "Trim leading 0"); } bits[bitidx] = 0; - // printf ("==> %s\n",bits); + // logon if ((strncmp(bits, "0011", 4) == 0) && (bitidx == 49)) { haveData = true; @@ -2017,8 +2018,9 @@ int CmdEM4x05Sniff(const char *Cmd) { sprintf(cmdText, "Write"); tmpValue = (bits[4] - '0') + ((bits[5] - '0') << 1) + ((bits[6] - '0') << 2) + ((bits[7] - '0') << 3); sprintf(blkAddr, "%d", tmpValue); - if (tmpValue == 2) + if (tmpValue == 2) { pwd = true; + } tmpValue = em4x05_Sniff_GetBlock(&bits[11], fwd); sprintf(dataText, "%08X", tmpValue); } @@ -2057,8 +2059,9 @@ int CmdEM4x05Sniff(const char *Cmd) { } else { i = (CycleWidth - ZeroWidth) / 28; bits[bitidx++] = '0'; - for (int ii = 0; ii < i; ii++) + for (int ii = 0; ii < i; ii++) { bits[bitidx++] = '1'; + } } } } @@ -2068,15 +2071,14 @@ int CmdEM4x05Sniff(const char *Cmd) { // Print results if (haveData) { //&& (minWidth > 1) && (maxWidth > minWidth)){ if (pwd) - PrintAndLogEx(SUCCESS, "%6zu | %-10s | "_YELLOW_("%8s")" | "_YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits); + PrintAndLogEx(SUCCESS, "%6zu | %-10s | " _YELLOW_("%8s")" | " _YELLOW_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits); else - PrintAndLogEx(SUCCESS, "%6zu | %-10s | "_GREEN_("%8s")" | "_GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits); + PrintAndLogEx(SUCCESS, "%6zu | %-10s | " _GREEN_("%8s")" | " _GREEN_("%3s")" | %s", pktOffset, cmdText, dataText, blkAddr, bits); } } // footer PrintAndLogEx(SUCCESS, "---------------------------------------------------------------------------------------------------"); PrintAndLogEx(NORMAL, ""); - return PM3_SUCCESS; } diff --git a/client/src/cmdlffdxb.c b/client/src/cmdlffdxb.c index efd567128..92e466358 100644 --- a/client/src/cmdlffdxb.c +++ b/client/src/cmdlffdxb.c @@ -50,7 +50,7 @@ static int CmdHelp(const char *Cmd); static int usage_lf_fdxb_clone(void) { PrintAndLogEx(NORMAL, "Clone a FDX-B animal tag to a T55x7 or Q5/T5555 tag."); - PrintAndLogEx(NORMAL, "Usage: lf fdxb clone [h] [c ] [a ] [e ] "); + PrintAndLogEx(NORMAL, "Usage: lf fdxb clone [h] [c ] [n ] [e ] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " c : (dec) Country code"); diff --git a/client/src/cmdlfhid.c b/client/src/cmdlfhid.c index 9bfbbaf3f..178a75449 100644 --- a/client/src/cmdlfhid.c +++ b/client/src/cmdlfhid.c @@ -138,9 +138,9 @@ int demodHID(bool verbose) { wiegand_message_t packed = initialize_message_object(hi2, hi, lo); if (HIDTryUnpack(&packed, false) == false) { - PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo); printDemodBuff(0, false, false, true); } + PrintAndLogEx(INFO, "raw: " _GREEN_("%08x%08x%08x"), hi2, hi, lo); PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %zu, Printing Demod Buffer: ", idx, size); if (g_debugMode) { diff --git a/client/src/cmdlft55xx.c b/client/src/cmdlft55xx.c index ab1a86fbd..80c8eda4f 100644 --- a/client/src/cmdlft55xx.c +++ b/client/src/cmdlft55xx.c @@ -315,11 +315,13 @@ static int usage_t55xx_wipe(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " c - set configuration from a block0"); + PrintAndLogEx(NORMAL, " p "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " <0|1> off or on"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" hints 1")); - return PM3_SUCCESS; -} - -static int usage_msleep(void) { - PrintAndLogEx(NORMAL, "Sleep for given amount of milliseconds"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: msleep "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " time in milliseconds"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" msleep 100")); - return PM3_SUCCESS; -} - -static int usage_auto(void) { - PrintAndLogEx(NORMAL, "Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE "); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: auto "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, _YELLOW_(" auto")); - return PM3_SUCCESS; -} - static void AppendDate(char *s, size_t slen, const char *fmt) { struct tm *ct, tm_buf; time_t now = time(NULL); @@ -158,17 +121,30 @@ static int lf_search_plus(const char *Cmd) { } static int CmdAuto(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_auto(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "auto", + "Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE", + "auto" + ); + void *argtable[] = { + arg_param_begin, + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + CLIParserFree(ctx); + + PrintAndLogEx(INFO, "lf search"); int ret = CmdLFfind(""); if (ret == PM3_SUCCESS) return ret; + PrintAndLogEx(INFO, "hf search"); ret = CmdHFSearch(""); if (ret == PM3_SUCCESS) return ret; + PrintAndLogEx(INFO, "lf search - unknown"); ret = lf_search_plus(""); if (ret == PM3_SUCCESS) return ret; @@ -193,26 +169,35 @@ int CmdRem(const char *Cmd) { } static int CmdHints(const char *Cmd) { - uint32_t ms = 0; - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_hints(); - if (strlen(Cmd) > 1) { - str_lower((char *)Cmd); - if (str_startswith(Cmd, "of")) { - session.show_hints = false; - } else { - session.show_hints = true; - } - } else if (strlen(Cmd) == 1) { - if (param_getchar(Cmd, 0) != 0x00) { - ms = param_get32ex(Cmd, 0, 0, 10); - if (ms == 0) { - session.show_hints = false; - } else { - session.show_hints = true; - } - } + CLIParserContext *ctx; + CLIParserInit(&ctx, "hints", + "Turn on/off hints", + "hints --on\n" + "hints -1\n" + ); + + void *argtable[] = { + arg_param_begin, + arg_lit0("1", "on", "turn on hints"), + arg_lit0("0", "off", "turn off hints"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, true); + + bool turn_on = arg_get_lit(ctx, 1); + bool turn_off = arg_get_lit(ctx, 2); + CLIParserFree(ctx); + + if (turn_on && turn_off) { + PrintAndLogEx(ERR, "you can't turn off and on at the same time"); + return PM3_EINVARG; + } + + if (turn_off) { + session.show_hints = false; + } else if (turn_on) { + session.show_hints = true; } PrintAndLogEx(INFO, "Hints are %s", (session.show_hints) ? "ON" : "OFF"); @@ -220,14 +205,26 @@ static int CmdHints(const char *Cmd) { } static int CmdMsleep(const char *Cmd) { - uint32_t ms = 0; - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_msleep(); - if (param_getchar(Cmd, 0) != 0x00) { - ms = param_get32ex(Cmd, 0, 0, 10); - if (ms == 0) - return usage_msleep(); + CLIParserContext *ctx; + CLIParserInit(&ctx, "msleep", + "Sleep for given amount of milliseconds", + "msleep 100" + ); + + void *argtable[] = { + arg_param_begin, + arg_int0("t", "ms", "", "time in milliseconds"), + arg_param_end + }; + CLIExecWithReturn(ctx, Cmd, argtable, false); + uint32_t ms = arg_get_u32_def(ctx, 1, 0); + CLIParserFree(ctx); + + if (ms == 0) { + PrintAndLogEx(ERR, "Specified invalid input. Can't be zero"); + return PM3_EINVARG; } + msleep(ms); return PM3_SUCCESS; } diff --git a/client/src/cmdscript.c b/client/src/cmdscript.c index 40c4f3aa6..b66516296 100644 --- a/client/src/cmdscript.c +++ b/client/src/cmdscript.c @@ -9,7 +9,6 @@ //----------------------------------------------------------------------------- // 2020, added Python support (@iceman1001) - #include #include @@ -32,7 +31,15 @@ #include "ui.h" #include "fileutils.h" +#ifdef HAVE_LUA_SWIG +extern int luaopen_pm3(lua_State* L); +#endif + #ifdef HAVE_PYTHON +#ifdef HAVE_PYTHON_SWIG +extern PyObject* PyInit__pm3(void); +#endif // HAVE_PYTHON_SWIG + // Partly ripped from PyRun_SimpleFileExFlags // but does not terminate client on sys.exit // and print exit code only if != 0 @@ -274,7 +281,9 @@ static int CmdScriptRun(const char *Cmd) { //Add the 'bit' library set_bit_library(lua_state); - +#ifdef HAVE_LUA_SWIG + luaL_requiref(lua_state, "pm3", luaopen_pm3, 1); +#endif error = luaL_loadfile(lua_state, script_path); free(script_path); if (!error) { @@ -355,6 +364,10 @@ static int CmdScriptRun(const char *Cmd) { // optional but recommended Py_SetProgramName(program); +#ifdef HAVE_PYTHON_SWIG + // hook Proxmark3 API + PyImport_AppendInittab("_pm3", PyInit__pm3); +#endif Py_Initialize(); //int argc, char ** argv diff --git a/client/src/cmdsmartcard.c b/client/src/cmdsmartcard.c index ae9d018d4..ddeece950 100644 --- a/client/src/cmdsmartcard.c +++ b/client/src/cmdsmartcard.c @@ -18,8 +18,8 @@ #include "comms.h" // getfromdevice #include "emv/emvcore.h" // decodeTVL #include "crypto/libpcrypto.h" // sha512hash -#include "emv/dump.h" #include "ui.h" +#include "util.h" #include "fileutils.h" #include "crc16.h" // crc @@ -316,7 +316,7 @@ static void PrintATR(uint8_t *atr, size_t atrlen) { if (K > 1) { PrintAndLogEx(INFO, "\tHistorical bytes"); - dump_buffer(&atr[2 + T1len + TD1len + TDilen], K, NULL, 1); + print_buffer(&atr[2 + T1len + TD1len + TDilen], K, 1); } } diff --git a/client/src/comms.c b/client/src/comms.c index 416225c0f..57a03afe7 100644 --- a/client/src/comms.c +++ b/client/src/comms.c @@ -14,6 +14,7 @@ #include #include #include +#include #include "uart/uart.h" #include "ui.h" @@ -541,7 +542,7 @@ bool IsCommunicationThreadDead(void) { return ret; } -bool OpenProxmark(char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) { +bool OpenProxmark(pm3_device **dev, char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed) { if (!wait_for_port) { PrintAndLogEx(INFO, "Using UART port " _YELLOW_("%s"), port); @@ -588,15 +589,17 @@ bool OpenProxmark(char *port, bool wait_for_port, int timeout, bool flash_mode, pthread_create(&communication_thread, NULL, &uart_communication, &conn); __atomic_clear(&comm_thread_dead, __ATOMIC_SEQ_CST); - session.pm3_present = true; + session.pm3_present = true; // TODO support for multiple devices fflush(stdout); + *dev = malloc(sizeof(pm3_device)); + (*dev)->conn = &conn; // TODO conn shouldn't be global return true; } } // check if we can communicate with Pm3 -int TestProxmark(void) { +int TestProxmark(pm3_device *dev) { PacketResponseNG resp; uint16_t len = 32; @@ -659,8 +662,8 @@ int TestProxmark(void) { return PM3_SUCCESS; } -void CloseProxmark(void) { - conn.run = false; +void CloseProxmark(pm3_device *dev) { + dev->conn->run = false; #ifdef __BIONIC__ if (communication_thread != 0) { diff --git a/client/src/comms.h b/client/src/comms.h index 9fcf1b7a6..3ee691a30 100644 --- a/client/src/comms.h +++ b/client/src/comms.h @@ -65,6 +65,12 @@ typedef struct { extern communication_arg_t conn; +typedef struct pm3_device pm3_device; +struct pm3_device { + communication_arg_t *conn; + int script_embedded; +}; + void *uart_receiver(void *targ); void SendCommandBL(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); void SendCommandOLD(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void *data, size_t len); @@ -74,9 +80,10 @@ void clearCommandBuffer(void); #define FLASHMODE_SPEED 460800 bool IsCommunicationThreadDead(void); -bool OpenProxmark(char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed); -int TestProxmark(void); -void CloseProxmark(void); +typedef struct pm3_device pm3_device; +bool OpenProxmark(pm3_device **dev, char *port, bool wait_for_port, int timeout, bool flash_mode, uint32_t speed); +int TestProxmark(pm3_device *dev); +void CloseProxmark(pm3_device *dev); bool WaitForResponseTimeoutW(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, PacketResponseNG *response, size_t ms_timeout); diff --git a/client/src/crypto/asn1dump.c b/client/src/crypto/asn1dump.c index 91b04216a..cae25c1b6 100644 --- a/client/src/crypto/asn1dump.c +++ b/client/src/crypto/asn1dump.c @@ -15,23 +15,17 @@ #include #include #include -#include #include #include #include #include #include "emv/emv_tags.h" -#include "emv/dump.h" #include "emv/emvjson.h" #include "util.h" #include "proxmark3.h" #include "fileutils.h" #include "pm3_cmd.h" -#ifndef PRINT_INDENT -# define PRINT_INDENT(level) {for (int myi = 0; myi < (level); myi++) fprintf(f, " ");} -#endif - enum asn1_tag_t { ASN1_TAG_GENERIC, ASN1_TAG_BOOLEAN, @@ -109,65 +103,62 @@ static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { return tag ? tag : &asn1_tags[0]; } -static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool longyear, bool *needdump) { +static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, int level, bool longyear, bool *needdump) { int len = tlv->len; *needdump = false; int startindx = longyear ? 4 : 2; if (len > 4) { - fprintf(f, "\tvalue: '"); + PrintAndLogEx(NORMAL, " value: '" NOLF); while (true) { // year - if (!longyear) - fprintf(f, "20"); - fwrite(tlv->value, 1, longyear ? 4 : 2, f); - fprintf(f, "-"); + if (longyear == false) + PrintAndLogEx(NORMAL, "20" NOLF); + + PrintAndLogEx(NORMAL, "%s-" NOLF, sprint_hex(tlv->value, startindx)); + if (len < startindx + 2) break; + // month - fwrite(&tlv->value[startindx], 1, 2, f); - fprintf(f, "-"); + PrintAndLogEx(NORMAL, "%02x%02x-" NOLF, tlv->value[startindx], tlv->value[startindx + 1]); if (len < startindx + 4) break; + // day - fwrite(&tlv->value[startindx + 2], 1, 2, f); - fprintf(f, " "); + PrintAndLogEx(NORMAL, "%02x%02x " NOLF, tlv->value[startindx + 2], tlv->value[startindx + 3]); if (len < startindx + 6) break; // hour - fwrite(&tlv->value[startindx + 4], 1, 2, f); - fprintf(f, ":"); + PrintAndLogEx(NORMAL, "%02x%02x:" NOLF, tlv->value[startindx + 4], tlv->value[startindx + 5]); if (len < startindx + 8) break; // min - fwrite(&tlv->value[startindx + 6], 1, 2, f); - fprintf(f, ":"); + PrintAndLogEx(NORMAL, "%02x%02x:" NOLF, tlv->value[startindx + 6], tlv->value[startindx + 7]); if (len < startindx + 10) break; // sec - fwrite(&tlv->value[startindx + 8], 1, 2, f); + PrintAndLogEx(NORMAL, "%02x%02x" NOLF, tlv->value[startindx + 8], tlv->value[startindx + 9]); if (len < startindx + 11) break; // time zone - fprintf(f, " zone: %.*s", len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); - + PrintAndLogEx(NORMAL, " zone: %.*s" NOLF, len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); break; } - fprintf(f, "'\n"); + PrintAndLogEx(NORMAL, "'"); } else { - fprintf(f, "\n"); + PrintAndLogEx(NORMAL, ""); *needdump = true; } } -static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - fprintf(f, "\tvalue: '"); - fwrite(tlv->value, 1, tlv->len, f); - fprintf(f, "'\n"); +static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, int level) { + PrintAndLogEx(NORMAL, " value: '" NOLF); + PrintAndLogEx(NORMAL, "%s'", sprint_hex(tlv->value, tlv->len)); } -static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump) { +static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, int level, bool *needdump) { *needdump = false; for (size_t i = 0; i < tlv->len; i++) if (!isspace(tlv->value[i]) && !isprint(tlv->value[i])) { @@ -176,10 +167,10 @@ static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_ } if (*needdump) { - fprintf(f, "'\n"); + PrintAndLogEx(NORMAL, "'"); } else { - fprintf(f, "\t\t"); - asn1_tag_dump_string(tlv, tag, f, level); + PrintAndLogEx(NORMAL, " " NOLF); + asn1_tag_dump_string(tlv, tag, level); } } @@ -213,25 +204,26 @@ static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, u return ret; } -static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); +static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag *tag, int level) { + PrintAndLogEx(NORMAL, "%*s" NOLF, (level * 4), " "); if (tlv->len > 0) { - fprintf(f, "\tvalue: %s\n", tlv->value[0] ? "true" : "false"); + PrintAndLogEx(NORMAL, " value: %s", tlv->value[0] ? "true" : "false"); } else { - fprintf(f, "n/a\n"); + PrintAndLogEx(NORMAL, "n/a"); } } -static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); +static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, int level) { + PrintAndLogEx(NORMAL, "%*s" NOLF, (level * 4), " "); if (tlv->len == 4) { int32_t val = 0; - for (size_t i = 0; i < tlv->len; i++) + for (size_t i = 0; i < tlv->len; i++) { val = (val << 8) + tlv->value[i]; - fprintf(f, "\tvalue4b: %d\n", val); + } + PrintAndLogEx(NORMAL, " value4b: %d", val); return; } - fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); + PrintAndLogEx(NORMAL, " value: %lu", asn1_value_integer(tlv, 0, tlv->len * 2)); } static char *asn1_oid_description(const char *oid, bool with_group_desc) { @@ -277,77 +269,77 @@ error: return NULL; } -static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); +static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, int level) { + mbedtls_asn1_buf asn1_buf; asn1_buf.len = tlv->len; asn1_buf.p = (uint8_t *)tlv->value; char pstr[300]; mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); - fprintf(f, " %s", pstr); + + PrintAndLogEx(INFO, "%*s %s" NOLF, (level * 4), " ", pstr); char *jsondesc = asn1_oid_description(pstr, true); if (jsondesc) { - fprintf(f, " - %s", jsondesc); + PrintAndLogEx(NORMAL, " - %s" NOLF, jsondesc); } else { const char *ppstr; mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); + PrintAndLogEx(NORMAL, " (%s)", ppstr); return; } mbedtls_oid_get_sig_alg_desc(&asn1_buf, &ppstr); if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); + PrintAndLogEx(NORMAL, " (%s)", ppstr); return; } mbedtls_oid_get_extended_key_usage(&asn1_buf, &ppstr); if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); + PrintAndLogEx(NORMAL, " (%s)", ppstr); return; } } - fprintf(f, "\n"); + PrintAndLogEx(NORMAL, ""); } -bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { - if (!tlv) { - fprintf(f, "NULL\n"); +bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump) { + if (tlv == NULL) { + PrintAndLogEx(FAILED, "NULL\n"); return false; } const struct asn1_tag *tag = asn1_get_tag(tlv); - PRINT_INDENT(level); - fprintf(f, "--%2x[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + PrintAndLogEx(INFO, "%*s--%2x[%02zx] '%s':" NOLF, (level * 4), " ", tlv->tag, tlv->len, tag->name); switch (tag->type) { case ASN1_TAG_GENERIC: - fprintf(f, "\n"); + PrintAndLogEx(NORMAL, ""); break; case ASN1_TAG_STRING: - asn1_tag_dump_string(tlv, tag, f, level); + asn1_tag_dump_string(tlv, tag, level); *candump = false; break; case ASN1_TAG_OCTET_STRING: - asn1_tag_dump_octet_string(tlv, tag, f, level, candump); + asn1_tag_dump_octet_string(tlv, tag, level, candump); break; case ASN1_TAG_BOOLEAN: - asn1_tag_dump_boolean(tlv, tag, f, level); + asn1_tag_dump_boolean(tlv, tag, level); *candump = false; break; case ASN1_TAG_INTEGER: - asn1_tag_dump_integer(tlv, tag, f, level); + asn1_tag_dump_integer(tlv, tag, level); *candump = false; break; case ASN1_TAG_UTC_TIME: - asn1_tag_dump_str_time(tlv, tag, f, level, false, candump); + asn1_tag_dump_str_time(tlv, tag, level, false, candump); break; case ASN1_TAG_STR_TIME: - asn1_tag_dump_str_time(tlv, tag, f, level, true, candump); + asn1_tag_dump_str_time(tlv, tag, level, true, candump); break; case ASN1_TAG_OBJECT_ID: - asn1_tag_dump_object_id(tlv, tag, f, level); + asn1_tag_dump_object_id(tlv, tag, level); *candump = false; break; }; diff --git a/client/src/crypto/asn1dump.h b/client/src/crypto/asn1dump.h index c7aef7e39..21caae36d 100644 --- a/client/src/crypto/asn1dump.h +++ b/client/src/crypto/asn1dump.h @@ -13,9 +13,8 @@ #include #include #include -#include #include "emv/tlv.h" -bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump); +bool asn1_tag_dump(const struct tlv *tlv, int level, bool *candump); #endif /* asn1utils.h */ diff --git a/client/src/crypto/asn1utils.c b/client/src/crypto/asn1utils.c index 9e5826712..a076f207d 100644 --- a/client/src/crypto/asn1utils.c +++ b/client/src/crypto/asn1utils.c @@ -12,19 +12,16 @@ #include #include #include - #include "ui.h" // Print... - #include "emv/tlv.h" -#include "emv/dump.h" #include "asn1dump.h" #include "util.h" int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval) { if (!signature || !signaturelen || !rval || !sval) - return 1; + return PM3_EINVARG; - int res = 0; + int res = PM3_SUCCESS; unsigned char *p = signature; const unsigned char *end = p + signaturelen; size_t len; @@ -57,7 +54,7 @@ int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *r // check size if (end != p) - return 2; + return PM3_ESOFT; } exit: @@ -66,9 +63,9 @@ exit: static void print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) { bool candump = true; - asn1_tag_dump(tlv, stdout, level, &candump); + asn1_tag_dump(tlv, level, &candump); if (is_leaf && candump) { - dump_buffer(tlv->value, tlv->len, stdout, level); + print_buffer(tlv->value, tlv->len, level); } } @@ -80,10 +77,10 @@ int asn1_print(uint8_t *asn1buf, size_t asn1buflen, const char *indent) { tlvdb_free(t); } else { PrintAndLogEx(ERR, "Can't parse data as TLV tree"); - return 1; + return PM3_ESOFT; } - return 0; + return PM3_SUCCESS; } diff --git a/client/src/crypto/libpcrypto.c b/client/src/crypto/libpcrypto.c index 3d8e7ffc4..cb73b3f5c 100644 --- a/client/src/crypto/libpcrypto.c +++ b/client/src/crypto/libpcrypto.c @@ -418,7 +418,7 @@ int ecdsa_nist_test(bool verbose) { // make signature res = ecdsa_signature_create_test(curveid, T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen); // PrintAndLogEx(INFO, "res: %x signature[%x]: %s", (res < 0)? -res : res, siglen, sprint_hex(signature, siglen)); - if (res) + if (res != PM3_SUCCESS) goto exit; // check vectors @@ -483,7 +483,7 @@ int ecdsa_nist_test(bool verbose) { if (verbose) PrintAndLogEx(NORMAL, _GREEN_("passed\n")); - return 0; + return PM3_SUCCESS; exit: if (verbose) PrintAndLogEx(NORMAL, _RED_("failed\n")); diff --git a/client/src/emv/cmdemv.c b/client/src/emv/cmdemv.c index fa1e9618a..3e0fec872 100644 --- a/client/src/emv/cmdemv.c +++ b/client/src/emv/cmdemv.c @@ -1153,7 +1153,7 @@ static int CmdEMVExec(const char *Cmd) { // 9F27: Cryptogram Information Data (CID) const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL); if (CID) { - emv_tag_dump(CID, stdout, 0); + emv_tag_dump(CID, 1); PrintAndLogEx(NORMAL, "------------------------------"); if (CID->len > 0) { switch (CID->value[0] & EMVAC_AC_MASK) { @@ -1356,10 +1356,10 @@ static int CmdEMVExec(const char *Cmd) { // here must be AC2, but we dont make external authenticate ( /* // AC2 PRINT_INDENT(level); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) PrintAndLogEx(NORMAL, "\tAC2: AAC (Transaction declined)"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) PrintAndLogEx(NORMAL, "\tAC2: TC (Transaction approved)"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) PrintAndLogEx(NORMAL, "\tAC2: not requested (ARQC)"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) PrintAndLogEx(NORMAL, "\tAC2: RFU"); */ } } diff --git a/client/src/emv/dump.c b/client/src/emv/dump.c deleted file mode 100644 index edf60d34d..000000000 --- a/client/src/emv/dump.c +++ /dev/null @@ -1,57 +0,0 @@ -/* - * libopenemv - a library to work with EMV family of smart cards - * Copyright (C) 2015 Dmitry Eremin-Solenikov - * - * This library 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 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - */ - -#ifdef HAVE_CONFIG_H -#include -#endif - -#include "dump.h" - -#ifndef PRINT_INDENT -# define PRINT_INDENT(level) {for (int myi = 0; myi < (level); myi++) fprintf(f, " ");} -#endif - -void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) { - int i; - - if (!f) - f = stdout; - - for (i = 0; i < len; i ++) - fprintf(f, "%s%02hhX", i ? " " : "", ptr[i]); -} - -void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level) { - int i, j; - - if (!f) - f = stdout; - - for (i = 0; i < len; i += 16) { - PRINT_INDENT(level); - fprintf(f, "\t%02x:", i); - for (j = 0; j < 16; j++) { - if (i + j < len) - fprintf(f, " %02hhx", ptr[i + j]); - else - fprintf(f, " "); - } - fprintf(f, " |"); - for (j = 0; j < 16 && i + j < len; j++) { - fprintf(f, "%c", (ptr[i + j] >= 0x20 && ptr[i + j] < 0x7f) ? ptr[i + j] : '.'); - } - fprintf(f, "\n"); - } -} diff --git a/client/src/emv/dump.h b/client/src/emv/dump.h deleted file mode 100644 index 5a71b9519..000000000 --- a/client/src/emv/dump.h +++ /dev/null @@ -1,27 +0,0 @@ -/* - * libopenemv - a library to work with EMV family of smart cards - * Copyright (C) 2015 Dmitry Eremin-Solenikov - * - * This library 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 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - */ - -#ifndef DUMP_H -#define DUMP_H - -#include "common.h" - -#include // FILE - -void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f); -void dump_buffer(const unsigned char *ptr, size_t len, FILE *f, int level); -void dump_buffer_tab(const unsigned char *ptr, size_t len, FILE *f, int tabs); - -#endif diff --git a/client/src/emv/emv_pki.c b/client/src/emv/emv_pki.c index 0afcfe775..f06a5ea69 100644 --- a/client/src/emv/emv_pki.c +++ b/client/src/emv/emv_pki.c @@ -24,7 +24,6 @@ #include #include "crypto.h" -#include "dump.h" #include "util.h" #include "ui.h" @@ -73,7 +72,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, /* if (true){ PrintAndLogEx(SUCCESS, "Recovered data:\n"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); }*/ if (data[data_len - 1] != 0xbc || data[0] != 0x6a || data[1] != msgtype) { @@ -200,7 +199,7 @@ static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk, if (showData) { PrintAndLogEx(SUCCESS, "Recovered data:"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); } /* Perform the rest of checks here */ @@ -375,7 +374,7 @@ struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct t if (showData) { PrintAndLogEx(SUCCESS, "Recovered data:"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); } struct tlvdb *dac_db = tlvdb_fixed(0x9f45, 2, data + 3); @@ -409,7 +408,7 @@ struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct t if (showData) { PrintAndLogEx(SUCCESS, "Recovered data:"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); } size_t idn_len = data[4]; @@ -445,7 +444,7 @@ struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct t if (showData) { PrintAndLogEx(SUCCESS, "Recovered data:"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); } size_t idn_len = data[4]; @@ -511,7 +510,7 @@ struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct t if (showData) { PrintAndLogEx(SUCCESS, "Recovered data:"); - dump_buffer(data, data_len, stdout, 0); + print_buffer(data, data_len, 1); } if (data[3] < 30 || data[3] > data_len - 4) { diff --git a/client/src/emv/emv_tags.c b/client/src/emv/emv_tags.c index 296dcdf82..f86b88826 100644 --- a/client/src/emv/emv_tags.c +++ b/client/src/emv/emv_tags.c @@ -18,15 +18,10 @@ #endif #include "emv_tags.h" - #include #include - #include "commonutil.h" - -#ifndef PRINT_INDENT -# define PRINT_INDENT(level) {for (int myi = 0; myi < (level); myi++) fprintf(f, " ");} -#endif +#include "ui.h" enum emv_tag_t { EMV_TAG_GENERIC, @@ -455,19 +450,21 @@ static const char *bitstrings[] = { "1.......", }; -static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { +static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, int level) { const struct emv_tag_bit *bits = tag->data; unsigned bit, byte; for (byte = 1; byte <= tlv->len; byte ++) { unsigned char val = tlv->value[byte - 1]; - PRINT_INDENT(level); - fprintf(f, "\tByte %u (%02x)\n", byte, val); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Byte %u (%02x)", byte, val); for (bit = 8; bit > 0; bit--, val <<= 1) { if (val & 0x80) { - PRINT_INDENT(level); - fprintf(f, "\t\t%s - '%s'\n", bitstrings[bit - 1], - bits->bit == EMV_BIT(byte, bit) ? bits->name : "Unknown"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " %s - '%s'", + bitstrings[bit - 1], + (bits->bit == EMV_BIT(byte, bit)) ? bits->name : "Unknown" + ); } if (bits->bit == EMV_BIT(byte, bit)) bits ++; @@ -475,7 +472,7 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta } } -static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { +static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, int level) { const unsigned char *buf = tlv->value; size_t left = tlv->len; @@ -484,22 +481,20 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F const struct emv_tag *doltag; if (!tlv_parse_tl(&buf, &left, &doltlv)) { - PRINT_INDENT(level); - fprintf(f, "Invalid Tag-Len\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, "Invalid Tag-Len"); continue; } doltag = emv_get_tag(&doltlv); - PRINT_INDENT(level); - fprintf(f, "\tTag %4x len %02zx ('%s')\n", doltlv.tag, doltlv.len, doltag->name); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Tag %4x len %02zx ('%s')", doltlv.tag, doltlv.len, doltag->name); } } -static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { - fprintf(f, "\tString value '"); - fwrite(tlv->value, 1, tlv->len, f); - fprintf(f, "'\n"); +static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, int level) { + PrintAndLogEx(NORMAL, " String value '%s'", sprint_hex_inrow(tlv->value, tlv->len)); } static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, unsigned end) { @@ -532,17 +527,18 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un return ret; } -static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); - fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2)); +static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, int level) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Numeric value %lu", emv_value_numeric(tlv, 0, tlv->len * 2)); } -static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); - fprintf(f, "\tDate: 20%02lu.%lu.%lu\n", - emv_value_numeric(tlv, 0, 2), - emv_value_numeric(tlv, 2, 4), - emv_value_numeric(tlv, 4, 6)); +static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, int level) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Date: 20%02lu.%lu.%lu", + emv_value_numeric(tlv, 0, 2), + emv_value_numeric(tlv, 2, 4), + emv_value_numeric(tlv, 4, 6) + ); } static uint32_t emv_get_binary(const unsigned char *S) { @@ -550,44 +546,44 @@ static uint32_t emv_get_binary(const unsigned char *S) { } // https://github.com/binaryfoo/emv-bertlv/blob/master/src/main/resources/fields/visa-cvr.txt -static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { - if (!tlv || tlv->len < 1) { - PRINT_INDENT(level); - fprintf(f, "\tINVALID!\n"); +static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, int level) { + if (tlv == NULL || tlv->len < 1) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " INVALID length!"); return; } if (tlv->len != tlv->value[0] + 1) { - PRINT_INDENT(level); - fprintf(f, "\tINVALID length!\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " INVALID length!"); return; } if (tlv->len >= 2) { // AC1 - PRINT_INDENT(level); - if ((tlv->value[1] & 0xC0) == 0x00) fprintf(f, "\tAC1: AAC (Transaction declined)\n"); - if ((tlv->value[1] & 0xC0) == 0x40) fprintf(f, "\tAC1: TC (Transaction approved)\n"); - if ((tlv->value[1] & 0xC0) == 0x80) fprintf(f, "\tAC1: ARQC (Online authorisation requested)\n"); - if ((tlv->value[1] & 0xC0) == 0xC0) fprintf(f, "\tAC1: RFU\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + if ((tlv->value[1] & 0xC0) == 0x00) PrintAndLogEx(NORMAL, " AC1: AAC (Transaction declined)"); + if ((tlv->value[1] & 0xC0) == 0x40) PrintAndLogEx(NORMAL, " AC1: TC (Transaction approved)"); + if ((tlv->value[1] & 0xC0) == 0x80) PrintAndLogEx(NORMAL, " AC1: ARQC (Online authorisation requested)"); + if ((tlv->value[1] & 0xC0) == 0xC0) PrintAndLogEx(NORMAL, " AC1: RFU"); // AC2 - PRINT_INDENT(level); - if ((tlv->value[1] & 0x30) == 0x00) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); - if ((tlv->value[1] & 0x30) == 0x10) fprintf(f, "\tAC2: TC (Transaction approved)\n"); - if ((tlv->value[1] & 0x30) == 0x20) fprintf(f, "\tAC2: not requested (ARQC)\n"); - if ((tlv->value[1] & 0x30) == 0x30) fprintf(f, "\tAC2: RFU\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + if ((tlv->value[1] & 0x30) == 0x00) PrintAndLogEx(NORMAL, " AC2: AAC (Transaction declined)"); + if ((tlv->value[1] & 0x30) == 0x10) PrintAndLogEx(NORMAL, " AC2: TC (Transaction approved)"); + if ((tlv->value[1] & 0x30) == 0x20) PrintAndLogEx(NORMAL, " AC2: not requested (ARQC)"); + if ((tlv->value[1] & 0x30) == 0x30) PrintAndLogEx(NORMAL, " AC2: RFU"); } if (tlv->len >= 3 && (tlv->value[2] >> 4)) { - PRINT_INDENT(level); - fprintf(f, "\tPIN try: %x\n", tlv->value[2] >> 4); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " PIN try: %x", tlv->value[2] >> 4); } if (tlv->len >= 4 && (tlv->value[3] & 0x0F)) { - PRINT_INDENT(level); - fprintf(f, "\tIssuer discretionary bits: %x\n", tlv->value[3] & 0x0F); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Issuer discretionary bits: %x", tlv->value[3] & 0x0F); } if (tlv->len >= 5 && (tlv->value[4] >> 4)) { - PRINT_INDENT(level); - fprintf(f, "\tSuccessfully processed issuer script commands: %x\n", tlv->value[4] >> 4); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Successfully processed issuer script commands: %x", tlv->value[4] >> 4); } // mask 0F 0F F0 0F @@ -610,68 +606,73 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, F }; if (data[0] || data[1] || data[2] || data[3]) - emv_tag_dump_bitmask(&bit_tlv, &bit_tag, f, level); + emv_tag_dump_bitmask(&bit_tlv, &bit_tag, level); } // EMV Book 3 -static void emv_tag_dump_cid(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { - if (!tlv || tlv->len < 1) { - PRINT_INDENT(level); - fprintf(f, "\tINVALID!\n"); +static void emv_tag_dump_cid(const struct tlv *tlv, const struct emv_tag *tag, int level) { + if (tlv == NULL || tlv->len < 1) { + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " INVALID!"); return; } - PRINT_INDENT(level); - if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_AAC) fprintf(f, "\tAC1: AAC (Transaction declined)\n"); - if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_TC) fprintf(f, "\tAC1: TC (Transaction approved)\n"); - if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_ARQC) fprintf(f, "\tAC1: ARQC (Online authorisation requested)\n"); - if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_AC_MASK) fprintf(f, "\tAC1: RFU\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + + if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_AAC) + PrintAndLogEx(NORMAL, " AC1: AAC (Transaction declined)"); + if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_TC) + PrintAndLogEx(NORMAL, " AC1: TC (Transaction approved)"); + if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_ARQC) + PrintAndLogEx(NORMAL, " AC1: ARQC (Online authorisation requested)"); + if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_AC_MASK) + PrintAndLogEx(NORMAL, " AC1: RFU"); if (tlv->value[0] & EMVCID_ADVICE) { - PRINT_INDENT(level); - fprintf(f, "\tAdvice required!\n"); + PrintAndLogEx(NORMAL, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Advice required!"); } if (tlv->value[0] & EMVCID_REASON_MASK) { - PRINT_INDENT(level); - fprintf(f, "\tReason/advice/referral code: "); + PrintAndLogEx(NORMAL, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Reason/advice/referral code: " NOLF); switch ((tlv->value[0] & EMVCID_REASON_MASK)) { case 0: - fprintf(f, "No information given\n"); + PrintAndLogEx(NORMAL, "No information given"); break; case 1: - fprintf(f, "Service not allowed\n"); + PrintAndLogEx(NORMAL, "Service not allowed"); break; case 2: - fprintf(f, "PIN Try Limit exceeded\n"); + PrintAndLogEx(NORMAL, "PIN Try Limit exceeded"); break; case 3: - fprintf(f, "Issuer authentication failed\n"); + PrintAndLogEx(NORMAL, "Issuer authentication failed"); break; default: - fprintf(f, "\tRFU: %2x\n", (tlv->value[0] & EMVCID_REASON_MASK)); + PrintAndLogEx(NORMAL, " RFU: %2x", (tlv->value[0] & EMVCID_REASON_MASK)); break; } } } -static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { +static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, int level) { uint32_t X, Y; int i; if (tlv->len < 10 || tlv->len % 2) { - PRINT_INDENT(level); - fprintf(f, "\tINVALID!\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " INVALID!"); return; } X = emv_get_binary(tlv->value); Y = emv_get_binary(tlv->value + 4); - PRINT_INDENT(level); - fprintf(f, "\tX: %u\n", X); - PRINT_INDENT(level); - fprintf(f, "\tY: %u\n", Y); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " X: %u", X); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " Y: %u", Y); for (i = 8; i < tlv->len; i += 2) { const char *method; @@ -746,73 +747,76 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t break; } - PRINT_INDENT(level); - fprintf(f, "\t%02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful\n", - tlv->value[i], tlv->value[i + 1], - method, condition, (tlv->value[i] & 0x40) ? "continue" : "fail"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " %02x %02x: '%s' '%s' and '%s' if this CVM is unsuccessful", + tlv->value[i], + tlv->value[i + 1], + method, + condition, + (tlv->value[i] & 0x40) ? "continue" : "fail" + ); } } -static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { +static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, int level) { if (tlv->len < 4 || tlv->len % 4) { - PRINT_INDENT(level); - fprintf(f, "\tINVALID!\n"); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, " INVALID!"); return; } for (int i = 0; i < tlv->len / 4; i++) { - PRINT_INDENT(level); - fprintf(f, "SFI[%02x] start:%02x end:%02x offline:%02x\n", tlv->value[i * 4 + 0] >> 3, tlv->value[i * 4 + 1], tlv->value[i * 4 + 2], tlv->value[i * 4 + 3]); + PrintAndLogEx(INFO, "%*s" NOLF, (level * 4), " "); + PrintAndLogEx(NORMAL, "SFI[%02x] start:%02x end:%02x offline:%02x", tlv->value[i * 4 + 0] >> 3, tlv->value[i * 4 + 1], tlv->value[i * 4 + 2], tlv->value[i * 4 + 3]); } } -bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { - if (!tlv) { - fprintf(f, "NULL\n"); +bool emv_tag_dump(const struct tlv *tlv, int level) { + if (tlv == NULL) { + PrintAndLogEx(FAILED, "NULL"); return false; } const struct emv_tag *tag = emv_get_tag(tlv); - PRINT_INDENT(level); - fprintf(f, "--%2x[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + PrintAndLogEx(INFO, "%*s--%2x[%02zx] '%s':" NOLF, (level * 4), " ", tlv->tag, tlv->len, tag->name); switch (tag->type) { case EMV_TAG_GENERIC: - fprintf(f, "\n"); + PrintAndLogEx(NORMAL, ""); break; case EMV_TAG_BITMASK: - fprintf(f, "\n"); - emv_tag_dump_bitmask(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_bitmask(tlv, tag, level); break; case EMV_TAG_DOL: - fprintf(f, "\n"); - emv_tag_dump_dol(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_dol(tlv, tag, level); break; case EMV_TAG_CVM_LIST: - fprintf(f, "\n"); - emv_tag_dump_cvm_list(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_cvm_list(tlv, tag, level); break; case EMV_TAG_AFL: - fprintf(f, "\n"); - emv_tag_dump_afl(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_afl(tlv, tag, level); break; case EMV_TAG_STRING: - emv_tag_dump_string(tlv, tag, f, level); + emv_tag_dump_string(tlv, tag, level); break; case EMV_TAG_NUMERIC: - emv_tag_dump_numeric(tlv, tag, f, level); + emv_tag_dump_numeric(tlv, tag, level); break; case EMV_TAG_YYMMDD: - emv_tag_dump_yymmdd(tlv, tag, f, level); + emv_tag_dump_yymmdd(tlv, tag, level); break; case EMV_TAG_CVR: - fprintf(f, "\n"); - emv_tag_dump_cvr(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_cvr(tlv, tag, level); break; case EMV_TAG_CID: - fprintf(f, "\n"); - emv_tag_dump_cid(tlv, tag, f, level); + PrintAndLogEx(NORMAL, ""); + emv_tag_dump_cid(tlv, tag, level); break; }; diff --git a/client/src/emv/emv_tags.h b/client/src/emv/emv_tags.h index 235048b20..2da2cd2ef 100644 --- a/client/src/emv/emv_tags.h +++ b/client/src/emv/emv_tags.h @@ -17,7 +17,6 @@ #define TAGS_H #include "tlv.h" -#include // FILE // AC # define EMVAC_AC_MASK 0xC0 @@ -34,7 +33,7 @@ # define EMVCID_ADVICE 0x08 # define EMVCID_REASON_MASK 0x07 -bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level); +bool emv_tag_dump(const struct tlv *tlv, int level); const char *emv_get_tag_name(const struct tlv *tlv); #endif diff --git a/client/src/emv/emvcore.c b/client/src/emv/emvcore.c index 23de78c7d..913316725 100644 --- a/client/src/emv/emvcore.c +++ b/client/src/emv/emvcore.c @@ -19,7 +19,6 @@ #include "ui.h" #include "cmdhf14a.h" #include "dol.h" -#include "dump.h" #include "emv_tags.h" #include "emvjson.h" #include "util_posix.h" @@ -158,9 +157,9 @@ enum CardPSVendor GetCardPSVendor(uint8_t *AID, size_t AIDlen) { } static void print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) { - emv_tag_dump(tlv, stdout, level); + emv_tag_dump(tlv, level); if (is_leaf) { - dump_buffer(tlv->value, tlv->len, stdout, level); + print_buffer(tlv->value, tlv->len, level); } } @@ -805,6 +804,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { emv_pk_free(pk); emv_pk_free(issuer_pk); emv_pk_free(icc_pk); + atc_db = NULL; return 9; } } else { diff --git a/client/src/emv/test/cda_test.c b/client/src/emv/test/cda_test.c index acdde8bb4..b5a87952c 100644 --- a/client/src/emv/test/cda_test.c +++ b/client/src/emv/test/cda_test.c @@ -23,10 +23,10 @@ #include "../emv_pk.h" #include "../crypto.h" -#include "../dump.h" #include "../tlv.h" #include "../emv_pki.h" #include "ui.h" // printandlog +#include "util.h" // print_buffer struct emv_pk c_mchip_05 = { .rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, }, @@ -172,7 +172,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "issuer cert:"); - dump_buffer(ipk_data, ipk_data_len, stdout, 0); + print_buffer(ipk_data, ipk_data_len, 1); } size_t ipk_pk_len = ipk_data[13]; @@ -202,7 +202,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) { @@ -231,7 +231,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "icc cert:"); - dump_buffer(iccpk_data, iccpk_data_len, stdout, 0); + print_buffer(iccpk_data, iccpk_data_len, 1); } size_t iccpk_pk_len = iccpk_data[19]; @@ -260,7 +260,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash1.1:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) { @@ -287,7 +287,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "SDAD:"); - dump_buffer(sdad, sdad_len, stdout, 0); + print_buffer(sdad, sdad_len, 1); } ch = crypto_hash_open(HASH_SHA_1); @@ -308,7 +308,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash2:"); - dump_buffer(h2, 20, stdout, 0); + print_buffer(h2, 20, 1); } crypto_hash_close(ch); @@ -331,7 +331,7 @@ static int cda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash2.1:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(sdad + 5 + 8 + 1 + 8, h, 20)) { @@ -408,7 +408,7 @@ static int cda_test_pk(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "IDN:"); - dump_buffer(idn->value, idn->len, stdout, 0); + print_buffer(idn->value, idn->len, 1); } tlvdb_free(idndb); diff --git a/client/src/emv/test/crypto_test.c b/client/src/emv/test/crypto_test.c index e3b8124f0..987a672da 100644 --- a/client/src/emv/test/crypto_test.c +++ b/client/src/emv/test/crypto_test.c @@ -24,7 +24,6 @@ #include "commonutil.h" // ARRAYLEN #include "../crypto.h" -#include "../dump.h" #include "util_posix.h" #include "ui.h" // printandlog diff --git a/client/src/emv/test/dda_test.c b/client/src/emv/test/dda_test.c index 7bf6d4975..c36af108d 100644 --- a/client/src/emv/test/dda_test.c +++ b/client/src/emv/test/dda_test.c @@ -23,11 +23,10 @@ #include "dda_test.h" #include "../emv_pk.h" #include "../crypto.h" -#include "../dump.h" #include "../tlv.h" #include "../emv_pki.h" #include "ui.h" // printandlog - +#include "util.h" // print_buffer struct emv_pk mchip_05 = { .rid = { 0xa0, 0x00, 0x00, 0x00, 0x04, }, @@ -161,7 +160,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "issuer cert:"); - dump_buffer(ipk_data, ipk_data_len, stdout, 0); + print_buffer(ipk_data, ipk_data_len, 1); } size_t ipk_pk_len = ipk_data[13]; @@ -191,7 +190,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) { @@ -220,7 +219,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "icc cert:"); - dump_buffer(iccpk_data, iccpk_data_len, stdout, 0); + print_buffer(iccpk_data, iccpk_data_len, 1); } size_t iccpk_pk_len = iccpk_data[19]; @@ -249,7 +248,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash1.1:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(iccpk_data + iccpk_data_len - 21, h, 20)) { @@ -276,7 +275,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "sdad:"); - dump_buffer(sdad, sdad_len, stdout, 0); + print_buffer(sdad, sdad_len, 1); } ch = crypto_hash_open(HASH_SHA_1); @@ -297,7 +296,7 @@ static int dda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash2:"); - dump_buffer(h2, 20, stdout, 0); + print_buffer(h2, 20, 1); } crypto_hash_close(ch); @@ -356,7 +355,7 @@ static int dda_test_pk(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "IDN:"); - dump_buffer(idn->value, idn->len, stdout, 0); + print_buffer(idn->value, idn->len, 1); } tlvdb_free(idndb); diff --git a/client/src/emv/test/sda_test.c b/client/src/emv/test/sda_test.c index 04f3b70ae..731adb563 100644 --- a/client/src/emv/test/sda_test.c +++ b/client/src/emv/test/sda_test.c @@ -23,10 +23,10 @@ #include "../emv_pk.h" #include "../crypto.h" -#include "../dump.h" #include "../tlv.h" #include "../emv_pki.h" #include "ui.h" // printandlog +#include "util.h" // print_buffer #include "sda_test.h" struct emv_pk vsdc_01 = { @@ -122,7 +122,7 @@ static int sda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "issuer cert:"); - dump_buffer(ipk_data, ipk_data_len, stdout, 0); + print_buffer(ipk_data, ipk_data_len, 1); } size_t ipk_pk_len = ipk_data[13]; @@ -152,7 +152,7 @@ static int sda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash:"); - dump_buffer(h, 20, stdout, 0); + print_buffer(h, 20, 1); } if (memcmp(ipk_data + ipk_data_len - 21, h, 20)) { @@ -179,7 +179,7 @@ static int sda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "ssad:"); - dump_buffer(ssad, ssad_len, stdout, 0); + print_buffer(ssad, ssad_len, 1); } ch = crypto_hash_open(HASH_SHA_1); @@ -200,7 +200,7 @@ static int sda_test_raw(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "crypto hash2:"); - dump_buffer(h2, 20, stdout, 0); + print_buffer(h2, 20, 1); } crypto_hash_close(ch); @@ -245,7 +245,7 @@ static int sda_test_pk(bool verbose) { if (verbose) { PrintAndLogEx(INFO, "dac:"); - dump_buffer(dac->value, dac->len, stdout, 0); + print_buffer(dac->value, dac->len, 1); } tlvdb_free(dacdb); diff --git a/client/src/fido/fidocore.c b/client/src/fido/fidocore.c index 3cddbc5a9..fcebb2674 100644 --- a/client/src/fido/fidocore.c +++ b/client/src/fido/fidocore.c @@ -22,7 +22,6 @@ #include "crypto/libpcrypto.h" #include "additional_ca.h" #include "cose.h" -#include "emv/dump.h" #include "ui.h" #include "util.h" @@ -274,7 +273,7 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu } if (verbose) - PrintAndLogEx(NORMAL, "------------------DER-------------------"); + PrintAndLogEx(INFO, "------------------DER-------------------"); mbedtls_x509_crt_free(&cert); mbedtls_x509_crt_free(&cacert); @@ -364,10 +363,10 @@ static int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, uint8_t sval[300] = {0}; int res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); - if (!res) { + if (res == PM3_SUCCESS) { if (verbose) { - PrintAndLogEx(NORMAL, " r: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL, " s: %s", sprint_hex(sval, 32)); + PrintAndLogEx(INFO, " r: %s", sprint_hex(rval, 32)); + PrintAndLogEx(INFO, " s: %s", sprint_hex(sval, 32)); } uint8_t clientDataHash[32] = {0}; @@ -488,9 +487,9 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b if (showCBOR) { PrintAndLogEx(INFO, "COSE structure:"); - PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); + PrintAndLogEx(INFO, "---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); - PrintAndLogEx(NORMAL, "---------------- CBOR ------------------"); + PrintAndLogEx(INFO, "---------------- CBOR ------------------"); } res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); @@ -542,11 +541,12 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); cbor_check(res); if (verbose2) { - PrintAndLogEx(NORMAL, "DER certificate[%zu]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)der, derLen, NULL); - PrintAndLogEx(NORMAL, "\n----------------DER---------------------"); + PrintAndLogEx(INFO, "DER certificate[%zu]:", derLen); + PrintAndLogEx(INFO, "------------------DER-------------------"); + PrintAndLogEx(INFO, "%s", sprint_hex(der, derLen)); + PrintAndLogEx(INFO, "----------------DER---------------------"); } else { - PrintAndLogEx(NORMAL, "DER [%zu]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); + PrintAndLogEx(INFO, "DER [%zu]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); } JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); } @@ -558,9 +558,9 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b // print DER certificate in TLV view if (showDERTLV) { - PrintAndLogEx(NORMAL, "----------------DER TLV-----------------"); + PrintAndLogEx(INFO, "----------------DER TLV-----------------"); asn1_print(der, derLen, " "); - PrintAndLogEx(NORMAL, "----------------DER TLV-----------------"); + PrintAndLogEx(INFO, "----------------DER TLV-----------------"); } FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key)); diff --git a/client/src/flash.c b/client/src/flash.c index 95fc4b7aa..1541b8d17 100644 --- a/client/src/flash.c +++ b/client/src/flash.c @@ -373,11 +373,11 @@ static int enter_bootloader(char *serial_port_name) { PrintAndLogEx(SUCCESS, "Press and hold down button NOW if your bootloader requires it."); } msleep(100); - CloseProxmark(); + CloseProxmark(session.current_device); // Let time to OS to make the port disappear msleep(1000); - if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { + if (OpenProxmark(&session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) { PrintAndLogEx(NORMAL, _GREEN_(" found")); return PM3_SUCCESS; } else { diff --git a/client/src/mifare/desfire_crypto.h b/client/src/mifare/desfire_crypto.h index a1d514507..e7219eaf0 100644 --- a/client/src/mifare/desfire_crypto.h +++ b/client/src/mifare/desfire_crypto.h @@ -93,6 +93,7 @@ struct desfire_tag { uint8_t *crypto_buffer; size_t crypto_buffer_size; uint32_t selected_application; + bool rf_field_on; }; typedef struct desfire_tag *desfiretag_t; diff --git a/client/src/mifare/mifarehost.c b/client/src/mifare/mifarehost.c index f48a696ed..3df2e295c 100644 --- a/client/src/mifare/mifarehost.c +++ b/client/src/mifare/mifarehost.c @@ -859,7 +859,7 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0, 16)); if (wipecard) params |= MAGIC_WIPE; - if (oldUID == NULL) params |= MAGIC_UID; + if (oldUID != NULL) params |= MAGIC_UID; return mfCSetBlock(0, block0, oldUID, params); } diff --git a/client/src/mifare/ndef.c b/client/src/mifare/ndef.c index 785b822db..bd1109e80 100644 --- a/client/src/mifare/ndef.c +++ b/client/src/mifare/ndef.c @@ -14,7 +14,6 @@ #include "ui.h" #include "util.h" // sprint_hex... -#include "emv/dump.h" #include "crypto/asn1utils.h" #include "pm3_cmd.h" @@ -181,7 +180,7 @@ static int ndefDecodeSig1(uint8_t *sig, size_t siglen) { uint8_t rval[300] = {0}; uint8_t sval[300] = {0}; int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); - if (!res) { + if (res == PM3_SUCCESS) { PrintAndLogEx(SUCCESS, "\t\tr: %s", sprint_hex(rval + 32 - slen, slen)); PrintAndLogEx(SUCCESS, "\t\ts: %s", sprint_hex(sval + 32 - slen, slen)); } @@ -375,15 +374,15 @@ static int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { if (NDEFHeader.TypeLen) { PrintAndLogEx(INFO, "Type data:"); - dump_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, stdout, 1); + print_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, 1); } if (NDEFHeader.IDLen) { PrintAndLogEx(INFO, "ID data:"); - dump_buffer(NDEFHeader.ID, NDEFHeader.IDLen, stdout, 1); + print_buffer(NDEFHeader.ID, NDEFHeader.IDLen, 1); } if (NDEFHeader.PayloadLen) { PrintAndLogEx(INFO, "Payload data:"); - dump_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, stdout, 1); + print_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, 1); if (NDEFHeader.TypeLen) ndefDecodePayload(&NDEFHeader); } diff --git a/client/src/pm3.c b/client/src/pm3.c new file mode 100644 index 000000000..14f0b00ad --- /dev/null +++ b/client/src/pm3.c @@ -0,0 +1,55 @@ +//----------------------------------------------------------------------------- +// User API +//----------------------------------------------------------------------------- + +#include "pm3.h" + +#include + +#include "proxmark3.h" +#include "cmdmain.h" +#include "ui.h" +#include "usart_defs.h" +#include "util_posix.h" +#include "comms.h" + +pm3_device* pm3_open(char *port) { + pm3_init(); + OpenProxmark(&session.current_device, port, false, 20, false, USART_BAUD_RATE); + if (session.pm3_present && (TestProxmark(session.current_device) != PM3_SUCCESS)) { + PrintAndLogEx(ERR, _RED_("ERROR:") " cannot communicate with the Proxmark\n"); + CloseProxmark(session.current_device); + } + + if ((port != NULL) && (!session.pm3_present)) + exit(EXIT_FAILURE); + + if (!session.pm3_present) + PrintAndLogEx(INFO, "Running in " _YELLOW_("OFFLINE") " mode"); + // For now, there is no real device context: + return session.current_device; +} + +void pm3_close(pm3_device* dev) { + // Clean up the port + if (session.pm3_present) { + clearCommandBuffer(); + SendCommandNG(CMD_QUIT_SESSION, NULL, 0); + msleep(100); // Make sure command is sent before killing client + CloseProxmark(dev); + } +} + +int pm3_console(pm3_device* dev, char *Cmd) { + // For now, there is no real device context: + (void) dev; + return CommandReceived(Cmd); +} + +const char *pm3_name_get(pm3_device* dev) { + return dev->conn->serial_port_name; +} + +pm3_device* pm3_get_current_dev(void) { + return session.current_device; +} diff --git a/client/src/pm3.i b/client/src/pm3.i new file mode 100644 index 000000000..dc47563b2 --- /dev/null +++ b/client/src/pm3.i @@ -0,0 +1,39 @@ +%module pm3 +%{ +/* Include the header in the wrapper code */ +#include "pm3.h" +#include "comms.h" +%} + +/* Strip "pm3_" from API functions for SWIG */ +%rename("%(strip:[pm3_])s") ""; +%feature("immutable","1") pm3_current_dev; +typedef struct { + %extend { + pm3() { +// printf("SWIG pm3 constructor, get current pm3\n"); + pm3_device * p = pm3_get_current_dev(); + p->script_embedded = 1; + return p; + } + pm3(char *port) { +// printf("SWIG pm3 constructor with port, open pm3\n"); + pm3_device * p = pm3_open(port); + p->script_embedded = 0; + return p; + } + ~pm3() { + if ($self->script_embedded) { +// printf("SWIG pm3 destructor, nothing to do\n"); + } else { +// printf("SWIG pm3 destructor, close pm3\n"); + pm3_close($self); + } + } + int console(char *cmd); + char const * const name; + } +} pm3; +//%nodefaultctor device; +//%nodefaultdtor device; +/* Parse the header file to generate wrappers */ diff --git a/client/src/pm3.py b/client/src/pm3.py new file mode 100644 index 000000000..1c321a2ec --- /dev/null +++ b/client/src/pm3.py @@ -0,0 +1,80 @@ +# This file was automatically generated by SWIG (http://www.swig.org). +# Version 4.0.1 +# +# Do not make changes to this file unless you know what you are doing--modify +# the SWIG interface file instead. + +from sys import version_info as _swig_python_version_info +if _swig_python_version_info < (2, 7, 0): + raise RuntimeError("Python 2.7 or later required") + +# Import the low-level C/C++ module +if __package__ or "." in __name__: + from . import _pm3 +else: + import _pm3 + +try: + import builtins as __builtin__ +except ImportError: + import __builtin__ + +def _swig_repr(self): + try: + strthis = "proxy of " + self.this.__repr__() + except __builtin__.Exception: + strthis = "" + return "<%s.%s; %s >" % (self.__class__.__module__, self.__class__.__name__, strthis,) + + +def _swig_setattr_nondynamic_instance_variable(set): + def set_instance_attr(self, name, value): + if name == "thisown": + self.this.own(value) + elif name == "this": + set(self, name, value) + elif hasattr(self, name) and isinstance(getattr(type(self), name), property): + set(self, name, value) + else: + raise AttributeError("You cannot add instance attributes to %s" % self) + return set_instance_attr + + +def _swig_setattr_nondynamic_class_variable(set): + def set_class_attr(cls, name, value): + if hasattr(cls, name) and not isinstance(getattr(cls, name), property): + set(cls, name, value) + else: + raise AttributeError("You cannot add class attributes to %s" % cls) + return set_class_attr + + +def _swig_add_metaclass(metaclass): + """Class decorator for adding a metaclass to a SWIG wrapped class - a slimmed down version of six.add_metaclass""" + def wrapper(cls): + return metaclass(cls.__name__, cls.__bases__, cls.__dict__.copy()) + return wrapper + + +class _SwigNonDynamicMeta(type): + """Meta class to enforce nondynamic attributes (no new attributes) for a class""" + __setattr__ = _swig_setattr_nondynamic_class_variable(type.__setattr__) + + +class pm3(object): + thisown = property(lambda x: x.this.own(), lambda x, v: x.this.own(v), doc="The membership flag") + __repr__ = _swig_repr + + def __init__(self, *args): + _pm3.pm3_swiginit(self, _pm3.new_pm3(*args)) + __swig_destroy__ = _pm3.delete_pm3 + + def console(self, cmd): + return _pm3.pm3_console(self, cmd) + name = property(_pm3.pm3_name_get) + +# Register pm3 in _pm3: +_pm3.pm3_swigregister(pm3) + + + diff --git a/client/src/pm3_luawrap.c b/client/src/pm3_luawrap.c new file mode 100644 index 000000000..cc8ca7dcf --- /dev/null +++ b/client/src/pm3_luawrap.c @@ -0,0 +1,3259 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + + +#ifndef SWIGLUA +#define SWIGLUA +#endif + +#define SWIG_LUA_TARGET SWIG_LUA_FLAVOR_LUA +#define SWIG_LUA_MODULE_GLOBAL + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic C API SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "4" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the SWIG runtime code. + In 99.9% of the cases, SWIG just needs to declare them as 'static'. + + But only do this if strictly necessary, ie, if you have problems + with your compiler or suchlike. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 +#define SWIG_POINTER_NO_NULL 0x4 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The SWIG conversion methods, as ConvertPtr, return an integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old versions of SWIG, code such as the following was usually written: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + which is the same really, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + also requires SWIG_ConvertPtr to return new result values, such as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + SWIG errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() +*/ + +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast(r) (r) +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *, int *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store information on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCmp(const char *nb, const char *tb) { + int equiv = 1; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (equiv != 0 && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = SWIG_TypeNameComp(nb, ne, tb, te); + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; +} + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (strcmp(iter->type->name, c) == 0) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (iter->type == from) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + size_t l = 0; + size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + const unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + char d = *(c++); + unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = (unsigned char)((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = (unsigned char)((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (unsigned char)(d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (unsigned char)(d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +/* ----------------------------------------------------------------------------- + * luarun.swg + * + * This file contains the runtime support for Lua modules + * and includes code for managing global variables and pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include "lua.h" +#include "lauxlib.h" +#include /* for malloc */ +#include /* for a few sanity tests */ + +/* ----------------------------------------------------------------------------- + * Lua flavors + * ----------------------------------------------------------------------------- */ + +#define SWIG_LUA_FLAVOR_LUA 1 +#define SWIG_LUA_FLAVOR_ELUA 2 +#define SWIG_LUA_FLAVOR_ELUAC 3 + +#if !defined(SWIG_LUA_TARGET) +# error SWIG_LUA_TARGET not defined +#endif + +#if defined(SWIG_LUA_ELUA_EMULATE) + +struct swig_elua_entry; + +typedef struct swig_elua_key { + int type; + union { + const char* strkey; + lua_Number numkey; + } key; +} swig_elua_key; + +typedef struct swig_elua_val { + int type; + union { + lua_Number number; + const struct swig_elua_entry *table; + const char *string; + lua_CFunction function; + struct { + char member; + long lvalue; + void *pvalue; + swig_type_info **ptype; + } userdata; + } value; +} swig_elua_val; + +typedef struct swig_elua_entry { + swig_elua_key key; + swig_elua_val value; +} swig_elua_entry; + +#define LSTRKEY(x) {LUA_TSTRING, {.strkey = x} } +#define LNUMKEY(x) {LUA_TNUMBER, {.numkey = x} } +#define LNILKEY {LUA_TNIL, {.strkey = 0} } + +#define LNUMVAL(x) {LUA_TNUMBER, {.number = x} } +#define LFUNCVAL(x) {LUA_TFUNCTION, {.function = x} } +#define LROVAL(x) {LUA_TTABLE, {.table = x} } +#define LNILVAL {LUA_TNIL, {.string = 0} } +#define LSTRVAL(x) {LUA_TSTRING, {.string = x} } + +#define LUA_REG_TYPE swig_elua_entry + +#define SWIG_LUA_ELUA_EMUL_METATABLE_KEY "__metatable" + +#define lua_pushrotable(L,p)\ + lua_newtable(L);\ + assert(p);\ + SWIG_Lua_elua_emulate_register(L,(swig_elua_entry*)(p)); + +#define SWIG_LUA_CONSTTAB_POINTER(B,C,D)\ + LSTRKEY(B), {LUA_TUSERDATA, { .userdata={0,0,(void*)(C),&D} } } + +#define SWIG_LUA_CONSTTAB_BINARY(B,S,C,D)\ + LSTRKEY(B), {LUA_TUSERDATA, { .userdata={1,S,(void*)(C),&D} } } +#endif + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) +# define SWIG_LUA_CONSTTAB_INT(B, C) LSTRKEY(B), LNUMVAL(C) +# define SWIG_LUA_CONSTTAB_FLOAT(B, C) LSTRKEY(B), LNUMVAL(C) +# define SWIG_LUA_CONSTTAB_STRING(B, C) LSTRKEY(B), LSTRVAL(C) +# define SWIG_LUA_CONSTTAB_CHAR(B, C) LSTRKEY(B), LNUMVAL(C) + /* Those two types of constants are not supported in elua */ + +#ifndef SWIG_LUA_CONSTTAB_POINTER +#warning eLua does not support pointers as constants. By default, nil will be used as value +#define SWIG_LUA_CONSTTAB_POINTER(B,C,D) LSTRKEY(B), LNILVAL +#endif + +#ifndef SWIG_LUA_CONSTTAB_BINARY +#warning eLua does not support pointers to member as constants. By default, nil will be used as value +#define SWIG_LUA_CONSTTAB_BINARY(B, S, C, D) LSTRKEY(B), LNILVAL +#endif +#else /* SWIG_LUA_FLAVOR_LUA */ +# define SWIG_LUA_CONSTTAB_INT(B, C) SWIG_LUA_INT, (char *)B, (long)C, 0, 0, 0 +# define SWIG_LUA_CONSTTAB_FLOAT(B, C) SWIG_LUA_FLOAT, (char *)B, 0, (double)C, 0, 0 +# define SWIG_LUA_CONSTTAB_STRING(B, C) SWIG_LUA_STRING, (char *)B, 0, 0, (void *)C, 0 +# define SWIG_LUA_CONSTTAB_CHAR(B, C) SWIG_LUA_CHAR, (char *)B, (long)C, 0, 0, 0 +# define SWIG_LUA_CONSTTAB_POINTER(B,C,D)\ + SWIG_LUA_POINTER, (char *)B, 0, 0, (void *)C, &D +# define SWIG_LUA_CONSTTAB_BINARY(B, S, C, D)\ + SWIG_LUA_BINARY, (char *)B, S, 0, (void *)C, &D +#endif + +#ifndef SWIG_LUA_ELUA_EMULATE +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) +# define LRO_STRVAL(v) {{.p = (char *) v}, LUA_TSTRING} +# define LSTRVAL LRO_STRVAL +#endif +#endif /* SWIG_LUA_ELUA_EMULATE*/ + +#ifndef SWIG_LUA_ELUA_EMULATE +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) + +#ifndef MIN_OPT_LEVEL +#define MIN_OPT_LEVEL 2 +#endif + +#include "lrodefs.h" +#include "lrotable.h" +#endif +#endif /* SWIG_LUA_ELUA_EMULATE*/ +/* ----------------------------------------------------------------------------- + * compatibility defines + * ----------------------------------------------------------------------------- */ + +/* History of Lua C API length functions: In Lua 5.0 (and before?) + there was "lua_strlen". In Lua 5.1, this was renamed "lua_objlen", + but a compatibility define of "lua_strlen" was added. In Lua 5.2, + this function was again renamed, to "lua_rawlen" (to emphasize that + it doesn't call the "__len" metamethod), and the compatibility + define of lua_strlen was removed. All SWIG uses have been updated + to "lua_rawlen", and we add our own defines of that here for older + versions of Lua. */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 +# define lua_rawlen lua_strlen +#elif LUA_VERSION_NUM == 501 +# define lua_rawlen lua_objlen +#endif + + +/* lua_pushglobaltable is the recommended "future-proof" way to get + the global table for Lua 5.2 and later. Here we define + lua_pushglobaltable ourselves for Lua versions before 5.2. */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 +# define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) +#endif + +/* lua_absindex was introduced in Lua 5.2 */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 +# define lua_absindex(L,i) ((i)>0 || (i) <= LUA_REGISTRYINDEX ? (i) : lua_gettop(L) + (i) + 1) +#endif + +/* lua_rawsetp was introduced in Lua 5.2 */ +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 502 +#define lua_rawsetp(L,index,ptr)\ + lua_pushlightuserdata(L,(void*)(ptr));\ + lua_insert(L,-2);\ + lua_rawset(L,index); + +#define lua_rawgetp(L,index,ptr)\ + lua_pushlightuserdata(L,(void*)(ptr));\ + lua_rawget(L,index); + +#endif + +/* -------------------------------------------------------------------------- + * Helper functions for error handling + * -------------------------------------------------------------------------- */ + +/* Push the string STR on the Lua stack, like lua_pushstring, but + prefixed with the location of the innermost Lua call-point + (as formatted by luaL_where). */ +SWIGRUNTIME void +SWIG_Lua_pusherrstring (lua_State *L, const char *str) +{ + luaL_where (L, 1); + lua_pushstring (L, str); + lua_concat (L, 2); +} + +/* Push a formatted string generated from FMT and following args on + the Lua stack, like lua_pushfstring, but prefixed with the + location of the innermost Lua call-point (as formatted by luaL_where). */ +SWIGRUNTIME void +SWIG_Lua_pushferrstring (lua_State *L, const char *fmt, ...) +{ + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); +} + + +/* ----------------------------------------------------------------------------- + * global swig types + * ----------------------------------------------------------------------------- */ +/* Constant table */ +#define SWIG_LUA_INT 1 +#define SWIG_LUA_FLOAT 2 +#define SWIG_LUA_STRING 3 +#define SWIG_LUA_POINTER 4 +#define SWIG_LUA_BINARY 5 +#define SWIG_LUA_CHAR 6 + +/* Structure for variable linking table */ +typedef struct { + const char *name; + lua_CFunction get; + lua_CFunction set; +} swig_lua_var_info; + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) +typedef const LUA_REG_TYPE swig_lua_method; +typedef const LUA_REG_TYPE swig_lua_const_info; +#else /* Normal lua */ +typedef luaL_Reg swig_lua_method; + +/* Constant information structure */ +typedef struct { + int type; + char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_lua_const_info; + +#endif + +typedef struct { + const char *name; + lua_CFunction getmethod; + lua_CFunction setmethod; +} swig_lua_attribute; + + +struct swig_lua_class; +/* Can be used to create namespaces. Currently used to wrap class static methods/variables/constants */ +typedef struct swig_lua_namespace { + const char *name; + swig_lua_method *ns_methods; + swig_lua_attribute *ns_attributes; + swig_lua_const_info *ns_constants; + struct swig_lua_class **ns_classes; + struct swig_lua_namespace **ns_namespaces; +} swig_lua_namespace; + +typedef struct swig_lua_class { + const char *name; /* Name that this class has in Lua */ + const char *fqname; /* Fully qualified name - Scope + class name */ + swig_type_info **type; + lua_CFunction constructor; + void (*destructor)(void *); + swig_lua_method *methods; + swig_lua_attribute *attributes; + swig_lua_namespace *cls_static; + swig_lua_method *metatable; /* 0 for -eluac */ + struct swig_lua_class **bases; + const char **base_names; +} swig_lua_class; + +/* this is the struct for wrapping all pointers in SwigLua +*/ +typedef struct { + swig_type_info *type; + int own; /* 1 if owned & must be destroyed */ + void *ptr; +} swig_lua_userdata; + +/* this is the struct for wrapping arbitrary packed binary data +(currently it is only used for member function pointers) +the data ordering is similar to swig_lua_userdata, but it is currently not possible +to tell the two structures apart within SWIG, other than by looking at the type +*/ +typedef struct { + swig_type_info *type; + int own; /* 1 if owned & must be destroyed */ + char data[1]; /* arbitrary amount of data */ +} swig_lua_rawdata; + +/* Common SWIG API */ +#define SWIG_NewPointerObj(L, ptr, type, owner) SWIG_Lua_NewPointerObj(L, (void *)ptr, type, owner) +#define SWIG_ConvertPtr(L,idx, ptr, type, flags) SWIG_Lua_ConvertPtr(L,idx,ptr,type,flags) +#define SWIG_MustGetPtr(L,idx, type,flags, argnum,fnname) SWIG_Lua_MustGetPtr(L,idx, type,flags, argnum,fnname) +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(L, idx, ptr, sz, ty) SWIG_Lua_ConvertPacked(L, idx, ptr, sz, ty) +#define SWIG_NewMemberObj(L, ptr, sz, type) SWIG_Lua_NewPackedObj(L, ptr, sz, type) + +/* Runtime API */ +#define SWIG_GetModule(clientdata) SWIG_Lua_GetModule((lua_State*)(clientdata)) +#define SWIG_SetModule(clientdata, pointer) SWIG_Lua_SetModule((lua_State*) (clientdata), pointer) +#define SWIG_MODULE_CLIENTDATA_TYPE lua_State* + +/* Contract support */ +#define SWIG_contract_assert(expr, msg) \ + if (!(expr)) { SWIG_Lua_pusherrstring(L, (char *) msg); goto fail; } else + + +/* helper #defines */ +#define SWIG_fail {goto fail;} +#define SWIG_fail_arg(func_name,argnum,type) \ + {SWIG_Lua_pushferrstring(L,"Error in %s (arg %d), expected '%s' got '%s'",\ + func_name,argnum,type,SWIG_Lua_typename(L,argnum));\ + goto fail;} +#define SWIG_fail_ptr(func_name,argnum,type) \ + SWIG_fail_arg(func_name,argnum,(type && type->str)?type->str:"void*") +#define SWIG_check_num_args(func_name,a,b) \ + if (lua_gettop(L)b) \ + {SWIG_Lua_pushferrstring(L,"Error in %s expected %d..%d args, got %d",func_name,a,b,lua_gettop(L));\ + goto fail;} + + +#define SWIG_Lua_get_table(L,n) \ + (lua_pushstring(L, n), lua_rawget(L,-2)) + +#define SWIG_Lua_add_function(L,n,f) \ + (lua_pushstring(L, n), \ + lua_pushcfunction(L, f), \ + lua_rawset(L,-3)) + +#define SWIG_Lua_add_boolean(L,n,b) \ + (lua_pushstring(L, n), \ + lua_pushboolean(L, b), \ + lua_rawset(L,-3)) + +/* special helper for allowing 'nil' for usertypes */ +#define SWIG_isptrtype(L,I) (lua_isuserdata(L,I) || lua_isnil(L,I)) + +#ifdef __cplusplus +/* Special helper for member function pointers +it gets the address, casts it, then dereferences it */ +/*#define SWIG_mem_fn_as_voidptr(a) (*((char**)&(a))) */ +#endif + +/* storing/access of swig_module_info */ +SWIGRUNTIME swig_module_info * +SWIG_Lua_GetModule(lua_State *L) { + swig_module_info *ret = 0; + lua_pushstring(L,"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME); + lua_rawget(L,LUA_REGISTRYINDEX); + if (lua_islightuserdata(L,-1)) + ret=(swig_module_info*)lua_touserdata(L,-1); + lua_pop(L,1); /* tidy */ + return ret; +} + +SWIGRUNTIME void +SWIG_Lua_SetModule(lua_State *L, swig_module_info *module) { + /* add this all into the Lua registry: */ + lua_pushstring(L,"swig_runtime_data_type_pointer" SWIG_RUNTIME_VERSION SWIG_TYPE_TABLE_NAME); + lua_pushlightuserdata(L,(void*)module); + lua_rawset(L,LUA_REGISTRYINDEX); +} + +/* ----------------------------------------------------------------------------- + * global variable support code: modules + * ----------------------------------------------------------------------------- */ + +/* this function is called when trying to set an immutable. +default action is to print an error. +This can removed with a compile flag SWIGLUA_IGNORE_SET_IMMUTABLE */ +SWIGINTERN int SWIG_Lua_set_immutable(lua_State *L) +{ +/* there should be 1 param passed in: the new value */ +#ifndef SWIGLUA_IGNORE_SET_IMMUTABLE + lua_pop(L,1); /* remove it */ + luaL_error(L,"This variable is immutable"); +#endif + return 0; /* should not return anything */ +} + +#ifdef SWIG_LUA_ELUA_EMULATE + +SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *type, int own); +SWIGRUNTIME void SWIG_Lua_NewPackedObj(lua_State *L,void *ptr,size_t size,swig_type_info *type); +static int swig_lua_elua_emulate_unique_key; + +/* This function emulates eLua rotables behaviour. It loads a rotable definition into the usual lua table. */ +SWIGINTERN void SWIG_Lua_elua_emulate_register(lua_State *L, const swig_elua_entry *table) +{ + int i, table_parsed, parsed_tables_array, target_table; + assert(lua_istable(L,-1)); + target_table = lua_gettop(L); + /* Get the registry where we put all parsed tables to avoid loops */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &swig_lua_elua_emulate_unique_key); + if(lua_isnil(L,-1)) { + lua_pop(L,1); + lua_newtable(L); + lua_pushvalue(L,-1); + lua_rawsetp(L,LUA_REGISTRYINDEX,(void*)(&swig_lua_elua_emulate_unique_key)); + } + parsed_tables_array = lua_gettop(L); + lua_pushvalue(L,target_table); + lua_rawsetp(L, parsed_tables_array, table); + table_parsed = 0; + const int SWIGUNUSED pairs_start = lua_gettop(L); + for(i = 0;table[i].key.type != LUA_TNIL || table[i].value.type != LUA_TNIL;i++) + { + const swig_elua_entry *entry = table + i; + int is_metatable = 0; + switch(entry->key.type) { + case LUA_TSTRING: + lua_pushstring(L,entry->key.key.strkey); + if(strcmp(entry->key.key.strkey, SWIG_LUA_ELUA_EMUL_METATABLE_KEY) == 0) + is_metatable = 1; + break; + case LUA_TNUMBER: + lua_pushnumber(L,entry->key.key.numkey); + break; + case LUA_TNIL: + lua_pushnil(L); + break; + default: + assert(0); + } + switch(entry->value.type) { + case LUA_TSTRING: + lua_pushstring(L,entry->value.value.string); + break; + case LUA_TNUMBER: + lua_pushnumber(L,entry->value.value.number); + break; + case LUA_TFUNCTION: + lua_pushcfunction(L,entry->value.value.function); + break; + case LUA_TTABLE: + lua_rawgetp(L,parsed_tables_array, entry->value.value.table); + table_parsed = !lua_isnil(L,-1); + if(!table_parsed) { + lua_pop(L,1); /*remove nil */ + lua_newtable(L); + SWIG_Lua_elua_emulate_register(L,entry->value.value.table); + } + if(is_metatable) { + assert(lua_istable(L,-1)); + lua_pushvalue(L,-1); + lua_setmetatable(L,target_table); + } + + break; + case LUA_TUSERDATA: + if(entry->value.value.userdata.member) + SWIG_NewMemberObj(L,entry->value.value.userdata.pvalue, + entry->value.value.userdata.lvalue, + *(entry->value.value.userdata.ptype)); + else + SWIG_NewPointerObj(L,entry->value.value.userdata.pvalue, + *(entry->value.value.userdata.ptype),0); + break; + case LUA_TNIL: + lua_pushnil(L); + break; + default: + assert(0); + } + assert(lua_gettop(L) == pairs_start + 2); + lua_rawset(L,target_table); + } + lua_pop(L,1); /* Removing parsed tables storage */ + assert(lua_gettop(L) == target_table); +} + +SWIGINTERN void SWIG_Lua_elua_emulate_register_clear(lua_State *L) +{ + lua_pushnil(L); + lua_rawsetp(L, LUA_REGISTRYINDEX, &swig_lua_elua_emulate_unique_key); +} + +SWIGINTERN void SWIG_Lua_get_class_registry(lua_State *L); + +SWIGINTERN int SWIG_Lua_emulate_elua_getmetatable(lua_State *L) +{ + SWIG_check_num_args("getmetatable(SWIG eLua emulation)", 1, 1); + SWIG_Lua_get_class_registry(L); + lua_getfield(L,-1,"lua_getmetatable"); + lua_remove(L,-2); /* remove the registry*/ + assert(!lua_isnil(L,-1)); + lua_pushvalue(L,1); + assert(lua_gettop(L) == 3); /* object | function | object again */ + lua_call(L,1,1); + if(!lua_isnil(L,-1)) /*There is an ordinary metatable */ + return 1; + /*if it is a table, then emulate elua behaviour - check for __metatable attribute of a table*/ + assert(lua_gettop(L) == 2); + if(lua_istable(L,-2)) { + lua_pop(L,1); /*remove the nil*/ + lua_getfield(L,-1, SWIG_LUA_ELUA_EMUL_METATABLE_KEY); + } + assert(lua_gettop(L) == 2); + return 1; + +fail: + lua_error(L); + return 0; +} + +SWIGINTERN void SWIG_Lua_emulate_elua_swap_getmetatable(lua_State *L) +{ + SWIG_Lua_get_class_registry(L); + lua_pushglobaltable(L); + lua_pushstring(L,"lua_getmetatable"); + lua_getfield(L,-2,"getmetatable"); + assert(!lua_isnil(L,-1)); + lua_rawset(L,-4); + lua_pushstring(L, "getmetatable"); + lua_pushcfunction(L, SWIG_Lua_emulate_elua_getmetatable); + lua_rawset(L,-3); + lua_pop(L,2); + +} +/* END OF REMOVE */ + +#endif +/* ----------------------------------------------------------------------------- + * global variable support code: namespaces and modules (which are the same thing) + * ----------------------------------------------------------------------------- */ + +SWIGINTERN int SWIG_Lua_namespace_get(lua_State *L) +{ +/* there should be 2 params passed in + (1) table (not the meta table) + (2) string name of the attribute +*/ + assert(lua_istable(L,-2)); /* just in case */ + lua_getmetatable(L,-2); + assert(lua_istable(L,-1)); + SWIG_Lua_get_table(L,".get"); /* find the .get table */ + assert(lua_istable(L,-1)); + /* look for the key in the .get table */ + lua_pushvalue(L,2); /* key */ + lua_rawget(L,-2); + lua_remove(L,-2); /* stack tidy, remove .get table */ + if (lua_iscfunction(L,-1)) + { /* found it so call the fn & return its value */ + lua_call(L,0,1); /* 1 value in (userdata),1 out (result) */ + lua_remove(L,-2); /* stack tidy, remove metatable */ + return 1; + } + lua_pop(L,1); /* remove whatever was there */ + /* ok, so try the .fn table */ + SWIG_Lua_get_table(L,".fn"); /* find the .get table */ + assert(lua_istable(L,-1)); /* just in case */ + lua_pushvalue(L,2); /* key */ + lua_rawget(L,-2); /* look for the fn */ + lua_remove(L,-2); /* stack tidy, remove .fn table */ + if (lua_isfunction(L,-1)) /* note: whether it's a C function or lua function */ + { /* found it so return the fn & let lua call it */ + lua_remove(L,-2); /* stack tidy, remove metatable */ + return 1; + } + lua_pop(L,1); /* remove whatever was there */ + return 0; +} + +SWIGINTERN int SWIG_Lua_namespace_set(lua_State *L) +{ +/* there should be 3 params passed in + (1) table (not the meta table) + (2) string name of the attribute + (3) any for the new value +*/ + + assert(lua_istable(L,1)); + lua_getmetatable(L,1); /* get the meta table */ + assert(lua_istable(L,-1)); + + SWIG_Lua_get_table(L,".set"); /* find the .set table */ + if (lua_istable(L,-1)) + { + /* look for the key in the .set table */ + lua_pushvalue(L,2); /* key */ + lua_rawget(L,-2); + if (lua_iscfunction(L,-1)) + { /* found it so call the fn & return its value */ + lua_pushvalue(L,3); /* value */ + lua_call(L,1,0); + return 0; + } + lua_pop(L,1); /* remove the value */ + } + lua_pop(L,1); /* remove the value .set table */ + lua_pop(L,1); /* remote metatable */ + lua_rawset(L,-3); + return 0; +} + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) /* In elua this is useless */ +SWIGINTERN void SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]); /* forward declaration */ +SWIGINTERN void SWIG_Lua_add_variable(lua_State *L,const char *name,lua_CFunction getFn,lua_CFunction setFn); /* forward declaration */ +SWIGINTERN void SWIG_Lua_class_register(lua_State *L,swig_lua_class *clss); + +/* helper function - register namespace methods and attributes into namespace */ +SWIGINTERN int SWIG_Lua_add_namespace_details(lua_State *L, swig_lua_namespace *ns) +{ + int i; + /* There must be namespace table (not metatable) at the top of the stack */ + assert(lua_istable(L,-1)); + SWIG_Lua_InstallConstants(L, ns->ns_constants); + + /* add methods to the namespace/module table */ + for(i=0;ns->ns_methods[i].name;i++){ + SWIG_Lua_add_function(L,ns->ns_methods[i].name,ns->ns_methods[i].func); + } + lua_getmetatable(L,-1); + + /* add fns */ + for(i=0;ns->ns_attributes[i].name;i++){ + SWIG_Lua_add_variable(L,ns->ns_attributes[i].name,ns->ns_attributes[i].getmethod,ns->ns_attributes[i].setmethod); + } + + /* clear stack - remove metatble */ + lua_pop(L,1); + return 0; +} + +/* Register all classes in the namespace */ +SWIGINTERN void SWIG_Lua_add_namespace_classes(lua_State *L, swig_lua_namespace *ns) +{ + swig_lua_class **classes; + + /* There must be a module/namespace table at the top of the stack */ + assert(lua_istable(L,-1)); + + classes = ns->ns_classes; + + if( classes != 0 ) { + while(*classes != 0) { + SWIG_Lua_class_register(L, *classes); + classes++; + } + } +} + +/* Helper function. Creates namespace table and adds it to module table + if 'reg' is true, then will register namespace table to parent one (must be on top of the stack + when function is called). + Function always returns newly registered table on top of the stack. +*/ +SWIGINTERN void SWIG_Lua_namespace_register(lua_State *L, swig_lua_namespace *ns, int reg) +{ + swig_lua_namespace **sub_namespace; + /* 1 argument - table on the top of the stack */ + const int SWIGUNUSED begin = lua_gettop(L); + assert(lua_istable(L,-1)); /* just in case. This is supposed to be module table or parent namespace table */ + lua_checkstack(L,5); + lua_newtable(L); /* namespace itself */ + lua_newtable(L); /* metatable for namespace */ + + /* add a table called ".get" */ + lua_pushstring(L,".get"); + lua_newtable(L); + lua_rawset(L,-3); + /* add a table called ".set" */ + lua_pushstring(L,".set"); + lua_newtable(L); + lua_rawset(L,-3); + /* add a table called ".fn" */ + lua_pushstring(L,".fn"); + lua_newtable(L); + lua_rawset(L,-3); + + /* add accessor fns for using the .get,.set&.fn */ + SWIG_Lua_add_function(L,"__index",SWIG_Lua_namespace_get); + SWIG_Lua_add_function(L,"__newindex",SWIG_Lua_namespace_set); + + lua_setmetatable(L,-2); /* set metatable */ + + /* Register all functions, variables etc */ + SWIG_Lua_add_namespace_details(L,ns); + /* Register classes */ + SWIG_Lua_add_namespace_classes(L,ns); + + sub_namespace = ns->ns_namespaces; + if( sub_namespace != 0) { + while(*sub_namespace != 0) { + SWIG_Lua_namespace_register(L, *sub_namespace, 1); + lua_pop(L,1); /* removing sub-namespace table */ + sub_namespace++; + } + } + + if (reg) { + lua_pushstring(L,ns->name); + lua_pushvalue(L,-2); + lua_rawset(L,-4); /* add namespace to module table */ + } + assert(lua_gettop(L) == begin+1); +} +#endif /* SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA */ + +/* ----------------------------------------------------------------------------- + * global variable support code: classes + * ----------------------------------------------------------------------------- */ + +SWIGINTERN void SWIG_Lua_get_class_metatable(lua_State *L,const char *cname); + +typedef int (*swig_lua_base_iterator_func)(lua_State*,swig_type_info*, int, int *ret); + +SWIGINTERN int SWIG_Lua_iterate_bases(lua_State *L, swig_type_info * SWIGUNUSED swig_type, + int first_arg, swig_lua_base_iterator_func func, int *const ret) +{ + /* first_arg - position of the object in stack. Everything that is above are arguments + * and is passed to every evocation of the func */ + int last_arg = lua_gettop(L);/* position of last argument */ + int original_metatable = last_arg + 1; + size_t bases_count; + int result = SWIG_ERROR; + int bases_table; + (void)swig_type; + lua_getmetatable(L,first_arg); + + /* initialise base search */ +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) + SWIG_Lua_get_table(L,".bases"); + assert(lua_istable(L,-1)); + bases_count = lua_rawlen(L,-1); + bases_table = lua_gettop(L); +#else + /* In elua .bases table doesn't exist. Use table from swig_lua_class */ + (void)bases_table; + assert(swig_type!=0); + swig_module_info *module=SWIG_GetModule(L); + swig_lua_class **bases= ((swig_lua_class*)(swig_type->clientdata))->bases; + const char **base_names= ((swig_lua_class*)(swig_type->clientdata))->base_names; + bases_count = 0; + for(;base_names[bases_count]; + bases_count++);/* get length of bases */ +#endif + + if(ret) + *ret = 0; + if(bases_count>0) + { + int to_remove; + size_t i; + int j; + int subcall_last_arg; + int subcall_first_arg = lua_gettop(L) + 1;/* Here a copy of first_arg and arguments begin */ + int valid = 1; + swig_type_info *base_swig_type = 0; + for(j=first_arg;j<=last_arg;j++) + lua_pushvalue(L,j); + subcall_last_arg = lua_gettop(L); + + /* Trick: temporarily replacing original metatable with metatable for base class and call getter */ + for(i=0;ifqname); + base_swig_type = SWIG_TypeQueryModule(module,module,base_names[i]); + assert(base_swig_type != 0); + } +#endif + + if(!valid) + continue; + assert(lua_isuserdata(L, subcall_first_arg)); + assert(lua_istable(L,-1)); + lua_setmetatable(L,subcall_first_arg); /* Set new metatable */ + assert(lua_gettop(L) == subcall_last_arg); + result = func(L, base_swig_type,subcall_first_arg, ret); /* Forward call */ + if(result != SWIG_ERROR) { + break; + } + } + /* Restore original metatable */ + lua_pushvalue(L,original_metatable); + lua_setmetatable(L,first_arg); + /* Clear - remove everything between last_arg and subcall_last_arg including */ + to_remove = subcall_last_arg - last_arg; + for(j=0;jtype; + result = SWIG_Lua_class_do_get(L,type,1,&ret); + if(result == SWIG_OK) + return ret; + + result = SWIG_Lua_class_do_get_item(L,type,1,&ret); + if(result == SWIG_OK) + return ret; + + return 0; +} + +/* helper for the class.set method, performs the lookup of class attributes + * It returns error code. Number of function return values is passed inside 'ret' + */ +SWIGINTERN int SWIG_Lua_class_do_set(lua_State *L, swig_type_info *type, int first_arg, int *ret) +{ +/* there should be 3 params passed in + (1) table (not the meta table) + (2) string name of the attribute + (3) any for the new value + */ + + int bases_search_result; + int substack_start = lua_gettop(L) - 3; + lua_checkstack(L,5); + assert(lua_isuserdata(L,substack_start+1)); /* just in case */ + lua_getmetatable(L,substack_start+1); /* get the meta table */ + assert(lua_istable(L,-1)); /* just in case */ + if(ret) + *ret = 0; /* it is setter - number of return values is always 0 */ + + SWIG_Lua_get_table(L,".set"); /* find the .set table */ + if (lua_istable(L,-1)) + { + /* look for the key in the .set table */ + lua_pushvalue(L,substack_start+2); /* key */ + lua_rawget(L,-2); + lua_remove(L,-2); /* tidy stack, remove .set table */ + if (lua_iscfunction(L,-1)) + { /* found it so call the fn & return its value */ + lua_pushvalue(L,substack_start+1); /* userdata */ + lua_pushvalue(L,substack_start+3); /* value */ + lua_call(L,2,0); + lua_remove(L,substack_start+4); /*remove metatable*/ + return SWIG_OK; + } + lua_pop(L,1); /* remove the value */ + } else { + lua_pop(L,1); /* remove the answer for .set table request*/ + } + /* NEW: looks for the __setitem() fn + this is a user provided set fn */ + SWIG_Lua_get_table(L,"__setitem"); /* find the fn */ + if (lua_iscfunction(L,-1)) /* if its there */ + { /* found it so call the fn & return its value */ + lua_pushvalue(L,substack_start+1); /* the userdata */ + lua_pushvalue(L,substack_start+2); /* the parameter */ + lua_pushvalue(L,substack_start+3); /* the value */ + lua_call(L,3,0); /* 3 values in ,0 out */ + lua_remove(L,-2); /* stack tidy, remove metatable */ + return SWIG_OK; + } + lua_pop(L,1); /* remove value */ + + lua_pop(L,1); /* remove metatable */ + /* Search among bases */ + bases_search_result = SWIG_Lua_iterate_bases(L,type,first_arg,SWIG_Lua_class_do_set,ret); + if(ret) + assert(*ret == 0); + assert(lua_gettop(L) == substack_start + 3); + return bases_search_result; +} + +/* This is the actual method exported to Lua. It calls SWIG_Lua_class_do_set and correctly + * handles return values. + */ +SWIGINTERN int SWIG_Lua_class_set(lua_State *L) +{ +/* There should be 3 params passed in + (1) table (not the meta table) + (2) string name of the attribute + (3) any for the new value + */ + int ret = 0; + int result; + swig_lua_userdata *usr; + swig_type_info *type; + assert(lua_isuserdata(L,1)); + usr=(swig_lua_userdata*)lua_touserdata(L,1); /* get data */ + type = usr->type; + result = SWIG_Lua_class_do_set(L,type,1,&ret); + if(result != SWIG_OK) { + SWIG_Lua_pushferrstring(L,"Assignment not possible. No setter/member with this name. For custom assignments implement __setitem method."); + lua_error(L); + } else { + assert(ret==0); + } + return 0; +} + +/* the class.destruct method called by the interpreter */ +SWIGINTERN int SWIG_Lua_class_destruct(lua_State *L) +{ +/* there should be 1 params passed in + (1) userdata (not the meta table) */ + swig_lua_userdata *usr; + swig_lua_class *clss; + assert(lua_isuserdata(L,-1)); /* just in case */ + usr=(swig_lua_userdata*)lua_touserdata(L,-1); /* get it */ + /* if must be destroyed & has a destructor */ + if (usr->own) /* if must be destroyed */ + { + clss=(swig_lua_class*)usr->type->clientdata; /* get the class */ + if (clss && clss->destructor) /* there is a destroy fn */ + { + clss->destructor(usr->ptr); /* bye bye */ + } + } + return 0; +} + +/* the class.__tostring method called by the interpreter and print */ +SWIGINTERN int SWIG_Lua_class_tostring(lua_State *L) +{ +/* there should be 1 param passed in + (1) userdata (not the metatable) */ + swig_lua_userdata* userData; + assert(lua_isuserdata(L,1)); /* just in case */ + userData = (swig_lua_userdata*)lua_touserdata(L,1); /* get the userdata address */ + + lua_pushfstring(L, "", userData->type->str, userData->ptr); + return 1; +} + +/* to manually disown some userdata */ +SWIGINTERN int SWIG_Lua_class_disown(lua_State *L) +{ +/* there should be 1 params passed in + (1) userdata (not the meta table) */ + swig_lua_userdata *usr; + assert(lua_isuserdata(L,-1)); /* just in case */ + usr=(swig_lua_userdata*)lua_touserdata(L,-1); /* get it */ + + usr->own = 0; /* clear our ownership */ + return 0; +} + +/* lua callable function to compare userdata's value +the issue is that two userdata may point to the same thing +but to lua, they are different objects */ +SWIGRUNTIME int SWIG_Lua_class_equal(lua_State *L) +{ + int result; + swig_lua_userdata *usr1,*usr2; + if (!lua_isuserdata(L,1) || !lua_isuserdata(L,2)) /* just in case */ + return 0; /* nil reply */ + usr1=(swig_lua_userdata*)lua_touserdata(L,1); /* get data */ + usr2=(swig_lua_userdata*)lua_touserdata(L,2); /* get data */ + /*result=(usr1->ptr==usr2->ptr && usr1->type==usr2->type); only works if type is the same*/ + result=(usr1->ptr==usr2->ptr); + lua_pushboolean(L,result); + return 1; +} + +/* populate table at the top of the stack with metamethods that ought to be inherited */ +SWIGINTERN void SWIG_Lua_populate_inheritable_metamethods(lua_State *L) +{ + SWIG_Lua_add_boolean(L, "__add", 1); + SWIG_Lua_add_boolean(L, "__sub", 1); + SWIG_Lua_add_boolean(L, "__mul", 1); + SWIG_Lua_add_boolean(L, "__div", 1); + SWIG_Lua_add_boolean(L, "__mod", 1); + SWIG_Lua_add_boolean(L, "__pow", 1); + SWIG_Lua_add_boolean(L, "__unm", 1); + SWIG_Lua_add_boolean(L, "__len", 1 ); + SWIG_Lua_add_boolean(L, "__concat", 1 ); + SWIG_Lua_add_boolean(L, "__eq", 1); + SWIG_Lua_add_boolean(L, "__lt", 1); + SWIG_Lua_add_boolean(L, "__le", 1); + SWIG_Lua_add_boolean(L, "__call", 1); + SWIG_Lua_add_boolean(L, "__tostring", 1); + SWIG_Lua_add_boolean(L, "__gc", 0); +} + +/* creates the swig registry */ +SWIGINTERN void SWIG_Lua_create_class_registry(lua_State *L) +{ + /* create main SWIG registry table */ + lua_pushstring(L,"SWIG"); + lua_newtable(L); + /* populate it with some predefined data */ + + /* .library table. Placeholder */ + lua_pushstring(L,".library"); + lua_newtable(L); + { + /* list of metamethods that class inherits from its bases */ + lua_pushstring(L,"inheritable_metamethods"); + lua_newtable(L); + /* populate with list of metamethods */ + SWIG_Lua_populate_inheritable_metamethods(L); + lua_rawset(L,-3); + } + lua_rawset(L,-3); + + lua_rawset(L,LUA_REGISTRYINDEX); +} + +/* gets the swig registry (or creates it) */ +SWIGINTERN void SWIG_Lua_get_class_registry(lua_State *L) +{ + /* add this all into the swig registry: */ + lua_pushstring(L,"SWIG"); + lua_rawget(L,LUA_REGISTRYINDEX); /* get the registry */ + if (!lua_istable(L,-1)) /* not there */ + { /* must be first time, so add it */ + lua_pop(L,1); /* remove the result */ + SWIG_Lua_create_class_registry(L); + /* then get it */ + lua_pushstring(L,"SWIG"); + lua_rawget(L,LUA_REGISTRYINDEX); + } +} + +SWIGINTERN void SWIG_Lua_get_inheritable_metamethods(lua_State *L) +{ + SWIG_Lua_get_class_registry(L); + lua_pushstring(L, ".library"); + lua_rawget(L,-2); + assert( !lua_isnil(L,-1) ); + lua_pushstring(L, "inheritable_metamethods"); + lua_rawget(L,-2); + + /* Remove class registry and library table */ + lua_remove(L,-2); + lua_remove(L,-2); +} + +/* Helper function to get the classes metatable from the register */ +SWIGINTERN void SWIG_Lua_get_class_metatable(lua_State *L,const char *cname) +{ + SWIG_Lua_get_class_registry(L); /* get the registry */ + lua_pushstring(L,cname); /* get the name */ + lua_rawget(L,-2); /* get it */ + lua_remove(L,-2); /* tidy up (remove registry) */ +} + +/* Set up the base classes pointers. +Each class structure has a list of pointers to the base class structures. +This function fills them. +It cannot be done at compile time, as this will not work with hireachies +spread over more than one swig file. +Therefore it must be done at runtime, querying the SWIG type system. +*/ +SWIGINTERN void SWIG_Lua_init_base_class(lua_State *L,swig_lua_class *clss) +{ + int i=0; + swig_module_info *module=SWIG_GetModule(L); + for(i=0;clss->base_names[i];i++) + { + if (clss->bases[i]==0) /* not found yet */ + { + /* lookup and cache the base class */ + swig_type_info *info = SWIG_TypeQueryModule(module,module,clss->base_names[i]); + if (info) clss->bases[i] = (swig_lua_class *) info->clientdata; + } + } +} + +#if defined(SWIG_LUA_SQUASH_BASES) && (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) +/* Merges two tables */ +SWIGINTERN void SWIG_Lua_merge_tables_by_index(lua_State *L, int target, int source) +{ + /* iterating */ + lua_pushnil(L); + while (lua_next(L,source) != 0) { + /* -1 - value, -2 - index */ + /* have to copy to assign */ + lua_pushvalue(L,-2); /* copy of index */ + lua_pushvalue(L,-2); /* copy of value */ + lua_rawset(L, target); + lua_pop(L,1); + /* only key is left */ + } +} + +/* Merges two tables with given name. original - index of target metatable, base - index of source metatable */ +SWIGINTERN void SWIG_Lua_merge_tables(lua_State *L, const char* name, int original, int base) +{ + /* push original[name], then base[name] */ + lua_pushstring(L,name); + lua_rawget(L,original); + int original_table = lua_gettop(L); + lua_pushstring(L,name); + lua_rawget(L,base); + int base_table = lua_gettop(L); + SWIG_Lua_merge_tables_by_index(L, original_table, base_table); + /* clearing stack */ + lua_pop(L,2); +} + +/* Function takes all symbols from base and adds it to derived class. It's just a helper. */ +SWIGINTERN void SWIG_Lua_class_squash_base(lua_State *L, swig_lua_class *base_cls) +{ + /* There is one parameter - original, i.e. 'derived' class metatable */ + assert(lua_istable(L,-1)); + int original = lua_gettop(L); + SWIG_Lua_get_class_metatable(L,base_cls->fqname); + int base = lua_gettop(L); + SWIG_Lua_merge_tables(L, ".fn", original, base ); + SWIG_Lua_merge_tables(L, ".set", original, base ); + SWIG_Lua_merge_tables(L, ".get", original, base ); + lua_pop(L,1); +} + +/* Function squashes all symbols from 'clss' bases into itself */ +SWIGINTERN void SWIG_Lua_class_squash_bases(lua_State *L, swig_lua_class *clss) +{ + int i; + SWIG_Lua_get_class_metatable(L,clss->fqname); + for(i=0;clss->base_names[i];i++) + { + if (clss->bases[i]==0) /* Somehow it's not found. Skip it */ + continue; + /* Thing is: all bases are already registered. Thus they have already executed + * this function. So we just need to squash them into us, because their bases + * are already squashed into them. No need for recursion here! + */ + SWIG_Lua_class_squash_base(L, clss->bases[i]); + } + lua_pop(L,1); /*tidy stack*/ +} +#endif + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) /* In elua this is useless */ +/* helper add a variable to a registered class */ +SWIGINTERN void SWIG_Lua_add_variable(lua_State *L,const char *name,lua_CFunction getFn,lua_CFunction setFn) +{ + assert(lua_istable(L,-1)); /* just in case */ + SWIG_Lua_get_table(L,".get"); /* find the .get table */ + assert(lua_istable(L,-1)); /* just in case */ + SWIG_Lua_add_function(L,name,getFn); + lua_pop(L,1); /* tidy stack (remove table) */ + if (setFn) + { + SWIG_Lua_get_table(L,".set"); /* find the .set table */ + assert(lua_istable(L,-1)); /* just in case */ + SWIG_Lua_add_function(L,name,setFn); + lua_pop(L,1); /* tidy stack (remove table) */ + } +} + +/* helper to recursively add class static details (static attributes, operations and constants) */ +SWIGINTERN void SWIG_Lua_add_class_static_details(lua_State *L, swig_lua_class *clss) +{ + int i = 0; + /* The class namespace table must be on the top of the stack */ + assert(lua_istable(L,-1)); + /* call all the base classes first: we can then override these later: */ + for(i=0;clss->bases[i];i++) + { + SWIG_Lua_add_class_static_details(L,clss->bases[i]); + } + + SWIG_Lua_add_namespace_details(L, clss->cls_static); +} + +SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class *clss); /* forward declaration */ + +/* helper to recursively add class details (attributes & operations) */ +SWIGINTERN void SWIG_Lua_add_class_instance_details(lua_State *L, swig_lua_class *clss) +{ + int i; + size_t bases_count = 0; + /* Add bases to .bases table */ + SWIG_Lua_get_table(L,".bases"); + assert(lua_istable(L,-1)); /* just in case */ + for(i=0;clss->bases[i];i++) + { + SWIG_Lua_get_class_metatable(L,clss->bases[i]->fqname); + /* Base class must be already registered */ + assert(lua_istable(L,-1)); + lua_rawseti(L,-2,i+1); /* In lua indexing starts from 1 */ + bases_count++; + } + assert(lua_rawlen(L,-1) == bases_count); + lua_pop(L,1); /* remove .bases table */ + /* add attributes */ + for(i=0;clss->attributes[i].name;i++){ + SWIG_Lua_add_variable(L,clss->attributes[i].name,clss->attributes[i].getmethod,clss->attributes[i].setmethod); + } + /* add methods to the metatable */ + SWIG_Lua_get_table(L,".fn"); /* find the .fn table */ + assert(lua_istable(L,-1)); /* just in case */ + for(i=0;clss->methods[i].name;i++){ + SWIG_Lua_add_function(L,clss->methods[i].name,clss->methods[i].func); + } + lua_pop(L,1); /* tidy stack (remove table) */ + /* add operator overloads + This adds methods from metatable array to metatable. Can mess up garbage + collectind if someone defines __gc method + */ + if(clss->metatable) { + for(i=0;clss->metatable[i].name;i++) { + SWIG_Lua_add_function(L,clss->metatable[i].name,clss->metatable[i].func); + } + } + +#if !defined(SWIG_LUA_SQUASH_BASES) + /* Adding metamethods that are defined in base classes. If bases were squashed + * then it is obviously unnecessary + */ + SWIG_Lua_add_class_user_metamethods(L, clss); +#endif +} + +/* Helpers to add user defined class metamedhods - __add, __sub etc. The helpers are needed + for the following issue: Lua runtime checks for metamethod existence with rawget function + ignoring our SWIG-provided __index and __newindex functions. Thus our inheritance-aware method + search algorithm doesn't work in such case. (Not to say that Lua runtime queries metamethod directly + in metatable and not in object). + Current solution is this: if somewhere in hierarchy metamethod __x is defined, then all descendants + are automatically given a special proxy __x that calls the real __x method. + Obvious idea - to copy __x instead of creating __x-proxy is wrong because if someone changes __x in runtime, + those changes must be reflected in all descendants. +*/ + +SWIGRUNTIME int SWIG_Lua_resolve_metamethod(lua_State *L); /*forward declaration*/ + +/* The real function that resolves a metamethod. + * Function searches given class and all it's bases(recursively) for first instance of something that is + * not equal to SWIG_Lua_resolve_metatmethod. (Almost always this 'something' is actual metamethod implementation + * and it is a SWIG-generated C function.). It returns value on the top of the L and there is no garbage below the + * answer. + * Returns 1 if found, 0 otherwise. + * clss is class which metatable we will search for method + * metamethod_name_idx is index in L where metamethod name (as string) lies + * skip_check allows to skip searching metamethod in givel clss and immideatelly go to searching in bases. skip_check + * is not caried to subsequent recursive calls - false is always passed. It is set to true only at first call from + * SWIG_Lua_resolve_metamethod + * */ +SWIGINTERN int SWIG_Lua_do_resolve_metamethod(lua_State *L, const swig_lua_class *clss, int metamethod_name_idx, + int skip_check) +{ + /* This function is called recursively */ + int result = 0; + int i = 0; + + if (!skip_check) { + SWIG_Lua_get_class_metatable(L, clss->fqname); + lua_pushvalue(L, metamethod_name_idx); + lua_rawget(L,-2); + /* If this is cfunction and it is equal to SWIG_Lua_resolve_metamethod then + * this isn't the function we are looking for :) + * lua_tocfunction will return NULL if not cfunction + */ + if (!lua_isnil(L,-1) && lua_tocfunction(L,-1) != SWIG_Lua_resolve_metamethod ) { + lua_remove(L,-2); /* removing class metatable */ + return 1; + } + lua_pop(L,2); /* remove class metatable and query result */ + } + + /* Forwarding calls to bases */ + for(i=0;clss->bases[i];i++) + { + result = SWIG_Lua_do_resolve_metamethod(L, clss->bases[i], metamethod_name_idx, 0); + if (result) + break; + } + + return result; +} + +/* The proxy function for metamethod. All parameters are passed as cclosure. Searches for actual method + * and calls it */ +SWIGRUNTIME int SWIG_Lua_resolve_metamethod(lua_State *L) +{ + int numargs; + int metamethod_name_idx; + const swig_lua_class* clss; + int result; + + lua_checkstack(L,5); + numargs = lua_gettop(L); /* number of arguments to pass to actual metamethod */ + + /* Get upvalues from closure */ + lua_pushvalue(L, lua_upvalueindex(1)); /*Get function name*/ + metamethod_name_idx = lua_gettop(L); + + lua_pushvalue(L, lua_upvalueindex(2)); + clss = (const swig_lua_class*)(lua_touserdata(L,-1)); + lua_pop(L,1); /* remove lightuserdata with clss from stack */ + + /* Actual work */ + result = SWIG_Lua_do_resolve_metamethod(L, clss, metamethod_name_idx, 1); + if (!result) { + SWIG_Lua_pushferrstring(L,"The metamethod proxy is set, but it failed to find actual metamethod. Memory corruption is most likely explanation."); + lua_error(L); + return 0; + } + + lua_remove(L,-2); /* remove metamethod key */ + lua_insert(L,1); /* move function to correct position */ + lua_call(L, numargs, LUA_MULTRET); + return lua_gettop(L); /* return all results */ +} + + +/* If given metamethod must be present in given class, then creates appropriate proxy + * Returns 1 if successfully added, 0 if not added because no base class has it, -1 + * if method is defined in the class metatable itself + */ +SWIGINTERN int SWIG_Lua_add_class_user_metamethod(lua_State *L, swig_lua_class *clss, const int metatable_index) +{ + int key_index; + int success = 0; + int i = 0; + + /* metamethod name - on the top of the stack */ + assert(lua_isstring(L,-1)); + + key_index = lua_gettop(L); + + /* Check whether method is already defined in metatable */ + lua_pushvalue(L,key_index); /* copy of the key */ + lua_gettable(L,metatable_index); + if( !lua_isnil(L,-1) ) { + lua_pop(L,1); + return -1; + } + lua_pop(L,1); + + /* Iterating over immediate bases */ + for(i=0;clss->bases[i];i++) + { + const swig_lua_class *base = clss->bases[i]; + SWIG_Lua_get_class_metatable(L, base->fqname); + lua_pushvalue(L, key_index); + lua_rawget(L, -2); + if( !lua_isnil(L,-1) ) { + lua_pushvalue(L, key_index); + + /* Add proxy function */ + lua_pushvalue(L, key_index); /* first closure value is function name */ + lua_pushlightuserdata(L, clss); /* second closure value is swig_lua_class structure */ + lua_pushcclosure(L, SWIG_Lua_resolve_metamethod, 2); + + lua_rawset(L, metatable_index); + success = 1; + } + lua_pop(L,1); /* remove function or nil */ + lua_pop(L,1); /* remove base class metatable */ + + if( success ) + break; + } + + return success; +} + +SWIGINTERN void SWIG_Lua_add_class_user_metamethods(lua_State *L, swig_lua_class *clss) +{ + int metatable_index; + int metamethods_info_index; + int tostring_undefined; + int eq_undefined = 0; + + SWIG_Lua_get_class_metatable(L, clss->fqname); + metatable_index = lua_gettop(L); + SWIG_Lua_get_inheritable_metamethods(L); + assert(lua_istable(L,-1)); + metamethods_info_index = lua_gettop(L); + lua_pushnil(L); /* first key */ + while(lua_next(L, metamethods_info_index) != 0 ) { + /* key at index -2, value at index -1 */ + const int is_inheritable = lua_toboolean(L,-2); + lua_pop(L,1); /* remove value - we don't need it anymore */ + + if(is_inheritable) { /* if metamethod is inheritable */ + SWIG_Lua_add_class_user_metamethod(L,clss,metatable_index); + } + } + + lua_pop(L,1); /* remove inheritable metatmethods table */ + + /* Special handling for __tostring method */ + lua_pushstring(L, "__tostring"); + lua_pushvalue(L,-1); + lua_rawget(L,metatable_index); + tostring_undefined = lua_isnil(L,-1); + lua_pop(L,1); + if( tostring_undefined ) { + lua_pushcfunction(L, SWIG_Lua_class_tostring); + lua_rawset(L, metatable_index); + } else { + lua_pop(L,1); /* remove copy of the key */ + } + + /* Special handling for __eq method */ + lua_pushstring(L, "__eq"); + lua_pushvalue(L,-1); + lua_rawget(L,metatable_index); + eq_undefined = lua_isnil(L,-1); + lua_pop(L,1); + if( eq_undefined ) { + lua_pushcfunction(L, SWIG_Lua_class_equal); + lua_rawset(L, metatable_index); + } else { + lua_pop(L,1); /* remove copy of the key */ + } + /* Warning: __index and __newindex are SWIG-defined. For user-defined operator[] + * a __getitem/__setitem method should be defined + */ + lua_pop(L,1); /* pop class metatable */ +} + +/* Register class static methods,attributes etc as well as constructor proxy */ +SWIGINTERN void SWIG_Lua_class_register_static(lua_State *L, swig_lua_class *clss) +{ + const int SWIGUNUSED begin = lua_gettop(L); + lua_checkstack(L,5); /* just in case */ + assert(lua_istable(L,-1)); /* just in case */ + assert(strcmp(clss->name, clss->cls_static->name) == 0); /* in class those 2 must be equal */ + + SWIG_Lua_namespace_register(L,clss->cls_static, 1); + + assert(lua_istable(L,-1)); /* just in case */ + + /* add its constructor to module with the name of the class + so you can do MyClass(...) as well as new_MyClass(...) + BUT only if a constructor is defined + (this overcomes the problem of pure virtual classes without constructors)*/ + if (clss->constructor) + { + lua_getmetatable(L,-1); + assert(lua_istable(L,-1)); /* just in case */ + SWIG_Lua_add_function(L,"__call", clss->constructor); + lua_pop(L,1); + } + + assert(lua_istable(L,-1)); /* just in case */ + SWIG_Lua_add_class_static_details(L, clss); + + /* clear stack */ + lua_pop(L,1); + assert( lua_gettop(L) == begin ); +} + +/* Performs the instance (non-static) class registration process. Metatable for class is created + * and added to the class registry. + */ +SWIGINTERN void SWIG_Lua_class_register_instance(lua_State *L,swig_lua_class *clss) +{ + const int SWIGUNUSED begin = lua_gettop(L); + int i; + /* if name already there (class is already registered) then do nothing */ + SWIG_Lua_get_class_registry(L); /* get the registry */ + lua_pushstring(L,clss->fqname); /* get the name */ + lua_rawget(L,-2); + if(!lua_isnil(L,-1)) { + lua_pop(L,2); + assert(lua_gettop(L)==begin); + return; + } + lua_pop(L,2); /* tidy stack */ + /* Recursively initialize all bases */ + for(i=0;clss->bases[i];i++) + { + SWIG_Lua_class_register_instance(L,clss->bases[i]); + } + /* Again, get registry and push name */ + SWIG_Lua_get_class_registry(L); /* get the registry */ + lua_pushstring(L,clss->fqname); /* get the name */ + lua_newtable(L); /* create the metatable */ +#if defined(SWIG_LUA_SQUASH_BASES) && (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) + /* If squashing is requested, then merges all bases metatable into this one. + * It would get us all special methods: __getitem, __add etc. + * This would set .fn, .type, and other .xxx incorrectly, but we will overwrite it right away + */ + { + int new_metatable_index = lua_absindex(L,-1); + for(i=0;clss->bases[i];i++) + { + int base_metatable; + SWIG_Lua_get_class_metatable(L,clss->bases[i]->fqname); + base_metatable = lua_absindex(L,-1); + SWIG_Lua_merge_tables_by_index(L,new_metatable_index, base_metatable); + lua_pop(L,1); + } + } + /* And now we will overwrite all incorrectly set data */ +#endif + /* add string of class name called ".type" */ + lua_pushstring(L,".type"); + lua_pushstring(L,clss->fqname); + lua_rawset(L,-3); + /* add a table called bases */ + lua_pushstring(L,".bases"); + lua_newtable(L); + lua_rawset(L,-3); + /* add a table called ".get" */ + lua_pushstring(L,".get"); + lua_newtable(L); + lua_rawset(L,-3); + /* add a table called ".set" */ + lua_pushstring(L,".set"); + lua_newtable(L); + lua_rawset(L,-3); + /* add a table called ".fn" */ + lua_pushstring(L,".fn"); + lua_newtable(L); + /* add manual disown method */ + SWIG_Lua_add_function(L,"__disown",SWIG_Lua_class_disown); + lua_rawset(L,-3); + /* add accessor fns for using the .get,.set&.fn */ + SWIG_Lua_add_function(L,"__index",SWIG_Lua_class_get); + SWIG_Lua_add_function(L,"__newindex",SWIG_Lua_class_set); + SWIG_Lua_add_function(L,"__gc",SWIG_Lua_class_destruct); + /* add it */ + lua_rawset(L,-3); /* metatable into registry */ + lua_pop(L,1); /* tidy stack (remove registry) */ + assert(lua_gettop(L) == begin); + +#if defined(SWIG_LUA_SQUASH_BASES) && (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) + /* Now merge all symbols from .fn, .set, .get etc from bases to our tables */ + SWIG_Lua_class_squash_bases(L,clss); +#endif + SWIG_Lua_get_class_metatable(L,clss->fqname); + SWIG_Lua_add_class_instance_details(L,clss); /* recursive adding of details (atts & ops) */ + lua_pop(L,1); /* tidy stack (remove class metatable) */ + assert( lua_gettop(L) == begin ); +} + +SWIGINTERN void SWIG_Lua_class_register(lua_State *L,swig_lua_class *clss) +{ + int SWIGUNUSED begin; + assert(lua_istable(L,-1)); /* This is a table (module or namespace) where classes will be added */ + SWIG_Lua_class_register_instance(L,clss); + SWIG_Lua_class_register_static(L,clss); + + /* Add links from static part to instance part and vice versa */ + /* [SWIG registry] [Module] + * "MyClass" ----> [MyClass metatable] <===== "MyClass" -+> [static part] + * ".get" ----> ... | | getmetatable()----| + * ".set" ----> ... | | | + * ".static" --------------)----------------/ [static part metatable] + * | ".get" --> ... + * | ".set" --> .... + * |=============================== ".instance" + */ + begin = lua_gettop(L); + lua_pushstring(L,clss->cls_static->name); + lua_rawget(L,-2); /* get class static table */ + assert(lua_istable(L,-1)); + lua_getmetatable(L,-1); + assert(lua_istable(L,-1)); /* get class static metatable */ + lua_pushstring(L,".instance"); /* prepare key */ + + SWIG_Lua_get_class_metatable(L,clss->fqname); /* get class metatable */ + assert(lua_istable(L,-1)); + lua_pushstring(L,".static"); /* prepare key */ + lua_pushvalue(L, -4); /* push static class TABLE */ + assert(lua_istable(L,-1)); + lua_rawset(L,-3); /* assign static class table(!NOT metatable) as ".static" member of class metatable */ + lua_rawset(L,-3); /* assign class metatable as ".instance" member of class static METATABLE */ + lua_pop(L,2); + assert(lua_gettop(L) == begin); +} +#endif /* SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA */ + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) +SWIGINTERN void SWIG_Lua_elua_class_register_instance(lua_State *L, swig_lua_class *clss) +{ + const int SWIGUNUSED begin = lua_gettop(L); + int i; + /* if name already there (class is already registered) then do nothing */ + SWIG_Lua_get_class_registry(L); /* get the registry */ + lua_pushstring(L,clss->fqname); /* get the name */ + lua_rawget(L,-2); + if(!lua_isnil(L,-1)) { + lua_pop(L,2); + assert(lua_gettop(L)==begin); + return; + } + lua_pop(L,2); /* tidy stack */ + /* Recursively initialize all bases */ + for(i=0;clss->bases[i];i++) + { + SWIG_Lua_elua_class_register_instance(L,clss->bases[i]); + } + /* Again, get registry and push name */ + SWIG_Lua_get_class_registry(L); /* get the registry */ + lua_pushstring(L,clss->fqname); /* get the name */ + assert(clss->metatable); + lua_pushrotable(L, (void*)(clss->metatable)); /* create the metatable */ + lua_rawset(L,-3); + lua_pop(L,1); + assert(lua_gettop(L) == begin); +} +#endif /* elua && eluac */ + +/* ----------------------------------------------------------------------------- + * Class/structure conversion fns + * ----------------------------------------------------------------------------- */ + +/* helper to add metatable to new lua object */ +SWIGINTERN void SWIG_Lua_AddMetatable(lua_State *L,swig_type_info *type) +{ + if (type->clientdata) /* there is clientdata: so add the metatable */ + { + SWIG_Lua_get_class_metatable(L,((swig_lua_class*)(type->clientdata))->fqname); + if (lua_istable(L,-1)) + { + lua_setmetatable(L,-2); + } + else + { + lua_pop(L,1); + } + } +} + +/* pushes a new object into the lua stack */ +SWIGRUNTIME void SWIG_Lua_NewPointerObj(lua_State *L,void *ptr,swig_type_info *type, int own) +{ + swig_lua_userdata *usr; + if (!ptr){ + lua_pushnil(L); + return; + } + usr=(swig_lua_userdata*)lua_newuserdata(L,sizeof(swig_lua_userdata)); /* get data */ + usr->ptr=ptr; /* set the ptr */ + usr->type=type; + usr->own=own; +#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC) + SWIG_Lua_AddMetatable(L,type); /* add metatable */ +#endif +} + +/* takes a object from the lua stack & converts it into an object of the correct type + (if possible) */ +SWIGRUNTIME int SWIG_Lua_ConvertPtr(lua_State *L,int index,void **ptr,swig_type_info *type,int flags) +{ + swig_lua_userdata *usr; + swig_cast_info *cast; + /* special case: lua nil => NULL pointer */ + if (lua_isnil(L,index)) + { + *ptr=0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; + } + usr=(swig_lua_userdata*)lua_touserdata(L,index); /* get data */ + if (usr) + { + if (flags & SWIG_POINTER_DISOWN) /* must disown the object */ + { + usr->own=0; + } + if (!type) /* special cast void*, no casting fn */ + { + *ptr=usr->ptr; + return SWIG_OK; /* ok */ + } + cast=SWIG_TypeCheckStruct(usr->type,type); /* performs normal type checking */ + if (cast) + { + int newmemory = 0; + *ptr=SWIG_TypeCast(cast,usr->ptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + return SWIG_OK; /* ok */ + } + } + return SWIG_ERROR; /* error */ +} + +SWIGRUNTIME void* SWIG_Lua_MustGetPtr(lua_State *L,int index,swig_type_info *type,int flags, + int argnum,const char *func_name){ + void *result; + if (!SWIG_IsOK(SWIG_ConvertPtr(L,index,&result,type,flags))){ + luaL_error (L,"Error in %s, expected a %s at argument number %d\n", + func_name,(type && type->str)?type->str:"void*",argnum); + } + return result; +} + +/* pushes a packed userdata. user for member fn pointers only */ +SWIGRUNTIME void SWIG_Lua_NewPackedObj(lua_State *L,void *ptr,size_t size,swig_type_info *type) +{ + swig_lua_rawdata *raw; + assert(ptr); /* not acceptable to pass in a NULL value */ + raw=(swig_lua_rawdata*)lua_newuserdata(L,sizeof(swig_lua_rawdata)-1+size); /* alloc data */ + raw->type=type; + raw->own=0; + memcpy(raw->data,ptr,size); /* copy the data */ + SWIG_Lua_AddMetatable(L,type); /* add metatable */ +} + +/* converts a packed userdata. user for member fn pointers only */ +SWIGRUNTIME int SWIG_Lua_ConvertPacked(lua_State *L,int index,void *ptr,size_t size,swig_type_info *type) +{ + swig_lua_rawdata *raw; + raw=(swig_lua_rawdata*)lua_touserdata(L,index); /* get data */ + if (!raw) return SWIG_ERROR; /* error */ + if (type==0 || type==raw->type) /* void* or identical type */ + { + memcpy(ptr,raw->data,size); /* copy it */ + return SWIG_OK; /* ok */ + } + return SWIG_ERROR; /* error */ +} + +/* a function to get the typestring of a piece of data */ +SWIGRUNTIME const char *SWIG_Lua_typename(lua_State *L, int tp) +{ + swig_lua_userdata *usr; + if (lua_isuserdata(L,tp)) + { + usr=(swig_lua_userdata*)lua_touserdata(L,tp); /* get data */ + if (usr && usr->type && usr->type->str) + return usr->type->str; + return "userdata (unknown type)"; + } + return lua_typename(L,lua_type(L,tp)); +} + +/* lua callable function to get the userdata's type */ +SWIGRUNTIME int SWIG_Lua_type(lua_State *L) +{ + lua_pushstring(L,SWIG_Lua_typename(L,1)); + return 1; +} + +/* ----------------------------------------------------------------------------- + * global variable support code: class/struct typemap functions + * ----------------------------------------------------------------------------- */ + +#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) +/* Install Constants */ +SWIGINTERN void +SWIG_Lua_InstallConstants(lua_State *L, swig_lua_const_info constants[]) { + int i; + for (i = 0; constants[i].type; i++) { + switch(constants[i].type) { + case SWIG_LUA_INT: + lua_pushstring(L,constants[i].name); + lua_pushinteger(L,(lua_Integer)constants[i].lvalue); + lua_rawset(L,-3); + break; + case SWIG_LUA_FLOAT: + lua_pushstring(L,constants[i].name); + lua_pushnumber(L,(lua_Number)constants[i].dvalue); + lua_rawset(L,-3); + break; + case SWIG_LUA_CHAR: + lua_pushstring(L,constants[i].name); + { + char c = (char)constants[i].lvalue; + lua_pushlstring(L,&c,1); + } + lua_rawset(L,-3); + break; + case SWIG_LUA_STRING: + lua_pushstring(L,constants[i].name); + lua_pushstring(L,(char *) constants[i].pvalue); + lua_rawset(L,-3); + break; + case SWIG_LUA_POINTER: + lua_pushstring(L,constants[i].name); + SWIG_NewPointerObj(L,constants[i].pvalue, *(constants[i]).ptype,0); + lua_rawset(L,-3); + break; + case SWIG_LUA_BINARY: + lua_pushstring(L,constants[i].name); + SWIG_NewMemberObj(L,constants[i].pvalue,constants[i].lvalue,*(constants[i]).ptype); + lua_rawset(L,-3); + break; + default: + break; + } + } +} +#endif + +/* ----------------------------------------------------------------------------- + * executing lua code from within the wrapper + * ----------------------------------------------------------------------------- */ + +#ifndef SWIG_DOSTRING_FAIL /* Allows redefining of error function */ +#define SWIG_DOSTRING_FAIL(S) fprintf(stderr,"%s\n",S) +#endif +/* Executes a C string in Lua which is a really simple way of calling lua from C +Unfortunately lua keeps changing its APIs, so we need a conditional compile +In lua 5.0.X it's lua_dostring() +In lua 5.1.X it's luaL_dostring() +*/ +SWIGINTERN int +SWIG_Lua_dostring(lua_State *L, const char *str) { + int ok,top; + if (str==0 || str[0]==0) return 0; /* nothing to do */ + top=lua_gettop(L); /* save stack */ +#if (defined(LUA_VERSION_NUM) && (LUA_VERSION_NUM>=501)) + ok=luaL_dostring(L,str); /* looks like this is lua 5.1.X or later, good */ +#else + ok=lua_dostring(L,str); /* might be lua 5.0.x, using lua_dostring */ +#endif + if (ok!=0) { + SWIG_DOSTRING_FAIL(lua_tostring(L,-1)); + } + lua_settop(L,top); /* restore the stack */ + return ok; +} + +#ifdef __cplusplus +} +#endif + +/* ------------------------------ end luarun.swg ------------------------------ */ + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_pm3 swig_types[0] +static swig_type_info *swig_types[2]; +static swig_module_info swig_module = {swig_types, 1, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#define SWIG_name "pm3" +#define SWIG_init luaopen_pm3 +#define SWIG_init_user luaopen_pm3_user + +#define SWIG_LUACODE luaopen_pm3_luacode + +/* Include the header in the wrapper code */ +#include "pm3.h" +#include "comms.h" + +SWIGINTERN pm3 *new_pm3__SWIG_0(void){ +// printf("SWIG pm3 constructor, get current pm3\n"); + pm3_device * p = pm3_get_current_dev(); + p->script_embedded = 1; + return p; + } + +SWIGINTERN int SWIG_lua_isnilstring(lua_State *L, int idx) { + int ret = lua_isstring(L, idx); + if (!ret) + ret = lua_isnil(L, idx); + return ret; +} + +SWIGINTERN pm3 *new_pm3__SWIG_1(char *port){ +// printf("SWIG pm3 constructor with port, open pm3\n"); + pm3_device * p = pm3_open(port); + p->script_embedded = 0; + return p; + } +SWIGINTERN void delete_pm3(pm3 *self){ + if (self->script_embedded) { +// printf("SWIG pm3 destructor, nothing to do\n"); + } else { +// printf("SWIG pm3 destructor, close pm3\n"); + pm3_close(self); + } + } +#ifdef __cplusplus +extern "C" { +#endif +static int _wrap_new_pm3__SWIG_0(lua_State* L) { + int SWIG_arg = 0; + pm3 *result = 0 ; + + SWIG_check_num_args("pm3::pm3",0,0) + result = (pm3 *)new_pm3__SWIG_0(); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_pm3,1); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_new_pm3__SWIG_1(lua_State* L) { + int SWIG_arg = 0; + char *arg1 = (char *) 0 ; + pm3 *result = 0 ; + + SWIG_check_num_args("pm3::pm3",1,1) + if(!SWIG_lua_isnilstring(L,1)) SWIG_fail_arg("pm3::pm3",1,"char *"); + arg1 = (char *)lua_tostring(L, 1); + result = (pm3 *)new_pm3__SWIG_1(arg1); + SWIG_NewPointerObj(L,result,SWIGTYPE_p_pm3,1); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_new_pm3(lua_State* L) { + int argc; + int argv[2]={ + 1,2 + }; + + argc = lua_gettop(L); + if (argc == 0) { + return _wrap_new_pm3__SWIG_0(L); + } + if (argc == 1) { + int _v; + { + _v = SWIG_lua_isnilstring(L,argv[0]); + } + if (_v) { + return _wrap_new_pm3__SWIG_1(L); + } + } + + SWIG_Lua_pusherrstring(L,"Wrong arguments for overloaded function 'new_pm3'\n" + " Possible C/C++ prototypes are:\n" + " pm3::pm3()\n" + " pm3::pm3(char *)\n"); + lua_error(L);return 0; +} + + +static int _wrap_pm3_console(lua_State* L) { + int SWIG_arg = 0; + pm3 *arg1 = (pm3 *) 0 ; + char *arg2 = (char *) 0 ; + int result; + + SWIG_check_num_args("pm3::console",2,2) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("pm3::console",1,"pm3 *"); + if(!SWIG_lua_isnilstring(L,2)) SWIG_fail_arg("pm3::console",2,"char *"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_pm3,0))){ + SWIG_fail_ptr("pm3_console",1,SWIGTYPE_p_pm3); + } + + arg2 = (char *)lua_tostring(L, 2); + result = (int)pm3_console(arg1,arg2); + lua_pushnumber(L, (lua_Number) result); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static int _wrap_pm3_name_get(lua_State* L) { + int SWIG_arg = 0; + pm3 *arg1 = (pm3 *) 0 ; + char *result = 0 ; + + SWIG_check_num_args("pm3::name",1,1) + if(!SWIG_isptrtype(L,1)) SWIG_fail_arg("pm3::name",1,"pm3 *"); + + if (!SWIG_IsOK(SWIG_ConvertPtr(L,1,(void**)&arg1,SWIGTYPE_p_pm3,0))){ + SWIG_fail_ptr("pm3_name_get",1,SWIGTYPE_p_pm3); + } + + result = (char *)pm3_name_get(arg1); + lua_pushstring(L,(const char *)result); SWIG_arg++; + return SWIG_arg; + + if(0) SWIG_fail; + +fail: + lua_error(L); + return SWIG_arg; +} + + +static void swig_delete_pm3(void *obj) { +pm3 *arg1 = (pm3 *) obj; +delete_pm3(arg1); +} +static int _proxy__wrap_new_pm3(lua_State *L) { + assert(lua_istable(L,1)); + lua_pushcfunction(L,_wrap_new_pm3); + assert(!lua_isnil(L,-1)); + lua_replace(L,1); /* replace our table with real constructor */ + lua_call(L,lua_gettop(L)-1,1); + return 1; +} +static swig_lua_attribute swig_pm3_attributes[] = { + { "name", _wrap_pm3_name_get, SWIG_Lua_set_immutable }, + {0,0,0} +}; +static swig_lua_method swig_pm3_methods[]= { + { "console", _wrap_pm3_console}, + {0,0} +}; +static swig_lua_method swig_pm3_meta[] = { + {0,0} +}; + +static swig_lua_attribute swig_pm3_Sf_SwigStatic_attributes[] = { + {0,0,0} +}; +static swig_lua_const_info swig_pm3_Sf_SwigStatic_constants[]= { + {0,0,0,0,0,0} +}; +static swig_lua_method swig_pm3_Sf_SwigStatic_methods[]= { + {0,0} +}; +static swig_lua_class* swig_pm3_Sf_SwigStatic_classes[]= { + 0 +}; + +static swig_lua_namespace swig_pm3_Sf_SwigStatic = { + "pm3", + swig_pm3_Sf_SwigStatic_methods, + swig_pm3_Sf_SwigStatic_attributes, + swig_pm3_Sf_SwigStatic_constants, + swig_pm3_Sf_SwigStatic_classes, + 0 +}; +static swig_lua_class *swig_pm3_bases[] = {0}; +static const char *swig_pm3_base_names[] = {0}; +static swig_lua_class _wrap_class_pm3 = { "pm3", "pm3", &SWIGTYPE_p_pm3,_proxy__wrap_new_pm3, swig_delete_pm3, swig_pm3_methods, swig_pm3_attributes, &swig_pm3_Sf_SwigStatic, swig_pm3_meta, swig_pm3_bases, swig_pm3_base_names }; + +static swig_lua_attribute swig_SwigModule_attributes[] = { + {0,0,0} +}; +static swig_lua_const_info swig_SwigModule_constants[]= { + {0,0,0,0,0,0} +}; +static swig_lua_method swig_SwigModule_methods[]= { + {0,0} +}; +static swig_lua_class* swig_SwigModule_classes[]= { +&_wrap_class_pm3, + 0 +}; +static swig_lua_namespace* swig_SwigModule_namespaces[] = { + 0 +}; + +static swig_lua_namespace swig_SwigModule = { + "pm3", + swig_SwigModule_methods, + swig_SwigModule_attributes, + swig_SwigModule_constants, + swig_SwigModule_classes, + swig_SwigModule_namespaces +}; +#ifdef __cplusplus +} +#endif + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_pm3 = {"_p_pm3", "pm3 *", 0, 0, (void*)&_wrap_class_pm3, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_pm3, +}; + +static swig_cast_info _swigc__p_pm3[] = { {&_swigt__p_pm3, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_pm3, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned statically to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int init; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + init = 1; + } else { + init = 0; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + iter=module_head; + do { + if (iter==&swig_module) { + /* Our module is already in the list, so there's nothing more to do. */ + return; + } + iter=iter->next; + } while (iter!= module_head); + + /* otherwise we must add our module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* When multiple interpreters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %lu\n", (unsigned long)swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ /* c-mode */ +#endif +} +#endif + + + +/* Forward declaration of where the user's %init{} gets inserted */ +void SWIG_init_user(lua_State* L ); + +#ifdef __cplusplus +extern "C" { +#endif +/* this is the initialization function + added at the very end of the code + the function is always called SWIG_init, but an earlier #define will rename it +*/ +#if ((SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC)) +LUALIB_API int SWIG_init(lua_State* L) +#else +SWIGEXPORT int SWIG_init(lua_State* L) /* default Lua action */ +#endif +{ +#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC) /* valid for both Lua and eLua */ + int i; + int globalRegister = 0; + /* start with global table */ + lua_pushglobaltable (L); + /* SWIG's internal initialisation */ + SWIG_InitializeModule((void*)L); + SWIG_PropagateClientData(); +#endif + +#if ((SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUA) && (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC)) || defined(SWIG_LUA_ELUA_EMULATE) + /* add a global fn */ + SWIG_Lua_add_function(L,"swig_type",SWIG_Lua_type); + SWIG_Lua_add_function(L,"swig_equals",SWIG_Lua_class_equal); +#endif + +#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC) + /* set up base class pointers (the hierarchy) */ + for (i = 0; swig_types[i]; i++){ + if (swig_types[i]->clientdata){ + SWIG_Lua_init_base_class(L,(swig_lua_class*)(swig_types[i]->clientdata)); + } + } +#ifdef SWIG_LUA_MODULE_GLOBAL + globalRegister = 1; +#endif + + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_LUA) + SWIG_Lua_namespace_register(L,&swig_SwigModule, globalRegister); +#endif + +#if (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUA) || (SWIG_LUA_TARGET == SWIG_LUA_FLAVOR_ELUAC) + for (i = 0; swig_types[i]; i++){ + if (swig_types[i]->clientdata){ + SWIG_Lua_elua_class_register_instance(L,(swig_lua_class*)(swig_types[i]->clientdata)); + } + } +#endif + +#if defined(SWIG_LUA_ELUA_EMULATE) + lua_newtable(L); + SWIG_Lua_elua_emulate_register(L,swig_SwigModule.ns_methods); + SWIG_Lua_elua_emulate_register_clear(L); + if(globalRegister) { + lua_pushstring(L,swig_SwigModule.name); + lua_pushvalue(L,-2); + lua_rawset(L,-4); + } +#endif + +#endif + +#if (SWIG_LUA_TARGET != SWIG_LUA_FLAVOR_ELUAC) + /* invoke user-specific initialization */ + SWIG_init_user(L); + /* end module */ + /* Note: We do not clean up the stack here (Lua will do this for us). At this + point, we have the globals table and out module table on the stack. Returning + one value makes the module table the result of the require command. */ + return 1; +#else + return 0; +#endif +} + +#ifdef __cplusplus +} +#endif + + +const char* SWIG_LUACODE= + ""; + +void SWIG_init_user(lua_State* L) +{ + /* exec Lua code if applicable */ + SWIG_Lua_dostring(L,SWIG_LUACODE); +} + diff --git a/client/src/pm3_pywrap.c b/client/src/pm3_pywrap.c new file mode 100644 index 000000000..03a584e48 --- /dev/null +++ b/client/src/pm3_pywrap.c @@ -0,0 +1,3781 @@ +/* ---------------------------------------------------------------------------- + * This file was automatically generated by SWIG (http://www.swig.org). + * Version 4.0.1 + * + * This file is not intended to be easily readable and contains a number of + * coding conventions designed to improve portability and efficiency. Do not make + * changes to this file unless you know what you are doing--modify the SWIG + * interface file instead. + * ----------------------------------------------------------------------------- */ + + +#ifndef SWIGPYTHON +#define SWIGPYTHON +#endif + +#define SWIG_PYTHON_DIRECTOR_NO_VTABLE + +/* ----------------------------------------------------------------------------- + * This section contains generic SWIG labels for method/variable + * declarations/attributes, and other compiler dependent labels. + * ----------------------------------------------------------------------------- */ + +/* template workaround for compilers that cannot correctly implement the C++ standard */ +#ifndef SWIGTEMPLATEDISAMBIGUATOR +# if defined(__SUNPRO_CC) && (__SUNPRO_CC <= 0x560) +# define SWIGTEMPLATEDISAMBIGUATOR template +# elif defined(__HP_aCC) +/* Needed even with `aCC -AA' when `aCC -V' reports HP ANSI C++ B3910B A.03.55 */ +/* If we find a maximum version that requires this, the test would be __HP_aCC <= 35500 for A.03.55 */ +# define SWIGTEMPLATEDISAMBIGUATOR template +# else +# define SWIGTEMPLATEDISAMBIGUATOR +# endif +#endif + +/* inline attribute */ +#ifndef SWIGINLINE +# if defined(__cplusplus) || (defined(__GNUC__) && !defined(__STRICT_ANSI__)) +# define SWIGINLINE inline +# else +# define SWIGINLINE +# endif +#endif + +/* attribute recognised by some compilers to avoid 'unused' warnings */ +#ifndef SWIGUNUSED +# if defined(__GNUC__) +# if !(defined(__cplusplus)) || (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4)) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +# elif defined(__ICC) +# define SWIGUNUSED __attribute__ ((__unused__)) +# else +# define SWIGUNUSED +# endif +#endif + +#ifndef SWIG_MSC_UNSUPPRESS_4505 +# if defined(_MSC_VER) +# pragma warning(disable : 4505) /* unreferenced local function has been removed */ +# endif +#endif + +#ifndef SWIGUNUSEDPARM +# ifdef __cplusplus +# define SWIGUNUSEDPARM(p) +# else +# define SWIGUNUSEDPARM(p) p SWIGUNUSED +# endif +#endif + +/* internal SWIG method */ +#ifndef SWIGINTERN +# define SWIGINTERN static SWIGUNUSED +#endif + +/* internal inline SWIG method */ +#ifndef SWIGINTERNINLINE +# define SWIGINTERNINLINE SWIGINTERN SWIGINLINE +#endif + +/* exporting methods */ +#if defined(__GNUC__) +# if (__GNUC__ >= 4) || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4) +# ifndef GCC_HASCLASSVISIBILITY +# define GCC_HASCLASSVISIBILITY +# endif +# endif +#endif + +#ifndef SWIGEXPORT +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# if defined(STATIC_LINKED) +# define SWIGEXPORT +# else +# define SWIGEXPORT __declspec(dllexport) +# endif +# else +# if defined(__GNUC__) && defined(GCC_HASCLASSVISIBILITY) +# define SWIGEXPORT __attribute__ ((visibility("default"))) +# else +# define SWIGEXPORT +# endif +# endif +#endif + +/* calling conventions for Windows */ +#ifndef SWIGSTDCALL +# if defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) +# define SWIGSTDCALL __stdcall +# else +# define SWIGSTDCALL +# endif +#endif + +/* Deal with Microsoft's attempt at deprecating C standard runtime functions */ +#if !defined(SWIG_NO_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +# define _CRT_SECURE_NO_DEPRECATE +#endif + +/* Deal with Microsoft's attempt at deprecating methods in the standard C++ library */ +#if !defined(SWIG_NO_SCL_SECURE_NO_DEPRECATE) && defined(_MSC_VER) && !defined(_SCL_SECURE_NO_DEPRECATE) +# define _SCL_SECURE_NO_DEPRECATE +#endif + +/* Deal with Apple's deprecated 'AssertMacros.h' from Carbon-framework */ +#if defined(__APPLE__) && !defined(__ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES) +# define __ASSERT_MACROS_DEFINE_VERSIONS_WITHOUT_UNDERSCORES 0 +#endif + +/* Intel's compiler complains if a variable which was never initialised is + * cast to void, which is a common idiom which we use to indicate that we + * are aware a variable isn't used. So we just silence that warning. + * See: https://github.com/swig/swig/issues/192 for more discussion. + */ +#ifdef __INTEL_COMPILER +# pragma warning disable 592 +#endif + + +#if defined(__GNUC__) && defined(_WIN32) && !defined(SWIG_PYTHON_NO_HYPOT_WORKAROUND) +/* Workaround for '::hypot' has not been declared', see https://bugs.python.org/issue11566 */ +# include +#endif + +#if defined(_DEBUG) && defined(SWIG_PYTHON_INTERPRETER_NO_DEBUG) +/* Use debug wrappers with the Python release dll */ +# undef _DEBUG +# include +# define _DEBUG 1 +#else +# include +#endif + +/* ----------------------------------------------------------------------------- + * swigrun.swg + * + * This file contains generic C API SWIG runtime support for pointer + * type checking. + * ----------------------------------------------------------------------------- */ + +/* This should only be incremented when either the layout of swig_type_info changes, + or for whatever reason, the runtime changes incompatibly */ +#define SWIG_RUNTIME_VERSION "4" + +/* define SWIG_TYPE_TABLE_NAME as "SWIG_TYPE_TABLE" */ +#ifdef SWIG_TYPE_TABLE +# define SWIG_QUOTE_STRING(x) #x +# define SWIG_EXPAND_AND_QUOTE_STRING(x) SWIG_QUOTE_STRING(x) +# define SWIG_TYPE_TABLE_NAME SWIG_EXPAND_AND_QUOTE_STRING(SWIG_TYPE_TABLE) +#else +# define SWIG_TYPE_TABLE_NAME +#endif + +/* + You can use the SWIGRUNTIME and SWIGRUNTIMEINLINE macros for + creating a static or dynamic library from the SWIG runtime code. + In 99.9% of the cases, SWIG just needs to declare them as 'static'. + + But only do this if strictly necessary, ie, if you have problems + with your compiler or suchlike. +*/ + +#ifndef SWIGRUNTIME +# define SWIGRUNTIME SWIGINTERN +#endif + +#ifndef SWIGRUNTIMEINLINE +# define SWIGRUNTIMEINLINE SWIGRUNTIME SWIGINLINE +#endif + +/* Generic buffer size */ +#ifndef SWIG_BUFFER_SIZE +# define SWIG_BUFFER_SIZE 1024 +#endif + +/* Flags for pointer conversions */ +#define SWIG_POINTER_DISOWN 0x1 +#define SWIG_CAST_NEW_MEMORY 0x2 +#define SWIG_POINTER_NO_NULL 0x4 + +/* Flags for new pointer objects */ +#define SWIG_POINTER_OWN 0x1 + + +/* + Flags/methods for returning states. + + The SWIG conversion methods, as ConvertPtr, return an integer + that tells if the conversion was successful or not. And if not, + an error code can be returned (see swigerrors.swg for the codes). + + Use the following macros/flags to set or process the returning + states. + + In old versions of SWIG, code such as the following was usually written: + + if (SWIG_ConvertPtr(obj,vptr,ty.flags) != -1) { + // success code + } else { + //fail code + } + + Now you can be more explicit: + + int res = SWIG_ConvertPtr(obj,vptr,ty.flags); + if (SWIG_IsOK(res)) { + // success code + } else { + // fail code + } + + which is the same really, but now you can also do + + Type *ptr; + int res = SWIG_ConvertPtr(obj,(void **)(&ptr),ty.flags); + if (SWIG_IsOK(res)) { + // success code + if (SWIG_IsNewObj(res) { + ... + delete *ptr; + } else { + ... + } + } else { + // fail code + } + + I.e., now SWIG_ConvertPtr can return new objects and you can + identify the case and take care of the deallocation. Of course that + also requires SWIG_ConvertPtr to return new result values, such as + + int SWIG_ConvertPtr(obj, ptr,...) { + if () { + if () { + *ptr = ; + return SWIG_NEWOBJ; + } else { + *ptr = ; + return SWIG_OLDOBJ; + } + } else { + return SWIG_BADOBJ; + } + } + + Of course, returning the plain '0(success)/-1(fail)' still works, but you can be + more explicit by returning SWIG_BADOBJ, SWIG_ERROR or any of the + SWIG errors code. + + Finally, if the SWIG_CASTRANK_MODE is enabled, the result code + allows to return the 'cast rank', for example, if you have this + + int food(double) + int fooi(int); + + and you call + + food(1) // cast rank '1' (1 -> 1.0) + fooi(1) // cast rank '0' + + just use the SWIG_AddCast()/SWIG_CheckState() +*/ + +#define SWIG_OK (0) +#define SWIG_ERROR (-1) +#define SWIG_IsOK(r) (r >= 0) +#define SWIG_ArgError(r) ((r != SWIG_ERROR) ? r : SWIG_TypeError) + +/* The CastRankLimit says how many bits are used for the cast rank */ +#define SWIG_CASTRANKLIMIT (1 << 8) +/* The NewMask denotes the object was created (using new/malloc) */ +#define SWIG_NEWOBJMASK (SWIG_CASTRANKLIMIT << 1) +/* The TmpMask is for in/out typemaps that use temporal objects */ +#define SWIG_TMPOBJMASK (SWIG_NEWOBJMASK << 1) +/* Simple returning values */ +#define SWIG_BADOBJ (SWIG_ERROR) +#define SWIG_OLDOBJ (SWIG_OK) +#define SWIG_NEWOBJ (SWIG_OK | SWIG_NEWOBJMASK) +#define SWIG_TMPOBJ (SWIG_OK | SWIG_TMPOBJMASK) +/* Check, add and del mask methods */ +#define SWIG_AddNewMask(r) (SWIG_IsOK(r) ? (r | SWIG_NEWOBJMASK) : r) +#define SWIG_DelNewMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_NEWOBJMASK) : r) +#define SWIG_IsNewObj(r) (SWIG_IsOK(r) && (r & SWIG_NEWOBJMASK)) +#define SWIG_AddTmpMask(r) (SWIG_IsOK(r) ? (r | SWIG_TMPOBJMASK) : r) +#define SWIG_DelTmpMask(r) (SWIG_IsOK(r) ? (r & ~SWIG_TMPOBJMASK) : r) +#define SWIG_IsTmpObj(r) (SWIG_IsOK(r) && (r & SWIG_TMPOBJMASK)) + +/* Cast-Rank Mode */ +#if defined(SWIG_CASTRANK_MODE) +# ifndef SWIG_TypeRank +# define SWIG_TypeRank unsigned long +# endif +# ifndef SWIG_MAXCASTRANK /* Default cast allowed */ +# define SWIG_MAXCASTRANK (2) +# endif +# define SWIG_CASTRANKMASK ((SWIG_CASTRANKLIMIT) -1) +# define SWIG_CastRank(r) (r & SWIG_CASTRANKMASK) +SWIGINTERNINLINE int SWIG_AddCast(int r) { + return SWIG_IsOK(r) ? ((SWIG_CastRank(r) < SWIG_MAXCASTRANK) ? (r + 1) : SWIG_ERROR) : r; +} +SWIGINTERNINLINE int SWIG_CheckState(int r) { + return SWIG_IsOK(r) ? SWIG_CastRank(r) + 1 : 0; +} +#else /* no cast-rank mode */ +# define SWIG_AddCast(r) (r) +# define SWIG_CheckState(r) (SWIG_IsOK(r) ? 1 : 0) +#endif + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void *(*swig_converter_func)(void *, int *); +typedef struct swig_type_info *(*swig_dycast_func)(void **); + +/* Structure to store information on one type */ +typedef struct swig_type_info { + const char *name; /* mangled name of this type */ + const char *str; /* human readable name of this type */ + swig_dycast_func dcast; /* dynamic cast function down a hierarchy */ + struct swig_cast_info *cast; /* linked list of types that can cast into this type */ + void *clientdata; /* language specific type data */ + int owndata; /* flag if the structure owns the clientdata */ +} swig_type_info; + +/* Structure to store a type and conversion function used for casting */ +typedef struct swig_cast_info { + swig_type_info *type; /* pointer to type that is equivalent to this type */ + swig_converter_func converter; /* function to cast the void pointers */ + struct swig_cast_info *next; /* pointer to next cast in linked list */ + struct swig_cast_info *prev; /* pointer to the previous cast */ +} swig_cast_info; + +/* Structure used to store module information + * Each module generates one structure like this, and the runtime collects + * all of these structures and stores them in a circularly linked list.*/ +typedef struct swig_module_info { + swig_type_info **types; /* Array of pointers to swig_type_info structures that are in this module */ + size_t size; /* Number of types in this module */ + struct swig_module_info *next; /* Pointer to next element in circularly linked list */ + swig_type_info **type_initial; /* Array of initially generated type structures */ + swig_cast_info **cast_initial; /* Array of initially generated casting structures */ + void *clientdata; /* Language specific module data */ +} swig_module_info; + +/* + Compare two type names skipping the space characters, therefore + "char*" == "char *" and "Class" == "Class", etc. + + Return 0 when the two name types are equivalent, as in + strncmp, but skipping ' '. +*/ +SWIGRUNTIME int +SWIG_TypeNameComp(const char *f1, const char *l1, + const char *f2, const char *l2) { + for (;(f1 != l1) && (f2 != l2); ++f1, ++f2) { + while ((*f1 == ' ') && (f1 != l1)) ++f1; + while ((*f2 == ' ') && (f2 != l2)) ++f2; + if (*f1 != *f2) return (*f1 > *f2) ? 1 : -1; + } + return (int)((l1 - f1) - (l2 - f2)); +} + +/* + Check type equivalence in a name list like ||... + Return 0 if equal, -1 if nb < tb, 1 if nb > tb +*/ +SWIGRUNTIME int +SWIG_TypeCmp(const char *nb, const char *tb) { + int equiv = 1; + const char* te = tb + strlen(tb); + const char* ne = nb; + while (equiv != 0 && *ne) { + for (nb = ne; *ne; ++ne) { + if (*ne == '|') break; + } + equiv = SWIG_TypeNameComp(nb, ne, tb, te); + if (*ne) ++ne; + } + return equiv; +} + +/* + Check type equivalence in a name list like ||... + Return 0 if not equal, 1 if equal +*/ +SWIGRUNTIME int +SWIG_TypeEquiv(const char *nb, const char *tb) { + return SWIG_TypeCmp(nb, tb) == 0 ? 1 : 0; +} + +/* + Check the typename +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheck(const char *c, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (strcmp(iter->type->name, c) == 0) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Identical to SWIG_TypeCheck, except strcmp is replaced with a pointer comparison +*/ +SWIGRUNTIME swig_cast_info * +SWIG_TypeCheckStruct(swig_type_info *from, swig_type_info *ty) { + if (ty) { + swig_cast_info *iter = ty->cast; + while (iter) { + if (iter->type == from) { + if (iter == ty->cast) + return iter; + /* Move iter to the top of the linked list */ + iter->prev->next = iter->next; + if (iter->next) + iter->next->prev = iter->prev; + iter->next = ty->cast; + iter->prev = 0; + if (ty->cast) ty->cast->prev = iter; + ty->cast = iter; + return iter; + } + iter = iter->next; + } + } + return 0; +} + +/* + Cast a pointer up an inheritance hierarchy +*/ +SWIGRUNTIMEINLINE void * +SWIG_TypeCast(swig_cast_info *ty, void *ptr, int *newmemory) { + return ((!ty) || (!ty->converter)) ? ptr : (*ty->converter)(ptr, newmemory); +} + +/* + Dynamic pointer casting. Down an inheritance hierarchy +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeDynamicCast(swig_type_info *ty, void **ptr) { + swig_type_info *lastty = ty; + if (!ty || !ty->dcast) return ty; + while (ty && (ty->dcast)) { + ty = (*ty->dcast)(ptr); + if (ty) lastty = ty; + } + return lastty; +} + +/* + Return the name associated with this type +*/ +SWIGRUNTIMEINLINE const char * +SWIG_TypeName(const swig_type_info *ty) { + return ty->name; +} + +/* + Return the pretty name associated with this type, + that is an unmangled type name in a form presentable to the user. +*/ +SWIGRUNTIME const char * +SWIG_TypePrettyName(const swig_type_info *type) { + /* The "str" field contains the equivalent pretty names of the + type, separated by vertical-bar characters. We choose + to print the last name, as it is often (?) the most + specific. */ + if (!type) return NULL; + if (type->str != NULL) { + const char *last_name = type->str; + const char *s; + for (s = type->str; *s; s++) + if (*s == '|') last_name = s+1; + return last_name; + } + else + return type->name; +} + +/* + Set the clientdata field for a type +*/ +SWIGRUNTIME void +SWIG_TypeClientData(swig_type_info *ti, void *clientdata) { + swig_cast_info *cast = ti->cast; + /* if (ti->clientdata == clientdata) return; */ + ti->clientdata = clientdata; + + while (cast) { + if (!cast->converter) { + swig_type_info *tc = cast->type; + if (!tc->clientdata) { + SWIG_TypeClientData(tc, clientdata); + } + } + cast = cast->next; + } +} +SWIGRUNTIME void +SWIG_TypeNewClientData(swig_type_info *ti, void *clientdata) { + SWIG_TypeClientData(ti, clientdata); + ti->owndata = 1; +} + +/* + Search for a swig_type_info structure only by mangled name + Search is a O(log #types) + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_MangledTypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + swig_module_info *iter = start; + do { + if (iter->size) { + size_t l = 0; + size_t r = iter->size - 1; + do { + /* since l+r >= 0, we can (>> 1) instead (/ 2) */ + size_t i = (l + r) >> 1; + const char *iname = iter->types[i]->name; + if (iname) { + int compare = strcmp(name, iname); + if (compare == 0) { + return iter->types[i]; + } else if (compare < 0) { + if (i) { + r = i - 1; + } else { + break; + } + } else if (compare > 0) { + l = i + 1; + } + } else { + break; /* should never happen */ + } + } while (l <= r); + } + iter = iter->next; + } while (iter != end); + return 0; +} + +/* + Search for a swig_type_info structure for either a mangled name or a human readable name. + It first searches the mangled names of the types, which is a O(log #types) + If a type is not found it then searches the human readable names, which is O(#types). + + We start searching at module start, and finish searching when start == end. + Note: if start == end at the beginning of the function, we go all the way around + the circular list. +*/ +SWIGRUNTIME swig_type_info * +SWIG_TypeQueryModule(swig_module_info *start, + swig_module_info *end, + const char *name) { + /* STEP 1: Search the name field using binary search */ + swig_type_info *ret = SWIG_MangledTypeQueryModule(start, end, name); + if (ret) { + return ret; + } else { + /* STEP 2: If the type hasn't been found, do a complete search + of the str field (the human readable name) */ + swig_module_info *iter = start; + do { + size_t i = 0; + for (; i < iter->size; ++i) { + if (iter->types[i]->str && (SWIG_TypeEquiv(iter->types[i]->str, name))) + return iter->types[i]; + } + iter = iter->next; + } while (iter != end); + } + + /* neither found a match */ + return 0; +} + +/* + Pack binary data into a string +*/ +SWIGRUNTIME char * +SWIG_PackData(char *c, void *ptr, size_t sz) { + static const char hex[17] = "0123456789abcdef"; + const unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + unsigned char uu = *u; + *(c++) = hex[(uu & 0xf0) >> 4]; + *(c++) = hex[uu & 0xf]; + } + return c; +} + +/* + Unpack binary data from a string +*/ +SWIGRUNTIME const char * +SWIG_UnpackData(const char *c, void *ptr, size_t sz) { + unsigned char *u = (unsigned char *) ptr; + const unsigned char *eu = u + sz; + for (; u != eu; ++u) { + char d = *(c++); + unsigned char uu; + if ((d >= '0') && (d <= '9')) + uu = (unsigned char)((d - '0') << 4); + else if ((d >= 'a') && (d <= 'f')) + uu = (unsigned char)((d - ('a'-10)) << 4); + else + return (char *) 0; + d = *(c++); + if ((d >= '0') && (d <= '9')) + uu |= (unsigned char)(d - '0'); + else if ((d >= 'a') && (d <= 'f')) + uu |= (unsigned char)(d - ('a'-10)); + else + return (char *) 0; + *u = uu; + } + return c; +} + +/* + Pack 'void *' into a string buffer. +*/ +SWIGRUNTIME char * +SWIG_PackVoidPtr(char *buff, void *ptr, const char *name, size_t bsz) { + char *r = buff; + if ((2*sizeof(void *) + 2) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,&ptr,sizeof(void *)); + if (strlen(name) + 1 > (bsz - (r - buff))) return 0; + strcpy(r,name); + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackVoidPtr(const char *c, void **ptr, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + *ptr = (void *) 0; + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sizeof(void *)); +} + +SWIGRUNTIME char * +SWIG_PackDataName(char *buff, void *ptr, size_t sz, const char *name, size_t bsz) { + char *r = buff; + size_t lname = (name ? strlen(name) : 0); + if ((2*sz + 2 + lname) > bsz) return 0; + *(r++) = '_'; + r = SWIG_PackData(r,ptr,sz); + if (lname) { + strncpy(r,name,lname+1); + } else { + *r = 0; + } + return buff; +} + +SWIGRUNTIME const char * +SWIG_UnpackDataName(const char *c, void *ptr, size_t sz, const char *name) { + if (*c != '_') { + if (strcmp(c,"NULL") == 0) { + memset(ptr,0,sz); + return name; + } else { + return 0; + } + } + return SWIG_UnpackData(++c,ptr,sz); +} + +#ifdef __cplusplus +} +#endif + +/* Errors in SWIG */ +#define SWIG_UnknownError -1 +#define SWIG_IOError -2 +#define SWIG_RuntimeError -3 +#define SWIG_IndexError -4 +#define SWIG_TypeError -5 +#define SWIG_DivisionByZero -6 +#define SWIG_OverflowError -7 +#define SWIG_SyntaxError -8 +#define SWIG_ValueError -9 +#define SWIG_SystemError -10 +#define SWIG_AttributeError -11 +#define SWIG_MemoryError -12 +#define SWIG_NullReferenceError -13 + + + +/* Compatibility macros for Python 3 */ +#if PY_VERSION_HEX >= 0x03000000 + +#define PyClass_Check(obj) PyObject_IsInstance(obj, (PyObject *)&PyType_Type) +#define PyInt_Check(x) PyLong_Check(x) +#define PyInt_AsLong(x) PyLong_AsLong(x) +#define PyInt_FromLong(x) PyLong_FromLong(x) +#define PyInt_FromSize_t(x) PyLong_FromSize_t(x) +#define PyString_Check(name) PyBytes_Check(name) +#define PyString_FromString(x) PyUnicode_FromString(x) +#define PyString_Format(fmt, args) PyUnicode_Format(fmt, args) +#define PyString_AsString(str) PyBytes_AsString(str) +#define PyString_Size(str) PyBytes_Size(str) +#define PyString_InternFromString(key) PyUnicode_InternFromString(key) +#define Py_TPFLAGS_HAVE_CLASS Py_TPFLAGS_BASETYPE +#define PyString_AS_STRING(x) PyUnicode_AS_STRING(x) +#define _PyLong_FromSsize_t(x) PyLong_FromSsize_t(x) + +#endif + +#ifndef Py_TYPE +# define Py_TYPE(op) ((op)->ob_type) +#endif + +/* SWIG APIs for compatibility of both Python 2 & 3 */ + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_FromFormat PyUnicode_FromFormat +#else +# define SWIG_Python_str_FromFormat PyString_FromFormat +#endif + + +/* Warning: This function will allocate a new string in Python 3, + * so please call SWIG_Python_str_DelForPy3(x) to free the space. + */ +SWIGINTERN char* +SWIG_Python_str_AsChar(PyObject *str) +{ +#if PY_VERSION_HEX >= 0x03000000 + char *newstr = 0; + str = PyUnicode_AsUTF8String(str); + if (str) { + char *cstr; + Py_ssize_t len; + PyBytes_AsStringAndSize(str, &cstr, &len); + newstr = (char *) malloc(len+1); + memcpy(newstr, cstr, len+1); + Py_XDECREF(str); + } + return newstr; +#else + return PyString_AsString(str); +#endif +} + +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_Python_str_DelForPy3(x) free( (void*) (x) ) +#else +# define SWIG_Python_str_DelForPy3(x) +#endif + + +SWIGINTERN PyObject* +SWIG_Python_str_FromChar(const char *c) +{ +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_FromString(c); +#else + return PyString_FromString(c); +#endif +} + +#ifndef PyObject_DEL +# define PyObject_DEL PyObject_Del +#endif + +// SWIGPY_USE_CAPSULE is no longer used within SWIG itself, but some user +// interface files check for it. +# define SWIGPY_USE_CAPSULE +# define SWIGPY_CAPSULE_NAME ("swig_runtime_data" SWIG_RUNTIME_VERSION ".type_pointer_capsule" SWIG_TYPE_TABLE_NAME) + +#if PY_VERSION_HEX < 0x03020000 +#define PyDescr_TYPE(x) (((PyDescrObject *)(x))->d_type) +#define PyDescr_NAME(x) (((PyDescrObject *)(x))->d_name) +#define Py_hash_t long +#endif + +/* ----------------------------------------------------------------------------- + * error manipulation + * ----------------------------------------------------------------------------- */ + +SWIGRUNTIME PyObject* +SWIG_Python_ErrorType(int code) { + PyObject* type = 0; + switch(code) { + case SWIG_MemoryError: + type = PyExc_MemoryError; + break; + case SWIG_IOError: + type = PyExc_IOError; + break; + case SWIG_RuntimeError: + type = PyExc_RuntimeError; + break; + case SWIG_IndexError: + type = PyExc_IndexError; + break; + case SWIG_TypeError: + type = PyExc_TypeError; + break; + case SWIG_DivisionByZero: + type = PyExc_ZeroDivisionError; + break; + case SWIG_OverflowError: + type = PyExc_OverflowError; + break; + case SWIG_SyntaxError: + type = PyExc_SyntaxError; + break; + case SWIG_ValueError: + type = PyExc_ValueError; + break; + case SWIG_SystemError: + type = PyExc_SystemError; + break; + case SWIG_AttributeError: + type = PyExc_AttributeError; + break; + default: + type = PyExc_RuntimeError; + } + return type; +} + + +SWIGRUNTIME void +SWIG_Python_AddErrorMsg(const char* mesg) +{ + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + + if (PyErr_Occurred()) + PyErr_Fetch(&type, &value, &traceback); + if (value) { + PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); + PyErr_Clear(); + Py_XINCREF(type); + if (tmp) + PyErr_Format(type, "%s %s", tmp, mesg); + else + PyErr_Format(type, "%s", mesg); + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + Py_DECREF(value); + } else { + PyErr_SetString(PyExc_RuntimeError, mesg); + } +} + +SWIGRUNTIME int +SWIG_Python_TypeErrorOccurred(PyObject *obj) +{ + PyObject *error; + if (obj) + return 0; + error = PyErr_Occurred(); + return error && PyErr_GivenExceptionMatches(error, PyExc_TypeError); +} + +SWIGRUNTIME void +SWIG_Python_RaiseOrModifyTypeError(const char *message) +{ + if (SWIG_Python_TypeErrorOccurred(NULL)) { + /* Use existing TypeError to preserve stacktrace and enhance with given message */ + PyObject *newvalue; + PyObject *type = NULL, *value = NULL, *traceback = NULL; + PyErr_Fetch(&type, &value, &traceback); +#if PY_VERSION_HEX >= 0x03000000 + newvalue = PyUnicode_FromFormat("%S\nAdditional information:\n%s", value, message); +#else + newvalue = PyString_FromFormat("%s\nAdditional information:\n%s", PyString_AsString(value), message); +#endif + Py_XDECREF(value); + PyErr_Restore(type, newvalue, traceback); + } else { + /* Raise TypeError using given message */ + PyErr_SetString(PyExc_TypeError, message); + } +} + +#if defined(SWIG_PYTHON_NO_THREADS) +# if defined(SWIG_PYTHON_THREADS) +# undef SWIG_PYTHON_THREADS +# endif +#endif +#if defined(SWIG_PYTHON_THREADS) /* Threading support is enabled */ +# if !defined(SWIG_PYTHON_USE_GIL) && !defined(SWIG_PYTHON_NO_USE_GIL) +# define SWIG_PYTHON_USE_GIL +# endif +# if defined(SWIG_PYTHON_USE_GIL) /* Use PyGILState threads calls */ +# ifndef SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_INITIALIZE_THREADS PyEval_InitThreads() +# endif +# ifdef __cplusplus /* C++ code */ + class SWIG_Python_Thread_Block { + bool status; + PyGILState_STATE state; + public: + void end() { if (status) { PyGILState_Release(state); status = false;} } + SWIG_Python_Thread_Block() : status(true), state(PyGILState_Ensure()) {} + ~SWIG_Python_Thread_Block() { end(); } + }; + class SWIG_Python_Thread_Allow { + bool status; + PyThreadState *save; + public: + void end() { if (status) { PyEval_RestoreThread(save); status = false; }} + SWIG_Python_Thread_Allow() : status(true), save(PyEval_SaveThread()) {} + ~SWIG_Python_Thread_Allow() { end(); } + }; +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK SWIG_Python_Thread_Block _swig_thread_block +# define SWIG_PYTHON_THREAD_END_BLOCK _swig_thread_block.end() +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW SWIG_Python_Thread_Allow _swig_thread_allow +# define SWIG_PYTHON_THREAD_END_ALLOW _swig_thread_allow.end() +# else /* C code */ +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK PyGILState_STATE _swig_thread_block = PyGILState_Ensure() +# define SWIG_PYTHON_THREAD_END_BLOCK PyGILState_Release(_swig_thread_block) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW PyThreadState *_swig_thread_allow = PyEval_SaveThread() +# define SWIG_PYTHON_THREAD_END_ALLOW PyEval_RestoreThread(_swig_thread_allow) +# endif +# else /* Old thread way, not implemented, user must provide it */ +# if !defined(SWIG_PYTHON_INITIALIZE_THREADS) +# define SWIG_PYTHON_INITIALIZE_THREADS +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_BLOCK) +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_END_BLOCK) +# define SWIG_PYTHON_THREAD_END_BLOCK +# endif +# if !defined(SWIG_PYTHON_THREAD_BEGIN_ALLOW) +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# endif +# if !defined(SWIG_PYTHON_THREAD_END_ALLOW) +# define SWIG_PYTHON_THREAD_END_ALLOW +# endif +# endif +#else /* No thread support */ +# define SWIG_PYTHON_INITIALIZE_THREADS +# define SWIG_PYTHON_THREAD_BEGIN_BLOCK +# define SWIG_PYTHON_THREAD_END_BLOCK +# define SWIG_PYTHON_THREAD_BEGIN_ALLOW +# define SWIG_PYTHON_THREAD_END_ALLOW +#endif + +/* ----------------------------------------------------------------------------- + * Python API portion that goes into the runtime + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#endif + +/* ----------------------------------------------------------------------------- + * Constant declarations + * ----------------------------------------------------------------------------- */ + +/* Constant Types */ +#define SWIG_PY_POINTER 4 +#define SWIG_PY_BINARY 5 + +/* Constant information structure */ +typedef struct swig_const_info { + int type; + const char *name; + long lvalue; + double dvalue; + void *pvalue; + swig_type_info **ptype; +} swig_const_info; + +#ifdef __cplusplus +} +#endif + + +/* ----------------------------------------------------------------------------- + * pyrun.swg + * + * This file contains the runtime support for Python modules + * and includes code for managing global variables and pointer + * type checking. + * + * ----------------------------------------------------------------------------- */ + +#if PY_VERSION_HEX < 0x02070000 /* 2.7.0 */ +# error "This version of SWIG only supports Python >= 2.7" +#endif + +#if PY_VERSION_HEX >= 0x03000000 && PY_VERSION_HEX < 0x03020000 +# error "This version of SWIG only supports Python 3 >= 3.2" +#endif + +/* Common SWIG API */ + +/* for raw pointers */ +#define SWIG_Python_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, 0) +#define SWIG_ConvertPtr(obj, pptr, type, flags) SWIG_Python_ConvertPtr(obj, pptr, type, flags) +#define SWIG_ConvertPtrAndOwn(obj,pptr,type,flags,own) SWIG_Python_ConvertPtrAndOwn(obj, pptr, type, flags, own) + +#ifdef SWIGPYTHON_BUILTIN +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(self, ptr, type, flags) +#else +#define SWIG_NewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) +#endif + +#define SWIG_InternalNewPointerObj(ptr, type, flags) SWIG_Python_NewPointerObj(NULL, ptr, type, flags) + +#define SWIG_CheckImplicit(ty) SWIG_Python_CheckImplicit(ty) +#define SWIG_AcquirePtr(ptr, src) SWIG_Python_AcquirePtr(ptr, src) +#define swig_owntype int + +/* for raw packed data */ +#define SWIG_ConvertPacked(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewPackedObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + +/* for class or struct pointers */ +#define SWIG_ConvertInstance(obj, pptr, type, flags) SWIG_ConvertPtr(obj, pptr, type, flags) +#define SWIG_NewInstanceObj(ptr, type, flags) SWIG_NewPointerObj(ptr, type, flags) + +/* for C or C++ function pointers */ +#define SWIG_ConvertFunctionPtr(obj, pptr, type) SWIG_Python_ConvertFunctionPtr(obj, pptr, type) +#define SWIG_NewFunctionPtrObj(ptr, type) SWIG_Python_NewPointerObj(NULL, ptr, type, 0) + +/* for C++ member pointers, ie, member methods */ +#define SWIG_ConvertMember(obj, ptr, sz, ty) SWIG_Python_ConvertPacked(obj, ptr, sz, ty) +#define SWIG_NewMemberObj(ptr, sz, type) SWIG_Python_NewPackedObj(ptr, sz, type) + + +/* Runtime API */ + +#define SWIG_GetModule(clientdata) SWIG_Python_GetModule(clientdata) +#define SWIG_SetModule(clientdata, pointer) SWIG_Python_SetModule(pointer) +#define SWIG_NewClientData(obj) SwigPyClientData_New(obj) + +#define SWIG_SetErrorObj SWIG_Python_SetErrorObj +#define SWIG_SetErrorMsg SWIG_Python_SetErrorMsg +#define SWIG_ErrorType(code) SWIG_Python_ErrorType(code) +#define SWIG_Error(code, msg) SWIG_Python_SetErrorMsg(SWIG_ErrorType(code), msg) +#define SWIG_fail goto fail + + +/* Runtime API implementation */ + +/* Error manipulation */ + +SWIGINTERN void +SWIG_Python_SetErrorObj(PyObject *errtype, PyObject *obj) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetObject(errtype, obj); + Py_DECREF(obj); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +SWIGINTERN void +SWIG_Python_SetErrorMsg(PyObject *errtype, const char *msg) { + SWIG_PYTHON_THREAD_BEGIN_BLOCK; + PyErr_SetString(errtype, msg); + SWIG_PYTHON_THREAD_END_BLOCK; +} + +#define SWIG_Python_Raise(obj, type, desc) SWIG_Python_SetErrorObj(SWIG_Python_ExceptionType(desc), obj) + +/* Set a constant value */ + +#if defined(SWIGPYTHON_BUILTIN) + +SWIGINTERN void +SwigPyBuiltin_AddPublicSymbol(PyObject *seq, const char *key) { + PyObject *s = PyString_InternFromString(key); + PyList_Append(seq, s); + Py_DECREF(s); +} + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, PyObject *public_interface, const char *name, PyObject *obj) { + PyDict_SetItemString(d, name, obj); + Py_DECREF(obj); + if (public_interface) + SwigPyBuiltin_AddPublicSymbol(public_interface, name); +} + +#else + +SWIGINTERN void +SWIG_Python_SetConstant(PyObject *d, const char *name, PyObject *obj) { + PyDict_SetItemString(d, name, obj); + Py_DECREF(obj); +} + +#endif + +/* Append a value to the result obj */ + +SWIGINTERN PyObject* +SWIG_Python_AppendOutput(PyObject* result, PyObject* obj) { + if (!result) { + result = obj; + } else if (result == Py_None) { + Py_DECREF(result); + result = obj; + } else { + if (!PyList_Check(result)) { + PyObject *o2 = result; + result = PyList_New(1); + PyList_SetItem(result, 0, o2); + } + PyList_Append(result,obj); + Py_DECREF(obj); + } + return result; +} + +/* Unpack the argument tuple */ + +SWIGINTERN Py_ssize_t +SWIG_Python_UnpackTuple(PyObject *args, const char *name, Py_ssize_t min, Py_ssize_t max, PyObject **objs) +{ + if (!args) { + if (!min && !max) { + return 1; + } else { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got none", + name, (min == max ? "" : "at least "), (int)min); + return 0; + } + } + if (!PyTuple_Check(args)) { + if (min <= 1 && max >= 1) { + Py_ssize_t i; + objs[0] = args; + for (i = 1; i < max; ++i) { + objs[i] = 0; + } + return 2; + } + PyErr_SetString(PyExc_SystemError, "UnpackTuple() argument list is not a tuple"); + return 0; + } else { + Py_ssize_t l = PyTuple_GET_SIZE(args); + if (l < min) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at least "), (int)min, (int)l); + return 0; + } else if (l > max) { + PyErr_Format(PyExc_TypeError, "%s expected %s%d arguments, got %d", + name, (min == max ? "" : "at most "), (int)max, (int)l); + return 0; + } else { + Py_ssize_t i; + for (i = 0; i < l; ++i) { + objs[i] = PyTuple_GET_ITEM(args, i); + } + for (; l < max; ++l) { + objs[l] = 0; + } + return i + 1; + } + } +} + +/* A functor is a function object with one single object argument */ +#define SWIG_Python_CallFunctor(functor, obj) PyObject_CallFunctionObjArgs(functor, obj, NULL); + +/* + Helper for static pointer initialization for both C and C++ code, for example + static PyObject *SWIG_STATIC_POINTER(MyVar) = NewSomething(...); +*/ +#ifdef __cplusplus +#define SWIG_STATIC_POINTER(var) var +#else +#define SWIG_STATIC_POINTER(var) var = 0; if (!var) var +#endif + +/* ----------------------------------------------------------------------------- + * Pointer declarations + * ----------------------------------------------------------------------------- */ + +/* Flags for new pointer objects */ +#define SWIG_POINTER_NOSHADOW (SWIG_POINTER_OWN << 1) +#define SWIG_POINTER_NEW (SWIG_POINTER_NOSHADOW | SWIG_POINTER_OWN) + +#define SWIG_POINTER_IMPLICIT_CONV (SWIG_POINTER_DISOWN << 1) + +#define SWIG_BUILTIN_TP_INIT (SWIG_POINTER_OWN << 2) +#define SWIG_BUILTIN_INIT (SWIG_BUILTIN_TP_INIT | SWIG_POINTER_OWN) + +#ifdef __cplusplus +extern "C" { +#endif + +/* The python void return value */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Py_Void(void) +{ + PyObject *none = Py_None; + Py_INCREF(none); + return none; +} + +/* SwigPyClientData */ + +typedef struct { + PyObject *klass; + PyObject *newraw; + PyObject *newargs; + PyObject *destroy; + int delargs; + int implicitconv; + PyTypeObject *pytype; +} SwigPyClientData; + +SWIGRUNTIMEINLINE int +SWIG_Python_CheckImplicit(swig_type_info *ty) +{ + SwigPyClientData *data = (SwigPyClientData *)ty->clientdata; + int fail = data ? data->implicitconv : 0; + if (fail) + PyErr_SetString(PyExc_TypeError, "Implicit conversion is prohibited for explicit constructors."); + return fail; +} + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_ExceptionType(swig_type_info *desc) { + SwigPyClientData *data = desc ? (SwigPyClientData *) desc->clientdata : 0; + PyObject *klass = data ? data->klass : 0; + return (klass ? klass : PyExc_RuntimeError); +} + + +SWIGRUNTIME SwigPyClientData * +SwigPyClientData_New(PyObject* obj) +{ + if (!obj) { + return 0; + } else { + SwigPyClientData *data = (SwigPyClientData *)malloc(sizeof(SwigPyClientData)); + /* the klass element */ + data->klass = obj; + Py_INCREF(data->klass); + /* the newraw method and newargs arguments used to create a new raw instance */ + if (PyClass_Check(obj)) { + data->newraw = 0; + data->newargs = obj; + Py_INCREF(obj); + } else { + data->newraw = PyObject_GetAttrString(data->klass, "__new__"); + if (data->newraw) { + Py_INCREF(data->newraw); + data->newargs = PyTuple_New(1); + PyTuple_SetItem(data->newargs, 0, obj); + } else { + data->newargs = obj; + } + Py_INCREF(data->newargs); + } + /* the destroy method, aka as the C++ delete method */ + data->destroy = PyObject_GetAttrString(data->klass, "__swig_destroy__"); + if (PyErr_Occurred()) { + PyErr_Clear(); + data->destroy = 0; + } + if (data->destroy) { + int flags; + Py_INCREF(data->destroy); + flags = PyCFunction_GET_FLAGS(data->destroy); + data->delargs = !(flags & (METH_O)); + } else { + data->delargs = 0; + } + data->implicitconv = 0; + data->pytype = 0; + return data; + } +} + +SWIGRUNTIME void +SwigPyClientData_Del(SwigPyClientData *data) { + Py_XDECREF(data->newraw); + Py_XDECREF(data->newargs); + Py_XDECREF(data->destroy); +} + +/* =============== SwigPyObject =====================*/ + +typedef struct { + PyObject_HEAD + void *ptr; + swig_type_info *ty; + int own; + PyObject *next; +#ifdef SWIGPYTHON_BUILTIN + PyObject *dict; +#endif +} SwigPyObject; + + +#ifdef SWIGPYTHON_BUILTIN + +SWIGRUNTIME PyObject * +SwigPyObject_get___dict__(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *)v; + + if (!sobj->dict) + sobj->dict = PyDict_New(); + + Py_INCREF(sobj->dict); + return sobj->dict; +} + +#endif + +SWIGRUNTIME PyObject * +SwigPyObject_long(SwigPyObject *v) +{ + return PyLong_FromVoidPtr(v->ptr); +} + +SWIGRUNTIME PyObject * +SwigPyObject_format(const char* fmt, SwigPyObject *v) +{ + PyObject *res = NULL; + PyObject *args = PyTuple_New(1); + if (args) { + if (PyTuple_SetItem(args, 0, SwigPyObject_long(v)) == 0) { + PyObject *ofmt = SWIG_Python_str_FromChar(fmt); + if (ofmt) { +#if PY_VERSION_HEX >= 0x03000000 + res = PyUnicode_Format(ofmt,args); +#else + res = PyString_Format(ofmt,args); +#endif + Py_DECREF(ofmt); + } + Py_DECREF(args); + } + } + return res; +} + +SWIGRUNTIME PyObject * +SwigPyObject_oct(SwigPyObject *v) +{ + return SwigPyObject_format("%o",v); +} + +SWIGRUNTIME PyObject * +SwigPyObject_hex(SwigPyObject *v) +{ + return SwigPyObject_format("%x",v); +} + +SWIGRUNTIME PyObject * +SwigPyObject_repr(SwigPyObject *v) +{ + const char *name = SWIG_TypePrettyName(v->ty); + PyObject *repr = SWIG_Python_str_FromFormat("", (name ? name : "unknown"), (void *)v); + if (v->next) { + PyObject *nrep = SwigPyObject_repr((SwigPyObject *)v->next); +# if PY_VERSION_HEX >= 0x03000000 + PyObject *joined = PyUnicode_Concat(repr, nrep); + Py_DecRef(repr); + Py_DecRef(nrep); + repr = joined; +# else + PyString_ConcatAndDel(&repr,nrep); +# endif + } + return repr; +} + +/* We need a version taking two PyObject* parameters so it's a valid + * PyCFunction to use in swigobject_methods[]. */ +SWIGRUNTIME PyObject * +SwigPyObject_repr2(PyObject *v, PyObject *SWIGUNUSEDPARM(args)) +{ + return SwigPyObject_repr((SwigPyObject*)v); +} + +SWIGRUNTIME int +SwigPyObject_compare(SwigPyObject *v, SwigPyObject *w) +{ + void *i = v->ptr; + void *j = w->ptr; + return (i < j) ? -1 : ((i > j) ? 1 : 0); +} + +/* Added for Python 3.x, would it also be useful for Python 2.x? */ +SWIGRUNTIME PyObject* +SwigPyObject_richcompare(SwigPyObject *v, SwigPyObject *w, int op) +{ + PyObject* res; + if( op != Py_EQ && op != Py_NE ) { + Py_INCREF(Py_NotImplemented); + return Py_NotImplemented; + } + res = PyBool_FromLong( (SwigPyObject_compare(v, w)==0) == (op == Py_EQ) ? 1 : 0); + return res; +} + + +SWIGRUNTIME PyTypeObject* SwigPyObject_TypeOnce(void); + +#ifdef SWIGPYTHON_BUILTIN +static swig_type_info *SwigPyObject_stype = 0; +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + SwigPyClientData *cd; + assert(SwigPyObject_stype); + cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; + assert(cd); + assert(cd->pytype); + return cd->pytype; +} +#else +SWIGRUNTIME PyTypeObject* +SwigPyObject_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyObject_TypeOnce(); + return type; +} +#endif + +SWIGRUNTIMEINLINE int +SwigPyObject_Check(PyObject *op) { +#ifdef SWIGPYTHON_BUILTIN + PyTypeObject *target_tp = SwigPyObject_type(); + if (PyType_IsSubtype(op->ob_type, target_tp)) + return 1; + return (strcmp(op->ob_type->tp_name, "SwigPyObject") == 0); +#else + return (Py_TYPE(op) == SwigPyObject_type()) + || (strcmp(Py_TYPE(op)->tp_name,"SwigPyObject") == 0); +#endif +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own); + +SWIGRUNTIME void +SwigPyObject_dealloc(PyObject *v) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + PyObject *next = sobj->next; + if (sobj->own == SWIG_POINTER_OWN) { + swig_type_info *ty = sobj->ty; + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + PyObject *destroy = data ? data->destroy : 0; + if (destroy) { + /* destroy is always a VARARGS method */ + PyObject *res; + + /* PyObject_CallFunction() has the potential to silently drop + the active exception. In cases of unnamed temporary + variable or where we just finished iterating over a generator + StopIteration will be active right now, and this needs to + remain true upon return from SwigPyObject_dealloc. So save + and restore. */ + + PyObject *type = NULL, *value = NULL, *traceback = NULL; + PyErr_Fetch(&type, &value, &traceback); + + if (data->delargs) { + /* we need to create a temporary object to carry the destroy operation */ + PyObject *tmp = SwigPyObject_New(sobj->ptr, ty, 0); + res = SWIG_Python_CallFunctor(destroy, tmp); + Py_DECREF(tmp); + } else { + PyCFunction meth = PyCFunction_GET_FUNCTION(destroy); + PyObject *mself = PyCFunction_GET_SELF(destroy); + res = ((*meth)(mself, v)); + } + if (!res) + PyErr_WriteUnraisable(destroy); + + PyErr_Restore(type, value, traceback); + + Py_XDECREF(res); + } +#if !defined(SWIG_PYTHON_SILENT_MEMLEAK) + else { + const char *name = SWIG_TypePrettyName(ty); + printf("swig/python detected a memory leak of type '%s', no destructor found.\n", (name ? name : "unknown")); + } +#endif + } + Py_XDECREF(next); + PyObject_DEL(v); +} + +SWIGRUNTIME PyObject* +SwigPyObject_append(PyObject* v, PyObject* next) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + if (!SwigPyObject_Check(next)) { + PyErr_SetString(PyExc_TypeError, "Attempt to append a non SwigPyObject"); + return NULL; + } + sobj->next = next; + Py_INCREF(next); + return SWIG_Py_Void(); +} + +SWIGRUNTIME PyObject* +SwigPyObject_next(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *) v; + if (sobj->next) { + Py_INCREF(sobj->next); + return sobj->next; + } else { + return SWIG_Py_Void(); + } +} + +SWIGINTERN PyObject* +SwigPyObject_disown(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = 0; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +SwigPyObject_acquire(PyObject* v, PyObject *SWIGUNUSEDPARM(args)) +{ + SwigPyObject *sobj = (SwigPyObject *)v; + sobj->own = SWIG_POINTER_OWN; + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject* +SwigPyObject_own(PyObject *v, PyObject *args) +{ + PyObject *val = 0; + if (!PyArg_UnpackTuple(args, "own", 0, 1, &val)) { + return NULL; + } else { + SwigPyObject *sobj = (SwigPyObject *)v; + PyObject *obj = PyBool_FromLong(sobj->own); + if (val) { + if (PyObject_IsTrue(val)) { + SwigPyObject_acquire(v,args); + } else { + SwigPyObject_disown(v,args); + } + } + return obj; + } +} + +static PyMethodDef +swigobject_methods[] = { + {"disown", SwigPyObject_disown, METH_NOARGS, "releases ownership of the pointer"}, + {"acquire", SwigPyObject_acquire, METH_NOARGS, "acquires ownership of the pointer"}, + {"own", SwigPyObject_own, METH_VARARGS, "returns/sets ownership of the pointer"}, + {"append", SwigPyObject_append, METH_O, "appends another 'this' object"}, + {"next", SwigPyObject_next, METH_NOARGS, "returns the next 'this' object"}, + {"__repr__",SwigPyObject_repr2, METH_NOARGS, "returns object representation"}, + {0, 0, 0, 0} +}; + +SWIGRUNTIME PyTypeObject* +SwigPyObject_TypeOnce(void) { + static char swigobject_doc[] = "Swig object carries a C/C++ instance pointer"; + + static PyNumberMethods SwigPyObject_as_number = { + (binaryfunc)0, /*nb_add*/ + (binaryfunc)0, /*nb_subtract*/ + (binaryfunc)0, /*nb_multiply*/ + /* nb_divide removed in Python 3 */ +#if PY_VERSION_HEX < 0x03000000 + (binaryfunc)0, /*nb_divide*/ +#endif + (binaryfunc)0, /*nb_remainder*/ + (binaryfunc)0, /*nb_divmod*/ + (ternaryfunc)0,/*nb_power*/ + (unaryfunc)0, /*nb_negative*/ + (unaryfunc)0, /*nb_positive*/ + (unaryfunc)0, /*nb_absolute*/ + (inquiry)0, /*nb_nonzero*/ + 0, /*nb_invert*/ + 0, /*nb_lshift*/ + 0, /*nb_rshift*/ + 0, /*nb_and*/ + 0, /*nb_xor*/ + 0, /*nb_or*/ +#if PY_VERSION_HEX < 0x03000000 + 0, /*nb_coerce*/ +#endif + (unaryfunc)SwigPyObject_long, /*nb_int*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_long, /*nb_long*/ +#else + 0, /*nb_reserved*/ +#endif + (unaryfunc)0, /*nb_float*/ +#if PY_VERSION_HEX < 0x03000000 + (unaryfunc)SwigPyObject_oct, /*nb_oct*/ + (unaryfunc)SwigPyObject_hex, /*nb_hex*/ +#endif +#if PY_VERSION_HEX >= 0x03050000 /* 3.5 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_inplace_matrix_multiply */ +#elif PY_VERSION_HEX >= 0x03000000 /* 3.0 */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index, nb_inplace_divide removed */ +#else + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 /* nb_inplace_add -> nb_index */ +#endif + }; + + static PyTypeObject swigpyobject_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + "SwigPyObject", /* tp_name */ + sizeof(SwigPyObject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyObject_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX >= 0x03000000 + 0, /* tp_reserved in 3.0.1, tp_compare in 3.0.0 but not used */ +#else + (cmpfunc)SwigPyObject_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyObject_repr, /* tp_repr */ + &SwigPyObject_as_number, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigobject_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + (richcmpfunc)SwigPyObject_richcompare,/* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + swigobject_methods, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ + 0, /* tp_prev */ + 0 /* tp_next */ +#endif + }; + swigpyobject_type = tmp; + type_init = 1; + if (PyType_Ready(&swigpyobject_type) < 0) + return NULL; + } + return &swigpyobject_type; +} + +SWIGRUNTIME PyObject * +SwigPyObject_New(void *ptr, swig_type_info *ty, int own) +{ + SwigPyObject *sobj = PyObject_NEW(SwigPyObject, SwigPyObject_type()); + if (sobj) { + sobj->ptr = ptr; + sobj->ty = ty; + sobj->own = own; + sobj->next = 0; + } + return (PyObject *)sobj; +} + +/* ----------------------------------------------------------------------------- + * Implements a simple Swig Packed type, and use it instead of string + * ----------------------------------------------------------------------------- */ + +typedef struct { + PyObject_HEAD + void *pack; + swig_type_info *ty; + size_t size; +} SwigPyPacked; + +SWIGRUNTIME PyObject * +SwigPyPacked_repr(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))) { + return SWIG_Python_str_FromFormat("", result, v->ty->name); + } else { + return SWIG_Python_str_FromFormat("", v->ty->name); + } +} + +SWIGRUNTIME PyObject * +SwigPyPacked_str(SwigPyPacked *v) +{ + char result[SWIG_BUFFER_SIZE]; + if (SWIG_PackDataName(result, v->pack, v->size, 0, sizeof(result))){ + return SWIG_Python_str_FromFormat("%s%s", result, v->ty->name); + } else { + return SWIG_Python_str_FromChar(v->ty->name); + } +} + +SWIGRUNTIME int +SwigPyPacked_compare(SwigPyPacked *v, SwigPyPacked *w) +{ + size_t i = v->size; + size_t j = w->size; + int s = (i < j) ? -1 : ((i > j) ? 1 : 0); + return s ? s : strncmp((const char *)v->pack, (const char *)w->pack, 2*v->size); +} + +SWIGRUNTIME PyTypeObject* SwigPyPacked_TypeOnce(void); + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_type(void) { + static PyTypeObject *SWIG_STATIC_POINTER(type) = SwigPyPacked_TypeOnce(); + return type; +} + +SWIGRUNTIMEINLINE int +SwigPyPacked_Check(PyObject *op) { + return ((op)->ob_type == SwigPyPacked_TypeOnce()) + || (strcmp((op)->ob_type->tp_name,"SwigPyPacked") == 0); +} + +SWIGRUNTIME void +SwigPyPacked_dealloc(PyObject *v) +{ + if (SwigPyPacked_Check(v)) { + SwigPyPacked *sobj = (SwigPyPacked *) v; + free(sobj->pack); + } + PyObject_DEL(v); +} + +SWIGRUNTIME PyTypeObject* +SwigPyPacked_TypeOnce(void) { + static char swigpacked_doc[] = "Swig object carries a C/C++ instance pointer"; + static PyTypeObject swigpypacked_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX>=0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + "SwigPyPacked", /* tp_name */ + sizeof(SwigPyPacked), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)SwigPyPacked_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc)0, /* tp_getattr */ + (setattrfunc)0, /* tp_setattr */ +#if PY_VERSION_HEX>=0x03000000 + 0, /* tp_reserved in 3.0.1 */ +#else + (cmpfunc)SwigPyPacked_compare, /* tp_compare */ +#endif + (reprfunc)SwigPyPacked_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + (hashfunc)0, /* tp_hash */ + (ternaryfunc)0, /* tp_call */ + (reprfunc)SwigPyPacked_str, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + swigpacked_doc, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + 0, /* tp_alloc */ + 0, /* tp_new */ + 0, /* tp_free */ + 0, /* tp_is_gc */ + 0, /* tp_bases */ + 0, /* tp_mro */ + 0, /* tp_cache */ + 0, /* tp_subclasses */ + 0, /* tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ + 0, /* tp_prev */ + 0 /* tp_next */ +#endif + }; + swigpypacked_type = tmp; + type_init = 1; + if (PyType_Ready(&swigpypacked_type) < 0) + return NULL; + } + return &swigpypacked_type; +} + +SWIGRUNTIME PyObject * +SwigPyPacked_New(void *ptr, size_t size, swig_type_info *ty) +{ + SwigPyPacked *sobj = PyObject_NEW(SwigPyPacked, SwigPyPacked_type()); + if (sobj) { + void *pack = malloc(size); + if (pack) { + memcpy(pack, ptr, size); + sobj->pack = pack; + sobj->ty = ty; + sobj->size = size; + } else { + PyObject_DEL((PyObject *) sobj); + sobj = 0; + } + } + return (PyObject *) sobj; +} + +SWIGRUNTIME swig_type_info * +SwigPyPacked_UnpackData(PyObject *obj, void *ptr, size_t size) +{ + if (SwigPyPacked_Check(obj)) { + SwigPyPacked *sobj = (SwigPyPacked *)obj; + if (sobj->size != size) return 0; + memcpy(ptr, sobj->pack, size); + return sobj->ty; + } else { + return 0; + } +} + +/* ----------------------------------------------------------------------------- + * pointers/data manipulation + * ----------------------------------------------------------------------------- */ + +static PyObject *Swig_This_global = NULL; + +SWIGRUNTIME PyObject * +SWIG_This(void) +{ + if (Swig_This_global == NULL) + Swig_This_global = SWIG_Python_str_FromChar("this"); + return Swig_This_global; +} + +/* #define SWIG_PYTHON_SLOW_GETSET_THIS */ + +/* TODO: I don't know how to implement the fast getset in Python 3 right now */ +#if PY_VERSION_HEX>=0x03000000 +#define SWIG_PYTHON_SLOW_GETSET_THIS +#endif + +SWIGRUNTIME SwigPyObject * +SWIG_Python_GetSwigThis(PyObject *pyobj) +{ + PyObject *obj; + + if (SwigPyObject_Check(pyobj)) + return (SwigPyObject *) pyobj; + +#ifdef SWIGPYTHON_BUILTIN + (void)obj; +# ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + pyobj = PyWeakref_GET_OBJECT(pyobj); + if (pyobj && SwigPyObject_Check(pyobj)) + return (SwigPyObject*) pyobj; + } +# endif + return NULL; +#else + + obj = 0; + +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + if (PyInstance_Check(pyobj)) { + obj = _PyInstance_Lookup(pyobj, SWIG_This()); + } else { + PyObject **dictptr = _PyObject_GetDictPtr(pyobj); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + obj = dict ? PyDict_GetItem(dict, SWIG_This()) : 0; + } else { +#ifdef PyWeakref_CheckProxy + if (PyWeakref_CheckProxy(pyobj)) { + PyObject *wobj = PyWeakref_GET_OBJECT(pyobj); + return wobj ? SWIG_Python_GetSwigThis(wobj) : 0; + } +#endif + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } + } + } +#else + obj = PyObject_GetAttr(pyobj,SWIG_This()); + if (obj) { + Py_DECREF(obj); + } else { + if (PyErr_Occurred()) PyErr_Clear(); + return 0; + } +#endif + if (obj && !SwigPyObject_Check(obj)) { + /* a PyObject is called 'this', try to get the 'real this' + SwigPyObject from it */ + return SWIG_Python_GetSwigThis(obj); + } + return (SwigPyObject *)obj; +#endif +} + +/* Acquire a pointer value */ + +SWIGRUNTIME int +SWIG_Python_AcquirePtr(PyObject *obj, int own) { + if (own == SWIG_POINTER_OWN) { + SwigPyObject *sobj = SWIG_Python_GetSwigThis(obj); + if (sobj) { + int oldown = sobj->own; + sobj->own = own; + return oldown; + } + } + return 0; +} + +/* Convert a pointer value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPtrAndOwn(PyObject *obj, void **ptr, swig_type_info *ty, int flags, int *own) { + int res; + SwigPyObject *sobj; + int implicit_conv = (flags & SWIG_POINTER_IMPLICIT_CONV) != 0; + + if (!obj) + return SWIG_ERROR; + if (obj == Py_None && !implicit_conv) { + if (ptr) + *ptr = 0; + return (flags & SWIG_POINTER_NO_NULL) ? SWIG_NullReferenceError : SWIG_OK; + } + + res = SWIG_ERROR; + + sobj = SWIG_Python_GetSwigThis(obj); + if (own) + *own = 0; + while (sobj) { + void *vptr = sobj->ptr; + if (ty) { + swig_type_info *to = sobj->ty; + if (to == ty) { + /* no type cast needed */ + if (ptr) *ptr = vptr; + break; + } else { + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) { + sobj = (SwigPyObject *)sobj->next; + } else { + if (ptr) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + if (newmemory == SWIG_CAST_NEW_MEMORY) { + assert(own); /* badly formed typemap which will lead to a memory leak - it must set and use own to delete *ptr */ + if (own) + *own = *own | SWIG_CAST_NEW_MEMORY; + } + } + break; + } + } + } else { + if (ptr) *ptr = vptr; + break; + } + } + if (sobj) { + if (own) + *own = *own | sobj->own; + if (flags & SWIG_POINTER_DISOWN) { + sobj->own = 0; + } + res = SWIG_OK; + } else { + if (implicit_conv) { + SwigPyClientData *data = ty ? (SwigPyClientData *) ty->clientdata : 0; + if (data && !data->implicitconv) { + PyObject *klass = data->klass; + if (klass) { + PyObject *impconv; + data->implicitconv = 1; /* avoid recursion and call 'explicit' constructors*/ + impconv = SWIG_Python_CallFunctor(klass, obj); + data->implicitconv = 0; + if (PyErr_Occurred()) { + PyErr_Clear(); + impconv = 0; + } + if (impconv) { + SwigPyObject *iobj = SWIG_Python_GetSwigThis(impconv); + if (iobj) { + void *vptr; + res = SWIG_Python_ConvertPtrAndOwn((PyObject*)iobj, &vptr, ty, 0, 0); + if (SWIG_IsOK(res)) { + if (ptr) { + *ptr = vptr; + /* transfer the ownership to 'ptr' */ + iobj->own = 0; + res = SWIG_AddCast(res); + res = SWIG_AddNewMask(res); + } else { + res = SWIG_AddCast(res); + } + } + } + Py_DECREF(impconv); + } + } + } + if (!SWIG_IsOK(res) && obj == Py_None) { + if (ptr) + *ptr = 0; + if (PyErr_Occurred()) + PyErr_Clear(); + res = SWIG_OK; + } + } + } + return res; +} + +/* Convert a function ptr value */ + +SWIGRUNTIME int +SWIG_Python_ConvertFunctionPtr(PyObject *obj, void **ptr, swig_type_info *ty) { + if (!PyCFunction_Check(obj)) { + return SWIG_ConvertPtr(obj, ptr, ty, 0); + } else { + void *vptr = 0; + swig_cast_info *tc; + + /* here we get the method pointer for callbacks */ + const char *doc = (((PyCFunctionObject *)obj) -> m_ml -> ml_doc); + const char *desc = doc ? strstr(doc, "swig_ptr: ") : 0; + if (desc) + desc = ty ? SWIG_UnpackVoidPtr(desc + 10, &vptr, ty->name) : 0; + if (!desc) + return SWIG_ERROR; + tc = SWIG_TypeCheck(desc,ty); + if (tc) { + int newmemory = 0; + *ptr = SWIG_TypeCast(tc,vptr,&newmemory); + assert(!newmemory); /* newmemory handling not yet implemented */ + } else { + return SWIG_ERROR; + } + return SWIG_OK; + } +} + +/* Convert a packed pointer value */ + +SWIGRUNTIME int +SWIG_Python_ConvertPacked(PyObject *obj, void *ptr, size_t sz, swig_type_info *ty) { + swig_type_info *to = SwigPyPacked_UnpackData(obj, ptr, sz); + if (!to) return SWIG_ERROR; + if (ty) { + if (to != ty) { + /* check type cast? */ + swig_cast_info *tc = SWIG_TypeCheck(to->name,ty); + if (!tc) return SWIG_ERROR; + } + } + return SWIG_OK; +} + +/* ----------------------------------------------------------------------------- + * Create a new pointer object + * ----------------------------------------------------------------------------- */ + +/* + Create a new instance object, without calling __init__, and set the + 'this' attribute. +*/ + +SWIGRUNTIME PyObject* +SWIG_Python_NewShadowInstance(SwigPyClientData *data, PyObject *swig_this) +{ + PyObject *inst = 0; + PyObject *newraw = data->newraw; + if (newraw) { + inst = PyObject_Call(newraw, data->newargs, NULL); + if (inst) { +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + PyObject *dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + PyDict_SetItem(dict, SWIG_This(), swig_this); + } + } +#else + PyObject *key = SWIG_This(); + PyObject_SetAttr(inst, key, swig_this); +#endif + } + } else { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *empty_args = PyTuple_New(0); + if (empty_args) { + PyObject *empty_kwargs = PyDict_New(); + if (empty_kwargs) { + inst = ((PyTypeObject *)data->newargs)->tp_new((PyTypeObject *)data->newargs, empty_args, empty_kwargs); + Py_DECREF(empty_kwargs); + if (inst) { + PyObject_SetAttr(inst, SWIG_This(), swig_this); + Py_TYPE(inst)->tp_flags &= ~Py_TPFLAGS_VALID_VERSION_TAG; + } + } + Py_DECREF(empty_args); + } +#else + PyObject *dict = PyDict_New(); + if (dict) { + PyDict_SetItem(dict, SWIG_This(), swig_this); + inst = PyInstance_NewRaw(data->newargs, dict); + Py_DECREF(dict); + } +#endif + } + return inst; +} + +SWIGRUNTIME void +SWIG_Python_SetSwigThis(PyObject *inst, PyObject *swig_this) +{ + PyObject *dict; +#if !defined(SWIG_PYTHON_SLOW_GETSET_THIS) + PyObject **dictptr = _PyObject_GetDictPtr(inst); + if (dictptr != NULL) { + dict = *dictptr; + if (dict == NULL) { + dict = PyDict_New(); + *dictptr = dict; + } + PyDict_SetItem(dict, SWIG_This(), swig_this); + return; + } +#endif + dict = PyObject_GetAttrString(inst, "__dict__"); + PyDict_SetItem(dict, SWIG_This(), swig_this); + Py_DECREF(dict); +} + + +SWIGINTERN PyObject * +SWIG_Python_InitShadowInstance(PyObject *args) { + PyObject *obj[2]; + if (!SWIG_Python_UnpackTuple(args, "swiginit", 2, 2, obj)) { + return NULL; + } else { + SwigPyObject *sthis = SWIG_Python_GetSwigThis(obj[0]); + if (sthis) { + SwigPyObject_append((PyObject*) sthis, obj[1]); + } else { + SWIG_Python_SetSwigThis(obj[0], obj[1]); + } + return SWIG_Py_Void(); + } +} + +/* Create a new pointer object */ + +SWIGRUNTIME PyObject * +SWIG_Python_NewPointerObj(PyObject *self, void *ptr, swig_type_info *type, int flags) { + SwigPyClientData *clientdata; + PyObject * robj; + int own; + + if (!ptr) + return SWIG_Py_Void(); + + clientdata = type ? (SwigPyClientData *)(type->clientdata) : 0; + own = (flags & SWIG_POINTER_OWN) ? SWIG_POINTER_OWN : 0; + if (clientdata && clientdata->pytype) { + SwigPyObject *newobj; + if (flags & SWIG_BUILTIN_TP_INIT) { + newobj = (SwigPyObject*) self; + if (newobj->ptr) { + PyObject *next_self = clientdata->pytype->tp_alloc(clientdata->pytype, 0); + while (newobj->next) + newobj = (SwigPyObject *) newobj->next; + newobj->next = next_self; + newobj = (SwigPyObject *)next_self; +#ifdef SWIGPYTHON_BUILTIN + newobj->dict = 0; +#endif + } + } else { + newobj = PyObject_New(SwigPyObject, clientdata->pytype); +#ifdef SWIGPYTHON_BUILTIN + newobj->dict = 0; +#endif + } + if (newobj) { + newobj->ptr = ptr; + newobj->ty = type; + newobj->own = own; + newobj->next = 0; + return (PyObject*) newobj; + } + return SWIG_Py_Void(); + } + + assert(!(flags & SWIG_BUILTIN_TP_INIT)); + + robj = SwigPyObject_New(ptr, type, own); + if (robj && clientdata && !(flags & SWIG_POINTER_NOSHADOW)) { + PyObject *inst = SWIG_Python_NewShadowInstance(clientdata, robj); + Py_DECREF(robj); + robj = inst; + } + return robj; +} + +/* Create a new packed object */ + +SWIGRUNTIMEINLINE PyObject * +SWIG_Python_NewPackedObj(void *ptr, size_t sz, swig_type_info *type) { + return ptr ? SwigPyPacked_New((void *) ptr, sz, type) : SWIG_Py_Void(); +} + +/* -----------------------------------------------------------------------------* + * Get type list + * -----------------------------------------------------------------------------*/ + +#ifdef SWIG_LINK_RUNTIME +void *SWIG_ReturnGlobalTypeList(void *); +#endif + +SWIGRUNTIME swig_module_info * +SWIG_Python_GetModule(void *SWIGUNUSEDPARM(clientdata)) { + static void *type_pointer = (void *)0; + /* first check if module already created */ + if (!type_pointer) { +#ifdef SWIG_LINK_RUNTIME + type_pointer = SWIG_ReturnGlobalTypeList((void *)0); +#else + type_pointer = PyCapsule_Import(SWIGPY_CAPSULE_NAME, 0); + if (PyErr_Occurred()) { + PyErr_Clear(); + type_pointer = (void *)0; + } +#endif + } + return (swig_module_info *) type_pointer; +} + +SWIGRUNTIME void +SWIG_Python_DestroyModule(PyObject *obj) +{ + swig_module_info *swig_module = (swig_module_info *) PyCapsule_GetPointer(obj, SWIGPY_CAPSULE_NAME); + swig_type_info **types = swig_module->types; + size_t i; + for (i =0; i < swig_module->size; ++i) { + swig_type_info *ty = types[i]; + if (ty->owndata) { + SwigPyClientData *data = (SwigPyClientData *) ty->clientdata; + if (data) SwigPyClientData_Del(data); + } + } + Py_DECREF(SWIG_This()); + Swig_This_global = NULL; +} + +SWIGRUNTIME void +SWIG_Python_SetModule(swig_module_info *swig_module) { +#if PY_VERSION_HEX >= 0x03000000 + /* Add a dummy module object into sys.modules */ + PyObject *module = PyImport_AddModule("swig_runtime_data" SWIG_RUNTIME_VERSION); +#else + static PyMethodDef swig_empty_runtime_method_table[] = { {NULL, NULL, 0, NULL} }; /* Sentinel */ + PyObject *module = Py_InitModule("swig_runtime_data" SWIG_RUNTIME_VERSION, swig_empty_runtime_method_table); +#endif + PyObject *pointer = PyCapsule_New((void *) swig_module, SWIGPY_CAPSULE_NAME, SWIG_Python_DestroyModule); + if (pointer && module) { + PyModule_AddObject(module, "type_pointer_capsule" SWIG_TYPE_TABLE_NAME, pointer); + } else { + Py_XDECREF(pointer); + } +} + +/* The python cached type query */ +SWIGRUNTIME PyObject * +SWIG_Python_TypeCache(void) { + static PyObject *SWIG_STATIC_POINTER(cache) = PyDict_New(); + return cache; +} + +SWIGRUNTIME swig_type_info * +SWIG_Python_TypeQuery(const char *type) +{ + PyObject *cache = SWIG_Python_TypeCache(); + PyObject *key = SWIG_Python_str_FromChar(type); + PyObject *obj = PyDict_GetItem(cache, key); + swig_type_info *descriptor; + if (obj) { + descriptor = (swig_type_info *) PyCapsule_GetPointer(obj, NULL); + } else { + swig_module_info *swig_module = SWIG_GetModule(0); + descriptor = SWIG_TypeQueryModule(swig_module, swig_module, type); + if (descriptor) { + obj = PyCapsule_New((void*) descriptor, NULL, NULL); + PyDict_SetItem(cache, key, obj); + Py_DECREF(obj); + } + } + Py_DECREF(key); + return descriptor; +} + +/* + For backward compatibility only +*/ +#define SWIG_POINTER_EXCEPTION 0 +#define SWIG_arg_fail(arg) SWIG_Python_ArgFail(arg) +#define SWIG_MustGetPtr(p, type, argnum, flags) SWIG_Python_MustGetPtr(p, type, argnum, flags) + +SWIGRUNTIME int +SWIG_Python_AddErrMesg(const char* mesg, int infront) +{ + if (PyErr_Occurred()) { + PyObject *type = 0; + PyObject *value = 0; + PyObject *traceback = 0; + PyErr_Fetch(&type, &value, &traceback); + if (value) { + PyObject *old_str = PyObject_Str(value); + const char *tmp = SWIG_Python_str_AsChar(old_str); + const char *errmesg = tmp ? tmp : "Invalid error message"; + Py_XINCREF(type); + PyErr_Clear(); + if (infront) { + PyErr_Format(type, "%s %s", mesg, errmesg); + } else { + PyErr_Format(type, "%s %s", errmesg, mesg); + } + SWIG_Python_str_DelForPy3(tmp); + Py_DECREF(old_str); + } + return 1; + } else { + return 0; + } +} + +SWIGRUNTIME int +SWIG_Python_ArgFail(int argnum) +{ + if (PyErr_Occurred()) { + /* add information about failing argument */ + char mesg[256]; + PyOS_snprintf(mesg, sizeof(mesg), "argument number %d:", argnum); + return SWIG_Python_AddErrMesg(mesg, 1); + } else { + return 0; + } +} + +SWIGRUNTIMEINLINE const char * +SwigPyObject_GetDesc(PyObject *self) +{ + SwigPyObject *v = (SwigPyObject *)self; + swig_type_info *ty = v ? v->ty : 0; + return ty ? ty->str : ""; +} + +SWIGRUNTIME void +SWIG_Python_TypeError(const char *type, PyObject *obj) +{ + if (type) { +#if defined(SWIG_COBJECT_TYPES) + if (obj && SwigPyObject_Check(obj)) { + const char *otype = (const char *) SwigPyObject_GetDesc(obj); + if (otype) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, 'SwigPyObject(%s)' is received", + type, otype); + return; + } + } else +#endif + { + const char *otype = (obj ? obj->ob_type->tp_name : 0); + if (otype) { + PyObject *str = PyObject_Str(obj); + const char *cstr = str ? SWIG_Python_str_AsChar(str) : 0; + if (cstr) { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s(%s)' is received", + type, otype, cstr); + SWIG_Python_str_DelForPy3(cstr); + } else { + PyErr_Format(PyExc_TypeError, "a '%s' is expected, '%s' is received", + type, otype); + } + Py_XDECREF(str); + return; + } + } + PyErr_Format(PyExc_TypeError, "a '%s' is expected", type); + } else { + PyErr_Format(PyExc_TypeError, "unexpected type is received"); + } +} + + +/* Convert a pointer value, signal an exception on a type mismatch */ +SWIGRUNTIME void * +SWIG_Python_MustGetPtr(PyObject *obj, swig_type_info *ty, int SWIGUNUSEDPARM(argnum), int flags) { + void *result; + if (SWIG_Python_ConvertPtr(obj, &result, ty, flags) == -1) { + PyErr_Clear(); +#if SWIG_POINTER_EXCEPTION + if (flags) { + SWIG_Python_TypeError(SWIG_TypePrettyName(ty), obj); + SWIG_Python_ArgFail(argnum); + } +#endif + } + return result; +} + +#ifdef SWIGPYTHON_BUILTIN +SWIGRUNTIME int +SWIG_Python_NonDynamicSetAttr(PyObject *obj, PyObject *name, PyObject *value) { + PyTypeObject *tp = obj->ob_type; + PyObject *descr; + PyObject *encoded_name; + descrsetfunc f; + int res = -1; + +# ifdef Py_USING_UNICODE + if (PyString_Check(name)) { + name = PyUnicode_Decode(PyString_AsString(name), PyString_Size(name), NULL, NULL); + if (!name) + return -1; + } else if (!PyUnicode_Check(name)) +# else + if (!PyString_Check(name)) +# endif + { + PyErr_Format(PyExc_TypeError, "attribute name must be string, not '%.200s'", name->ob_type->tp_name); + return -1; + } else { + Py_INCREF(name); + } + + if (!tp->tp_dict) { + if (PyType_Ready(tp) < 0) + goto done; + } + + descr = _PyType_Lookup(tp, name); + f = NULL; + if (descr != NULL) + f = descr->ob_type->tp_descr_set; + if (!f) { + if (PyString_Check(name)) { + encoded_name = name; + Py_INCREF(name); + } else { + encoded_name = PyUnicode_AsUTF8String(name); + if (!encoded_name) + return -1; + } + PyErr_Format(PyExc_AttributeError, "'%.100s' object has no attribute '%.200s'", tp->tp_name, PyString_AsString(encoded_name)); + Py_DECREF(encoded_name); + } else { + res = f(descr, obj, value); + } + + done: + Py_DECREF(name); + return res; +} +#endif + + +#ifdef __cplusplus +} +#endif + + + +#define SWIG_exception_fail(code, msg) do { SWIG_Error(code, msg); SWIG_fail; } while(0) + +#define SWIG_contract_assert(expr, msg) if (!(expr)) { SWIG_Error(SWIG_RuntimeError, msg); SWIG_fail; } else + + + +#ifdef __cplusplus +extern "C" { +#endif + +/* Method creation and docstring support functions */ + +SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name); +SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func); +SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func); + +#ifdef __cplusplus +} +#endif + + +/* -------- TYPES TABLE (BEGIN) -------- */ + +#define SWIGTYPE_p_char swig_types[0] +#define SWIGTYPE_p_pm3 swig_types[1] +static swig_type_info *swig_types[3]; +static swig_module_info swig_module = {swig_types, 2, 0, 0, 0, 0}; +#define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name) +#define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name) + +/* -------- TYPES TABLE (END) -------- */ + +#ifdef SWIG_TypeQuery +# undef SWIG_TypeQuery +#endif +#define SWIG_TypeQuery SWIG_Python_TypeQuery + +/*----------------------------------------------- + @(target):= _pm3.so + ------------------------------------------------*/ +#if PY_VERSION_HEX >= 0x03000000 +# define SWIG_init PyInit__pm3 + +#else +# define SWIG_init init_pm3 + +#endif +#define SWIG_name "_pm3" + +#define SWIGVERSION 0x040001 +#define SWIG_VERSION SWIGVERSION + + +#define SWIG_as_voidptr(a) (void *)((const void *)(a)) +#define SWIG_as_voidptrptr(a) ((void)SWIG_as_voidptr(*a),(void**)(a)) + + +/* Include the header in the wrapper code */ +#include "pm3.h" +#include "comms.h" + +SWIGINTERN pm3 *new_pm3__SWIG_0(void){ +// printf("SWIG pm3 constructor, get current pm3\n"); + pm3_device * p = pm3_get_current_dev(); + p->script_embedded = 1; + return p; + } + +SWIGINTERN swig_type_info* +SWIG_pchar_descriptor(void) +{ + static int init = 0; + static swig_type_info* info = 0; + if (!init) { + info = SWIG_TypeQuery("_p_char"); + init = 1; + } + return info; +} + + +SWIGINTERN int +SWIG_AsCharPtrAndSize(PyObject *obj, char** cptr, size_t* psize, int *alloc) +{ +#if PY_VERSION_HEX>=0x03000000 +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + if (PyBytes_Check(obj)) +#else + if (PyUnicode_Check(obj)) +#endif +#else + if (PyString_Check(obj)) +#endif + { + char *cstr; Py_ssize_t len; + int ret = SWIG_OK; +#if PY_VERSION_HEX>=0x03000000 +#if !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + if (!alloc && cptr) { + /* We can't allow converting without allocation, since the internal + representation of string in Python 3 is UCS-2/UCS-4 but we require + a UTF-8 representation. + TODO(bhy) More detailed explanation */ + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + if (!obj) + return SWIG_TypeError; + if (alloc) + *alloc = SWIG_NEWOBJ; +#endif + PyBytes_AsStringAndSize(obj, &cstr, &len); +#else + PyString_AsStringAndSize(obj, &cstr, &len); +#endif + if (cptr) { + if (alloc) { + if (*alloc == SWIG_NEWOBJ) { + *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + *alloc = SWIG_NEWOBJ; + } else { + *cptr = cstr; + *alloc = SWIG_OLDOBJ; + } + } else { +#if PY_VERSION_HEX>=0x03000000 +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + *cptr = PyBytes_AsString(obj); +#else + assert(0); /* Should never reach here with Unicode strings in Python 3 */ +#endif +#else + *cptr = SWIG_Python_str_AsChar(obj); + if (!*cptr) + ret = SWIG_TypeError; +#endif + } + } + if (psize) *psize = len + 1; +#if PY_VERSION_HEX>=0x03000000 && !defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + Py_XDECREF(obj); +#endif + return ret; + } else { +#if defined(SWIG_PYTHON_2_UNICODE) +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) +#error "Cannot use both SWIG_PYTHON_2_UNICODE and SWIG_PYTHON_STRICT_BYTE_CHAR at once" +#endif +#if PY_VERSION_HEX<0x03000000 + if (PyUnicode_Check(obj)) { + char *cstr; Py_ssize_t len; + if (!alloc && cptr) { + return SWIG_RuntimeError; + } + obj = PyUnicode_AsUTF8String(obj); + if (!obj) + return SWIG_TypeError; + if (PyString_AsStringAndSize(obj, &cstr, &len) != -1) { + if (cptr) { + if (alloc) *alloc = SWIG_NEWOBJ; + *cptr = (char *)memcpy(malloc((len + 1)*sizeof(char)), cstr, sizeof(char)*(len + 1)); + } + if (psize) *psize = len + 1; + + Py_XDECREF(obj); + return SWIG_OK; + } else { + Py_XDECREF(obj); + } + } +#endif +#endif + + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + if (pchar_descriptor) { + void* vptr = 0; + if (SWIG_ConvertPtr(obj, &vptr, pchar_descriptor, 0) == SWIG_OK) { + if (cptr) *cptr = (char *) vptr; + if (psize) *psize = vptr ? (strlen((char *)vptr) + 1) : 0; + if (alloc) *alloc = SWIG_OLDOBJ; + return SWIG_OK; + } + } + } + return SWIG_TypeError; +} + + + + +SWIGINTERN pm3 *new_pm3__SWIG_1(char *port){ +// printf("SWIG pm3 constructor with port, open pm3\n"); + pm3_device * p = pm3_open(port); + p->script_embedded = 0; + return p; + } +SWIGINTERN void delete_pm3(pm3 *self){ + if (self->script_embedded) { +// printf("SWIG pm3 destructor, nothing to do\n"); + } else { +// printf("SWIG pm3 destructor, close pm3\n"); + pm3_close(self); + } + } + +SWIGINTERNINLINE PyObject* + SWIG_From_int (int value) +{ + return PyInt_FromLong((long) value); +} + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtrAndSize(const char* carray, size_t size) +{ + if (carray) { + if (size > INT_MAX) { + swig_type_info* pchar_descriptor = SWIG_pchar_descriptor(); + return pchar_descriptor ? + SWIG_InternalNewPointerObj((char *)(carray), pchar_descriptor, 0) : SWIG_Py_Void(); + } else { +#if PY_VERSION_HEX >= 0x03000000 +#if defined(SWIG_PYTHON_STRICT_BYTE_CHAR) + return PyBytes_FromStringAndSize(carray, (Py_ssize_t)(size)); +#else + return PyUnicode_DecodeUTF8(carray, (Py_ssize_t)(size), "surrogateescape"); +#endif +#else + return PyString_FromStringAndSize(carray, (Py_ssize_t)(size)); +#endif + } + } else { + return SWIG_Py_Void(); + } +} + + +SWIGINTERNINLINE PyObject * +SWIG_FromCharPtr(const char *cptr) +{ + return SWIG_FromCharPtrAndSize(cptr, (cptr ? strlen(cptr) : 0)); +} + +#ifdef __cplusplus +extern "C" { +#endif +SWIGINTERN PyObject *_wrap_new_pm3__SWIG_0(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **SWIGUNUSEDPARM(swig_obj)) { + PyObject *resultobj = 0; + pm3 *result = 0 ; + + if ((nobjs < 0) || (nobjs > 0)) SWIG_fail; + result = (pm3 *)new_pm3__SWIG_0(); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_pm3, SWIG_POINTER_NEW | 0 ); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_new_pm3__SWIG_1(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) { + PyObject *resultobj = 0; + char *arg1 = (char *) 0 ; + int res1 ; + char *buf1 = 0 ; + int alloc1 = 0 ; + pm3 *result = 0 ; + + if ((nobjs < 1) || (nobjs > 1)) SWIG_fail; + res1 = SWIG_AsCharPtrAndSize(swig_obj[0], &buf1, NULL, &alloc1); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_pm3" "', argument " "1"" of type '" "char *""'"); + } + arg1 = (char *)(buf1); + result = (pm3 *)new_pm3__SWIG_1(arg1); + resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_pm3, SWIG_POINTER_NEW | 0 ); + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return resultobj; +fail: + if (alloc1 == SWIG_NEWOBJ) free((char*)buf1); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_new_pm3(PyObject *self, PyObject *args) { + Py_ssize_t argc; + PyObject *argv[2] = { + 0 + }; + + if (!(argc = SWIG_Python_UnpackTuple(args, "new_pm3", 0, 1, argv))) SWIG_fail; + --argc; + if (argc == 0) { + return _wrap_new_pm3__SWIG_0(self, argc, argv); + } + if (argc == 1) { + int _v; + int res = SWIG_AsCharPtrAndSize(argv[0], 0, NULL, 0); + _v = SWIG_CheckState(res); + if (_v) { + return _wrap_new_pm3__SWIG_1(self, argc, argv); + } + } + +fail: + SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_pm3'.\n" + " Possible C/C++ prototypes are:\n" + " pm3::pm3()\n" + " pm3::pm3(char *)\n"); + return 0; +} + + +SWIGINTERN PyObject *_wrap_delete_pm3(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + pm3 *arg1 = (pm3 *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_pm3, SWIG_POINTER_DISOWN | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "delete_pm3" "', argument " "1"" of type '" "pm3 *""'"); + } + arg1 = (pm3 *)(argp1); + delete_pm3(arg1); + resultobj = SWIG_Py_Void(); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *_wrap_pm3_console(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + pm3 *arg1 = (pm3 *) 0 ; + char *arg2 = (char *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + int res2 ; + char *buf2 = 0 ; + int alloc2 = 0 ; + PyObject *swig_obj[2] ; + int result; + + if (!SWIG_Python_UnpackTuple(args, "pm3_console", 2, 2, swig_obj)) SWIG_fail; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_pm3, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "pm3_console" "', argument " "1"" of type '" "pm3 *""'"); + } + arg1 = (pm3 *)(argp1); + res2 = SWIG_AsCharPtrAndSize(swig_obj[1], &buf2, NULL, &alloc2); + if (!SWIG_IsOK(res2)) { + SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "pm3_console" "', argument " "2"" of type '" "char *""'"); + } + arg2 = (char *)(buf2); + result = (int)pm3_console(arg1,arg2); + resultobj = SWIG_From_int((int)(result)); + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return resultobj; +fail: + if (alloc2 == SWIG_NEWOBJ) free((char*)buf2); + return NULL; +} + + +SWIGINTERN PyObject *_wrap_pm3_name_get(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *resultobj = 0; + pm3 *arg1 = (pm3 *) 0 ; + void *argp1 = 0 ; + int res1 = 0 ; + PyObject *swig_obj[1] ; + char *result = 0 ; + + if (!args) SWIG_fail; + swig_obj[0] = args; + res1 = SWIG_ConvertPtr(swig_obj[0], &argp1,SWIGTYPE_p_pm3, 0 | 0 ); + if (!SWIG_IsOK(res1)) { + SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "pm3_name_get" "', argument " "1"" of type '" "pm3 *""'"); + } + arg1 = (pm3 *)(argp1); + result = (char *)pm3_name_get(arg1); + resultobj = SWIG_FromCharPtr((const char *)result); + return resultobj; +fail: + return NULL; +} + + +SWIGINTERN PyObject *pm3_swigregister(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + PyObject *obj; + if (!SWIG_Python_UnpackTuple(args, "swigregister", 1, 1, &obj)) return NULL; + SWIG_TypeNewClientData(SWIGTYPE_p_pm3, SWIG_NewClientData(obj)); + return SWIG_Py_Void(); +} + +SWIGINTERN PyObject *pm3_swiginit(PyObject *SWIGUNUSEDPARM(self), PyObject *args) { + return SWIG_Python_InitShadowInstance(args); +} + +static PyMethodDef SwigMethods[] = { + { "SWIG_PyInstanceMethod_New", SWIG_PyInstanceMethod_New, METH_O, NULL}, + { "new_pm3", _wrap_new_pm3, METH_VARARGS, NULL}, + { "delete_pm3", _wrap_delete_pm3, METH_O, NULL}, + { "pm3_console", _wrap_pm3_console, METH_VARARGS, NULL}, + { "pm3_name_get", _wrap_pm3_name_get, METH_O, NULL}, + { "pm3_swigregister", pm3_swigregister, METH_O, NULL}, + { "pm3_swiginit", pm3_swiginit, METH_VARARGS, NULL}, + { NULL, NULL, 0, NULL } +}; + +static PyMethodDef SwigMethods_proxydocs[] = { + { NULL, NULL, 0, NULL } +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (BEGIN) -------- */ + +static swig_type_info _swigt__p_char = {"_p_char", "char *", 0, 0, (void*)0, 0}; +static swig_type_info _swigt__p_pm3 = {"_p_pm3", "pm3 *", 0, 0, (void*)0, 0}; + +static swig_type_info *swig_type_initial[] = { + &_swigt__p_char, + &_swigt__p_pm3, +}; + +static swig_cast_info _swigc__p_char[] = { {&_swigt__p_char, 0, 0, 0},{0, 0, 0, 0}}; +static swig_cast_info _swigc__p_pm3[] = { {&_swigt__p_pm3, 0, 0, 0},{0, 0, 0, 0}}; + +static swig_cast_info *swig_cast_initial[] = { + _swigc__p_char, + _swigc__p_pm3, +}; + + +/* -------- TYPE CONVERSION AND EQUIVALENCE RULES (END) -------- */ + +static swig_const_info swig_const_table[] = { +{0, 0, 0, 0.0, 0, 0}}; + +#ifdef __cplusplus +} +#endif +/* ----------------------------------------------------------------------------- + * Type initialization: + * This problem is tough by the requirement that no dynamic + * memory is used. Also, since swig_type_info structures store pointers to + * swig_cast_info structures and swig_cast_info structures store pointers back + * to swig_type_info structures, we need some lookup code at initialization. + * The idea is that swig generates all the structures that are needed. + * The runtime then collects these partially filled structures. + * The SWIG_InitializeModule function takes these initial arrays out of + * swig_module, and does all the lookup, filling in the swig_module.types + * array with the correct data and linking the correct swig_cast_info + * structures together. + * + * The generated swig_type_info structures are assigned statically to an initial + * array. We just loop through that array, and handle each type individually. + * First we lookup if this type has been already loaded, and if so, use the + * loaded structure instead of the generated one. Then we have to fill in the + * cast linked list. The cast data is initially stored in something like a + * two-dimensional array. Each row corresponds to a type (there are the same + * number of rows as there are in the swig_type_initial array). Each entry in + * a column is one of the swig_cast_info structures for that type. + * The cast_initial array is actually an array of arrays, because each row has + * a variable number of columns. So to actually build the cast linked list, + * we find the array of casts associated with the type, and loop through it + * adding the casts to the list. The one last trick we need to do is making + * sure the type pointer in the swig_cast_info struct is correct. + * + * First off, we lookup the cast->type name to see if it is already loaded. + * There are three cases to handle: + * 1) If the cast->type has already been loaded AND the type we are adding + * casting info to has not been loaded (it is in this module), THEN we + * replace the cast->type pointer with the type pointer that has already + * been loaded. + * 2) If BOTH types (the one we are adding casting info to, and the + * cast->type) are loaded, THEN the cast info has already been loaded by + * the previous module so we just ignore it. + * 3) Finally, if cast->type has not already been loaded, then we add that + * swig_cast_info to the linked list (because the cast->type) pointer will + * be correct. + * ----------------------------------------------------------------------------- */ + +#ifdef __cplusplus +extern "C" { +#if 0 +} /* c-mode */ +#endif +#endif + +#if 0 +#define SWIGRUNTIME_DEBUG +#endif + + +SWIGRUNTIME void +SWIG_InitializeModule(void *clientdata) { + size_t i; + swig_module_info *module_head, *iter; + int init; + + /* check to see if the circular list has been setup, if not, set it up */ + if (swig_module.next==0) { + /* Initialize the swig_module */ + swig_module.type_initial = swig_type_initial; + swig_module.cast_initial = swig_cast_initial; + swig_module.next = &swig_module; + init = 1; + } else { + init = 0; + } + + /* Try and load any already created modules */ + module_head = SWIG_GetModule(clientdata); + if (!module_head) { + /* This is the first module loaded for this interpreter */ + /* so set the swig module into the interpreter */ + SWIG_SetModule(clientdata, &swig_module); + } else { + /* the interpreter has loaded a SWIG module, but has it loaded this one? */ + iter=module_head; + do { + if (iter==&swig_module) { + /* Our module is already in the list, so there's nothing more to do. */ + return; + } + iter=iter->next; + } while (iter!= module_head); + + /* otherwise we must add our module into the list */ + swig_module.next = module_head->next; + module_head->next = &swig_module; + } + + /* When multiple interpreters are used, a module could have already been initialized in + a different interpreter, but not yet have a pointer in this interpreter. + In this case, we do not want to continue adding types... everything should be + set up already */ + if (init == 0) return; + + /* Now work on filling in swig_module.types */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: size %lu\n", (unsigned long)swig_module.size); +#endif + for (i = 0; i < swig_module.size; ++i) { + swig_type_info *type = 0; + swig_type_info *ret; + swig_cast_info *cast; + +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); +#endif + + /* if there is another module already loaded */ + if (swig_module.next != &swig_module) { + type = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, swig_module.type_initial[i]->name); + } + if (type) { + /* Overwrite clientdata field */ +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found type %s\n", type->name); +#endif + if (swig_module.type_initial[i]->clientdata) { + type->clientdata = swig_module.type_initial[i]->clientdata; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: found and overwrite type %s \n", type->name); +#endif + } + } else { + type = swig_module.type_initial[i]; + } + + /* Insert casting types */ + cast = swig_module.cast_initial[i]; + while (cast->type) { + /* Don't need to add information already in the list */ + ret = 0; +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: look cast %s\n", cast->type->name); +#endif + if (swig_module.next != &swig_module) { + ret = SWIG_MangledTypeQueryModule(swig_module.next, &swig_module, cast->type->name); +#ifdef SWIGRUNTIME_DEBUG + if (ret) printf("SWIG_InitializeModule: found cast %s\n", ret->name); +#endif + } + if (ret) { + if (type == swig_module.type_initial[i]) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: skip old type %s\n", ret->name); +#endif + cast->type = ret; + ret = 0; + } else { + /* Check for casting already in the list */ + swig_cast_info *ocast = SWIG_TypeCheck(ret->name, type); +#ifdef SWIGRUNTIME_DEBUG + if (ocast) printf("SWIG_InitializeModule: skip old cast %s\n", ret->name); +#endif + if (!ocast) ret = 0; + } + } + + if (!ret) { +#ifdef SWIGRUNTIME_DEBUG + printf("SWIG_InitializeModule: adding cast %s\n", cast->type->name); +#endif + if (type->cast) { + type->cast->prev = cast; + cast->next = type->cast; + } + type->cast = cast; + } + cast++; + } + /* Set entry in modules->types array equal to the type */ + swig_module.types[i] = type; + } + swig_module.types[i] = 0; + +#ifdef SWIGRUNTIME_DEBUG + printf("**** SWIG_InitializeModule: Cast List ******\n"); + for (i = 0; i < swig_module.size; ++i) { + int j = 0; + swig_cast_info *cast = swig_module.cast_initial[i]; + printf("SWIG_InitializeModule: type %lu %s\n", (unsigned long)i, swig_module.type_initial[i]->name); + while (cast->type) { + printf("SWIG_InitializeModule: cast type %s\n", cast->type->name); + cast++; + ++j; + } + printf("---- Total casts: %d\n",j); + } + printf("**** SWIG_InitializeModule: Cast List ******\n"); +#endif +} + +/* This function will propagate the clientdata field of type to +* any new swig_type_info structures that have been added into the list +* of equivalent types. It is like calling +* SWIG_TypeClientData(type, clientdata) a second time. +*/ +SWIGRUNTIME void +SWIG_PropagateClientData(void) { + size_t i; + swig_cast_info *equiv; + static int init_run = 0; + + if (init_run) return; + init_run = 1; + + for (i = 0; i < swig_module.size; i++) { + if (swig_module.types[i]->clientdata) { + equiv = swig_module.types[i]->cast; + while (equiv) { + if (!equiv->converter) { + if (equiv->type && !equiv->type->clientdata) + SWIG_TypeClientData(equiv->type, swig_module.types[i]->clientdata); + } + equiv = equiv->next; + } + } + } +} + +#ifdef __cplusplus +#if 0 +{ + /* c-mode */ +#endif +} +#endif + + + +#ifdef __cplusplus +extern "C" { +#endif + + /* Python-specific SWIG API */ +#define SWIG_newvarlink() SWIG_Python_newvarlink() +#define SWIG_addvarlink(p, name, get_attr, set_attr) SWIG_Python_addvarlink(p, name, get_attr, set_attr) +#define SWIG_InstallConstants(d, constants) SWIG_Python_InstallConstants(d, constants) + + /* ----------------------------------------------------------------------------- + * global variable support code. + * ----------------------------------------------------------------------------- */ + + typedef struct swig_globalvar { + char *name; /* Name of global variable */ + PyObject *(*get_attr)(void); /* Return the current value */ + int (*set_attr)(PyObject *); /* Set the value */ + struct swig_globalvar *next; + } swig_globalvar; + + typedef struct swig_varlinkobject { + PyObject_HEAD + swig_globalvar *vars; + } swig_varlinkobject; + + SWIGINTERN PyObject * + swig_varlink_repr(swig_varlinkobject *SWIGUNUSEDPARM(v)) { +#if PY_VERSION_HEX >= 0x03000000 + return PyUnicode_InternFromString(""); +#else + return PyString_FromString(""); +#endif + } + + SWIGINTERN PyObject * + swig_varlink_str(swig_varlinkobject *v) { +#if PY_VERSION_HEX >= 0x03000000 + PyObject *str = PyUnicode_InternFromString("("); + PyObject *tail; + PyObject *joined; + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + tail = PyUnicode_FromString(var->name); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + if (var->next) { + tail = PyUnicode_InternFromString(", "); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; + } + } + tail = PyUnicode_InternFromString(")"); + joined = PyUnicode_Concat(str, tail); + Py_DecRef(str); + Py_DecRef(tail); + str = joined; +#else + PyObject *str = PyString_FromString("("); + swig_globalvar *var; + for (var = v->vars; var; var=var->next) { + PyString_ConcatAndDel(&str,PyString_FromString(var->name)); + if (var->next) PyString_ConcatAndDel(&str,PyString_FromString(", ")); + } + PyString_ConcatAndDel(&str,PyString_FromString(")")); +#endif + return str; + } + + SWIGINTERN void + swig_varlink_dealloc(swig_varlinkobject *v) { + swig_globalvar *var = v->vars; + while (var) { + swig_globalvar *n = var->next; + free(var->name); + free(var); + var = n; + } + } + + SWIGINTERN PyObject * + swig_varlink_getattr(swig_varlinkobject *v, char *n) { + PyObject *res = NULL; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->get_attr)(); + break; + } + var = var->next; + } + if (res == NULL && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; + } + + SWIGINTERN int + swig_varlink_setattr(swig_varlinkobject *v, char *n, PyObject *p) { + int res = 1; + swig_globalvar *var = v->vars; + while (var) { + if (strcmp(var->name,n) == 0) { + res = (*var->set_attr)(p); + break; + } + var = var->next; + } + if (res == 1 && !PyErr_Occurred()) { + PyErr_Format(PyExc_AttributeError, "Unknown C global variable '%s'", n); + } + return res; + } + + SWIGINTERN PyTypeObject* + swig_varlink_type(void) { + static char varlink__doc__[] = "Swig var link object"; + static PyTypeObject varlink_type; + static int type_init = 0; + if (!type_init) { + const PyTypeObject tmp = { +#if PY_VERSION_HEX >= 0x03000000 + PyVarObject_HEAD_INIT(NULL, 0) +#else + PyObject_HEAD_INIT(NULL) + 0, /* ob_size */ +#endif + "swigvarlink", /* tp_name */ + sizeof(swig_varlinkobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor) swig_varlink_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + (getattrfunc) swig_varlink_getattr, /* tp_getattr */ + (setattrfunc) swig_varlink_setattr, /* tp_setattr */ + 0, /* tp_compare */ + (reprfunc) swig_varlink_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + (reprfunc) swig_varlink_str, /* tp_str */ + 0, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + varlink__doc__, /* tp_doc */ + 0, /* tp_traverse */ + 0, /* tp_clear */ + 0, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, /* tp_iter -> tp_weaklist */ + 0, /* tp_del */ + 0, /* tp_version_tag */ +#if PY_VERSION_HEX >= 0x03040000 + 0, /* tp_finalize */ +#endif +#ifdef COUNT_ALLOCS + 0, /* tp_allocs */ + 0, /* tp_frees */ + 0, /* tp_maxalloc */ + 0, /* tp_prev */ + 0 /* tp_next */ +#endif + }; + varlink_type = tmp; + type_init = 1; + if (PyType_Ready(&varlink_type) < 0) + return NULL; + } + return &varlink_type; + } + + /* Create a variable linking object for use later */ + SWIGINTERN PyObject * + SWIG_Python_newvarlink(void) { + swig_varlinkobject *result = PyObject_NEW(swig_varlinkobject, swig_varlink_type()); + if (result) { + result->vars = 0; + } + return ((PyObject*) result); + } + + SWIGINTERN void + SWIG_Python_addvarlink(PyObject *p, const char *name, PyObject *(*get_attr)(void), int (*set_attr)(PyObject *p)) { + swig_varlinkobject *v = (swig_varlinkobject *) p; + swig_globalvar *gv = (swig_globalvar *) malloc(sizeof(swig_globalvar)); + if (gv) { + size_t size = strlen(name)+1; + gv->name = (char *)malloc(size); + if (gv->name) { + memcpy(gv->name, name, size); + gv->get_attr = get_attr; + gv->set_attr = set_attr; + gv->next = v->vars; + } + } + v->vars = gv; + } + + SWIGINTERN PyObject * + SWIG_globals(void) { + static PyObject *globals = 0; + if (!globals) { + globals = SWIG_newvarlink(); + } + return globals; + } + + /* ----------------------------------------------------------------------------- + * constants/methods manipulation + * ----------------------------------------------------------------------------- */ + + /* Install Constants */ + SWIGINTERN void + SWIG_Python_InstallConstants(PyObject *d, swig_const_info constants[]) { + PyObject *obj = 0; + size_t i; + for (i = 0; constants[i].type; ++i) { + switch(constants[i].type) { + case SWIG_PY_POINTER: + obj = SWIG_InternalNewPointerObj(constants[i].pvalue, *(constants[i]).ptype,0); + break; + case SWIG_PY_BINARY: + obj = SWIG_NewPackedObj(constants[i].pvalue, constants[i].lvalue, *(constants[i].ptype)); + break; + default: + obj = 0; + break; + } + if (obj) { + PyDict_SetItemString(d, constants[i].name, obj); + Py_DECREF(obj); + } + } + } + + /* -----------------------------------------------------------------------------*/ + /* Fix SwigMethods to carry the callback ptrs when needed */ + /* -----------------------------------------------------------------------------*/ + + SWIGINTERN void + SWIG_Python_FixMethods(PyMethodDef *methods, + swig_const_info *const_table, + swig_type_info **types, + swig_type_info **types_initial) { + size_t i; + for (i = 0; methods[i].ml_name; ++i) { + const char *c = methods[i].ml_doc; + if (!c) continue; + c = strstr(c, "swig_ptr: "); + if (c) { + int j; + swig_const_info *ci = 0; + const char *name = c + 10; + for (j = 0; const_table[j].type; ++j) { + if (strncmp(const_table[j].name, name, + strlen(const_table[j].name)) == 0) { + ci = &(const_table[j]); + break; + } + } + if (ci) { + void *ptr = (ci->type == SWIG_PY_POINTER) ? ci->pvalue : 0; + if (ptr) { + size_t shift = (ci->ptype) - types; + swig_type_info *ty = types_initial[shift]; + size_t ldoc = (c - methods[i].ml_doc); + size_t lptr = strlen(ty->name)+2*sizeof(void*)+2; + char *ndoc = (char*)malloc(ldoc + lptr + 10); + if (ndoc) { + char *buff = ndoc; + memcpy(buff, methods[i].ml_doc, ldoc); + buff += ldoc; + memcpy(buff, "swig_ptr: ", 10); + buff += 10; + SWIG_PackVoidPtr(buff, ptr, ty->name, lptr); + methods[i].ml_doc = ndoc; + } + } + } + } + } + } + + /* ----------------------------------------------------------------------------- + * Method creation and docstring support functions + * ----------------------------------------------------------------------------- */ + + /* ----------------------------------------------------------------------------- + * Function to find the method definition with the correct docstring for the + * proxy module as opposed to the low-level API + * ----------------------------------------------------------------------------- */ + + SWIGINTERN PyMethodDef *SWIG_PythonGetProxyDoc(const char *name) { + /* Find the function in the modified method table */ + size_t offset = 0; + int found = 0; + while (SwigMethods_proxydocs[offset].ml_meth != NULL) { + if (strcmp(SwigMethods_proxydocs[offset].ml_name, name) == 0) { + found = 1; + break; + } + offset++; + } + /* Use the copy with the modified docstring if available */ + return found ? &SwigMethods_proxydocs[offset] : NULL; + } + + /* ----------------------------------------------------------------------------- + * Wrapper of PyInstanceMethod_New() used in Python 3 + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ + + SWIGINTERN PyObject *SWIG_PyInstanceMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) { + if (PyCFunction_Check(func)) { + PyCFunctionObject *funcobj = (PyCFunctionObject *)func; + PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name); + if (ml) + func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module); + } +#if PY_VERSION_HEX >= 0x03000000 + return PyInstanceMethod_New(func); +#else + return PyMethod_New(func, NULL, NULL); +#endif + } + + /* ----------------------------------------------------------------------------- + * Wrapper of PyStaticMethod_New() + * It is exported to the generated module, used for -fastproxy + * ----------------------------------------------------------------------------- */ + + SWIGINTERN PyObject *SWIG_PyStaticMethod_New(PyObject *SWIGUNUSEDPARM(self), PyObject *func) { + if (PyCFunction_Check(func)) { + PyCFunctionObject *funcobj = (PyCFunctionObject *)func; + PyMethodDef *ml = SWIG_PythonGetProxyDoc(funcobj->m_ml->ml_name); + if (ml) + func = PyCFunction_NewEx(ml, funcobj->m_self, funcobj->m_module); + } + return PyStaticMethod_New(func); + } + +#ifdef __cplusplus +} +#endif + +/* -----------------------------------------------------------------------------* + * Partial Init method + * -----------------------------------------------------------------------------*/ + +#ifdef __cplusplus +extern "C" +#endif + +SWIGEXPORT +#if PY_VERSION_HEX >= 0x03000000 +PyObject* +#else +void +#endif +SWIG_init(void) { + PyObject *m, *d, *md, *globals; + +#if PY_VERSION_HEX >= 0x03000000 + static struct PyModuleDef SWIG_module = { + PyModuleDef_HEAD_INIT, + SWIG_name, + NULL, + -1, + SwigMethods, + NULL, + NULL, + NULL, + NULL + }; +#endif + +#if defined(SWIGPYTHON_BUILTIN) + static SwigPyClientData SwigPyObject_clientdata = { + 0, 0, 0, 0, 0, 0, 0 + }; + static PyGetSetDef this_getset_def = { + (char *)"this", &SwigPyBuiltin_ThisClosure, NULL, NULL, NULL + }; + static SwigPyGetSet thisown_getset_closure = { + SwigPyObject_own, + SwigPyObject_own + }; + static PyGetSetDef thisown_getset_def = { + (char *)"thisown", SwigPyBuiltin_GetterClosure, SwigPyBuiltin_SetterClosure, NULL, &thisown_getset_closure + }; + PyTypeObject *builtin_pytype; + int builtin_base_count; + swig_type_info *builtin_basetype; + PyObject *tuple; + PyGetSetDescrObject *static_getset; + PyTypeObject *metatype; + PyTypeObject *swigpyobject; + SwigPyClientData *cd; + PyObject *public_interface, *public_symbol; + PyObject *this_descr; + PyObject *thisown_descr; + PyObject *self = 0; + int i; + + (void)builtin_pytype; + (void)builtin_base_count; + (void)builtin_basetype; + (void)tuple; + (void)static_getset; + (void)self; + + /* Metaclass is used to implement static member variables */ + metatype = SwigPyObjectType(); + assert(metatype); +#endif + + (void)globals; + + /* Create singletons now to avoid potential deadlocks with multi-threaded usage after module initialization */ + SWIG_This(); + SWIG_Python_TypeCache(); + SwigPyPacked_type(); +#ifndef SWIGPYTHON_BUILTIN + SwigPyObject_type(); +#endif + + /* Fix SwigMethods to carry the callback ptrs when needed */ + SWIG_Python_FixMethods(SwigMethods, swig_const_table, swig_types, swig_type_initial); + +#if PY_VERSION_HEX >= 0x03000000 + m = PyModule_Create(&SWIG_module); +#else + m = Py_InitModule(SWIG_name, SwigMethods); +#endif + + md = d = PyModule_GetDict(m); + (void)md; + + SWIG_InitializeModule(0); + +#ifdef SWIGPYTHON_BUILTIN + swigpyobject = SwigPyObject_TypeOnce(); + + SwigPyObject_stype = SWIG_MangledTypeQuery("_p_SwigPyObject"); + assert(SwigPyObject_stype); + cd = (SwigPyClientData*) SwigPyObject_stype->clientdata; + if (!cd) { + SwigPyObject_stype->clientdata = &SwigPyObject_clientdata; + SwigPyObject_clientdata.pytype = swigpyobject; + } else if (swigpyobject->tp_basicsize != cd->pytype->tp_basicsize) { + PyErr_SetString(PyExc_RuntimeError, "Import error: attempted to load two incompatible swig-generated modules."); +# if PY_VERSION_HEX >= 0x03000000 + return NULL; +# else + return; +# endif + } + + /* All objects have a 'this' attribute */ + this_descr = PyDescr_NewGetSet(SwigPyObject_type(), &this_getset_def); + (void)this_descr; + + /* All objects have a 'thisown' attribute */ + thisown_descr = PyDescr_NewGetSet(SwigPyObject_type(), &thisown_getset_def); + (void)thisown_descr; + + public_interface = PyList_New(0); + public_symbol = 0; + (void)public_symbol; + + PyDict_SetItemString(md, "__all__", public_interface); + Py_DECREF(public_interface); + for (i = 0; SwigMethods[i].ml_name != NULL; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, SwigMethods[i].ml_name); + for (i = 0; swig_const_table[i].name != 0; ++i) + SwigPyBuiltin_AddPublicSymbol(public_interface, swig_const_table[i].name); +#endif + + SWIG_InstallConstants(d,swig_const_table); + +#if PY_VERSION_HEX >= 0x03000000 + return m; +#else + return; +#endif +} + diff --git a/client/src/proxmark3.c b/client/src/proxmark3.c index 7554e41ca..539b7a20b 100644 --- a/client/src/proxmark3.c +++ b/client/src/proxmark3.c @@ -34,6 +34,7 @@ #include "flash.h" #include "preferences.h" +#ifndef LIBPM3 #define BANNERMSG1 " Iceman :coffee:" #define BANNERMSG2 " :snowflake: bleeding edge" #define BANNERMSG3 " https://github.com/rfidresearchgroup/proxmark3/" @@ -113,6 +114,7 @@ static void showBanner(void) { fflush(stdout); g_printAndLog = PRINTANDLOG_PRINT | PRINTANDLOG_LOG; } +#endif //LIBPM3 static const char *prompt_dev = ""; static const char *prompt_ctx = ""; @@ -134,7 +136,7 @@ static int check_comm(void) { rl_set_prompt(prompt_filtered); rl_forced_update_display(); #endif - CloseProxmark(); + CloseProxmark(session.current_device); } msleep(10); return 0; @@ -452,6 +454,7 @@ check_script: } } +#ifndef LIBPM3 static void dumpAllHelp(int markdown) { session.help_dump_mode = true; PrintAndLogEx(NORMAL, "\n%sProxmark3 command dump%s\n\n", markdown ? "# " : "", markdown ? "" : "\n======================"); @@ -462,6 +465,7 @@ static void dumpAllHelp(int markdown) { dumpCommandsRecursive(cmds, markdown); session.help_dump_mode = false; } +#endif //LIBPM3 static char *my_executable_path = NULL; static char *my_executable_directory = NULL; @@ -546,6 +550,7 @@ static void set_my_user_directory(void) { } } +#ifndef LIBPM3 static void show_help(bool showFullHelp, char *exec_name) { PrintAndLogEx(NORMAL, "\nsyntax: %s [-h|-t|-m]", exec_name); @@ -631,7 +636,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ PrintAndLogEx(SUCCESS, " "_YELLOW_("%s"), filepaths[i]); } - if (OpenProxmark(serial_port_name, true, 60, true, FLASHMODE_SPEED)) { + if (OpenProxmark(&session.current_device, serial_port_name, true, 60, true, FLASHMODE_SPEED)) { PrintAndLogEx(NORMAL, _GREEN_(" found")); } else { PrintAndLogEx(ERR, "Could not find Proxmark3 on " _RED_("%s") ".\n", serial_port_name); @@ -669,7 +674,7 @@ static int flash_pm3(char *serial_port_name, uint8_t num_files, char *filenames[ finish: ret = flash_stop_flashing(); - CloseProxmark(); + CloseProxmark(session.current_device); finish2: for (int i = 0 ; i < num_files; ++i) { if (filepaths[i] != NULL) @@ -682,6 +687,7 @@ finish2: PrintAndLogEx(NORMAL, "\nHave a nice day!"); return ret; } +#endif //LIBPM3 #if defined(_WIN32) static bool DetectWindowsAnsiSupport(void) { @@ -696,14 +702,28 @@ static bool DetectWindowsAnsiSupport(void) { return SetConsoleMode(hOut, dwMode) ? true : false; } -#endif +#endif //_WIN32 -int main(int argc, char *argv[]) { +void pm3_init(void) { srand(time(0)); session.pm3_present = false; session.help_dump_mode = false; session.incognito = false; + session.supports_colors = false; + session.emoji_mode = ALTTEXT; + session.stdinOnTTY = false; + session.stdoutOnTTY = false; + + // set global variables soon enough to get the log path + set_my_executable_path(); + set_my_user_directory(); + +} + +#ifndef LIBPM3 +int main(int argc, char *argv[]) { + pm3_init(); bool waitCOMPort = false; bool addLuaExec = false; bool stayInCommandLoop = false; @@ -737,10 +757,6 @@ int main(int argc, char *argv[]) { int flash_num_files = 0; char *flash_filenames[FLASH_MAX_FILES]; - // set global variables soon enough to get the log path - set_my_executable_path(); - set_my_user_directory(); - // color management: // 1. default = no color // 2. enable colors if OS seems to support colors and if stdin/stdout aren't redirected @@ -882,7 +898,7 @@ int main(int argc, char *argv[]) { // execute pm3 command file if (strcmp(argv[i], "-s") == 0 || strcmp(argv[i], "--script-file") == 0) { - if (i + 1 == argc) { + if (i + 1 == argc || strlen(argv[i + 1]) == 0) { PrintAndLogEx(ERR, _RED_("ERROR:") " missing script file specification after -s\n"); show_help(false, exec_name); return 1; @@ -894,7 +910,7 @@ int main(int argc, char *argv[]) { // execute lua script if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "--lua") == 0) { addLuaExec = true; - if (i + 1 == argc) { + if (i + 1 == argc || strlen(argv[i + 1]) == 0) { PrintAndLogEx(ERR, _RED_("ERROR:") " missing lua script specification after -l\n"); show_help(false, exec_name); return 1; @@ -999,12 +1015,12 @@ int main(int argc, char *argv[]) { // try to open USB connection to Proxmark if (port != NULL) { - OpenProxmark(port, waitCOMPort, 20, false, speed); + OpenProxmark(&session.current_device, port, waitCOMPort, 20, false, speed); } - if (session.pm3_present && (TestProxmark() != PM3_SUCCESS)) { + if (session.pm3_present && (TestProxmark(session.current_device) != PM3_SUCCESS)) { PrintAndLogEx(ERR, _RED_("ERROR:") " cannot communicate with the Proxmark\n"); - CloseProxmark(); + CloseProxmark(session.current_device); } if ((port != NULL) && (!session.pm3_present)) @@ -1060,10 +1076,11 @@ int main(int argc, char *argv[]) { // Clean up the port if (session.pm3_present) { - CloseProxmark(); + CloseProxmark(session.current_device); } if (session.window_changed) // Plot/Overlay moved or resized preferences_save(); exit(EXIT_SUCCESS); } +#endif //LIBPM3 diff --git a/client/src/proxmark3.h b/client/src/proxmark3.h index 6d7e9dfb4..dc5bab2b9 100644 --- a/client/src/proxmark3.h +++ b/client/src/proxmark3.h @@ -49,6 +49,7 @@ int push_cmdscriptfile(char *path, bool stayafter); const char *get_my_executable_path(void); const char *get_my_executable_directory(void); const char *get_my_user_directory(void); +void pm3_init(void); void main_loop(char *script_cmds_file, char *script_cmd, bool stayInCommandLoop); #ifdef __cplusplus diff --git a/client/src/ui.h b/client/src/ui.h index b30f6c868..1a8a14028 100644 --- a/client/src/ui.h +++ b/client/src/ui.h @@ -13,6 +13,7 @@ #include #include "common.h" +#include "comms.h" #include "ansi.h" #ifdef __cplusplus @@ -46,6 +47,7 @@ typedef struct { clientdebugLevel_t client_debug_level; // uint8_t device_debug_level; char *history_path; + pm3_device *current_device; } session_arg_t; extern session_arg_t session; diff --git a/client/src/util.c b/client/src/util.c index 6a49a27dd..76a2d7885 100644 --- a/client/src/util.c +++ b/client/src/util.c @@ -200,6 +200,52 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { PrintAndLogEx(NORMAL, ""); } +void print_buffer(const uint8_t *data, const size_t len, int level) { + + if (len < 1) + return; + + char buf[UTIL_BUFFER_SIZE_SPRINT + 3]; + int i; + for (i = 0; i < len; i += 16) { + + // (16 * 3) + (16) + + 1 + memset(buf, 0, sizeof(buf)); + sprintf(buf, "%*s%02x: ", (level * 4), " ", i); + + hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, 16, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, 16)); + PrintAndLogEx(INFO, "%s", buf); + } + + // the last odd bytes + uint8_t mod = len % 16; + + if (mod) { + memset(buf, 0, sizeof(buf)); + sprintf(buf, "%*s%02x: ", (level * 4), " ", i); + hex_to_buffer((uint8_t *)(buf + strlen(buf)), data + i, mod, (sizeof(buf) - strlen(buf) - 1), 0, 1, true); + + // add the spaces... + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "%*s", ((16 - mod) * 3), " "); + + snprintf(buf + strlen(buf), sizeof(buf) - strlen(buf), "| %s", sprint_ascii(data + i, mod)); + PrintAndLogEx(INFO, "%s", buf); + } +} + +void print_blocks(uint32_t *data, size_t len) { + PrintAndLogEx(SUCCESS, "Blk | Data "); + PrintAndLogEx(SUCCESS, "----+------------"); + + if (!data) { + PrintAndLogEx(ERR, "..empty data"); + } else { + for (uint8_t i = 0; i < len; i++) + PrintAndLogEx(SUCCESS, " %02d | %08X", i, data[i]); + } +} + char *sprint_hex(const uint8_t *data, const size_t len) { static char buf[UTIL_BUFFER_SIZE_SPRINT - 3] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, true); @@ -344,18 +390,6 @@ char *sprint_ascii(const uint8_t *data, const size_t len) { return sprint_ascii_ex(data, len, 0); } -void print_blocks(uint32_t *data, size_t len) { - PrintAndLogEx(SUCCESS, "Blk | Data "); - PrintAndLogEx(SUCCESS, "----+------------"); - - if (!data) { - PrintAndLogEx(ERR, "..empty data"); - } else { - for (uint8_t i = 0; i < len; i++) - PrintAndLogEx(SUCCESS, " %02d | %08X", i, data[i]); - } -} - int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen) { char buf[4] = {0}; int indx = 0; diff --git a/client/src/util.h b/client/src/util.h index f65c94622..51100731e 100644 --- a/client/src/util.h +++ b/client/src/util.h @@ -50,6 +50,7 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len); char *sprint_ascii(const uint8_t *data, const size_t len); char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_str_len); +void print_buffer(const uint8_t *data, const size_t len, int level); void print_blocks(uint32_t *data, size_t len); int hex_to_bytes(const char *hexValue, uint8_t *bytesValue, size_t maxBytesValueLen); diff --git a/common/lz4/lz4.c b/common/lz4/lz4.c index da5bbf1e2..0b7df1fb0 100644 --- a/common/lz4/lz4.c +++ b/common/lz4/lz4.c @@ -1586,7 +1586,7 @@ int LZ4_compress_fast_continue(LZ4_stream_t *LZ4_stream, * cost to copy the dictionary's tables into the active context, * so that the compression loop is only looking into one table. */ - LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(LZ4_stream_t)); + LZ4_memcpy(streamPtr, streamPtr->dictCtx, sizeof(*streamPtr)); result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingExtDict, noDictIssue, acceleration); } else { result = LZ4_compress_generic(streamPtr, source, dest, inputSize, NULL, maxOutputSize, limitedOutput, tableType, usingDictCtx, noDictIssue, acceleration); diff --git a/doc/cheatsheet.md b/doc/cheatsheet.md index a3ea9c579..9699fabf0 100644 --- a/doc/cheatsheet.md +++ b/doc/cheatsheet.md @@ -111,22 +111,24 @@ Encrypt iCLASS Block ``` Options --- -d : 16 bytes hex -k : 16 bytes hex +-d, --data data to encrypt +-k, --key 3DES transport key +-v, --verbose verbose output -pm3 --> hf iclass encrypt d 0000000f2aa3dba8 +pm3 --> hf iclass encrypt -d 0000000f2aa3dba8 ``` Decrypt iCLASS Block / file ``` Options --- -d : 16 bytes hex -f : filename of dump -k : 16 bytes hex +-f, --file filename of dumpfile +-d, --data 3DES encrypted data +-k, --key 3DES transport key +-v, --verbose verbose output -pm3 --> hf iclass decrypt d 2AD4C8211F996871 -pm3 --> hf iclass decrypt f hf-iclass-db883702f8ff12e0.bin +pm3 --> hf iclass decrypt -d 2AD4C8211F996871 +pm3 --> hf iclass decrypt -f hf-iclass-db883702f8ff12e0.bin ``` Load iCLASS dump into memory for simulation diff --git a/pm3 b/pm3 index 4349ed643..27e992b11 100755 --- a/pm3 +++ b/pm3 @@ -11,22 +11,36 @@ FINDBTRFCOMM=true FINDBTDIRECT=true PM3PATH=$(dirname "$0") +EVALENV="" FULLIMAGE="fullimage.elf" BOOTIMAGE="bootrom.elf" # try pm3 dirs in current repo workdir if [ -d "$PM3PATH/client/" ]; then - CLIENT="$PM3PATH/client/proxmark3" + if [ -x "$PM3PATH/client/proxmark3" ]; then + CLIENT="$PM3PATH/client/proxmark3" + elif [ -x "$PM3PATH/client/build/proxmark3" ]; then + CLIENT="$PM3PATH/client/build/proxmark3" + else + echo >&2 "[!!] In devel workdir but no executable found, did you compile it?" + exit 1 + fi + # Devel mode: point to workdir pm3.py module + EVALENV+=" PYTHONPATH=$PM3PATH/client/src" # try install dir elif [ -x "$PM3PATH/proxmark3" ]; then CLIENT="$PM3PATH/proxmark3" + EVALENV+=" PYTHONPATH=$PM3PATH/../share/proxmark3/pyscripts/" + # or /usr/[local/]lib/python3/dist-packages/pm3.py ? else -# hope it's installed somehow, still not sure where fw images are... +# hope it's installed somehow, still not sure where fw images and pm3.py are... CLIENT="proxmark3" fi -EVALENV="" # LeakSanitizer suppressions if [ -e .lsan_suppressions ]; then - EVALENV="export LSAN_OPTIONS=suppressions=.lsan_suppressions" + EVALENV+=" LSAN_OPTIONS=suppressions=.lsan_suppressions" +fi +if [ "$EVALENV" != "" ]; then + EVALENV="export $EVALENV" fi PM3LIST=() SHOWLIST=false diff --git a/recovery/Makefile b/recovery/Makefile index 1ef142eda..e6e3f7041 100644 --- a/recovery/Makefile +++ b/recovery/Makefile @@ -11,7 +11,7 @@ FWMAXSIZE = $(shell echo $$(($(PLATFORM_SIZE)*1024))) BINS = bootrom.bin fullimage.bin $(INSTALLFW) all: $(BINS) - @FWSIZE=$$(stat -c "%s" $(INSTALLFW));\ + @FWSIZE=$$(wc -c < $(INSTALLFW));\ if [ $$FWSIZE -gt $(FWMAXSIZE) ]; then \ echo "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!"; \ echo "ERROR: Firmware image too large for your platform! $$FWSIZE > $(FWMAXSIZE)"; \