5 Commits

Author SHA1 Message Date
Romuald Conty
e076683dea minor fixes/enhancements and version bumping 2011-04-04 12:28:11 +00:00
Romuald Conty
4d1ce73772 hide authentication errors 2011-04-04 10:38:30 +00:00
Romuald Conty
dafa6e42db sync nfc-utils.h/c and mifare.c/h with libnfc's ones. 2011-04-04 10:01:33 +00:00
Romain Tartiere
c973c3cd81 mfox: Unbreak autotools on FreeBSD. 2011-02-21 16:26:48 +00:00
Romuald Conty
6a3977545e use strtoll() function in order to retrieve 64bits wide value. (Fixes Issue 55) 2011-02-02 10:46:16 +00:00
7 changed files with 185 additions and 81 deletions

View File

@@ -1,4 +1,4 @@
AC_INIT([mfoc], [0.10], [mifare@nethemba.com])
AC_INIT([mfoc], [0.10.1], [mifare@nethemba.com])
AC_CONFIG_MACRO_DIR([m4])
@@ -13,7 +13,7 @@ AM_INIT_AUTOMAKE
m4_ifdef([AM_SILENT_RULES],[AM_SILENT_RULES([yes])])
# Checks for pkg-config modules.
LIBNFC_REQUIRED_VERSION=1.4.0
LIBNFC_REQUIRED_VERSION=1.4.2
PKG_CHECK_MODULES([LIBNFC], [libnfc >= $LIBNFC_REQUIRED_VERSION], [], [AC_MSG_ERROR([libnfc >= $LIBNFC_REQUIRED_VERSION is mandatory.])])
PKG_CONFIG_REQUIRES="libnfc"

View File

@@ -1,7 +1,9 @@
AM_CFLAGS = @LIBNFC_CFLAGS@
AM_LDFLAGS = @LIBNFC_LIBS@
bin_PROGRAMS = mfoc
noinst_HEADERS = crapto1.h mfoc.h mifare.h nfc-utils.h
mfoc_SOURCES = crapto1.c crypto1.c mfoc.c mifare.c nfc-utils.c
mfoc_LDADD = @LIBNFC_LIBS@
# dist_man_MANS = mfoc.1

View File

