From aacd31e32689c4dc1bf7b4cdc5e98d074c47619c Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sat, 14 Aug 2010 16:22:56 +0800 Subject: add functions to alter easycard log records and mifare value blocks --- easytool/Makefile | 2 +- easytool/easycard.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++ easytool/easycard.h | 33 ++++++++++++++++++++ easytool/easytool.c | 56 ---------------------------------- easytool/mifare_classic.c | 16 ++++++++++ easytool/mifare_classic.h | 8 +++++ 6 files changed, 135 insertions(+), 57 deletions(-) create mode 100644 easytool/easycard.c diff --git a/easytool/Makefile b/easytool/Makefile index 81b3ae2..f4f8262 100644 --- a/easytool/Makefile +++ b/easytool/Makefile @@ -6,7 +6,7 @@ all: easytool clean: @rm -f *.o easytool -easytool: easytool.o data.o utils.o mifare_classic.o +easytool: easytool.o easycard.o data.o utils.o mifare_classic.o $(CC) $(LDFLAGS) -o $@ $^ %.o: %.c diff --git a/easytool/easycard.c b/easytool/easycard.c new file mode 100644 index 0000000..32c71f3 --- /dev/null +++ b/easytool/easycard.c @@ -0,0 +1,77 @@ +/* A reverse-engineered implementation of the EasyCard data format */ + +/* (C) 2010 by Harald Welte + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +/* System includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* libnfc includes */ +#include +#include + +#include "mifare_classic.h" + +/* Easycard specific includes */ +#include "easycard.h" + +time_t easy_timestamp2time(const uint8_t *easy_ts) +{ + return (easy_ts[2] << 16 | easy_ts[1] << 8 | easy_ts[0]) << 8; +} + +/* apply a telta (positive or negative) to a EasyCard log record */ +int easy_update_log_rec(struct easy_log_rec *elr, int16_t delta) +{ + int32_t sum = elr->amount + delta; + int32_t remaining = elr->remaining = delta; + + if ((sum < 0 || sum > 0xffff) || + (remaining < 0 || remaining > 0xffff)) + return -ERANGE; + + elr->amount = sum; + elr->remaining = remaining; + + return 0; +} + +static char tsbuf[64]; +char *easy_asc_timestamp(const uint8_t *timestamp) +{ + time_t t_time = easy_timestamp2time(timestamp); + struct tm *t_tm = gmtime(&t_time); + memset(tsbuf, 0, sizeof(tsbuf)); + snprintf(tsbuf, sizeof(tsbuf), "%4u-%02u-%02u %02u:%02u", + t_tm->tm_year+1900, t_tm->tm_mon+1, t_tm->tm_mday, + t_tm->tm_hour, t_tm->tm_min); + return tsbuf; +} + diff --git a/easytool/easycard.h b/easytool/easycard.h index 9d547f8..7da1015 100644 --- a/easytool/easycard.h +++ b/easytool/easycard.h @@ -11,4 +11,37 @@ extern const struct value_string easy_tt_names[]; extern const struct value_string taipei_mrt_stn_id[]; +/* Sector 0 of Block 2 seems to contain manufacturing timestamp */ +struct easy_block2sec0 { + uint8_t unknown[6]; + uint8_t timestamp[3]; + uint8_t unknown2[7]; +} __attribute__ ((packed)); + +/* Sector 2 of Block 15 */ +struct easy_block15sec2 { + uint8_t unknown[11]; + uint8_t day_of_month; + uint8_t unknown2; /* always 0x3d? */ + uint16_t sum_of_day; /* sum of all shop purchases on a day */ + uint8_t unknown3; +} __attribute__ ((packed)); + + +/* storage of a transaction log record on the transponder itself */ +struct easy_log_rec { + uint8_t trans_id; + uint8_t unknown; + uint8_t timestamp[3]; /* seconds since January 1st 1970 / 256 */ + uint8_t trans_type; + uint16_t amount; /* transaction amount / value */ + uint16_t remaining; /* remaining value on card _after_ trans */ + uint8_t unknown2; + uint8_t station_code; /* MRT station code */ + uint16_t reader_code; /* unique code of RFID reader */ + uint8_t unknown3[2]; +} __attribute__ ((packed)); + +time_t easy_timestamp2time(const uint8_t *easy_ts); + #endif /* EASYCARD_H */ diff --git a/easytool/easytool.c b/easytool/easytool.c index 65de185..fa15c6b 100644 --- a/easytool/easytool.c +++ b/easytool/easytool.c @@ -54,62 +54,6 @@ struct { mifare_tag *mft; } global; -/* Sector 0 of Block 2 seems to contain manufacturing timestamp */ -struct easy_block2sec0 { - uint8_t unknown[6]; - uint8_t timestamp[3]; - uint8_t unknown2[7]; -} __attribute__ ((packed)); - -/* Sector 2 of Block 15 */ -struct easy_block15sec2 { - uint8_t unknown[11]; - uint8_t day_of_month; - uint8_t unknown2; /* always 0x3d? */ - uint16_t sum_of_day; /* sum of all shop purchases on a day */ - uint8_t unknown3; -} __attribute__ ((packed)); - - -/* storage of a transaction log record on the transponder itself */ -struct easy_log_rec { - uint8_t trans_id; - uint8_t unknown; - uint8_t timestamp[3]; /* seconds since January 1st 1970 / 256 */ - uint8_t trans_type; - uint16_t amount; /* transaction amount / value */ - uint16_t remaining; /* remaining value on card _after_ trans */ - uint8_t unknown2; - uint8_t station_code; /* MRT station code */ - uint16_t reader_code; /* unique code of RFID reader */ - uint8_t unknown3[2]; -} __attribute__ ((packed)); - -/* Mifare classic VALUE BLOCK */ -struct mfcl_value_block { - uint32_t value; /* value in NTD */ - uint32_t value_inv; /* bit-inverted copy of value in NTD */ - uint32_t value_backup; /* backup copy of value in NTD */ - uint8_t addr[4]; -} __attribute__ ((packed)); - -static time_t easy_timestamp2time(const uint8_t *easy_ts) -{ - return (easy_ts[2] << 16 | easy_ts[1] << 8 | easy_ts[0]) << 8; -} - -static char tsbuf[64]; -char *easy_asc_timestamp(const uint8_t *timestamp) -{ - time_t t_time = easy_timestamp2time(timestamp); - struct tm *t_tm = gmtime(&t_time); - memset(tsbuf, 0, sizeof(tsbuf)); - snprintf(tsbuf, sizeof(tsbuf), "%4u-%02u-%02u %02u:%02u", - t_tm->tm_year+1900, t_tm->tm_mon+1, t_tm->tm_mday, - t_tm->tm_hour, t_tm->tm_min); - return tsbuf; -} - static void dump_easy_log(const struct easy_log_rec *elr) { printf("%s | %02x | %10s | Paid %4u NTD | %4u NTD remaining\n", diff --git a/easytool/mifare_classic.c b/easytool/mifare_classic.c index e516631..5f21fd5 100644 --- a/easytool/mifare_classic.c +++ b/easytool/mifare_classic.c @@ -1,6 +1,7 @@ #include #include #include +#include #include "mifare_classic.h" @@ -27,3 +28,18 @@ void mfcl_parse_acc_bits(struct acc_bits_parsed *abp, uint8_t *acc_bits) abp->block[block] |= ABP_C3; } } + +/* apply a delta (positive or negative) to a Mifare Classic VALUE block */ +int mfcl_update_value_block(struct mfcl_value_block *mvb, int32_t delta) +{ + int64_t sum = mvb->value + delta; + + if (sum > 0xffffffff || sum < 0) + return -ERANGE; + + mvb->value = sum; + mvb->value_backup = mvb->value; + mvb->value_inv = ~sum; + + return 0; +} diff --git a/easytool/mifare_classic.h b/easytool/mifare_classic.h index c6ba524..f04f32f 100644 --- a/easytool/mifare_classic.h +++ b/easytool/mifare_classic.h @@ -13,4 +13,12 @@ struct acc_bits_parsed { void mfcl_parse_acc_bits(struct acc_bits_parsed *abp, uint8_t *acc_bits); +/* Mifare classic VALUE BLOCK */ +struct mfcl_value_block { + uint32_t value; /* value in NTD */ + uint32_t value_inv; /* bit-inverted copy of value in NTD */ + uint32_t value_backup; /* backup copy of value in NTD */ + uint8_t addr[4]; +} __attribute__ ((packed)); + #endif -- cgit v1.2.3