@@ -1,6 +1,6 @@
/*
Mifare Classic Offline Cracker version 0.08
Mifare Classic Offline Cracker
Requirements: crapto1 library http://code.google.com/p/crapto1
libnfc http://www.libnfc.org
@@ -22,6 +22,7 @@
Porting to libnfc 1.3.3: Michal Boska <boska.michal@gmail.com>
Porting to libnfc 1.3.9: Romuald Conty <romuald@libnfc.org>
Porting to libnfc 1.4.x: Romuald Conty <romuald@libnfc.org>
URL http://eprint.iacr.org/2009/137.pdf
URL http://www.sos.cs.ru.nl/applications/rfid/2008-esorics.pdf
@@ -106,27 +107,27 @@ int main(int argc, char * const argv[]) {
case 'P':
// Number of probes
if (!(probes = atoi(optarg)) || probes < 1) {
fprintf(stderr, "The number of probes must be a positive number\n");
exit(1);
ERR ("The number of probes must be a positive number");
exit (EXIT_FAILURE);
}
// fprintf(stdout, "Number of probes: %d\n", probes);
break;
case 'T':
// Nonce tolerance range
if (!(d.tolerance = atoi(optarg)) || d.tolerance < 0) {
fprintf(stderr, "The nonce distances range must be a zero or a positive number\n");
exit(1);
ERR ("The nonce distances range must be a zero or a positive number");
exit (EXIT_FAILURE);
}
// fprintf(stdout, "Tolerance number: %d\n", probes);
break;
case 'k':
// Add this key to the default keys list
if ((defKey = calloc(6, sizeof(byte_t))) == NULL) {
fprintf(stderr, "Cannot allocate memory for defKey\n");
exit(1);
ERR ("Cannot allocate memory for defKey");
exit (EXIT_FAILURE);
} else {
bzero(defKey, 6);
num_to_bytes(strtol(optarg, NULL, 16), 6, defKey);
num_to_bytes(strtoll(optarg, NULL, 16), 6, defKey);
memcpy(defaultKeys[0], defKey, 6);
}
fprintf(stdout, "The custom key 0x%012llx has been added to the default keys\n", bytes_to_num(defKey, 6));
@@ -136,7 +137,7 @@ int main(int argc, char * const argv[]) {
// File output
if (!(pfDump = fopen(optarg, "wb"))) {
fprintf(stderr, "Cannot open: %s, exiting\n", optarg);
exit(1);
exit (EXIT_FAILURE);
}
// fprintf(stdout, "Output file: %s\n", optarg);
break;
@@ -150,8 +151,8 @@ int main(int argc, char * const argv[]) {
}
if (!pfDump) {
fprintf(stderr, "Error, parameter -O is mandatory\n");
exit(1);
ERR ("parameter -O is mandatory");
exit (EXIT_FAILURE);
}
// Initialize reader/tag structures
@@ -169,16 +170,16 @@ int main(int argc, char * const argv[]) {
t.sectors = (void *) calloc(t.num_sectors, sizeof(sector));
if (t.sectors == NULL) {
fprintf(stderr, "Cannot allocate memory for t.sectors\n");
exit(1);
ERR ("Cannot allocate memory for t.sectors");
exit (EXIT_FAILURE);
}
if ((pk = (void *) malloc(sizeof(pKeys))) == NULL) {
fprintf(stderr, "Cannot allocate memory for pk\n");
exit(1);
ERR ("Cannot allocate memory for pk");
exit (EXIT_FAILURE);
}
if ((bk = (void *) malloc(sizeof(bKeys))) == NULL) {
fprintf(stderr, "Cannot allocate memory for bk\n");
exit(1);
ERR ("Cannot allocate memory for bk");
exit (EXIT_FAILURE);
} else {
bk->brokenKeys = NULL;
bk->size = 0;
@@ -186,15 +187,15 @@ int main(int argc, char * const argv[]) {
d.distances = (void *) calloc(d.num_distances, sizeof(u_int32_t));
if (d.distances == NULL) {
fprintf(stderr, "Cannot allocate memory for t.distances\n");
exit(1);
ERR ("Cannot allocate memory for t.distances");
exit (EXIT_FAILURE);
}
// Test if a compatible MIFARE tag is used
if ((t.nt.nti.nai.btSak & 0x08) == 0) {
printf("Error: inserted tag is not a MIFARE Classic card\n");
ERR ("inserted tag is not a MIFARE Classic");
nfc_disconnect(r.pdi);
exit(1);
exit (EXIT_FAILURE);
}
// Initialize t.sectors, keys are not known yet
@@ -371,8 +372,8 @@ int main(int argc, char * const argv[]) {
}
// We haven't found any key, exiting
if ((dumpKeysA && !t.sectors[j].foundKeyA) || (!dumpKeysA && !t.sectors[j].foundKeyB)) {
fprintf(stderr, "No success, maybe you should increase the probes\n");
exit(1);
ERR ("No success, maybe you should increase the probes");
exit (EXIT_FAILURE);
}
}
}
@@ -399,7 +400,7 @@ int main(int argc, char * const argv[]) {
// Try A key, auth() + read()
memcpy(mp.mpa.abtKey, t.sectors[i].KeyA, sizeof(t.sectors[i].KeyA));
if (!nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_A, block, &mp)) {
// fprintf(stderr, "Error: Auth A\n");
// ERR ("Error: Auth A");
mf_configure(r.pdi);
mf_anticollision(t, r);
} else { // and Read
@@ -411,12 +412,12 @@ int main(int argc, char * const argv[]) {
failure = false;
} else {
// Error, now try read() with B key
// fprintf(stderr, "Error: Read A\n");
// ERR ("Error: Read A");
mf_configure(r.pdi);
mf_anticollision(t, r);
memcpy(mp.mpa.abtKey, t.sectors[i].KeyB, sizeof(t.sectors[i].KeyB));
if (!nfc_initiator_mifare_cmd(r.pdi, MC_AUTH_B, block, &mp)) {
// fprintf(stderr, "Error: Auth B\n");
// ERR ("Error: Auth B");
mf_configure(r.pdi);
mf_anticollision(t, r);
} else { // and Read
@@ -429,7 +430,7 @@ int main(int argc, char * const argv[]) {
} else {
mf_configure(r.pdi);
mf_anticollision(t, r);
// fprintf(stderr, "Error: Read B\n");
// ERR ("Error: Read B");
}
}
}
@@ -447,7 +448,7 @@ int main(int argc, char * const argv[]) {
if (fwrite(&mtDump, 1, sizeof(mtDump), pfDump) != sizeof(mtDump)) {
fprintf(stdout, "Error, cannot write dump\n");
fclose(pfDump);
exit(1);
exit (EXIT_FAILURE);
}
fclose(pfDump);
}
@@ -488,8 +489,8 @@ void mf_init(mftag *t, mfreader *r) {
// Connect to the first NFC device
r->pdi = nfc_connect(NULL);
if (!r->pdi) {
fprintf(stderr, "!Error connecting to the NFC reader\n");
exit(1);
ERR ("Unable to connect to NFC device\n");
exit (EXIT_FAILURE);
}
}
@@ -513,9 +514,9 @@ void mf_select_tag(nfc_device_t* pdi, nfc_target_t* pnt) {
.nbr = NBR_106,
};
if (!nfc_initiator_select_passive_target(pdi, nm, NULL, 0, pnt)) {
fprintf(stderr, "!Error connecting to the MIFARE Classic tag\n");
ERR ("Unable to connect to the MIFARE Classic tag");
nfc_disconnect(pdi);
exit(1);
exit (EXIT_FAILURE);
}
}
@@ -546,8 +547,8 @@ int find_exploit_sector(mftag t) {
return i;
}
}
fprintf(stderr, "\n\nNo sector encrypted with the default key has been found, exiting..\n");
exit(1);
ERR ("\n\nNo sector encrypted with the default key has been found, exiting..");
exit (EXIT_FAILURE);
}
void mf_anticollision(mftag t, mfreader r) {
@@ -556,8 +557,8 @@ void mf_anticollision(mftag t, mfreader r) {
.nbr = NBR_106,
};
if (!nfc_initiator_select_passive_target(r.pdi, nm, NULL, 0, &t.nt)) {
fprintf(stderr, "\n\n!Error: tag has been removed\n");
exit(1);
ERR ("\n\n!Error: tag has been removed");
exit (EXIT_FAILURE);
}
}
@@ -654,8 +655,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// fprintf(stdout, "\t{Ar}:\t");
// print_hex_par(ArEnc, 64, ArEncPar);
if ((!nfc_initiator_transceive_bits(r.pdi, ArEnc, 64, ArEncPar, Rx, &RxLen, RxPar)) || (RxLen != 32)) {
fprintf(stderr, "Reader-answer transfer error, exiting..\n");
exit(1);
ERR ("Reader-answer transfer error, exiting..");
exit (EXIT_FAILURE);
}
// Now print the answer from the tag
@@ -665,8 +666,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// Decrypt the tag answer and verify that suc3(Nt) is At
Nt = prng_successor(Nt, 32);
if (!((crypto1_word(pcs, 0x00, 0) ^ bytes_to_num(Rx, 4)) == (Nt&0xFFFFFFFF))) {
fprintf(stderr, "[At] is not Suc3(Nt), something is wrong, exiting..\n");
exit(1);
ERR ("[At] is not Suc3(Nt), something is wrong, exiting..");
exit (EXIT_FAILURE);
}
// fprintf(stdout, "Authentication completed.\n\n");
@@ -684,7 +685,7 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// Sending the encrypted Auth command
if (!nfc_initiator_transceive_bits(r.pdi, AuthEnc, 32, AuthEncPar,Rx, &RxLen, RxPar)) {
fprintf(stdout, "Error requesting encrypted tag-nonce\n");
exit(1);
exit (EXIT_FAILURE);
}
// Decrypt the encrypted auth
@@ -712,13 +713,13 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
}
nfc_configure(r.pdi,NDO_HANDLE_PARITY,false);
if ((!nfc_initiator_transceive_bits(r.pdi, ArEnc, 64, ArEncPar, Rx, &RxLen, RxPar)) || (RxLen != 32)) {
fprintf(stderr, "Reader-answer transfer error, exiting..\n");
exit(1);
ERR ("Reader-answer transfer error, exiting..");
exit (EXIT_FAILURE);
}
Nt = prng_successor(Nt, 32);
if (!((crypto1_word(pcs, 0x00, 0) ^ bytes_to_num(Rx, 4)) == (Nt&0xFFFFFFFF))) {
fprintf(stderr, "[At] is not Suc3(Nt), something is wrong, exiting..\n");
exit(1);
ERR ("[At] is not Suc3(Nt), something is wrong, exiting..");
exit (EXIT_FAILURE);
}
} // Next auth probe
@@ -741,8 +742,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
AuthEncPar[i] = filter(pcs->odd) ^ oddparity(Auth[i]);
}
if (!nfc_initiator_transceive_bits(r.pdi, AuthEnc, 32, AuthEncPar,Rx, &RxLen, RxPar)) {
fprintf(stdout, "Error requesting encrypted tag-nonce\n");
exit(1);
ERR ("while requesting encrypted tag-nonce");
exit (EXIT_FAILURE);
}
// Save the encrypted nonce
@@ -778,8 +779,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
// fprintf(stdout, "New chunk by %d, sizeof %lu\n", kcount, pk->size * sizeof(uint64_t));
pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t));
if (pk->possibleKeys == NULL) {
fprintf(stderr, "Memory allocation error for pk->possibleKeys\n");
exit(1);
ERR ("Memory allocation error for pk->possibleKeys");
exit (EXIT_FAILURE);
}
}
pk->possibleKeys[kcount] = lfsr;
@@ -794,8 +795,8 @@ int mf_enhanced_auth(int e_sector, int a_sector, mftag t, mfreader r, denonce *d
if (kcount != 0) {
pk->size = --kcount;
if ((pk->possibleKeys = (uint64_t *) realloc((void *)pk->possibleKeys, pk->size * sizeof(uint64_t))) == NULL) {
fprintf(stderr, "Memory allocation error for pk->possibleKeys\n");
exit(1);
ERR ("Memory allocation error for pk->possibleKeys");
exit (EXIT_FAILURE);
}
}
}
@@ -835,8 +836,8 @@ countKeys * uniqsort(uint64_t * possibleKeys, uint32_t size) {
our_counts = calloc(size, sizeof(countKeys));
if (our_counts == NULL) {
fprintf(stderr, "Memory allocation error for our_counts\n");
exit(1);
ERR ("Memory allocation error for our_counts");
exit (EXIT_FAILURE);
}
for (i = 0; i < size; i++) {

View File

@@ -1,3 +1,33 @@
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
#include "mifare.h"
#include <string.h>
@@ -21,13 +51,10 @@ bool
nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t ui8Block, mifare_param * pmp)
{
byte_t abtRx[265];
size_t szRxLen;
size_t szRx = sizeof(abtRx);
size_t szParamLen;
byte_t abtCmd[265];
// Make sure we are dealing with a active device
if (!pnd->bActive)
return false;
bool bEasyFraming;
abtCmd[0] = mc; // The MIFARE Classic command
abtCmd[1] = ui8Block; // The block address (1K=0x00..0x39, 4K=0x00..0xff)
@@ -67,15 +94,34 @@ nfc_initiator_mifare_cmd (nfc_device_t * pnd, const mifare_cmd mc, const uint8_t
if (szParamLen)
memcpy (abtCmd + 2, (byte_t *) pmp, szParamLen);
// Fire the mifare command
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRxLen)) {
if (pnd->iLastError != 0x14)
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
bEasyFraming = pnd->bEasyFraming;
if (!nfc_configure (pnd, NDO_EASY_FRAMING, true)) {
nfc_perror (pnd, "nfc_configure");
return false;
}
// Fire the mifare command
if (!nfc_initiator_transceive_bytes (pnd, abtCmd, 2 + szParamLen, abtRx, &szRx)) {
if (pnd->iLastError == EINVRXFRAM) {
// "Invalid received frame" AKA EINVRXFRAM, usual means we are
// authenticated on a sector but the requested MIFARE cmd (read, write)
// is not permitted by current acces bytes;
// So there is nothing to do here.
} else if (pnd->iLastError == EMFAUTH) {
// In MFOC, we have to hide authentication errors :)
} else {
nfc_perror (pnd, "nfc_initiator_transceive_bytes");
}
nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming);
return false;
}
if (!nfc_configure (pnd, NDO_EASY_FRAMING, bEasyFraming)) {
nfc_perror (pnd, "nfc_configure");
return false;
}
// When we have executed a read command, copy the received bytes into the param
if (mc == MC_READ) {
if (szRxLen == 16) {
if (szRx == 16) {
memcpy (pmp->mpd.abtData, abtRx, 16);
} else {
return false;

View File

@@ -1,22 +1,34 @@
/**
* Public platform independent Near Field Communication (NFC) library
/*-
* Public platform independent Near Field Communication (NFC) library examples
*
* Copyright (C) 2009, Roel Verdult, 2010, Romuald Conty
* Copyright (C) 2009, Roel Verdult
* Copyright (C) 2010, Romuald Conty, Romain Tartière
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by the
* Free Software Foundation, either version 3 of the License, or (at your
* option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1) Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2 )Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* Note that this license only applies on the examples, NFC library itself is under LGPL
*
*/
/**
* @file mifaretag.h
* @brief provide samples structs and functions to manipulate MIFARE Classic and Ultralight tags using libnfc
*/

View File

@@ -532,6 +532,7 @@ print_nfc_iso14443a_info (const nfc_iso14443a_info_t nai, bool verbose)
void
print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
{
(void) verbose;
printf (" ID (NFCID2): ");
print_hex (nfi.abtId, 8);
printf (" Parameter (PAD): ");
@@ -541,6 +542,7 @@ print_nfc_felica_info (const nfc_felica_info_t nfi, bool verbose)
void
print_nfc_jewel_info (const nfc_jewel_info_t nji, bool verbose)
{
(void) verbose;
printf (" ATQA (SENS_RES): ");
print_hex (nji.btSensRes, 2);
printf (" 4-LSB JEWELID: ");
@@ -608,6 +610,7 @@ print_nfc_iso14443b_info (const nfc_iso14443b_info_t nbi, bool verbose)
void
print_nfc_dep_info (const nfc_dep_info_t ndi, bool verbose)
{
(void) verbose;
printf (" NFCID3: ");
print_hex (ndi.abtNFCID3, 10);
printf (" BS: %02x\n", ndi.btBS);

View File

@@ -38,6 +38,46 @@
# include <stdlib.h>
# include <string.h>
# include <err.h>
/**
* @macro DBG
* @brief Print a message of standard output only in DEBUG mode
*/
#ifdef DEBUG
# define DBG(...) do { \
warnx ("DBG %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define DBG(...) {}
#endif
/**
* @macro WARN
* @brief Print a warn message
*/
#ifdef DEBUG
# define WARN(...) do { \
warnx ("WARNING %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define WARN(...) warnx ("WARNING: " __VA_ARGS__ )
#endif
/**
* @macro ERR
* @brief Print a error message
*/
#ifdef DEBUG
# define ERR(...) do { \
warnx ("ERROR %s:%d", __FILE__, __LINE__); \
warnx (" " __VA_ARGS__ ); \
} while (0)
#else
# define ERR(...) warnx ("ERROR: " __VA_ARGS__ )
#endif
byte_t oddparity (const byte_t bt);
void oddparity_byte_ts (const byte_t * pbtData, const size_t szLen, byte_t * pbtPar);